Merge branch 'code-cleanup-and-unit-tests' into development

This commit is contained in:
Christian Koop 2021-10-30 14:54:25 +02:00
commit cbee2ed45e
No known key found for this signature in database
GPG Key ID: 89A8181384E010A3
379 changed files with 11568 additions and 8327 deletions

View File

@ -1,3 +1,7 @@
# This EditorConfig aims to achieve compact code while allowing a file's content to be understood easily
root = true
[*]
charset = utf-8
end_of_line = lf
@ -15,8 +19,127 @@ ij_smart_tabs = false
ij_visual_guides = none
ij_wrap_on_typing = false
##
# Common file formats
##
[*.properties]
ij_properties_align_group_field_declarations = false
ij_properties_keep_blank_lines = false
ij_properties_key_value_delimiter = equals
ij_properties_spaces_around_key_value_delimiter = false
[{*.yaml,*.yml}]
indent_size = 2
ij_yaml_align_values_properties = do_not_align
ij_yaml_autoinsert_sequence_marker = true
ij_yaml_block_mapping_on_new_line = false
ij_yaml_indent_sequence_value = true
ij_yaml_keep_indents_on_empty_lines = false
ij_yaml_keep_line_breaks = true
ij_yaml_sequence_on_new_line = false
ij_yaml_space_before_colon = false
ij_yaml_spaces_within_braces = true
ij_yaml_spaces_within_brackets = true
[{*.json,*.graphqlconfig,*.har,*.jsb2,*.jsb3,*.webmanifest,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}]
indent_size = 2
ij_json_keep_blank_lines_in_code = 0
ij_json_keep_indents_on_empty_lines = false
ij_json_keep_line_breaks = true
ij_json_space_after_colon = true
ij_json_space_after_comma = true
ij_json_space_before_colon = true
ij_json_space_before_comma = false
ij_json_spaces_within_braces = false
ij_json_spaces_within_brackets = false
ij_json_wrap_long_lines = false
[{*.xml,*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.mpd,*.pom,*.rng,*.tld,*.wsdl,*.xsd,*.xsl,*.xslt,*.xul}]
ij_xml_align_attributes = true
ij_xml_align_text = false
ij_xml_attribute_wrap = normal
ij_xml_block_comment_at_first_column = true
ij_xml_keep_blank_lines = 2
ij_xml_keep_indents_on_empty_lines = false
ij_xml_keep_line_breaks = true
ij_xml_keep_line_breaks_in_text = true
ij_xml_keep_whitespaces = false
ij_xml_keep_whitespaces_around_cdata = preserve
ij_xml_keep_whitespaces_inside_cdata = false
ij_xml_line_comment_at_first_column = true
ij_xml_space_after_tag_name = false
ij_xml_space_around_equals_in_attribute = false
ij_xml_space_inside_empty_tag = false
ij_xml_text_wrap = normal
##
# MarkDown
# TODO: Not happy with this yet
##
[{*.markdown,*.md}]
indent_size = 2
tab_width = 2
ij_continuation_indent_size = 4
##
# HTML + CSS
##
[{*.html,*.htm,*.ng,*.sht,*.shtm,*.shtml}]
indent_size = 2
tab_width = 2
ij_continuation_indent_size = 4
ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3
ij_html_align_attributes = true
ij_html_align_text = false
ij_html_attribute_wrap = normal
ij_html_block_comment_at_first_column = true
ij_html_do_not_align_children_of_min_lines = 0
ij_html_do_not_break_if_inline_tags = title, h1, h2, h3, h4, h5, h6, p, li
ij_html_do_not_indent_children_of_tags = html, body, thead, tbody, tfoot
ij_html_enforce_quotes = true
ij_html_inline_tags = a, abbr, acronym, b, basefont, bdo, big, br, cite, cite, code, dfn, em, font, i, img, input, kbd, label, q, s, samp, select, small, span, strike, strong, sub, sup, textarea, tt, u, var
ij_html_keep_blank_lines = 2
ij_html_keep_indents_on_empty_lines = false
ij_html_keep_line_breaks = true
ij_html_keep_line_breaks_in_text = true
ij_html_keep_whitespaces = false
ij_html_keep_whitespaces_inside = span, pre, textarea
ij_html_line_comment_at_first_column = true
ij_html_new_line_after_last_attribute = never
ij_html_new_line_before_first_attribute = never
ij_html_quote_style = double
ij_html_remove_new_line_before_tags = br
ij_html_space_after_tag_name = false
ij_html_space_around_equality_in_attribute = false
ij_html_space_inside_empty_tag = false
ij_html_text_wrap = normal
[*.css]
ij_css_align_closing_brace_with_properties = false
ij_css_blank_lines_around_nested_selector = 1
ij_css_blank_lines_between_blocks = 1
ij_css_brace_placement = end_of_line
ij_css_enforce_quotes_on_format = true
ij_css_hex_color_long_format = false
ij_css_hex_color_lower_case = true
ij_css_hex_color_short_format = true
ij_css_hex_color_upper_case = false
ij_css_keep_blank_lines_in_code = 2
ij_css_keep_indents_on_empty_lines = false
ij_css_keep_single_line_blocks = false
ij_css_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow
ij_css_space_after_colon = true
ij_css_space_before_opening_brace = true
ij_css_use_double_quotes = true
ij_css_value_alignment = on_value
##
# Java + Gradle
##
[*.java]
ij_smart_tabs = true
ij_java_align_consecutive_assignments = false
ij_java_align_consecutive_variable_declarations = false
ij_java_align_group_field_declarations = false
@ -71,7 +194,7 @@ ij_java_case_statement_on_separate_line = true
ij_java_catch_on_new_line = false
ij_java_class_annotation_wrap = split_into_lines
ij_java_class_brace_style = end_of_line
ij_java_class_count_to_use_import_on_demand = 15
ij_java_class_count_to_use_import_on_demand = 999
ij_java_class_names_in_javadoc = 1
ij_java_do_not_indent_top_level_class_members = false
ij_java_do_not_wrap_after_single_annotation = false
@ -79,10 +202,10 @@ ij_java_do_while_brace_force = never
ij_java_doc_add_blank_line_after_description = true
ij_java_doc_add_blank_line_after_param_comments = true
ij_java_doc_add_blank_line_after_return = true
ij_java_doc_add_p_tag_on_empty_lines = true
ij_java_doc_add_p_tag_on_empty_lines = false
ij_java_doc_align_exception_comments = true
ij_java_doc_align_param_comments = true
ij_java_doc_do_not_wrap_if_one_line = true
ij_java_doc_do_not_wrap_if_one_line = false
ij_java_doc_enable_formatting = true
ij_java_doc_enable_leading_asterisks = true
ij_java_doc_indent_on_continuation = true
@ -111,10 +234,10 @@ ij_java_imports_layout = *, |, javax.**, java.**, |, $*
ij_java_indent_case_from_switch = true
ij_java_insert_inner_class_imports = false
ij_java_insert_override_annotation = true
ij_java_keep_blank_lines_before_right_brace = 0
ij_java_keep_blank_lines_between_package_declaration_and_header = 0
ij_java_keep_blank_lines_in_code = 1
ij_java_keep_blank_lines_in_declarations = 1
ij_java_keep_blank_lines_before_right_brace = 2
ij_java_keep_blank_lines_between_package_declaration_and_header = 2
ij_java_keep_blank_lines_in_code = 2
ij_java_keep_blank_lines_in_declarations = 2
ij_java_keep_builder_methods_indents = false
ij_java_keep_control_statement_in_one_line = true
ij_java_keep_first_column_comment = true
@ -122,9 +245,9 @@ ij_java_keep_indents_on_empty_lines = false
ij_java_keep_line_breaks = true
ij_java_keep_multiple_expressions_in_one_line = false
ij_java_keep_simple_blocks_in_one_line = false
ij_java_keep_simple_classes_in_one_line = true
ij_java_keep_simple_lambdas_in_one_line = true
ij_java_keep_simple_methods_in_one_line = true
ij_java_keep_simple_classes_in_one_line = false
ij_java_keep_simple_lambdas_in_one_line = false
ij_java_keep_simple_methods_in_one_line = false
ij_java_label_indent_absolute = false
ij_java_label_indent_size = 0
ij_java_lambda_brace_style = end_of_line
@ -138,9 +261,9 @@ ij_java_method_parameters_new_line_after_left_paren = false
ij_java_method_parameters_right_paren_on_new_line = false
ij_java_method_parameters_wrap = off
ij_java_modifier_list_wrap = false
ij_java_names_count_to_use_import_on_demand = 9
ij_java_names_count_to_use_import_on_demand = 999
ij_java_new_line_after_lparen_in_record_header = false
ij_java_packages_to_use_import_on_demand = _java.awt.*, _javax.swing.*
ij_java_packages_to_use_import_on_demand = java.awt.*, javax.swing.*
ij_java_parameter_annotation_wrap = off
ij_java_parentheses_expression_new_line_after_left_paren = false
ij_java_parentheses_expression_right_paren_on_new_line = false
@ -199,7 +322,7 @@ ij_java_space_before_while_keyword = true
ij_java_space_before_while_left_brace = true
ij_java_space_before_while_parentheses = true
ij_java_space_inside_one_line_enum_braces = false
ij_java_space_within_empty_array_initializer_braces = true
ij_java_space_within_empty_array_initializer_braces = false
ij_java_space_within_empty_method_call_parentheses = false
ij_java_space_within_empty_method_parentheses = false
ij_java_spaces_around_additive_operators = true
@ -217,7 +340,7 @@ ij_java_spaces_around_unary_operator = false
ij_java_spaces_within_angle_brackets = false
ij_java_spaces_within_annotation_parentheses = false
ij_java_spaces_within_array_initializer_braces = false
ij_java_spaces_within_braces = true
ij_java_spaces_within_braces = false
ij_java_spaces_within_brackets = false
ij_java_spaces_within_cast_parentheses = false
ij_java_spaces_within_catch_parentheses = false
@ -250,12 +373,539 @@ ij_java_wrap_comments = false
ij_java_wrap_first_method_in_call_chain = false
ij_java_wrap_long_lines = false
[*.properties]
ij_properties_align_group_field_declarations = false
ij_properties_keep_blank_lines = false
ij_properties_key_value_delimiter = equals
ij_properties_spaces_around_key_value_delimiter = false
[{*.gradle,*.gant,*.groovy,*.gy}]
ij_groovy_align_group_field_declarations = false
ij_groovy_align_multiline_array_initializer_expression = false
ij_groovy_align_multiline_assignment = false
ij_groovy_align_multiline_binary_operation = false
ij_groovy_align_multiline_chained_methods = false
ij_groovy_align_multiline_extends_list = false
ij_groovy_align_multiline_for = true
ij_groovy_align_multiline_list_or_map = true
ij_groovy_align_multiline_method_parentheses = false
ij_groovy_align_multiline_parameters = true
ij_groovy_align_multiline_parameters_in_calls = false
ij_groovy_align_multiline_resources = true
ij_groovy_align_multiline_ternary_operation = false
ij_groovy_align_multiline_throws_list = false
ij_groovy_align_named_args_in_map = true
ij_groovy_align_throws_keyword = false
ij_groovy_array_initializer_new_line_after_left_brace = false
ij_groovy_array_initializer_right_brace_on_new_line = false
ij_groovy_array_initializer_wrap = off
ij_groovy_assert_statement_wrap = off
ij_groovy_assignment_wrap = off
ij_groovy_binary_operation_wrap = off
ij_groovy_blank_lines_after_class_header = 0
ij_groovy_blank_lines_after_imports = 1
ij_groovy_blank_lines_after_package = 1
ij_groovy_blank_lines_around_class = 1
ij_groovy_blank_lines_around_field = 0
ij_groovy_blank_lines_around_field_in_interface = 0
ij_groovy_blank_lines_around_method = 1
ij_groovy_blank_lines_around_method_in_interface = 1
ij_groovy_blank_lines_before_imports = 1
ij_groovy_blank_lines_before_method_body = 0
ij_groovy_blank_lines_before_package = 0
ij_groovy_block_brace_style = end_of_line
ij_groovy_block_comment_at_first_column = true
ij_groovy_call_parameters_new_line_after_left_paren = false
ij_groovy_call_parameters_right_paren_on_new_line = false
ij_groovy_call_parameters_wrap = off
ij_groovy_catch_on_new_line = false
ij_groovy_class_annotation_wrap = split_into_lines
ij_groovy_class_brace_style = end_of_line
ij_groovy_class_count_to_use_import_on_demand = 5
ij_groovy_do_while_brace_force = never
ij_groovy_else_on_new_line = false
ij_groovy_enum_constants_wrap = off
ij_groovy_extends_keyword_wrap = off
ij_groovy_extends_list_wrap = off
ij_groovy_field_annotation_wrap = split_into_lines
ij_groovy_finally_on_new_line = false
ij_groovy_for_brace_force = never
ij_groovy_for_statement_new_line_after_left_paren = false
ij_groovy_for_statement_right_paren_on_new_line = false
ij_groovy_for_statement_wrap = off
ij_groovy_if_brace_force = never
ij_groovy_import_annotation_wrap = 2
ij_groovy_imports_layout = *, |, javax.**, java.**, |, $*
ij_groovy_indent_case_from_switch = true
ij_groovy_indent_label_blocks = true
ij_groovy_insert_inner_class_imports = false
ij_groovy_keep_blank_lines_before_right_brace = 2
ij_groovy_keep_blank_lines_in_code = 2
ij_groovy_keep_blank_lines_in_declarations = 2
ij_groovy_keep_control_statement_in_one_line = true
ij_groovy_keep_first_column_comment = true
ij_groovy_keep_indents_on_empty_lines = false
ij_groovy_keep_line_breaks = true
ij_groovy_keep_multiple_expressions_in_one_line = false
ij_groovy_keep_simple_blocks_in_one_line = false
ij_groovy_keep_simple_classes_in_one_line = true
ij_groovy_keep_simple_lambdas_in_one_line = true
ij_groovy_keep_simple_methods_in_one_line = true
ij_groovy_label_indent_absolute = false
ij_groovy_label_indent_size = 0
ij_groovy_lambda_brace_style = end_of_line
ij_groovy_layout_static_imports_separately = true
ij_groovy_line_comment_add_space = false
ij_groovy_line_comment_at_first_column = true
ij_groovy_method_annotation_wrap = split_into_lines
ij_groovy_method_brace_style = end_of_line
ij_groovy_method_call_chain_wrap = off
ij_groovy_method_parameters_new_line_after_left_paren = false
ij_groovy_method_parameters_right_paren_on_new_line = false
ij_groovy_method_parameters_wrap = off
ij_groovy_modifier_list_wrap = false
ij_groovy_names_count_to_use_import_on_demand = 3
ij_groovy_parameter_annotation_wrap = off
ij_groovy_parentheses_expression_new_line_after_left_paren = false
ij_groovy_parentheses_expression_right_paren_on_new_line = false
ij_groovy_prefer_parameters_wrap = false
ij_groovy_resource_list_new_line_after_left_paren = false
ij_groovy_resource_list_right_paren_on_new_line = false
ij_groovy_resource_list_wrap = off
ij_groovy_space_after_assert_separator = true
ij_groovy_space_after_colon = true
ij_groovy_space_after_comma = true
ij_groovy_space_after_comma_in_type_arguments = true
ij_groovy_space_after_for_semicolon = true
ij_groovy_space_after_quest = true
ij_groovy_space_after_type_cast = true
ij_groovy_space_before_annotation_parameter_list = false
ij_groovy_space_before_array_initializer_left_brace = false
ij_groovy_space_before_assert_separator = false
ij_groovy_space_before_catch_keyword = true
ij_groovy_space_before_catch_left_brace = true
ij_groovy_space_before_catch_parentheses = true
ij_groovy_space_before_class_left_brace = true
ij_groovy_space_before_closure_left_brace = true
ij_groovy_space_before_colon = true
ij_groovy_space_before_comma = false
ij_groovy_space_before_do_left_brace = true
ij_groovy_space_before_else_keyword = true
ij_groovy_space_before_else_left_brace = true
ij_groovy_space_before_finally_keyword = true
ij_groovy_space_before_finally_left_brace = true
ij_groovy_space_before_for_left_brace = true
ij_groovy_space_before_for_parentheses = true
ij_groovy_space_before_for_semicolon = false
ij_groovy_space_before_if_left_brace = true
ij_groovy_space_before_if_parentheses = true
ij_groovy_space_before_method_call_parentheses = false
ij_groovy_space_before_method_left_brace = true
ij_groovy_space_before_method_parentheses = false
ij_groovy_space_before_quest = true
ij_groovy_space_before_switch_left_brace = true
ij_groovy_space_before_switch_parentheses = true
ij_groovy_space_before_synchronized_left_brace = true
ij_groovy_space_before_synchronized_parentheses = true
ij_groovy_space_before_try_left_brace = true
ij_groovy_space_before_try_parentheses = true
ij_groovy_space_before_while_keyword = true
ij_groovy_space_before_while_left_brace = true
ij_groovy_space_before_while_parentheses = true
ij_groovy_space_in_named_argument = true
ij_groovy_space_in_named_argument_before_colon = false
ij_groovy_space_within_empty_array_initializer_braces = false
ij_groovy_space_within_empty_method_call_parentheses = false
ij_groovy_spaces_around_additive_operators = true
ij_groovy_spaces_around_assignment_operators = true
ij_groovy_spaces_around_bitwise_operators = true
ij_groovy_spaces_around_equality_operators = true
ij_groovy_spaces_around_lambda_arrow = true
ij_groovy_spaces_around_logical_operators = true
ij_groovy_spaces_around_multiplicative_operators = true
ij_groovy_spaces_around_regex_operators = true
ij_groovy_spaces_around_relational_operators = true
ij_groovy_spaces_around_shift_operators = true
ij_groovy_spaces_within_annotation_parentheses = false
ij_groovy_spaces_within_array_initializer_braces = false
ij_groovy_spaces_within_braces = true
ij_groovy_spaces_within_brackets = false
ij_groovy_spaces_within_cast_parentheses = false
ij_groovy_spaces_within_catch_parentheses = false
ij_groovy_spaces_within_for_parentheses = false
ij_groovy_spaces_within_gstring_injection_braces = false
ij_groovy_spaces_within_if_parentheses = false
ij_groovy_spaces_within_list_or_map = false
ij_groovy_spaces_within_method_call_parentheses = false
ij_groovy_spaces_within_method_parentheses = false
ij_groovy_spaces_within_parentheses = false
ij_groovy_spaces_within_switch_parentheses = false
ij_groovy_spaces_within_synchronized_parentheses = false
ij_groovy_spaces_within_try_parentheses = false
ij_groovy_spaces_within_tuple_expression = false
ij_groovy_spaces_within_while_parentheses = false
ij_groovy_special_else_if_treatment = true
ij_groovy_ternary_operation_wrap = off
ij_groovy_throws_keyword_wrap = off
ij_groovy_throws_list_wrap = off
ij_groovy_use_flying_geese_braces = false
ij_groovy_use_fq_class_names = false
ij_groovy_use_fq_class_names_in_javadoc = true
ij_groovy_use_relative_indents = false
ij_groovy_use_single_class_imports = true
ij_groovy_variable_annotation_wrap = off
ij_groovy_while_brace_force = never
ij_groovy_while_on_new_line = false
ij_groovy_wrap_chain_calls_after_dot = false
ij_groovy_wrap_long_lines = false
##
# TypeScript / JavaScript
##
[{*.ts,*.ats}]
indent_size = 2
tab_width = 2
ij_continuation_indent_size = 4
ij_typescript_align_imports = false
ij_typescript_align_multiline_array_initializer_expression = false
ij_typescript_align_multiline_binary_operation = false
ij_typescript_align_multiline_chained_methods = false
ij_typescript_align_multiline_extends_list = false
ij_typescript_align_multiline_for = true
ij_typescript_align_multiline_parameters = true
ij_typescript_align_multiline_parameters_in_calls = false
ij_typescript_align_multiline_ternary_operation = false
ij_typescript_align_object_properties = 0
ij_typescript_align_union_types = false
ij_typescript_align_var_statements = 0
ij_typescript_array_initializer_new_line_after_left_brace = false
ij_typescript_array_initializer_right_brace_on_new_line = false
ij_typescript_array_initializer_wrap = off
ij_typescript_assignment_wrap = off
ij_typescript_binary_operation_sign_on_next_line = false
ij_typescript_binary_operation_wrap = off
ij_typescript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/**
ij_typescript_blank_lines_after_imports = 1
ij_typescript_blank_lines_around_class = 1
ij_typescript_blank_lines_around_field = 0
ij_typescript_blank_lines_around_field_in_interface = 0
ij_typescript_blank_lines_around_function = 1
ij_typescript_blank_lines_around_method = 1
ij_typescript_blank_lines_around_method_in_interface = 1
ij_typescript_block_brace_style = end_of_line
ij_typescript_call_parameters_new_line_after_left_paren = false
ij_typescript_call_parameters_right_paren_on_new_line = false
ij_typescript_call_parameters_wrap = off
ij_typescript_catch_on_new_line = false
ij_typescript_chained_call_dot_on_new_line = true
ij_typescript_class_brace_style = end_of_line
ij_typescript_comma_on_new_line = false
ij_typescript_do_while_brace_force = never
ij_typescript_else_on_new_line = false
ij_typescript_enforce_trailing_comma = remove
ij_typescript_extends_keyword_wrap = off
ij_typescript_extends_list_wrap = off
ij_typescript_field_prefix = _
ij_typescript_file_name_style = relaxed
ij_typescript_finally_on_new_line = false
ij_typescript_for_brace_force = never
ij_typescript_for_statement_new_line_after_left_paren = false
ij_typescript_for_statement_right_paren_on_new_line = false
ij_typescript_for_statement_wrap = off
ij_typescript_force_quote_style = true
ij_typescript_force_semicolon_style = true
ij_typescript_function_expression_brace_style = end_of_line
ij_typescript_if_brace_force = never
ij_typescript_import_merge_members = global
ij_typescript_import_prefer_absolute_path = global
ij_typescript_import_sort_members = true
ij_typescript_import_sort_module_name = true
ij_typescript_import_use_node_resolution = true
ij_typescript_imports_wrap = on_every_item
ij_typescript_indent_case_from_switch = true
ij_typescript_indent_chained_calls = true
ij_typescript_indent_package_children = 0
ij_typescript_jsdoc_include_types = false
ij_typescript_jsx_attribute_value = braces
ij_typescript_keep_blank_lines_in_code = 2
ij_typescript_keep_first_column_comment = true
ij_typescript_keep_indents_on_empty_lines = false
ij_typescript_keep_line_breaks = true
ij_typescript_keep_simple_blocks_in_one_line = false
ij_typescript_keep_simple_methods_in_one_line = false
ij_typescript_line_comment_add_space = true
ij_typescript_line_comment_at_first_column = false
ij_typescript_method_brace_style = end_of_line
ij_typescript_method_call_chain_wrap = off
ij_typescript_method_parameters_new_line_after_left_paren = false
ij_typescript_method_parameters_right_paren_on_new_line = false
ij_typescript_method_parameters_wrap = off
ij_typescript_object_literal_wrap = on_every_item
ij_typescript_parentheses_expression_new_line_after_left_paren = false
ij_typescript_parentheses_expression_right_paren_on_new_line = false
ij_typescript_place_assignment_sign_on_next_line = false
ij_typescript_prefer_as_type_cast = false
ij_typescript_prefer_explicit_types_function_expression_returns = false
ij_typescript_prefer_explicit_types_function_returns = false
ij_typescript_prefer_explicit_types_vars_fields = false
ij_typescript_prefer_parameters_wrap = false
ij_typescript_reformat_c_style_comments = false
ij_typescript_space_after_colon = true
ij_typescript_space_after_comma = true
ij_typescript_space_after_dots_in_rest_parameter = false
ij_typescript_space_after_generator_mult = true
ij_typescript_space_after_property_colon = true
ij_typescript_space_after_quest = true
ij_typescript_space_after_type_colon = true
ij_typescript_space_after_unary_not = false
ij_typescript_space_before_async_arrow_lparen = true
ij_typescript_space_before_catch_keyword = true
ij_typescript_space_before_catch_left_brace = true
ij_typescript_space_before_catch_parentheses = true
ij_typescript_space_before_class_lbrace = true
ij_typescript_space_before_class_left_brace = true
ij_typescript_space_before_colon = true
ij_typescript_space_before_comma = false
ij_typescript_space_before_do_left_brace = true
ij_typescript_space_before_else_keyword = true
ij_typescript_space_before_else_left_brace = true
ij_typescript_space_before_finally_keyword = true
ij_typescript_space_before_finally_left_brace = true
ij_typescript_space_before_for_left_brace = true
ij_typescript_space_before_for_parentheses = true
ij_typescript_space_before_for_semicolon = false
ij_typescript_space_before_function_left_parenth = true
ij_typescript_space_before_generator_mult = false
ij_typescript_space_before_if_left_brace = true
ij_typescript_space_before_if_parentheses = true
ij_typescript_space_before_method_call_parentheses = false
ij_typescript_space_before_method_left_brace = true
ij_typescript_space_before_method_parentheses = false
ij_typescript_space_before_property_colon = false
ij_typescript_space_before_quest = true
ij_typescript_space_before_switch_left_brace = true
ij_typescript_space_before_switch_parentheses = true
ij_typescript_space_before_try_left_brace = true
ij_typescript_space_before_type_colon = false
ij_typescript_space_before_unary_not = false
ij_typescript_space_before_while_keyword = true
ij_typescript_space_before_while_left_brace = true
ij_typescript_space_before_while_parentheses = true
ij_typescript_spaces_around_additive_operators = true
ij_typescript_spaces_around_arrow_function_operator = true
ij_typescript_spaces_around_assignment_operators = true
ij_typescript_spaces_around_bitwise_operators = true
ij_typescript_spaces_around_equality_operators = true
ij_typescript_spaces_around_logical_operators = true
ij_typescript_spaces_around_multiplicative_operators = true
ij_typescript_spaces_around_relational_operators = true
ij_typescript_spaces_around_shift_operators = true
ij_typescript_spaces_around_unary_operator = false
ij_typescript_spaces_within_array_initializer_brackets = false
ij_typescript_spaces_within_brackets = false
ij_typescript_spaces_within_catch_parentheses = false
ij_typescript_spaces_within_for_parentheses = false
ij_typescript_spaces_within_if_parentheses = false
ij_typescript_spaces_within_imports = true
ij_typescript_spaces_within_interpolation_expressions = false
ij_typescript_spaces_within_method_call_parentheses = false
ij_typescript_spaces_within_method_parentheses = false
ij_typescript_spaces_within_object_literal_braces = false
ij_typescript_spaces_within_object_type_braces = true
ij_typescript_spaces_within_parentheses = false
ij_typescript_spaces_within_switch_parentheses = false
ij_typescript_spaces_within_type_assertion = false
ij_typescript_spaces_within_union_types = true
ij_typescript_spaces_within_while_parentheses = false
ij_typescript_special_else_if_treatment = true
ij_typescript_ternary_operation_signs_on_next_line = false
ij_typescript_ternary_operation_wrap = off
ij_typescript_union_types_wrap = on_every_item
ij_typescript_use_chained_calls_group_indents = false
ij_typescript_use_double_quotes = false
ij_typescript_use_explicit_js_extension = global
ij_typescript_use_path_mapping = always
ij_typescript_use_public_modifier = false
ij_typescript_use_semicolon_after_statement = true
ij_typescript_var_declaration_wrap = normal
ij_typescript_while_brace_force = never
ij_typescript_while_on_new_line = false
ij_typescript_wrap_comments = false
[{*.js,*.cjs}]
indent_size = 2
tab_width = 2
ij_continuation_indent_size = 4
ij_javascript_align_imports = false
ij_javascript_align_multiline_array_initializer_expression = false
ij_javascript_align_multiline_binary_operation = false
ij_javascript_align_multiline_chained_methods = false
ij_javascript_align_multiline_extends_list = false
ij_javascript_align_multiline_for = true
ij_javascript_align_multiline_parameters = true
ij_javascript_align_multiline_parameters_in_calls = false
ij_javascript_align_multiline_ternary_operation = false
ij_javascript_align_object_properties = 0
ij_javascript_align_union_types = false
ij_javascript_align_var_statements = 0
ij_javascript_array_initializer_new_line_after_left_brace = false
ij_javascript_array_initializer_right_brace_on_new_line = false
ij_javascript_array_initializer_wrap = off
ij_javascript_assignment_wrap = off
ij_javascript_binary_operation_sign_on_next_line = false
ij_javascript_binary_operation_wrap = off
ij_javascript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/**
ij_javascript_blank_lines_after_imports = 1
ij_javascript_blank_lines_around_class = 1
ij_javascript_blank_lines_around_field = 0
ij_javascript_blank_lines_around_function = 1
ij_javascript_blank_lines_around_method = 1
ij_javascript_block_brace_style = end_of_line
ij_javascript_call_parameters_new_line_after_left_paren = false
ij_javascript_call_parameters_right_paren_on_new_line = false
ij_javascript_call_parameters_wrap = off
ij_javascript_catch_on_new_line = false
ij_javascript_chained_call_dot_on_new_line = true
ij_javascript_class_brace_style = end_of_line
ij_javascript_comma_on_new_line = false
ij_javascript_do_while_brace_force = never
ij_javascript_else_on_new_line = false
ij_javascript_enforce_trailing_comma = remove
ij_javascript_extends_keyword_wrap = off
ij_javascript_extends_list_wrap = off
ij_javascript_field_prefix = _
ij_javascript_file_name_style = relaxed
ij_javascript_finally_on_new_line = false
ij_javascript_for_brace_force = never
ij_javascript_for_statement_new_line_after_left_paren = false
ij_javascript_for_statement_right_paren_on_new_line = false
ij_javascript_for_statement_wrap = off
ij_javascript_force_quote_style = true
ij_javascript_force_semicolon_style = true
ij_javascript_function_expression_brace_style = end_of_line
ij_javascript_if_brace_force = never
ij_javascript_import_merge_members = global
ij_javascript_import_prefer_absolute_path = global
ij_javascript_import_sort_members = true
ij_javascript_import_sort_module_name = false
ij_javascript_import_use_node_resolution = true
ij_javascript_imports_wrap = on_every_item
ij_javascript_indent_case_from_switch = true
ij_javascript_indent_chained_calls = true
ij_javascript_indent_package_children = 0
ij_javascript_jsx_attribute_value = braces
ij_javascript_keep_blank_lines_in_code = 2
ij_javascript_keep_first_column_comment = true
ij_javascript_keep_indents_on_empty_lines = false
ij_javascript_keep_line_breaks = true
ij_javascript_keep_simple_blocks_in_one_line = false
ij_javascript_keep_simple_methods_in_one_line = false
ij_javascript_line_comment_add_space = true
ij_javascript_line_comment_at_first_column = false
ij_javascript_method_brace_style = end_of_line
ij_javascript_method_call_chain_wrap = off
ij_javascript_method_parameters_new_line_after_left_paren = false
ij_javascript_method_parameters_right_paren_on_new_line = false
ij_javascript_method_parameters_wrap = off
ij_javascript_object_literal_wrap = on_every_item
ij_javascript_parentheses_expression_new_line_after_left_paren = false
ij_javascript_parentheses_expression_right_paren_on_new_line = false
ij_javascript_place_assignment_sign_on_next_line = false
ij_javascript_prefer_as_type_cast = false
ij_javascript_prefer_explicit_types_function_expression_returns = false
ij_javascript_prefer_explicit_types_function_returns = false
ij_javascript_prefer_explicit_types_vars_fields = false
ij_javascript_prefer_parameters_wrap = false
ij_javascript_reformat_c_style_comments = false
ij_javascript_space_after_colon = true
ij_javascript_space_after_comma = true
ij_javascript_space_after_dots_in_rest_parameter = false
ij_javascript_space_after_generator_mult = true
ij_javascript_space_after_property_colon = true
ij_javascript_space_after_quest = true
ij_javascript_space_after_type_colon = true
ij_javascript_space_after_unary_not = false
ij_javascript_space_before_async_arrow_lparen = true
ij_javascript_space_before_catch_keyword = true
ij_javascript_space_before_catch_left_brace = true
ij_javascript_space_before_catch_parentheses = true
ij_javascript_space_before_class_lbrace = true
ij_javascript_space_before_class_left_brace = true
ij_javascript_space_before_colon = true
ij_javascript_space_before_comma = false
ij_javascript_space_before_do_left_brace = true
ij_javascript_space_before_else_keyword = true
ij_javascript_space_before_else_left_brace = true
ij_javascript_space_before_finally_keyword = true
ij_javascript_space_before_finally_left_brace = true
ij_javascript_space_before_for_left_brace = true
ij_javascript_space_before_for_parentheses = true
ij_javascript_space_before_for_semicolon = false
ij_javascript_space_before_function_left_parenth = true
ij_javascript_space_before_generator_mult = false
ij_javascript_space_before_if_left_brace = true
ij_javascript_space_before_if_parentheses = true
ij_javascript_space_before_method_call_parentheses = false
ij_javascript_space_before_method_left_brace = true
ij_javascript_space_before_method_parentheses = false
ij_javascript_space_before_property_colon = false
ij_javascript_space_before_quest = true
ij_javascript_space_before_switch_left_brace = true
ij_javascript_space_before_switch_parentheses = true
ij_javascript_space_before_try_left_brace = true
ij_javascript_space_before_type_colon = false
ij_javascript_space_before_unary_not = false
ij_javascript_space_before_while_keyword = true
ij_javascript_space_before_while_left_brace = true
ij_javascript_space_before_while_parentheses = true
ij_javascript_spaces_around_additive_operators = true
ij_javascript_spaces_around_arrow_function_operator = true
ij_javascript_spaces_around_assignment_operators = true
ij_javascript_spaces_around_bitwise_operators = true
ij_javascript_spaces_around_equality_operators = true
ij_javascript_spaces_around_logical_operators = true
ij_javascript_spaces_around_multiplicative_operators = true
ij_javascript_spaces_around_relational_operators = true
ij_javascript_spaces_around_shift_operators = true
ij_javascript_spaces_around_unary_operator = false
ij_javascript_spaces_within_array_initializer_brackets = false
ij_javascript_spaces_within_brackets = false
ij_javascript_spaces_within_catch_parentheses = false
ij_javascript_spaces_within_for_parentheses = false
ij_javascript_spaces_within_if_parentheses = false
ij_javascript_spaces_within_imports = true
ij_javascript_spaces_within_interpolation_expressions = false
ij_javascript_spaces_within_method_call_parentheses = false
ij_javascript_spaces_within_method_parentheses = false
ij_javascript_spaces_within_object_literal_braces = false
ij_javascript_spaces_within_object_type_braces = true
ij_javascript_spaces_within_parentheses = false
ij_javascript_spaces_within_switch_parentheses = false
ij_javascript_spaces_within_type_assertion = false
ij_javascript_spaces_within_union_types = true
ij_javascript_spaces_within_while_parentheses = false
ij_javascript_special_else_if_treatment = true
ij_javascript_ternary_operation_signs_on_next_line = false
ij_javascript_ternary_operation_wrap = off
ij_javascript_union_types_wrap = on_every_item
ij_javascript_use_chained_calls_group_indents = false
ij_javascript_use_double_quotes = false
ij_javascript_use_explicit_js_extension = global
ij_javascript_use_path_mapping = always
ij_javascript_use_public_modifier = false
ij_javascript_use_semicolon_after_statement = true
ij_javascript_var_declaration_wrap = normal
ij_javascript_while_brace_force = never
ij_javascript_while_on_new_line = false
ij_javascript_wrap_comments = false
##
# Shell scripts
##
[{*.bash,*.sh,*.zsh}]
indent_size = 2
tab_width = 2
##
# EditorConfig
##
[.editorconfig]
ij_editorconfig_align_group_field_declarations = false
ij_editorconfig_space_after_colon = false
@ -263,49 +913,3 @@ ij_editorconfig_space_after_comma = true
ij_editorconfig_space_before_colon = false
ij_editorconfig_space_before_comma = false
ij_editorconfig_spaces_around_assignment_operators = true
[{*.ant, *.fxml, *.jhm, *.jnlp, *.jrxml, *.pom, *.rng, *.tld, *.wsdl, *.xml, *.xsd, *.xsl, *.xslt, *.xul}]
ij_xml_align_attributes = true
ij_xml_align_text = false
ij_xml_attribute_wrap = normal
ij_xml_block_comment_at_first_column = true
ij_xml_keep_blank_lines = 2
ij_xml_keep_indents_on_empty_lines = false
ij_xml_keep_line_breaks = true
ij_xml_keep_line_breaks_in_text = true
ij_xml_keep_whitespaces = false
ij_xml_keep_whitespaces_around_cdata = preserve
ij_xml_keep_whitespaces_inside_cdata = false
ij_xml_line_comment_at_first_column = true
ij_xml_space_after_tag_name = false
ij_xml_space_around_equals_in_attribute = false
ij_xml_space_inside_empty_tag = false
ij_xml_text_wrap = normal
[{*.markdown, *.md}]
indent_size = 2
tab_width = 2
ij_markdown_force_one_space_after_blockquote_symbol = true
ij_markdown_force_one_space_after_header_symbol = true
ij_markdown_force_one_space_after_list_bullet = true
ij_markdown_force_one_space_between_words = true
ij_markdown_keep_indents_on_empty_lines = false
ij_markdown_max_lines_around_block_elements = 1
ij_markdown_max_lines_around_header = 1
ij_markdown_max_lines_between_paragraphs = 1
ij_markdown_min_lines_around_block_elements = 1
ij_markdown_min_lines_around_header = 1
ij_markdown_min_lines_between_paragraphs = 1
[{*.yaml, *.yml, *.lang}]
indent_size = 2
ij_yaml_align_values_properties = do_not_align
ij_yaml_autoinsert_sequence_marker = true
ij_yaml_block_mapping_on_new_line = false
ij_yaml_indent_sequence_value = true
ij_yaml_keep_indents_on_empty_lines = false
ij_yaml_keep_line_breaks = true
ij_yaml_sequence_on_new_line = false
ij_yaml_space_before_colon = false
ij_yaml_spaces_within_braces = true
ij_yaml_spaces_within_brackets = true

View File

@ -50,13 +50,13 @@ jobs:
if: ${{ success() && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development') }}
continue-on-error: true
run: |
curl -X POST --data "{\"content\":null,\"embeds\":[{\"title\":\"Build succeeded!\",\"description\":\"The build with the ID #$GITHUB_RUN_NUMBER has succeeded!\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\",\"color\":5490477,\"fields\":[{\"name\":\"Branch\",\"value\":\"$GITHUB_REF\",\"inline\":true}],\"author\":{\"name\":\"$GITHUB_REPOSITORY\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY\",\"icon_url\":\"$GITHUB_SERVER_URL/songoda.png\"},\"footer\":{\"text\":\"Initiated by $GITHUB_ACTOR\",\"icon_url\":\"$GITHUB_SERVER_URL/$GITHUB_ACTOR.png\"}}],\"username\":\"OctoAgent\",\"avatar_url\":\"https://github.githubassets.com/images/modules/logos_page/Octocat.png\"}" --header 'Content-Type: application/json' $DISCORD_WEBHOOK
curl -X POST --data "{\"content\":null,\"embeds\":[{\"title\":\"Build succeeded!\",\"description\":\"The build with the ID #$GITHUB_RUN_NUMBER has succeeded!\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\",\"color\":5490477,\"fields\":[{\"name\":\"Branch\",\"value\":\"$GITHUB_REF\",\"inline\":true}],\"author\":{\"name\":\"$GITHUB_REPOSITORY\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY\",\"icon_url\":\"$GITHUB_SERVER_URL/songoda.png\"},\"footer\":{\"text\":\"Initiated by $GITHUB_ACTOR\",\"icon_url\":\"$GITHUB_SERVER_URL/$GITHUB_ACTOR.png\"}}],\"username\":\"OctoAgent\",\"avatar_url\":\"https://github.githubassets.com/images/modules/logos_page/Octocat.png\"}" --header 'Content-Type: application/json' $DISCORD_WEBHOOK
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_BUILD_STATUS_WEBHOOK }}
- name: 'Discord Webhook (Failure)'
if: ${{ failure() && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development') }}
continue-on-error: true
run: |
curl -X POST --data "{\"content\":null,\"embeds\":[{\"title\":\"Build failed!\",\"description\":\"The build with the ID #$GITHUB_RUN_NUMBER has failed!\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\",\"color\":15611419,\"fields\":[{\"name\":\"Branch\",\"value\":\"$GITHUB_REF\",\"inline\":true}],\"author\":{\"name\":\"$GITHUB_REPOSITORY\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY\",\"icon_url\":\"$GITHUB_SERVER_URL/songoda.png\"},\"footer\":{\"text\":\"Initiated by $GITHUB_ACTOR\",\"icon_url\":\"$GITHUB_SERVER_URL/$GITHUB_ACTOR.png\"}}],\"username\":\"OctoAgent\",\"avatar_url\":\"https://github.githubassets.com/images/modules/logos_page/Octocat.png\"}" --header "Content-Type:application/json" $DISCORD_WEBHOOK
curl -X POST --data "{\"content\":null,\"embeds\":[{\"title\":\"Build failed!\",\"description\":\"The build with the ID #$GITHUB_RUN_NUMBER has failed!\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\",\"color\":15611419,\"fields\":[{\"name\":\"Branch\",\"value\":\"$GITHUB_REF\",\"inline\":true}],\"author\":{\"name\":\"$GITHUB_REPOSITORY\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY\",\"icon_url\":\"$GITHUB_SERVER_URL/songoda.png\"},\"footer\":{\"text\":\"Initiated by $GITHUB_ACTOR\",\"icon_url\":\"$GITHUB_SERVER_URL/$GITHUB_ACTOR.png\"}}],\"username\":\"OctoAgent\",\"avatar_url\":\"https://github.githubassets.com/images/modules/logos_page/Octocat.png\"}" --header "Content-Type:application/json" $DISCORD_WEBHOOK
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_BUILD_STATUS_WEBHOOK }}

1
.gitignore vendored
View File

@ -14,6 +14,7 @@
/NMS/*/target/
dependency-reduced-pom.xml
/**/logs/*.log
##
# Misc.

View File

@ -1,7 +1,6 @@
package com.songoda.core.compatibility;
public enum ClassMapping {
BIOME_BASE("world.level.biome", "BiomeBase"),
BIOME_STORAGE("world.level.chunk", "BiomeStorage"),
BLOCK("world.level.block", "Block"),
@ -65,15 +64,18 @@ public enum ClassMapping {
public Class<?> getClazz(String sub) {
try {
String name = sub == null ? className : className + "$" + sub;
if (className.startsWith("Craft"))
if (className.startsWith("Craft")) {
return Class.forName("org.bukkit.craftbukkit." + ServerVersion.getServerVersionString()
+ (packageName == null ? "" : "." + packageName) + "." + name);
}
return Class.forName("net.minecraft." + (
ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17) && packageName != null
? packageName : "server." + ServerVersion.getServerVersionString()) + "." + name);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
return null;
}
}

View File

@ -19,12 +19,8 @@ import java.util.Set;
/**
* Biomes that are compatible with server versions 1.7+
*
* @author Brianna
* @since 2020-03-27
*/
public enum CompatibleBiome {
/* 1.17 */
DRIPSTONE_CAVES(ServerVersion.V1_17),
LUSH_CAVES(ServerVersion.V1_17),
@ -114,20 +110,24 @@ public enum CompatibleBiome {
private static final boolean isAbove1_16_R1 = ServerVersion.isServerVersionAtLeast(ServerVersion.V1_16)
&& !ServerVersion.getServerVersionString().equals("v1_16_R1");
private static final Map<String, CompatibleBiome> lookupMap = new HashMap();
private static final Map<String, CompatibleBiome> lookupMap = new HashMap<>();
private static final Set<CompatibleBiome> compatibleBiomes = new HashSet<>();
private final Deque<Version> versions = new ArrayDeque<>();
private static Method methodGetHandle, methodMarkDirty, methodBiomeToBiomeBase, methodGetBiomeIndex, methodSetBiome;
private static Field fieldStorageRegistry;
static {
for (CompatibleBiome biome : values())
for (Version version : biome.getVersions())
for (CompatibleBiome biome : values()) {
for (Version version : biome.getVersions()) {
lookupMap.put(version.biome, biome);
}
}
for (CompatibleBiome biome : CompatibleBiome.values())
if (biome.isCompatible())
for (CompatibleBiome biome : CompatibleBiome.values()) {
if (biome.isCompatible()) {
compatibleBiomes.add(biome);
}
}
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_15)) {
try {
@ -148,13 +148,14 @@ public enum CompatibleBiome {
try {
// If 1.16.5
fieldStorageRegistry = classBiomeStorage.getDeclaredField("registry");
} catch (NoSuchFieldException e) {
} catch (NoSuchFieldException ex) {
// If less than 1.16.5
fieldStorageRegistry = classBiomeStorage.getDeclaredField("g");
}
fieldStorageRegistry.setAccessible(true);
} catch (NoSuchMethodException | NoSuchFieldException e) {
e.printStackTrace();
} catch (NoSuchMethodException | NoSuchFieldException ex) {
ex.printStackTrace();
}
}
}
@ -171,6 +172,7 @@ public enum CompatibleBiome {
public boolean isCompatible() {
Version version = versions.getLast();
ServerVersion.isServerVersionAtLeast(version.version);
return true;
}
@ -179,9 +181,12 @@ public enum CompatibleBiome {
}
public Biome getBiome() {
for (Version version : versions)
if (ServerVersion.isServerVersionAtLeast(version.version))
for (Version version : versions) {
if (ServerVersion.isServerVersionAtLeast(version.version)) {
return Biome.valueOf(version.biome);
}
}
return null;
}
@ -201,14 +206,17 @@ public enum CompatibleBiome {
Object nmsChunk = null;
Object biomeStorage = null;
Object biomeBase = null;
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_15)) {
nmsChunk = methodGetHandle.invoke(chunk);
biomeStorage = methodGetBiomeIndex.invoke(nmsChunk);
if (isAbove1_16_R1) {
Object registry = fieldStorageRegistry.get(biomeStorage);
biomeBase = methodBiomeToBiomeBase.invoke(null, registry, getBiome());
} else
} else {
biomeBase = methodBiomeToBiomeBase.invoke(null, getBiome());
}
}
World world = chunk.getWorld();
@ -216,22 +224,31 @@ public enum CompatibleBiome {
int chunkZ = chunk.getZ();
for (int x = chunkX << 4; x < (chunkX << 4) + 16; x++) {
for (int z = chunkZ << 4; z < (chunkZ << 4) + 16; z++) {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_15))
for (int y = 0; y < world.getMaxHeight(); ++y)
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_15)) {
for (int y = 0; y < world.getMaxHeight(); ++y) {
methodSetBiome.invoke(biomeStorage, x >> 2, y >> 2, z >> 2, biomeBase);
else
chunk.getWorld().setBiome(x, z, getBiome());
}
continue;
}
chunk.getWorld().setBiome(x, z, getBiome());
}
}
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_15))
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_15)) {
methodMarkDirty.invoke(nmsChunk);
}
}
public void setBiome(World world, int x, int y, int z) {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_15))
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_15)) {
world.setBiome(x, y, z, getBiome());
else
world.setBiome(x, z, getBiome());
return;
}
world.setBiome(x, z, getBiome());
}
private static Version v(ServerVersion version, String biome) {
@ -243,7 +260,6 @@ public enum CompatibleBiome {
}
private static class Version {
final ServerVersion version;
final String biome;

View File

@ -11,20 +11,17 @@ import java.util.Map;
/**
* Get which hand is being used.
*
* @author Brianna
* @since 2020-03-24
*/
public enum CompatibleHand {
MAIN_HAND, OFF_HAND;
private static Map<String, Method> methodCache = new HashMap<>();
private static final Map<String, Method> methodCache = new HashMap<>();
public static CompatibleHand getHand(Object event) {
try {
Class<?> clazz = event.getClass();
String className = clazz.getName();
Method method;
if (methodCache.containsKey(className)) {
method = methodCache.get(className);
@ -32,10 +29,15 @@ public enum CompatibleHand {
method = clazz.getDeclaredMethod("getHand");
methodCache.put(className, method);
}
EquipmentSlot slot = (EquipmentSlot) method.invoke(event);
if (slot == EquipmentSlot.OFF_HAND) return OFF_HAND;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
if (slot == EquipmentSlot.OFF_HAND) {
return OFF_HAND;
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignore) {
}
return MAIN_HAND;
}
@ -65,10 +67,12 @@ public enum CompatibleHand {
int result = item.getAmount() - amount;
item.setAmount(result);
if (this == CompatibleHand.MAIN_HAND)
if (this == CompatibleHand.MAIN_HAND) {
player.setItemInHand(result > 0 ? item : null);
else
player.getInventory().setItemInOffHand(result > 0 ? item : null);
return;
}
player.getInventory().setItemInOffHand(result > 0 ? item : null);
}
/**
@ -79,10 +83,11 @@ public enum CompatibleHand {
* @return the item
*/
public ItemStack getItem(Player player) {
if (this == MAIN_HAND)
if (this == MAIN_HAND) {
return player.getItemInHand();
else
return player.getInventory().getItemInOffHand();
}
return player.getInventory().getItemInOffHand();
}
/**
@ -92,9 +97,11 @@ public enum CompatibleHand {
* @param item the item to set
*/
public void setItem(Player player, ItemStack item) {
if (this == MAIN_HAND)
if (this == MAIN_HAND) {
player.setItemInHand(item);
else
player.getInventory().setItemInOffHand(item);
return;
}
player.getInventory().setItemInOffHand(item);
}
}

View File

@ -16,12 +16,9 @@ import java.util.Set;
/**
* Items that are compatible with server versions 1.7+
*
* @author jascotty2
* @since 2019-08-23
*/
public enum CompatibleMaterial {
/*
/*
TODO: add another handler for getBlockItem() for materials and fallback materials
Legacy has some values not used in modern, eg:
@ -33,7 +30,7 @@ public enum CompatibleMaterial {
JUNGLE_DOOR_ITEM(429),
ACACIA_DOOR_ITEM(430),
DARK_OAK_DOOR_ITEM(431),
*/
*/
/* 1.17 */
AMETHYST_BLOCK(),
@ -1296,7 +1293,7 @@ public enum CompatibleMaterial {
// quick test to see if our version is < 1.13
protected static final boolean useLegacy = ServerVersion.isServerVersionBelow(ServerVersion.V1_13);
// map to speed up name->material lookups
private static final Map<String, CompatibleMaterial> lookupMap = new HashMap();
private static final Map<String, CompatibleMaterial> lookupMap = new HashMap<>();
static {
for (CompatibleMaterial m : values()) {
@ -1304,22 +1301,27 @@ public enum CompatibleMaterial {
lookupMap.put(m.legacy, m);
continue;
}
lookupMap.put(m.name(), m);
if (!m.usesCompatibility()) {
lookupMap.put(m.material + ":" + (m.data == null ? "" : m.data), m);
}
}
for (CompatibleMaterial m : values()) {
if (!m.usesCompatibility()) {
if (m.legacy != null && !lookupMap.containsKey(m.legacy)) {
lookupMap.put(m.legacy, m);
}
if (m.modern2 != null && !lookupMap.containsKey(m.modern2)) {
lookupMap.put(m.modern2, m);
}
if (m.legacyBlockMaterial != null && !lookupMap.containsKey(m.legacyBlockMaterial.blockMaterialName)) {
lookupMap.put(m.legacyBlockMaterial.blockMaterialName, m);
}
if (m.legacyBlockMaterial != null && !lookupMap.containsKey(m.legacyBlockMaterial.alternateBlockMaterialName)) {
lookupMap.put(m.legacyBlockMaterial.alternateBlockMaterialName, m);
}
@ -1422,8 +1424,6 @@ public enum CompatibleMaterial {
/**
* Does this material need to use a legacy fallback?
*
* @return
*/
public boolean usesLegacy() {
return legacy != null && ServerVersion.isServerVersionBelow(minVersion);
@ -1431,8 +1431,6 @@ public enum CompatibleMaterial {
/**
* Does this material need to use a fallback item on this server?
*
* @return
*/
public boolean usesCompatibility() {
return compatibleMaterial != null && material == compatibleMaterial.material;
@ -1441,18 +1439,13 @@ public enum CompatibleMaterial {
/**
* Is this item reused in later versions of Minecraft?
*
* @return
*/
public boolean isRecycled() {
return usesLegacy() && this == CompatibleMaterial.GRASS;
}
/**
* Get the legacy data value for this material if there is one, or -1 if
* none
*
* @return
* Get the legacy data value for this material if there is one, or -1 if none
*/
public byte getData() {
return data != null ? data : -1;
@ -1523,6 +1516,7 @@ public enum CompatibleMaterial {
if (item == null) {
return null;
}
String key = item.getType() + ":";
CompatibleMaterial m = lookupMap.get(key);
return m != null ? m : lookupMap.get(key + item.getDurability());
@ -1561,8 +1555,8 @@ public enum CompatibleMaterial {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_12)) {
try {
methodGetBlockData = FallingBlock.class.getDeclaredMethod("getBlockData");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
}
}
@ -1575,16 +1569,20 @@ public enum CompatibleMaterial {
* @return LegacyMaterial or null if none found
*/
public static CompatibleMaterial getMaterial(FallingBlock block) {
if (block == null) return null;
if (block == null) {
return null;
}
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
return getMaterial(block.getBlockData().getMaterial());
} else {
try {
return getMaterial(block.getMaterial(), (byte) methodGetBlockData.invoke(block));
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
try {
return getMaterial(block.getMaterial(), (byte) methodGetBlockData.invoke(block));
} catch (IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();
}
return null;
}
@ -1599,21 +1597,21 @@ public enum CompatibleMaterial {
public static CompatibleMaterial getMaterial(Material mat, byte data) {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) { // Flattening
return CompatibleMaterial.getMaterial(mat);
} else { // Pre-Flattening
if (mat != null) {
if (data != 0) {
for (CompatibleMaterial cm : CompatibleMaterial.values()) {
if (cm.getMaterial() != null
&& cm.getMaterial().equals(mat)) {
if (cm.getData() == data) {
return cm;
}
}
}
// Pre-Flattening
if (mat != null) {
if (data != 0) {
for (CompatibleMaterial cm : CompatibleMaterial.values()) {
if (cm.getMaterial() != null && cm.getMaterial().equals(mat) && cm.getData() == data) {
return cm;
}
}
return CompatibleMaterial.getMaterial(mat);
}
return CompatibleMaterial.getMaterial(mat);
}
return null;
}
@ -1621,15 +1619,19 @@ public enum CompatibleMaterial {
if (block == null) {
return null;
}
Material mat = block.getType();
if (useLegacy) {
LegacyMaterialBlockType legacyBlock = LegacyMaterialBlockType.getFromLegacy(mat.name(), block.getData());
if (legacyBlock != null) {
return lookupMap.get(legacyBlock.name());
}
CompatibleMaterial withData = lookupMap.get(mat.name() + ":" + block.getData());
return withData == null ? lookupMap.get(mat.name()) : withData;
}
return lookupMap.get(mat.name());
}
@ -1645,12 +1647,16 @@ public enum CompatibleMaterial {
public static CompatibleMaterial getBlockMaterial(String name) {
if (name == null) {
return null;
} else if (useLegacy) {
}
if (useLegacy) {
LegacyMaterialBlockType legacyBlock = LegacyMaterialBlockType.getFromLegacy(name.toUpperCase());
if (legacyBlock != null) {
return lookupMap.get(legacyBlock.name());
}
}
return lookupMap.get(name.toUpperCase());
}
@ -1667,12 +1673,16 @@ public enum CompatibleMaterial {
public static CompatibleMaterial getBlockMaterial(String name, CompatibleMaterial def) {
if (name == null) {
return def;
} else if (useLegacy) {
}
if (useLegacy) {
LegacyMaterialBlockType legacyBlock = LegacyMaterialBlockType.getFromLegacy(name.toUpperCase());
if (legacyBlock != null) {
return lookupMap.get(legacyBlock.name());
}
}
return lookupMap.getOrDefault(name.toUpperCase(), def);
}
@ -1686,12 +1696,16 @@ public enum CompatibleMaterial {
public static CompatibleMaterial getBlockMaterial(Material mat) {
if (mat == null) {
return null;
} else if (useLegacy) {
}
if (useLegacy) {
LegacyMaterialBlockType legacyBlock = LegacyMaterialBlockType.getFromLegacy(mat.name());
if (legacyBlock != null) {
return lookupMap.get(legacyBlock.name());
}
}
return lookupMap.get(mat.name());
}
@ -1699,13 +1713,15 @@ public enum CompatibleMaterial {
public static Set<CompatibleMaterial> getAllValidItemMaterials() {
if (all == null) {
all = new LinkedHashSet();
all = new LinkedHashSet<>();
for (CompatibleMaterial mat : values()) {
if (mat.isValidItem() && !mat.usesCompatibility()) {
all.add(mat);
}
}
}
return Collections.unmodifiableSet(all);
}
@ -1723,10 +1739,12 @@ public enum CompatibleMaterial {
if (name == null) {
return null;
}
CompatibleMaterial m = lookupMap.get(name.toUpperCase());
if (m != null) {
return m.getItem();
}
Material mat = Material.getMaterial(name);
return mat != null ? new ItemStack(mat) : null;
}
@ -1737,8 +1755,8 @@ public enum CompatibleMaterial {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_12)) {
try {
methodSetData = Block.class.getDeclaredMethod("setData", byte.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
}
}
@ -1750,12 +1768,14 @@ public enum CompatibleMaterial {
*/
public void applyToBlock(Block block) {
if (block == null) return;
block.setType(material);
if (data != null && data != -1 && ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_12)) {
try {
methodSetData.invoke(block, data);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException | InvocationTargetException ex) {
ex.printStackTrace();
}
}
}
@ -1768,14 +1788,15 @@ public enum CompatibleMaterial {
* @return true if material of the ItemStack matches this item, corrected for legacy data
*/
public boolean matches(ItemStack item) {
return item != null && !usesCompatibility() && item.getType() == material && (data == null || item.getDurability() == data); // eons ago, ItemStack.getData() would return a byte. 1.7 doesn't, though.
return item != null &&
!usesCompatibility() && item.getType() == material &&
// eons ago, ItemStack.getData() would return a byte. 1.7 doesn't, though.
(data == null || item.getDurability() == data);
}
/**
* Some blocks change to other materials when placed down. This checks to
* see if this one is one of those.
*
* @return
*/
public boolean hasDifferentBlockItem() {
switch (this) {
@ -1832,14 +1853,13 @@ public enum CompatibleMaterial {
case CAKE:
case COMPARATOR:
return usesLegacy();
default:
return false;
}
return false;
}
/**
* Check to see if this is a material that can exist as a block
*
* @return
*/
public boolean isBlock() {
return material != null && material.isBlock();
@ -1847,8 +1867,6 @@ public enum CompatibleMaterial {
/**
* Check to see if this is an item that can be consumed to restore hunger
*
* @return
*/
public boolean isEdible() {
return material != null && material.isEdible();
@ -1856,8 +1874,6 @@ public enum CompatibleMaterial {
/**
* Check if the material is a block and can be built on
*
* @return
*/
public boolean isSolid() {
return material != null && material.isSolid();
@ -1865,8 +1881,6 @@ public enum CompatibleMaterial {
/**
* Check if the material is a block and does not block any light
*
* @return
*/
public boolean isTransparent() {
return material != null && material.isTransparent();
@ -1874,8 +1888,6 @@ public enum CompatibleMaterial {
/**
* Check if the material is a block and can catch fire
*
* @return
*/
public boolean isFlammable() {
return material != null && material.isFlammable();
@ -1883,8 +1895,6 @@ public enum CompatibleMaterial {
/**
* Check if the material is a block and can be destroyed by burning
*
* @return
*/
public boolean isBurnable() {
return material != null && material.isBurnable();
@ -1892,11 +1902,9 @@ public enum CompatibleMaterial {
/**
* Checks if this Material can be used as fuel in a Furnace
*
* @return
*/
public boolean isFuel() {
// this function is not implemented in some older versions, so we need this here..
// this function is not implemented in some older versions, so we need this here...
switch (this) {
case ACACIA_BOAT:
case ACACIA_BUTTON:
@ -2253,8 +2261,6 @@ public enum CompatibleMaterial {
/**
* Check if the material is air
*
* @return
*/
public boolean isAir() {
switch (this) {
@ -2269,8 +2275,6 @@ public enum CompatibleMaterial {
/**
* Check if the material is water
*
* @return
*/
public boolean isWater() {
return this == CompatibleMaterial.WATER;
@ -2278,26 +2282,26 @@ public enum CompatibleMaterial {
/**
* Get the EntityType of the monster spawn egg.
*
* @return
*/
public EntityType getEggType() {
String entityName = this.name().replace("_SPAWN_EGG", "");
if (entityName.equals("MOOSHROOM"))
if (entityName.equals("MOOSHROOM")) {
entityName = "MUSHROOM_COW";
else if (entityName.equals("ZOMBIE_PIGMAN"))
} else if (entityName.equals("ZOMBIE_PIGMAN")) {
entityName = "PIG_ZOMBIE";
}
try {
return EntityType.valueOf(entityName);
} catch (IllegalArgumentException e) {
return null;
} catch (IllegalArgumentException ignore) {
}
return null;
}
/**
* Check if the material is a block and completely blocks vision
*
* @return
*/
public boolean isOccluding() {
return material != null && material.isOccluding();
@ -2312,11 +2316,9 @@ public enum CompatibleMaterial {
/**
* Checks if this Material is an obtainable item.
*
* @return
*/
public boolean isItem() {
// this function is not implemented in some older versions, so we need this here..
// this function is not implemented in some older versions, so we need this here...
switch (this) {
case CAVE_AIR:
case VOID_AIR:
@ -2410,19 +2412,18 @@ public enum CompatibleMaterial {
case YELLOW_WALL_BANNER:
case ZOMBIE_WALL_HEAD:
return false;
default:
return true;
}
return true;
}
/**
* Checks if this Material can be interacted with. <br />
* This method will return true if there is at least one state in which
* additional interact handling is performed for the material.
*
* @return
*/
public boolean isInteractable() {
// this function is not implemented in some older versions, so we need this here..
// this function is not implemented in some older versions, so we need this here...
switch (this) {
case ACACIA_BUTTON:
case ACACIA_DOOR:
@ -2634,11 +2635,11 @@ public enum CompatibleMaterial {
case WHITE_BED:
case WHITE_SHULKER_BOX:
case YELLOW_BED:
case YELLOW_SHULKER_BOX: {
case YELLOW_SHULKER_BOX:
return true;
}
default:
return false;
}
return false;
}
/**
@ -2738,7 +2739,10 @@ public enum CompatibleMaterial {
case WHITE_WALL_BANNER:
case WITHER_SKELETON_WALL_SKULL:
return false;
default:
break;
}
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_12)) {
switch (this) {
case ACACIA_WOOD:
@ -2754,8 +2758,11 @@ public enum CompatibleMaterial {
case STRIPPED_OAK_WOOD:
case STRIPPED_SPRUCE_WOOD:
return false;
default:
break;
}
}
return true;
}
@ -2786,8 +2793,9 @@ public enum CompatibleMaterial {
return false;
}
/**
* @return true if this material is a food that can be cooked and is in its cooked state
* @return true if this material is food that can be cooked and is in its cooked state
*/
public boolean isCooked() {
switch (this) {
@ -2801,12 +2809,13 @@ public enum CompatibleMaterial {
case COOKED_SALMON:
case DRIED_KELP:
return true;
default:
return false;
}
return false;
}
/**
* @return true if this material is a food that can be cooked and is in its raw state
* @return true if this material is food that can be cooked and is in its raw state
*/
public boolean isRaw() {
switch (this) {
@ -2820,8 +2829,9 @@ public enum CompatibleMaterial {
case RABBIT:
case SALMON:
return true;
default:
return false;
}
return false;
}
/**
@ -2836,8 +2846,9 @@ public enum CompatibleMaterial {
case PEONY:
case TALL_GRASS:
return true;
default:
return false;
}
return false;
}
/**
@ -2935,8 +2946,7 @@ public enum CompatibleMaterial {
return MOOSHROOM_SPAWN_EGG;
}
if (ServerVersion.isServerVersionBelow(ServerVersion.V1_16)
&& type == EntityType.valueOf("PIG_ZOMBIE")) {
if (ServerVersion.isServerVersionBelow(ServerVersion.V1_16) && type == EntityType.valueOf("PIG_ZOMBIE")) {
return ZOMBIE_PIGMAN_SPAWN_EGG;
}
@ -2977,8 +2987,9 @@ public enum CompatibleMaterial {
return RED_STAINED_GLASS_PANE;
case 15:
return BLACK_STAINED_GLASS_PANE;
default:
return WHITE_STAINED_GLASS;
}
return WHITE_STAINED_GLASS_PANE;
}
public static CompatibleMaterial getGlassColor(int color) {
@ -3015,8 +3026,9 @@ public enum CompatibleMaterial {
return RED_STAINED_GLASS;
case 15:
return BLACK_STAINED_GLASS;
default:
return WHITE_STAINED_GLASS;
}
return WHITE_STAINED_GLASS;
}
public static CompatibleMaterial getWoolColor(int color) {
@ -3053,8 +3065,9 @@ public enum CompatibleMaterial {
return RED_WOOL;
case 15:
return BLACK_WOOL;
default:
return WHITE_WOOL;
}
return WHITE_WOOL;
}
public static CompatibleMaterial getDyeColor(int color) {
@ -3091,7 +3104,8 @@ public enum CompatibleMaterial {
return ORANGE_DYE;
case 15:
return WHITE_DYE;
default:
return WHITE_DYE;
}
return WHITE_DYE;
}
}

View File

@ -1,326 +1,325 @@
package com.songoda.core.compatibility;
import org.bukkit.Color;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public class CompatibleParticleHandler {
public static enum ParticleType {
EXPLOSION_NORMAL,
EXPLOSION_LARGE,
EXPLOSION_HUGE,
FIREWORKS_SPARK,
WATER_BUBBLE,
WATER_SPLASH,
WATER_WAKE,
SUSPENDED,
SUSPENDED_DEPTH,
CRIT,
CRIT_MAGIC,
SMOKE_NORMAL,
SMOKE_LARGE,
SPELL,
SPELL_INSTANT,
SPELL_MOB,
SPELL_MOB_AMBIENT,
SPELL_WITCH,
DRIP_WATER,
DRIP_LAVA,
VILLAGER_ANGRY,
VILLAGER_HAPPY,
TOWN_AURA,
NOTE,
PORTAL,
ENCHANTMENT_TABLE,
FLAME,
LAVA,
CLOUD,
REDSTONE(), //DustOptions
SNOWBALL,
SNOW_SHOVEL,
SLIME,
HEART,
BARRIER,
ITEM_CRACK(), // ItemStack
BLOCK_CRACK(), // BlockData
BLOCK_DUST(), // BlockData
WATER_DROP,
// 1.8-1.12 included ITEM_TAKE
MOB_APPEARANCE,
/// End 1.8 particles ///
DRAGON_BREATH(ServerVersion.V1_9, "SPELL_MOB_AMBIENT"),
END_ROD(ServerVersion.V1_9, "ENCHANTMENT_TABLE"),
DAMAGE_INDICATOR(ServerVersion.V1_9, "VILLAGER_ANGRY"),
SWEEP_ATTACK(ServerVersion.V1_9, "CRIT"),
/// End 1.9 particles ///
FALLING_DUST(ServerVersion.V1_10, "BLOCK_DUST"), // BlockData
/// End 1.10 ///
TOTEM(ServerVersion.V1_11, "VILLAGER_HAPPY"),
SPIT(ServerVersion.V1_11, "REDSTONE"),
/// End 1.11-1.12 ///
SQUID_INK(ServerVersion.V1_13, "CRIT"),
BUBBLE_POP(ServerVersion.V1_13, "CRIT"),
CURRENT_DOWN(ServerVersion.V1_13, "CRIT"),
BUBBLE_COLUMN_UP(ServerVersion.V1_13, "CRIT"),
NAUTILUS(ServerVersion.V1_13, "ENCHANTMENT_TABLE"),
DOLPHIN(ServerVersion.V1_13, "TOWN_AURA"),
/// End 1.13 ///
SNEEZE(ServerVersion.V1_14, "REDSTONE"),
CAMPFIRE_COSY_SMOKE(ServerVersion.V1_14, "SMOKE_NORMAL"),
CAMPFIRE_SIGNAL_SMOKE(ServerVersion.V1_14, "SMOKE_LARGE"),
COMPOSTER(ServerVersion.V1_14, "CRIT"),
FLASH(ServerVersion.V1_14, "EXPLOSION_NORMAL"), // idk
FALLING_LAVA(ServerVersion.V1_14, "DRIP_LAVA"),
LANDING_LAVA(ServerVersion.V1_14, "LAVA"),
FALLING_WATER(ServerVersion.V1_14, "DRIP_WATER"),
/// End 1.14 ///
DRIPPING_HONEY(ServerVersion.V1_15, "DRIP_WATER"),
FALLING_HONEY(ServerVersion.V1_15, "DRIP_WATER"),
FALLING_NECTAR(ServerVersion.V1_15, "DRIP_WATER"),
LANDING_HONEY(ServerVersion.V1_15, "DRIP_WATER"),
/// End 1.15 ///
// ToDo: Someone needs to make better compatible fall backs.
SOUL_FIRE_FLAME(ServerVersion.V1_16, "DRIP_WATER"),
ASH(ServerVersion.V1_16, "DRIP_WATER"),
CRIMSON_SPORE(ServerVersion.V1_16, "DRIP_WATER"),
WARPED_SPORE(ServerVersion.V1_16, "DRIP_WATER"),
SOUL(ServerVersion.V1_16, "DRIP_WATER"),
DRIPPING_OBSIDIAN_TEAR(ServerVersion.V1_16, "DRIP_WATER"),
FALLING_OBSIDIAN_TEAR(ServerVersion.V1_16, "DRIP_WATER"),
LANDING_OBSIDIAN_TEAR(ServerVersion.V1_16, "DRIP_WATER"),
REVERSE_PORTAL(ServerVersion.V1_16, "DRIP_WATER"),
WHITE_ASH(ServerVersion.V1_16, "DRIP_WATER"),
/// End 1.16 ///
// ToDo: Someone needs to make better compatible fall backs.
LIGHT(ServerVersion.V1_17, "DRIP_WATER"),
DUST_COLOR_TRANSITION(ServerVersion.V1_17, "DRIP_WATER"),
VIBRATION(ServerVersion.V1_17, "DRIP_WATER"),
FALLING_SPORE_BLOSSOM(ServerVersion.V1_17, "DRIP_WATER"),
SPORE_BLOSSOM_AIR(ServerVersion.V1_17, "DRIP_WATER"),
SMALL_FLAME(ServerVersion.V1_17, "DRIP_WATER"),
SNOWFLAKE(ServerVersion.V1_17, "DRIP_WATER"),
DRIPPING_DRIPSTONE_LAVA(ServerVersion.V1_17, "DRIP_WATER"),
FALLING_DRIPSTONE_LAVA(ServerVersion.V1_17, "DRIP_WATER"),
DRIPPING_DRIPSTONE_WATER(ServerVersion.V1_17, "DRIP_WATER"),
FALLING_DRIPSTONE_WATER(ServerVersion.V1_17, "DRIP_WATER"),
GLOW_SQUID_INK(ServerVersion.V1_17, "DRIP_WATER"),
GLOW(ServerVersion.V1_17, "DRIP_WATER"),
WAX_ON(ServerVersion.V1_17, "DRIP_WATER"),
WAX_OFF(ServerVersion.V1_17, "DRIP_WATER"),
ELECTRIC_SPARK(ServerVersion.V1_17, "DRIP_WATER"),
SCRAPE(ServerVersion.V1_17, "DRIP_WATER"),
/// End 1.17 ///
;
final boolean compatibilityMode;
final LegacyParticleEffects.Type compatibleEffect;
final Object particle;
final static Map<String, ParticleType> map = new HashMap<>();
static {
for (ParticleType t : values()) {
map.put(t.name(), t);
}
}
private ParticleType() {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
this.compatibilityMode = true;
this.particle = null;
this.compatibleEffect = LegacyParticleEffects.Type.valueOf(name());
} else {
this.compatibleEffect = null;
// does this particle exist in our version?
Particle check = Stream.of(Particle.values()).filter(p -> p.name().equals(name())).findFirst().orElse(null);
if (check != null) {
this.particle = check;
this.compatibilityMode = false;
} else {
// this shouldn't happen, really
this.particle = Particle.END_ROD;
this.compatibilityMode = true;
}
}
}
private ParticleType(ServerVersion minVersion, String compatible) {
// Particle class doesn't exist in 1.8
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
this.compatibilityMode = true;
this.compatibleEffect = LegacyParticleEffects.Type.valueOf(compatible);
this.particle = null;
} else if (ServerVersion.isServerVersionBelow(minVersion)) {
this.compatibilityMode = true;
this.compatibleEffect = null;
this.particle = Particle.valueOf(compatible);
} else {
this.compatibleEffect = null;
// does this particle exist in our version?
Particle check = Stream.of(Particle.values()).filter(p -> p.name().equals(name())).findFirst().orElse(null);
if (check != null) {
this.particle = check;
this.compatibilityMode = false;
} else {
// this shouldn't happen, really
this.particle = Particle.END_ROD;
this.compatibilityMode = true;
}
}
}
public static ParticleType getParticle(String name) {
return map.get(name);
}
}
public static void spawnParticles(String type, Location location) {
spawnParticles(type, location, 0);
}
public static void spawnParticles(String type, Location location, int count) {
ParticleType pt;
if (type != null && (pt = ParticleType.getParticle(type.toUpperCase())) != null) {
spawnParticles(pt, location, count);
}
}
public static void spawnParticles(String type, Location location, int count, double offsetX, double offsetY, double offsetZ) {
ParticleType pt;
if (type != null && (pt = ParticleType.getParticle(type.toUpperCase())) != null) {
spawnParticles(pt, location, count, offsetX, offsetY, offsetZ);
}
}
public static void spawnParticles(ParticleType type, Location location) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
LegacyParticleEffects.createParticle(location, type.compatibleEffect);
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, 0);
}
}
public static void spawnParticles(ParticleType type, Location location, int count) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
for (int i = 0; i < count; i++) {
float xx = (float) (1 * (Math.random() - Math.random()));
float yy = (float) (1 * (Math.random() - Math.random()));
float zz = (float) (1 * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, type.compatibleEffect);
}
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, count);
}
}
public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
for (int i = 0; i < count; i++) {
float xx = (float) (offsetX * (Math.random() - Math.random()));
float yy = (float) (offsetY * (Math.random() - Math.random()));
float zz = (float) (offsetZ * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, type.compatibleEffect);
}
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ);
}
}
public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ, double extra) {
spawnParticles(type, location, count, offsetX, offsetY, offsetZ, extra, null);
}
public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ, double extra, Player receiver) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
for (int i = 0; i < count; i++) {
float xx = (float) (offsetX * (Math.random() - Math.random()));
float yy = (float) (offsetY * (Math.random() - Math.random()));
float zz = (float) (offsetZ * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, type.compatibleEffect, 0F, 0F, 0F, (float) extra, 0, receiver != null ? Collections.singletonList(receiver) : null);
}
} else {
if (receiver == null) {
location.getWorld().spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ, extra);
} else {
receiver.spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ, extra);
}
}
}
public static void redstoneParticles(Location location, int red, int green, int blue) {
redstoneParticles(location, red, green, blue, 1F, 1, 0, null);
}
public static void redstoneParticles(Location location, int red, int green, int blue, float size, int count, float radius) {
redstoneParticles(location, red, green, blue, size, count, radius, null);
}
/**
* Spawn colored redstone particles
*
* @param location area to spawn the particle in
* @param red red value 0-255
* @param green green value 0-255
* @param blue blue value 0-255
* @param size (1.13+) size of the particles
* @param count how many particles to spawn
* @param radius how far to spread out the particles from location
*/
public static void redstoneParticles(Location location, int red, int green, int blue, float size, int count, float radius, Player player) {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
float xx = (float) (radius * (Math.random() - Math.random()));
float yy = (float) (radius * (Math.random() - Math.random()));
float zz = (float) (radius * (Math.random() - Math.random()));
if (player == null)
location.getWorld().spawnParticle(Particle.REDSTONE, location, count, xx, yy, zz, 1, new Particle.DustOptions(Color.fromBGR(blue, green, red), size));
else
player.spawnParticle(Particle.REDSTONE, location, count, xx, yy, zz, 1, new Particle.DustOptions(Color.fromBGR(blue, green, red), size));
} else if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) {
for (int i = 0; i < count; i++) {
float xx = (float) (radius * (Math.random() - Math.random()));
float yy = (float) (radius * (Math.random() - Math.random()));
float zz = (float) (radius * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
if (player == null)
location.getWorld().spawnParticle(Particle.REDSTONE, at, 0, red / 255F, green / 255F, blue / 255F, size); // particle, location, count, red, green, blue, extra data
else
player.spawnParticle(Particle.REDSTONE, at, 0, red / 255F, green / 255F, blue / 255F, size); // particle, location, count, red, green, blue, extra data
}
} else {
// WE NEED MAGIC!
for (int i = 0; i < count; i++) {
float xx = (float) (radius * (Math.random() - Math.random()));
float yy = (float) (radius * (Math.random() - Math.random()));
float zz = (float) (radius * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, LegacyParticleEffects.Type.REDSTONE,
red / 255F, green / 255F, blue / 255F, 1F,
0, player == null ? null : Collections.singletonList(player));
}
}
}
public static void bonemealSmoke(Location l) {
final org.bukkit.World w = l.getWorld();
w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH_EAST);
w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH);
w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH_WEST);
w.playEffect(l, Effect.SMOKE, BlockFace.EAST);
w.playEffect(l, Effect.SMOKE, BlockFace.SELF);
w.playEffect(l, Effect.SMOKE, BlockFace.WEST);
w.playEffect(l, Effect.SMOKE, BlockFace.NORTH_EAST);
w.playEffect(l, Effect.SMOKE, BlockFace.NORTH);
w.playEffect(l, Effect.SMOKE, BlockFace.NORTH_WEST);
}
}
package com.songoda.core.compatibility;
import org.bukkit.Color;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
public class CompatibleParticleHandler {
public enum ParticleType {
EXPLOSION_NORMAL,
EXPLOSION_LARGE,
EXPLOSION_HUGE,
FIREWORKS_SPARK,
WATER_BUBBLE,
WATER_SPLASH,
WATER_WAKE,
SUSPENDED,
SUSPENDED_DEPTH,
CRIT,
CRIT_MAGIC,
SMOKE_NORMAL,
SMOKE_LARGE,
SPELL,
SPELL_INSTANT,
SPELL_MOB,
SPELL_MOB_AMBIENT,
SPELL_WITCH,
DRIP_WATER,
DRIP_LAVA,
VILLAGER_ANGRY,
VILLAGER_HAPPY,
TOWN_AURA,
NOTE,
PORTAL,
ENCHANTMENT_TABLE,
FLAME,
LAVA,
CLOUD,
REDSTONE(), //DustOptions
SNOWBALL,
SNOW_SHOVEL,
SLIME,
HEART,
BARRIER,
ITEM_CRACK(), // ItemStack
BLOCK_CRACK(), // BlockData
BLOCK_DUST(), // BlockData
WATER_DROP,
// 1.8-1.12 included ITEM_TAKE
MOB_APPEARANCE,
/// End 1.8 particles ///
DRAGON_BREATH(ServerVersion.V1_9, "SPELL_MOB_AMBIENT"),
END_ROD(ServerVersion.V1_9, "ENCHANTMENT_TABLE"),
DAMAGE_INDICATOR(ServerVersion.V1_9, "VILLAGER_ANGRY"),
SWEEP_ATTACK(ServerVersion.V1_9, "CRIT"),
/// End 1.9 particles ///
FALLING_DUST(ServerVersion.V1_10, "BLOCK_DUST"), // BlockData
/// End 1.10 ///
TOTEM(ServerVersion.V1_11, "VILLAGER_HAPPY"),
SPIT(ServerVersion.V1_11, "REDSTONE"),
/// End 1.11-1.12 ///
SQUID_INK(ServerVersion.V1_13, "CRIT"),
BUBBLE_POP(ServerVersion.V1_13, "CRIT"),
CURRENT_DOWN(ServerVersion.V1_13, "CRIT"),
BUBBLE_COLUMN_UP(ServerVersion.V1_13, "CRIT"),
NAUTILUS(ServerVersion.V1_13, "ENCHANTMENT_TABLE"),
DOLPHIN(ServerVersion.V1_13, "TOWN_AURA"),
/// End 1.13 ///
SNEEZE(ServerVersion.V1_14, "REDSTONE"),
CAMPFIRE_COSY_SMOKE(ServerVersion.V1_14, "SMOKE_NORMAL"),
CAMPFIRE_SIGNAL_SMOKE(ServerVersion.V1_14, "SMOKE_LARGE"),
COMPOSTER(ServerVersion.V1_14, "CRIT"),
FLASH(ServerVersion.V1_14, "EXPLOSION_NORMAL"), // idk
FALLING_LAVA(ServerVersion.V1_14, "DRIP_LAVA"),
LANDING_LAVA(ServerVersion.V1_14, "LAVA"),
FALLING_WATER(ServerVersion.V1_14, "DRIP_WATER"),
/// End 1.14 ///
DRIPPING_HONEY(ServerVersion.V1_15, "DRIP_WATER"),
FALLING_HONEY(ServerVersion.V1_15, "DRIP_WATER"),
FALLING_NECTAR(ServerVersion.V1_15, "DRIP_WATER"),
LANDING_HONEY(ServerVersion.V1_15, "DRIP_WATER"),
/// End 1.15 ///
// ToDo: Someone needs to make better compatible fall backs.
SOUL_FIRE_FLAME(ServerVersion.V1_16, "DRIP_WATER"),
ASH(ServerVersion.V1_16, "DRIP_WATER"),
CRIMSON_SPORE(ServerVersion.V1_16, "DRIP_WATER"),
WARPED_SPORE(ServerVersion.V1_16, "DRIP_WATER"),
SOUL(ServerVersion.V1_16, "DRIP_WATER"),
DRIPPING_OBSIDIAN_TEAR(ServerVersion.V1_16, "DRIP_WATER"),
FALLING_OBSIDIAN_TEAR(ServerVersion.V1_16, "DRIP_WATER"),
LANDING_OBSIDIAN_TEAR(ServerVersion.V1_16, "DRIP_WATER"),
REVERSE_PORTAL(ServerVersion.V1_16, "DRIP_WATER"),
WHITE_ASH(ServerVersion.V1_16, "DRIP_WATER"),
/// End 1.16 ///
// ToDo: Someone needs to make better compatible fall backs.
LIGHT(ServerVersion.V1_17, "DRIP_WATER"),
DUST_COLOR_TRANSITION(ServerVersion.V1_17, "DRIP_WATER"),
VIBRATION(ServerVersion.V1_17, "DRIP_WATER"),
FALLING_SPORE_BLOSSOM(ServerVersion.V1_17, "DRIP_WATER"),
SPORE_BLOSSOM_AIR(ServerVersion.V1_17, "DRIP_WATER"),
SMALL_FLAME(ServerVersion.V1_17, "DRIP_WATER"),
SNOWFLAKE(ServerVersion.V1_17, "DRIP_WATER"),
DRIPPING_DRIPSTONE_LAVA(ServerVersion.V1_17, "DRIP_WATER"),
FALLING_DRIPSTONE_LAVA(ServerVersion.V1_17, "DRIP_WATER"),
DRIPPING_DRIPSTONE_WATER(ServerVersion.V1_17, "DRIP_WATER"),
FALLING_DRIPSTONE_WATER(ServerVersion.V1_17, "DRIP_WATER"),
GLOW_SQUID_INK(ServerVersion.V1_17, "DRIP_WATER"),
GLOW(ServerVersion.V1_17, "DRIP_WATER"),
WAX_ON(ServerVersion.V1_17, "DRIP_WATER"),
WAX_OFF(ServerVersion.V1_17, "DRIP_WATER"),
ELECTRIC_SPARK(ServerVersion.V1_17, "DRIP_WATER"),
SCRAPE(ServerVersion.V1_17, "DRIP_WATER"),
/// End 1.17 ///
;
final boolean compatibilityMode;
final LegacyParticleEffects.Type compatibleEffect;
final Object particle;
final static Map<String, ParticleType> map = new HashMap<>();
static {
for (ParticleType t : values()) {
map.put(t.name(), t);
}
}
ParticleType() {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
this.compatibilityMode = true;
this.particle = null;
this.compatibleEffect = LegacyParticleEffects.Type.valueOf(name());
} else {
this.compatibleEffect = null;
// does this particle exist in our version?
Particle check = Stream.of(Particle.values()).filter(p -> p.name().equals(name())).findFirst().orElse(null);
if (check != null) {
this.particle = check;
this.compatibilityMode = false;
} else {
// this shouldn't happen, really
this.particle = Particle.END_ROD;
this.compatibilityMode = true;
}
}
}
ParticleType(ServerVersion minVersion, String compatible) {
// Particle class doesn't exist in 1.8
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
this.compatibilityMode = true;
this.compatibleEffect = LegacyParticleEffects.Type.valueOf(compatible);
this.particle = null;
} else if (ServerVersion.isServerVersionBelow(minVersion)) {
this.compatibilityMode = true;
this.compatibleEffect = null;
this.particle = Particle.valueOf(compatible);
} else {
this.compatibleEffect = null;
// does this particle exist in our version?
Particle check = Stream.of(Particle.values()).filter(p -> p.name().equals(name())).findFirst().orElse(null);
if (check != null) {
this.particle = check;
this.compatibilityMode = false;
} else {
// this shouldn't happen, really
this.particle = Particle.END_ROD;
this.compatibilityMode = true;
}
}
}
public static ParticleType getParticle(String name) {
return map.get(name);
}
}
public static void spawnParticles(String type, Location location) {
spawnParticles(type, location, 0);
}
public static void spawnParticles(String type, Location location, int count) {
ParticleType pt;
if (type != null && (pt = ParticleType.getParticle(type.toUpperCase())) != null) {
spawnParticles(pt, location, count);
}
}
public static void spawnParticles(String type, Location location, int count, double offsetX, double offsetY, double offsetZ) {
ParticleType pt;
if (type != null && (pt = ParticleType.getParticle(type.toUpperCase())) != null) {
spawnParticles(pt, location, count, offsetX, offsetY, offsetZ);
}
}
public static void spawnParticles(ParticleType type, Location location) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
LegacyParticleEffects.createParticle(location, type.compatibleEffect);
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, 0);
}
}
public static void spawnParticles(ParticleType type, Location location, int count) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
for (int i = 0; i < count; i++) {
float xx = (float) (1 * (Math.random() - Math.random()));
float yy = (float) (1 * (Math.random() - Math.random()));
float zz = (float) (1 * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, type.compatibleEffect);
}
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, count);
}
}
public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
for (int i = 0; i < count; i++) {
float xx = (float) (offsetX * (Math.random() - Math.random()));
float yy = (float) (offsetY * (Math.random() - Math.random()));
float zz = (float) (offsetZ * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, type.compatibleEffect);
}
} else {
location.getWorld().spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ);
}
}
public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ, double extra) {
spawnParticles(type, location, count, offsetX, offsetY, offsetZ, extra, null);
}
public static void spawnParticles(ParticleType type, Location location, int count, double offsetX, double offsetY, double offsetZ, double extra, Player receiver) {
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8)) {
for (int i = 0; i < count; i++) {
float xx = (float) (offsetX * (Math.random() - Math.random()));
float yy = (float) (offsetY * (Math.random() - Math.random()));
float zz = (float) (offsetZ * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, type.compatibleEffect, 0F, 0F, 0F, (float) extra, 0, receiver != null ? Collections.singletonList(receiver) : null);
}
} else {
if (receiver == null) {
location.getWorld().spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ, extra);
} else {
receiver.spawnParticle((Particle) type.particle, location, count, offsetX, offsetY, offsetZ, extra);
}
}
}
public static void redstoneParticles(Location location, int red, int green, int blue) {
redstoneParticles(location, red, green, blue, 1F, 1, 0, null);
}
public static void redstoneParticles(Location location, int red, int green, int blue, float size, int count, float radius) {
redstoneParticles(location, red, green, blue, size, count, radius, null);
}
/**
* Spawn colored redstone particles
*
* @param location area to spawn the particle in
* @param red red value 0-255
* @param green green value 0-255
* @param blue blue value 0-255
* @param size (1.13+) size of the particles
* @param count how many particles to spawn
* @param radius how far to spread out the particles from location
*/
public static void redstoneParticles(Location location, int red, int green, int blue, float size, int count, float radius, Player player) {
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
float xx = (float) (radius * (Math.random() - Math.random()));
float yy = (float) (radius * (Math.random() - Math.random()));
float zz = (float) (radius * (Math.random() - Math.random()));
if (player == null)
location.getWorld().spawnParticle(Particle.REDSTONE, location, count, xx, yy, zz, 1, new Particle.DustOptions(Color.fromBGR(blue, green, red), size));
else
player.spawnParticle(Particle.REDSTONE, location, count, xx, yy, zz, 1, new Particle.DustOptions(Color.fromBGR(blue, green, red), size));
} else if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) {
for (int i = 0; i < count; i++) {
float xx = (float) (radius * (Math.random() - Math.random()));
float yy = (float) (radius * (Math.random() - Math.random()));
float zz = (float) (radius * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
if (player == null)
location.getWorld().spawnParticle(Particle.REDSTONE, at, 0, red / 255F, green / 255F, blue / 255F, size); // particle, location, count, red, green, blue, extra data
else
player.spawnParticle(Particle.REDSTONE, at, 0, red / 255F, green / 255F, blue / 255F, size); // particle, location, count, red, green, blue, extra data
}
} else {
// WE NEED MAGIC!
for (int i = 0; i < count; i++) {
float xx = (float) (radius * (Math.random() - Math.random()));
float yy = (float) (radius * (Math.random() - Math.random()));
float zz = (float) (radius * (Math.random() - Math.random()));
Location at = location.clone().add(xx, yy, zz);
LegacyParticleEffects.createParticle(at, LegacyParticleEffects.Type.REDSTONE,
red / 255F, green / 255F, blue / 255F, 1F,
0, player == null ? null : Collections.singletonList(player));
}
}
}
public static void bonemealSmoke(Location l) {
final org.bukkit.World w = l.getWorld();
w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH_EAST);
w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH);
w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH_WEST);
w.playEffect(l, Effect.SMOKE, BlockFace.EAST);
w.playEffect(l, Effect.SMOKE, BlockFace.SELF);
w.playEffect(l, Effect.SMOKE, BlockFace.WEST);
w.playEffect(l, Effect.SMOKE, BlockFace.NORTH_EAST);
w.playEffect(l, Effect.SMOKE, BlockFace.NORTH);
w.playEffect(l, Effect.SMOKE, BlockFace.NORTH_WEST);
}
}

View File

@ -13,13 +13,9 @@ import org.bukkit.entity.Player;
* sounds were renamed. New sounds have been added by different versions, as
* well. The intent of this class is to provide either the correct sound or a
* near equivalent for the current server.
*
* @author jascotty2
* @since 2019-08-25
*/
public enum CompatibleSound {
// some of these values are missing an API value..
// some of these values are missing an API value...
// would using the raw strings be better?
// 1.8 list:
// https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/mapping-and-modding-tutorials/2213619-1-8-all-playsound-sound-arguments
@ -473,8 +469,8 @@ public enum CompatibleSound {
BLOCK_CHEST_CLOSE(ServerVersion.V1_9, v("CHEST_CLOSE")),
BLOCK_CHEST_LOCKED(ServerVersion.V1_9, v("CHEST_CLOSE", true)),
BLOCK_CHEST_OPEN(ServerVersion.V1_9, v("CHEST_OPEN")),
BLOCK_CHORUS_FLOWER_DEATH(ServerVersion.V1_9, v(null, true)), // I have no idea..
BLOCK_CHORUS_FLOWER_GROW(ServerVersion.V1_9, v(null, true)), // I have no idea..
BLOCK_CHORUS_FLOWER_DEATH(ServerVersion.V1_9, v(null, true)), // I have no idea...
BLOCK_CHORUS_FLOWER_GROW(ServerVersion.V1_9, v(null, true)), // I have no idea...
BLOCK_COMPARATOR_CLICK(ServerVersion.V1_9, v("WOOD_CLICK", true)),
BLOCK_COMPOSTER_EMPTY,
BLOCK_COMPOSTER_FILL,
@ -638,7 +634,7 @@ public enum CompatibleSound {
ENTITY_ARMOR_STAND_FALL,
ENTITY_ARMOR_STAND_HIT,
ENTITY_ARMOR_STAND_PLACE,
ENTITY_ARROW_HIT("SUCCESSFUL_HIT"), // these may be reversed..
ENTITY_ARROW_HIT("SUCCESSFUL_HIT"), // these may be reversed...
ENTITY_ARROW_HIT_PLAYER("ARROW_HIT"),
ENTITY_ARROW_SHOOT("SHOOT_ARROW"),
ENTITY_BAT_AMBIENT("BAT_IDLE"),
@ -1226,7 +1222,7 @@ public enum CompatibleSound {
protected /*final*/ boolean compatibilityMode;
protected static final boolean DEBUG = false;
private CompatibleSound() {
CompatibleSound() {
// This could get risky, since we haven't finished this
//sound = Sound.valueOf(name());
Sound find = null;
@ -1244,21 +1240,22 @@ public enum CompatibleSound {
}
// if the sound ony ever changed from 1.8 -> 1.9
private CompatibleSound(String compatibility_18) {
CompatibleSound(String compatibility_18) {
try {
compatibilityMode = false;
if (ServerVersion.isServerVersionBelow(ServerVersion.V1_9)) {
sound = Sound.valueOf(compatibility_18);
} else {
sound = Sound.valueOf(name());
}
} catch (Exception e) {
} catch (Exception ex) {
System.err.println("ERROR loading " + name());
e.printStackTrace();
ex.printStackTrace();
}
}
private CompatibleSound(Version... versions) {
CompatibleSound(Version... versions) {
try {
for (Version v : versions) {
if (v.sound != null && ServerVersion.isServerVersionAtLeast(v.version)) {
@ -1267,12 +1264,13 @@ public enum CompatibleSound {
return;
}
}
} catch (Exception e) {
} catch (Exception ex) {
System.err.println("ERROR loading " + name());
for (Version v : versions) {
System.err.println(v.version + " - " + v.sound);
}
e.printStackTrace();
ex.printStackTrace();
}
Sound find = null;
for (Sound s : Sound.values()) {
@ -1285,7 +1283,7 @@ public enum CompatibleSound {
compatibilityMode = find == null;
}
private CompatibleSound(ServerVersion minVersion, Version... versions) {
CompatibleSound(ServerVersion minVersion, Version... versions) {
try {
if (ServerVersion.isServerVersionAtLeast(minVersion)) {
// should be good to use this sound
@ -1302,12 +1300,13 @@ public enum CompatibleSound {
sound = null;
compatibilityMode = false;
}
} catch (Exception e) {
} catch (Exception ex) {
System.err.println("ERROR loading " + name() + " (" + minVersion);
for (Version v : versions) {
System.err.println(v.version + " - " + v.sound);
}
e.printStackTrace();
ex.printStackTrace();
}
}

View File

@ -1,85 +1,88 @@
package com.songoda.core.compatibility;
import org.bukkit.entity.EntityType;
import java.util.HashMap;
import java.util.Map;
public class EntityNamespace {
static final HashMap<String, EntityType> validTypes = new HashMap();
static final HashMap<String, String> legacyToModernTypes = new HashMap() {
{
put("xporb", "experience_orb");
put("xp_orb", "experience_orb");
put("leashknot", "leash_knot");
put("smallfireball", "small_fireball");
put("thrownenderpearl", "ender_pearl");
put("eyeofendersignal", "eye_of_ender");
put("eye_of_ender_signal", "eye_of_ender");
put("thrownexpbottle", "experience_bottle");
put("xp_bottle", "experience_bottle");
put("itemframe", "item_frame");
put("witherskull", "wither_skull");
put("primedtnt", "tnt");
put("fallingsand", "falling_block");
put("fireworksrocketentity", "firework_rocket");
put("fireworks_rocket", "firework_rocket");
put("spectralarrow", "spectral_arrow");
put("tippedarrow", "arrow");
put("shulkerbullet", "shulker_bullet");
put("dragonfireball", "dragon_fireball");
put("armorstand", "armor_stand");
put("minecartcommandblock", "command_block_minecart");
put("commandblock_minecart", "command_block_minecart");
put("minecartrideable", "minecart");
put("minecartchest", "chest_minecart");
put("minecartfurnace", "furnace_minecart");
put("minecarttnt", "tnt_minecart");
put("minecarthopper", "hopper_minecart");
put("minecartmobspawner", "spawner_minecart");
put("pigzombie", "zombie_pigman");
put("cavespider", "cave_spider");
put("lavaslime", "magma_cube");
put("enderdragon", "ender_dragon");
put("witherboss", "wither");
put("mushroomcow", "mooshroom");
put("snowman", "snow_golem");
put("ozelot", "ocelot");
put("villagergolem", "iron_golem");
put("villager_golem", "iron_golem");
put("entityhorse", "horse");
put("endercrystal", "end_crystal");
put("ender_crystal", "end_crystal");
}
};
static {
for (EntityType t : EntityType.values()) {
if (t.getName() != null) {
validTypes.put(t.getName().toLowerCase(), t);
}
}
}
public static EntityType minecraftToBukkit(String entity) {
if (entity == null) {
return null;
}
// first try to translate natively
EntityType type = EntityType.fromName(entity);
if (type == null) {
// try legacy values
type = EntityType.fromName(legacyToModernTypes.get(entity));
// try converting modern to legacy
if (type == null && legacyToModernTypes.containsValue(entity)) {
for (Map.Entry<String, String> e : legacyToModernTypes.entrySet()) {
if (e.getValue().equals(entity) && (type = EntityType.fromName(legacyToModernTypes.get(e.getKey()))) != null) {
return type;
}
}
}
}
return type;
}
}
package com.songoda.core.compatibility;
import org.bukkit.entity.EntityType;
import java.util.HashMap;
import java.util.Map;
public class EntityNamespace {
static final HashMap<String, EntityType> validTypes = new HashMap<>();
static final HashMap<String, String> legacyToModernTypes = new HashMap<String, String>() {
{
put("xporb", "experience_orb");
put("xp_orb", "experience_orb");
put("leashknot", "leash_knot");
put("smallfireball", "small_fireball");
put("thrownenderpearl", "ender_pearl");
put("eyeofendersignal", "eye_of_ender");
put("eye_of_ender_signal", "eye_of_ender");
put("thrownexpbottle", "experience_bottle");
put("xp_bottle", "experience_bottle");
put("itemframe", "item_frame");
put("witherskull", "wither_skull");
put("primedtnt", "tnt");
put("fallingsand", "falling_block");
put("fireworksrocketentity", "firework_rocket");
put("fireworks_rocket", "firework_rocket");
put("spectralarrow", "spectral_arrow");
put("tippedarrow", "arrow");
put("shulkerbullet", "shulker_bullet");
put("dragonfireball", "dragon_fireball");
put("armorstand", "armor_stand");
put("minecartcommandblock", "command_block_minecart");
put("commandblock_minecart", "command_block_minecart");
put("minecartrideable", "minecart");
put("minecartchest", "chest_minecart");
put("minecartfurnace", "furnace_minecart");
put("minecarttnt", "tnt_minecart");
put("minecarthopper", "hopper_minecart");
put("minecartmobspawner", "spawner_minecart");
put("pigzombie", "zombie_pigman");
put("cavespider", "cave_spider");
put("lavaslime", "magma_cube");
put("enderdragon", "ender_dragon");
put("witherboss", "wither");
put("mushroomcow", "mooshroom");
put("snowman", "snow_golem");
put("ozelot", "ocelot");
put("villagergolem", "iron_golem");
put("villager_golem", "iron_golem");
put("entityhorse", "horse");
put("endercrystal", "end_crystal");
put("ender_crystal", "end_crystal");
}
};
static {
for (EntityType t : EntityType.values()) {
if (t.getName() != null) {
validTypes.put(t.getName().toLowerCase(), t);
}
}
}
public static EntityType minecraftToBukkit(String entity) {
if (entity == null) {
return null;
}
// first try to translate natively
EntityType type = EntityType.fromName(entity);
if (type == null) {
// try legacy values
type = EntityType.fromName(legacyToModernTypes.get(entity));
// try converting modern to legacy
if (type == null && legacyToModernTypes.containsValue(entity)) {
for (Map.Entry<String, String> e : legacyToModernTypes.entrySet()) {
if (e.getValue().equals(entity) && (type = EntityType.fromName(legacyToModernTypes.get(e.getKey()))) != null) {
return type;
}
}
}
}
return type;
}
}

View File

@ -8,12 +8,8 @@ import java.util.Map;
/**
* Starting in Minecraft 1.13, separate materials for blocks and items were
* phased out. This provides a translation for those values.
*
* @author jascotty2
* @since 2019-09-12
*/
public enum LegacyMaterialBlockType {
OAK_LEAVES("LEAVES", (byte) 8, true),
SPRUCE_LEAVES("LEAVES", (byte) 9, true),
BIRCH_LEAVES("LEAVES", (byte) 10, true),
@ -56,8 +52,8 @@ public enum LegacyMaterialBlockType {
final String alternateBlockMaterialName;
final Material blockMaterial, alternateBlockMaterial;
final boolean requiresData; // some blocks require data to render properly (double blocks)
final static Map<String, LegacyMaterialBlockType> lookupTable = new HashMap();
final static Map<String, LegacyMaterialBlockType> reverseLookupTable = new HashMap();
final static Map<String, LegacyMaterialBlockType> lookupTable = new HashMap<>();
final static Map<String, LegacyMaterialBlockType> reverseLookupTable = new HashMap<>();
static {
for (LegacyMaterialBlockType t : values()) {
@ -69,23 +65,23 @@ public enum LegacyMaterialBlockType {
}
}
private LegacyMaterialBlockType(String blockMaterial) {
LegacyMaterialBlockType(String blockMaterial) {
this(blockMaterial, (byte) -1, null, false);
}
private LegacyMaterialBlockType(String blockMaterial, boolean requiresData) {
LegacyMaterialBlockType(String blockMaterial, boolean requiresData) {
this(blockMaterial, (byte) -1, null, requiresData);
}
private LegacyMaterialBlockType(String blockMaterial, byte data, boolean requiresData) {
LegacyMaterialBlockType(String blockMaterial, byte data, boolean requiresData) {
this(blockMaterial, data, null, requiresData);
}
private LegacyMaterialBlockType(String blockMaterial, String alternateMaterial) {
LegacyMaterialBlockType(String blockMaterial, String alternateMaterial) {
this(blockMaterial, (byte) -1, alternateMaterial, false);
}
private LegacyMaterialBlockType(String blockMaterial, byte data, String alternateMaterial, boolean requiresData) {
LegacyMaterialBlockType(String blockMaterial, byte data, String alternateMaterial, boolean requiresData) {
this.blockMaterialName = blockMaterial;
this.alternateBlockMaterialName = alternateMaterial;
this.requiresData = requiresData;

View File

@ -1,255 +1,253 @@
package com.songoda.core.compatibility;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Particle effects for servers 1.8 and below
*
* @author jascotty2
* @since 2019-08-23
*/
public class LegacyParticleEffects {
public static enum Type {
EXPLOSION_NORMAL("explode"),
EXPLOSION_LARGE("largeexplode"),
EXPLOSION_HUGE("hugeexplosion"),
FIREWORKS_SPARK("fireworksSpark"),
WATER_BUBBLE("bubble"),
WATER_SPLASH("splash"),
WATER_WAKE("wake", ServerVersion.V1_8),
SUSPENDED("suspended"),
SUSPENDED_DEPTH("depthsuspend"),
CRIT("crit"),
CRIT_MAGIC("magicCrit"),
SMOKE_NORMAL("smoke"),
SMOKE_LARGE("largesmoke"),
SPELL("spell"),
SPELL_INSTANT("instantSpell"),
SPELL_MOB("mobSpell"),
SPELL_MOB_AMBIENT("mobSpellAmbient"),
SPELL_WITCH("witchMagic"),
DRIP_WATER("dripWater"),
DRIP_LAVA("dripLava"),
VILLAGER_ANGRY("angryVillager"),
VILLAGER_HAPPY("happyVillager"),
TOWN_AURA("townaura"),
NOTE("note"),
PORTAL("portal"),
ENCHANTMENT_TABLE("enchantmenttable"),
FLAME("flame"),
LAVA("lava"),
FOOTSTEP("footstep"),
CLOUD("cloud"),
REDSTONE("reddust"),
SNOWBALL("snowballpoof"),
SNOW_SHOVEL("snowshovel"),
SLIME("slime"),
HEART("heart"),
BARRIER("barrier", ServerVersion.V1_8),
/**
* Used when a block is broken
*/
ITEM_CRACK("iconcrack_"),
BLOCK_CRACK("blockcrack_", ServerVersion.V1_8),
BLOCK_DUST("blockdust_", ServerVersion.V1_8),
WATER_DROP("droplet", ServerVersion.V1_8),
ITEM_TAKE("take", ServerVersion.V1_8),
MOB_APPEARANCE("mobappearance", ServerVersion.V1_8),
TOOL_BREAK("tilecrack_", ServerVersion.UNKNOWN, ServerVersion.V1_7);
public final String name;
public final ServerVersion minVersion;
public final ServerVersion maxVersion;
private Type(String name) {
this.name = name;
this.minVersion = ServerVersion.UNKNOWN;
this.maxVersion = null;
}
private Type(String name, ServerVersion minVersion) {
this.name = name;
this.minVersion = minVersion;
this.maxVersion = null;
}
private Type(String name, ServerVersion minVersion, ServerVersion maxVersion) {
this.name = name;
this.minVersion = minVersion;
this.maxVersion = maxVersion;
}
public static Type getById(String id) {
for (Type t : Type.values()) {
if (t.name.equalsIgnoreCase(id) || t.name().equalsIgnoreCase(id)) {
return t;
}
}
return null;
}
}
private static final String version = getNMSVersion();
private static boolean enabled = true;
private static Class mc_packetPlayOutWorldParticlesClazz;
private static Class cb_craftPlayerClazz;
private static Method cb_craftPlayer_getHandle;
private static Class mc_entityPlayerClazz;
private static Class mc_playerConnectionClazz;
private static Field mc_entityPlayer_playerConnection;
private static Class mc_PacketInterface;
private static Method mc_playerConnection_sendPacket;
private static Class mc_EnumParticle;
private static Method mc_EnumParticle_valueOf;
static {
try {
// lower versions use "Packet63WorldParticles"
if (!version.startsWith("v1_7") && !version.startsWith("v1_8")) {
mc_packetPlayOutWorldParticlesClazz = Class.forName("net.minecraft.server." + version + ".Packet63WorldParticles");
} else {
mc_packetPlayOutWorldParticlesClazz = Class.forName("net.minecraft.server." + version + ".PacketPlayOutWorldParticles");
}
cb_craftPlayerClazz = Class.forName("org.bukkit.craftbukkit." + version + ".entity.CraftPlayer");
cb_craftPlayer_getHandle = cb_craftPlayerClazz.getDeclaredMethod("getHandle");
mc_entityPlayerClazz = Class.forName("net.minecraft.server." + version + ".EntityPlayer");
mc_entityPlayer_playerConnection = mc_entityPlayerClazz.getDeclaredField("playerConnection");
mc_playerConnectionClazz = Class.forName("net.minecraft.server." + version + ".PlayerConnection");
mc_PacketInterface = Class.forName("net.minecraft.server." + version + ".Packet");
mc_playerConnection_sendPacket = mc_playerConnectionClazz.getDeclaredMethod("sendPacket", mc_PacketInterface);
if (version.startsWith("v1_8")) {
// Aren't worrying about anything after 1.8 in this class here
mc_EnumParticle = Class.forName("net.minecraft.server." + version + ".EnumParticle");
mc_EnumParticle_valueOf = mc_EnumParticle.getDeclaredMethod("valueOf", String.class);
}
} catch (Throwable ex) {
Logger.getAnonymousLogger().log(Level.WARNING, "Problem preparing particle packets (disabling further packets)", ex);
enabled = false;
}
}
private static String getNMSVersion() {
String ver = Bukkit.getServer().getClass().getPackage().getName();
return ver.substring(ver.lastIndexOf('.') + 1);
}
public static void createParticle(Location l, Type e) {
createParticle(l, e, 0F, 0F, 0F, 1, 0, null);
}
public static void createParticle(Location l, Type e, List<Player> localOnly) {
createParticle(l, e, 0F, 0F, 0F, 1, 0, localOnly);
}
public static void createParticle(Location l, Type e, float effectSpeed, int amountOfParticles) {
createParticle(l, e, 0F, 0F, 0F, effectSpeed, amountOfParticles, null);
}
/**
* @param l exact location to spawn the particle
* @param e particle effect type
* @param xx for notes, this is a value 0-1 for the color ([0-24]/24), for
* redstone this is the red value 0-1 ([0-255]/255).
* Otherwise this is the distance for particles to fly on the x-axis.
* @param yy for redstone this is the green value 0-1 ([0-255]/255)
* Otherwise this is the distance for particles to fly on the y-axis.
* @param zz for redstone this is the blue value 0-1 ([0-255]/255)
* Otherwise this is the distance for particles to fly on the z-axis.
* @param effectSpeed particle effect speed
* @param amountOfParticles extra particles to spawn (client-side)
* @param localOnly list of players to send the packets to, or null for all players
*/
public static void createParticle(Location l, Type e, float xx, float yy, float zz, float effectSpeed, int amountOfParticles, List<Player> localOnly) {
if (!enabled || e == null || effectSpeed < 0 || amountOfParticles < 0
|| !ServerVersion.isServerVersionAtLeast(e.minVersion)
|| (e.maxVersion != null && !ServerVersion.isServerVersionBelow(e.maxVersion))) {
return;
}
final int rangeSquared = 256; // apparently there is no way to override this (unless to make smaller, of course)
// collect a list of players to send this packet to
List<Player> sendTo = new ArrayList();
if (localOnly == null) {
for (Player p : l.getWorld().getPlayers()) {
if (p.getLocation().distanceSquared(l) <= rangeSquared) {
sendTo.add(p);
}
}
} else {
final World w = l.getWorld();
for (Player p : localOnly) {
if (p.getWorld() == w && p.getLocation().distanceSquared(l) <= rangeSquared) {
sendTo.add(p);
}
}
}
if (sendTo.isEmpty()) {
return;
}
try {
// Make an instance of the packet!
Object sPacket = mc_packetPlayOutWorldParticlesClazz.newInstance();
for (Field field : sPacket.getClass().getDeclaredFields()) {
// Set those fields we need to be accessible!
field.setAccessible(true);
final String fieldName = field.getName();
// Set them to what we want!
if (fieldName.equals("a")) {
// we're just going to assume it's either 1.7 or 1.8
if (version.startsWith("v1_8")) {
// 1.8 uses an Enum
field.set(sPacket, mc_EnumParticle_valueOf.invoke(null, e.name()));
} else {
field.set(sPacket, e.name);
}
} else if (fieldName.equals("b")) {
field.setFloat(sPacket, (float) l.getX()); // x
} else if (fieldName.equals("c")) {
field.setFloat(sPacket, (float) l.getY()); // y
} else if (fieldName.equals("d")) {
field.setFloat(sPacket, (float) l.getZ()); // z
} else if (fieldName.equals("e")) {
field.setFloat(sPacket, xx); // xOffset
} else if (fieldName.equals("f")) {
field.setFloat(sPacket, yy); // yOffset
} else if (fieldName.equals("g")) {
field.setFloat(sPacket, zz); // zOffset
} else if (fieldName.equals("h")) {
field.setFloat(sPacket, effectSpeed);
} else if (fieldName.equals("i")) {
field.setInt(sPacket, amountOfParticles);
}
/*
1.8 also includes other data:
j = boolean, set if view distance is increased from 256 to 65536
k = int[] for packet data (like block type for ITEM_CRACK)
*/
}
// send it on its way!
for (Player p : sendTo) {
sendPacket(sPacket, p);
}
} catch (Throwable ex) {
Logger.getAnonymousLogger().log(Level.WARNING, "Problem preparing a particle packet (disabling further packets)", ex);
enabled = false;
}
}
private static void sendPacket(Object packet, Player to) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Object cbPlayer = cb_craftPlayer_getHandle.invoke(to);
Object mcConnection = mc_entityPlayer_playerConnection.get(cbPlayer);
mc_playerConnection_sendPacket.invoke(mcConnection, packet);
}
}
package com.songoda.core.compatibility;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Particle effects for servers 1.8 and below
*/
public class LegacyParticleEffects {
public enum Type {
EXPLOSION_NORMAL("explode"),
EXPLOSION_LARGE("largeexplode"),
EXPLOSION_HUGE("hugeexplosion"),
FIREWORKS_SPARK("fireworksSpark"),
WATER_BUBBLE("bubble"),
WATER_SPLASH("splash"),
WATER_WAKE("wake", ServerVersion.V1_8),
SUSPENDED("suspended"),
SUSPENDED_DEPTH("depthsuspend"),
CRIT("crit"),
CRIT_MAGIC("magicCrit"),
SMOKE_NORMAL("smoke"),
SMOKE_LARGE("largesmoke"),
SPELL("spell"),
SPELL_INSTANT("instantSpell"),
SPELL_MOB("mobSpell"),
SPELL_MOB_AMBIENT("mobSpellAmbient"),
SPELL_WITCH("witchMagic"),
DRIP_WATER("dripWater"),
DRIP_LAVA("dripLava"),
VILLAGER_ANGRY("angryVillager"),
VILLAGER_HAPPY("happyVillager"),
TOWN_AURA("townaura"),
NOTE("note"),
PORTAL("portal"),
ENCHANTMENT_TABLE("enchantmenttable"),
FLAME("flame"),
LAVA("lava"),
FOOTSTEP("footstep"),
CLOUD("cloud"),
REDSTONE("reddust"),
SNOWBALL("snowballpoof"),
SNOW_SHOVEL("snowshovel"),
SLIME("slime"),
HEART("heart"),
BARRIER("barrier", ServerVersion.V1_8),
/**
* Used when a block is broken
*/
ITEM_CRACK("iconcrack_"),
BLOCK_CRACK("blockcrack_", ServerVersion.V1_8),
BLOCK_DUST("blockdust_", ServerVersion.V1_8),
WATER_DROP("droplet", ServerVersion.V1_8),
ITEM_TAKE("take", ServerVersion.V1_8),
MOB_APPEARANCE("mobappearance", ServerVersion.V1_8),
TOOL_BREAK("tilecrack_", ServerVersion.UNKNOWN, ServerVersion.V1_7);
public final String name;
public final ServerVersion minVersion;
public final ServerVersion maxVersion;
Type(String name) {
this.name = name;
this.minVersion = ServerVersion.UNKNOWN;
this.maxVersion = null;
}
Type(String name, ServerVersion minVersion) {
this.name = name;
this.minVersion = minVersion;
this.maxVersion = null;
}
Type(String name, ServerVersion minVersion, ServerVersion maxVersion) {
this.name = name;
this.minVersion = minVersion;
this.maxVersion = maxVersion;
}
public static Type getById(String id) {
for (Type t : Type.values()) {
if (t.name.equalsIgnoreCase(id) || t.name().equalsIgnoreCase(id)) {
return t;
}
}
return null;
}
}
private static final String version = getNMSVersion();
private static boolean enabled = true;
private static Class<?> mc_packetPlayOutWorldParticlesClazz;
private static Class<?> cb_craftPlayerClazz;
private static Method cb_craftPlayer_getHandle;
private static Class<?> mc_entityPlayerClazz;
private static Class<?> mc_playerConnectionClazz;
private static Field mc_entityPlayer_playerConnection;
private static Class<?> mc_PacketInterface;
private static Method mc_playerConnection_sendPacket;
private static Class<?> mc_EnumParticle;
private static Method mc_EnumParticle_valueOf;
static {
try {
// lower versions use "Packet63WorldParticles"
if (!version.startsWith("v1_7") && !version.startsWith("v1_8")) {
mc_packetPlayOutWorldParticlesClazz = Class.forName("net.minecraft.server." + version + ".Packet63WorldParticles");
} else {
mc_packetPlayOutWorldParticlesClazz = Class.forName("net.minecraft.server." + version + ".PacketPlayOutWorldParticles");
}
cb_craftPlayerClazz = Class.forName("org.bukkit.craftbukkit." + version + ".entity.CraftPlayer");
cb_craftPlayer_getHandle = cb_craftPlayerClazz.getDeclaredMethod("getHandle");
mc_entityPlayerClazz = Class.forName("net.minecraft.server." + version + ".EntityPlayer");
mc_entityPlayer_playerConnection = mc_entityPlayerClazz.getDeclaredField("playerConnection");
mc_playerConnectionClazz = Class.forName("net.minecraft.server." + version + ".PlayerConnection");
mc_PacketInterface = Class.forName("net.minecraft.server." + version + ".Packet");
mc_playerConnection_sendPacket = mc_playerConnectionClazz.getDeclaredMethod("sendPacket", mc_PacketInterface);
if (version.startsWith("v1_8")) {
// Aren't worrying about anything after 1.8 in this class here
mc_EnumParticle = Class.forName("net.minecraft.server." + version + ".EnumParticle");
mc_EnumParticle_valueOf = mc_EnumParticle.getDeclaredMethod("valueOf", String.class);
}
} catch (Throwable ex) {
Logger.getAnonymousLogger().log(Level.WARNING, "Problem preparing particle packets (disabling further packets)", ex);
enabled = false;
}
}
private static String getNMSVersion() {
String ver = Bukkit.getServer().getClass().getPackage().getName();
return ver.substring(ver.lastIndexOf('.') + 1);
}
public static void createParticle(Location l, Type e) {
createParticle(l, e, 0F, 0F, 0F, 1, 0, null);
}
public static void createParticle(Location l, Type e, List<Player> localOnly) {
createParticle(l, e, 0F, 0F, 0F, 1, 0, localOnly);
}
public static void createParticle(Location l, Type e, float effectSpeed, int amountOfParticles) {
createParticle(l, e, 0F, 0F, 0F, effectSpeed, amountOfParticles, null);
}
/**
* @param l exact location to spawn the particle
* @param e particle effect type
* @param xx for notes, this is a value 0-1 for the color ([0-24]/24), for
* redstone this is the red value 0-1 ([0-255]/255).
* Otherwise, this is the distance for particles to fly on the x-axis.
* @param yy for redstone this is the green value 0-1 ([0-255]/255)
* Otherwise this is the distance for particles to fly on the y-axis.
* @param zz for redstone this is the blue value 0-1 ([0-255]/255)
* Otherwise this is the distance for particles to fly on the z-axis.
* @param effectSpeed particle effect speed
* @param amountOfParticles extra particles to spawn (client-side)
* @param localOnly list of players to send the packets to, or null for all players
*/
public static void createParticle(Location l, Type e, float xx, float yy, float zz, float effectSpeed, int amountOfParticles, List<Player> localOnly) {
if (!enabled || e == null || effectSpeed < 0 || amountOfParticles < 0
|| !ServerVersion.isServerVersionAtLeast(e.minVersion)
|| (e.maxVersion != null && !ServerVersion.isServerVersionBelow(e.maxVersion))) {
return;
}
final int rangeSquared = 256; // apparently there is no way to override this (unless to make smaller, of course)
// collect a list of players to send this packet to
List<Player> sendTo = new ArrayList();
if (localOnly == null) {
for (Player p : l.getWorld().getPlayers()) {
if (p.getLocation().distanceSquared(l) <= rangeSquared) {
sendTo.add(p);
}
}
} else {
final World w = l.getWorld();
for (Player p : localOnly) {
if (p.getWorld() == w && p.getLocation().distanceSquared(l) <= rangeSquared) {
sendTo.add(p);
}
}
}
if (sendTo.isEmpty()) {
return;
}
try {
// Make an instance of the packet!
Object sPacket = mc_packetPlayOutWorldParticlesClazz.newInstance();
for (Field field : sPacket.getClass().getDeclaredFields()) {
// Set those fields we need to be accessible!
field.setAccessible(true);
final String fieldName = field.getName();
// Set them to what we want!
if (fieldName.equals("a")) {
// we're just going to assume it's either 1.7 or 1.8
if (version.startsWith("v1_8")) {
// 1.8 uses an Enum
field.set(sPacket, mc_EnumParticle_valueOf.invoke(null, e.name()));
} else {
field.set(sPacket, e.name);
}
} else if (fieldName.equals("b")) {
field.setFloat(sPacket, (float) l.getX()); // x
} else if (fieldName.equals("c")) {
field.setFloat(sPacket, (float) l.getY()); // y
} else if (fieldName.equals("d")) {
field.setFloat(sPacket, (float) l.getZ()); // z
} else if (fieldName.equals("e")) {
field.setFloat(sPacket, xx); // xOffset
} else if (fieldName.equals("f")) {
field.setFloat(sPacket, yy); // yOffset
} else if (fieldName.equals("g")) {
field.setFloat(sPacket, zz); // zOffset
} else if (fieldName.equals("h")) {
field.setFloat(sPacket, effectSpeed);
} else if (fieldName.equals("i")) {
field.setInt(sPacket, amountOfParticles);
}
/*
1.8 also includes other data:
j = boolean, set if view distance is increased from 256 to 65536
k = int[] for packet data (like block type for ITEM_CRACK)
*/
}
// send it on its way!
for (Player p : sendTo) {
sendPacket(sPacket, p);
}
} catch (Throwable ex) {
Logger.getAnonymousLogger().log(Level.WARNING, "Problem preparing a particle packet (disabling further packets)", ex);
enabled = false;
}
}
private static void sendPacket(Object packet, Player to) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Object cbPlayer = cb_craftPlayer_getHandle.invoke(to);
Object mcConnection = mc_entityPlayer_playerConnection.get(cbPlayer);
mc_playerConnection_sendPacket.invoke(mcConnection, packet);
}
}

View File

@ -1,50 +1,49 @@
package com.songoda.core.compatibility;
import org.bukkit.potion.PotionEffectType;
import java.util.HashMap;
import java.util.Random;
public class LegacyPotionEffects {
private LegacyPotionEffects() {
}
protected final static Random rand = new Random();
private final static HashMap<Integer, String> potionEffectNames = new HashMap() {
{
put(PotionEffectType.SPEED.getId(), "Speed");
put(PotionEffectType.SLOW.getId(), "Slowness");
put(PotionEffectType.FAST_DIGGING.getId(), "Haste");
put(PotionEffectType.SLOW_DIGGING.getId(), "Mining Fatigue");
put(PotionEffectType.INCREASE_DAMAGE.getId(), "Strength");
put(PotionEffectType.WEAKNESS.getId(), "Weakness");
put(PotionEffectType.HEAL.getId(), "Instant Health");
put(PotionEffectType.HARM.getId(), "Instant Damage");
put(PotionEffectType.JUMP.getId(), "Jump Boost");
put(PotionEffectType.CONFUSION.getId(), "Nausea");
put(PotionEffectType.REGENERATION.getId(), "Regeneration");
put(PotionEffectType.DAMAGE_RESISTANCE.getId(), "Resistance");
put(PotionEffectType.FIRE_RESISTANCE.getId(), "Fire Resistance");
put(PotionEffectType.WATER_BREATHING.getId(), "Water Breathing");
put(PotionEffectType.INVISIBILITY.getId(), "Invisibility");
put(PotionEffectType.BLINDNESS.getId(), "Blindness");
put(PotionEffectType.NIGHT_VISION.getId(), "Night Vision");
put(PotionEffectType.HUNGER.getId(), "Hunger");
put(PotionEffectType.POISON.getId(), "Poison");
put(PotionEffectType.WITHER.getId(), "Wither");
put(PotionEffectType.HEALTH_BOOST.getId(), "Health Boost");
put(PotionEffectType.ABSORPTION.getId(), "Absorption");
put(PotionEffectType.SATURATION.getId(), "Saturation");
}
};
public static String getEffectName(PotionEffectType e) {
if (e == null) {
return "null";
}
final String n = potionEffectNames.get(e.getId());
return n == null ? e.getName() : n;
}
}
package com.songoda.core.compatibility;
import org.bukkit.potion.PotionEffectType;
import java.util.HashMap;
import java.util.Random;
public class LegacyPotionEffects {
private LegacyPotionEffects() {
}
protected final static Random rand = new Random();
private final static HashMap<Integer, String> potionEffectNames = new HashMap<Integer, String>() {
{
put(PotionEffectType.SPEED.getId(), "Speed");
put(PotionEffectType.SLOW.getId(), "Slowness");
put(PotionEffectType.FAST_DIGGING.getId(), "Haste");
put(PotionEffectType.SLOW_DIGGING.getId(), "Mining Fatigue");
put(PotionEffectType.INCREASE_DAMAGE.getId(), "Strength");
put(PotionEffectType.WEAKNESS.getId(), "Weakness");
put(PotionEffectType.HEAL.getId(), "Instant Health");
put(PotionEffectType.HARM.getId(), "Instant Damage");
put(PotionEffectType.JUMP.getId(), "Jump Boost");
put(PotionEffectType.CONFUSION.getId(), "Nausea");
put(PotionEffectType.REGENERATION.getId(), "Regeneration");
put(PotionEffectType.DAMAGE_RESISTANCE.getId(), "Resistance");
put(PotionEffectType.FIRE_RESISTANCE.getId(), "Fire Resistance");
put(PotionEffectType.WATER_BREATHING.getId(), "Water Breathing");
put(PotionEffectType.INVISIBILITY.getId(), "Invisibility");
put(PotionEffectType.BLINDNESS.getId(), "Blindness");
put(PotionEffectType.NIGHT_VISION.getId(), "Night Vision");
put(PotionEffectType.HUNGER.getId(), "Hunger");
put(PotionEffectType.POISON.getId(), "Poison");
put(PotionEffectType.WITHER.getId(), "Wither");
put(PotionEffectType.HEALTH_BOOST.getId(), "Health Boost");
put(PotionEffectType.ABSORPTION.getId(), "Absorption");
put(PotionEffectType.SATURATION.getId(), "Saturation");
}
};
public static String getEffectName(PotionEffectType e) {
if (e == null) {
return "null";
}
final String n = potionEffectNames.get(e.getId());
return n == null ? e.getName() : n;
}
}

View File

@ -4,38 +4,43 @@ import org.apache.commons.lang.ArrayUtils;
import org.bukkit.Bukkit;
public enum ServerProject {
UNKNOWN, CRAFTBUKKIT, SPIGOT, PAPER, TACO, GLOWSTONE;
private final static ServerProject serverProject = checkProject();
private static ServerProject checkProject() {
String serverPath = Bukkit.getServer().getClass().getName();
if (serverPath.contains("glowstone")) {
return GLOWSTONE;
}
// taco is pretty easy to check. it uses paper stuff, though, so should be checked first
try {
Class.forName("net.techcable.tacospigot.TacoSpigotConfig");
return TACO;
} catch (ClassNotFoundException ex) {
} catch (ClassNotFoundException ignore) {
}
// paper used to be called "paperclip"
try {
Class.forName("com.destroystokyo.paperclip.Paperclip");
return PAPER;
} catch (ClassNotFoundException ex) {
} catch (ClassNotFoundException ignore) {
}
try {
Class.forName("com.destroystokyo.paper.PaperConfig");
return PAPER;
} catch (ClassNotFoundException ex) {
} catch (ClassNotFoundException ignore) {
}
// spigot is the fork that pretty much all builds are based on anymore
try {
Class.forName("org.spigotmc.SpigotConfig");
return SPIGOT;
} catch (ClassNotFoundException ex) {
} catch (ClassNotFoundException ignore) {
}
return serverPath.contains("craftbukkit") ? CRAFTBUKKIT : UNKNOWN;
}

View File

@ -87,13 +87,14 @@ public class SongodaCore {
for (Class<?> clazz : Bukkit.getServicesManager().getKnownServices()) {
if (clazz.getSimpleName().equals("SongodaCore")) {
try {
// test to see if we're up to date
// test to see if we're up-to-date
int otherVersion;
try {
otherVersion = (int) clazz.getMethod("getCoreVersion").invoke(null);
} catch (Exception ignore) {
otherVersion = -1;
}
if (otherVersion >= getCoreVersion()) {
// use the active service
// assuming that the other is greater than R6 if we get here ;)
@ -104,49 +105,57 @@ public class SongodaCore {
INSTANCE.shadingListener = new ShadedEventListener();
Bukkit.getPluginManager().registerEvents(INSTANCE.shadingListener, plugin);
}
return;
} else {
// we are newer than the registered service: steal all of its registrations
// grab the old core's registrations
List otherPlugins = (List) clazz.getMethod("getPlugins").invoke(null);
// destroy the old core
Object oldCore = clazz.getMethod("getInstance").invoke(null);
Method destruct = clazz.getDeclaredMethod("destroy");
destruct.setAccessible(true);
destruct.invoke(oldCore);
// register ourselves as the SongodaCore service!
INSTANCE = new SongodaCore(plugin);
INSTANCE.init();
INSTANCE.register(plugin, pluginID, icon, coreVersion);
Bukkit.getServicesManager().register(SongodaCore.class, INSTANCE, plugin, ServicePriority.Normal);
// we need (JavaPlugin plugin, int pluginID, String icon) for our object
if (!otherPlugins.isEmpty()) {
Object testSubject = otherPlugins.get(0);
Class otherPluginInfo = testSubject.getClass();
Method otherPluginInfo_getJavaPlugin = otherPluginInfo.getMethod("getJavaPlugin");
Method otherPluginInfo_getSongodaId = otherPluginInfo.getMethod("getSongodaId");
Method otherPluginInfo_getCoreIcon = otherPluginInfo.getMethod("getCoreIcon");
Method otherPluginInfo_getCoreLibraryVersion = otherVersion >= 6 ? otherPluginInfo.getMethod("getCoreLibraryVersion") : null;
for (Object other : otherPlugins) {
INSTANCE.register(
(JavaPlugin) otherPluginInfo_getJavaPlugin.invoke(other),
(int) otherPluginInfo_getSongodaId.invoke(other),
(String) otherPluginInfo_getCoreIcon.invoke(other),
otherPluginInfo_getCoreLibraryVersion != null ? (String) otherPluginInfo_getCoreLibraryVersion.invoke(other) : "?");
}
}
// we are newer than the registered service: steal all of its registrations
// grab the old core's registrations
List<?> otherPlugins = (List<?>) clazz.getMethod("getPlugins").invoke(null);
// destroy the old core
Object oldCore = clazz.getMethod("getInstance").invoke(null);
Method destruct = clazz.getDeclaredMethod("destroy");
destruct.setAccessible(true);
destruct.invoke(oldCore);
// register ourselves as the SongodaCore service!
INSTANCE = new SongodaCore(plugin);
INSTANCE.init();
INSTANCE.register(plugin, pluginID, icon, coreVersion);
Bukkit.getServicesManager().register(SongodaCore.class, INSTANCE, plugin, ServicePriority.Normal);
// we need (JavaPlugin plugin, int pluginID, String icon) for our object
if (!otherPlugins.isEmpty()) {
Object testSubject = otherPlugins.get(0);
Class otherPluginInfo = testSubject.getClass();
Method otherPluginInfo_getJavaPlugin = otherPluginInfo.getMethod("getJavaPlugin");
Method otherPluginInfo_getSongodaId = otherPluginInfo.getMethod("getSongodaId");
Method otherPluginInfo_getCoreIcon = otherPluginInfo.getMethod("getCoreIcon");
Method otherPluginInfo_getCoreLibraryVersion = otherVersion >= 6 ? otherPluginInfo.getMethod("getCoreLibraryVersion") : null;
for (Object other : otherPlugins) {
INSTANCE.register(
(JavaPlugin) otherPluginInfo_getJavaPlugin.invoke(other),
(int) otherPluginInfo_getSongodaId.invoke(other),
(String) otherPluginInfo_getCoreIcon.invoke(other),
otherPluginInfo_getCoreLibraryVersion != null ? (String) otherPluginInfo_getCoreLibraryVersion.invoke(other) : "?");
}
}
return;
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) {
plugin.getLogger().log(Level.WARNING, "Error registering core service", ignored);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) {
plugin.getLogger().log(Level.WARNING, "Error registering core service", ex);
}
}
}
// register ourselves as the SongodaCore service!
INSTANCE = new SongodaCore(plugin);
INSTANCE.init();
Bukkit.getServicesManager().register(SongodaCore.class, INSTANCE, plugin, ServicePriority.Normal);
}
INSTANCE.register(plugin, pluginID, icon, coreVersion);
}
@ -166,16 +175,17 @@ public class SongodaCore {
.addSubCommand(new SongodaCoreDiagCommand());
Bukkit.getPluginManager().registerEvents(loginListener, piggybackedPlugin);
Bukkit.getPluginManager().registerEvents(shadingListener, piggybackedPlugin);
// we aggressively want to own this command
tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(piggybackedPlugin, () -> {
CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager);
}, 10 * 60 * 1));
tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(piggybackedPlugin, () -> {
CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager);
}, 20 * 60 * 1));
tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(piggybackedPlugin, () -> {
CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager);
}, 20 * 60 * 2));
tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(piggybackedPlugin, () ->
CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager),
10 * 60));
tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(piggybackedPlugin, () ->
CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager),
20 * 60));
tasks.add(Bukkit.getScheduler().runTaskLaterAsynchronously(piggybackedPlugin, () ->
CommandManager.registerCommandDynamically(piggybackedPlugin, "songoda", commandManager, commandManager),
20 * 60 * 2));
}
/**
@ -183,22 +193,26 @@ public class SongodaCore {
*/
private void destroy() {
Bukkit.getServicesManager().unregister(SongodaCore.class, INSTANCE);
tasks.stream().filter(Objects::nonNull)
.forEach(task -> Bukkit.getScheduler().cancelTask(task.getTaskId()));
HandlerList.unregisterAll(loginListener);
if (!hasShading()) {
HandlerList.unregisterAll(shadingListener);
}
registeredPlugins.clear();
commandManager = null;
loginListener = null;
}
private ArrayList<BukkitTask> tasks = new ArrayList();
private ArrayList<BukkitTask> tasks = new ArrayList<>();
private void register(JavaPlugin plugin, int pluginID, String icon, String libraryVersion) {
logger.info(getPrefix() + "Hooked " + plugin.getName() + ".");
PluginInfo info = new PluginInfo(plugin, pluginID, icon, libraryVersion);
// don't forget to check for language pack updates ;)
info.addModule(new LocaleModule());
registeredPlugins.add(info);
@ -238,10 +252,10 @@ public class SongodaCore {
for (PluginInfoModule module : plugin.getModules()) {
module.run(plugin);
}
} catch (IOException e) {
final String er = e.getMessage();
} catch (IOException ex) {
final String er = ex.getMessage();
logger.log(Level.FINE, "Connection with Songoda servers failed: " + (er.contains("URL") ? er.substring(0, er.indexOf("URL") + 3) : er));
} catch (ParseException e) {
} catch (ParseException ex) {
logger.log(Level.FINE, "Failed to parse json for " + plugin.getJavaPlugin().getName() + " update check");
}
}
@ -283,13 +297,19 @@ public class SongodaCore {
}
private static class ShadedEventListener implements Listener {
boolean via = false;
boolean via;
boolean proto = false;
ShadedEventListener() {
if ((via = Bukkit.getPluginManager().isPluginEnabled("ViaVersion"))) {
via = Bukkit.getPluginManager().isPluginEnabled("ViaVersion");
if (via) {
Bukkit.getOnlinePlayers().forEach(p -> ClientVersion.onLoginVia(p, getHijackedPlugin()));
} else if ((proto = Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport"))) {
return;
}
proto = Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport");
if (proto) {
Bukkit.getOnlinePlayers().forEach(p -> ClientVersion.onLoginProtocol(p, getHijackedPlugin()));
}
}
@ -298,7 +318,10 @@ public class SongodaCore {
void onLogin(PlayerLoginEvent event) {
if (via) {
ClientVersion.onLoginVia(event.getPlayer(), getHijackedPlugin());
} else if (proto) {
return;
}
if (proto) {
ClientVersion.onLoginProtocol(event.getPlayer(), getHijackedPlugin());
}
}
@ -322,18 +345,25 @@ public class SongodaCore {
}
private class EventListener implements Listener {
final HashMap<UUID, Long> lastCheck = new HashMap();
final HashMap<UUID, Long> lastCheck = new HashMap<>();
@EventHandler
void onLogin(PlayerLoginEvent event) {
final Player player = event.getPlayer();
// don't spam players with update checks
long now = System.currentTimeMillis();
Long last = lastCheck.get(player.getUniqueId());
if (last != null && now - 10000 < last) return;
if (last != null && now - 10000 < last) {
return;
}
lastCheck.put(player.getUniqueId(), now);
// is this player good to revieve update notices?
if (!event.getPlayer().isOp() && !player.hasPermission("songoda.updatecheck")) return;
// check for updates! ;)
for (PluginInfo plugin : getPlugins()) {
if (plugin.getNotification() != null && plugin.getJavaPlugin().isEnabled())
@ -346,16 +376,20 @@ public class SongodaCore {
void onDisable(PluginDisableEvent event) {
// don't track disabled plugins
PluginInfo pi = registeredPlugins.stream().filter(p -> event.getPlugin() == p.getJavaPlugin()).findFirst().orElse(null);
if (pi != null) {
registeredPlugins.remove(pi);
}
if (event.getPlugin() == piggybackedPlugin) {
// uh-oh! Abandon ship!!
Bukkit.getServicesManager().unregisterAll(piggybackedPlugin);
// can we move somewhere else?
if ((pi = registeredPlugins.stream().findFirst().orElse(null)) != null) {
// move ourselves to this plugin
piggybackedPlugin = pi.getJavaPlugin();
Bukkit.getServicesManager().register(SongodaCore.class, INSTANCE, piggybackedPlugin, ServicePriority.Normal);
Bukkit.getPluginManager().registerEvents(loginListener, piggybackedPlugin);
Bukkit.getPluginManager().registerEvents(shadingListener, piggybackedPlugin);

View File

@ -17,8 +17,6 @@ import java.util.logging.Level;
/**
* REMINDER: When converting plugins to use this, REMOVE METRICS <br>
* Must not have two instances of Metrics enabled!
*
* @author jascotty2
*/
public abstract class SongodaPlugin extends JavaPlugin {
protected Locale locale;
@ -78,6 +76,7 @@ public abstract class SongodaPlugin extends JavaPlugin {
+ " v" + getDescription().getVersion()
+ " c" + SongodaCore.getCoreLibraryVersion()
+ ": Disabling plugin!", t);
emergencyStop = true;
}
}
@ -86,38 +85,46 @@ public abstract class SongodaPlugin extends JavaPlugin {
public final void onEnable() {
if (emergencyStop) {
setEnabled(false);
return;
}
console.sendMessage(" "); // blank line to separate chatter
console.sendMessage(ChatColor.GREEN + "=============================");
console.sendMessage(String.format("%s%s %s by %sSongoda <3!", ChatColor.GRAY.toString(),
getDescription().getName(), getDescription().getVersion(), ChatColor.DARK_PURPLE.toString()));
console.sendMessage(String.format("%sAction: %s%s%s...", ChatColor.GRAY.toString(),
ChatColor.GREEN.toString(), "Enabling", ChatColor.GRAY.toString()));
console.sendMessage(String.format("%s%s %s by %sSongoda <3!", ChatColor.GRAY,
getDescription().getName(), getDescription().getVersion(), ChatColor.DARK_PURPLE));
console.sendMessage(String.format("%sAction: %s%s%s...", ChatColor.GRAY,
ChatColor.GREEN, "Enabling", ChatColor.GRAY));
try {
locale = Locale.loadDefaultLocale(this, "en_US");
// plugin setup
onPluginEnable();
// Load Data.
Bukkit.getScheduler().runTaskLater(this, this::onDataLoad, dataLoadDelay);
if (emergencyStop) {
console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
console.sendMessage(" ");
return;
}
// Start Metrics
Metrics.start(this);
} catch (Throwable t) {
} catch (Throwable th) {
Bukkit.getLogger().log(Level.SEVERE,
"Unexpected error while loading " + getDescription().getName()
+ " v" + getDescription().getVersion()
+ " c" + SongodaCore.getCoreLibraryVersion()
+ ": Disabling plugin!", t);
+ ": Disabling plugin!", th);
emergencyStop();
console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
console.sendMessage(" ");
return;
}
@ -127,6 +134,7 @@ public abstract class SongodaPlugin extends JavaPlugin {
protected void emergencyStop() {
emergencyStop = true;
Bukkit.getPluginManager().disablePlugin(this);
}
@ -135,13 +143,16 @@ public abstract class SongodaPlugin extends JavaPlugin {
if (emergencyStop) {
return;
}
console.sendMessage(" "); // blank line to speparate chatter
console.sendMessage(ChatColor.GREEN + "=============================");
console.sendMessage(String.format("%s%s %s by %sSongoda <3!", ChatColor.GRAY.toString(),
getDescription().getName(), getDescription().getVersion(), ChatColor.DARK_PURPLE.toString()));
console.sendMessage(String.format("%sAction: %s%s%s...", ChatColor.GRAY.toString(),
ChatColor.RED.toString(), "Disabling", ChatColor.GRAY.toString()));
console.sendMessage(String.format("%s%s %s by %sSongoda <3!", ChatColor.GRAY,
getDescription().getName(), getDescription().getVersion(), ChatColor.DARK_PURPLE));
console.sendMessage(String.format("%sAction: %s%s%s...", ChatColor.GRAY,
ChatColor.RED, "Disabling", ChatColor.GRAY));
onPluginDisable();
console.sendMessage(ChatColor.GREEN + "=============================");
console.sendMessage(" "); // blank line to speparate chatter
}
@ -166,15 +177,15 @@ public abstract class SongodaPlugin extends JavaPlugin {
public boolean setLocale(String localeName, boolean reload) {
if (locale != null && locale.getName().equals(localeName)) {
return !reload || locale.reloadMessages();
} else {
Locale l = Locale.loadLocale(this, localeName);
if (l != null) {
locale = l;
return true;
} else {
return false;
}
}
Locale l = Locale.loadLocale(this, localeName);
if (l != null) {
locale = l;
return true;
}
return false;
}
protected void shutdownDataManager(DataManagerAbstract dataManager) {

View File

@ -23,7 +23,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ChatMessage {
private static final Gson gson = new GsonBuilder().create();
private final List<JsonObject> textList = new ArrayList<>();
@ -36,7 +35,8 @@ public class ChatMessage {
}
public ChatMessage fromText(String text, boolean noHex) {
Pattern pattern = Pattern.compile("(.*?)(?!&([omnlk]))(?=(&([123456789abcdefr#])|$)|#([a-f]|[A-F]|[0-9]){6})",
Pattern pattern = Pattern.compile(
"(.*?)(?!&([omnlk]))(?=(&([123456789abcdefr#])|$)|#([a-f]|[A-F]|[0-9]){6})",
Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(text);
@ -44,12 +44,15 @@ public class ChatMessage {
ColorContainer color = null;
String match1 = matcher.group(1);
if (matcher.groupCount() == 0 || match1.length() == 0) continue;
if (matcher.groupCount() == 0 || match1.length() == 0) {
continue;
}
char colorChar = '-';
if (matcher.start() != 0)
if (matcher.start() != 0) {
colorChar = text.substring(matcher.start() - 1, matcher.start()).charAt(0);
}
if (colorChar != '-') {
if (colorChar == '#') {
@ -70,15 +73,17 @@ public class ChatMessage {
ColorCode code = ColorCode.getByChar(Character.toLowerCase(match2.charAt(0)));
if (code != null && code != ColorCode.RESET)
if (code != null && code != ColorCode.RESET) {
stackedCodes.add(code);
}
if (color != null)
if (color != null) {
match2 = match2.substring(1);
}
if (match2.length() == 0) continue;
addMessage(match2, color, stackedCodes);
if (match2.length() != 0) {
addMessage(match2, color, stackedCodes);
}
}
}
@ -91,31 +96,40 @@ public class ChatMessage {
public String toText(boolean noHex) {
StringBuilder text = new StringBuilder();
for (JsonObject object : textList) {
if (object.has("color")) {
String color = object.get("color").getAsString();
text.append("&");
if (color.length() == 7) {
text.append(new ColorContainer(color, noHex).getColor().getCode());
} else {
text.append(ColorCode.valueOf(color.toUpperCase()).getCode());
}
}
for (ColorCode code : ColorCode.values()) {
if (code.isColor()) continue;
String c = code.name().toLowerCase();
if (object.has(c) && object.get(c).getAsBoolean())
if (object.has(c) && object.get(c).getAsBoolean()) {
text.append("&").append(code.getCode());
}
}
text.append(object.get("text").getAsString());
}
return text.toString();
}
public ChatMessage addMessage(String s) {
JsonObject txt = new JsonObject();
txt.addProperty("text", s);
textList.add(txt);
return this;
}
@ -127,11 +141,14 @@ public class ChatMessage {
JsonObject txt = new JsonObject();
txt.addProperty("text", text);
if (color != null)
if (color != null) {
txt.addProperty("color", color.getHexCode() != null ? "#" + color.getHexCode() : color.getColorCode().name().toLowerCase());
}
for (ColorCode code : ColorCode.values()) {
if (!code.isColor())
if (!code.isColor()) {
txt.addProperty(code.name().toLowerCase(), colorCodes.contains(code));
}
}
textList.add(txt);
@ -141,14 +158,17 @@ public class ChatMessage {
public ChatMessage addRunCommand(String text, String hoverText, String cmd) {
JsonObject txt = new JsonObject();
txt.addProperty("text", text);
JsonObject hover = new JsonObject();
hover.addProperty("action", "show_text");
hover.addProperty("value", hoverText);
txt.add("hoverEvent", hover);
JsonObject click = new JsonObject();
click.addProperty("action", "run_command");
click.addProperty("value", cmd);
txt.add("clickEvent", click);
textList.add(txt);
return this;
}
@ -156,14 +176,17 @@ public class ChatMessage {
public ChatMessage addPromptCommand(String text, String hoverText, String cmd) {
JsonObject txt = new JsonObject();
txt.addProperty("text", text);
JsonObject hover = new JsonObject();
hover.addProperty("action", "show_text");
hover.addProperty("value", hoverText);
txt.add("hoverEvent", hover);
JsonObject click = new JsonObject();
click.addProperty("action", "suggest_command");
click.addProperty("value", cmd);
txt.add("clickEvent", click);
textList.add(txt);
return this;
}
@ -171,14 +194,17 @@ public class ChatMessage {
public ChatMessage addURL(String text, String hoverText, String url) {
JsonObject txt = new JsonObject();
txt.addProperty("text", text);
JsonObject hover = new JsonObject();
hover.addProperty("action", "show_text");
hover.addProperty("value", hoverText);
txt.add("hoverEvent", hover);
JsonObject click = new JsonObject();
click.addProperty("action", "open_url");
click.addProperty("value", url);
txt.add("clickEvent", hover);
textList.add(txt);
return this;
}
@ -200,10 +226,14 @@ public class ChatMessage {
Object packet;
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_16)) {
packet = mc_PacketPlayOutChat_new.newInstance(mc_IChatBaseComponent_ChatSerializer_a.invoke(null, gson.toJson(textList)), mc_chatMessageType_Chat.get(null), ((Player) sender).getUniqueId());
packet = mc_PacketPlayOutChat_new.newInstance(
mc_IChatBaseComponent_ChatSerializer_a.invoke(null, gson.toJson(textList)),
mc_chatMessageType_Chat.get(null),
((Player) sender).getUniqueId());
} else {
packet = mc_PacketPlayOutChat_new.newInstance(mc_IChatBaseComponent_ChatSerializer_a.invoke(null, gson.toJson(textList)));
}
Object cbPlayer = cb_craftPlayer_getHandle.invoke(sender);
Object mcConnection = mc_entityPlayer_playerConnection.get(cbPlayer);
mc_playerConnection_sendPacket.invoke(mcConnection, packet);
@ -211,9 +241,11 @@ public class ChatMessage {
Bukkit.getLogger().log(Level.WARNING, "Problem preparing raw chat packets (disabling further packets)", ex);
enabled = false;
}
} else {
sender.sendMessage(TextUtils.formatText((prefix == null ? "" : prefix.toText(true) + " ") + toText(true)));
return;
}
sender.sendMessage(TextUtils.formatText((prefix == null ? "" : prefix.toText(true) + " ") + toText(true)));
}
private static boolean enabled = ServerVersion.isServerVersionAtLeast(ServerVersion.V1_8);
@ -230,7 +262,6 @@ public class ChatMessage {
static void init() {
if (enabled) {
try {
final String version = ServerVersion.getServerVersionString();
Class<?> cb_craftPlayerClazz, mc_entityPlayerClazz, mc_playerConnectionClazz, mc_PacketInterface,
mc_IChatBaseComponent, mc_IChatBaseComponent_ChatSerializer, mc_PacketPlayOutChat;
@ -263,11 +294,12 @@ public class ChatMessage {
public ChatMessage replaceAll(String toReplace, String replaceWith) {
for (JsonObject object : textList) {
String text = object.get("text").getAsString()
.replaceAll(toReplace, replaceWith);
String text = object.get("text").getAsString().replaceAll(toReplace, replaceWith);
object.remove("text");
object.addProperty("text", text);
}
return this;
}
}

View File

@ -6,7 +6,6 @@ import java.util.HashMap;
import java.util.Map;
public enum ColorCode {
BLACK('0', ChatColor.BLACK, true),
DARK_BLUE('1', ChatColor.DARK_BLUE, true),
DARK_GREEN('2', ChatColor.DARK_GREEN, true),
@ -43,11 +42,7 @@ public enum ColorCode {
}
static {
ColorCode[] var0 = values();
int l = var0.length;
for (int i = 0; i < l; ++i) {
ColorCode color = var0[i];
for (ColorCode color : values()) {
BY_CHAR.put(color.code, color);
}
}

View File

@ -3,10 +3,9 @@ package com.songoda.core.chat;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.utils.ColorUtils;
import java.awt.Color;
import java.awt.*;
public class ColorContainer {
private ColorCode colorCode;
private String hexCode;
@ -17,6 +16,7 @@ public class ColorContainer {
public ColorContainer(String hexCode, boolean noHex) {
this.hexCode = hexCode;
if (noHex || ServerVersion.isServerVersionBelow(ServerVersion.V1_16)) {
this.colorCode = getColor();
this.hexCode = null;
@ -32,12 +32,19 @@ public class ColorContainer {
}
public ColorCode getColor() {
if (colorCode != null) return colorCode;
if (hexCode == null) return null;
if (colorCode != null) {
return colorCode;
}
if (hexCode == null) {
return null;
}
java.awt.Color jColor = new Color(
Integer.valueOf(hexCode.substring(0, 2), 16),
Integer.valueOf(hexCode.substring(2, 4), 16),
Integer.valueOf(hexCode.substring(4, 6), 16));
return ColorUtils.fromRGB(jColor.getRed(), jColor.getGreen(), jColor.getBlue());
}
}

View File

@ -8,7 +8,6 @@ import java.util.Collections;
import java.util.List;
public abstract class AbstractCommand {
private final CommandType _cmdType;
private final boolean _hasArgs;
private final List<String> _handledCommands = new ArrayList<>();
@ -65,8 +64,8 @@ public abstract class AbstractCommand {
return _cmdType == CommandType.PLAYER_ONLY;
}
public static enum ReturnType {SUCCESS, NEEDS_PLAYER, FAILURE, SYNTAX_ERROR}
public enum ReturnType {SUCCESS, NEEDS_PLAYER, FAILURE, SYNTAX_ERROR}
public static enum CommandType {PLAYER_ONLY, CONSOLE_OK}
public enum CommandType {PLAYER_ONLY, CONSOLE_OK}
}

View File

@ -28,7 +28,6 @@ import java.util.Set;
import java.util.stream.Collectors;
public class CommandManager implements CommandExecutor, TabCompleter {
private final JavaPlugin plugin;
private final HashMap<String, SimpleNestedCommand> commands = new HashMap<>();
@ -68,19 +67,27 @@ public class CommandManager implements CommandExecutor, TabCompleter {
public List<String> getSubCommands(String command) {
SimpleNestedCommand nested = command == null ? null : commands.get(command.toLowerCase());
return nested == null ? Collections.emptyList() : new ArrayList<>(nested.children.keySet());
if (nested == null) {
return Collections.emptyList();
}
return new ArrayList<>(nested.children.keySet());
}
public Set<AbstractCommand> getAllCommands() {
HashSet<AbstractCommand> all = new HashSet<>();
commands.values().stream()
.filter(c -> c.parent != null && !all.contains(c.parent))
.forEach(c -> {
all.add(c.parent);
c.children.values().stream()
.filter(s -> !all.contains(s))
.forEach(s -> all.add(s));
.forEach(all::add);
});
return all;
}
@ -91,10 +98,12 @@ public class CommandManager implements CommandExecutor, TabCompleter {
public SimpleNestedCommand registerCommandDynamically(AbstractCommand abstractCommand) {
SimpleNestedCommand nested = new SimpleNestedCommand(abstractCommand);
abstractCommand.getCommands().forEach(cmd -> {
CommandManager.registerCommandDynamically(plugin, cmd, this, this);
commands.put(cmd.toLowerCase(), nested);
PluginCommand pcmd = plugin.getCommand(cmd);
if (pcmd != null) {
pcmd.setExecutor(this);
pcmd.setTabCompleter(this);
@ -102,21 +111,26 @@ public class CommandManager implements CommandExecutor, TabCompleter {
plugin.getLogger().warning("Failed to register command: /" + cmd);
}
});
return nested;
}
public SimpleNestedCommand addCommand(AbstractCommand abstractCommand) {
SimpleNestedCommand nested = new SimpleNestedCommand(abstractCommand);
abstractCommand.getCommands().forEach(cmd -> {
commands.put(cmd.toLowerCase(), nested);
PluginCommand pcmd = plugin.getCommand(cmd);
if (pcmd != null) {
pcmd.setExecutor(this);
pcmd.setTabCompleter(this);
} else {
if (pcmd == null) {
plugin.getLogger().warning("Failed to register command: /" + cmd);
return;
}
pcmd.setExecutor(this);
pcmd.setTabCompleter(this);
});
return nested;
}
@ -137,9 +151,11 @@ public class CommandManager implements CommandExecutor, TabCompleter {
public MainCommand getMainCommand(String command) {
SimpleNestedCommand nested = command == null ? null : commands.get(command.toLowerCase());
if (nested != null && nested.parent instanceof MainCommand) {
return (MainCommand) nested.parent;
}
return null;
}
@ -147,16 +163,19 @@ public class CommandManager implements CommandExecutor, TabCompleter {
for (AbstractCommand abstractCommand : abstractCommands) {
addCommand(abstractCommand);
}
return this;
}
public CommandManager setExecutor(String command) {
PluginCommand pcmd = command == null ? null : plugin.getCommand(command);
if (pcmd != null) {
pcmd.setExecutor(this);
} else {
plugin.getLogger().warning("Failed to register command: /" + command);
}
return this;
}
@ -169,28 +188,34 @@ public class CommandManager implements CommandExecutor, TabCompleter {
public boolean onCommand(CommandSender commandSender, Command command, String label, String[] args) {
// grab the specific command that's being called
SimpleNestedCommand nested = commands.get(command.getName().toLowerCase());
if (nested != null) {
// check to see if we're trying to call a sub-command
if (args.length != 0 && !nested.children.isEmpty()) {
String subCmd = getSubCommand(nested, args);
if (subCmd != null) {
// we have a subcommand to use!
AbstractCommand sub = nested.children.get(subCmd);
// adjust the arguments to match - BREAKING!!
int i = subCmd.indexOf(' ') == -1 ? 1 : 2;
String[] newArgs = new String[args.length - i];
System.arraycopy(args, i, newArgs, 0, newArgs.length);
// now process the command
processRequirements(sub, commandSender, newArgs);
return true;
}
}
// if we've gotten this far, then just use the command we have
if (nested.parent != null) {
processRequirements(nested.parent, commandSender, args);
return true;
}
}
commandSender.sendMessage(msg_noCommand);
return true;
}
@ -227,6 +252,7 @@ public class CommandManager implements CommandExecutor, TabCompleter {
}
}
}
return match;
}
@ -235,17 +261,24 @@ public class CommandManager implements CommandExecutor, TabCompleter {
sender.sendMessage(msg_noConsole);
return;
}
if (command.getPermissionNode() == null || sender.hasPermission(command.getPermissionNode())) {
AbstractCommand.ReturnType returnType = command.runCommand(sender, args);
if (returnType == AbstractCommand.ReturnType.NEEDS_PLAYER) {
sender.sendMessage(msg_noConsole);
} else if (returnType == AbstractCommand.ReturnType.SYNTAX_ERROR) {
return;
}
if (returnType == AbstractCommand.ReturnType.SYNTAX_ERROR) {
for (String s : msg_syntaxError) {
sender.sendMessage(s.replace("%syntax%", command.getSyntax()));
}
}
return;
}
sender.sendMessage(msg_noPerms);
}
@ -253,10 +286,12 @@ public class CommandManager implements CommandExecutor, TabCompleter {
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
// grab the specific command that's being called
SimpleNestedCommand nested = commands.get(command.getName().toLowerCase());
if (nested != null) {
if (args.length == 0 || nested.children.isEmpty()) {
return nested.parent != null ? nested.parent.onTab(sender, args) : null;
}
// check for each sub-command that they have access to
final boolean op = sender.isOp();
final boolean console = !(sender instanceof Player);
@ -267,44 +302,49 @@ public class CommandManager implements CommandExecutor, TabCompleter {
.filter(e -> !console || !e.getValue().isNoConsole())
.filter(e -> e.getKey().startsWith(arg))
.filter(e -> op || e.getValue().getPermissionNode() == null || sender.hasPermission(e.getValue().getPermissionNode()))
.map(e -> e.getKey())
.map(Map.Entry::getKey)
.collect(Collectors.toList());
} else {
// more than one arg, let's check to see if we have a command here
String subCmd = getSubCommand(nested, args);
AbstractCommand sub;
if (subCmd != null && (sub = nested.children.get(subCmd)) != null
&& (!console || !sub.isNoConsole())
&& (op || sub.getPermissionNode() == null || sender.hasPermission(sub.getPermissionNode()))) {
// adjust the arguments to match - BREAKING!!
int i = subCmd.indexOf(' ') == -1 ? 1 : 2;
String[] newArgs = new String[args.length - i];
System.arraycopy(args, i, newArgs, 0, newArgs.length);
// we're good to go!
return fetchList(sub, newArgs, sender);
}
}
// more than one arg, let's check to see if we have a command here
String subCmd = getSubCommand(nested, args);
AbstractCommand sub;
if (subCmd != null &&
(sub = nested.children.get(subCmd)) != null &&
(!console || !sub.isNoConsole()) &&
(op || sub.getPermissionNode() == null || sender.hasPermission(sub.getPermissionNode()))) {
// adjust the arguments to match - BREAKING!!
int i = subCmd.indexOf(' ') == -1 ? 1 : 2;
String[] newArgs = new String[args.length - i];
System.arraycopy(args, i, newArgs, 0, newArgs.length);
// we're good to go!
return fetchList(sub, newArgs, sender);
}
}
return Collections.emptyList();
}
private List<String> fetchList(AbstractCommand abstractCommand, String[] args, CommandSender sender) {
List<String> list = abstractCommand.onTab(sender, args);
if (args.length != 0) {
String str = args[args.length - 1];
if (list != null && str != null && str.length() >= 1) {
try {
list.removeIf(s -> !s.toLowerCase().startsWith(str.toLowerCase()));
} catch (UnsupportedOperationException ignored) {
} catch (UnsupportedOperationException ignore) {
}
}
}
return list;
}
public static void registerCommandDynamically(Plugin plugin, String command, CommandExecutor executor, TabCompleter tabManager) {
try {
// Retrieve the SimpleCommandMap from the server
Class<?> clazzCraftServer = Bukkit.getServer().getClass();
Object craftServer = clazzCraftServer.cast(Bukkit.getServer());
@ -337,8 +377,8 @@ public class CommandManager implements CommandExecutor, TabCompleter {
fieldKnownCommands.setAccessible(true);
Map<String, Command> knownCommands = (Map<String, Command>) fieldKnownCommands.get(commandMap);
knownCommands.put(command, commandObject);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
}
}

View File

@ -12,7 +12,6 @@ import java.util.List;
import java.util.stream.Collectors;
public class MainCommand extends AbstractCommand {
String header = null;
String description;
boolean sortHelp = false;
@ -22,6 +21,7 @@ public class MainCommand extends AbstractCommand {
public MainCommand(Plugin plugin, String command) {
super(CommandType.CONSOLE_OK, command);
this.command = command;
this.plugin = plugin;
this.description = "Shows the command help page for /" + command;
@ -56,6 +56,7 @@ public class MainCommand extends AbstractCommand {
@Override
protected ReturnType runCommand(CommandSender sender, String... args) {
sender.sendMessage("");
if (header != null) {
sender.sendMessage(header);
} else {
@ -63,17 +64,21 @@ public class MainCommand extends AbstractCommand {
plugin.getDescription().getName(), plugin.getDescription().getVersion()), sender instanceof ConsoleCommandSender)
.sendTo(sender);
}
sender.sendMessage(ChatColor.DARK_GRAY + "- " + ChatColor.YELLOW + "/songoda" + ChatColor.GRAY + " - Opens the Songoda plugin GUI");
sender.sendMessage("");
if (nestedCommands != null) {
List<String> commands = nestedCommands.children.values().stream().distinct().map(c -> c.getCommands().get(0)).collect(Collectors.toList());
if (sortHelp) {
Collections.sort(commands);
}
boolean isPlayer = sender instanceof Player;
// todo? pagation if commands.size is too large? (player-only)
sender.sendMessage(ChatColor.DARK_GRAY + "- " + ChatColor.YELLOW + getSyntax() + ChatColor.GRAY + " - " + getDescription());
for (String cmdStr : commands) {
final AbstractCommand cmd = nestedCommands.children.get(cmdStr);
if (cmd == null) continue;
@ -85,7 +90,7 @@ public class MainCommand extends AbstractCommand {
chatMessage.addMessage(ChatColor.DARK_GRAY + "- ")
.addPromptCommand(ChatColor.YELLOW + c + cmd.getSyntax(), ChatColor.YELLOW + c + cmdStr, c + cmdStr)
.addMessage(ChatColor.GRAY + " - " + cmd.getDescription());
chatMessage.sendTo((Player) sender);
chatMessage.sendTo(sender);
}
}
}

View File

@ -20,8 +20,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
public class SelectorArguments {
static Pattern selectorPattern = Pattern.compile("^(@[apers])(\\[(.*?)\\])?$");
static Pattern selectorPattern = Pattern.compile("^(@[apers])(\\[(.*?)])?$");
static Pattern selectorRangePattern = Pattern.compile("^([0-9]{1,9}(\\.[0-9]{1,9})?)?(\\.\\.)?([0-9]{1,9}(\\.[0-9]{1,9})?)?$");
/**
@ -38,14 +37,17 @@ public class SelectorArguments {
if (!(sender instanceof BlockCommandSender || sender instanceof Player)) {
return null;
}
Matcher m = selectorPattern.matcher(argument);
if (!m.find()) {
return null;
}
SelectorType type = SelectorType.getType(m.group(1));
if (type == null) {
return null;
}
SelectorArguments selector = new SelectorArguments(sender, type);
if (m.group(3) != null) {
@ -67,9 +69,11 @@ public class SelectorArguments {
private void parseArguments(String selectorArgs) {
String[] args = selectorArgs.split(",");
for (String s : args) {
if (s.contains("=")) {
String[] v = s.split("=");
if (v[0].equals("distance")) {
// 10 = d == 10
// 10..12 = d > 10 && d <= 12
@ -80,6 +84,7 @@ public class SelectorArguments {
if (distGroup.group(1) != null) {
rangeMin = Double.parseDouble(distGroup.group(1));
}
if (distGroup.group(3) == null) {
rangeMax = rangeMin;
} else if (distGroup.group(4) != null) {
@ -89,9 +94,11 @@ public class SelectorArguments {
} else if (v[0].equals("type")) {
entityType = EntityNamespace.minecraftToBukkit(v[1]);
}
// more arguments can be parsed here (TODO)
}
}
/*
advancements Advancement earned by entity.
distance Distance to entity.
@ -121,16 +128,21 @@ public class SelectorArguments {
public Collection<Entity> getSelection() {
final Location location = sender instanceof Player ? ((Player) sender).getLocation() : ((BlockCommandSender) sender).getBlock().getLocation();
Collection<Entity> list = preSelect(location);
if (list.isEmpty()) {
return list;
}
List<Entity> list2 = filter(location, list);
if (list2.isEmpty()) {
return list2;
}
switch (selector) {
case PLAYER:
Collections.sort(list2, (o1, o2) -> (int) (o1.getLocation().distanceSquared(location) - o2.getLocation().distanceSquared(location)));
list2.sort((o1, o2) -> (int) (o1.getLocation().distanceSquared(location) - o2.getLocation().distanceSquared(location)));
return Arrays.asList(list2.get(0));
case RANDOM_PLAYER:
Collections.shuffle(list2);
@ -140,6 +152,7 @@ public class SelectorArguments {
case SELF:
return list2;
}
return list2;
}
@ -151,28 +164,32 @@ public class SelectorArguments {
return rangeMax == Double.POSITIVE_INFINITY
? location.getWorld().getEntitiesByClasses(Player.class)
: location.getWorld().getNearbyEntities(location, rangeMax * 2, rangeMax * 2, rangeMax * 2).stream()
.filter(e -> e instanceof Player).collect(Collectors.toSet());
.filter(Player.class::isInstance).collect(Collectors.toSet());
case ALL_ENTITIES:
return rangeMax == Double.POSITIVE_INFINITY
? location.getWorld().getEntities()
: location.getWorld().getNearbyEntities(location, rangeMax * 2, rangeMax * 2, rangeMax * 2);
case SELF:
return sender instanceof Entity ? Arrays.asList((Entity) sender) : Collections.EMPTY_LIST;
return sender instanceof Entity ? Arrays.asList((Entity) sender) : Collections.emptyList();
}
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
protected List<Entity> filter(Location location, Collection<Entity> list) {
Stream<Entity> stream = list.stream()
.filter(p -> rangeMin == 0 || p.getLocation().distance(location) > rangeMin)
.filter(e -> entityType == null || e.getType() == entityType);
return stream.collect(Collectors.toList());
}
public static enum SelectorType {
public enum SelectorType {
PLAYER, RANDOM_PLAYER, ALL_PLAYER, ALL_ENTITIES, SELF;
// TODO: Store selector string in enum
public static SelectorType getType(String str) {
if (str != null) {
switch (str.toLowerCase()) {
@ -186,8 +203,11 @@ public class SelectorArguments {
return ALL_ENTITIES;
case "@s":
return SELF;
default:
break;
}
}
return null;
}
}

View File

@ -4,7 +4,6 @@ import java.util.LinkedHashMap;
import java.util.stream.Stream;
public class SimpleNestedCommand {
final AbstractCommand parent;
final LinkedHashMap<String, AbstractCommand> children = new LinkedHashMap<>();

View File

@ -1,108 +1,114 @@
package com.songoda.core.configuration;
import com.songoda.core.configuration.ConfigFormattingRules.CommentStyle;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* A comment for a configuration key
*
* @author jascotty2
* @since 2019-08-28
*/
public class Comment {
final List<String> lines = new ArrayList();
CommentStyle commentStyle = null;
public Comment() {
}
public Comment(String... lines) {
this(null, Arrays.asList(lines));
}
public Comment(List<String> lines) {
this(null, lines);
}
public Comment(CommentStyle commentStyle, String... lines) {
this(commentStyle, Arrays.asList(lines));
}
public Comment(CommentStyle commentStyle, List<String> lines) {
this.commentStyle = commentStyle;
if (lines != null) {
lines.forEach(s -> this.lines.addAll(Arrays.asList(s.split("\n"))));
}
}
public CommentStyle getCommentStyle() {
return commentStyle;
}
public void setCommentStyle(CommentStyle commentStyle) {
this.commentStyle = commentStyle;
}
public List<String> getLines() {
return lines;
}
@Override
public String toString() {
return lines.isEmpty() ? "" : lines.stream().collect(Collectors.joining("\n"));
}
public static Comment loadComment(List<String> lines) {
CommentStyle style = ConfigFormattingRules.parseStyle(lines);
int linePad = (style.drawBorder ? 1 : 0) + (style.drawSpace ? 1 : 0);
int prefix = style.commentPrefix.length();
int suffix = style.commentSuffix.length();
return new Comment(style, lines.subList(linePad, lines.size() - linePad).stream().map(s -> s.substring(prefix, s.length() - suffix).trim()).collect(Collectors.toList()));
}
public void writeComment(Writer output, int offset, CommentStyle defaultStyle) throws IOException {
CommentStyle style = commentStyle != null ? commentStyle : defaultStyle;
int minSpacing = 0, borderSpacing = 0;
// first draw the top of the comment
if (style.drawBorder) {
// grab the longest line in the list of lines
minSpacing = lines.stream().max((s1, s2) -> s1.length() - s2.length()).get().length();
borderSpacing = minSpacing + style.commentPrefix.length() + style.commentSuffix.length();
// draw the first line
output.write((new String(new char[offset])).replace('\0', ' ') + (new String(new char[borderSpacing + 2])).replace('\0', '#') + "\n");
if (style.drawSpace) {
output.write((new String(new char[offset])).replace('\0', ' ')
+ "#" + style.spacePrefixTop
+ (new String(new char[borderSpacing - style.spacePrefixTop.length() - style.spaceSuffixTop.length()])).replace('\0', style.spaceCharTop)
+ style.spaceSuffixTop + "#\n");
}
} else if (style.drawSpace) {
output.write((new String(new char[offset])).replace('\0', ' ') + "#\n");
}
// then the actual comment lines
for (String line : lines) {
// todo? should we auto-wrap comment lines that are longer than 80 characters?
output.write((new String(new char[offset])).replace('\0', ' ') + "#" + style.commentPrefix
+ (minSpacing == 0 ? line : line + (new String(new char[minSpacing - line.length()])).replace('\0', ' ')) + style.commentSuffix + (style.drawBorder ? "#\n" : "\n"));
}
// now draw the bottom of the comment border
if (style.drawBorder) {
if (style.drawSpace) {
output.write((new String(new char[offset])).replace('\0', ' ')
+ "#" + style.spacePrefixBottom
+ (new String(new char[borderSpacing - style.spacePrefixBottom.length() - style.spaceSuffixBottom.length()])).replace('\0', style.spaceCharBottom)
+ style.spaceSuffixBottom + "#\n");
}
output.write((new String(new char[offset])).replace('\0', ' ') + (new String(new char[borderSpacing + 2])).replace('\0', '#') + "\n");
} else if (style.drawSpace) {
output.write((new String(new char[offset])).replace('\0', ' ') + "#\n");
}
}
}
package com.songoda.core.configuration;
import com.songoda.core.configuration.ConfigFormattingRules.CommentStyle;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* A comment for a configuration key
*/
public class Comment {
final List<String> lines = new ArrayList<>();
CommentStyle commentStyle = null;
public Comment() {
}
public Comment(String... lines) {
this(null, Arrays.asList(lines));
}
public Comment(List<String> lines) {
this(null, lines);
}
public Comment(CommentStyle commentStyle, String... lines) {
this(commentStyle, Arrays.asList(lines));
}
public Comment(CommentStyle commentStyle, List<String> lines) {
this.commentStyle = commentStyle;
if (lines != null) {
lines.forEach(s -> this.lines.addAll(Arrays.asList(s.split("\n"))));
}
}
public CommentStyle getCommentStyle() {
return commentStyle;
}
public void setCommentStyle(CommentStyle commentStyle) {
this.commentStyle = commentStyle;
}
public List<String> getLines() {
return lines;
}
@Override
public String toString() {
return lines.isEmpty() ? "" : String.join("\n", lines);
}
public static Comment loadComment(List<String> lines) {
CommentStyle style = ConfigFormattingRules.parseStyle(lines);
int linePad = (style.drawBorder ? 1 : 0) + (style.drawSpace ? 1 : 0);
int prefix = style.commentPrefix.length();
int suffix = style.commentSuffix.length();
return new Comment(style, lines.subList(linePad, lines.size() - linePad).stream().map(s -> s.substring(prefix, s.length() - suffix).trim()).collect(Collectors.toList()));
}
public void writeComment(Writer output, int offset, CommentStyle defaultStyle) throws IOException {
CommentStyle style = commentStyle != null ? commentStyle : defaultStyle;
int minSpacing = 0, borderSpacing = 0;
// first draw the top of the comment
if (style.drawBorder) {
// grab the longest line in the list of lines
minSpacing = lines.stream().max(Comparator.comparingInt(String::length)).orElse("").length();
borderSpacing = minSpacing + style.commentPrefix.length() + style.commentSuffix.length();
// draw the first line
output.write((new String(new char[offset])).replace('\0', ' ') + (new String(new char[borderSpacing + 2])).replace('\0', '#') + "\n");
if (style.drawSpace) {
output.write((new String(new char[offset])).replace('\0', ' ')
+ "#" + style.spacePrefixTop
+ (new String(new char[borderSpacing - style.spacePrefixTop.length() - style.spaceSuffixTop.length()])).replace('\0', style.spaceCharTop)
+ style.spaceSuffixTop + "#\n");
}
} else if (style.drawSpace) {
output.write((new String(new char[offset])).replace('\0', ' ') + "#\n");
}
// then the actual comment lines
for (String line : lines) {
// todo? should we auto-wrap comment lines that are longer than 80 characters?
output.write((new String(new char[offset])).replace('\0', ' ') + "#" + style.commentPrefix
+ (minSpacing == 0 ? line : line + (new String(new char[minSpacing - line.length()])).replace('\0', ' ')) + style.commentSuffix + (style.drawBorder ? "#\n" : "\n"));
}
// now draw the bottom of the comment border
if (style.drawBorder) {
if (style.drawSpace) {
output.write((new String(new char[offset])).replace('\0', ' ')
+ "#" + style.spacePrefixBottom
+ (new String(new char[borderSpacing - style.spacePrefixBottom.length() - style.spaceSuffixBottom.length()])).replace('\0', style.spaceCharBottom)
+ style.spaceSuffixBottom + "#\n");
}
output.write((new String(new char[offset])).replace('\0', ' ') + (new String(new char[borderSpacing + 2])).replace('\0', '#') + "\n");
} else if (style.drawSpace) {
output.write((new String(new char[offset])).replace('\0', ' ') + "#\n");
}
}
}

View File

@ -21,7 +21,6 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
@ -45,12 +44,8 @@ import java.util.stream.Collectors;
/**
* Configuration settings for a plugin
*
* @author jascotty2
* @since 2019-08-28
*/
public class Config extends ConfigSection {
/*
Serialization notes:
// implements ConfigurationSerializable:
@ -75,35 +70,43 @@ public class Config extends ConfigSection {
Charset defaultCharset = StandardCharsets.UTF_8;
SaveTask saveTask;
Timer autosaveTimer;
////////////// Config settings ////////////////
/**
* save file whenever a change is made
*/
boolean autosave = false;
/**
* time in seconds to start a save after a change is made
*/
int autosaveInterval = 60;
/**
* remove nodes not defined in defaults
*/
boolean autoremove = false;
/**
* load comments when loading the file
*/
boolean loadComments = true;
/**
* Default comment applied to config nodes
*/
ConfigFormattingRules.CommentStyle defaultNodeCommentFormat = ConfigFormattingRules.CommentStyle.SIMPLE;
/**
* Default comment applied to section nodes
*/
ConfigFormattingRules.CommentStyle defaultSectionCommentFormat = ConfigFormattingRules.CommentStyle.SPACED;
/**
* Extra lines to put between root nodes
*/
int rootNodeSpacing = 1;
/**
* Extra lines to put in front of comments. <br>
* This is separate from rootNodeSpacing, if applicable.
@ -113,6 +116,7 @@ public class Config extends ConfigSection {
public Config() {
this.plugin = null;
this.file = null;
dirName = null;
fileName = null;
}
@ -120,24 +124,28 @@ public class Config extends ConfigSection {
public Config(@NotNull File file) {
this.plugin = null;
this.file = file.getAbsoluteFile();
dirName = null;
fileName = null;
}
public Config(@NotNull Plugin plugin) {
this.plugin = plugin;
dirName = null;
fileName = null;
}
public Config(@NotNull Plugin plugin, @NotNull String file) {
this.plugin = plugin;
dirName = null;
fileName = file;
}
public Config(@NotNull Plugin plugin, @Nullable String directory, @NotNull String file) {
this.plugin = plugin;
dirName = directory;
fileName = file;
}
@ -156,6 +164,7 @@ public class Config extends ConfigSection {
this.file = new File(plugin.getDataFolder(), fileName != null ? fileName : "config.yml");
}
}
return file;
}
@ -337,6 +346,7 @@ public class Config extends ConfigSection {
} else {
headerComment = new Comment(description);
}
return this;
}
@ -347,6 +357,7 @@ public class Config extends ConfigSection {
} else {
headerComment = new Comment(commentStyle, description);
}
return this;
}
@ -357,6 +368,7 @@ public class Config extends ConfigSection {
} else {
headerComment = new Comment(description);
}
return this;
}
@ -367,6 +379,7 @@ public class Config extends ConfigSection {
} else {
headerComment = new Comment(commentStyle, description);
}
return this;
}
@ -374,24 +387,27 @@ public class Config extends ConfigSection {
public List<String> getHeader() {
if (headerComment != null) {
return headerComment.getLines();
} else {
return Collections.EMPTY_LIST;
}
return Collections.emptyList();
}
public Config clearConfig(boolean clearDefaults) {
root.values.clear();
root.configComments.clear();
if (clearDefaults) {
root.defaultComments.clear();
root.defaults.clear();
}
return this;
}
public Config clearDefaults() {
root.defaultComments.clear();
root.defaults.clear();
return this;
}
@ -404,17 +420,22 @@ public class Config extends ConfigSection {
if (file.exists()) {
try (BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file))) {
Charset charset = TextUtils.detectCharset(stream, StandardCharsets.UTF_8);
// upgrade charset if file was saved in a more complex format
if (charset == StandardCharsets.UTF_16BE || charset == StandardCharsets.UTF_16LE) {
defaultCharset = StandardCharsets.UTF_16;
}
this.load(new InputStreamReader(stream, charset));
return true;
} catch (IOException | InvalidConfigurationException ex) {
(plugin != null ? plugin.getLogger() : Bukkit.getLogger()).log(Level.SEVERE, "Failed to load config file: " + file.getName(), ex);
}
return false;
}
return true;
}
@ -432,22 +453,26 @@ public class Config extends ConfigSection {
builder.append(line).append('\n');
}
}
this.loadFromString(builder.toString());
}
public void loadFromString(@NotNull String contents) throws InvalidConfigurationException {
Map input;
Map<?, ?> input;
try {
input = (Map) this.yaml.load(contents);
input = this.yaml.load(contents);
} catch (YAMLException e2) {
throw new InvalidConfigurationException(e2);
} catch (ClassCastException e3) {
throw new InvalidConfigurationException("Top level is not a Map.");
}
if (input != null) {
if (loadComments) {
this.parseComments(contents, input);
}
this.convertMapsToSections(input, this);
}
}
@ -457,10 +482,12 @@ public class Config extends ConfigSection {
for (Map.Entry<?, ?> entry : input.entrySet()) {
String key = entry.getKey().toString();
Object value = entry.getValue();
if (value instanceof Map) {
this.convertMapsToSections((Map) value, section.createSection(key));
this.convertMapsToSections((Map<?, ?>) value, section.createSection(key));
continue;
}
section.set(key, value);
}
}
@ -475,8 +502,9 @@ public class Config extends ConfigSection {
boolean insideScalar = false;
boolean firstNode = true;
int index = 0;
LinkedList<String> currentPath = new LinkedList();
ArrayList<String> commentBlock = new ArrayList();
LinkedList<String> currentPath = new LinkedList<>();
ArrayList<String> commentBlock = new ArrayList<>();
try {
while ((line = in.readLine()) != null) {
if (line.isEmpty()) {
@ -523,17 +551,20 @@ public class Config extends ConfigSection {
}
}
}
if (!commentBlock.isEmpty()) {
footerComment = Comment.loadComment(commentBlock);
commentBlock.clear();
}
} catch (IOException ex) {
Logger.getLogger(Config.class.getName()).log(Level.SEVERE, "Error parsing config comment", ex);
}
}
public void deleteNonDefaultSettings() {
// Delete old config values (thread-safe)
List<String> defaultKeys = Arrays.asList(defaults.keySet().toArray(new String[0]));
for (String key : values.keySet().toArray(new String[0])) {
if (!defaultKeys.contains(key)) {
values.remove(key);
@ -558,9 +589,11 @@ public class Config extends ConfigSection {
public boolean saveChanges() {
boolean saved = true;
if (changed || hasNewDefaults()) {
saved = save();
}
if (saveTask != null) {
//Close Threads
saveTask.cancel();
@ -568,14 +601,19 @@ public class Config extends ConfigSection {
saveTask = null;
autosaveTimer = null;
}
return saved;
}
boolean hasNewDefaults() {
if (file != null && !file.exists()) return true;
for (String def : defaults.keySet()) {
if (!values.containsKey(def)) return true;
if (!values.containsKey(def)) {
return true;
}
}
return false;
}
@ -587,6 +625,7 @@ public class Config extends ConfigSection {
saveTask = null;
autosaveTimer = null;
}
return save(getFile());
}
@ -597,15 +636,18 @@ public class Config extends ConfigSection {
public boolean save(@NotNull File file) {
Validate.notNull(file, "File cannot be null");
if (file.getParentFile() != null && !file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
String data = this.saveToString();
try (OutputStreamWriter writer = new OutputStreamWriter((OutputStream) new FileOutputStream(file), defaultCharset);) {
try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file), defaultCharset)) {
writer.write(data);
} catch (IOException e) {
} catch (IOException ex) {
return false;
}
return true;
}
@ -615,41 +657,50 @@ public class Config extends ConfigSection {
if (autoremove) {
deleteNonDefaultSettings();
}
yamlOptions.setIndent(indentation);
yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
yamlOptions.setSplitLines(false);
yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
StringWriter str = new StringWriter();
if (headerComment != null) {
headerComment.writeComment(str, 0, ConfigFormattingRules.CommentStyle.BLOCKED);
str.write("\n"); // add one space after the header
}
String dump = yaml.dump(this.getValues(false));
if (!dump.equals(BLANK_CONFIG)) {
writeComments(dump, str);
}
if (footerComment != null) {
str.write("\n");
footerComment.writeComment(str, 0, ConfigFormattingRules.CommentStyle.BLOCKED);
}
return str.toString();
} catch (Throwable ex) {
Logger.getLogger(Config.class.getName()).log(Level.SEVERE, "Error saving config", ex);
delaySave();
}
return "";
}
protected final Pattern yamlNode = Pattern.compile("^( *)([^:\\{\\}\\[\\],&\\*#\\?\\|\\-<>=!%@`]+):(.*)$");
protected final Pattern yamlNode = Pattern.compile("^( *)([^:{}\\[\\],&*#?|\\-<>=!%@`]+):(.*)$");
protected void writeComments(String data, Writer out) throws IOException {
// line-by-line apply line spacing formatting and comments per-node
BufferedReader in = new BufferedReader(new StringReader(data));
String line;
boolean insideScalar = false;
boolean firstNode = true;
int index = 0;
LinkedList<String> currentPath = new LinkedList();
LinkedList<String> currentPath = new LinkedList<>();
while ((line = in.readLine()) != null) {
// ignore comments and empty lines (there shouldn't be any, but just in case)
if (line.trim().startsWith("#") || line.isEmpty()) {
@ -667,6 +718,7 @@ public class Config extends ConfigSection {
while (depth < currentPath.size()) {
currentPath.removeLast();
}
currentPath.add(m.group(2));
String path = currentPath.stream().collect(Collectors.joining(String.valueOf(pathChar)));
@ -708,6 +760,7 @@ public class Config extends ConfigSection {
// write it down!
comment.writeComment(out, lineOffset, style);
}
// ignore scalars
index = lineOffset;
if (m.group(3).trim().equals("|") || m.group(3).trim().equals(">")) {
@ -727,11 +780,11 @@ public class Config extends ConfigSection {
return i;
}
}
return -1;
}
class SaveTask extends TimerTask {
@Override
public void run() {
saveChanges();

View File

@ -1,273 +1,272 @@
package com.songoda.core.configuration;
import com.songoda.core.compatibility.CompatibleMaterial;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class ConfigFileConfigurationAdapter extends FileConfiguration {
final Config config;
public ConfigFileConfigurationAdapter(Config config) {
super(config);
this.config = config;
}
public Config getCoreConfig() {
return config;
}
@Override
public String saveToString() {
return config.saveToString();
}
@Override
public void loadFromString(String string) throws InvalidConfigurationException {
config.loadFromString(string);
}
@Override
protected String buildHeader() {
return "#" + config.getHeader().stream().collect(Collectors.joining("\n#"));
}
@Override
public ConfigOptionsAdapter options() {
return new ConfigOptionsAdapter(config);
}
@Override
public Set<String> getKeys(boolean deep) {
return config.getKeys(deep);
}
@Override
public Map<String, Object> getValues(boolean deep) {
return config.getValues(deep);
}
@Override
public boolean contains(String path) {
return config.contains(path);
}
@Override
public boolean isSet(String path) {
return config.isSet(path);
}
@Override
public String getCurrentPath() {
return config.getCurrentPath();
}
@Override
public String getName() {
return config.getName();
}
@Override
public Configuration getRoot() {
return config;
}
@Override
public ConfigurationSection getParent() {
return null;
}
@Override
public void addDefault(String path, Object value) {
config.addDefault(path, value);
}
@Override
public ConfigurationSection getDefaultSection() {
return config.getDefaultSection();
}
@Override
public void set(String path, Object value) {
config.set(path, value);
}
@Override
public Object get(String path) {
return config.get(path);
}
@Override
public Object get(String path, Object def) {
return config.get(path, def);
}
@Override
public ConfigurationSection createSection(String path) {
return config.createSection(path);
}
@Override
public ConfigurationSection createSection(String path, Map<?, ?> map) {
return config.createSection(path, map);
}
// Other non-FileConfiguration methods
@NotNull
public ConfigSection createDefaultSection(@NotNull String path) {
return config.createDefaultSection(path);
}
@NotNull
public ConfigSection createDefaultSection(@NotNull String path, String... comment) {
return config.createDefaultSection(path, comment);
}
@NotNull
public ConfigSection createDefaultSection(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.createDefaultSection(path, commentStyle, comment);
}
@NotNull
public ConfigSection setComment(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... lines) {
return config.setComment(path, commentStyle, lines);
}
@NotNull
public ConfigSection setComment(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> lines) {
return config.setComment(path, commentStyle, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, String... lines) {
return config.setDefaultComment(path, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, @Nullable List<String> lines) {
return config.setDefaultComment(path, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, String... lines) {
return config.setDefaultComment(path, commentStyle, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> lines) {
return config.setDefaultComment(path, commentStyle, lines);
}
@Nullable
public Comment getComment(@NotNull String path) {
return config.getComment(path);
}
@Nullable
public String getCommentString(@NotNull String path) {
return config.getCommentString(path);
}
@NotNull
public List<ConfigSection> getSections(String path) {
return config.getSections(path);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, String... comment) {
return config.set(path, value, comment);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, List<String> comment) {
return config.set(path, value, comment);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.set(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, @Nullable ConfigFormattingRules.CommentStyle commentStyle, List<String> comment) {
return config.set(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value) {
return config.setDefault(path, value);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, String... comment) {
return config.setDefault(path, value, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, List<String> comment) {
return config.setDefault(path, value, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.setDefault(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, ConfigFormattingRules.CommentStyle commentStyle, List<String> comment) {
return config.setDefault(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, String... comment) {
return config.createSection(path, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, @Nullable List<String> comment) {
return config.createSection(path, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.createSection(path, commentStyle, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> comment) {
return config.createSection(path, commentStyle, comment);
}
public char getChar(@NotNull String path) {
return config.getChar(path);
}
public char getChar(@NotNull String path, char def) {
return config.getChar(path, def);
}
@Nullable
public CompatibleMaterial getMaterial(@NotNull String path) {
return config.getMaterial(path);
}
@Nullable
public CompatibleMaterial getMaterial(@NotNull String path, @Nullable CompatibleMaterial def) {
return config.getMaterial(path, def);
}
@NotNull
public ConfigSection getOrCreateConfigurationSection(@NotNull String path) {
return config.getOrCreateConfigurationSection(path);
}
}
package com.songoda.core.configuration;
import com.songoda.core.compatibility.CompatibleMaterial;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ConfigFileConfigurationAdapter extends FileConfiguration {
final Config config;
public ConfigFileConfigurationAdapter(Config config) {
super(config);
this.config = config;
}
public Config getCoreConfig() {
return config;
}
@Override
public String saveToString() {
return config.saveToString();
}
@Override
public void loadFromString(String string) throws InvalidConfigurationException {
config.loadFromString(string);
}
@Override
protected String buildHeader() {
return "#" + String.join("\n#", config.getHeader());
}
@Override
public ConfigOptionsAdapter options() {
return new ConfigOptionsAdapter(config);
}
@Override
public Set<String> getKeys(boolean deep) {
return config.getKeys(deep);
}
@Override
public Map<String, Object> getValues(boolean deep) {
return config.getValues(deep);
}
@Override
public boolean contains(String path) {
return config.contains(path);
}
@Override
public boolean isSet(String path) {
return config.isSet(path);
}
@Override
public String getCurrentPath() {
return config.getCurrentPath();
}
@Override
public String getName() {
return config.getName();
}
@Override
public Configuration getRoot() {
return config;
}
@Override
public ConfigurationSection getParent() {
return null;
}
@Override
public void addDefault(String path, Object value) {
config.addDefault(path, value);
}
@Override
public ConfigurationSection getDefaultSection() {
return config.getDefaultSection();
}
@Override
public void set(String path, Object value) {
config.set(path, value);
}
@Override
public Object get(String path) {
return config.get(path);
}
@Override
public Object get(String path, Object def) {
return config.get(path, def);
}
@Override
public ConfigurationSection createSection(String path) {
return config.createSection(path);
}
@Override
public ConfigurationSection createSection(String path, Map<?, ?> map) {
return config.createSection(path, map);
}
// Other non-FileConfiguration methods
@NotNull
public ConfigSection createDefaultSection(@NotNull String path) {
return config.createDefaultSection(path);
}
@NotNull
public ConfigSection createDefaultSection(@NotNull String path, String... comment) {
return config.createDefaultSection(path, comment);
}
@NotNull
public ConfigSection createDefaultSection(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.createDefaultSection(path, commentStyle, comment);
}
@NotNull
public ConfigSection setComment(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... lines) {
return config.setComment(path, commentStyle, lines);
}
@NotNull
public ConfigSection setComment(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> lines) {
return config.setComment(path, commentStyle, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, String... lines) {
return config.setDefaultComment(path, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, @Nullable List<String> lines) {
return config.setDefaultComment(path, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, String... lines) {
return config.setDefaultComment(path, commentStyle, lines);
}
@NotNull
public ConfigSection setDefaultComment(@NotNull String path, ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> lines) {
return config.setDefaultComment(path, commentStyle, lines);
}
@Nullable
public Comment getComment(@NotNull String path) {
return config.getComment(path);
}
@Nullable
public String getCommentString(@NotNull String path) {
return config.getCommentString(path);
}
@NotNull
public List<ConfigSection> getSections(String path) {
return config.getSections(path);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, String... comment) {
return config.set(path, value, comment);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, List<String> comment) {
return config.set(path, value, comment);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.set(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection set(@NotNull String path, @Nullable Object value, @Nullable ConfigFormattingRules.CommentStyle commentStyle, List<String> comment) {
return config.set(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value) {
return config.setDefault(path, value);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, String... comment) {
return config.setDefault(path, value, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, List<String> comment) {
return config.setDefault(path, value, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.setDefault(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection setDefault(@NotNull String path, @Nullable Object value, ConfigFormattingRules.CommentStyle commentStyle, List<String> comment) {
return config.setDefault(path, value, commentStyle, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, String... comment) {
return config.createSection(path, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, @Nullable List<String> comment) {
return config.createSection(path, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
return config.createSection(path, commentStyle, comment);
}
@NotNull
public ConfigSection createSection(@NotNull String path, @Nullable ConfigFormattingRules.CommentStyle commentStyle, @Nullable List<String> comment) {
return config.createSection(path, commentStyle, comment);
}
public char getChar(@NotNull String path) {
return config.getChar(path);
}
public char getChar(@NotNull String path, char def) {
return config.getChar(path, def);
}
@Nullable
public CompatibleMaterial getMaterial(@NotNull String path) {
return config.getMaterial(path);
}
@Nullable
public CompatibleMaterial getMaterial(@NotNull String path, @Nullable CompatibleMaterial def) {
return config.getMaterial(path, def);
}
@NotNull
public ConfigSection getOrCreateConfigurationSection(@NotNull String path) {
return config.getOrCreateConfigurationSection(path);
}
}

View File

@ -3,14 +3,12 @@ package com.songoda.core.configuration;
import java.util.List;
public class ConfigFormattingRules {
int spacesBetweenMainCategories;
int spacesBetweenValues;
CommentStyle rootCommentStyle = CommentStyle.BLOCKSPACED;
CommentStyle mainCategoryCommentStyle = CommentStyle.SPACED;
public static enum CommentStyle {
public enum CommentStyle {
/**
* # Comment
*/
@ -41,10 +39,10 @@ public class ConfigFormattingRules {
final String commentSuffix, spaceSuffixTop, spaceSuffixBottom;
final char spaceCharTop, spaceCharBottom;
private CommentStyle(boolean drawBorder, boolean drawSpace,
String spacePrefixTop, char spaceCharTop, String spaceSuffixTop,
String commentPrefix, String commentSuffix,
String spacePrefixBottom, char spaceCharBottom, String spaceSuffixBottom) {
CommentStyle(boolean drawBorder, boolean drawSpace,
String spacePrefixTop, char spaceCharTop, String spaceSuffixTop,
String commentPrefix, String commentSuffix,
String spacePrefixBottom, char spaceCharBottom, String spaceSuffixBottom) {
this.drawBorder = drawBorder;
this.drawSpace = drawSpace;
this.commentPrefix = commentPrefix;
@ -57,7 +55,7 @@ public class ConfigFormattingRules {
this.spaceCharBottom = spaceCharBottom;
}
private CommentStyle(boolean drawBorder, boolean drawSpace, String commentPrefix, String commentSuffix) {
CommentStyle(boolean drawBorder, boolean drawSpace, String commentPrefix, String commentSuffix) {
this.drawBorder = drawBorder;
this.drawSpace = drawSpace;
this.commentPrefix = commentPrefix;
@ -71,14 +69,18 @@ public class ConfigFormattingRules {
public static CommentStyle parseStyle(List<String> lines) {
if (lines == null || lines.size() <= 2) {
return CommentStyle.SIMPLE;
} else if (lines.size() > 2 && lines.get(0).trim().equals("#") && lines.get(lines.size() - 1).trim().equals("#")) {
}
if (lines.get(0).trim().equals("#") && lines.get(lines.size() - 1).trim().equals("#")) {
return CommentStyle.SPACED;
}
boolean hasBorders = lines.size() > 2 && lines.get(0).trim().matches("^##+$") && lines.get(lines.size() - 1).trim().matches("^##+$");
boolean hasBorders = lines.get(0).trim().matches("^##+$") && lines.get(lines.size() - 1).trim().matches("^##+$");
if (!hasBorders) {
// default return
return CommentStyle.SIMPLE;
}
// now need to figure out if this is blocked or not
if (lines.size() > 4 && lines.get(1).trim().matches(("^#"
+ CommentStyle.BLOCKSPACED.spacePrefixTop + CommentStyle.BLOCKSPACED.spaceCharTop + "+"
@ -88,6 +90,7 @@ public class ConfigFormattingRules {
+ CommentStyle.BLOCKSPACED.spaceSuffixTop + "#$").replace("|", "\\|"))) {
return CommentStyle.BLOCKSPACED;
}
return CommentStyle.BLOCKED;
}
}

View File

@ -1,71 +1,72 @@
package com.songoda.core.configuration;
import org.bukkit.configuration.file.FileConfigurationOptions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class ConfigOptionsAdapter extends FileConfigurationOptions {
final ConfigSection config;
public ConfigOptionsAdapter(ConfigSection config) {
super(config);
this.config = config;
}
public Config getConfig() {
return (Config) config.root;
}
@NotNull
@Override
public ConfigFileConfigurationAdapter configuration() {
return new ConfigFileConfigurationAdapter((Config) config.root);
}
@NotNull
@Override
public ConfigOptionsAdapter copyDefaults(boolean value) {
// we always copy new values
return this;
}
@NotNull
@Override
public ConfigOptionsAdapter pathSeparator(char value) {
((Config) config.root).setPathSeparator(value);
return this;
}
@NotNull
@Override
public ConfigOptionsAdapter header(@Nullable String value) {
if (value == null) {
((Config) config.root).setHeader((List) null);
} else {
((Config) config.root).setHeader(value.split("\n"));
}
return this;
}
@NotNull
@Override
public ConfigOptionsAdapter copyHeader(boolean value) {
if (!value) {
((Config) config.root).setHeader((List) null);
}
return this;
}
public int indent() {
return ((Config) config.root).getIndent();
}
@NotNull
public ConfigOptionsAdapter indent(int value) {
((Config) config.root).setIndent(value);
return this;
}
}
package com.songoda.core.configuration;
import org.bukkit.configuration.file.FileConfigurationOptions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class ConfigOptionsAdapter extends FileConfigurationOptions {
final ConfigSection config;
public ConfigOptionsAdapter(ConfigSection config) {
super(config);
this.config = config;
}
public Config getConfig() {
return (Config) config.root;
}
@NotNull
@Override
public ConfigFileConfigurationAdapter configuration() {
return new ConfigFileConfigurationAdapter((Config) config.root);
}
@NotNull
@Override
public ConfigOptionsAdapter copyDefaults(boolean value) {
// we always copy new values
return this;
}
@NotNull
@Override
public ConfigOptionsAdapter pathSeparator(char value) {
(config.root).setPathSeparator(value);
return this;
}
@NotNull
@Override
public ConfigOptionsAdapter header(@Nullable String value) {
if (value == null) {
((Config) config.root).setHeader((List) null);
} else {
((Config) config.root).setHeader(value.split("\n"));
}
return this;
}
@NotNull
@Override
public ConfigOptionsAdapter copyHeader(boolean value) {
if (!value) {
((Config) config.root).setHeader((List) null);
}
return this;
}
public int indent() {
return config.root.getIndent();
}
@NotNull
public ConfigOptionsAdapter indent(int value) {
config.root.setIndent(value);
return this;
}
}

View File

@ -9,7 +9,6 @@ import java.util.List;
import java.util.logging.Level;
public class ConfigSetting {
final Config config;
final String key;
@ -21,12 +20,14 @@ public class ConfigSetting {
public ConfigSetting(@NotNull Config config, @NotNull String key, @NotNull Object defaultValue, String... comment) {
this.config = config;
this.key = key;
config.setDefault(key, defaultValue, comment);
}
public ConfigSetting(@NotNull Config config, @NotNull String key, @NotNull Object defaultValue, ConfigFormattingRules.CommentStyle commentStyle, String... comment) {
this.config = config;
this.key = key;
config.setDefault(key, defaultValue, commentStyle, comment);
}

View File

@ -1,35 +1,30 @@
package com.songoda.core.configuration;
import org.bukkit.configuration.ConfigurationSection;
public interface DataStoreObject<T> {
/**
* @return a unique hashable instance of T to store this value under
*/
public abstract T getKey();
/**
* @return a unique identifier for saving this value with
*/
public abstract String getConfigKey();
/**
* Save this data to a ConfigurationSection
*
* @param sec
*/
public abstract void saveToSection(ConfigurationSection sec);
/**
* @return true if this data has changed from the state saved to file
*/
public boolean hasChanged();
/**
* Mark this data as needing a save or not
*
* @param isChanged
*/
public void setChanged(boolean isChanged);
}
package com.songoda.core.configuration;
import org.bukkit.configuration.ConfigurationSection;
public interface DataStoreObject<T> {
/**
* @return a unique hashable instance of T to store this value under
*/
T getKey();
/**
* @return a unique identifier for saving this value with
*/
String getConfigKey();
/**
* Save this data to a ConfigurationSection
*/
void saveToSection(ConfigurationSection sec);
/**
* @return true if this data has changed from the state saved to file
*/
boolean hasChanged();
/**
* Mark this data as needing a save or not
*/
void setChanged(boolean isChanged);
}

View File

@ -21,16 +21,12 @@ import java.util.logging.Level;
* Used to easily store a set of one data value
*
* @param <T> DataObject class that is used to store the data
*
* @author jascotty2
* @since 2019-09-06
*/
public class SimpleDataStore<T extends DataStoreObject> {
protected final Plugin plugin;
protected final String filename, dirName;
private final Function<ConfigurationSection, T> getFromSection;
protected final HashMap<Object, T> data = new HashMap();
protected final HashMap<Object, T> data = new HashMap<>();
private File file;
private final Object lock = new Object();
SaveTask saveTask;
@ -63,6 +59,7 @@ public class SimpleDataStore<T extends DataStoreObject> {
this.file = new File(plugin.getDataFolder(), filename != null ? filename : "data.yml");
}
}
return file;
}
@ -99,10 +96,13 @@ public class SimpleDataStore<T extends DataStoreObject> {
@Nullable
public T remove(@NotNull Object key) {
T temp;
synchronized (lock) {
temp = data.remove(key);
}
save();
return temp;
}
@ -119,11 +119,15 @@ public class SimpleDataStore<T extends DataStoreObject> {
if (value == null) {
return null;
}
T temp;
synchronized (lock) {
temp = data.remove(value.getKey());
}
save();
return temp;
}
@ -141,11 +145,15 @@ public class SimpleDataStore<T extends DataStoreObject> {
if (value == null) {
return null;
}
T temp;
synchronized (lock) {
temp = data.put(value.getKey(), value);
}
save();
return temp;
}
@ -155,18 +163,19 @@ public class SimpleDataStore<T extends DataStoreObject> {
*
* @param value values to be added
*/
@Nullable
public void addAll(@NotNull T[] value) {
if (value == null) {
return;
}
synchronized (lock) {
for (int i = 0; i < value.length; ++i) {
if (value[i] != null) {
data.put(value[i].getKey(), value[i]);
for (T t : value) {
if (t != null) {
data.put(t.getKey(), t);
}
}
}
save();
}
@ -181,6 +190,7 @@ public class SimpleDataStore<T extends DataStoreObject> {
if (value == null) {
return;
}
synchronized (lock) {
for (T v : value) {
if (v != null) {
@ -188,6 +198,7 @@ public class SimpleDataStore<T extends DataStoreObject> {
}
}
}
save();
}
@ -198,6 +209,7 @@ public class SimpleDataStore<T extends DataStoreObject> {
if (!getFile().exists()) {
return;
}
try {
YamlConfiguration f = new YamlConfiguration();
f.options().pathSeparator('\0');
@ -205,9 +217,9 @@ public class SimpleDataStore<T extends DataStoreObject> {
synchronized (lock) {
data.clear();
f.getValues(false).entrySet().stream()
.filter(d -> d.getValue() instanceof ConfigurationSection)
.map(Map.Entry::getValue)
f.getValues(false).values().stream()
.filter(ConfigurationSection.class::isInstance)
.map(v -> getFromSection.apply((ConfigurationSection) v))
.forEach(v -> data.put(v.getKey(), v));
}
@ -221,7 +233,7 @@ public class SimpleDataStore<T extends DataStoreObject> {
* made
*/
public void saveChanges() {
if (saveTask != null || data.values().stream().anyMatch(v -> v.hasChanged())) {
if (saveTask != null || data.values().stream().anyMatch(DataStoreObject::hasChanged)) {
flushSave();
}
}
@ -248,20 +260,22 @@ public class SimpleDataStore<T extends DataStoreObject> {
saveTask = null;
autosaveTimer = null;
}
YamlConfiguration f = new YamlConfiguration();
synchronized (lock) {
data.values().stream().forEach(e -> e.saveToSection(f.createSection(e.getConfigKey())));
data.values().forEach(e -> e.saveToSection(f.createSection(e.getConfigKey())));
}
try {
f.save(getFile());
data.values().stream().forEach(e -> e.setChanged(false));
data.values().forEach(e -> e.setChanged(false));
} catch (IOException ex) {
plugin.getLogger().log(Level.SEVERE, "Failed to save data to " + file.getName(), ex);
}
}
class SaveTask extends TimerTask {
@Override
public void run() {
flushSave();

View File

@ -27,12 +27,8 @@ import java.util.logging.Level;
/**
* Edit a configuration file for a specific plugin
*
* @author jascotty2
* @since 2019-08-31
*/
public class ConfigEditorGui extends SimplePagedGui {
final JavaPlugin plugin;
final String file;
final MemoryConfiguration config;
@ -40,8 +36,8 @@ public class ConfigEditorGui extends SimplePagedGui {
final Player player;
Method configSection_getCommentString = null;
boolean edits = false;
List<String> sections = new ArrayList();
List<String> settings = new ArrayList();
List<String> sections = new ArrayList<>();
List<String> settings = new ArrayList<>();
protected ConfigEditorGui(Player player, JavaPlugin plugin, Gui parent, String file, MemoryConfiguration config) {
this(player, plugin, parent, file, config, config);
@ -49,6 +45,7 @@ public class ConfigEditorGui extends SimplePagedGui {
protected ConfigEditorGui(Player player, JavaPlugin plugin, Gui parent, String file, MemoryConfiguration config, ConfigurationSection node) {
super(parent);
this.player = player;
this.plugin = plugin;
this.file = file;
@ -65,7 +62,7 @@ public class ConfigEditorGui extends SimplePagedGui {
// if we have a ConfigSection, we can also grab comments
try {
configSection_getCommentString = node.getClass().getDeclaredMethod("getCommentString", String.class);
} catch (Exception ex) {
} catch (Exception ignore) {
}
// decorate header
@ -80,9 +77,10 @@ public class ConfigEditorGui extends SimplePagedGui {
for (String key : node.getKeys(false)) {
if (node.isConfigurationSection(key)) {
sections.add(key);
} else {
settings.add(key);
continue;
}
settings.add(key);
}
// next we need to display the config settings
@ -95,17 +93,21 @@ public class ConfigEditorGui extends SimplePagedGui {
// now display individual settings
for (final String settingKey : settings) {
final Object val = node.get(settingKey);
if (val == null) continue;
else if (val instanceof Boolean) {
if (val == null) {
continue;
}
if (val instanceof Boolean) {
// toggle switch
setButton(index, configItem(CompatibleMaterial.LEVER, ChatColor.YELLOW + settingKey, node, settingKey, String.valueOf((Boolean) val), "Click to toggle this setting"),
setButton(index, configItem(CompatibleMaterial.LEVER, ChatColor.YELLOW + settingKey, node, settingKey, String.valueOf(val), "Click to toggle this setting"),
(event) -> this.toggle(event.slot, settingKey));
if ((Boolean) val) {
highlightItem(index);
}
} else if (isNumber(val)) {
// number dial
this.setButton(index, configItem(CompatibleMaterial.CLOCK, ChatColor.YELLOW + settingKey, node, settingKey, String.valueOf((Number) val), "Click to edit this setting"),
this.setButton(index, configItem(CompatibleMaterial.CLOCK, ChatColor.YELLOW + settingKey, node, settingKey, String.valueOf(val), "Click to edit this setting"),
(event) -> {
event.gui.exit();
ChatPrompt.showPrompt(plugin, event.player, "Enter a new number value for " + settingKey + ":", response -> {
@ -151,17 +153,16 @@ public class ConfigEditorGui extends SimplePagedGui {
});
});
} else if (val instanceof List) {
setButton(index, configItem(CompatibleMaterial.WRITABLE_BOOK, ChatColor.YELLOW + settingKey, node, settingKey, String.format("(%d values)", ((List) val).size()), "Click to edit this setting"),
(event) -> {
event.manager.showGUI(event.player, (new ConfigEditorListEditorGui(this, settingKey, (List) val)).setOnClose((gui) -> {
if (((ConfigEditorListEditorGui) gui.gui).saveChanges) {
setList(event.slot, settingKey, ((ConfigEditorListEditorGui) gui.gui).values);
}
}));
});
} else {
setButton(index, configItem(CompatibleMaterial.WRITABLE_BOOK, ChatColor.YELLOW + settingKey, node, settingKey, String.format("(%d values)", ((List<?>) val).size()), "Click to edit this setting"),
(event) ->
event.manager.showGUI(event.player, (new ConfigEditorListEditorGui(this, settingKey, (List) val)).setOnClose((gui) -> {
if (((ConfigEditorListEditorGui) gui.gui).saveChanges) {
setList(event.slot, settingKey, ((ConfigEditorListEditorGui) gui.gui).values);
}
})));
} /* else {
// idk. should we display uneditable values?
}
} */
++index;
}
@ -173,16 +174,22 @@ public class ConfigEditorGui extends SimplePagedGui {
protected void updateValue(int clickCell, String path) {
ItemStack item = inventory.getItem(clickCell);
if (item == null || item == AIR) return;
if (item == null || item == AIR) {
return;
}
ItemMeta meta = item.getItemMeta();
Object val = node.get(path);
if (meta != null && val != null) {
String valStr;
if (val instanceof List) {
valStr = String.format("(%d values)", ((List) val).size());
valStr = String.format("(%d values)", ((List<?>) val).size());
} else {
valStr = val.toString();
}
List<String> lore = meta.getLore();
if (lore == null || lore.isEmpty()) {
meta.setLore(Arrays.asList(valStr));
@ -190,20 +197,24 @@ public class ConfigEditorGui extends SimplePagedGui {
lore.set(0, valStr);
meta.setLore(lore);
}
item.setItemMeta(meta);
setItem(clickCell, item);
}
edits = true;
}
void toggle(int clickCell, String path) {
boolean val = !node.getBoolean(path);
node.set(path, val);
if (val) {
setItem(clickCell, ItemUtils.addGlow(inventory.getItem(clickCell)));
} else {
setItem(clickCell, ItemUtils.removeGlow(inventory.getItem(clickCell)));
}
updateValue(clickCell, path);
}
@ -216,20 +227,24 @@ public class ConfigEditorGui extends SimplePagedGui {
} else if (node.isLong(path)) {
node.set(path, Long.parseLong(input));
}
updateValue(clickCell, path);
} catch (NumberFormatException e) {
} catch (NumberFormatException ex) {
return false;
}
return true;
}
void setMaterial(int clickCell, String path, ItemStack item) {
CompatibleMaterial mat = CompatibleMaterial.getMaterial(item);
if (mat == null) {
node.set(path, CompatibleMaterial.STONE.name());
} else {
node.set(path, mat.name());
}
updateValue(clickCell, path);
}
@ -242,6 +257,7 @@ public class ConfigEditorGui extends SimplePagedGui {
if (!edits) {
return;
}
// could also check and call saveChanges()
if (config instanceof FileConfiguration) {
try {
@ -257,50 +273,59 @@ public class ConfigEditorGui extends SimplePagedGui {
plugin.getLogger().log(Level.WARNING, "Unknown configuration type '" + config.getClass().getName() + "' - Please report this error!");
return;
}
plugin.reloadConfig();
player.sendMessage(ChatColor.GREEN + "Config " + file + " saved!");
}
private boolean isNumber(Object value) {
return value != null && (
value instanceof Long
|| value instanceof Integer
|| value instanceof Float
|| value instanceof Double);
return (value instanceof Long
|| value instanceof Integer
|| value instanceof Float
|| value instanceof Double);
}
private boolean isMaterial(Object value) {
CompatibleMaterial m;
return value instanceof String && value.toString().equals(value.toString().toUpperCase())
&& (m = CompatibleMaterial.getMaterial(value.toString())) != null && m.isValidItem();
}
protected ItemStack configItem(CompatibleMaterial type, String name, ConfigurationSection node, String path, String def) {
String[] info = null;
if (configSection_getCommentString != null) {
try {
Object comment = configSection_getCommentString.invoke(node, path);
if (comment != null) {
info = comment.toString().split("\n");
}
} catch (Exception ex) {
} catch (Exception ignore) {
}
}
return GuiUtils.createButtonItem(type, name, info != null ? info : (def != null ? def.split("\n") : null));
}
protected ItemStack configItem(CompatibleMaterial type, String name, ConfigurationSection node, String path, String value, String def) {
if (value == null) value = "";
if (value == null) {
value = "";
}
String[] info = null;
if (configSection_getCommentString != null) {
try {
Object comment = configSection_getCommentString.invoke(node, path);
if (comment != null) {
info = (value + "\n" + comment.toString()).split("\n");
info = (value + "\n" + comment).split("\n");
}
} catch (Exception ex) {
} catch (Exception ignore) {
}
}
return GuiUtils.createButtonItem(type, name, info != null ? info : (def != null ? (value + "\n" + def).split("\n") : null));
}
}

View File

@ -12,12 +12,8 @@ import java.util.List;
/**
* Edit a string list
*
* @author jascotty2
* @since 2019-08-31
*/
public class ConfigEditorListEditorGui extends SimplePagedGui {
final ConfigEditorGui current;
public boolean saveChanges = false;
@ -25,6 +21,7 @@ public class ConfigEditorListEditorGui extends SimplePagedGui {
public ConfigEditorListEditorGui(ConfigEditorGui current, String key, List<String> val) {
super(current);
this.current = current;
this.blankItem = current.getDefaultItem();
headerBackItem = footerBackItem = current.getHeaderBackItem();
@ -32,7 +29,7 @@ public class ConfigEditorListEditorGui extends SimplePagedGui {
this.setUseHeader(true);
this.setItem(4, current.configItem(CompatibleMaterial.FILLED_MAP, key, current.getCurrentNode(), key, null));
this.setButton(8, GuiUtils.createButtonItem(CompatibleMaterial.OAK_DOOR, "Exit"), (event) -> event.player.closeInventory());
this.values = new ArrayList(val);
this.values = new ArrayList<>(val);
this.setButton(8, GuiUtils.createButtonItem(CompatibleMaterial.LAVA_BUCKET, ChatColor.RED + "Discard Changes"), (event) -> event.player.closeInventory());
this.setButton(0, GuiUtils.createButtonItem(CompatibleMaterial.REDSTONE, ChatColor.GREEN + "Save"), (event) -> {
@ -45,9 +42,8 @@ public class ConfigEditorListEditorGui extends SimplePagedGui {
ChatPrompt.showPrompt(event.manager.getPlugin(), event.player, "Enter a new value to add:", response -> {
values.add(response.getMessage().trim());
redraw();
}).setOnClose(() -> {
event.manager.showGUI(event.player, this);
})
.setOnClose(() -> event.manager.showGUI(event.player, this))
.setOnCancel(() -> {
event.player.sendMessage(ChatColor.RED + "Edit canceled");
event.manager.showGUI(event.player, this);
@ -59,6 +55,7 @@ public class ConfigEditorListEditorGui extends SimplePagedGui {
void redraw() {
page = 1;
// clear old display
if (inventory != null) {
for (Integer i : cellItems.keySet().toArray(new Integer[0])) {
@ -78,6 +75,7 @@ public class ConfigEditorListEditorGui extends SimplePagedGui {
redraw();
});
}
// update display
update();
}

View File

@ -19,14 +19,10 @@ import java.util.Map;
/**
* Edit all configuration files for a specific plugin
*
* @author jascotty2
* @since 2019-08-31
*/
public class PluginConfigGui extends SimplePagedGui {
final JavaPlugin plugin;
LinkedHashMap<String, MemoryConfiguration> configs = new LinkedHashMap();
LinkedHashMap<String, MemoryConfiguration> configs = new LinkedHashMap<>();
public PluginConfigGui(SongodaPlugin plugin) {
this(plugin, null);
@ -34,6 +30,7 @@ public class PluginConfigGui extends SimplePagedGui {
public PluginConfigGui(SongodaPlugin plugin, Gui parent) {
super(parent);
this.plugin = plugin;
// collect list of plugins
@ -44,6 +41,7 @@ public class PluginConfigGui extends SimplePagedGui {
configs.put(cfg.getFile().getName(), cfg);
}
}
init();
}
@ -61,21 +59,22 @@ public class PluginConfigGui extends SimplePagedGui {
try {
// can we also grab extra config from this mysterious plugin?
Object more = plugin.getClass().getDeclaredMethod("getExtraConfig").invoke(plugin);
if (more != null && more instanceof List && !((List) more).isEmpty()) {
if (more instanceof List && !((List<?>) more).isEmpty()) {
try {
// if we have the getExtraConfig function, we should also be able to get the file
Method method_Config_getFile = ((List) more).get(0).getClass().getDeclaredMethod("getFile");
for (Object cfg : ((List) more)) {
Method method_Config_getFile = ((List<?>) more).get(0).getClass().getDeclaredMethod("getFile");
for (Object cfg : ((List<?>) more)) {
configs.put(((File) method_Config_getFile.invoke(cfg)).getName(), (MemoryConfiguration) cfg);
}
} catch (Exception ex) {
// include a failsafe, I guess
((List) more).forEach(cfg -> configs.put("(File " + configs.size() + ")", (MemoryConfiguration) cfg));
((List<?>) more).forEach(cfg -> configs.put("(File " + configs.size() + ")", (MemoryConfiguration) cfg));
}
}
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
// I guess not!
}
init();
}

View File

@ -6,19 +6,21 @@ import org.json.simple.JSONObject;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LocaleModule implements PluginInfoModule {
@Override
public void run(PluginInfo plugin) {
if (plugin.getJavaPlugin() == null || plugin.getSongodaId() <= 0) return;
JSONObject json = plugin.getJson();
if (plugin.getJavaPlugin() == null || plugin.getSongodaId() <= 0) {
return;
}
try {
JSONObject json = plugin.getJson();
JSONArray files = (JSONArray) json.get("neededFiles");
for (Object o : files) {
JSONObject file = (JSONObject) o;
@ -26,13 +28,14 @@ public class LocaleModule implements PluginInfoModule {
downloadLocale(plugin, (String) file.get("link"), (String) file.get("name"));
}
}
} catch (IOException e) {
Logger.getLogger(LocaleModule.class.getName()).log(Level.INFO, "Failed to check for locale files: " + e.getMessage());
} catch (IOException ex) {
Logger.getLogger(LocaleModule.class.getName()).log(Level.INFO, "Failed to check for locale files: " + ex.getMessage());
}
}
void downloadLocale(PluginInfo plugin, String link, String fileName) throws MalformedURLException, IOException {
void downloadLocale(PluginInfo plugin, String link, String fileName) throws IOException {
URL url = new URL(link);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
urlConnection.setRequestProperty("Accept", "*/*");

View File

@ -9,7 +9,6 @@ import java.util.Collections;
import java.util.List;
public final class PluginInfo {
protected final JavaPlugin javaPlugin;
protected final int songodaId;
protected final String coreIcon;
@ -37,6 +36,7 @@ public final class PluginInfo {
public void setLatestVersion(String latestVersion) {
this.latestVersion = latestVersion;
hasUpdate = latestVersion != null && !latestVersion.isEmpty() && !javaPlugin.getDescription().getVersion().equalsIgnoreCase(latestVersion);
}
@ -82,6 +82,7 @@ public final class PluginInfo {
public PluginInfoModule addModule(PluginInfoModule module) {
modules.add(module);
return module;
}

View File

@ -1,6 +1,5 @@
package com.songoda.core.core;
public interface PluginInfoModule {
void run(PluginInfo plugin);
}

View File

@ -9,7 +9,6 @@ import org.bukkit.entity.Player;
import java.util.List;
public class SongodaCoreCommand extends AbstractCommand {
protected GuiManager guiManager;
public SongodaCoreCommand() {
@ -22,10 +21,12 @@ public class SongodaCoreCommand extends AbstractCommand {
if (guiManager == null || guiManager.isClosed()) {
guiManager = new GuiManager(SongodaCore.getHijackedPlugin());
}
guiManager.showGUI((Player) sender, new SongodaCoreOverviewGUI());
} else {
sender.sendMessage("/songoda diag");
}
return ReturnType.SUCCESS;
}

View File

@ -14,7 +14,6 @@ import java.text.DecimalFormat;
import java.util.List;
public class SongodaCoreDiagCommand extends AbstractCommand {
private final DecimalFormat format = new DecimalFormat("##.##");
private Object serverInstance;
@ -27,36 +26,38 @@ public class SongodaCoreDiagCommand extends AbstractCommand {
serverInstance = ClassMapping.MINECRAFT_SERVER.getClazz().getMethod("getServer").invoke(null);
tpsField = serverInstance.getClass().getField("recentTps");
} catch (NoSuchFieldException | SecurityException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
| InvocationTargetException | NoSuchMethodException ex) {
ex.printStackTrace();
}
}
@Override
protected ReturnType runCommand(CommandSender sender, String... args) {
sender.sendMessage("");
sender.sendMessage("Songoda Diagnostics Information");
sender.sendMessage("");
sender.sendMessage("Plugins:");
for (PluginInfo plugin : SongodaCore.getPlugins()) {
sender.sendMessage(plugin.getJavaPlugin().getName()
+ " (" + plugin.getJavaPlugin().getDescription().getVersion() + " Core " + plugin.getCoreLibraryVersion() + ")");
}
sender.sendMessage("");
sender.sendMessage("Server Version: " + Bukkit.getVersion());
sender.sendMessage("NMS: " + ServerProject.getServerVersion() + " " + ServerVersion.getServerVersionString());
sender.sendMessage("Operating System: " + System.getProperty("os.name"));
sender.sendMessage("Allocated Memory: " + format.format(Runtime.getRuntime().maxMemory() / (1024 * 1024)) + "Mb");
sender.sendMessage("Online Players: " + Bukkit.getOnlinePlayers().size());
if (tpsField != null) {
try {
double[] tps = ((double[]) tpsField.get(serverInstance));
sender.sendMessage("TPS from last 1m, 5m, 15m: " + format.format(tps[0]) + ", "
+ format.format(tps[1]) + ", " + format.format(tps[2]));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}

View File

@ -11,7 +11,6 @@ import org.bukkit.event.inventory.ClickType;
import java.util.List;
final class SongodaCoreOverviewGUI extends Gui {
protected SongodaCoreOverviewGUI() {
List<PluginInfo> plugins = SongodaCore.getPlugins();
// could do pages, too, but don't think we'll have that many at a time for a while
@ -23,6 +22,7 @@ final class SongodaCoreOverviewGUI extends Gui {
for (int i = 0; i < plugins.size(); i++) {
final PluginInfo plugin = plugins.get(i);
if (plugin.hasUpdate()) {
setButton(i, GuiUtils.createButtonItem(plugin.icon != null ? plugin.icon : CompatibleMaterial.STONE,
ChatColor.GOLD + plugin.getJavaPlugin().getName(),
@ -38,17 +38,19 @@ final class SongodaCoreOverviewGUI extends Gui {
ClickType.LEFT, (event) -> event.player.sendMessage(plugin.getMarketplaceLink()));
setAction(i, ClickType.RIGHT, (event) -> event.manager.showGUI(event.player, new PluginConfigGui(plugin.getJavaPlugin(), event.gui)));
highlightItem(i);
} else {
setButton(i, GuiUtils.createButtonItem(plugin.icon != null ? plugin.icon : CompatibleMaterial.STONE,
ChatColor.GOLD + plugin.getJavaPlugin().getName(),
ChatColor.GRAY + "Installed Version: " + plugin.getJavaPlugin().getDescription().getVersion(),
"",
ChatColor.GOLD + "Click for the marketplace page link.",
ChatColor.GOLD + "Right Click to edit plugin settings."
),
ClickType.LEFT, (event) -> event.player.sendMessage(plugin.getMarketplaceLink()));
setAction(i, ClickType.RIGHT, (event) -> event.manager.showGUI(event.player, new PluginConfigGui(plugin.getJavaPlugin(), event.gui)));
continue;
}
setButton(i, GuiUtils.createButtonItem(plugin.icon != null ? plugin.icon : CompatibleMaterial.STONE,
ChatColor.GOLD + plugin.getJavaPlugin().getName(),
ChatColor.GRAY + "Installed Version: " + plugin.getJavaPlugin().getDescription().getVersion(),
"",
ChatColor.GOLD + "Click for the marketplace page link.",
ChatColor.GOLD + "Right Click to edit plugin settings."
),
ClickType.LEFT, (event) -> event.player.sendMessage(plugin.getMarketplaceLink()));
setAction(i, ClickType.RIGHT, (event) -> event.manager.showGUI(event.player, new PluginConfigGui(plugin.getJavaPlugin(), event.gui)));
}
}
}

View File

@ -64,9 +64,10 @@ public class DataManagerAbstract {
ResultSet result = statement.executeQuery(query);
result.next();
id = result.getInt(1);
} catch (SQLException e) {
e.printStackTrace();
} catch (SQLException ex) {
ex.printStackTrace();
}
return id;
}
@ -143,24 +144,31 @@ public class DataManagerAbstract {
}
/**
* Queue tasks to be ran asynchronously.
* Queue tasks to be run asynchronously.
*
* @param runnable task to put into queue.
* @param queueKey the queue key to add the runnable to.
*/
@Deprecated
public void queueAsync(Runnable runnable, String queueKey) {
if (queueKey == null) return;
if (queueKey == null) {
return;
}
List<Runnable> queue = queues.computeIfAbsent(queueKey, t -> new LinkedList<>());
queue.add(runnable);
if (queue.size() == 1) runQueue(queueKey);
if (queue.size() == 1) {
runQueue(queueKey);
}
}
@Deprecated
private void runQueue(String queueKey) {
doQueue(queueKey, (s) -> {
if (!queues.get(queueKey).isEmpty())
if (!queues.get(queueKey).isEmpty()) {
runQueue(queueKey);
}
});
}

View File

@ -4,7 +4,6 @@ import java.sql.Connection;
import java.sql.SQLException;
public abstract class DataMigration {
private final int revision;
public DataMigration(int revision) {

View File

@ -8,7 +8,6 @@ import java.util.List;
import java.util.stream.Collectors;
public class DataMigrationManager {
private final List<DataMigration> migrations;
private final DatabaseConnector databaseConnector;
private final DataManagerAbstract dataManagerAbstract;
@ -65,23 +64,23 @@ public class DataMigrationManager {
// Grab required migrations
int finalCurrentMigration = currentMigration;
List<DataMigration> requiredMigrations = this.migrations
.stream()
List<DataMigration> requiredMigrations = this.migrations.stream()
.filter(x -> x.getRevision() > finalCurrentMigration)
.sorted(Comparator.comparingInt(DataMigration::getRevision))
.collect(Collectors.toList());
// Nothing to migrate, abort
if (requiredMigrations.isEmpty())
if (requiredMigrations.isEmpty()) {
return;
}
// Migrate the data
for (DataMigration dataMigration : requiredMigrations)
for (DataMigration dataMigration : requiredMigrations) {
dataMigration.migrate(connection, this.dataManagerAbstract.getTablePrefix());
}
// Set the new current migration to be the highest migrated to
currentMigration = requiredMigrations
.stream()
currentMigration = requiredMigrations.stream()
.map(DataMigration::getRevision)
.max(Integer::compareTo)
.orElse(-1);

View File

@ -4,7 +4,6 @@ import java.sql.Connection;
import java.sql.SQLException;
public interface DatabaseConnector {
/**
* Checks if the connection to the database has been created
*

View File

@ -1,6 +1,5 @@
package com.songoda.core.database;
import com.songoda.core.SongodaCore;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.bukkit.plugin.Plugin;
@ -9,7 +8,6 @@ import java.sql.Connection;
import java.sql.SQLException;
public class MySQLConnector implements DatabaseConnector {
private final Plugin plugin;
private HikariDataSource hikari;
private boolean initializedSuccessfully;

View File

@ -8,7 +8,6 @@ import java.sql.DriverManager;
import java.sql.SQLException;
public class SQLiteConnector implements DatabaseConnector {
private final Plugin plugin;
private final String connectionString;
private Connection connection;
@ -19,8 +18,8 @@ public class SQLiteConnector implements DatabaseConnector {
try {
Class.forName("org.sqlite.JDBC"); // This is required to put here for Spigot 1.10 and below to force class load
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}

View File

@ -1,128 +1,140 @@
package com.songoda.core.gui;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.gui.methods.Clickable;
import com.songoda.core.nms.NmsManager;
import com.songoda.core.nms.anvil.AnvilCore;
import com.songoda.core.nms.anvil.CustomAnvil;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
/**
* Anvil GUI for text prompts
*
* @author jascotty2
* @since 2019-09-15
*/
public class AnvilGui extends Gui {
final Player player;
CustomAnvil anvil;
List<String> endPrompt = null;
public AnvilGui(Player player) {
this.player = player;
}
public AnvilGui(Player player, Gui parent) {
super(parent);
this.player = player;
}
@NotNull
public AnvilGui setAction(@Nullable Clickable action) {
return (AnvilGui) setAction(2, action);
}
@NotNull
public AnvilGui setAction(@Nullable ClickType type, @Nullable Clickable action) {
return (AnvilGui) setAction(2, type, action);
}
protected void open() {
anvil.open();
}
public AnvilGui setInput(ItemStack item) {
return (AnvilGui) this.setItem(0, item);
}
public ItemStack getInput() {
return this.getItem(0);
}
public AnvilGui setOutput(ItemStack item) {
return (AnvilGui) this.setItem(2, item);
}
public AnvilGui setOutputPrompt(String str) {
endPrompt = Arrays.asList(str);
return this;
}
public AnvilGui setOutputPrompt(String... str) {
endPrompt = Arrays.asList(str);
return this;
}
public AnvilGui setOutputPrompt(List<String> str) {
endPrompt = str;
return this;
}
void updateOutputPrompt() {
final ItemStack in;
if (endPrompt != null && (in = cellItems.get(0)) != null) {
setItem(2, GuiUtils.createButtonItem(in, endPrompt));
}
}
public ItemStack getOutput() {
return this.getItem(2);
}
public String getInputText() {
return anvil != null ? anvil.getRenameText() : null;
}
@NotNull
@Override
protected Inventory generateInventory(@NotNull GuiManager manager) {
this.guiManager = manager;
createInventory();
ItemStack item;
if ((item = cellItems.get(0)) != null) {
inventory.setItem(0, item);
} else if ((item = cellItems.get(1)) != null) {
inventory.setItem(1, item);
} else if (!acceptsItems) {
cellItems.put(0, item = GuiUtils.createButtonItem(CompatibleMaterial.PAPER, " ", " "));
inventory.setItem(0, item);
}
if ((item = cellItems.get(2)) != null) {
inventory.setItem(2, item);
}
return inventory;
}
@Override
protected void createInventory() {
AnvilCore nms = NmsManager.getAnvil();
if (nms != null) {
anvil = nms.createAnvil(player, new GuiHolder(guiManager, this));
anvil.setCustomTitle(title);
anvil.setLevelCost(0);
inventory = anvil.getInventory();
anvil.setOnChange(this::updateOutputPrompt);
}
}
}
package com.songoda.core.gui;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.gui.methods.Clickable;
import com.songoda.core.nms.NmsManager;
import com.songoda.core.nms.anvil.AnvilCore;
import com.songoda.core.nms.anvil.CustomAnvil;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
/**
* Anvil GUI for text prompts
*/
public class AnvilGui extends Gui {
final Player player;
CustomAnvil anvil;
List<String> endPrompt = null;
public AnvilGui(Player player) {
this.player = player;
}
public AnvilGui(Player player, Gui parent) {
super(parent);
this.player = player;
}
@NotNull
public AnvilGui setAction(@Nullable Clickable action) {
return (AnvilGui) setAction(2, action);
}
@NotNull
public AnvilGui setAction(@Nullable ClickType type, @Nullable Clickable action) {
return (AnvilGui) setAction(2, type, action);
}
protected void open() {
anvil.open();
}
public AnvilGui setInput(ItemStack item) {
return (AnvilGui) this.setItem(0, item);
}
public ItemStack getInput() {
return this.getItem(0);
}
public AnvilGui setOutput(ItemStack item) {
return (AnvilGui) this.setItem(2, item);
}
public AnvilGui setOutputPrompt(String str) {
endPrompt = Arrays.asList(str);
return this;
}
public AnvilGui setOutputPrompt(String... str) {
endPrompt = Arrays.asList(str);
return this;
}
public AnvilGui setOutputPrompt(List<String> str) {
endPrompt = str;
return this;
}
void updateOutputPrompt() {
if (endPrompt != null) {
ItemStack in = cellItems.get(0);
if (in != null) {
setItem(2, GuiUtils.createButtonItem(in, endPrompt));
}
}
}
public ItemStack getOutput() {
return this.getItem(2);
}
public String getInputText() {
return anvil != null ? anvil.getRenameText() : null;
}
@NotNull
@Override
protected Inventory generateInventory(@NotNull GuiManager manager) {
this.guiManager = manager;
createInventory();
ItemStack item;
if (cellItems.containsKey(0)) {
item = cellItems.get(0);
inventory.setItem(0, item);
} else if (cellItems.containsKey(1)) {
item = cellItems.get(1);
inventory.setItem(1, item);
} else if (!acceptsItems) {
item = GuiUtils.createButtonItem(CompatibleMaterial.PAPER, " ", " ");
cellItems.put(0, item);
inventory.setItem(0, item);
}
if (cellItems.containsKey(2)) {
item = cellItems.get(2);
inventory.setItem(2, item);
}
return inventory;
}
@Override
protected void createInventory() {
AnvilCore nms = NmsManager.getAnvil();
if (nms != null) {
anvil = nms.createAnvil(player, new GuiHolder(guiManager, this));
anvil.setCustomTitle(title);
anvil.setLevelCost(0);
inventory = anvil.getInventory();
anvil.setOnChange(this::updateOutputPrompt);
}
}
}

View File

@ -7,7 +7,7 @@ public enum BackgroundType {
ADVENTURE, END, HUSBANDRY, NETHER, STONE;
final String key;
private BackgroundType() {
BackgroundType() {
this.key = "minecraft:textures/gui/advancements/backgrounds/" + name().toLowerCase() + ".png";
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -33,12 +33,8 @@ import java.util.stream.Collectors;
/**
* TODO: animated buttons
*
* @author jascotty2
* @since 2019-08-25
*/
public class Gui {
protected Inventory inventory;
protected String title;
protected GuiType inventoryType = GuiType.STANDARD;
@ -72,6 +68,7 @@ public class Gui {
public Gui(@NotNull GuiType type) {
this.inventoryType = type;
switch (type) {
case HOPPER:
case DISPENSER:
@ -79,6 +76,7 @@ public class Gui {
break;
default:
this.rows = 3;
break;
}
}
@ -97,10 +95,13 @@ public class Gui {
@NotNull
public List<Player> getPlayers() {
return inventory == null ? Collections.EMPTY_LIST
: inventory.getViewers().stream()
.filter(e -> e instanceof Player)
.map(e -> (Player) e)
if (inventory == null) {
return Collections.emptyList();
}
return inventory.getViewers().stream()
.filter(Player.class::isInstance)
.map(Player.class::cast)
.collect(Collectors.toList());
}
@ -109,6 +110,7 @@ public class Gui {
if (inventory != null && inventory.getViewers().isEmpty()) {
open = false;
}
return open;
}
@ -154,9 +156,10 @@ public class Gui {
public void exit() {
allowClose = true;
open = false;
inventory.getViewers().stream()
.filter(e -> e instanceof Player)
.map(e -> (Player) e)
.filter(Player.class::isInstance)
.map(Player.class::cast)
.collect(Collectors.toList())
.forEach(Player::closeInventory);
}
@ -166,9 +169,10 @@ public class Gui {
*/
public void close() {
allowClose = true;
inventory.getViewers().stream()
.filter(e -> e instanceof Player)
.map(e -> (Player) e)
.filter(Player.class::isInstance)
.map(Player.class::cast)
.collect(Collectors.toList())
.forEach(Player::closeInventory);
}
@ -188,6 +192,7 @@ public class Gui {
public Gui setUnlocked(int row, int col) {
final int cell = col + row * inventoryType.columns;
unlockedCells.put(cell, true);
return this;
}
@ -196,6 +201,7 @@ public class Gui {
for (int cell = cellFirst; cell <= cellLast; ++cell) {
unlockedCells.put(cell, true);
}
return this;
}
@ -204,24 +210,29 @@ public class Gui {
for (int cell = cellFirst; cell <= cellLast; ++cell) {
unlockedCells.put(cell, open);
}
return this;
}
@NotNull
public Gui setUnlockedRange(int cellRowFirst, int cellColFirst, int cellRowLast, int cellColLast) {
final int last = cellColLast + cellRowLast * inventoryType.columns;
for (int cell = cellColFirst + cellRowFirst * inventoryType.columns; cell <= last; ++cell) {
unlockedCells.put(cell, true);
}
return this;
}
@NotNull
public Gui setUnlockedRange(int cellRowFirst, int cellColFirst, int cellRowLast, int cellColLast, boolean open) {
final int last = cellColLast + cellRowLast * inventoryType.columns;
for (int cell = cellColFirst + cellRowFirst * inventoryType.columns; cell <= last; ++cell) {
unlockedCells.put(cell, open);
}
return this;
}
@ -235,26 +246,35 @@ public class Gui {
public Gui setUnlocked(int row, int col, boolean open) {
final int cell = col + row * inventoryType.columns;
unlockedCells.put(cell, open);
return this;
}
@NotNull
public Gui setTitle(String title) {
if (title == null) title = "";
if (title == null) {
title = "";
}
if (!title.equals(this.title)) {
this.title = title;
if (inventory != null) {
// update active inventory
List<Player> toUpdate = getPlayers();
boolean isAllowClose = allowClose;
exit();
Inventory oldInv = inventory;
createInventory();
inventory.setContents(oldInv.getContents());
toUpdate.forEach(player -> player.openInventory(inventory));
allowClose = isAllowClose;
}
}
return this;
}
@ -270,7 +290,9 @@ public class Gui {
break;
default:
this.rows = Math.max(1, Math.min(6, rows));
break;
}
return this;
}
@ -302,24 +324,29 @@ public class Gui {
if (inventory != null && unlockedCells.getOrDefault(cell, false)) {
return inventory.getItem(cell);
}
return cellItems.get(cell);
}
@Nullable
public ItemStack getItem(int row, int col) {
final int cell = col + row * inventoryType.columns;
if (inventory != null && unlockedCells.getOrDefault(cell, false)) {
return inventory.getItem(cell);
}
return cellItems.get(cell);
}
@NotNull
public Gui setItem(int cell, @Nullable ItemStack item) {
cellItems.put(cell, item);
if (inventory != null && cell >= 0 && cell < inventory.getSize()) {
inventory.setItem(cell, item);
}
return this;
}
@ -332,36 +359,48 @@ public class Gui {
@NotNull
public Gui mirrorFill(int row, int col, boolean mirrorRow, boolean mirrorCol, ItemStack item) {
setItem(row, col, item);
if (mirrorRow)
if (mirrorRow) {
setItem(rows - row - 1, col, item);
if (mirrorCol)
}
if (mirrorCol) {
setItem(row, 8 - col, item);
if (mirrorRow && mirrorCol)
}
if (mirrorRow && mirrorCol) {
setItem(rows - row - 1, 8 - col, item);
}
return this;
}
@NotNull
public Gui highlightItem(int cell) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, ItemUtils.addGlow(item));
}
return this;
}
@NotNull
public Gui highlightItem(int row, int col) {
final int cell = col + row * inventoryType.columns;
return highlightItem(cell);
}
@NotNull
public Gui removeHighlight(int cell) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, ItemUtils.removeGlow(item));
}
return this;
}
@ -379,9 +418,11 @@ public class Gui {
@NotNull
public Gui updateItemLore(int cell, @NotNull String... lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItemLore(item, lore));
}
return this;
}
@ -393,9 +434,11 @@ public class Gui {
@NotNull
public Gui updateItemLore(int cell, @Nullable List<String> lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItemLore(item, lore));
}
return this;
}
@ -407,9 +450,11 @@ public class Gui {
@NotNull
public Gui updateItemName(int cell, @Nullable String name) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItemName(item, name));
}
return this;
}
@ -431,9 +476,11 @@ public class Gui {
@NotNull
public Gui updateItem(int cell, @NotNull String name, @Nullable List<String> lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, name, lore));
}
return this;
}
@ -445,9 +492,11 @@ public class Gui {
@NotNull
public Gui updateItem(int cell, @NotNull ItemStack itemTo, @Nullable String title, @NotNull String... lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, itemTo, title, lore));
}
return this;
}
@ -459,9 +508,11 @@ public class Gui {
@NotNull
public Gui updateItem(int cell, @NotNull CompatibleMaterial itemTo, @Nullable String title, @Nullable String... lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, itemTo, title, lore));
}
return this;
}
@ -473,9 +524,11 @@ public class Gui {
@NotNull
public Gui updateItem(int cell, @NotNull ItemStack itemTo, @Nullable String title, @Nullable List<String> lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, itemTo, title, lore));
}
return this;
}
@ -487,9 +540,11 @@ public class Gui {
@NotNull
public Gui updateItem(int cell, @NotNull CompatibleMaterial itemTo, @Nullable String title, @Nullable List<String> lore) {
ItemStack item = cellItems.get(cell);
if (item != null && item.getType() != Material.AIR) {
setItem(cell, GuiUtils.updateItem(item, itemTo, title, lore));
}
return this;
}
@ -522,15 +577,18 @@ public class Gui {
for (int cell = cellFirst; cell <= cellLast; ++cell) {
setConditional(cell, null, action);
}
return this;
}
@NotNull
public Gui setActionForRange(int cellRowFirst, int cellColFirst, int cellRowLast, int cellColLast, @Nullable Clickable action) {
final int last = cellColLast + cellRowLast * inventoryType.columns;
for (int cell = cellColFirst + cellRowFirst * inventoryType.columns; cell <= last; ++cell) {
setConditional(cell, null, action);
}
return this;
}
@ -539,15 +597,18 @@ public class Gui {
for (int cell = cellFirst; cell <= cellLast; ++cell) {
setConditional(cell, type, action);
}
return this;
}
@NotNull
public Gui setActionForRange(int cellRowFirst, int cellColFirst, int cellRowLast, int cellColLast, @Nullable ClickType type, @Nullable Clickable action) {
final int last = cellColLast + cellRowLast * inventoryType.columns;
for (int cell = cellColFirst + cellRowFirst * inventoryType.columns; cell <= last; ++cell) {
setConditional(cell, type, action);
}
return this;
}
@ -566,14 +627,17 @@ public class Gui {
public Gui setButton(int cell, ItemStack item, @Nullable Clickable action) {
setItem(cell, item);
setConditional(cell, null, action);
return this;
}
@NotNull
public Gui setButton(int row, int col, @Nullable ItemStack item, @Nullable Clickable action) {
final int cell = col + row * inventoryType.columns;
setItem(cell, item);
setConditional(cell, null, action);
return this;
}
@ -581,19 +645,22 @@ public class Gui {
public Gui setButton(int cell, @Nullable ItemStack item, @Nullable ClickType type, @Nullable Clickable action) {
setItem(cell, item);
setConditional(cell, type, action);
return this;
}
@NotNull
public Gui setButton(int row, int col, @Nullable ItemStack item, @Nullable ClickType type, @Nullable Clickable action) {
final int cell = col + row * inventoryType.columns;
setItem(cell, item);
setConditional(cell, type, action);
return this;
}
protected void setConditional(int cell, @Nullable ClickType type, @Nullable Clickable action) {
Map<ClickType, Clickable> conditionals = conditionalButtons.computeIfAbsent(cell, k -> new HashMap());
Map<ClickType, Clickable> conditionals = conditionalButtons.computeIfAbsent(cell, k -> new HashMap<>());
conditionals.put(type, action);
}
@ -632,8 +699,9 @@ public class Gui {
}
public void reset() {
if (inventory != null)
if (inventory != null) {
inventory.clear();
}
setActionForRange(0, 53, null);
cellItems.clear();
@ -645,9 +713,11 @@ public class Gui {
nextPageItem = cellItems.get(cell);
nextPageIndex = cell;
nextPage = item;
if (page < pages) {
setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage());
}
return this;
}
@ -661,9 +731,11 @@ public class Gui {
prevPageItem = cellItems.get(cell);
prevPageIndex = cell;
prevPage = item;
if (page > 1) {
setButton(prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage());
}
return this;
}
@ -674,6 +746,7 @@ public class Gui {
public void setPages(int pages) {
this.pages = Math.max(1, pages);
if (page > pages) {
setPage(pages);
}
@ -682,8 +755,10 @@ public class Gui {
public void setPage(int page) {
int lastPage = this.page;
this.page = Math.max(1, Math.min(pages, page));
if (pager != null && this.page != lastPage) {
pager.onPageChange(new GuiPageEvent(this, guiManager, lastPage, page));
// page markers
updatePageNavigation();
}
@ -692,8 +767,10 @@ public class Gui {
public void changePage(int direction) {
int lastPage = page;
this.page = Math.max(1, Math.min(pages, page + direction));
if (pager != null && this.page != lastPage) {
pager.onPageChange(new GuiPageEvent(this, guiManager, lastPage, page));
// page markers
updatePageNavigation();
}
@ -703,6 +780,7 @@ public class Gui {
if (page < pages) {
int lastPage = page;
++page;
// page switch events
if (pager != null) {
pager.onPageChange(new GuiPageEvent(this, guiManager, lastPage, page));
@ -721,6 +799,7 @@ public class Gui {
if (page > 1) {
int lastPage = page;
--page;
if (pager != null) {
pager.onPageChange(new GuiPageEvent(this, guiManager, lastPage, page));
@ -743,6 +822,7 @@ public class Gui {
this.clearActions(prevPageIndex);
}
}
if (nextPage != null) {
if (pages > 1 && page != pages) {
this.setButton(nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage());
@ -764,6 +844,7 @@ public class Gui {
final int cells = rows * inventoryType.columns;
createInventory();
for (int i = 0; i < cells; ++i) {
final ItemStack item = cellItems.get(i);
inventory.setItem(i, item != null ? item : (unlockedCells.getOrDefault(i, false) ? AIR : blankItem));
@ -784,6 +865,7 @@ public class Gui {
default:
inventory = new GuiHolder(guiManager, this).newInventory(rows * 9,
title == null ? "" : trimTitle(title));
break;
}
}
@ -793,8 +875,9 @@ public class Gui {
}
public void update() {
if (inventory == null)
if (inventory == null) {
return;
}
final int cells = rows * inventoryType.columns;
for (int i = 0; i < cells; ++i) {
@ -806,9 +889,12 @@ public class Gui {
protected static String trimTitle(String title) {
if (title == null) {
return "";
} else if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8) && title.length() > 32) {
}
if (ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_8) && title.length() > 32) {
return title.charAt(30) == '\u00A7' ? title.substring(0, 30) : title.substring(0, 31);
}
return title;
}
@ -819,6 +905,7 @@ public class Gui {
protected boolean onClick(@NotNull GuiManager manager, @NotNull Player player, @NotNull Inventory inventory, @NotNull InventoryClickEvent event) {
final int cell = event.getSlot();
Map<ClickType, Clickable> conditionals = conditionalButtons.get(cell);
Clickable button;
if (conditionals != null
&& ((button = conditionals.get(event.getClick())) != null || (button = conditionals.get(null)) != null)) {
@ -829,12 +916,15 @@ public class Gui {
// this is a default action, not a triggered action
defaultClicker.onClick(new GuiClickEvent(manager, this, player, event, cell, true));
}
if (privateDefaultClicker != null) {
// this is a private default action, not a triggered action
privateDefaultClicker.onClick(new GuiClickEvent(manager, this, player, event, cell, true));
}
return false;
}
return true;
}
@ -846,6 +936,7 @@ public class Gui {
public void onOpen(@NotNull GuiManager manager, @NotNull Player player) {
open = true;
guiManager = manager;
if (opener != null) {
opener.onOpen(new GuiOpenEvent(manager, this, player));
}
@ -856,10 +947,13 @@ public class Gui {
manager.showGUI(player, this);
return;
}
boolean showParent = open && parent != null;
if (closer != null) {
closer.onClose(new GuiCloseEvent(manager, this, player));
}
if (showParent) {
manager.showGUI(player, parent);
}

View File

@ -1,40 +1,36 @@
package com.songoda.core.gui;
import org.bukkit.Bukkit;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
/**
* Internal class for marking an inventory as a GUI inventory
*
* @author jascotty2
* @since 2019-08-25
*/
class GuiHolder implements InventoryHolder {
final Gui gui;
final GuiManager manager;
public GuiHolder(GuiManager manager, Gui gui) {
this.gui = gui;
this.manager = manager;
}
@Override
public Inventory getInventory() {
return gui.inventory;
}
public Gui getGUI() {
return gui;
}
public Inventory newInventory(int size, String title) {
return Bukkit.createInventory(this, size, title);
}
public Inventory newInventory(InventoryType type, String title) {
return Bukkit.createInventory(this, type, title);
}
}
package com.songoda.core.gui;
import org.bukkit.Bukkit;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
/**
* Internal class for marking an inventory as a GUI inventory
*/
class GuiHolder implements InventoryHolder {
final Gui gui;
final GuiManager manager;
public GuiHolder(GuiManager manager, Gui gui) {
this.gui = gui;
this.manager = manager;
}
@Override
public Inventory getInventory() {
return gui.inventory;
}
public Gui getGUI() {
return gui;
}
public Inventory newInventory(int size, String title) {
return Bukkit.createInventory(this, size, title);
}
public Inventory newInventory(InventoryType type, String title) {
return Bukkit.createInventory(this, type, title);
}
}

View File

@ -1,275 +1,300 @@
package com.songoda.core.gui;
import com.songoda.core.compatibility.ClientVersion;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.compatibility.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* Manages events for GUI screens
*
* @author jascotty2
* @since 2019-08-25
*/
public class GuiManager {
final Plugin plugin;
final UUID uuid = UUID.randomUUID(); // manager tracking to fix weird bugs from lazy programming
final GuiListener listener = new GuiListener(this);
final Map<Player, Gui> openInventories = new HashMap();
private final Object lock = new Object();
private boolean initialized = false;
private boolean shutdown = false;
public GuiManager(Plugin plugin) {
this.plugin = plugin;
}
public Plugin getPlugin() {
return plugin;
}
/**
* Initialize the GUI handlers
*/
public void init() {
Bukkit.getPluginManager().registerEvents(listener, plugin);
initialized = true;
shutdown = false;
}
/**
* Check to see if this manager cannot open any more GUI screens
*
* @return true if the owning plugin has shutdown
*/
public boolean isClosed() {
return shutdown;
}
/**
* Create and display a GUI interface for a player
*
* @param player player to open the interface for
* @param gui GUI to use
*/
public void showGUI(Player player, Gui gui) {
if (shutdown) {
if (plugin.isEnabled()) {
// recover if reloaded without calling init manually
init();
} else {
return;
}
} else if (!initialized) {
init();
}
if (gui instanceof AnvilGui) {
// bukkit throws a fit now if you try to set anvil stuff asynchronously
Gui openInv = openInventories.get(player);
if (openInv != null) {
openInv.open = false;
}
gui.getOrCreateInventory(this);
((AnvilGui) gui).open();
gui.onOpen(this, player);
synchronized (lock) {
openInventories.put(player, gui);
}
} else {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
Gui openInv = openInventories.get(player);
if (openInv != null) {
openInv.open = false;
}
Inventory inv = gui.getOrCreateInventory(this);
Bukkit.getScheduler().runTask(plugin, () -> {
player.openInventory(inv);
gui.onOpen(this, player);
synchronized (lock) {
openInventories.put(player, gui);
}
});
});
}
}
public void showPopup(Player player, String message) {
showPopup(player, message, CompatibleMaterial.NETHER_STAR, BackgroundType.ADVENTURE);
}
public void showPopup(Player player, String message, CompatibleMaterial icon) {
showPopup(player, message, icon, BackgroundType.ADVENTURE);
}
public void showPopup(Player player, String message, CompatibleMaterial icon, BackgroundType background) {
if (ClientVersion.getClientVersion(player).isAtLeast(ServerVersion.V1_12)) {
PopupMessage popup = new PopupMessage(plugin, icon, message, background);
popup.add();
popup.grant(player);
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> {
popup.revoke(player);
popup.remove();
}, 70);
} else if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) {
player.sendTitle("", message, 10, 70, 10);
} else {
player.sendTitle("", message);
}
}
/**
* Close all active GUIs
*/
public void closeAll() {
synchronized (lock) {
openInventories.entrySet().stream()
.filter(e -> e.getKey().getOpenInventory().getTopInventory().getHolder() instanceof GuiHolder)
.collect(Collectors.toList()) // to prevent concurrency exceptions
.forEach(e -> e.getKey().closeInventory());
openInventories.clear();
}
}
protected static class GuiListener implements Listener {
final GuiManager manager;
public GuiListener(GuiManager manager) {
this.manager = manager;
}
@EventHandler(priority = EventPriority.LOW)
void onDragGUI(InventoryDragEvent event) {
if (!(event.getWhoClicked() instanceof Player)) {
return;
}
Inventory openInv = event.getInventory();
Gui gui;
if (openInv.getHolder() != null && openInv.getHolder() instanceof GuiHolder
&& ((GuiHolder) openInv.getHolder()).manager.uuid.equals(manager.uuid)) {
gui = ((GuiHolder) openInv.getHolder()).getGUI();
if (event.getRawSlots().stream().filter(slot -> gui.inventory.getSize() > slot).anyMatch(slot -> !gui.unlockedCells.getOrDefault(slot, false))) {
event.setCancelled(true);
event.setResult(Result.DENY);
}
}
}
@EventHandler(priority = EventPriority.LOW)
void onClickGUI(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player)) {
return;
}
Inventory openInv = event.getInventory();
final Player player = (Player) event.getWhoClicked();
Gui gui;
if (openInv.getHolder() != null && openInv.getHolder() instanceof GuiHolder
&& ((GuiHolder) openInv.getHolder()).manager.uuid.equals(manager.uuid)) {
gui = ((GuiHolder) openInv.getHolder()).getGUI();
if (event.getClick() == ClickType.DOUBLE_CLICK) {
// always cancel this event if there are matching gui elements, since it tends to do bad things
ItemStack clicked = event.getCursor();
if (clicked != null && clicked.getType() != Material.AIR) {
int cell = 0;
for (ItemStack it : gui.inventory.getContents()) {
if (!gui.unlockedCells.getOrDefault(cell++, false) && clicked.isSimilar(it)) {
event.setCancelled(true);
if (gui instanceof AnvilGui) {
((AnvilGui) gui).anvil.update();
}
break;
}
}
}
}
if (event.getSlotType() == SlotType.OUTSIDE) {
if (!gui.onClickOutside(manager, player, event)) {
event.setCancelled(true);
}
} // did we click the gui or in the user's inventory?
else if (event.getRawSlot() < gui.inventory.getSize()) {// or could use event.getClickedInventory() == gui.inventory
// allow event if this is not a GUI element
event.setCancelled(gui.unlockedCells.entrySet().stream().noneMatch(e -> event.getSlot() == e.getKey() && e.getValue()));
// process button press
if (gui.onClick(manager, player, openInv, event)) {
player.playSound(player.getLocation(), gui.getDefaultSound().getSound(), 1F, 1F);
}
} else {
// Player clicked in the bottom inventory while GUI is open
if (gui.onClickPlayerInventory(manager, player, openInv, event)) {
player.playSound(player.getLocation(), gui.getDefaultSound().getSound(), 1F, 1F);
} else if (!gui.acceptsItems || event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
event.setCancelled(true);
if (gui instanceof AnvilGui) {
((AnvilGui) gui).anvil.update();
}
}
}
}
}
@EventHandler(priority = EventPriority.LOW)
void onCloseGUI(InventoryCloseEvent event) {
Inventory openInv = event.getInventory();
if (openInv.getHolder() != null && openInv.getHolder() instanceof GuiHolder
&& ((GuiHolder) openInv.getHolder()).manager.uuid.equals(manager.uuid)) {
Gui gui = ((GuiHolder) openInv.getHolder()).getGUI();
if (gui instanceof AnvilGui) {
gui.inventory.clear();
gui.inventory = null;
}
if (!gui.open) {
return;
}
final Player player = (Player) event.getPlayer();
if (!gui.allowDropItems) {
player.setItemOnCursor(null);
}
if (manager.shutdown) {
gui.onClose(manager, player);
} else {
Bukkit.getScheduler().runTaskLater(manager.plugin, () -> gui.onClose(manager, player), 1);
}
manager.openInventories.remove(player);
}
}
@EventHandler
void onDisable(PluginDisableEvent event) {
if (event.getPlugin() == manager.plugin) {
// uh-oh! Abandon ship!!
manager.shutdown = true;
manager.closeAll();
manager.initialized = false;
}
}
}
}
package com.songoda.core.gui;
import com.songoda.core.compatibility.ClientVersion;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.compatibility.ServerVersion;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* Manages events for GUI screens
*/
public class GuiManager {
final Plugin plugin;
final UUID uuid = UUID.randomUUID(); // manager tracking to fix weird bugs from lazy programming
final GuiListener listener = new GuiListener(this);
final Map<Player, Gui> openInventories = new HashMap<>();
private final Object lock = new Object();
private boolean initialized = false;
private boolean shutdown = false;
public GuiManager(Plugin plugin) {
this.plugin = plugin;
}
public Plugin getPlugin() {
return plugin;
}
/**
* Initialize the GUI handlers
*/
public void init() {
Bukkit.getPluginManager().registerEvents(listener, plugin);
initialized = true;
shutdown = false;
}
/**
* Check to see if this manager cannot open any more GUI screens
*
* @return true if the owning plugin has shutdown
*/
public boolean isClosed() {
return shutdown;
}
/**
* Create and display a GUI interface for a player
*
* @param player player to open the interface for
* @param gui GUI to use
*/
public void showGUI(Player player, Gui gui) {
if (shutdown) {
if (!plugin.isEnabled()) {
return;
}
// recover if reloaded without calling init manually
init();
} else if (!initialized) {
init();
}
if (gui instanceof AnvilGui) {
// bukkit throws a fit now if you try to set anvil stuff asynchronously
Gui openInv = openInventories.get(player);
if (openInv != null) {
openInv.open = false;
}
gui.getOrCreateInventory(this);
((AnvilGui) gui).open();
gui.onOpen(this, player);
synchronized (lock) {
openInventories.put(player, gui);
}
return;
}
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
Gui openInv = openInventories.get(player);
if (openInv != null) {
openInv.open = false;
}
Inventory inv = gui.getOrCreateInventory(this);
Bukkit.getScheduler().runTask(plugin, () -> {
player.openInventory(inv);
gui.onOpen(this, player);
synchronized (lock) {
openInventories.put(player, gui);
}
});
});
}
public void showPopup(Player player, String message) {
showPopup(player, message, CompatibleMaterial.NETHER_STAR, BackgroundType.ADVENTURE);
}
public void showPopup(Player player, String message, CompatibleMaterial icon) {
showPopup(player, message, icon, BackgroundType.ADVENTURE);
}
public void showPopup(Player player, String message, CompatibleMaterial icon, BackgroundType background) {
if (ClientVersion.getClientVersion(player).isAtLeast(ServerVersion.V1_12)) {
PopupMessage popup = new PopupMessage(plugin, icon, message, background);
popup.add();
popup.grant(player);
Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, () -> {
popup.revoke(player);
popup.remove();
}, 70);
return;
}
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_11)) {
player.sendTitle("", message, 10, 70, 10);
return;
}
player.sendTitle("", message);
}
/**
* Close all active GUIs
*/
public void closeAll() {
synchronized (lock) {
openInventories.entrySet().stream()
.filter(e -> e.getKey().getOpenInventory().getTopInventory().getHolder() instanceof GuiHolder)
.collect(Collectors.toList()) // to prevent concurrency exceptions
.forEach(e -> e.getKey().closeInventory());
openInventories.clear();
}
}
protected static class GuiListener implements Listener {
final GuiManager manager;
public GuiListener(GuiManager manager) {
this.manager = manager;
}
@EventHandler(priority = EventPriority.LOW)
void onDragGUI(InventoryDragEvent event) {
if (!(event.getWhoClicked() instanceof Player)) {
return;
}
Inventory openInv = event.getInventory();
Gui gui;
if (openInv.getHolder() != null && openInv.getHolder() instanceof GuiHolder
&& ((GuiHolder) openInv.getHolder()).manager.uuid.equals(manager.uuid)) {
gui = ((GuiHolder) openInv.getHolder()).getGUI();
if (event.getRawSlots().stream()
.filter(slot -> gui.inventory.getSize() > slot)
.anyMatch(slot -> !gui.unlockedCells.getOrDefault(slot, false))) {
event.setCancelled(true);
event.setResult(Result.DENY);
}
}
}
@EventHandler(priority = EventPriority.LOW)
void onClickGUI(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player)) {
return;
}
Inventory openInv = event.getInventory();
final Player player = (Player) event.getWhoClicked();
Gui gui;
if (openInv.getHolder() != null && openInv.getHolder() instanceof GuiHolder &&
((GuiHolder) openInv.getHolder()).manager.uuid.equals(manager.uuid)) {
gui = ((GuiHolder) openInv.getHolder()).getGUI();
if (event.getClick() == ClickType.DOUBLE_CLICK) {
// always cancel this event if there are matching gui elements, since it tends to do bad things
ItemStack clicked = event.getCursor();
if (clicked != null && clicked.getType() != Material.AIR) {
int cell = 0;
for (ItemStack it : gui.inventory.getContents()) {
if (!gui.unlockedCells.getOrDefault(cell++, false) && clicked.isSimilar(it)) {
event.setCancelled(true);
if (gui instanceof AnvilGui) {
((AnvilGui) gui).anvil.update();
}
break;
}
}
}
}
if (event.getSlotType() == SlotType.OUTSIDE) {
if (!gui.onClickOutside(manager, player, event)) {
event.setCancelled(true);
}
} // did we click the gui or in the user's inventory?
else if (event.getRawSlot() < gui.inventory.getSize()) { // or could use event.getClickedInventory() == gui.inventory
// allow event if this is not a GUI element
event.setCancelled(gui.unlockedCells.entrySet().stream().noneMatch(e -> event.getSlot() == e.getKey() && e.getValue()));
// process button press
if (gui.onClick(manager, player, openInv, event)) {
player.playSound(player.getLocation(), gui.getDefaultSound().getSound(), 1F, 1F);
}
} else {
// Player clicked in the bottom inventory while GUI is open
if (gui.onClickPlayerInventory(manager, player, openInv, event)) {
player.playSound(player.getLocation(), gui.getDefaultSound().getSound(), 1F, 1F);
} else if (!gui.acceptsItems || event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
event.setCancelled(true);
if (gui instanceof AnvilGui) {
((AnvilGui) gui).anvil.update();
}
}
}
}
}
@EventHandler(priority = EventPriority.LOW)
void onCloseGUI(InventoryCloseEvent event) {
Inventory openInv = event.getInventory();
if (openInv.getHolder() != null && openInv.getHolder() instanceof GuiHolder &&
((GuiHolder) openInv.getHolder()).manager.uuid.equals(manager.uuid)) {
Gui gui = ((GuiHolder) openInv.getHolder()).getGUI();
if (gui instanceof AnvilGui) {
gui.inventory.clear();
gui.inventory = null;
}
if (!gui.open) {
return;
}
final Player player = (Player) event.getPlayer();
if (!gui.allowDropItems) {
player.setItemOnCursor(null);
}
if (manager.shutdown) {
gui.onClose(manager, player);
} else {
Bukkit.getScheduler().runTaskLater(manager.plugin, () -> gui.onClose(manager, player), 1);
}
manager.openInventories.remove(player);
}
}
@EventHandler
void onDisable(PluginDisableEvent event) {
if (event.getPlugin() == manager.plugin) {
// uh-oh! Abandon ship!!
manager.shutdown = true;
manager.closeAll();
manager.initialized = false;
}
}
}
}

View File

@ -3,7 +3,6 @@ package com.songoda.core.gui;
import org.bukkit.event.inventory.InventoryType;
public enum GuiType {
STANDARD(InventoryType.CHEST, 6, 9),
DISPENSER(InventoryType.DISPENSER, 9, 3),
HOPPER(InventoryType.HOPPER, 5, 1);
@ -12,7 +11,7 @@ public enum GuiType {
protected final int rows;
protected final int columns;
private GuiType(InventoryType type, int rows, int columns) {
GuiType(InventoryType type, int rows, int columns) {
this.type = type;
this.rows = rows;
this.columns = columns;

View File

@ -10,32 +10,33 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author jascotty2
* @since 2019-08-25
*/
public class GuiUtils {
public static ItemStack getBorderGlassItem() {
ItemStack glass = CompatibleMaterial.LIGHT_BLUE_STAINED_GLASS_PANE.getItem();
ItemMeta glassmeta = glass.getItemMeta();
glassmeta.setDisplayName(ChatColor.BLACK.toString());
glass.setItemMeta(glassmeta);
return glass;
}
public static ItemStack getBorderItem(ItemStack item) {
ItemMeta glassmeta = item.getItemMeta();
glassmeta.setDisplayName(ChatColor.BLACK.toString());
item.setItemMeta(glassmeta);
return item;
}
public static ItemStack getBorderItem(CompatibleMaterial mat) {
ItemStack item = mat.getItem();
ItemMeta glassmeta = item.getItemMeta();
glassmeta.setDisplayName(ChatColor.BLACK.toString());
item.setItemMeta(glassmeta);
return item;
}
@ -52,198 +53,248 @@ public class GuiUtils {
*/
public static List<String> getSafeLore(List<String> lines) {
// fix newlines
ArrayList<String> newLore = new ArrayList();
ArrayList<String> newLore = new ArrayList<>();
for (String l : lines) {
for (String l2 : l.split("\n")) {
if (l2.length() < 54) {
newLore.add(l2);
} else {
// try to shorten the string
String shorterString = l2;
ChatColor lastColor = null; // todo? probably should also track formatting codes..
int line = 0;
while (shorterString.length() > 50) {
int breakingSpace = -1;
for (int i = 0; i < 50; ++i) {
if (shorterString.charAt(i) == ChatColor.COLOR_CHAR) {
lastColor = ChatColor.getByChar(shorterString.charAt(++i));
} else if (shorterString.charAt(i) == ' ' || shorterString.charAt(i) == '-') {
breakingSpace = i;
}
continue;
}
// try to shorten the string
String shorterString = l2;
ChatColor lastColor = null; // todo? probably should also track formatting codes..
int line = 0;
while (shorterString.length() > 50) {
int breakingSpace = -1;
for (int i = 0; i < 50; ++i) {
if (shorterString.charAt(i) == ChatColor.COLOR_CHAR) {
lastColor = ChatColor.getByChar(shorterString.charAt(++i));
} else if (shorterString.charAt(i) == ' ' || shorterString.charAt(i) == '-') {
breakingSpace = i;
}
if (breakingSpace == -1) {
breakingSpace = Math.max(50, shorterString.length());
newLore.add((line != 0 && lastColor != null ? lastColor.toString() : "") + shorterString.substring(0, breakingSpace) + "-");
shorterString = breakingSpace == shorterString.length() ? "" : shorterString.substring(breakingSpace + 1);
} else {
newLore.add((line != 0 && lastColor != null ? lastColor.toString() : "") + shorterString.substring(0, breakingSpace));
shorterString = breakingSpace == shorterString.length() ? "" : shorterString.substring(breakingSpace + 1);
}
++line;
}
if (!shorterString.isEmpty()) {
newLore.add((line != 0 && lastColor != null ? lastColor.toString() : "") + " " + shorterString);
if (breakingSpace == -1) {
breakingSpace = Math.max(50, shorterString.length());
newLore.add((line != 0 && lastColor != null ? lastColor.toString() : "") + shorterString.substring(0, breakingSpace) + "-");
shorterString = breakingSpace == shorterString.length() ? "" : shorterString.substring(breakingSpace + 1);
} else {
newLore.add((line != 0 && lastColor != null ? lastColor.toString() : "") + shorterString.substring(0, breakingSpace));
shorterString = breakingSpace == shorterString.length() ? "" : shorterString.substring(breakingSpace + 1);
}
++line;
}
if (!shorterString.isEmpty()) {
newLore.add((line != 0 && lastColor != null ? lastColor.toString() : "") + " " + shorterString);
}
}
}
return newLore;
}
public static ItemStack createButtonItem(CompatibleMaterial mat, String title, String... lore) {
ItemStack item = mat.getItem();
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack createButtonItem(CompatibleMaterial mat, int amount, String title, String... lore) {
ItemStack item = mat.getItem();
item.setAmount(amount);
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack createButtonItem(ItemStack from, String title, String... lore) {
ItemStack item = from.clone();
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack createButtonItem(CompatibleMaterial mat, String title, List<String> lore) {
ItemStack item = mat.getItem();
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack createButtonItem(CompatibleMaterial mat, int amount, String title, List<String> lore) {
ItemStack item = mat.getItem();
item.setAmount(amount);
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack createButtonItem(ItemStack from, String title, List<String> lore) {
ItemStack item = from.clone();
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack createButtonItem(CompatibleMaterial mat, String[] lore) {
ItemStack item = mat.getItem();
ItemMeta meta = item.getItemMeta();
if (meta != null) {
if (lore != null && lore.length != 0) {
List<String> safe = getSafeLore(lore);
meta.setDisplayName(safe.get(0));
meta.setLore(safe.subList(1, safe.size()));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack createButtonItem(CompatibleMaterial mat, int amount, String[] lore) {
ItemStack item = mat.getItem();
item.setAmount(amount);
ItemMeta meta = item.getItemMeta();
if (meta != null) {
if (lore != null && lore.length != 0) {
List<String> safe = getSafeLore(lore);
meta.setDisplayName(safe.get(0));
meta.setLore(safe.subList(1, safe.size()));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack createButtonItem(ItemStack from, String[] lore) {
ItemStack item = from.clone();
ItemMeta meta = item.getItemMeta();
if (meta != null) {
if (lore != null && lore.length != 0) {
List<String> safe = getSafeLore(lore);
meta.setDisplayName(safe.get(0));
meta.setLore(safe.subList(1, safe.size()));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack createButtonItem(CompatibleMaterial mat, List<String> lore) {
ItemStack item = mat.getItem();
ItemMeta meta = item.getItemMeta();
if (meta != null) {
if (lore != null && !lore.isEmpty()) {
List<String> safe = getSafeLore(lore);
meta.setDisplayName(safe.get(0));
meta.setLore(safe.subList(1, safe.size()));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
@ -251,81 +302,101 @@ public class GuiUtils {
ItemStack item = mat.getItem();
item.setAmount(amount);
ItemMeta meta = item.getItemMeta();
if (meta != null) {
if (lore != null && !lore.isEmpty()) {
List<String> safe = getSafeLore(lore);
meta.setDisplayName(safe.get(0));
meta.setLore(safe.subList(1, safe.size()));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack createButtonItem(ItemStack from, List<String> lore) {
ItemStack item = from.clone();
ItemMeta meta = item.getItemMeta();
if (meta != null) {
if (lore != null && !lore.isEmpty()) {
List<String> safe = getSafeLore(lore);
meta.setDisplayName(safe.get(0));
meta.setLore(safe.subList(1, safe.size()));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack updateItem(ItemStack item, String title, String... lore) {
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack updateItemName(ItemStack item, String title) {
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
item.setItemMeta(meta);
}
return item;
}
public static ItemStack updateItemLore(ItemStack item, String... lore) {
ItemMeta meta = item.getItemMeta();
if (meta != null) {
if (lore != null && lore.length != 0) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack updateItemLore(ItemStack item, List<String> lore) {
ItemMeta meta = item.getItemMeta();
if (meta != null) {
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
@ -333,16 +404,21 @@ public class GuiUtils {
if (!matTo.matches(item)) {
item = matTo.getItem();
}
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
@ -350,30 +426,39 @@ public class GuiUtils {
if (!CompatibleMaterial.getMaterial(item).matches(to)) {
item = to.clone();
}
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
public static ItemStack updateItem(ItemStack item, String title, List<String> lore) {
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
@ -381,16 +466,21 @@ public class GuiUtils {
if (!matTo.matches(item)) {
item = matTo.getItem();
}
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
@ -398,16 +488,21 @@ public class GuiUtils {
if (!CompatibleMaterial.getMaterial(item).matches(to)) {
item = to.clone();
}
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(title);
if (lore != null) {
meta.setLore(getSafeLore(lore));
} else {
meta.setLore(Collections.EMPTY_LIST);
meta.setLore(Collections.emptyList());
}
item.setItemMeta(meta);
}
return item;
}
}

View File

@ -24,9 +24,8 @@ import java.util.UUID;
* Calling this class on anything below 1.12 will cause ClassLoader Exceptions!
*/
class PopupMessage {
private static final Gson gson = new GsonBuilder().setPrettyPrinting().create();
private static final HashSet<UUID> registeredMessages = new HashSet();
private static final HashSet<UUID> registeredMessages = new HashSet<>();
final UUID id = UUID.randomUUID();
private final NamespacedKey key;
@ -52,14 +51,18 @@ class PopupMessage {
private String getJSON() {
JsonObject json = new JsonObject();
JsonObject advDisplay = new JsonObject();
if (this.icon != null) {
JsonObject displayIcon = new JsonObject();
displayIcon.addProperty("item", "minecraft:" + this.icon.getMaterial().name().toLowerCase());
if (this.icon.usesData()) {
displayIcon.addProperty("data", this.icon.getData());
}
advDisplay.add("icon", displayIcon);
}
advDisplay.add("title", gson.fromJson(ComponentSerializer.toString(this.title), JsonElement.class));
advDisplay.addProperty("background", background.key);
advDisplay.addProperty("description", "");
@ -88,24 +91,31 @@ class PopupMessage {
final Advancement adv = getAdvancement();
final AdvancementProgress progress = pl.getAdvancementProgress(adv);
if (!progress.isDone())
progress.getRemainingCriteria().forEach((crit) -> progress.awardCriteria(crit));
if (!progress.isDone()) {
for (String s : progress.getRemainingCriteria()) {
progress.awardCriteria(s);
}
}
}
protected void revoke(final Player pl) {
final Advancement adv = getAdvancement();
final AdvancementProgress prog = pl.getAdvancementProgress(adv);
if (prog.isDone())
prog.getAwardedCriteria().forEach((crit) -> prog.revokeCriteria(crit));
if (prog.isDone()) {
for (String s : prog.getAwardedCriteria()) {
prog.revokeCriteria(s);
}
}
}
protected void add() {
if (!registeredMessages.contains(id)) {
registeredMessages.add(id);
try {
Bukkit.getUnsafe().loadAdvancement(key, getJSON());
} catch (IllegalArgumentException e) {
} catch (IllegalArgumentException ex) {
Bukkit.getLogger().warning("Failed to create popup advancement!");
}
}
@ -122,18 +132,19 @@ class PopupMessage {
return Bukkit.getAdvancement(key);
}
public static enum FrameType {
public enum FrameType {
TASK,
CHALLENGE,
GOAL;
final String id;
private FrameType() {
FrameType() {
id = name().toLowerCase();
}
}
public static enum TriggerType {
public enum TriggerType {
ARBITRARY_PLAYER_TICK(ServerVersion.V1_13, "TICK"),
BRED_ANIMALS,
BREWED_POTION,
@ -163,17 +174,18 @@ class PopupMessage {
USED_ENDER_EYE,
USED_TOTEM,
VILLAGER_TRADE;
final ServerVersion minVersion;
final String compatible;
final String key;
private TriggerType() {
TriggerType() {
this.minVersion = ServerVersion.UNKNOWN;
this.compatible = "";
this.key = "minecraft:" + name().toLowerCase();
}
private TriggerType(ServerVersion minVersion, String compatible) {
TriggerType(ServerVersion minVersion, String compatible) {
this.minVersion = minVersion;
this.compatible = compatible;
this.key = "minecraft:" + (ServerVersion.isServerVersionAtLeast(minVersion) ? name() : compatible).toLowerCase();

View File

@ -1,225 +1,235 @@
package com.songoda.core.gui;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.gui.events.GuiClickEvent;
import com.songoda.core.gui.methods.Clickable;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.Map;
/**
* Paged GUI for when you aren't going to be making too many pages
*
* @author jascotty2
* @since 2019-08-31
*/
public class SimplePagedGui extends Gui {
protected boolean useHeader;
private int rowsPerPage, maxCellSlot;
protected ItemStack headerBackItem;
protected ItemStack footerBackItem;
final int nextPageIndex = 4, prevPageIndex = 6;
public SimplePagedGui() {
this(null);
}
public SimplePagedGui(Gui parent) {
super(parent);
nextPage = GuiUtils.createButtonItem(CompatibleMaterial.ARROW, "Next Page");
prevPage = GuiUtils.createButtonItem(CompatibleMaterial.ARROW, "Previous Page");
}
public SimplePagedGui setUseHeader(boolean useHeader) {
this.useHeader = useHeader;
return this;
}
public ItemStack getHeaderBackItem() {
return headerBackItem;
}
public SimplePagedGui setHeaderBackItem(ItemStack headerBackItem) {
this.headerBackItem = headerBackItem;
return this;
}
public ItemStack getFooterBackItem() {
return footerBackItem;
}
public SimplePagedGui setFooterBackItem(ItemStack footerBackItem) {
this.footerBackItem = footerBackItem;
return this;
}
@Override
public SimplePagedGui setItem(int row, int col, ItemStack item) {
return setItem(col + row * 9, item);
}
@Override
public SimplePagedGui setItem(int cell, ItemStack item) {
// set the cell relative to the current page
int cellIndex = cell < 0 ? cell : (page == 1 || (useHeader && cell < 9) ? cell : (cell + (page - 1) * (rowsPerPage * 9)));
cellItems.put(cellIndex, item);
if (open && cell >= 0 && cell < inventory.getSize()) {
inventory.setItem(cell, item);
}
return this;
}
@Override
public void nextPage() {
if (page < pages) {
++page;
showPage();
}
}
@Override
public void prevPage() {
if (page > 1) {
--page;
showPage();
}
}
public void showPage() {
int startCell = useHeader ? 9 : 0;
int cellIndex = startCell + (page - 1) * (rowsPerPage * 9);
for (int i = startCell; i < (rows - 1) * 9; ++i) {
final ItemStack item = cellItems.get(cellIndex++);
inventory.setItem(i, item != null ? item : blankItem);
}
// page markers
updatePageNavigation();
}
@Override
protected void updatePageNavigation() {
if (page > 1) {
inventory.setItem(inventory.getSize() - prevPageIndex, prevPage);
this.setButton(-prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage());
} else {
inventory.setItem(inventory.getSize() - prevPageIndex, footerBackItem != null ? footerBackItem : blankItem);
this.setItem(-prevPageIndex, null);
this.clearActions(-prevPageIndex);
}
if (pages > 1 && page != pages) {
inventory.setItem(inventory.getSize() - nextPageIndex, nextPage);
this.setButton(-nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage());
} else {
inventory.setItem(inventory.getSize() - nextPageIndex, footerBackItem != null ? footerBackItem : blankItem);
this.setItem(-nextPageIndex, null);
this.clearActions(-nextPageIndex);
}
}
@Override
protected Inventory generateInventory(GuiManager manager) {
this.guiManager = manager;
// calculate pages here
rowsPerPage = useHeader ? 4 : 5;
maxCellSlot = (this.cellItems.isEmpty() ? 0 : this.cellItems.keySet().stream().max(Integer::compare).get()) + 1;
int maxRows = (int) Math.ceil(maxCellSlot / 9.);
pages = (int) Math.max(1, Math.ceil(maxRows / (double) rowsPerPage));
this.setRows(maxRows + (useHeader ? 1 : 0));
// create inventory view
createInventory();
// populate and return the display inventory
setPage(Math.min(page, pages));
update();
return inventory;
}
@Override
protected void createInventory() {
final int cells = rows * 9;
inventory = Bukkit.getServer().createInventory(new GuiHolder(guiManager, this), cells,
title == null ? "" : trimTitle(title));
}
@Override
public void update() {
if (inventory == null) {
return;
}
// calculate pages here
rowsPerPage = useHeader ? 4 : 5;
maxCellSlot = (this.cellItems.isEmpty() ? 0 : this.cellItems.keySet().stream().max(Integer::compare).get()) + 1;
int maxRows = Math.max((useHeader ? 1 : 0), (int) Math.ceil(maxCellSlot / 9.));
pages = (int) Math.ceil(maxRows / rowsPerPage);
// create a new inventory if needed
List<Player> toUpdate = null;
if (Math.min(54, (maxRows + (useHeader ? 1 : 0)) * 9) != inventory.getSize()) {
toUpdate = getPlayers();
this.setRows(maxRows + (useHeader ? 1 : 0));
createInventory();
}
// populate header
if (useHeader) {
for (int i = 0; i < 9; ++i) {
final ItemStack item = cellItems.get(i);
inventory.setItem(i, item != null ? item : (headerBackItem != null ? headerBackItem : blankItem));
}
}
// last row is dedicated to pagation
final int cells = rows * 9;
for (int i = cells - 9; i < cells; ++i) {
inventory.setItem(i, footerBackItem != null ? footerBackItem : blankItem);
}
// fill out the rest of the page
showPage();
// did we need to change the display window size?
if (toUpdate != null) {
// whoopsie!
exit();
toUpdate.forEach(player -> guiManager.showGUI(player, this));
}
}
@Override
protected boolean onClick(GuiManager manager, Player player, Inventory inventory, InventoryClickEvent event) {
int cell = event.getSlot();
Map<ClickType, Clickable> conditionals;
if (useHeader && cell < 9) {
conditionals = conditionalButtons.get(cell);
} else if (cell >= (rows - 1) * 9) {
// footer row
conditionals = conditionalButtons.get(cell - (rows * 9));
} else {
int cellIndex = page == 1 || (useHeader && cell < 9) ? cell : (cell + (page - 1) * (rowsPerPage * 9));
conditionals = conditionalButtons.get(cellIndex);
}
Clickable button;
if (conditionals != null
&& ((button = conditionals.get(event.getClick())) != null || (button = conditionals.get(null)) != null)) {
button.onClick(new GuiClickEvent(manager, this, player, event, cell, true));
} else {
// no event for this button
return false;
}
return true;
}
}
package com.songoda.core.gui;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.gui.events.GuiClickEvent;
import com.songoda.core.gui.methods.Clickable;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.Map;
/**
* Paged GUI for when you aren't going to be making too many pages
*/
public class SimplePagedGui extends Gui {
protected boolean useHeader;
private int rowsPerPage, maxCellSlot;
protected ItemStack headerBackItem;
protected ItemStack footerBackItem;
final int nextPageIndex = 4, prevPageIndex = 6;
public SimplePagedGui() {
this(null);
}
public SimplePagedGui(Gui parent) {
super(parent);
nextPage = GuiUtils.createButtonItem(CompatibleMaterial.ARROW, "Next Page");
prevPage = GuiUtils.createButtonItem(CompatibleMaterial.ARROW, "Previous Page");
}
public SimplePagedGui setUseHeader(boolean useHeader) {
this.useHeader = useHeader;
return this;
}
public ItemStack getHeaderBackItem() {
return headerBackItem;
}
public SimplePagedGui setHeaderBackItem(ItemStack headerBackItem) {
this.headerBackItem = headerBackItem;
return this;
}
public ItemStack getFooterBackItem() {
return footerBackItem;
}
public SimplePagedGui setFooterBackItem(ItemStack footerBackItem) {
this.footerBackItem = footerBackItem;
return this;
}
@Override
public SimplePagedGui setItem(int row, int col, ItemStack item) {
return setItem(col + row * 9, item);
}
@Override
public SimplePagedGui setItem(int cell, ItemStack item) {
// set the cell relative to the current page
int cellIndex = cell < 0 ? cell : (page == 1 || (useHeader && cell < 9) ? cell : (cell + (page - 1) * (rowsPerPage * 9)));
cellItems.put(cellIndex, item);
if (open && cell >= 0 && cell < inventory.getSize()) {
inventory.setItem(cell, item);
}
return this;
}
@Override
public void nextPage() {
if (page < pages) {
++page;
showPage();
}
}
@Override
public void prevPage() {
if (page > 1) {
--page;
showPage();
}
}
public void showPage() {
int startCell = useHeader ? 9 : 0;
int cellIndex = startCell + (page - 1) * (rowsPerPage * 9);
for (int i = startCell; i < (rows - 1) * 9; ++i) {
final ItemStack item = cellItems.get(cellIndex++);
inventory.setItem(i, item != null ? item : blankItem);
}
// page markers
updatePageNavigation();
}
@Override
protected void updatePageNavigation() {
if (page > 1) {
inventory.setItem(inventory.getSize() - prevPageIndex, prevPage);
this.setButton(-prevPageIndex, prevPage, ClickType.LEFT, (event) -> this.prevPage());
} else {
inventory.setItem(inventory.getSize() - prevPageIndex, footerBackItem != null ? footerBackItem : blankItem);
this.setItem(-prevPageIndex, null);
this.clearActions(-prevPageIndex);
}
if (pages > 1 && page != pages) {
inventory.setItem(inventory.getSize() - nextPageIndex, nextPage);
this.setButton(-nextPageIndex, nextPage, ClickType.LEFT, (event) -> this.nextPage());
} else {
inventory.setItem(inventory.getSize() - nextPageIndex, footerBackItem != null ? footerBackItem : blankItem);
this.setItem(-nextPageIndex, null);
this.clearActions(-nextPageIndex);
}
}
@Override
protected Inventory generateInventory(GuiManager manager) {
this.guiManager = manager;
// calculate pages here
rowsPerPage = useHeader ? 4 : 5;
maxCellSlot = this.cellItems.keySet().stream().max(Integer::compare).orElse(0) + 1;
int maxRows = (int) Math.ceil(maxCellSlot / 9.);
pages = (int) Math.max(1, Math.ceil(maxRows / (double) rowsPerPage));
this.setRows(maxRows + (useHeader ? 1 : 0));
// create inventory view
createInventory();
// populate and return the display inventory
setPage(Math.min(page, pages));
update();
return inventory;
}
@Override
protected void createInventory() {
final int cells = rows * 9;
inventory = Bukkit.getServer().createInventory(new GuiHolder(guiManager, this), cells,
title == null ? "" : trimTitle(title));
}
@Override
public void update() {
if (inventory == null) {
return;
}
// calculate pages here
rowsPerPage = useHeader ? 4 : 5;
maxCellSlot = (this.cellItems.isEmpty() ? 0 : this.cellItems.keySet().stream().max(Integer::compare).get()) + 1;
int maxRows = Math.max((useHeader ? 1 : 0), (int) Math.ceil(maxCellSlot / 9.));
pages = (int) Math.ceil(maxRows / rowsPerPage);
// create a new inventory if needed
List<Player> toUpdate = null;
if (Math.min(54, (maxRows + (useHeader ? 1 : 0)) * 9) != inventory.getSize()) {
toUpdate = getPlayers();
this.setRows(maxRows + (useHeader ? 1 : 0));
createInventory();
}
// populate header
if (useHeader) {
for (int i = 0; i < 9; ++i) {
final ItemStack item = cellItems.get(i);
inventory.setItem(i, item != null ? item : (headerBackItem != null ? headerBackItem : blankItem));
}
}
// last row is dedicated to pagation
final int cells = rows * 9;
for (int i = cells - 9; i < cells; ++i) {
inventory.setItem(i, footerBackItem != null ? footerBackItem : blankItem);
}
// fill out the rest of the page
showPage();
// did we need to change the display window size?
if (toUpdate != null) {
// whoopsie!
exit();
toUpdate.forEach(player -> guiManager.showGUI(player, this));
}
}
@Override
protected boolean onClick(GuiManager manager, Player player, Inventory inventory, InventoryClickEvent event) {
int cell = event.getSlot();
Map<ClickType, Clickable> conditionals;
if (useHeader && cell < 9) {
conditionals = conditionalButtons.get(cell);
} else if (cell >= (rows - 1) * 9) {
// footer row
conditionals = conditionalButtons.get(cell - (rows * 9));
} else {
int cellIndex = page == 1 ? cell : cell + (page - 1) * rowsPerPage * 9;
conditionals = conditionalButtons.get(cellIndex);
}
Clickable button;
if (conditionals != null
&& ((button = conditionals.get(event.getClick())) != null || (button = conditionals.get(null)) != null)) {
button.onClick(new GuiClickEvent(manager, this, player, event, cell, true));
} else {
// no event for this button
return false;
}
return true;
}
}

View File

@ -17,10 +17,13 @@ public class GuiClickEvent extends GuiEvent {
public GuiClickEvent(GuiManager manager, Gui gui, Player player, InventoryClickEvent event, int slot, boolean guiClicked) {
super(manager, gui, player);
this.slot = slot;
this.guiClicked = guiClicked;
this.cursor = event.getCursor();
Inventory clicked = event.getClickedInventory();
this.clickedItem = clicked == null ? null : clicked.getItem(event.getSlot());
this.clickType = event.getClick();
this.event = event;

View File

@ -5,7 +5,6 @@ import com.songoda.core.gui.GuiManager;
import org.bukkit.entity.Player;
public class GuiCloseEvent extends GuiEvent {
public GuiCloseEvent(GuiManager manager, Gui gui, Player player) {
super(manager, gui, player);
}

View File

@ -14,6 +14,7 @@ public class GuiDropItemEvent extends GuiEvent {
public GuiDropItemEvent(GuiManager manager, Gui gui, Player player, InventoryClickEvent event) {
super(manager, gui, player);
this.cursor = event.getCursor();
this.clickType = event.getClick();
this.event = event;

View File

@ -5,7 +5,6 @@ import com.songoda.core.gui.GuiManager;
import org.bukkit.entity.Player;
public abstract class GuiEvent {
public final GuiManager manager;
public final Gui gui;
public final Player player;

View File

@ -5,7 +5,6 @@ import com.songoda.core.gui.GuiManager;
import org.bukkit.entity.Player;
public class GuiOpenEvent extends GuiEvent {
public GuiOpenEvent(GuiManager manager, Gui gui, Player player) {
super(manager, gui, player);
}

View File

@ -4,7 +4,6 @@ import com.songoda.core.gui.Gui;
import com.songoda.core.gui.GuiManager;
public class GuiPageEvent {
final Gui gui;
final GuiManager manager;
final int lastPage;

View File

@ -3,6 +3,5 @@ package com.songoda.core.gui.methods;
import com.songoda.core.gui.events.GuiClickEvent;
public interface Clickable {
void onClick(GuiClickEvent event);
}

View File

@ -3,6 +3,5 @@ package com.songoda.core.gui.methods;
import com.songoda.core.gui.events.GuiCloseEvent;
public interface Closable {
void onClose(GuiCloseEvent event);
}

View File

@ -3,6 +3,5 @@ package com.songoda.core.gui.methods;
import com.songoda.core.gui.events.GuiDropItemEvent;
public interface Droppable {
boolean onDrop(GuiDropItemEvent event);
}

View File

@ -1,8 +1,7 @@
package com.songoda.core.gui.methods;
import com.songoda.core.gui.events.GuiOpenEvent;
public interface Openable {
void onOpen(GuiOpenEvent event);
}
package com.songoda.core.gui.methods;
import com.songoda.core.gui.events.GuiOpenEvent;
public interface Openable {
void onOpen(GuiOpenEvent event);
}

View File

@ -3,6 +3,5 @@ package com.songoda.core.gui.methods;
import com.songoda.core.gui.events.GuiPageEvent;
public interface Pagable {
void onPageChange(GuiPageEvent event);
}

View File

@ -8,7 +8,6 @@ import org.bukkit.OfflinePlayer;
* A convenience class for static access to an Economy HookManager
*/
public class EconomyManager {
private static char currencySymbol = '$';
private static final HookManager<Economy> manager = new HookManager(Economy.class);
@ -48,8 +47,6 @@ public class EconomyManager {
/**
* Get the name of the economy plugin being used. <br />
* NOTE: using a default economy assumes that this library is shaded
*
* @return
*/
public static String getName() {
return manager.getName();
@ -119,7 +116,7 @@ public class EconomyManager {
}
/**
* Change the curency symbl used in the #formatEconomy method.
* Change the curency symbol used in the #formatEconomy method.
*
* @param currencySymbol the new symbol
*/
@ -128,7 +125,7 @@ public class EconomyManager {
}
/**
* Change the curency symbl used in the #formatEconomy method.
* Change the curency symbol used in the #formatEconomy method.
*
* @param currencySymbol the new symbol
*/

View File

@ -8,7 +8,6 @@ import org.bukkit.entity.LivingEntity;
* A convenience class for static access to a Stacker HookManager
*/
public class EntityStackerManager {
private static final HookManager<Stacker> manager = new HookManager(Stacker.class);
/**
@ -56,8 +55,9 @@ public class EntityStackerManager {
}
public static void remove(LivingEntity entity, int amount) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().remove(entity, amount);
}
}
public static void addOne(LivingEntity entity) {
@ -65,8 +65,9 @@ public class EntityStackerManager {
}
public static void add(LivingEntity entity, int amount) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().add(entity, amount);
}
}
public static int getMinStackSize(EntityType type) {

View File

@ -11,7 +11,6 @@ import java.util.Map;
* A convenience class for static access to a Holograms HookManager
*/
public class HologramManager {
private static final HookManager<Holograms> manager = new HookManager(Holograms.class);
/**
@ -49,37 +48,44 @@ public class HologramManager {
}
public static void createHologram(Location location, String line) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().createHologram(location, line);
}
}
public static void createHologram(Location location, List<String> lines) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().createHologram(location, lines);
}
}
public static void removeHologram(Location location) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().removeHologram(location);
}
}
public static void removeAllHolograms() {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().removeAllHolograms();
}
}
public static void updateHologram(Location location, String line) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().updateHologram(location, line);
}
}
public static void updateHologram(Location location, List<String> lines) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().updateHologram(location, lines);
}
}
public static void bulkUpdateHolograms(Map<Location, List<String>> holograms) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().bulkUpdateHolograms(holograms);
}
}
}

View File

@ -1,18 +1,15 @@
package com.songoda.core.hooks;
public interface Hook {
/**
* Get the name of the plugin being used
*
* @return
*/
abstract String getName();
/**
* Check to see if the economy plugin being used is active
*
* @return true if the plugin is loaded and active
*/
abstract boolean isEnabled();
}
package com.songoda.core.hooks;
public interface Hook {
/**
* Get the name of the plugin being used
*/
String getName();
/**
* Check to see if the economy plugin being used is active
*
* @return true if the plugin is loaded and active
*/
boolean isEnabled();
}

View File

@ -10,7 +10,6 @@ import java.util.Map;
import java.util.stream.Collectors;
public class HookManager<T extends Hook> {
private final Class typeClass;
private T defaultHook = null;
private boolean loaded = false;
@ -36,9 +35,11 @@ public class HookManager<T extends Hook> {
if (!loaded) {
registeredHooks.putAll(PluginHook.loadHooks(typeClass, hookingPlugin).entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> (T) e.getValue())));
if (!registeredHooks.isEmpty()) {
defaultHook = (T) registeredHooks.values().iterator().next();
defaultHook = registeredHooks.values().iterator().next();
}
loaded = true;
}
}
@ -66,8 +67,10 @@ public class HookManager<T extends Hook> {
T hook = getHook(name);
if (hook != null) {
defaultHook = hook;
return true;
}
return false;
}
@ -84,8 +87,10 @@ public class HookManager<T extends Hook> {
T hook = getHook(plugin);
if (hook != null) {
defaultHook = hook;
return true;
}
return false;
}
@ -97,10 +102,12 @@ public class HookManager<T extends Hook> {
* @return returns null if plugin is not enabled
*/
public T getHook(String name) {
if (name == null)
if (name == null) {
return null;
}
final String plugin = name.trim();
return (T) registeredHooks.get(registeredHooks.keySet().stream()
return registeredHooks.get(registeredHooks.keySet().stream()
.filter(type -> type.plugin.equalsIgnoreCase(plugin))
.findFirst().orElse(null));
}

View File

@ -1,233 +1,267 @@
package com.songoda.core.hooks;
import com.songoda.core.hooks.jobs.JobsHandler;
import com.songoda.core.hooks.jobs.JobsPlayerHandler;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.Collections;
import java.util.List;
public class JobsHook {
static boolean canHook;
static {
try {
// if this class exists, we're good to use Jobs classes
Class.forName("com.gamingmesh.jobs.Jobs");
canHook = true;
} catch (ClassNotFoundException ex) {
}
}
public static JobsPlayerHandler getPlayer(Player player) {
if (canHook) {
return JobsPlayerHandler.loadPlayer(player);
}
return null;
}
public static boolean isEnabled() {
return canHook;
}
public static List<String> getAllJobs() {
if (canHook) {
return JobsHandler.getJobs();
}
return Collections.EMPTY_LIST;
}
public static double getBoostExp(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getBoostExp(job);
}
return -1;
}
public static double getBoostMoney(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getBoostMoney(job);
}
return -1;
}
public static double getBoostPoints(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getBoostPoints(job);
}
return -1;
}
public static void promoteJob(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.promoteJob(job);
}
}
public static void promoteJob(Player player, String job, int levels) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.promoteJob(job, levels);
}
}
public static void demoteJob(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.demoteJob(job);
}
}
public static void demoteJob(Player player, String job, int levels) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.demoteJob(job, levels);
}
}
public static void joinJob(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.joinJob(job);
}
}
public static void leaveAllJobs(Player player) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.leaveAllJobs();
}
}
public static void leaveJob(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.leaveJob(job);
}
}
public static int getTotalLevels(Player player) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getTotalLevels();
}
return -1;
}
public static int getMaxBrewingStandsAllowed(Player player) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getMaxBrewingStandsAllowed();
}
return -1;
}
public static int getMaxFurnacesAllowed(Player player) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getMaxFurnacesAllowed();
}
return -1;
}
public static List<String> getJobs(Player player) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getJobs();
}
return Collections.EMPTY_LIST;
}
public static void eatItem(Player player, ItemStack item) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.eatItem(item);
}
}
public static void breakBlock(Player player, Block block) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.breakBlock(block);
}
}
public static void tntBreakBlock(Player player, Block block) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.tntBreakBlock(block);
}
}
public static void placeBlock(Player player, Block block) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.placeBlock(block);
}
}
public static void placeEntity(Player player, Entity block) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.placeEntity(block);
}
}
public static void breakEntity(Player player, Entity block) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.breakEntity(block);
}
}
public static void breedEntity(Player player, LivingEntity entity) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.breedEntity(entity);
}
}
public static void killEntity(Player player, LivingEntity entity) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.killEntity(entity);
}
}
public static void tameEntity(Player player, LivingEntity entity) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.tameEntity(entity);
}
}
public static void catchFish(Player player, ItemStack items) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.catchFish(items);
}
}
public static void killEntity(Player player, LivingEntity entity, Entity damageSource) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.killEntity(entity, damageSource);
}
}
public static void itemEnchanted(Player player, ItemStack resultStack) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.itemEnchanted(resultStack);
}
}
}
package com.songoda.core.hooks;
import com.songoda.core.hooks.jobs.JobsHandler;
import com.songoda.core.hooks.jobs.JobsPlayerHandler;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.Collections;
import java.util.List;
public class JobsHook {
static boolean canHook;
static {
try {
// if this class exists, we're good to use Jobs classes
Class.forName("com.gamingmesh.jobs.Jobs");
canHook = true;
} catch (ClassNotFoundException ignore) {
}
}
public static JobsPlayerHandler getPlayer(Player player) {
if (canHook) {
return JobsPlayerHandler.loadPlayer(player);
}
return null;
}
public static boolean isEnabled() {
return canHook;
}
public static List<String> getAllJobs() {
if (canHook) {
return JobsHandler.getJobs();
}
return Collections.emptyList();
}
public static double getBoostExp(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getBoostExp(job);
}
return -1;
}
public static double getBoostMoney(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getBoostMoney(job);
}
return -1;
}
public static double getBoostPoints(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getBoostPoints(job);
}
return -1;
}
public static void promoteJob(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.promoteJob(job);
}
}
public static void promoteJob(Player player, String job, int levels) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.promoteJob(job, levels);
}
}
public static void demoteJob(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.demoteJob(job);
}
}
public static void demoteJob(Player player, String job, int levels) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.demoteJob(job, levels);
}
}
public static void joinJob(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.joinJob(job);
}
}
public static void leaveAllJobs(Player player) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.leaveAllJobs();
}
}
public static void leaveJob(Player player, String job) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.leaveJob(job);
}
}
public static int getTotalLevels(Player player) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getTotalLevels();
}
return -1;
}
public static int getMaxBrewingStandsAllowed(Player player) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getMaxBrewingStandsAllowed();
}
return -1;
}
public static int getMaxFurnacesAllowed(Player player) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getMaxFurnacesAllowed();
}
return -1;
}
public static List<String> getJobs(Player player) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
return jPlayer.getJobs();
}
return Collections.emptyList();
}
public static void eatItem(Player player, ItemStack item) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.eatItem(item);
}
}
public static void breakBlock(Player player, Block block) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.breakBlock(block);
}
}
public static void tntBreakBlock(Player player, Block block) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.tntBreakBlock(block);
}
}
public static void placeBlock(Player player, Block block) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.placeBlock(block);
}
}
public static void placeEntity(Player player, Entity block) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.placeEntity(block);
}
}
public static void breakEntity(Player player, Entity block) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.breakEntity(block);
}
}
public static void breedEntity(Player player, LivingEntity entity) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.breedEntity(entity);
}
}
public static void killEntity(Player player, LivingEntity entity) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.killEntity(entity);
}
}
public static void tameEntity(Player player, LivingEntity entity) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.tameEntity(entity);
}
}
public static void catchFish(Player player, ItemStack items) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.catchFish(items);
}
}
public static void killEntity(Player player, LivingEntity entity, Entity damageSource) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.killEntity(entity, damageSource);
}
}
public static void itemEnchanted(Player player, ItemStack resultStack) {
JobsPlayerHandler jPlayer = getPlayer(player);
if (jPlayer != null) {
jPlayer.itemEnchanted(resultStack);
}
}
}

View File

@ -9,7 +9,6 @@ import org.bukkit.block.Block;
* A convenience class for static access to a Log HookManager
*/
public class LogManager {
private static final HookManager<Log> manager = new HookManager(Log.class);
/**
@ -47,8 +46,6 @@ public class LogManager {
/**
* Get the name of the log plugin being used. <br />
* NOTE: using a default log assumes that this library is shaded
*
* @return
*/
public static String getName() {
return manager.getName();
@ -62,8 +59,9 @@ public class LogManager {
* @param block the block that is placed
*/
public static void logPlacement(OfflinePlayer player, Block block) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().logPlacement(player, block);
}
}
/**
@ -73,8 +71,9 @@ public class LogManager {
* @param player player to commit actionremvedplaced
*/
public static void logRemoval(OfflinePlayer player, Block block) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().logRemoval(player, block);
}
}
/**
@ -85,7 +84,8 @@ public class LogManager {
* @param location the location that is interacted with
*/
public static void logInteraction(OfflinePlayer player, Location location) {
if (manager.isEnabled())
if (manager.isEnabled()) {
manager.getCurrentHook().logInteraction(player, location);
}
}
}

View File

@ -8,7 +8,6 @@ import org.bukkit.entity.Player;
import java.util.Collection;
public class McMMOHook {
static boolean canHook = false;
static {
@ -16,7 +15,7 @@ public class McMMOHook {
// if this class exists, we're good to use McMMO
Class.forName("com.gmail.nossr50.api.AbilityAPI");
canHook = true;
} catch (ClassNotFoundException ex) {
} catch (ClassNotFoundException ignore) {
}
}
@ -185,46 +184,46 @@ public class McMMOHook {
}
public static boolean hasHerbalismDoubleDrops(Player player) {
return canHook ? McMMOHandler.hasHerbalismDoubleDrops(player) : false;
return canHook && McMMOHandler.hasHerbalismDoubleDrops(player);
}
public static boolean hasMiningDoubleDrops(Player player) {
return canHook ? McMMOHandler.hasMiningDoubleDrops(player) : false;
return canHook && McMMOHandler.hasMiningDoubleDrops(player);
}
public static boolean hasWoodcuttingDoubleDrops(Player player) {
return canHook ? McMMOHandler.hasWoodcuttingDoubleDrops(player) : false;
return canHook && McMMOHandler.hasWoodcuttingDoubleDrops(player);
}
public static boolean isUsingBerserk(Player player) {
return canHook ? McMMOHandler.isUsingBerserk(player) : false;
return canHook && McMMOHandler.isUsingBerserk(player);
}
public static boolean isUsingGigaDrill(Player player) {
return canHook ? McMMOHandler.isUsingGigaDrill(player) : false;
return canHook && McMMOHandler.isUsingGigaDrill(player);
}
public static boolean isUsingGreenTerra(Player player) {
return canHook ? McMMOHandler.isUsingGreenTerra(player) : false;
return canHook && McMMOHandler.isUsingGreenTerra(player);
}
public static boolean isUsingSerratedStrikes(Player player) {
return canHook ? McMMOHandler.isUsingSerratedStrikes(player) : false;
return canHook && McMMOHandler.isUsingSerratedStrikes(player);
}
public static boolean isUsingSkullSplitter(Player player) {
return canHook ? McMMOHandler.isUsingSkullSplitter(player) : false;
return canHook && McMMOHandler.isUsingSkullSplitter(player);
}
public static boolean isUsingSuperBreaker(Player player) {
return canHook ? McMMOHandler.isUsingSuperBreaker(player) : false;
return canHook && McMMOHandler.isUsingSuperBreaker(player);
}
public static boolean isUsingTreeFeller(Player player) {
return canHook ? McMMOHandler.isUsingTreeFeller(player) : false;
return canHook && McMMOHandler.isUsingTreeFeller(player);
}
public static boolean isBleeding(LivingEntity victim) {
return canHook ? McMMOHandler.isBleeding(victim) : false;
return canHook && McMMOHandler.isBleeding(victim);
}
}

View File

@ -35,7 +35,6 @@ import java.util.logging.Level;
import java.util.stream.Collectors;
public final class PluginHook<T extends Class> {
public static final PluginHook ECO_VAULT = new PluginHook(Economy.class, "Vault", VaultEconomy.class);
public static final PluginHook ECO_PLAYER_POINTS = new PluginHook(Economy.class, "PlayerPoints", PlayerPointsEconomy.class);
public static final PluginHook ECO_RESERVE = new PluginHook(Economy.class, "Reserve", ReserveEconomy.class);
@ -65,13 +64,17 @@ public final class PluginHook<T extends Class> {
if (!Hook.class.isAssignableFrom(handler)) {
throw new RuntimeException("Tried to register a non-Hook plugin hook! " + pluginName + " -> " + handler.getName());
}
this.hookGeneric = type;
this.plugin = pluginName;
this.managerClass = handler;
if (hooks == null) {
hooks = new LinkedHashMap();
hooks = new LinkedHashMap<>();
}
hooks.put(handler, this);
// Does this class have a plugin constructor?
try {
pluginConstructor = handler.getDeclaredConstructor(Plugin.class);
@ -89,7 +92,6 @@ public final class PluginHook<T extends Class> {
* Permissible constructors are empty () or (org.bukkit.plugin.Plugin) <br>
* Each plugin defined must use a different handler class.
*
* @param <T>
* @param type Generic hook type for this plugin
* @param pluginName Plugin name
* @param handler Specific class that will handle this plugin, if enabled.
@ -107,6 +109,7 @@ public final class PluginHook<T extends Class> {
for (PluginHook hook : getHooks(type)) {
if (pluginManager.isPluginEnabled(hook.plugin)) {
Hook handler = (Hook) (plugin != null ? hook.load(plugin) : hook.load());
if (handler != null && handler.isEnabled()) {
loaded.put(hook, handler);
}
@ -136,6 +139,7 @@ public final class PluginHook<T extends Class> {
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
Bukkit.getLogger().log(Level.SEVERE, "Unexpected Error while creating a new Hook Manager for " + plugin, ex);
}
return null;
}
@ -148,6 +152,7 @@ public final class PluginHook<T extends Class> {
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
Bukkit.getLogger().log(Level.SEVERE, "Unexpected Error while creating a new Hook Manager for " + plugin, ex);
}
return null;
}
@ -156,6 +161,7 @@ public final class PluginHook<T extends Class> {
int hash = 3;
hash = 37 * hash + Objects.hashCode(this.plugin);
hash = 37 * hash + Objects.hashCode(this.managerClass);
return hash;
}
@ -164,8 +170,8 @@ public final class PluginHook<T extends Class> {
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final PluginHook<?> other = (PluginHook<?>) obj;
return Objects.equals(this.plugin, other.plugin)
&& Objects.equals(this.managerClass, other.managerClass);
return Objects.equals(this.plugin, other.plugin) && Objects.equals(this.managerClass, other.managerClass);
}
}

View File

@ -6,7 +6,6 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class ProtectionManager {
private static final HookManager<Protection> manager = new HookManager(Protection.class);
/**

View File

@ -13,7 +13,6 @@ import java.util.List;
import java.util.Objects;
public class WorldGuardHook {
static boolean canHook = false;
static {
@ -21,7 +20,7 @@ public class WorldGuardHook {
// if this class exists, we're good to use WG classes
Class.forName("com.sk89q.worldguard.protection.flags.Flag");
canHook = true;
} catch (ClassNotFoundException ex) {
} catch (ClassNotFoundException ignore) {
}
}
@ -147,7 +146,7 @@ public class WorldGuardHook {
*/
@NotNull
public static List<String> getRegionNames(@NotNull Location loc) {
return canHook ? WorldGuardRegionHandler.getRegionNames(loc) : Collections.EMPTY_LIST;
return canHook ? WorldGuardRegionHandler.getRegionNames(loc) : Collections.emptyList();
}
/**
@ -157,6 +156,6 @@ public class WorldGuardHook {
*/
@NotNull
public static List<String> getRegionNames(@NotNull Chunk c) {
return canHook ? WorldGuardRegionHandler.getRegionNames(c) : Collections.EMPTY_LIST;
return canHook ? WorldGuardRegionHandler.getRegionNames(c) : Collections.emptyList();
}
}

View File

@ -4,7 +4,6 @@ import com.songoda.core.hooks.Hook;
import org.bukkit.OfflinePlayer;
public abstract class Economy implements Hook {
/**
* Get the players available balance
*

View File

@ -5,7 +5,6 @@ import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
public class PlayerPointsEconomy extends Economy {
private final PlayerPoints playerPoints;
public PlayerPointsEconomy() {
@ -34,18 +33,21 @@ public class PlayerPointsEconomy extends Economy {
@Override
public boolean hasBalance(OfflinePlayer player, double cost) {
int amount = convertAmount(cost);
return playerPoints.getAPI().look(player.getUniqueId()) >= amount;
}
@Override
public boolean withdrawBalance(OfflinePlayer player, double cost) {
int amount = convertAmount(cost);
return playerPoints.getAPI().take(player.getUniqueId(), amount);
}
@Override
public boolean deposit(OfflinePlayer player, double amount) {
int amt = convertAmount(amount);
return playerPoints.getAPI().give(player.getUniqueId(), amt);
}
}

View File

@ -7,12 +7,12 @@ import org.bukkit.OfflinePlayer;
import java.math.BigDecimal;
public class ReserveEconomy extends Economy {
EconomyAPI economyAPI;
public ReserveEconomy() {
if (Reserve.instance().economyProvided())
if (Reserve.instance().economyProvided()) {
economyAPI = Reserve.instance().economy();
}
}
@Override
@ -32,16 +32,16 @@ public class ReserveEconomy extends Economy {
@Override
public boolean hasBalance(OfflinePlayer player, double cost) {
return economyAPI.hasHoldings(player.getUniqueId(), new BigDecimal(cost));
return economyAPI.hasHoldings(player.getUniqueId(), BigDecimal.valueOf(cost));
}
@Override
public boolean withdrawBalance(OfflinePlayer player, double cost) {
return economyAPI.removeHoldings(player.getUniqueId(), new BigDecimal(cost));
return economyAPI.removeHoldings(player.getUniqueId(), BigDecimal.valueOf(cost));
}
@Override
public boolean deposit(OfflinePlayer player, double amount) {
return economyAPI.addHoldings(player.getUniqueId(), new BigDecimal(amount));
return economyAPI.addHoldings(player.getUniqueId(), BigDecimal.valueOf(amount));
}
}

View File

@ -5,12 +5,12 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.RegisteredServiceProvider;
public class VaultEconomy extends Economy {
private final net.milkbowl.vault.economy.Economy vault;
public VaultEconomy() {
// this returns null if we have Vault with no compatible eco plugin
RegisteredServiceProvider<net.milkbowl.vault.economy.Economy> v = Bukkit.getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
if (v != null) {
this.vault = v.getProvider();
} else {
@ -31,8 +31,10 @@ public class VaultEconomy extends Economy {
@Override
public double getBalance(OfflinePlayer player) {
if (vault == null)
if (vault == null) {
return 0;
}
return vault.getBalance(player);
}

View File

@ -17,7 +17,6 @@ import java.util.logging.Level;
import java.util.logging.Logger;
public class CMIHolograms extends Holograms {
private static CMI cmi;
private static HologramManager cmiHologramManager;
private static HashSet<String> ourHolograms = new HashSet<>();
@ -28,14 +27,16 @@ public class CMIHolograms extends Holograms {
try {
useOldMethod = CMIHologram.class.getDeclaredField("lines").getDeclaringClass() == String[].class;
cmi_CMIHologram_getLines = CMIHologram.class.getMethod("getLines");
} catch (NoSuchFieldException | NoSuchMethodException e) {
e.printStackTrace();
} catch (NoSuchFieldException | NoSuchMethodException ex) {
ex.printStackTrace();
}
}
public CMIHolograms(Plugin plugin) {
super(plugin);
cmi = (CMI) Bukkit.getPluginManager().getPlugin("CMI");
if (cmi != null) {
cmiHologramManager = cmi.getHologramManager();
}
@ -64,11 +65,14 @@ public class CMIHolograms extends Holograms {
@Override
public void removeHologram(Location location) {
location = fixLocation(location);
final String id = locStr(location);
CMIHologram holo = cmiHologramManager.getByName(id);
if (holo != null) {
cmiHologramManager.removeHolo(holo);
}
ourHolograms.remove(id);
}
@ -76,10 +80,12 @@ public class CMIHolograms extends Holograms {
public void removeAllHolograms() {
for (String id : ourHolograms) {
CMIHologram holo = cmiHologramManager.getByName(id);
if (holo != null) {
cmiHologramManager.removeHolo(holo);
}
}
ourHolograms.clear();
}
@ -87,6 +93,7 @@ public class CMIHolograms extends Holograms {
public void updateHologram(Location location, List<String> lines) {
location = fixLocation(location);
CMIHologram holo = cmiHologramManager.getByName(locStr(location));
if (holo != null) {
// only update if there is a change to the text
List<String> holoLines;
@ -100,6 +107,7 @@ public class CMIHolograms extends Holograms {
Logger.getLogger(CMIHolograms.class.getName()).log(Level.SEVERE, "CMI Hologram error!", ex);
holoLines = Collections.emptyList();
}
boolean isChanged = lines.size() != holoLines.size();
if (!isChanged) {
// double-check the lines
@ -107,12 +115,15 @@ public class CMIHolograms extends Holograms {
isChanged = !holo.getLine(i).equals(lines.get(i));
}
}
if (isChanged) {
holo.setLines(lines);
holo.update();
}
return;
}
createAt(location, lines);
}
@ -129,6 +140,7 @@ public class CMIHolograms extends Holograms {
private void createAt(Location location, List<String> lines) {
final String id = locStr(location);
CMIHologram holo = new CMIHologram(id, location);
holo.setLines(lines);

View File

@ -9,7 +9,6 @@ import java.util.List;
import java.util.Map;
public abstract class Holograms implements Hook {
protected double xOffset = 0.5;
protected double yOffset = 0.5;
protected double zOffset = 0.5;
@ -24,6 +23,7 @@ public abstract class Holograms implements Hook {
this.xOffset = x;
this.yOffset = y;
this.zOffset = z;
return this;
}
@ -38,6 +38,7 @@ public abstract class Holograms implements Hook {
double x = location.getX();
double y = location.getY();
double z = location.getZ();
return location.clone().add((x - (int) x) + xOffset, (y - (int) y) + yOffset + defaultHeightOffset(), (z - (int) z) + zOffset);
}

View File

@ -13,12 +13,12 @@ import java.util.List;
import java.util.Map;
public class HologramsHolograms extends Holograms {
HologramPlugin hologramPlugin;
HashSet<String> ourHolograms = new HashSet<>();
public HologramsHolograms(Plugin plugin) {
super(plugin);
hologramPlugin = (HologramPlugin) Bukkit.getPluginManager().getPlugin("Holograms");
}
@ -45,12 +45,15 @@ public class HologramsHolograms extends Holograms {
@Override
public void removeHologram(Location location) {
location = fixLocation(location);
final String id = locStr(location);
Hologram hologram = hologramPlugin.getHologramManager().getHologram(id);
if (hologram != null) {
hologram.despawn();
hologramPlugin.getHologramManager().removeActiveHologram(hologram);
}
ourHolograms.remove(id);
}
@ -58,11 +61,13 @@ public class HologramsHolograms extends Holograms {
public void removeAllHolograms() {
for (String id : ourHolograms) {
Hologram hologram = hologramPlugin.getHologramManager().getHologram(id);
if (hologram != null) {
hologram.despawn();
hologramPlugin.getHologramManager().removeActiveHologram(hologram);
}
}
ourHolograms.clear();
}
@ -112,14 +117,15 @@ public class HologramsHolograms extends Holograms {
private void createAt(Location location, List<String> lines) {
final String id = locStr(location);
Hologram hologram = new Hologram(id, location);
for (String line : lines) {
hologram.addLine(new TextLine(hologram, line));
}
hologramPlugin.getHologramManager().addActiveHologram(hologram);
if (!ourHolograms.contains(id))
ourHolograms.add(id);
ourHolograms.add(id);
}
}

View File

@ -11,7 +11,6 @@ import java.util.List;
import java.util.Map;
public class HolographicDisplaysHolograms extends Holograms {
public HolographicDisplaysHolograms(Plugin plugin) {
super(plugin);
}
@ -39,10 +38,14 @@ public class HolographicDisplaysHolograms extends Holograms {
@Override
public void removeHologram(Location location) {
location = fixLocation(location);
for (Hologram hologram : HologramsAPI.getHolograms(plugin)) {
if (hologram.getX() != location.getX()
|| hologram.getY() != location.getY()
|| hologram.getZ() != location.getZ()) continue;
|| hologram.getZ() != location.getZ()) {
continue;
}
hologram.delete();
}
}
@ -63,7 +66,9 @@ public class HolographicDisplaysHolograms extends Holograms {
for (Hologram hologram : holograms) {
if (hologram.getX() != location.getX()
|| hologram.getY() != location.getY()
|| hologram.getZ() != location.getZ()) continue;
|| hologram.getZ() != location.getZ()) {
continue;
}
// only update if there is a change to the text
boolean isChanged = lines.size() != hologram.size();
@ -92,6 +97,7 @@ public class HolographicDisplaysHolograms extends Holograms {
private void createAt(Location location, List<String> lines) {
Hologram hologram = HologramsAPI.createHologram(plugin, location);
for (String line : lines) {
hologram.appendTextLine(line);
}

View File

@ -1,13 +1,13 @@
package com.songoda.core.hooks.jobs;
import com.gamingmesh.jobs.Jobs;
import java.util.List;
import java.util.stream.Collectors;
public class JobsHandler {
public static List<String> getJobs() {
return Jobs.getJobs().stream().map(j -> j.getName()).collect(Collectors.toList());
}
}
package com.songoda.core.hooks.jobs;
import com.gamingmesh.jobs.Jobs;
import com.gamingmesh.jobs.container.Job;
import java.util.List;
import java.util.stream.Collectors;
public class JobsHandler {
public static List<String> getJobs() {
return Jobs.getJobs().stream().map(Job::getName).collect(Collectors.toList());
}
}

View File

@ -1,183 +1,195 @@
package com.songoda.core.hooks.jobs;
import com.gamingmesh.jobs.CMILib.CMIEnchantment;
import com.gamingmesh.jobs.Jobs;
import com.gamingmesh.jobs.actions.BlockActionInfo;
import com.gamingmesh.jobs.actions.CustomKillInfo;
import com.gamingmesh.jobs.actions.EnchantActionInfo;
import com.gamingmesh.jobs.actions.EntityActionInfo;
import com.gamingmesh.jobs.actions.ItemActionInfo;
import com.gamingmesh.jobs.container.ActionType;
import com.gamingmesh.jobs.container.CurrencyType;
import com.gamingmesh.jobs.container.Job;
import com.gamingmesh.jobs.container.JobProgression;
import com.gamingmesh.jobs.container.JobsPlayer;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class JobsPlayerHandler {
protected final JobsPlayer jPlayer;
protected JobsPlayerHandler(JobsPlayer jPlayer) {
this.jPlayer = jPlayer;
}
public static JobsPlayerHandler loadPlayer(Player player) {
JobsPlayer jPlayer = Jobs.getPlayerManager().getJobsPlayer(player);
return jPlayer != null ? new JobsPlayerHandler(jPlayer) : null;
}
public double getBoostExp(String job) {
return jPlayer.getBoost(job, CurrencyType.EXP);
}
public double getBoostMoney(String job) {
return jPlayer.getBoost(job, CurrencyType.MONEY);
}
public double getBoostPoints(String job) {
return jPlayer.getBoost(job, CurrencyType.POINTS);
}
public void promoteJob(String jobName) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.promoteJob(job, 1);
}
}
public void promoteJob(String jobName, int levels) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.promoteJob(job, levels);
}
}
public void demoteJob(String jobName) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.demoteJob(job, 1);
}
}
public void demoteJob(String jobName, int levels) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.demoteJob(job, levels);
}
}
public void joinJob(String jobName) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.joinJob(job);
}
}
public void leaveAllJobs() {
jPlayer.leaveAllJobs();
}
public void leaveJob(String jobName) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.leaveJob(job);
}
}
public int getTotalLevels() {
return jPlayer.getTotalLevels();
}
public int getMaxBrewingStandsAllowed() {
return jPlayer.getMaxBrewingStandsAllowed();
}
public int getMaxFurnacesAllowed() {
return jPlayer.getMaxFurnacesAllowed();
}
public List<String> getJobs() {
return jPlayer.getJobProgression().stream().map(p -> p.getJob().getName()).collect(Collectors.toList());
}
public void eatItem(ItemStack item) {
Jobs.action(jPlayer, new ItemActionInfo(item, ActionType.EAT));
}
public void breakBlock(Block block) {
Jobs.action(jPlayer, new BlockActionInfo(block, ActionType.BREAK), block);
}
public void tntBreakBlock(Block block) {
Jobs.action(jPlayer, new BlockActionInfo(block, ActionType.TNTBREAK), block);
}
public void placeBlock(Block block) {
Jobs.action(jPlayer, new BlockActionInfo(block, ActionType.PLACE), block);
}
public void placeEntity(Entity block) {
Jobs.action(jPlayer, new EntityActionInfo(block, ActionType.PLACE));
}
public void breakEntity(Entity block) {
Jobs.action(jPlayer, new EntityActionInfo(block, ActionType.BREAK));
}
public void breedEntity(LivingEntity entity) {
Jobs.action(jPlayer, new EntityActionInfo(entity, ActionType.BREED));
}
public void killEntity(LivingEntity entity) {
killEntity(entity, jPlayer.getPlayer());
}
public void tameEntity(LivingEntity entity) {
Jobs.action(jPlayer, new EntityActionInfo((Entity) entity, ActionType.TAME));
}
public void catchFish(ItemStack items) {
Jobs.action(jPlayer, new ItemActionInfo(items, ActionType.FISH));
}
public void killEntity(LivingEntity entity, Entity damageSource) {
Jobs.action(jPlayer, new EntityActionInfo(entity, ActionType.KILL), damageSource, entity);
if (entity instanceof Player && !entity.hasMetadata("NPC")) {
JobsPlayer jVictim = Jobs.getPlayerManager().getJobsPlayer((Player) entity);
if (jVictim == null) {
return;
}
List<JobProgression> jobs = jVictim.getJobProgression();
if (jobs == null) {
return;
}
for (JobProgression job : jobs) {
Jobs.action(jPlayer, new CustomKillInfo(job.getJob().getName(), ActionType.CUSTOMKILL), damageSource, entity);
}
}
}
public void itemEnchanted(ItemStack resultStack) {
Map<Enchantment, Integer> enchants = resultStack.getEnchantments();
for (Map.Entry<Enchantment, Integer> oneEnchant : enchants.entrySet()) {
CMIEnchantment e;
String enchantName;
Integer level2;
Enchantment enchant = oneEnchant.getKey();
if (enchant == null || (enchantName = (e = CMIEnchantment.get(enchant)) == null ? null : e.toString()) == null || (level2 = oneEnchant.getValue()) == null) {
continue;
}
Jobs.action(jPlayer, new EnchantActionInfo(enchantName, level2, ActionType.ENCHANT));
}
}
}
package com.songoda.core.hooks.jobs;
import com.gamingmesh.jobs.CMILib.CMIEnchantment;
import com.gamingmesh.jobs.Jobs;
import com.gamingmesh.jobs.actions.BlockActionInfo;
import com.gamingmesh.jobs.actions.CustomKillInfo;
import com.gamingmesh.jobs.actions.EnchantActionInfo;
import com.gamingmesh.jobs.actions.EntityActionInfo;
import com.gamingmesh.jobs.actions.ItemActionInfo;
import com.gamingmesh.jobs.container.ActionType;
import com.gamingmesh.jobs.container.CurrencyType;
import com.gamingmesh.jobs.container.Job;
import com.gamingmesh.jobs.container.JobProgression;
import com.gamingmesh.jobs.container.JobsPlayer;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class JobsPlayerHandler {
protected final JobsPlayer jPlayer;
protected JobsPlayerHandler(JobsPlayer jPlayer) {
this.jPlayer = jPlayer;
}
public static JobsPlayerHandler loadPlayer(Player player) {
JobsPlayer jPlayer = Jobs.getPlayerManager().getJobsPlayer(player);
return jPlayer != null ? new JobsPlayerHandler(jPlayer) : null;
}
public double getBoostExp(String job) {
return jPlayer.getBoost(job, CurrencyType.EXP);
}
public double getBoostMoney(String job) {
return jPlayer.getBoost(job, CurrencyType.MONEY);
}
public double getBoostPoints(String job) {
return jPlayer.getBoost(job, CurrencyType.POINTS);
}
public void promoteJob(String jobName) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.promoteJob(job, 1);
}
}
public void promoteJob(String jobName, int levels) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.promoteJob(job, levels);
}
}
public void demoteJob(String jobName) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.demoteJob(job, 1);
}
}
public void demoteJob(String jobName, int levels) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.demoteJob(job, levels);
}
}
public void joinJob(String jobName) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.joinJob(job);
}
}
public void leaveAllJobs() {
jPlayer.leaveAllJobs();
}
public void leaveJob(String jobName) {
Job job = Jobs.getJob(jobName);
if (job != null) {
jPlayer.leaveJob(job);
}
}
public int getTotalLevels() {
return jPlayer.getTotalLevels();
}
public int getMaxBrewingStandsAllowed() {
return jPlayer.getMaxBrewingStandsAllowed();
}
public int getMaxFurnacesAllowed() {
return jPlayer.getMaxFurnacesAllowed();
}
public List<String> getJobs() {
return jPlayer.getJobProgression().stream().map(p -> p.getJob().getName()).collect(Collectors.toList());
}
public void eatItem(ItemStack item) {
Jobs.action(jPlayer, new ItemActionInfo(item, ActionType.EAT));
}
public void breakBlock(Block block) {
Jobs.action(jPlayer, new BlockActionInfo(block, ActionType.BREAK), block);
}
public void tntBreakBlock(Block block) {
Jobs.action(jPlayer, new BlockActionInfo(block, ActionType.TNTBREAK), block);
}
public void placeBlock(Block block) {
Jobs.action(jPlayer, new BlockActionInfo(block, ActionType.PLACE), block);
}
public void placeEntity(Entity block) {
Jobs.action(jPlayer, new EntityActionInfo(block, ActionType.PLACE));
}
public void breakEntity(Entity block) {
Jobs.action(jPlayer, new EntityActionInfo(block, ActionType.BREAK));
}
public void breedEntity(LivingEntity entity) {
Jobs.action(jPlayer, new EntityActionInfo(entity, ActionType.BREED));
}
public void killEntity(LivingEntity entity) {
killEntity(entity, jPlayer.getPlayer());
}
public void tameEntity(LivingEntity entity) {
Jobs.action(jPlayer, new EntityActionInfo(entity, ActionType.TAME));
}
public void catchFish(ItemStack items) {
Jobs.action(jPlayer, new ItemActionInfo(items, ActionType.FISH));
}
public void killEntity(LivingEntity entity, Entity damageSource) {
Jobs.action(jPlayer, new EntityActionInfo(entity, ActionType.KILL), damageSource, entity);
if (entity instanceof Player && !entity.hasMetadata("NPC")) {
JobsPlayer jVictim = Jobs.getPlayerManager().getJobsPlayer((Player) entity);
if (jVictim == null) {
return;
}
List<JobProgression> jobs = jVictim.getJobProgression();
if (jobs == null) {
return;
}
for (JobProgression job : jobs) {
Jobs.action(jPlayer, new CustomKillInfo(job.getJob().getName(), ActionType.CUSTOMKILL), damageSource, entity);
}
}
}
public void itemEnchanted(ItemStack resultStack) {
Map<Enchantment, Integer> enchants = resultStack.getEnchantments();
for (Map.Entry<Enchantment, Integer> oneEnchant : enchants.entrySet()) {
CMIEnchantment e;
String enchantName;
Integer level2;
Enchantment enchant = oneEnchant.getKey();
if (enchant == null || (enchantName = (e = CMIEnchantment.get(enchant)) == null ? null : e.toString()) == null || (level2 = oneEnchant.getValue()) == null) {
continue;
}
Jobs.action(jPlayer, new EnchantActionInfo(enchantName, level2, ActionType.ENCHANT));
}
}
}

View File

@ -8,7 +8,6 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
public class CoreProtectLog extends Log {
private CoreProtectAPI api;
private boolean useDeprecatedMethod = ServerVersion.isServerVersionAtOrBelow(ServerVersion.V1_12);
@ -30,18 +29,20 @@ public class CoreProtectLog extends Log {
public void logPlacement(OfflinePlayer player, Block block) {
if (this.useDeprecatedMethod) {
this.api.logPlacement(player.getName(), block.getLocation(), block.getType(), block.getData());
} else {
this.api.logPlacement(player.getName(), block.getLocation(), block.getType(), block.getBlockData());
return;
}
this.api.logPlacement(player.getName(), block.getLocation(), block.getType(), block.getBlockData());
}
@Override
public void logRemoval(OfflinePlayer player, Block block) {
if (this.useDeprecatedMethod) {
this.api.logRemoval(player.getName(), block.getLocation(), block.getType(), block.getData());
} else {
this.api.logRemoval(player.getName(), block.getLocation(), block.getType(), block.getBlockData());
return;
}
this.api.logRemoval(player.getName(), block.getLocation(), block.getType(), block.getBlockData());
}
@Override

View File

@ -6,7 +6,6 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
public abstract class Log implements Hook {
public abstract void logPlacement(OfflinePlayer player, Block block);
public abstract void logRemoval(OfflinePlayer player, Block block);

View File

@ -26,7 +26,6 @@ import java.util.logging.Logger;
import java.util.stream.Collectors;
public class McMMOHandler {
static boolean mcmmo_v2 = false;
static boolean legacy_v13 = false;
static boolean legacy_v12 = false;
@ -62,6 +61,7 @@ public class McMMOHandler {
mcmmo_SecondaryAbility_valueOf = mcmmo_SecondaryAbility.getDeclaredMethod("valueOf", String.class);
mcmmo_Permissions_secondaryAbilityEnabled = com.gmail.nossr50.util.Permissions.class.getDeclaredMethod("secondaryAbilityEnabled", Player.class, mcmmo_SecondaryAbility);
mcmmo_SkillUtils_activationSuccessful = com.gmail.nossr50.util.skills.SkillUtils.class.getDeclaredMethod("activationSuccessful", mcmmo_SecondaryAbility, Player.class, int.class, int.class);
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) {
mcmmo_ExperienceConfig_getXp = mcmmo_ExperienceConfig_instance.getClass().getDeclaredMethod("getXp", mcmmo_SkillType, org.bukkit.block.data.BlockData.class);
legacy_v13 = true;
@ -72,8 +72,8 @@ public class McMMOHandler {
mcmmo_ExperienceConfig_getXp = mcmmo_ExperienceConfig_instance.getClass().getDeclaredMethod("getXp", mcmmo_SkillType, org.bukkit.Material.class);
legacy_v8 = true;
}
} catch (Exception ex1) {
Logger.getLogger(McMMOHandler.class.getName()).log(Level.SEVERE, "Failed to register McMMO Legacy Hook", ex1);
} catch (Exception ex2) {
Logger.getLogger(McMMOHandler.class.getName()).log(Level.SEVERE, "Failed to register McMMO Legacy Hook", ex2);
}
}
}
@ -81,296 +81,392 @@ public class McMMOHandler {
public static void addMining(Player player, Collection<Block> blocks) {
if (player == null || blocks == null || blocks.isEmpty()) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
addBlockSkillLegacy(player, blocks, "mining");
return;
}
ArrayList<BlockState> blockStates = blocks.stream().map(b -> b.getState()).collect(Collectors.toCollection(ArrayList::new));
ArrayList<BlockState> blockStates = blocks.stream().map(Block::getState).collect(Collectors.toCollection(ArrayList::new));
ExperienceAPI.addXpFromBlocksBySkill(blockStates, UserManager.getPlayer(player), PrimarySkillType.MINING);
}
public static void addExcavation(Player player, Collection<Block> blocks) {
if (player == null || blocks == null || blocks.isEmpty()) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
addBlockSkillLegacy(player, blocks, "excavation");
return;
}
ArrayList<BlockState> blockStates = blocks.stream().map(b -> b.getState()).collect(Collectors.toCollection(ArrayList::new));
ArrayList<BlockState> blockStates = blocks.stream().map(Block::getState).collect(Collectors.toCollection(ArrayList::new));
ExperienceAPI.addXpFromBlocksBySkill(blockStates, UserManager.getPlayer(player), PrimarySkillType.EXCAVATION);
}
public static void addHerbalism(Player player, Collection<Block> blocks) {
if (player == null || blocks == null || blocks.isEmpty()) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
addBlockSkillLegacy(player, blocks, "herbalism");
return;
}
ArrayList<BlockState> blockStates = blocks.stream().map(b -> b.getState()).collect(Collectors.toCollection(ArrayList::new));
ArrayList<BlockState> blockStates = blocks.stream().map(Block::getState).collect(Collectors.toCollection(ArrayList::new));
ExperienceAPI.addXpFromBlocksBySkill(blockStates, UserManager.getPlayer(player), PrimarySkillType.HERBALISM);
}
public static void addWoodcutting(Player player, Collection<Block> blocks) {
if (player == null || blocks == null || blocks.isEmpty()) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
addBlockSkillLegacy(player, blocks, "woodcutting");
return;
}
ArrayList<BlockState> blockStates = blocks.stream().map(b -> b.getState()).collect(Collectors.toCollection(ArrayList::new));
ArrayList<BlockState> blockStates = blocks.stream().map(Block::getState).collect(Collectors.toCollection(ArrayList::new));
ExperienceAPI.addXpFromBlocksBySkill(blockStates, UserManager.getPlayer(player), PrimarySkillType.WOODCUTTING);
}
public static int getAcrobaticsSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "acrobatics");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.ACROBATICS);
}
public static int getAlchemySkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "alchemy");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.ALCHEMY);
}
public static int getArcherySkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "archery");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.ARCHERY);
}
public static int getAxesSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "axes");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.AXES);
}
public static int getExcavationSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "excavation");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.EXCAVATION);
}
public static int getFishingSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "fishing");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.FISHING);
}
public static int getHerbalismSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "herbalism");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.HERBALISM);
}
public static int getMiningSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "mining");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.MINING);
}
public static int getRepairSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "repair");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.REPAIR);
}
public static int getSmeltingSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "smelting");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.SMELTING);
}
public static int getSwordsSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "swords");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.SWORDS);
}
public static int getTamingSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "taming");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.TAMING);
}
public static int getUnarmedSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "unarmed");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.UNARMED);
}
public static int getWoodcuttingSkill(Player player) {
if (player == null) {
return -1;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
return getSkillLegacy(player, "woodcutting");
}
return UserManager.getPlayer(player).getSkillLevel(PrimarySkillType.WOODCUTTING);
}
public static void addAcrobatics(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "acrobatics", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.ACROBATICS, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addAlchemy(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "alchemy", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.ALCHEMY, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addArchery(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "archery", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.ARCHERY, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addAxes(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "axes", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.AXES, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addExcavation(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "excavation", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.EXCAVATION, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addFishing(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "fishing", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.FISHING, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addHerbalism(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "herbalism", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.HERBALISM, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addMining(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "mining", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.MINING, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addRepair(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "repair", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.REPAIR, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addSmelting(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "smelting", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.SMELTING, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addSwords(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "swords", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.SWORDS, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addTaming(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "taming", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.TAMING, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addUnarmed(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "unarmed", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.UNARMED, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
public static void addWoodcutting(Player player, int xp) {
if (player == null) {
return;
} else if (legacy_v13 || legacy_v12 || legacy_v8) {
}
if (legacy_v13 || legacy_v12 || legacy_v8) {
ExperienceAPI.addXP(player, "woodcutting", xp);
}
UserManager.getPlayer(player).beginXpGain(PrimarySkillType.WOODCUTTING, xp, XPGainReason.UNKNOWN, XPGainSource.CUSTOM);
}
@ -455,22 +551,25 @@ public class McMMOHandler {
if (player.hasMetadata("mcMMO: Player Data")) {
try {
Object skillType = mcmmo_SkillType_valueOf.invoke(null, skill.toUpperCase());
if ((boolean) mcmmo_SkillType_getDoubleDropsDisabled.invoke(skillType)) {
return false;
}
int skillLevel = (int) mcmmo_McMMOPlayer_getSkillLevel.invoke(UserManager.getPlayer(player), skillType);
int activationChance = (int) mcmmo_PerksUtils_handleLuckyPerks.invoke(null, player, skillType);
Object secondaryDouble = mcmmo_SecondaryAbility_valueOf.invoke(null, skill.toUpperCase() + "_DOUBLE_DROPS");
if (!((boolean) mcmmo_Permissions_secondaryAbilityEnabled.invoke(null, player, secondaryDouble))) {
return false;
}
return (boolean) mcmmo_SkillUtils_activationSuccessful.invoke(null, secondaryDouble, player, skillLevel, activationChance);
} catch (Exception ex1) {
Logger.getLogger(McMMOHandler.class.getName()).log(Level.SEVERE, "Failed to invoke McMMO Legacy Hook", ex1);
} catch (Exception ex) {
Logger.getLogger(McMMOHandler.class.getName()).log(Level.SEVERE, "Failed to invoke McMMO Legacy Hook", ex);
}
}
return false;
}
@ -484,30 +583,34 @@ public class McMMOHandler {
}
ExperienceAPI.addXP(player, skill, xp);
} catch (Exception ex1) {
Logger.getLogger(McMMOHandler.class.getName()).log(Level.SEVERE, "Failed to invoke McMMO Legacy Hook", ex1);
} catch (Exception ex) {
Logger.getLogger(McMMOHandler.class.getName()).log(Level.SEVERE, "Failed to invoke McMMO Legacy Hook", ex);
}
}
protected static Object legacy_getBlock(Block block) {
if (legacy_v13) {
return block.getBlockData();
} else if (legacy_v12) {
return block.getState().getData();
} else {
return block.getType();
}
if (legacy_v12) {
return block.getState().getData();
}
return block.getType();
}
protected static int getSkillLegacy(Player player, String skill) {
if (player.hasMetadata("mcMMO: Player Data")) {
try {
Object skillType = mcmmo_SkillType_valueOf.invoke(null, skill.toUpperCase());
return (int) mcmmo_McMMOPlayer_getSkillLevel.invoke(UserManager.getPlayer(player), skillType);
} catch (Exception ex1) {
Logger.getLogger(McMMOHandler.class.getName()).log(Level.SEVERE, "Failed to invoke McMMO Legacy Hook", ex1);
} catch (Exception ex) {
Logger.getLogger(McMMOHandler.class.getName()).log(Level.SEVERE, "Failed to invoke McMMO Legacy Hook", ex);
}
}
return 0;
}
}

View File

@ -13,11 +13,11 @@ import world.bentobox.bentobox.managers.IslandsManager;
import java.util.Optional;
public class BentoBoxProtection extends Protection {
private final IslandsManager islandsManager;
public BentoBoxProtection(Plugin plugin) {
super(plugin);
this.islandsManager = BentoBox.getInstance().getIslands();
}

View File

@ -8,38 +8,44 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class GriefPreventionProtection extends Protection {
private final DataStore dataStore;
public GriefPreventionProtection(Plugin plugin) {
super(plugin);
this.dataStore = GriefPrevention.instance.dataStore;
}
@Override
public boolean canPlace(Player player, Location location) {
Claim claim = getClaim(location);
if (claim == null) {
return true;
}
return claim.allowBuild(player, location.getBlock().getType()) == null;
}
@Override
public boolean canBreak(Player player, Location location) {
Claim claim = getClaim(location);
if (claim == null) {
return true;
}
return claim.allowBreak(player, location.getBlock().getType()) == null;
}
@Override
public boolean canInteract(Player player, Location location) {
Claim claim = getClaim(location);
if (claim == null) {
return true;
}
return claim.allowContainers(player) == null;
}

View File

@ -8,11 +8,11 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class LandsProtection extends Protection {
private final LandsIntegration landsIntegration;
public LandsProtection(Plugin plugin) {
super(plugin);
this.landsIntegration = new LandsIntegration(plugin);
}
@ -33,6 +33,7 @@ public class LandsProtection extends Protection {
private boolean hasPerms(Player player, Location location, RoleSetting roleSetting) {
Area area = landsIntegration.getAreaByLoc(location);
if (area == null) {
return true;
}

View File

@ -6,7 +6,6 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public abstract class Protection implements Hook {
protected final Plugin plugin;
public Protection(Plugin plugin) {

View File

@ -8,17 +8,18 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class RedProtectProtection extends Protection {
private final RedProtectAPI api;
public RedProtectProtection(Plugin plugin) {
super(plugin);
this.api = RedProtect.get().getAPI();
}
@Override
public boolean canPlace(Player player, Location location) {
Region region = api.getRegion(location);
if (region == null) {
return true;
}
@ -29,6 +30,7 @@ public class RedProtectProtection extends Protection {
@Override
public boolean canBreak(Player player, Location location) {
Region region = api.getRegion(location);
if (region == null) {
return true;
}
@ -39,6 +41,7 @@ public class RedProtectProtection extends Protection {
@Override
public boolean canInteract(Player player, Location location) {
Region region = api.getRegion(location);
if (region == null) {
return true;
}

Some files were not shown because too many files have changed in this diff Show More