mirror of
https://github.com/songoda/SongodaCore.git
synced 2024-11-27 12:35:12 +01:00
Merge branch 'development'
This commit is contained in:
commit
e65dcc67cb
311
.editorconfig
Normal file
311
.editorconfig
Normal file
@ -0,0 +1,311 @@
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
# max_line_length = 120
|
||||
tab_width = 4
|
||||
trim_trailing_whitespace = true
|
||||
ij_continuation_indent_size = 8
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = false
|
||||
ij_smart_tabs = false
|
||||
ij_visual_guides = none
|
||||
ij_wrap_on_typing = false
|
||||
|
||||
[*.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
|
||||
ij_java_align_multiline_annotation_parameters = false
|
||||
ij_java_align_multiline_array_initializer_expression = false
|
||||
ij_java_align_multiline_assignment = false
|
||||
ij_java_align_multiline_binary_operation = false
|
||||
ij_java_align_multiline_chained_methods = false
|
||||
ij_java_align_multiline_extends_list = false
|
||||
ij_java_align_multiline_for = true
|
||||
ij_java_align_multiline_method_parentheses = false
|
||||
ij_java_align_multiline_parameters = true
|
||||
ij_java_align_multiline_parameters_in_calls = false
|
||||
ij_java_align_multiline_parenthesized_expression = false
|
||||
ij_java_align_multiline_records = true
|
||||
ij_java_align_multiline_resources = true
|
||||
ij_java_align_multiline_ternary_operation = false
|
||||
ij_java_align_multiline_text_blocks = false
|
||||
ij_java_align_multiline_throws_list = false
|
||||
ij_java_align_subsequent_simple_methods = false
|
||||
ij_java_align_throws_keyword = false
|
||||
ij_java_annotation_parameter_wrap = off
|
||||
ij_java_array_initializer_new_line_after_left_brace = false
|
||||
ij_java_array_initializer_right_brace_on_new_line = false
|
||||
ij_java_array_initializer_wrap = off
|
||||
ij_java_assert_statement_colon_on_next_line = false
|
||||
ij_java_assert_statement_wrap = off
|
||||
ij_java_assignment_wrap = off
|
||||
ij_java_binary_operation_sign_on_next_line = false
|
||||
ij_java_binary_operation_wrap = off
|
||||
ij_java_blank_lines_after_anonymous_class_header = 0
|
||||
ij_java_blank_lines_after_class_header = 0
|
||||
ij_java_blank_lines_after_imports = 1
|
||||
ij_java_blank_lines_after_package = 1
|
||||
ij_java_blank_lines_around_class = 1
|
||||
ij_java_blank_lines_around_field = 0
|
||||
ij_java_blank_lines_around_field_in_interface = 0
|
||||
ij_java_blank_lines_around_initializer = 1
|
||||
ij_java_blank_lines_around_method = 1
|
||||
ij_java_blank_lines_around_method_in_interface = 1
|
||||
ij_java_blank_lines_before_class_end = 0
|
||||
ij_java_blank_lines_before_imports = 1
|
||||
ij_java_blank_lines_before_method_body = 0
|
||||
ij_java_blank_lines_before_package = 0
|
||||
ij_java_block_brace_style = end_of_line
|
||||
ij_java_block_comment_at_first_column = true
|
||||
ij_java_builder_methods = none
|
||||
ij_java_call_parameters_new_line_after_left_paren = false
|
||||
ij_java_call_parameters_right_paren_on_new_line = false
|
||||
ij_java_call_parameters_wrap = off
|
||||
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_names_in_javadoc = 1
|
||||
ij_java_do_not_indent_top_level_class_members = false
|
||||
ij_java_do_not_wrap_after_single_annotation = false
|
||||
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_align_exception_comments = true
|
||||
ij_java_doc_align_param_comments = true
|
||||
ij_java_doc_do_not_wrap_if_one_line = true
|
||||
ij_java_doc_enable_formatting = true
|
||||
ij_java_doc_enable_leading_asterisks = true
|
||||
ij_java_doc_indent_on_continuation = true
|
||||
ij_java_doc_keep_empty_lines = true
|
||||
ij_java_doc_keep_empty_parameter_tag = true
|
||||
ij_java_doc_keep_empty_return_tag = true
|
||||
ij_java_doc_keep_empty_throws_tag = true
|
||||
ij_java_doc_keep_invalid_tags = true
|
||||
ij_java_doc_param_description_on_new_line = false
|
||||
ij_java_doc_preserve_line_breaks = false
|
||||
ij_java_doc_use_throws_not_exception_tag = true
|
||||
ij_java_else_on_new_line = false
|
||||
ij_java_enum_constants_wrap = off
|
||||
ij_java_extends_keyword_wrap = off
|
||||
ij_java_extends_list_wrap = off
|
||||
ij_java_field_annotation_wrap = split_into_lines
|
||||
ij_java_finally_on_new_line = false
|
||||
ij_java_for_brace_force = never
|
||||
ij_java_for_statement_new_line_after_left_paren = false
|
||||
ij_java_for_statement_right_paren_on_new_line = false
|
||||
ij_java_for_statement_wrap = off
|
||||
ij_java_generate_final_locals = false
|
||||
ij_java_generate_final_parameters = false
|
||||
ij_java_if_brace_force = never
|
||||
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_builder_methods_indents = false
|
||||
ij_java_keep_control_statement_in_one_line = true
|
||||
ij_java_keep_first_column_comment = true
|
||||
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_label_indent_absolute = false
|
||||
ij_java_label_indent_size = 0
|
||||
ij_java_lambda_brace_style = end_of_line
|
||||
ij_java_layout_static_imports_separately = true
|
||||
ij_java_line_comment_add_space = false
|
||||
ij_java_line_comment_at_first_column = true
|
||||
ij_java_method_annotation_wrap = split_into_lines
|
||||
ij_java_method_brace_style = end_of_line
|
||||
ij_java_method_call_chain_wrap = off
|
||||
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_new_line_after_lparen_in_record_header = false
|
||||
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
|
||||
ij_java_place_assignment_sign_on_next_line = false
|
||||
ij_java_prefer_longer_names = true
|
||||
ij_java_prefer_parameters_wrap = false
|
||||
ij_java_record_components_wrap = normal
|
||||
ij_java_repeat_synchronized = true
|
||||
ij_java_replace_instanceof_and_cast = true
|
||||
ij_java_replace_null_check = true
|
||||
ij_java_replace_sum_lambda_with_method_ref = true
|
||||
ij_java_resource_list_new_line_after_left_paren = false
|
||||
ij_java_resource_list_right_paren_on_new_line = false
|
||||
ij_java_resource_list_wrap = off
|
||||
ij_java_rparen_on_new_line_in_record_header = false
|
||||
ij_java_space_after_closing_angle_bracket_in_type_argument = false
|
||||
ij_java_space_after_colon = true
|
||||
ij_java_space_after_comma = true
|
||||
ij_java_space_after_comma_in_type_arguments = true
|
||||
ij_java_space_after_for_semicolon = true
|
||||
ij_java_space_after_quest = true
|
||||
ij_java_space_after_type_cast = true
|
||||
ij_java_space_before_annotation_array_initializer_left_brace = false
|
||||
ij_java_space_before_annotation_parameter_list = false
|
||||
ij_java_space_before_array_initializer_left_brace = true
|
||||
ij_java_space_before_catch_keyword = true
|
||||
ij_java_space_before_catch_left_brace = true
|
||||
ij_java_space_before_catch_parentheses = true
|
||||
ij_java_space_before_class_left_brace = true
|
||||
ij_java_space_before_colon = true
|
||||
ij_java_space_before_colon_in_foreach = true
|
||||
ij_java_space_before_comma = false
|
||||
ij_java_space_before_do_left_brace = true
|
||||
ij_java_space_before_else_keyword = true
|
||||
ij_java_space_before_else_left_brace = true
|
||||
ij_java_space_before_finally_keyword = true
|
||||
ij_java_space_before_finally_left_brace = true
|
||||
ij_java_space_before_for_left_brace = true
|
||||
ij_java_space_before_for_parentheses = true
|
||||
ij_java_space_before_for_semicolon = false
|
||||
ij_java_space_before_if_left_brace = true
|
||||
ij_java_space_before_if_parentheses = true
|
||||
ij_java_space_before_method_call_parentheses = false
|
||||
ij_java_space_before_method_left_brace = true
|
||||
ij_java_space_before_method_parentheses = false
|
||||
ij_java_space_before_opening_angle_bracket_in_type_parameter = false
|
||||
ij_java_space_before_quest = true
|
||||
ij_java_space_before_switch_left_brace = true
|
||||
ij_java_space_before_switch_parentheses = true
|
||||
ij_java_space_before_synchronized_left_brace = true
|
||||
ij_java_space_before_synchronized_parentheses = true
|
||||
ij_java_space_before_try_left_brace = true
|
||||
ij_java_space_before_try_parentheses = true
|
||||
ij_java_space_before_type_parameter_list = false
|
||||
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_method_call_parentheses = false
|
||||
ij_java_space_within_empty_method_parentheses = false
|
||||
ij_java_spaces_around_additive_operators = true
|
||||
ij_java_spaces_around_assignment_operators = true
|
||||
ij_java_spaces_around_bitwise_operators = true
|
||||
ij_java_spaces_around_equality_operators = true
|
||||
ij_java_spaces_around_lambda_arrow = true
|
||||
ij_java_spaces_around_logical_operators = true
|
||||
ij_java_spaces_around_method_ref_dbl_colon = false
|
||||
ij_java_spaces_around_multiplicative_operators = true
|
||||
ij_java_spaces_around_relational_operators = true
|
||||
ij_java_spaces_around_shift_operators = true
|
||||
ij_java_spaces_around_type_bounds_in_type_parameters = true
|
||||
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_brackets = false
|
||||
ij_java_spaces_within_cast_parentheses = false
|
||||
ij_java_spaces_within_catch_parentheses = false
|
||||
ij_java_spaces_within_for_parentheses = false
|
||||
ij_java_spaces_within_if_parentheses = false
|
||||
ij_java_spaces_within_method_call_parentheses = false
|
||||
ij_java_spaces_within_method_parentheses = false
|
||||
ij_java_spaces_within_parentheses = false
|
||||
ij_java_spaces_within_record_header = false
|
||||
ij_java_spaces_within_switch_parentheses = false
|
||||
ij_java_spaces_within_synchronized_parentheses = false
|
||||
ij_java_spaces_within_try_parentheses = false
|
||||
ij_java_spaces_within_while_parentheses = false
|
||||
ij_java_special_else_if_treatment = true
|
||||
ij_java_subclass_name_suffix = Impl
|
||||
ij_java_ternary_operation_signs_on_next_line = false
|
||||
ij_java_ternary_operation_wrap = off
|
||||
ij_java_test_name_suffix = Test
|
||||
ij_java_throws_keyword_wrap = off
|
||||
ij_java_throws_list_wrap = off
|
||||
ij_java_use_external_annotations = false
|
||||
ij_java_use_fq_class_names = false
|
||||
ij_java_use_relative_indents = false
|
||||
ij_java_use_single_class_imports = true
|
||||
ij_java_variable_annotation_wrap = off
|
||||
ij_java_visibility = public
|
||||
ij_java_while_brace_force = never
|
||||
ij_java_while_on_new_line = false
|
||||
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
|
||||
|
||||
[.editorconfig]
|
||||
ij_editorconfig_align_group_field_declarations = false
|
||||
ij_editorconfig_space_after_colon = false
|
||||
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
|
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: songoda
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
11
.github/dependabot.yml
vendored
Normal file
11
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "maven" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "monthly"
|
41
.github/workflows/maven.yml
vendored
41
.github/workflows/maven.yml
vendored
@ -5,20 +5,39 @@ name: Build SongodaCore
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
branches: [ master, development ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
types: [ opened, synchronize, reopened ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 16
|
||||
- name: Build with Maven
|
||||
run: mvn -B package --file pom.xml
|
||||
# Setup Java
|
||||
- uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: 16
|
||||
distribution: adopt
|
||||
|
||||
# Checkout project files
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# Caches
|
||||
- name: 'Cache: Maven'
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: ${{ runner.os }}-maven-
|
||||
|
||||
# Build project
|
||||
- name: Build with Maven
|
||||
run: 'mvn -B -Duser.name="GitHub Runner on $GITHUB_REPOSITORY (id=$GITHUB_RUN_ID)" clean package'
|
||||
|
||||
# Upload build artifacts
|
||||
- name: 'Upload Build Artifact: SongodaCore-*.jar'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: SongodaCore-artifacts
|
||||
path: ./Core/target/SongodaCore-*.jar
|
||||
|
226
.gitignore
vendored
226
.gitignore
vendored
@ -1,214 +1,24 @@
|
||||
### Eclipse ###
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
.recommenders
|
||||
##
|
||||
# JetBrains IDEs
|
||||
##
|
||||
/.idea/
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT- autotools
|
||||
.autotools
|
||||
|
||||
# Java annotation processor (APT)
|
||||
.factorypath
|
||||
|
||||
# PDT-specific (PHP Development Tools)
|
||||
.buildpath
|
||||
|
||||
# sbteclipse plugin
|
||||
.target
|
||||
|
||||
# Tern plugin
|
||||
.tern-project
|
||||
|
||||
# TeXlipse plugin
|
||||
.texlipse
|
||||
|
||||
# STS (Spring Tool Suite)
|
||||
.springBeans
|
||||
|
||||
# Code Recommenders
|
||||
.recommenders/
|
||||
|
||||
# Annotation Processing
|
||||
.apt_generated/
|
||||
|
||||
# Scala IDE specific (Scala & Java development for Eclipse)
|
||||
.cache-main
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
|
||||
### Eclipse Patch ###
|
||||
# Eclipse Core
|
||||
.project
|
||||
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
# Annotation Processing
|
||||
.apt_generated
|
||||
|
||||
.sts4-cache/
|
||||
|
||||
### Intellij ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
auto-import.
|
||||
.idea/modules.xml
|
||||
.idea/*.iml
|
||||
.idea/modules
|
||||
# Don't exclude files that might not be related to the IDE
|
||||
*.iml
|
||||
*.ipr
|
||||
/*/*.iml
|
||||
/NMS/*/*.iml
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
##
|
||||
# Maven
|
||||
##
|
||||
# Don't exclude a 'target' package by accident
|
||||
/target/
|
||||
/*/target/
|
||||
/NMS/*/target/
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### Intellij Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
*.iml
|
||||
modules.xml
|
||||
.idea/misc.xml
|
||||
*.ipr
|
||||
.idea/compiler.xml
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/**/sonarlint/
|
||||
|
||||
# SonarQube Plugin
|
||||
.idea/**/sonarIssues.xml
|
||||
|
||||
# Markdown Navigator plugin
|
||||
.idea/**/markdown-navigator.xml
|
||||
.idea/**/markdown-navigator/
|
||||
|
||||
### Java ###
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
### Maven ###
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
.mvn/wrapper/maven-wrapper.jar
|
||||
.flattened-pom.xml
|
||||
|
||||
### NetBeans ###
|
||||
**/nbproject/private/
|
||||
**/nbproject/Makefile-*.mk
|
||||
**/nbproject/Package-*.bash
|
||||
build/
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
||||
|
||||
### Gradle ###
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
|
||||
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
||||
# gradle/wrapper/gradle-wrapper.properties
|
||||
|
||||
### Gradle Patch ###
|
||||
**/build/
|
||||
|
||||
.DS_Store
|
||||
##
|
||||
# Misc.
|
||||
##
|
||||
.DS_Store
|
||||
|
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/Compatibility/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/Core/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-API/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_10_R1/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_11_R1/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_12_R1/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_13_R1/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_13_R2/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_14_R1/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_15_R1/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_16_R1/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_16_R2/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_16_R3/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_17_R1/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_8_R1/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_8_R2/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_8_R3/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_9_R1/src" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS/NMS-v1_9_R2/src" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="spigot-repo" />
|
||||
<option name="name" value="spigot-repo" />
|
||||
<option name="url" value="https://hub.spigotmc.org/nexus/content/repositories/snapshots/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Central Repository" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jitpack.io" />
|
||||
<option name="name" value="jitpack.io" />
|
||||
<option name="url" value="https://jitpack.io" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="CodeMC" />
|
||||
<option name="name" value="CodeMC" />
|
||||
<option name="url" value="https://repo.codemc.org/repository/maven-public" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="public" />
|
||||
<option name="name" value="public" />
|
||||
<option name="url" value="https://repo.songoda.com/repository/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
@ -1,29 +1,33 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.songoda</groupId>
|
||||
<artifactId>SongodaCore-Modules</artifactId>
|
||||
<version>2.5.7</version>
|
||||
<relativePath>../</relativePath>
|
||||
<version>2.5.8</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>SongodaCore-Compatibility</artifactId>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>13.0</version>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.17-R0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>us.myles.viaversion-bukkit</groupId>
|
||||
<artifactId>ViaVersion</artifactId>
|
||||
<version>2.1.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>protocolsupport</groupId>
|
||||
<artifactId>ProtocolSupport</artifactId>
|
||||
@ -31,4 +35,4 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
|
@ -1,114 +1,115 @@
|
||||
package com.songoda.core.compatibility;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Handy reference for checking a connected client's Minecraft version<br>
|
||||
* NOTE: this is automatically initialized through SongodaCore
|
||||
*/
|
||||
public class ClientVersion {
|
||||
|
||||
static HashMap<UUID, ServerVersion> players = new HashMap();
|
||||
|
||||
/**
|
||||
* Check to see what client version this player is connected to the server
|
||||
* with. Note that if a player is connecting with a newer client than the server,
|
||||
* this value will simply be the server version.
|
||||
*
|
||||
* @param player Player to check
|
||||
* @return ServerVersion that matches this player's Minecraft version
|
||||
*/
|
||||
public static ServerVersion getClientVersion(Player player) {
|
||||
if (player == null || !players.containsKey(player.getUniqueId())) {
|
||||
return ServerVersion.getServerVersion();
|
||||
}
|
||||
return players.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Do Not Use: This is handled by SongodaCore.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void onLoginProtocol(Player p, JavaPlugin plugin) {
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
if (p.isOnline()) {
|
||||
final int version = protocolsupport.api.ProtocolSupportAPI.getProtocolVersion(p).getId();
|
||||
players.put(p.getUniqueId(), protocolToVersion(version));
|
||||
}
|
||||
}, 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do Not Use: This is handled by SongodaCore.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void onLoginVia(Player p, JavaPlugin plugin) {
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
if (p.isOnline()) {
|
||||
final int version = us.myles.ViaVersion.api.Via.getAPI().getPlayerVersion(p.getUniqueId());
|
||||
players.put(p.getUniqueId(), protocolToVersion(version));
|
||||
}
|
||||
}, 20);
|
||||
}
|
||||
|
||||
private static ServerVersion protocolToVersion(int version) {
|
||||
// https://github.com/ViaVersion/ViaVersion/blob/master/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java
|
||||
// https://github.com/ProtocolSupport/ProtocolSupport/blob/master/src/protocolsupport/api/ProtocolVersion.java
|
||||
switch (version) {
|
||||
case 4:
|
||||
case 5:
|
||||
return ServerVersion.V1_7;
|
||||
case 47:
|
||||
return ServerVersion.V1_8;
|
||||
case 107:
|
||||
case 108:
|
||||
case 109:
|
||||
case 110:
|
||||
return ServerVersion.V1_9;
|
||||
case 210:
|
||||
return ServerVersion.V1_10;
|
||||
case 315:
|
||||
case 316:
|
||||
return ServerVersion.V1_11;
|
||||
case 335:
|
||||
case 338:
|
||||
case 340:
|
||||
return ServerVersion.V1_12;
|
||||
case 393:
|
||||
case 401:
|
||||
case 404:
|
||||
return ServerVersion.V1_13;
|
||||
case 477:
|
||||
case 485:
|
||||
case 490:
|
||||
case 498:
|
||||
return ServerVersion.V1_14;
|
||||
case 573:
|
||||
case 575:
|
||||
case 578:
|
||||
return ServerVersion.V1_15;
|
||||
case 735:
|
||||
case 736:
|
||||
case 751:
|
||||
case 753:
|
||||
case 754:
|
||||
return ServerVersion.V1_16;
|
||||
case 755:
|
||||
return ServerVersion.V1_17;
|
||||
}
|
||||
return version > 498 ? ServerVersion.getServerVersion() : ServerVersion.UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do Not Use: This is handled by SongodaCore.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void onLogout(Player p) {
|
||||
players.remove(p.getUniqueId());
|
||||
}
|
||||
}
|
||||
package com.songoda.core.compatibility;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Handy reference for checking a connected client's Minecraft version<br>
|
||||
* NOTE: this is automatically initialized through SongodaCore
|
||||
*/
|
||||
public class ClientVersion {
|
||||
|
||||
static HashMap<UUID, ServerVersion> players = new HashMap();
|
||||
|
||||
/**
|
||||
* Check to see what client version this player is connected to the server
|
||||
* with. Note that if a player is connecting with a newer client than the server,
|
||||
* this value will simply be the server version.
|
||||
*
|
||||
* @param player Player to check
|
||||
*
|
||||
* @return ServerVersion that matches this player's Minecraft version
|
||||
*/
|
||||
public static ServerVersion getClientVersion(Player player) {
|
||||
if (player == null || !players.containsKey(player.getUniqueId())) {
|
||||
return ServerVersion.getServerVersion();
|
||||
}
|
||||
return players.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Do Not Use: This is handled by SongodaCore.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void onLoginProtocol(Player p, JavaPlugin plugin) {
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
if (p.isOnline()) {
|
||||
final int version = protocolsupport.api.ProtocolSupportAPI.getProtocolVersion(p).getId();
|
||||
players.put(p.getUniqueId(), protocolToVersion(version));
|
||||
}
|
||||
}, 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do Not Use: This is handled by SongodaCore.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void onLoginVia(Player p, JavaPlugin plugin) {
|
||||
Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
if (p.isOnline()) {
|
||||
final int version = us.myles.ViaVersion.api.Via.getAPI().getPlayerVersion(p.getUniqueId());
|
||||
players.put(p.getUniqueId(), protocolToVersion(version));
|
||||
}
|
||||
}, 20);
|
||||
}
|
||||
|
||||
private static ServerVersion protocolToVersion(int version) {
|
||||
// https://github.com/ViaVersion/ViaVersion/blob/master/common/src/main/java/us/myles/ViaVersion/api/protocol/ProtocolVersion.java
|
||||
// https://github.com/ProtocolSupport/ProtocolSupport/blob/master/src/protocolsupport/api/ProtocolVersion.java
|
||||
switch (version) {
|
||||
case 4:
|
||||
case 5:
|
||||
return ServerVersion.V1_7;
|
||||
case 47:
|
||||
return ServerVersion.V1_8;
|
||||
case 107:
|
||||
case 108:
|
||||
case 109:
|
||||
case 110:
|
||||
return ServerVersion.V1_9;
|
||||
case 210:
|
||||
return ServerVersion.V1_10;
|
||||
case 315:
|
||||
case 316:
|
||||
return ServerVersion.V1_11;
|
||||
case 335:
|
||||
case 338:
|
||||
case 340:
|
||||
return ServerVersion.V1_12;
|
||||
case 393:
|
||||
case 401:
|
||||
case 404:
|
||||
return ServerVersion.V1_13;
|
||||
case 477:
|
||||
case 485:
|
||||
case 490:
|
||||
case 498:
|
||||
return ServerVersion.V1_14;
|
||||
case 573:
|
||||
case 575:
|
||||
case 578:
|
||||
return ServerVersion.V1_15;
|
||||
case 735:
|
||||
case 736:
|
||||
case 751:
|
||||
case 753:
|
||||
case 754:
|
||||
return ServerVersion.V1_16;
|
||||
case 755:
|
||||
return ServerVersion.V1_17;
|
||||
}
|
||||
return version > 498 ? ServerVersion.getServerVersion() : ServerVersion.UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do Not Use: This is handled by SongodaCore.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void onLogout(Player p) {
|
||||
players.remove(p.getUniqueId());
|
||||
}
|
||||
}
|
@ -131,12 +131,12 @@ public enum CompatibleBiome {
|
||||
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_15)) {
|
||||
try {
|
||||
Class<?> classBiomeBase = ClassMapping.BIOME_BASE.getClazz(),
|
||||
classCraftChunk = ClassMapping.CRAFT_CHUNK.getClazz(),
|
||||
classCraftBlock = ClassMapping.CRAFT_BLOCK.getClazz(),
|
||||
classChunk = ClassMapping.CHUNK.getClazz(),
|
||||
classBiomeStorage = ClassMapping.BIOME_STORAGE.getClazz(),
|
||||
classIRegistry = ClassMapping.I_REGISTRY.getClazz();
|
||||
Class<?> classBiomeBase = ClassMapping.BIOME_BASE.getClazz(),
|
||||
classCraftChunk = ClassMapping.CRAFT_CHUNK.getClazz(),
|
||||
classCraftBlock = ClassMapping.CRAFT_BLOCK.getClazz(),
|
||||
classChunk = ClassMapping.CHUNK.getClazz(),
|
||||
classBiomeStorage = ClassMapping.BIOME_STORAGE.getClazz(),
|
||||
classIRegistry = ClassMapping.I_REGISTRY.getClazz();
|
||||
|
||||
methodBiomeToBiomeBase = isAbove1_16_R1 ? classCraftBlock.getMethod("biomeToBiomeBase", classIRegistry, Biome.class)
|
||||
: classCraftBlock.getMethod("biomeToBiomeBase", Biome.class);
|
||||
@ -189,7 +189,6 @@ public enum CompatibleBiome {
|
||||
return compatibleBiomes;
|
||||
}
|
||||
|
||||
|
||||
public static CompatibleBiome getBiome(Biome biome) {
|
||||
return biome == null ? null : lookupMap.get(biome.name());
|
||||
}
|
||||
@ -252,6 +251,5 @@ public enum CompatibleBiome {
|
||||
this.version = version;
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -75,6 +75,7 @@ public enum CompatibleHand {
|
||||
* Get item in the selected hand
|
||||
*
|
||||
* @param player the player to get the item from
|
||||
*
|
||||
* @return the item
|
||||
*/
|
||||
public ItemStack getItem(Player player) {
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,129 +1,128 @@
|
||||
package com.songoda.core.compatibility;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.HashMap;
|
||||
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),
|
||||
JUNGLE_LEAVES("LEAVES", (byte)11, true),
|
||||
ACACIA_LEAVES("LEAVES_2", (byte)8, true),
|
||||
DARK_OAK_LEAVES("LEAVES_2", (byte)9, true),
|
||||
|
||||
ACACIA_DOOR("ACACIA_DOOR", true),
|
||||
BED("BED_BLOCK", true),
|
||||
BIRCH_DOOR("BIRCH_DOOR", true),
|
||||
FURNACE("FURNACE", "BURNING_FURNACE"),
|
||||
CAKE("CAKE_BLOCK"),
|
||||
CARROTS("CARROT"), // totally makes sense, lol
|
||||
CAULDRON("CAULDRON_BLOCK"),
|
||||
COMPARATOR("REDSTONE_COMPARATOR_OFF", "REDSTONE_COMPARATOR_ON"),
|
||||
DARK_OAK_DOOR("DARK_OAK_DOOR", true),
|
||||
DAYLIGHT_DETECTOR("DAYLIGHT_DETECTOR", "DAYLIGHT_DETECTOR_INVERTED"),
|
||||
/*
|
||||
< DOUBLE_STEP,
|
||||
< DOUBLE_STONE_SLAB2,
|
||||
*/
|
||||
FLOWER_POT("FLOWER_POT"),
|
||||
IRON_DOOR("IRON_DOOR_BLOCK", true),
|
||||
JUNGLE_DOOR("JUNGLE_DOOR", true),
|
||||
LAVA("STATIONARY_LAVA"),
|
||||
NETHER_WART("NETHER_WARTS"),
|
||||
/*
|
||||
< PURPUR_DOUBLE_SLAB
|
||||
*/
|
||||
POTATOES("POTATO"),
|
||||
REDSTONE_LAMP("REDSTONE_LAMP_OFF", "REDSTONE_LAMP_ON"),
|
||||
REDSTONE_ORE("REDSTONE_ORE", "GLOWING_REDSTONE_ORE"),
|
||||
REDSTONE_TORCH("REDSTONE_TORCH_ON", "REDSTONE_TORCH_OFF"),
|
||||
SPRUCE_DOOR("SPRUCE_DOOR"),
|
||||
SUGAR_CANE("SUGAR_CANE_BLOCK"),
|
||||
WATER("STATIONARY_WATER"),
|
||||
WHEAT("CROPS");
|
||||
final String blockMaterialName;
|
||||
final byte blockData;
|
||||
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();
|
||||
|
||||
static {
|
||||
for (LegacyMaterialBlockType t : values()) {
|
||||
lookupTable.put(t.name(), t);
|
||||
reverseLookupTable.put(t.blockMaterialName + ":" + t.blockData, t);
|
||||
if (t.alternateBlockMaterialName != null) {
|
||||
reverseLookupTable.put(t.alternateBlockMaterialName, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private LegacyMaterialBlockType(String blockMaterial) {
|
||||
this(blockMaterial, (byte)-1, null,false);
|
||||
}
|
||||
|
||||
private LegacyMaterialBlockType(String blockMaterial, boolean requiresData) {
|
||||
this(blockMaterial, (byte)-1, null, requiresData);
|
||||
}
|
||||
|
||||
private LegacyMaterialBlockType(String blockMaterial, byte data, boolean requiresData) {
|
||||
this(blockMaterial, data, null, requiresData);
|
||||
}
|
||||
|
||||
private LegacyMaterialBlockType(String blockMaterial, String alternateMaterial) {
|
||||
this(blockMaterial, (byte)-1, alternateMaterial, false);
|
||||
}
|
||||
|
||||
private LegacyMaterialBlockType(String blockMaterial, byte data, String alternateMaterial, boolean requiresData) {
|
||||
this.blockMaterialName = blockMaterial;
|
||||
this.alternateBlockMaterialName = alternateMaterial;
|
||||
this.requiresData = requiresData;
|
||||
this.blockMaterial = Material.getMaterial(blockMaterialName);
|
||||
this.alternateBlockMaterial = Material.getMaterial(alternateBlockMaterialName);
|
||||
this.blockData = data;
|
||||
}
|
||||
|
||||
public String getBlockMaterialName() {
|
||||
return blockMaterialName;
|
||||
}
|
||||
|
||||
public String getAlternateMaterialName() {
|
||||
return alternateBlockMaterialName;
|
||||
}
|
||||
|
||||
public Material getBlockMaterial() {
|
||||
return blockMaterial;
|
||||
}
|
||||
|
||||
public Material getAlternateBlockMaterial() {
|
||||
return alternateBlockMaterial;
|
||||
}
|
||||
|
||||
public boolean requiresData() {
|
||||
return requiresData;
|
||||
}
|
||||
|
||||
public static LegacyMaterialBlockType getMaterial(String lookup) {
|
||||
return lookupTable.get(lookup);
|
||||
}
|
||||
|
||||
public static LegacyMaterialBlockType getFromLegacy(String lookup, byte data) {
|
||||
return reverseLookupTable.get(lookup + ":" + data);
|
||||
}
|
||||
|
||||
public static LegacyMaterialBlockType getFromLegacy(String lookup) {
|
||||
return getFromLegacy(lookup, (byte)-1);
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.compatibility;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.HashMap;
|
||||
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),
|
||||
JUNGLE_LEAVES("LEAVES", (byte) 11, true),
|
||||
ACACIA_LEAVES("LEAVES_2", (byte) 8, true),
|
||||
DARK_OAK_LEAVES("LEAVES_2", (byte) 9, true),
|
||||
|
||||
ACACIA_DOOR("ACACIA_DOOR", true),
|
||||
BED("BED_BLOCK", true),
|
||||
BIRCH_DOOR("BIRCH_DOOR", true),
|
||||
FURNACE("FURNACE", "BURNING_FURNACE"),
|
||||
CAKE("CAKE_BLOCK"),
|
||||
CARROTS("CARROT"), // totally makes sense, lol
|
||||
CAULDRON("CAULDRON_BLOCK"),
|
||||
COMPARATOR("REDSTONE_COMPARATOR_OFF", "REDSTONE_COMPARATOR_ON"),
|
||||
DARK_OAK_DOOR("DARK_OAK_DOOR", true),
|
||||
DAYLIGHT_DETECTOR("DAYLIGHT_DETECTOR", "DAYLIGHT_DETECTOR_INVERTED"),
|
||||
/*
|
||||
< DOUBLE_STEP,
|
||||
< DOUBLE_STONE_SLAB2,
|
||||
*/
|
||||
FLOWER_POT("FLOWER_POT"),
|
||||
IRON_DOOR("IRON_DOOR_BLOCK", true),
|
||||
JUNGLE_DOOR("JUNGLE_DOOR", true),
|
||||
LAVA("STATIONARY_LAVA"),
|
||||
NETHER_WART("NETHER_WARTS"),
|
||||
/*
|
||||
< PURPUR_DOUBLE_SLAB
|
||||
*/
|
||||
POTATOES("POTATO"),
|
||||
REDSTONE_LAMP("REDSTONE_LAMP_OFF", "REDSTONE_LAMP_ON"),
|
||||
REDSTONE_ORE("REDSTONE_ORE", "GLOWING_REDSTONE_ORE"),
|
||||
REDSTONE_TORCH("REDSTONE_TORCH_ON", "REDSTONE_TORCH_OFF"),
|
||||
SPRUCE_DOOR("SPRUCE_DOOR"),
|
||||
SUGAR_CANE("SUGAR_CANE_BLOCK"),
|
||||
WATER("STATIONARY_WATER"),
|
||||
WHEAT("CROPS");
|
||||
final String blockMaterialName;
|
||||
final byte blockData;
|
||||
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();
|
||||
|
||||
static {
|
||||
for (LegacyMaterialBlockType t : values()) {
|
||||
lookupTable.put(t.name(), t);
|
||||
reverseLookupTable.put(t.blockMaterialName + ":" + t.blockData, t);
|
||||
if (t.alternateBlockMaterialName != null) {
|
||||
reverseLookupTable.put(t.alternateBlockMaterialName, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private LegacyMaterialBlockType(String blockMaterial) {
|
||||
this(blockMaterial, (byte) -1, null, false);
|
||||
}
|
||||
|
||||
private LegacyMaterialBlockType(String blockMaterial, boolean requiresData) {
|
||||
this(blockMaterial, (byte) -1, null, requiresData);
|
||||
}
|
||||
|
||||
private LegacyMaterialBlockType(String blockMaterial, byte data, boolean requiresData) {
|
||||
this(blockMaterial, data, null, requiresData);
|
||||
}
|
||||
|
||||
private LegacyMaterialBlockType(String blockMaterial, String alternateMaterial) {
|
||||
this(blockMaterial, (byte) -1, alternateMaterial, false);
|
||||
}
|
||||
|
||||
private LegacyMaterialBlockType(String blockMaterial, byte data, String alternateMaterial, boolean requiresData) {
|
||||
this.blockMaterialName = blockMaterial;
|
||||
this.alternateBlockMaterialName = alternateMaterial;
|
||||
this.requiresData = requiresData;
|
||||
this.blockMaterial = Material.getMaterial(blockMaterialName);
|
||||
this.alternateBlockMaterial = Material.getMaterial(alternateBlockMaterialName);
|
||||
this.blockData = data;
|
||||
}
|
||||
|
||||
public String getBlockMaterialName() {
|
||||
return blockMaterialName;
|
||||
}
|
||||
|
||||
public String getAlternateMaterialName() {
|
||||
return alternateBlockMaterialName;
|
||||
}
|
||||
|
||||
public Material getBlockMaterial() {
|
||||
return blockMaterial;
|
||||
}
|
||||
|
||||
public Material getAlternateBlockMaterial() {
|
||||
return alternateBlockMaterial;
|
||||
}
|
||||
|
||||
public boolean requiresData() {
|
||||
return requiresData;
|
||||
}
|
||||
|
||||
public static LegacyMaterialBlockType getMaterial(String lookup) {
|
||||
return lookupTable.get(lookup);
|
||||
}
|
||||
|
||||
public static LegacyMaterialBlockType getFromLegacy(String lookup, byte data) {
|
||||
return reverseLookupTable.get(lookup + ":" + data);
|
||||
}
|
||||
|
||||
public static LegacyMaterialBlockType getFromLegacy(String lookup) {
|
||||
return getFromLegacy(lookup, (byte) -1);
|
||||
}
|
||||
}
|
@ -1,54 +1,53 @@
|
||||
package com.songoda.core.compatibility;
|
||||
|
||||
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) {
|
||||
}
|
||||
// paper used to be called "paperclip"
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paperclip.Paperclip");
|
||||
return PAPER;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.PaperConfig");
|
||||
return PAPER;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
// spigot is the fork that pretty much all builds are based on anymore
|
||||
try {
|
||||
Class.forName("org.spigotmc.SpigotConfig");
|
||||
return SPIGOT;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
return serverPath.contains("craftbukkit") ? CRAFTBUKKIT : UNKNOWN;
|
||||
}
|
||||
|
||||
public static ServerProject getServerVersion() {
|
||||
return serverProject;
|
||||
}
|
||||
|
||||
public static boolean isServer(ServerProject version) {
|
||||
return serverProject == version;
|
||||
}
|
||||
|
||||
public static boolean isServer(ServerProject... versions) {
|
||||
return ArrayUtils.contains(versions, serverProject);
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.compatibility;
|
||||
|
||||
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) {
|
||||
}
|
||||
// paper used to be called "paperclip"
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paperclip.Paperclip");
|
||||
return PAPER;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.PaperConfig");
|
||||
return PAPER;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
// spigot is the fork that pretty much all builds are based on anymore
|
||||
try {
|
||||
Class.forName("org.spigotmc.SpigotConfig");
|
||||
return SPIGOT;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
return serverPath.contains("craftbukkit") ? CRAFTBUKKIT : UNKNOWN;
|
||||
}
|
||||
|
||||
public static ServerProject getServerVersion() {
|
||||
return serverProject;
|
||||
}
|
||||
|
||||
public static boolean isServer(ServerProject version) {
|
||||
return serverProject == version;
|
||||
}
|
||||
|
||||
public static boolean isServer(ServerProject... versions) {
|
||||
return ArrayUtils.contains(versions, serverProject);
|
||||
}
|
||||
}
|
111
Core/pom.xml
111
Core/pom.xml
@ -1,27 +1,28 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.songoda</groupId>
|
||||
<artifactId>SongodaCore-Modules</artifactId>
|
||||
<version>2.5.7</version>
|
||||
<relativePath>../</relativePath>
|
||||
<version>2.5.8</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>com.songoda</groupId>
|
||||
<artifactId>SongodaCore</artifactId>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<defaultGoal>clean install</defaultGoal>
|
||||
<finalName>SongodaCore-${project.version}</finalName>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.8.1</version>
|
||||
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
@ -29,42 +30,52 @@
|
||||
<release>${java.release}</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>3.2.1</version>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>shaded</id>
|
||||
<phase>package</phase>
|
||||
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
|
||||
<configuration>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>com.songoda:*</include>
|
||||
<include>com.zaxxer:HikariCP</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>*:*</artifact>
|
||||
|
||||
<includes>
|
||||
<include>com/</include>
|
||||
<include>META-INF/MANIFEST.MF</include>
|
||||
@ -76,30 +87,9 @@
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<configuration>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<descriptors>
|
||||
<descriptor>../assembly.xml</descriptor>
|
||||
</descriptors>
|
||||
<finalName>SongodaCore-${project.version}</finalName>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>-->
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
@ -107,135 +97,121 @@
|
||||
<version>1.17</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-Compatibility</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Need to include all NMS modules here -->
|
||||
<!-- Note when adding a new module: include the class in NmsManager -->
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-API</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_8_R1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_8_R2</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_8_R3</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_9_R1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_9_R2</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_10_R1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_11_R1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_12_R1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_13_R1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_13_R2</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_14_R1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_15_R1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_16_R1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_16_R2</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_16_R3</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>SongodaCore-NMS-v1_17_R1</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- End NMS -->
|
||||
|
||||
<!-- Start Plugin Hooks -->
|
||||
<dependency>
|
||||
<groupId>com.gmail.filoghost.holographicdisplays</groupId>
|
||||
@ -243,152 +219,171 @@
|
||||
<version>2.3.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sainttx</groupId>
|
||||
<artifactId>Holograms</artifactId>
|
||||
<version>2.13</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.Zrips</groupId>
|
||||
<artifactId>CMI-API</artifactId>
|
||||
<version>7.6.2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.tnemc</groupId>
|
||||
<artifactId>Reserve</artifactId>
|
||||
<version>0.1.3.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.black_ixx</groupId>
|
||||
<artifactId>PlayerPoints</artifactId>
|
||||
<version>2.1.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.milkbowl</groupId>
|
||||
<artifactId>VaultAPI</artifactId>
|
||||
<version>1.7.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sk89q</groupId>
|
||||
<artifactId>worldguard-bukkit</artifactId>
|
||||
<version>7.0.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sk89q</groupId>
|
||||
<artifactId>worldedit-bukkit</artifactId>
|
||||
<version>7.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.songoda</groupId>
|
||||
<artifactId>UltimateStacker</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.bgsoftware</groupId>
|
||||
<artifactId>wildstacker</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>uk.antiperson</groupId>
|
||||
<artifactId>stackmob</artifactId>
|
||||
<version>4-0-2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.Zrips</groupId>
|
||||
<artifactId>Jobs</artifactId>
|
||||
<version>LATEST</version>
|
||||
<version>v4.17.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
||||
<artifactId>mcMMO</artifactId>
|
||||
<version>2.1.50</version>
|
||||
<version>2.1.200</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net</groupId>
|
||||
<artifactId>coreprotect</artifactId>
|
||||
<version>2.17.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>me.ryanhamshire</groupId>
|
||||
<artifactId>GriefPrevention</artifactId>
|
||||
<version>16.16.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>me.angeschossen</groupId>
|
||||
<artifactId>LandsAPI</artifactId>
|
||||
<version>4.12.20</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>br.net.fabiozumbi12</groupId>
|
||||
<artifactId>RedProtect</artifactId>
|
||||
<version>7.7.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.songoda</groupId>
|
||||
<artifactId>UltimateClaims</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.palmergames</groupId>
|
||||
<artifactId>Towny</artifactId>
|
||||
<version>0.96.5.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>world.bentobox</groupId>
|
||||
<artifactId>bentobox</artifactId>
|
||||
<version>1.15.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- End Plugin Hooks -->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.googlecode.json-simple</groupId>
|
||||
<artifactId>json-simple</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>13.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<version>1.26</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.25</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-nop</artifactId>
|
||||
<version>1.7.25</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>3.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
|
@ -9,8 +9,6 @@ import com.songoda.core.core.PluginInfoModule;
|
||||
import com.songoda.core.core.SongodaCoreCommand;
|
||||
import com.songoda.core.core.SongodaCoreDiagCommand;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
@ -22,7 +20,6 @@ import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.plugin.ServicePriority;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
@ -56,7 +53,7 @@ public class SongodaCore {
|
||||
/**
|
||||
* This has been added as of Rev 6
|
||||
*/
|
||||
private final static String coreVersion = "2.5.7";
|
||||
private final static String coreVersion = "2.5.8";
|
||||
|
||||
/**
|
||||
* This is specific to the website api
|
||||
@ -73,7 +70,7 @@ public class SongodaCore {
|
||||
|
||||
public static boolean hasShading() {
|
||||
// sneaky hack to check the package name since maven tries to re-shade all references to the package string
|
||||
return !SongodaCore.class.getPackage().getName().equals(new String(new char[]{'c', 'o', 'm', '.', 's', 'o', 'n', 'g', 'o', 'd', 'a', '.', 'c', 'o', 'r', 'e'}));
|
||||
return !SongodaCore.class.getPackage().getName().equals(new String(new char[] {'c', 'o', 'm', '.', 's', 'o', 'n', 'g', 'o', 'd', 'a', '.', 'c', 'o', 'r', 'e'}));
|
||||
}
|
||||
|
||||
public static void registerPlugin(JavaPlugin plugin, int pluginID, CompatibleMaterial icon) {
|
||||
@ -315,7 +312,7 @@ public class SongodaCore {
|
||||
if (!via && (via = event.getPlugin().getName().equals("ViaVersion"))) {
|
||||
Bukkit.getOnlinePlayers().forEach(p -> ClientVersion.onLoginVia(p, getHijackedPlugin()));
|
||||
} else if (!proto && (proto = event.getPlugin().getName().equals("ProtocolSupport"))) {
|
||||
Bukkit.getOnlinePlayers().forEach(p -> ClientVersion.onLoginProtocol(p, getHijackedPlugin()));
|
||||
Bukkit.getOnlinePlayers().forEach(p -> ClientVersion.onLoginProtocol(p, getHijackedPlugin()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,177 +1,178 @@
|
||||
package com.songoda.core;
|
||||
|
||||
import com.songoda.core.configuration.Config;
|
||||
import com.songoda.core.locale.Locale;
|
||||
import com.songoda.core.utils.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.List;
|
||||
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;
|
||||
protected Config config = new Config(this);
|
||||
protected long dataLoadDelay = 20L;
|
||||
|
||||
protected ConsoleCommandSender console = Bukkit.getConsoleSender();
|
||||
private boolean emergencyStop = false;
|
||||
|
||||
public abstract void onPluginLoad();
|
||||
|
||||
public abstract void onPluginEnable();
|
||||
|
||||
public abstract void onPluginDisable();
|
||||
|
||||
public abstract void onDataLoad();
|
||||
|
||||
/**
|
||||
* Called after reloadConfig() is called
|
||||
*/
|
||||
public abstract void onConfigReload();
|
||||
|
||||
/**
|
||||
* Any other plugin configuration files used by the plugin.
|
||||
*
|
||||
* @return a list of Configs that are used in addition to the main config.
|
||||
*/
|
||||
public abstract List<Config> getExtraConfig();
|
||||
|
||||
@Override
|
||||
public FileConfiguration getConfig() {
|
||||
return config.getFileConfig();
|
||||
}
|
||||
|
||||
public Config getCoreConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
config.load();
|
||||
onConfigReload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveConfig() {
|
||||
config.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onLoad() {
|
||||
try {
|
||||
onPluginLoad();
|
||||
} catch (Throwable t) {
|
||||
Bukkit.getLogger().log(Level.SEVERE,
|
||||
"Unexpected error while loading " + getDescription().getName()
|
||||
+ " v" + getDescription().getVersion()
|
||||
+ " c" + SongodaCore.getCoreLibraryVersion()
|
||||
+ ": Disabling plugin!", t);
|
||||
emergencyStop = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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()));
|
||||
|
||||
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) {
|
||||
Bukkit.getLogger().log(Level.SEVERE,
|
||||
"Unexpected error while loading " + getDescription().getName()
|
||||
+ " v" + getDescription().getVersion()
|
||||
+ " c" + SongodaCore.getCoreLibraryVersion()
|
||||
+ ": Disabling plugin!", t);
|
||||
emergencyStop();
|
||||
console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
console.sendMessage(" ");
|
||||
return;
|
||||
}
|
||||
|
||||
console.sendMessage(ChatColor.GREEN + "=============================");
|
||||
console.sendMessage(" "); // blank line to separate chatter
|
||||
}
|
||||
|
||||
protected void emergencyStop() {
|
||||
emergencyStop = true;
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onDisable() {
|
||||
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()));
|
||||
onPluginDisable();
|
||||
console.sendMessage(ChatColor.GREEN + "=============================");
|
||||
console.sendMessage(" "); // blank line to speparate chatter
|
||||
}
|
||||
|
||||
public ConsoleCommandSender getConsole() {
|
||||
return console;
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the plugin's locale to a specific language
|
||||
*
|
||||
* @param localeName locale to use, eg "en_US"
|
||||
* @param reload optionally reload the loaded locale if the locale didn't
|
||||
* change
|
||||
* @return true if the locale exists and was loaded successfully
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.songoda.core;
|
||||
|
||||
import com.songoda.core.configuration.Config;
|
||||
import com.songoda.core.locale.Locale;
|
||||
import com.songoda.core.utils.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.List;
|
||||
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;
|
||||
protected Config config = new Config(this);
|
||||
protected long dataLoadDelay = 20L;
|
||||
|
||||
protected ConsoleCommandSender console = Bukkit.getConsoleSender();
|
||||
private boolean emergencyStop = false;
|
||||
|
||||
public abstract void onPluginLoad();
|
||||
|
||||
public abstract void onPluginEnable();
|
||||
|
||||
public abstract void onPluginDisable();
|
||||
|
||||
public abstract void onDataLoad();
|
||||
|
||||
/**
|
||||
* Called after reloadConfig() is called
|
||||
*/
|
||||
public abstract void onConfigReload();
|
||||
|
||||
/**
|
||||
* Any other plugin configuration files used by the plugin.
|
||||
*
|
||||
* @return a list of Configs that are used in addition to the main config.
|
||||
*/
|
||||
public abstract List<Config> getExtraConfig();
|
||||
|
||||
@Override
|
||||
public FileConfiguration getConfig() {
|
||||
return config.getFileConfig();
|
||||
}
|
||||
|
||||
public Config getCoreConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
config.load();
|
||||
onConfigReload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveConfig() {
|
||||
config.save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onLoad() {
|
||||
try {
|
||||
onPluginLoad();
|
||||
} catch (Throwable t) {
|
||||
Bukkit.getLogger().log(Level.SEVERE,
|
||||
"Unexpected error while loading " + getDescription().getName()
|
||||
+ " v" + getDescription().getVersion()
|
||||
+ " c" + SongodaCore.getCoreLibraryVersion()
|
||||
+ ": Disabling plugin!", t);
|
||||
emergencyStop = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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()));
|
||||
|
||||
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) {
|
||||
Bukkit.getLogger().log(Level.SEVERE,
|
||||
"Unexpected error while loading " + getDescription().getName()
|
||||
+ " v" + getDescription().getVersion()
|
||||
+ " c" + SongodaCore.getCoreLibraryVersion()
|
||||
+ ": Disabling plugin!", t);
|
||||
emergencyStop();
|
||||
console.sendMessage(ChatColor.RED + "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
console.sendMessage(" ");
|
||||
return;
|
||||
}
|
||||
|
||||
console.sendMessage(ChatColor.GREEN + "=============================");
|
||||
console.sendMessage(" "); // blank line to separate chatter
|
||||
}
|
||||
|
||||
protected void emergencyStop() {
|
||||
emergencyStop = true;
|
||||
Bukkit.getPluginManager().disablePlugin(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onDisable() {
|
||||
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()));
|
||||
onPluginDisable();
|
||||
console.sendMessage(ChatColor.GREEN + "=============================");
|
||||
console.sendMessage(" "); // blank line to speparate chatter
|
||||
}
|
||||
|
||||
public ConsoleCommandSender getConsole() {
|
||||
return console;
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the plugin's locale to a specific language
|
||||
*
|
||||
* @param localeName locale to use, eg "en_US"
|
||||
* @param reload optionally reload the loaded locale if the locale didn't
|
||||
* change
|
||||
*
|
||||
* @return true if the locale exists and was loaded successfully
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,274 +1,273 @@
|
||||
package com.songoda.core.chat;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.core.compatibility.ClassMapping;
|
||||
import com.songoda.core.utils.TextUtils;
|
||||
import net.minecraft.network.chat.IChatBaseComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
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<>();
|
||||
|
||||
public void clear() {
|
||||
textList.clear();
|
||||
}
|
||||
|
||||
public ChatMessage fromText(String text) {
|
||||
return fromText(text, false);
|
||||
}
|
||||
|
||||
public ChatMessage fromText(String text, boolean noHex) {
|
||||
Pattern pattern = Pattern.compile("(.*?)(?!&([omnlk]))(?=(&([123456789abcdefr#])|$)|#([a-f]|[A-F]|[0-9]){6})",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
Matcher matcher = pattern.matcher(text);
|
||||
|
||||
while (matcher.find()) {
|
||||
ColorContainer color = null;
|
||||
String match1 = matcher.group(1);
|
||||
|
||||
if (matcher.groupCount() == 0 || match1.length() == 0) continue;
|
||||
|
||||
char colorChar = '-';
|
||||
|
||||
if (matcher.start() != 0)
|
||||
colorChar = text.substring(matcher.start() - 1, matcher.start()).charAt(0);
|
||||
|
||||
if (colorChar != '-') {
|
||||
if (colorChar == '#') {
|
||||
color = new ColorContainer(match1.substring(0, 6), noHex);
|
||||
match1 = match1.substring(5);
|
||||
} else if (colorChar == '&') {
|
||||
color = new ColorContainer(ColorCode.getByChar(Character.toLowerCase(match1.charAt(0))));
|
||||
}
|
||||
}
|
||||
|
||||
Pattern subPattern = Pattern.compile("(.*?)(?=&([omnlk])|$)");
|
||||
Matcher subMatcher = subPattern.matcher(match1);
|
||||
|
||||
List<ColorCode> stackedCodes = new ArrayList<>();
|
||||
while (subMatcher.find()) {
|
||||
String match2 = subMatcher.group(1);
|
||||
if (match2.length() == 0) continue;
|
||||
|
||||
ColorCode code = ColorCode.getByChar(Character.toLowerCase(match2.charAt(0)));
|
||||
|
||||
if (code != null && code != ColorCode.RESET)
|
||||
stackedCodes.add(code);
|
||||
|
||||
if (color != null)
|
||||
match2 = match2.substring(1);
|
||||
|
||||
if (match2.length() == 0) continue;
|
||||
|
||||
addMessage(match2, color, stackedCodes);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public String toText() {
|
||||
return toText(false);
|
||||
}
|
||||
|
||||
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())
|
||||
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;
|
||||
}
|
||||
|
||||
public ChatMessage addMessage(String text, ColorContainer color) {
|
||||
return addMessage(text, color, Collections.emptyList());
|
||||
}
|
||||
|
||||
public ChatMessage addMessage(String text, ColorContainer color, List<ColorCode> colorCodes) {
|
||||
JsonObject txt = new JsonObject();
|
||||
txt.addProperty("text", text);
|
||||
|
||||
if (color != null)
|
||||
txt.addProperty("color", color.getHexCode() != null ? "#" + color.getHexCode() : color.getColorCode().name().toLowerCase());
|
||||
for (ColorCode code : ColorCode.values()) {
|
||||
if (!code.isColor())
|
||||
txt.addProperty(code.name().toLowerCase(), colorCodes.contains(code));
|
||||
}
|
||||
|
||||
textList.add(txt);
|
||||
return this;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return gson.toJson(textList);
|
||||
}
|
||||
|
||||
public void sendTo(CommandSender sender) {
|
||||
sendTo(null, sender);
|
||||
}
|
||||
|
||||
public void sendTo(ChatMessage prefix, CommandSender sender) {
|
||||
if (sender instanceof Player && enabled) {
|
||||
try {
|
||||
List<JsonObject> textList = prefix == null ? new ArrayList<>() : new ArrayList<>(prefix.textList);
|
||||
textList.addAll(this.textList);
|
||||
|
||||
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());
|
||||
} 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);
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean enabled = ServerVersion.isServerVersionAtLeast(ServerVersion.V1_8);
|
||||
|
||||
private static Class<?> mc_ChatMessageType;
|
||||
private static Method mc_IChatBaseComponent_ChatSerializer_a, cb_craftPlayer_getHandle, mc_playerConnection_sendPacket;
|
||||
private static Constructor mc_PacketPlayOutChat_new;
|
||||
private static Field mc_entityPlayer_playerConnection, mc_chatMessageType_Chat;
|
||||
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
cb_craftPlayerClazz = ClassMapping.CRAFT_PLAYER.getClazz();
|
||||
cb_craftPlayer_getHandle = cb_craftPlayerClazz.getDeclaredMethod("getHandle");
|
||||
mc_entityPlayerClazz = ClassMapping.ENTITY_PLAYER.getClazz();
|
||||
mc_entityPlayer_playerConnection = mc_entityPlayerClazz.getDeclaredField(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17) ? "b" : "playerConnection");
|
||||
mc_playerConnectionClazz = ClassMapping.PLAYER_CONNECTION.getClazz();
|
||||
mc_PacketInterface = ClassMapping.PACKET.getClazz();
|
||||
mc_playerConnection_sendPacket = mc_playerConnectionClazz.getDeclaredMethod("sendPacket", mc_PacketInterface);
|
||||
mc_IChatBaseComponent = ClassMapping.I_CHAT_BASE_COMPONENT.getClazz();
|
||||
mc_IChatBaseComponent_ChatSerializer = ClassMapping.I_CHAT_BASE_COMPONENT.getClazz("ChatSerializer");
|
||||
mc_IChatBaseComponent_ChatSerializer_a = mc_IChatBaseComponent_ChatSerializer.getMethod("a", String.class);
|
||||
mc_PacketPlayOutChat = ClassMapping.PACKET_PLAY_OUT_CHAT.getClazz();
|
||||
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_16)) {
|
||||
mc_ChatMessageType = ClassMapping.CHAT_MESSAGE_TYPE.getClazz();
|
||||
mc_chatMessageType_Chat = mc_ChatMessageType.getField(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17) ? "a" : "CHAT");
|
||||
mc_PacketPlayOutChat_new = mc_PacketPlayOutChat.getConstructor(mc_IChatBaseComponent, mc_ChatMessageType, UUID.class);
|
||||
} else {
|
||||
mc_PacketPlayOutChat_new = mc_PacketPlayOutChat.getConstructor(mc_IChatBaseComponent);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Problem preparing raw chat packets (disabling further packets)", ex);
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ChatMessage replaceAll(String toReplace, String replaceWith) {
|
||||
for (JsonObject object : textList) {
|
||||
String text = object.get("text").getAsString()
|
||||
.replaceAll(toReplace, replaceWith);
|
||||
object.remove("text");
|
||||
object.addProperty("text", text);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
package com.songoda.core.chat;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.songoda.core.compatibility.ClassMapping;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.core.utils.TextUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
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<>();
|
||||
|
||||
public void clear() {
|
||||
textList.clear();
|
||||
}
|
||||
|
||||
public ChatMessage fromText(String text) {
|
||||
return fromText(text, false);
|
||||
}
|
||||
|
||||
public ChatMessage fromText(String text, boolean noHex) {
|
||||
Pattern pattern = Pattern.compile("(.*?)(?!&([omnlk]))(?=(&([123456789abcdefr#])|$)|#([a-f]|[A-F]|[0-9]){6})",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
Matcher matcher = pattern.matcher(text);
|
||||
|
||||
while (matcher.find()) {
|
||||
ColorContainer color = null;
|
||||
String match1 = matcher.group(1);
|
||||
|
||||
if (matcher.groupCount() == 0 || match1.length() == 0) continue;
|
||||
|
||||
char colorChar = '-';
|
||||
|
||||
if (matcher.start() != 0)
|
||||
colorChar = text.substring(matcher.start() - 1, matcher.start()).charAt(0);
|
||||
|
||||
if (colorChar != '-') {
|
||||
if (colorChar == '#') {
|
||||
color = new ColorContainer(match1.substring(0, 6), noHex);
|
||||
match1 = match1.substring(5);
|
||||
} else if (colorChar == '&') {
|
||||
color = new ColorContainer(ColorCode.getByChar(Character.toLowerCase(match1.charAt(0))));
|
||||
}
|
||||
}
|
||||
|
||||
Pattern subPattern = Pattern.compile("(.*?)(?=&([omnlk])|$)");
|
||||
Matcher subMatcher = subPattern.matcher(match1);
|
||||
|
||||
List<ColorCode> stackedCodes = new ArrayList<>();
|
||||
while (subMatcher.find()) {
|
||||
String match2 = subMatcher.group(1);
|
||||
if (match2.length() == 0) continue;
|
||||
|
||||
ColorCode code = ColorCode.getByChar(Character.toLowerCase(match2.charAt(0)));
|
||||
|
||||
if (code != null && code != ColorCode.RESET)
|
||||
stackedCodes.add(code);
|
||||
|
||||
if (color != null)
|
||||
match2 = match2.substring(1);
|
||||
|
||||
if (match2.length() == 0) continue;
|
||||
|
||||
addMessage(match2, color, stackedCodes);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public String toText() {
|
||||
return toText(false);
|
||||
}
|
||||
|
||||
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())
|
||||
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;
|
||||
}
|
||||
|
||||
public ChatMessage addMessage(String text, ColorContainer color) {
|
||||
return addMessage(text, color, Collections.emptyList());
|
||||
}
|
||||
|
||||
public ChatMessage addMessage(String text, ColorContainer color, List<ColorCode> colorCodes) {
|
||||
JsonObject txt = new JsonObject();
|
||||
txt.addProperty("text", text);
|
||||
|
||||
if (color != null)
|
||||
txt.addProperty("color", color.getHexCode() != null ? "#" + color.getHexCode() : color.getColorCode().name().toLowerCase());
|
||||
for (ColorCode code : ColorCode.values()) {
|
||||
if (!code.isColor())
|
||||
txt.addProperty(code.name().toLowerCase(), colorCodes.contains(code));
|
||||
}
|
||||
|
||||
textList.add(txt);
|
||||
return this;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return gson.toJson(textList);
|
||||
}
|
||||
|
||||
public void sendTo(CommandSender sender) {
|
||||
sendTo(null, sender);
|
||||
}
|
||||
|
||||
public void sendTo(ChatMessage prefix, CommandSender sender) {
|
||||
if (sender instanceof Player && enabled) {
|
||||
try {
|
||||
List<JsonObject> textList = prefix == null ? new ArrayList<>() : new ArrayList<>(prefix.textList);
|
||||
textList.addAll(this.textList);
|
||||
|
||||
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());
|
||||
} 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);
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean enabled = ServerVersion.isServerVersionAtLeast(ServerVersion.V1_8);
|
||||
|
||||
private static Class<?> mc_ChatMessageType;
|
||||
private static Method mc_IChatBaseComponent_ChatSerializer_a, cb_craftPlayer_getHandle, mc_playerConnection_sendPacket;
|
||||
private static Constructor mc_PacketPlayOutChat_new;
|
||||
private static Field mc_entityPlayer_playerConnection, mc_chatMessageType_Chat;
|
||||
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
cb_craftPlayerClazz = ClassMapping.CRAFT_PLAYER.getClazz();
|
||||
cb_craftPlayer_getHandle = cb_craftPlayerClazz.getDeclaredMethod("getHandle");
|
||||
mc_entityPlayerClazz = ClassMapping.ENTITY_PLAYER.getClazz();
|
||||
mc_entityPlayer_playerConnection = mc_entityPlayerClazz.getDeclaredField(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17) ? "b" : "playerConnection");
|
||||
mc_playerConnectionClazz = ClassMapping.PLAYER_CONNECTION.getClazz();
|
||||
mc_PacketInterface = ClassMapping.PACKET.getClazz();
|
||||
mc_playerConnection_sendPacket = mc_playerConnectionClazz.getDeclaredMethod("sendPacket", mc_PacketInterface);
|
||||
mc_IChatBaseComponent = ClassMapping.I_CHAT_BASE_COMPONENT.getClazz();
|
||||
mc_IChatBaseComponent_ChatSerializer = ClassMapping.I_CHAT_BASE_COMPONENT.getClazz("ChatSerializer");
|
||||
mc_IChatBaseComponent_ChatSerializer_a = mc_IChatBaseComponent_ChatSerializer.getMethod("a", String.class);
|
||||
mc_PacketPlayOutChat = ClassMapping.PACKET_PLAY_OUT_CHAT.getClazz();
|
||||
|
||||
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_16)) {
|
||||
mc_ChatMessageType = ClassMapping.CHAT_MESSAGE_TYPE.getClazz();
|
||||
mc_chatMessageType_Chat = mc_ChatMessageType.getField(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_17) ? "a" : "CHAT");
|
||||
mc_PacketPlayOutChat_new = mc_PacketPlayOutChat.getConstructor(mc_IChatBaseComponent, mc_ChatMessageType, UUID.class);
|
||||
} else {
|
||||
mc_PacketPlayOutChat_new = mc_PacketPlayOutChat.getConstructor(mc_IChatBaseComponent);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Problem preparing raw chat packets (disabling further packets)", ex);
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ChatMessage replaceAll(String toReplace, String replaceWith) {
|
||||
for (JsonObject object : textList) {
|
||||
String text = object.get("text").getAsString()
|
||||
.replaceAll(toReplace, replaceWith);
|
||||
object.remove("text");
|
||||
object.addProperty("text", text);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,6 @@ public enum ColorCode {
|
||||
ColorCode color = var0[i];
|
||||
BY_CHAR.put(color.code, color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static ColorCode getByChar(char code) {
|
||||
@ -68,4 +67,4 @@ public enum ColorCode {
|
||||
public boolean isColor() {
|
||||
return this.isColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package com.songoda.core.chat;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.core.utils.ColorUtils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
|
||||
public class ColorContainer {
|
||||
|
||||
@ -40,4 +40,4 @@ public class ColorContainer {
|
||||
Integer.valueOf(hexCode.substring(4, 6), 16));
|
||||
return ColorUtils.fromRGB(jColor.getRed(), jColor.getGreen(), jColor.getBlue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,9 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.command.SimpleCommandMap;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.command.defaults.BukkitCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -1,120 +1,119 @@
|
||||
package com.songoda.core.commands;
|
||||
|
||||
import com.songoda.core.chat.ChatMessage;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MainCommand extends AbstractCommand {
|
||||
|
||||
String header = null;
|
||||
String description;
|
||||
boolean sortHelp = false;
|
||||
final String command;
|
||||
final Plugin plugin;
|
||||
protected final SimpleNestedCommand nestedCommands;
|
||||
|
||||
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;
|
||||
this.nestedCommands = new SimpleNestedCommand(this);
|
||||
}
|
||||
|
||||
public MainCommand setHeader(String header) {
|
||||
this.header = header;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MainCommand setDescription(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MainCommand setSortHelp(boolean sortHelp) {
|
||||
this.sortHelp = sortHelp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MainCommand addSubCommand(AbstractCommand command) {
|
||||
nestedCommands.addSubCommand(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MainCommand addSubCommands(AbstractCommand... commands) {
|
||||
nestedCommands.addSubCommands(commands);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReturnType runCommand(CommandSender sender, String... args) {
|
||||
sender.sendMessage("");
|
||||
if (header != null) {
|
||||
sender.sendMessage(header);
|
||||
} else {
|
||||
new ChatMessage().fromText(String.format("#ff8080&l%s &8» &7Version %s Created with <3 by #ec4e74&l&oS#fa5b65&l&oo#ff6c55&l&on#ff7f44&l&og#ff9432&l&oo#ffaa1e&l&od#f4c009&l&oa",
|
||||
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;
|
||||
if (!isPlayer) {
|
||||
sender.sendMessage(ChatColor.DARK_GRAY + "- " + ChatColor.YELLOW + cmd.getSyntax() + ChatColor.GRAY + " - " + cmd.getDescription());
|
||||
} else if (cmd.getPermissionNode() == null || sender.hasPermission(cmd.getPermissionNode())) {
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
final String c = "/" + command + " ";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sender.sendMessage("");
|
||||
|
||||
return ReturnType.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> onTab(CommandSender sender, String... args) {
|
||||
// don't need to worry about tab for a root command - handled by the manager
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode() {
|
||||
// permissions for a root command should be handled in the plugin.yml
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSyntax() {
|
||||
return "/" + command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.commands;
|
||||
|
||||
import com.songoda.core.chat.ChatMessage;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MainCommand extends AbstractCommand {
|
||||
|
||||
String header = null;
|
||||
String description;
|
||||
boolean sortHelp = false;
|
||||
final String command;
|
||||
final Plugin plugin;
|
||||
protected final SimpleNestedCommand nestedCommands;
|
||||
|
||||
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;
|
||||
this.nestedCommands = new SimpleNestedCommand(this);
|
||||
}
|
||||
|
||||
public MainCommand setHeader(String header) {
|
||||
this.header = header;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MainCommand setDescription(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MainCommand setSortHelp(boolean sortHelp) {
|
||||
this.sortHelp = sortHelp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MainCommand addSubCommand(AbstractCommand command) {
|
||||
nestedCommands.addSubCommand(command);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MainCommand addSubCommands(AbstractCommand... commands) {
|
||||
nestedCommands.addSubCommands(commands);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReturnType runCommand(CommandSender sender, String... args) {
|
||||
sender.sendMessage("");
|
||||
if (header != null) {
|
||||
sender.sendMessage(header);
|
||||
} else {
|
||||
new ChatMessage().fromText(String.format("#ff8080&l%s &8» &7Version %s Created with <3 by #ec4e74&l&oS#fa5b65&l&oo#ff6c55&l&on#ff7f44&l&og#ff9432&l&oo#ffaa1e&l&od#f4c009&l&oa",
|
||||
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;
|
||||
if (!isPlayer) {
|
||||
sender.sendMessage(ChatColor.DARK_GRAY + "- " + ChatColor.YELLOW + cmd.getSyntax() + ChatColor.GRAY + " - " + cmd.getDescription());
|
||||
} else if (cmd.getPermissionNode() == null || sender.hasPermission(cmd.getPermissionNode())) {
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
final String c = "/" + command + " ";
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sender.sendMessage("");
|
||||
|
||||
return ReturnType.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> onTab(CommandSender sender, String... args) {
|
||||
// don't need to worry about tab for a root command - handled by the manager
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode() {
|
||||
// permissions for a root command should be handled in the plugin.yml
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSyntax() {
|
||||
return "/" + command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
@ -1,193 +1,194 @@
|
||||
package com.songoda.core.commands;
|
||||
|
||||
import com.songoda.core.compatibility.EntityNamespace;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SelectorArguments {
|
||||
|
||||
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})?)?$");
|
||||
|
||||
/**
|
||||
* Parse a command selector using Minecraft's selector format. <br>
|
||||
* Currently only supports distance and entity type
|
||||
*
|
||||
* @param sender CommandBlock or Player running the command
|
||||
* @param argument argument with the selector to parse
|
||||
* @return SelectorArguments Object for grabbing the list of entities, or null if the selector is invalid
|
||||
*/
|
||||
@Nullable
|
||||
public static SelectorArguments parseSelector(@NotNull CommandSender sender, @NotNull String argument) {
|
||||
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) {
|
||||
selector.parseArguments(m.group(3));
|
||||
}
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
protected final CommandSender sender;
|
||||
protected final SelectorType selector;
|
||||
protected double rangeMin = 0, rangeMax = Double.POSITIVE_INFINITY;
|
||||
protected EntityType entityType;
|
||||
|
||||
public SelectorArguments(CommandSender sender, SelectorType type) {
|
||||
this.sender = sender;
|
||||
this.selector = type;
|
||||
}
|
||||
|
||||
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
|
||||
// 5.. = d >= 5
|
||||
// ..5 = d <= 15
|
||||
Matcher distGroup = selectorRangePattern.matcher(v[1]);
|
||||
if (distGroup.find()) {
|
||||
if (distGroup.group(1) != null) {
|
||||
rangeMin = Double.parseDouble(distGroup.group(1));
|
||||
}
|
||||
if (distGroup.group(3) == null) {
|
||||
rangeMax = rangeMin;
|
||||
} else if (distGroup.group(4) != null) {
|
||||
rangeMax = Double.parseDouble(distGroup.group(4));
|
||||
}
|
||||
}
|
||||
} 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.
|
||||
dx Entities between x and x + dx.
|
||||
dy Entities between y and y + dy.
|
||||
dz Entities between z and z + dz.
|
||||
gamemode Players with gamemode. It can be one of the following values: adventure, creative, spectator, survival, !adventure, !creative, !spectator, !survival
|
||||
level Experience level. It must be an integer value that is 0 or greater.
|
||||
limit Maximum number of entities to target. It must be an integer value that is 1 or greater.
|
||||
name Entity name.
|
||||
nbt NBT tag.
|
||||
scores Score.
|
||||
sort Sort the entities. It must be one of the following values: arbitrary, furthest, nearest, random
|
||||
tag Scoreboard tag.
|
||||
team Entities on team.
|
||||
type Entity type (target must be the specified entity type - https://www.digminecraft.com/lists/entity_list_pc.php ).
|
||||
x Entity's x-coordinate position.
|
||||
x_rotation Entity's x rotation (vertical rotation).
|
||||
y Entity's y-coordinate position.
|
||||
y_rotation Entity's y rotation (horizontal rotation).
|
||||
z Entity's z-coordinate position.
|
||||
target selector arguments are case-sensitive
|
||||
@e[type=cow,limit=5]
|
||||
*/
|
||||
}
|
||||
|
||||
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)));
|
||||
return Arrays.asList(list2.get(0));
|
||||
case RANDOM_PLAYER:
|
||||
Collections.shuffle(list2);
|
||||
return Arrays.asList(list2.get(0));
|
||||
case ALL_PLAYER:
|
||||
case ALL_ENTITIES:
|
||||
case SELF:
|
||||
return list2;
|
||||
}
|
||||
return list2;
|
||||
}
|
||||
|
||||
protected Collection<Entity> preSelect(Location location) {
|
||||
switch (selector) {
|
||||
case PLAYER:
|
||||
case RANDOM_PLAYER:
|
||||
case ALL_PLAYER:
|
||||
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());
|
||||
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 Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
PLAYER, RANDOM_PLAYER, ALL_PLAYER, ALL_ENTITIES, SELF;
|
||||
|
||||
public static SelectorType getType(String str) {
|
||||
if (str != null) {
|
||||
switch (str.toLowerCase()) {
|
||||
case "@p":
|
||||
return PLAYER;
|
||||
case "@r":
|
||||
return RANDOM_PLAYER;
|
||||
case "@a":
|
||||
return ALL_PLAYER;
|
||||
case "@e":
|
||||
return ALL_ENTITIES;
|
||||
case "@s":
|
||||
return SELF;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.songoda.core.commands;
|
||||
|
||||
import com.songoda.core.compatibility.EntityNamespace;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SelectorArguments {
|
||||
|
||||
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})?)?$");
|
||||
|
||||
/**
|
||||
* Parse a command selector using Minecraft's selector format. <br>
|
||||
* Currently only supports distance and entity type
|
||||
*
|
||||
* @param sender CommandBlock or Player running the command
|
||||
* @param argument argument with the selector to parse
|
||||
*
|
||||
* @return SelectorArguments Object for grabbing the list of entities, or null if the selector is invalid
|
||||
*/
|
||||
@Nullable
|
||||
public static SelectorArguments parseSelector(@NotNull CommandSender sender, @NotNull String argument) {
|
||||
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) {
|
||||
selector.parseArguments(m.group(3));
|
||||
}
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
protected final CommandSender sender;
|
||||
protected final SelectorType selector;
|
||||
protected double rangeMin = 0, rangeMax = Double.POSITIVE_INFINITY;
|
||||
protected EntityType entityType;
|
||||
|
||||
public SelectorArguments(CommandSender sender, SelectorType type) {
|
||||
this.sender = sender;
|
||||
this.selector = type;
|
||||
}
|
||||
|
||||
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
|
||||
// 5.. = d >= 5
|
||||
// ..5 = d <= 15
|
||||
Matcher distGroup = selectorRangePattern.matcher(v[1]);
|
||||
if (distGroup.find()) {
|
||||
if (distGroup.group(1) != null) {
|
||||
rangeMin = Double.parseDouble(distGroup.group(1));
|
||||
}
|
||||
if (distGroup.group(3) == null) {
|
||||
rangeMax = rangeMin;
|
||||
} else if (distGroup.group(4) != null) {
|
||||
rangeMax = Double.parseDouble(distGroup.group(4));
|
||||
}
|
||||
}
|
||||
} 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.
|
||||
dx Entities between x and x + dx.
|
||||
dy Entities between y and y + dy.
|
||||
dz Entities between z and z + dz.
|
||||
gamemode Players with gamemode. It can be one of the following values: adventure, creative, spectator, survival, !adventure, !creative, !spectator, !survival
|
||||
level Experience level. It must be an integer value that is 0 or greater.
|
||||
limit Maximum number of entities to target. It must be an integer value that is 1 or greater.
|
||||
name Entity name.
|
||||
nbt NBT tag.
|
||||
scores Score.
|
||||
sort Sort the entities. It must be one of the following values: arbitrary, furthest, nearest, random
|
||||
tag Scoreboard tag.
|
||||
team Entities on team.
|
||||
type Entity type (target must be the specified entity type - https://www.digminecraft.com/lists/entity_list_pc.php ).
|
||||
x Entity's x-coordinate position.
|
||||
x_rotation Entity's x rotation (vertical rotation).
|
||||
y Entity's y-coordinate position.
|
||||
y_rotation Entity's y rotation (horizontal rotation).
|
||||
z Entity's z-coordinate position.
|
||||
target selector arguments are case-sensitive
|
||||
@e[type=cow,limit=5]
|
||||
*/
|
||||
}
|
||||
|
||||
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)));
|
||||
return Arrays.asList(list2.get(0));
|
||||
case RANDOM_PLAYER:
|
||||
Collections.shuffle(list2);
|
||||
return Arrays.asList(list2.get(0));
|
||||
case ALL_PLAYER:
|
||||
case ALL_ENTITIES:
|
||||
case SELF:
|
||||
return list2;
|
||||
}
|
||||
return list2;
|
||||
}
|
||||
|
||||
protected Collection<Entity> preSelect(Location location) {
|
||||
switch (selector) {
|
||||
case PLAYER:
|
||||
case RANDOM_PLAYER:
|
||||
case ALL_PLAYER:
|
||||
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());
|
||||
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 Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
PLAYER, RANDOM_PLAYER, ALL_PLAYER, ALL_ENTITIES, SELF;
|
||||
|
||||
public static SelectorType getType(String str) {
|
||||
if (str != null) {
|
||||
switch (str.toLowerCase()) {
|
||||
case "@p":
|
||||
return PLAYER;
|
||||
case "@r":
|
||||
return RANDOM_PLAYER;
|
||||
case "@a":
|
||||
return ALL_PLAYER;
|
||||
case "@e":
|
||||
return ALL_ENTITIES;
|
||||
case "@s":
|
||||
return SELF;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,24 @@
|
||||
package com.songoda.core.commands;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SimpleNestedCommand {
|
||||
|
||||
final AbstractCommand parent;
|
||||
final LinkedHashMap<String, AbstractCommand> children = new LinkedHashMap<>();
|
||||
|
||||
protected SimpleNestedCommand(AbstractCommand parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public SimpleNestedCommand addSubCommand(AbstractCommand command) {
|
||||
command.getCommands().forEach(cmd -> children.put(cmd.toLowerCase(), command));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleNestedCommand addSubCommands(AbstractCommand... commands) {
|
||||
Stream.of(commands).forEach(command -> command.getCommands().forEach(cmd -> children.put(cmd.toLowerCase(), command)));
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.commands;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SimpleNestedCommand {
|
||||
|
||||
final AbstractCommand parent;
|
||||
final LinkedHashMap<String, AbstractCommand> children = new LinkedHashMap<>();
|
||||
|
||||
protected SimpleNestedCommand(AbstractCommand parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public SimpleNestedCommand addSubCommand(AbstractCommand command) {
|
||||
command.getCommands().forEach(cmd -> children.put(cmd.toLowerCase(), command));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleNestedCommand addSubCommands(AbstractCommand... commands) {
|
||||
Stream.of(commands).forEach(command -> command.getCommands().forEach(cmd -> children.put(cmd.toLowerCase(), command)));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,94 +1,93 @@
|
||||
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 {
|
||||
|
||||
/**
|
||||
* # Comment
|
||||
*/
|
||||
SIMPLE(false, false, " ", ""),
|
||||
/**
|
||||
* # <br />
|
||||
* # Comment <br />
|
||||
* # <br />
|
||||
*/
|
||||
SPACED(false, true, " ", ""),
|
||||
/**
|
||||
* ########### <br />
|
||||
* # Comment # <br />
|
||||
* ########### <br />
|
||||
*/
|
||||
BLOCKED(true, false, " ", " "),
|
||||
/**
|
||||
* ############# <br />
|
||||
* #|¯¯¯¯¯¯¯¯¯|# <br />
|
||||
* #| Comment |# <br />
|
||||
* #|_________|# <br />
|
||||
* ############# <br />
|
||||
*/
|
||||
BLOCKSPACED(true, true, "|\u00AF", '\u00AF', "\u00AF|", "| ", " |", "|_", '_', "_|");
|
||||
|
||||
final boolean drawBorder, drawSpace;
|
||||
final String commentPrefix, spacePrefixTop, spacePrefixBottom;
|
||||
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) {
|
||||
this.drawBorder = drawBorder;
|
||||
this.drawSpace = drawSpace;
|
||||
this.commentPrefix = commentPrefix;
|
||||
this.spacePrefixTop = spacePrefixTop;
|
||||
this.spacePrefixBottom = spacePrefixBottom;
|
||||
this.commentSuffix = commentSuffix;
|
||||
this.spaceSuffixTop = spaceSuffixTop;
|
||||
this.spaceSuffixBottom = spaceSuffixBottom;
|
||||
this.spaceCharTop = spaceCharTop;
|
||||
this.spaceCharBottom = spaceCharBottom;
|
||||
}
|
||||
|
||||
private CommentStyle(boolean drawBorder, boolean drawSpace, String commentPrefix, String commentSuffix) {
|
||||
this.drawBorder = drawBorder;
|
||||
this.drawSpace = drawSpace;
|
||||
this.commentPrefix = commentPrefix;
|
||||
this.commentSuffix = commentSuffix;
|
||||
this.spacePrefixTop = this.spacePrefixBottom = "";
|
||||
this.spaceCharTop = this.spaceCharBottom = ' ';
|
||||
this.spaceSuffixTop = this.spaceSuffixBottom = "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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("#")) {
|
||||
return CommentStyle.SPACED;
|
||||
}
|
||||
boolean hasBorders = lines.size() > 2 && 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 + "+"
|
||||
+ CommentStyle.BLOCKSPACED.spaceSuffixTop + "#$").replace("|", "\\|"))
|
||||
&& lines.get(1).trim().matches(("^#"
|
||||
+ CommentStyle.BLOCKSPACED.spacePrefixTop + CommentStyle.BLOCKSPACED.spaceCharTop + "+"
|
||||
+ CommentStyle.BLOCKSPACED.spaceSuffixTop + "#$").replace("|", "\\|"))) {
|
||||
return CommentStyle.BLOCKSPACED;
|
||||
}
|
||||
return CommentStyle.BLOCKED;
|
||||
}
|
||||
}
|
||||
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 {
|
||||
|
||||
/**
|
||||
* # Comment
|
||||
*/
|
||||
SIMPLE(false, false, " ", ""),
|
||||
/**
|
||||
* # <br />
|
||||
* # Comment <br />
|
||||
* # <br />
|
||||
*/
|
||||
SPACED(false, true, " ", ""),
|
||||
/**
|
||||
* ########### <br />
|
||||
* # Comment # <br />
|
||||
* ########### <br />
|
||||
*/
|
||||
BLOCKED(true, false, " ", " "),
|
||||
/**
|
||||
* ############# <br />
|
||||
* #|¯¯¯¯¯¯¯¯¯|# <br />
|
||||
* #| Comment |# <br />
|
||||
* #|_________|# <br />
|
||||
* ############# <br />
|
||||
*/
|
||||
BLOCKSPACED(true, true, "|\u00AF", '\u00AF', "\u00AF|", "| ", " |", "|_", '_', "_|");
|
||||
|
||||
final boolean drawBorder, drawSpace;
|
||||
final String commentPrefix, spacePrefixTop, spacePrefixBottom;
|
||||
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) {
|
||||
this.drawBorder = drawBorder;
|
||||
this.drawSpace = drawSpace;
|
||||
this.commentPrefix = commentPrefix;
|
||||
this.spacePrefixTop = spacePrefixTop;
|
||||
this.spacePrefixBottom = spacePrefixBottom;
|
||||
this.commentSuffix = commentSuffix;
|
||||
this.spaceSuffixTop = spaceSuffixTop;
|
||||
this.spaceSuffixBottom = spaceSuffixBottom;
|
||||
this.spaceCharTop = spaceCharTop;
|
||||
this.spaceCharBottom = spaceCharBottom;
|
||||
}
|
||||
|
||||
private CommentStyle(boolean drawBorder, boolean drawSpace, String commentPrefix, String commentSuffix) {
|
||||
this.drawBorder = drawBorder;
|
||||
this.drawSpace = drawSpace;
|
||||
this.commentPrefix = commentPrefix;
|
||||
this.commentSuffix = commentSuffix;
|
||||
this.spacePrefixTop = this.spacePrefixBottom = "";
|
||||
this.spaceCharTop = this.spaceCharBottom = ' ';
|
||||
this.spaceSuffixTop = this.spaceSuffixBottom = "";
|
||||
}
|
||||
}
|
||||
|
||||
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("#")) {
|
||||
return CommentStyle.SPACED;
|
||||
}
|
||||
boolean hasBorders = lines.size() > 2 && 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 + "+"
|
||||
+ CommentStyle.BLOCKSPACED.spaceSuffixTop + "#$").replace("|", "\\|"))
|
||||
&& lines.get(1).trim().matches(("^#"
|
||||
+ CommentStyle.BLOCKSPACED.spacePrefixTop + CommentStyle.BLOCKSPACED.spaceCharTop + "+"
|
||||
+ CommentStyle.BLOCKSPACED.spaceSuffixTop + "#$").replace("|", "\\|"))) {
|
||||
return CommentStyle.BLOCKSPACED;
|
||||
}
|
||||
return CommentStyle.BLOCKED;
|
||||
}
|
||||
}
|
||||
|
@ -129,5 +129,4 @@ public class ConfigSetting {
|
||||
|
||||
return mat != null ? mat : def;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,265 +1,270 @@
|
||||
package com.songoda.core.configuration;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.function.Function;
|
||||
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();
|
||||
private File file;
|
||||
private final Object lock = new Object();
|
||||
SaveTask saveTask;
|
||||
Timer autosaveTimer;
|
||||
/**
|
||||
* time in seconds to start a save after a change is made
|
||||
*/
|
||||
int autosaveInterval = 60;
|
||||
|
||||
public SimpleDataStore(@NotNull Plugin plugin, @NotNull String filename, @NotNull Function<ConfigurationSection, T> loadFunction) {
|
||||
this.plugin = plugin;
|
||||
this.filename = filename;
|
||||
dirName = null;
|
||||
this.getFromSection = loadFunction;
|
||||
}
|
||||
|
||||
public SimpleDataStore(@NotNull Plugin plugin, @Nullable String directory, @NotNull String filename, @NotNull Function<ConfigurationSection, T> loadFunction) {
|
||||
this.plugin = plugin;
|
||||
this.filename = filename;
|
||||
this.dirName = directory;
|
||||
this.getFromSection = loadFunction;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public File getFile() {
|
||||
if (file == null) {
|
||||
if (dirName != null) {
|
||||
this.file = new File(plugin.getDataFolder() + dirName, filename != null ? filename : "data.yml");
|
||||
} else {
|
||||
this.file = new File(plugin.getDataFolder(), filename != null ? filename : "data.yml");
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a directly-modifiable instance of the data mapping for this
|
||||
* storage
|
||||
*/
|
||||
public Map<Object, T> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified key is mapped, or {@code null}
|
||||
* if this map contains no mapping for the key.
|
||||
*
|
||||
* @param key key whose mapping is to be retrieved from this storage
|
||||
* @return the value associated with <tt>key</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
|
||||
*/
|
||||
@Nullable
|
||||
public T get(Object key) {
|
||||
return data.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the mapping for the specified key from this storage if present.
|
||||
*
|
||||
* @param key key whose mapping is to be removed from this storage
|
||||
* @return the previous value associated with <tt>key</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
|
||||
*/
|
||||
@Nullable
|
||||
public T remove(@NotNull Object key) {
|
||||
T temp;
|
||||
synchronized (lock) {
|
||||
temp = data.remove(key);
|
||||
}
|
||||
save();
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the mapping for the specified key from this storage if present.
|
||||
*
|
||||
* @param value value whose mapping is to be removed from this storage
|
||||
* @return the previous value associated with <tt>key</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
|
||||
*/
|
||||
@Nullable
|
||||
public T remove(@NotNull T value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
T temp;
|
||||
synchronized (lock) {
|
||||
temp = data.remove(value.getKey());
|
||||
}
|
||||
save();
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified value in this storage. If the map previously contained
|
||||
* a mapping for the key, the old value is replaced.
|
||||
*
|
||||
* @param value value to be added
|
||||
* @return the previous value associated with <tt>value.getKey()</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>value.getKey()</tt>.
|
||||
*/
|
||||
@Nullable
|
||||
public T add(@NotNull T value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
T temp;
|
||||
synchronized (lock) {
|
||||
temp = data.put(value.getKey(), value);
|
||||
}
|
||||
save();
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified value in this storage. If the map previously contained
|
||||
* a mapping for the key, the old value is replaced.
|
||||
*
|
||||
* @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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified value in this storage. If the map previously contained
|
||||
* a mapping for the key, the old value is replaced.
|
||||
*
|
||||
* @param value values to be added
|
||||
*/
|
||||
@Nullable
|
||||
public void addAll(@NotNull Collection<T> value) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (lock) {
|
||||
for (T v : value) {
|
||||
if (v != null) {
|
||||
data.put(v.getKey(), v);
|
||||
}
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load data from the associated file
|
||||
*/
|
||||
public void load() {
|
||||
if (!getFile().exists()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
YamlConfiguration f = new YamlConfiguration();
|
||||
f.options().pathSeparator('\0');
|
||||
f.load(file);
|
||||
|
||||
synchronized (lock) {
|
||||
data.clear();
|
||||
f.getValues(false).entrySet().stream()
|
||||
.filter(d -> d.getValue() instanceof ConfigurationSection)
|
||||
.map(Map.Entry::getValue)
|
||||
.map(v -> getFromSection.apply((ConfigurationSection) v))
|
||||
.forEach(v -> data.put(v.getKey(), v));
|
||||
}
|
||||
} catch (IOException | InvalidConfigurationException ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to load data from " + file.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally save this storage's data to file if there have been changes
|
||||
* made
|
||||
*/
|
||||
public void saveChanges() {
|
||||
if (saveTask != null || data.values().stream().anyMatch(v -> v.hasChanged())) {
|
||||
flushSave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save this file data. This saves later asynchronously.
|
||||
*/
|
||||
public void save() {
|
||||
// save async even if no plugin or if plugin disabled
|
||||
if (saveTask == null) {
|
||||
autosaveTimer = new Timer((plugin != null ? plugin.getName() + "-DataStoreSave-" : "DataStoreSave-") + getFile().getName());
|
||||
autosaveTimer.schedule(saveTask = new SaveTask(), autosaveInterval * 1000L);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a new save of this storage's data
|
||||
*/
|
||||
public void flushSave() {
|
||||
if (saveTask != null) {
|
||||
//Close Threads
|
||||
saveTask.cancel();
|
||||
autosaveTimer.cancel();
|
||||
saveTask = null;
|
||||
autosaveTimer = null;
|
||||
}
|
||||
YamlConfiguration f = new YamlConfiguration();
|
||||
synchronized (lock) {
|
||||
data.values().stream().forEach(e -> e.saveToSection(f.createSection(e.getConfigKey())));
|
||||
}
|
||||
try {
|
||||
f.save(getFile());
|
||||
data.values().stream().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();
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.songoda.core.configuration;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.function.Function;
|
||||
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();
|
||||
private File file;
|
||||
private final Object lock = new Object();
|
||||
SaveTask saveTask;
|
||||
Timer autosaveTimer;
|
||||
/**
|
||||
* time in seconds to start a save after a change is made
|
||||
*/
|
||||
int autosaveInterval = 60;
|
||||
|
||||
public SimpleDataStore(@NotNull Plugin plugin, @NotNull String filename, @NotNull Function<ConfigurationSection, T> loadFunction) {
|
||||
this.plugin = plugin;
|
||||
this.filename = filename;
|
||||
dirName = null;
|
||||
this.getFromSection = loadFunction;
|
||||
}
|
||||
|
||||
public SimpleDataStore(@NotNull Plugin plugin, @Nullable String directory, @NotNull String filename, @NotNull Function<ConfigurationSection, T> loadFunction) {
|
||||
this.plugin = plugin;
|
||||
this.filename = filename;
|
||||
this.dirName = directory;
|
||||
this.getFromSection = loadFunction;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public File getFile() {
|
||||
if (file == null) {
|
||||
if (dirName != null) {
|
||||
this.file = new File(plugin.getDataFolder() + dirName, filename != null ? filename : "data.yml");
|
||||
} else {
|
||||
this.file = new File(plugin.getDataFolder(), filename != null ? filename : "data.yml");
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a directly-modifiable instance of the data mapping for this
|
||||
* storage
|
||||
*/
|
||||
public Map<Object, T> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified key is mapped, or {@code null}
|
||||
* if this map contains no mapping for the key.
|
||||
*
|
||||
* @param key key whose mapping is to be retrieved from this storage
|
||||
*
|
||||
* @return the value associated with <tt>key</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
|
||||
*/
|
||||
@Nullable
|
||||
public T get(Object key) {
|
||||
return data.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the mapping for the specified key from this storage if present.
|
||||
*
|
||||
* @param key key whose mapping is to be removed from this storage
|
||||
*
|
||||
* @return the previous value associated with <tt>key</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
|
||||
*/
|
||||
@Nullable
|
||||
public T remove(@NotNull Object key) {
|
||||
T temp;
|
||||
synchronized (lock) {
|
||||
temp = data.remove(key);
|
||||
}
|
||||
save();
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the mapping for the specified key from this storage if present.
|
||||
*
|
||||
* @param value value whose mapping is to be removed from this storage
|
||||
*
|
||||
* @return the previous value associated with <tt>key</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
|
||||
*/
|
||||
@Nullable
|
||||
public T remove(@NotNull T value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
T temp;
|
||||
synchronized (lock) {
|
||||
temp = data.remove(value.getKey());
|
||||
}
|
||||
save();
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified value in this storage. If the map previously contained
|
||||
* a mapping for the key, the old value is replaced.
|
||||
*
|
||||
* @param value value to be added
|
||||
*
|
||||
* @return the previous value associated with <tt>value.getKey()</tt>, or
|
||||
* <tt>null</tt> if there was no mapping for <tt>value.getKey()</tt>.
|
||||
*/
|
||||
@Nullable
|
||||
public T add(@NotNull T value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
T temp;
|
||||
synchronized (lock) {
|
||||
temp = data.put(value.getKey(), value);
|
||||
}
|
||||
save();
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified value in this storage. If the map previously contained
|
||||
* a mapping for the key, the old value is replaced.
|
||||
*
|
||||
* @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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified value in this storage. If the map previously contained
|
||||
* a mapping for the key, the old value is replaced.
|
||||
*
|
||||
* @param value values to be added
|
||||
*/
|
||||
@Nullable
|
||||
public void addAll(@NotNull Collection<T> value) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (lock) {
|
||||
for (T v : value) {
|
||||
if (v != null) {
|
||||
data.put(v.getKey(), v);
|
||||
}
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load data from the associated file
|
||||
*/
|
||||
public void load() {
|
||||
if (!getFile().exists()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
YamlConfiguration f = new YamlConfiguration();
|
||||
f.options().pathSeparator('\0');
|
||||
f.load(file);
|
||||
|
||||
synchronized (lock) {
|
||||
data.clear();
|
||||
f.getValues(false).entrySet().stream()
|
||||
.filter(d -> d.getValue() instanceof ConfigurationSection)
|
||||
.map(Map.Entry::getValue)
|
||||
.map(v -> getFromSection.apply((ConfigurationSection) v))
|
||||
.forEach(v -> data.put(v.getKey(), v));
|
||||
}
|
||||
} catch (IOException | InvalidConfigurationException ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to load data from " + file.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally save this storage's data to file if there have been changes
|
||||
* made
|
||||
*/
|
||||
public void saveChanges() {
|
||||
if (saveTask != null || data.values().stream().anyMatch(v -> v.hasChanged())) {
|
||||
flushSave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save this file data. This saves later asynchronously.
|
||||
*/
|
||||
public void save() {
|
||||
// save async even if no plugin or if plugin disabled
|
||||
if (saveTask == null) {
|
||||
autosaveTimer = new Timer((plugin != null ? plugin.getName() + "-DataStoreSave-" : "DataStoreSave-") + getFile().getName());
|
||||
autosaveTimer.schedule(saveTask = new SaveTask(), autosaveInterval * 1000L);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a new save of this storage's data
|
||||
*/
|
||||
public void flushSave() {
|
||||
if (saveTask != null) {
|
||||
//Close Threads
|
||||
saveTask.cancel();
|
||||
autosaveTimer.cancel();
|
||||
saveTask = null;
|
||||
autosaveTimer = null;
|
||||
}
|
||||
YamlConfiguration f = new YamlConfiguration();
|
||||
synchronized (lock) {
|
||||
data.values().stream().forEach(e -> e.saveToSection(f.createSection(e.getConfigKey())));
|
||||
}
|
||||
try {
|
||||
f.save(getFile());
|
||||
data.values().stream().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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,308 +1,306 @@
|
||||
package com.songoda.core.configuration.editor;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.configuration.Config;
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.gui.SimplePagedGui;
|
||||
import com.songoda.core.input.ChatPrompt;
|
||||
import com.songoda.core.utils.ItemUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.MemoryConfiguration;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
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;
|
||||
final ConfigurationSection node;
|
||||
final Player player;
|
||||
Method configSection_getCommentString = null;
|
||||
boolean edits = false;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
this.config = config;
|
||||
this.node = node;
|
||||
this.blankItem = GuiUtils.getBorderItem(CompatibleMaterial.LIGHT_GRAY_STAINED_GLASS_PANE);
|
||||
|
||||
if (!(parent instanceof ConfigEditorGui)) {
|
||||
setOnClose((gui) -> save());
|
||||
} else {
|
||||
setOnClose((gui) -> ((ConfigEditorGui) parent).edits |= edits);
|
||||
}
|
||||
|
||||
// if we have a ConfigSection, we can also grab comments
|
||||
try {
|
||||
configSection_getCommentString = node.getClass().getDeclaredMethod("getCommentString", String.class);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
|
||||
// decorate header
|
||||
this.setTitle(ChatColor.DARK_BLUE + file);
|
||||
this.setUseHeader(true);
|
||||
headerBackItem = footerBackItem = GuiUtils.getBorderItem(CompatibleMaterial.GRAY_STAINED_GLASS_PANE.getItem());
|
||||
final String path = node.getCurrentPath();
|
||||
this.setItem(4, configItem(CompatibleMaterial.FILLED_MAP, !path.isEmpty() ? path : file, config, !path.isEmpty() ? path : null, ChatColor.BLACK.toString()));
|
||||
this.setButton(8, GuiUtils.createButtonItem(CompatibleMaterial.OAK_DOOR, "Exit"), (event) -> event.player.closeInventory());
|
||||
|
||||
// compile list of settings
|
||||
for (String key : node.getKeys(false)) {
|
||||
if (node.isConfigurationSection(key)) {
|
||||
sections.add(key);
|
||||
} else {
|
||||
settings.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
// next we need to display the config settings
|
||||
int index = 9;
|
||||
for (final String sectionKey : sections) {
|
||||
setButton(index++, configItem(CompatibleMaterial.WRITABLE_BOOK, ChatColor.YELLOW + sectionKey, node, sectionKey, "Click to open this section"),
|
||||
(event) -> event.manager.showGUI(event.player, new ConfigEditorGui(player, plugin, this, file, config, node.getConfigurationSection(sectionKey))));
|
||||
}
|
||||
|
||||
// now display individual settings
|
||||
for (final String settingKey : settings) {
|
||||
final Object val = node.get(settingKey);
|
||||
if (val == null) continue;
|
||||
else 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"),
|
||||
(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"),
|
||||
(event) -> {
|
||||
event.gui.exit();
|
||||
ChatPrompt.showPrompt(plugin, event.player, "Enter a new number value for " + settingKey + ":", response -> {
|
||||
if (!setNumber(event.slot, settingKey, response.getMessage().trim())) {
|
||||
event.player.sendMessage(ChatColor.RED + "Error: \"" + response.getMessage().trim() + "\" is not a number!");
|
||||
}
|
||||
}).setOnClose(() -> event.manager.showGUI(event.player, this))
|
||||
.setOnCancel(() -> {
|
||||
event.player.sendMessage(ChatColor.RED + "Edit canceled");
|
||||
event.manager.showGUI(event.player, this);
|
||||
});
|
||||
});
|
||||
} else if (isMaterial(val)) {
|
||||
// changing a block
|
||||
// isMaterial is more of a guess, to be honest.
|
||||
setButton(index, configItem(CompatibleMaterial.STONE, ChatColor.YELLOW + settingKey, node, settingKey, val.toString(), "Click to edit this setting"),
|
||||
(event) -> {
|
||||
SimplePagedGui paged = new SimplePagedGui(this);
|
||||
paged.setTitle(ChatColor.BLUE + settingKey);
|
||||
paged.setHeaderBackItem(headerBackItem).setFooterBackItem(footerBackItem).setDefaultItem(blankItem);
|
||||
paged.setItem(4, configItem(CompatibleMaterial.FILLED_MAP, settingKey, node, settingKey, "Choose an item to change this value to"));
|
||||
int i = 9;
|
||||
for (CompatibleMaterial mat : CompatibleMaterial.getAllValidItemMaterials()) {
|
||||
paged.setButton(i++, GuiUtils.createButtonItem(mat, mat.name()), ClickType.LEFT, (matEvent) -> {
|
||||
setMaterial(event.slot, settingKey, matEvent.clickedItem);
|
||||
matEvent.player.closeInventory();
|
||||
});
|
||||
}
|
||||
event.manager.showGUI(event.player, paged);
|
||||
});
|
||||
|
||||
} else if (val instanceof String) {
|
||||
// changing a "string" value (or change to a feather for writing quill)
|
||||
setButton(index, configItem(CompatibleMaterial.STRING, ChatColor.YELLOW + settingKey, node, settingKey, val.toString(), "Click to edit this setting"),
|
||||
(event) -> {
|
||||
event.gui.exit();
|
||||
ChatPrompt.showPrompt(plugin, event.player, "Enter a new value for " + settingKey + ":", response -> {
|
||||
node.set(settingKey, response.getMessage().trim());
|
||||
updateValue(event.slot, settingKey);
|
||||
}).setOnClose(() -> event.manager.showGUI(event.player, this))
|
||||
.setOnCancel(() -> {
|
||||
event.player.sendMessage(ChatColor.RED + "Edit canceled");
|
||||
event.manager.showGUI(event.player, this);
|
||||
});
|
||||
});
|
||||
} 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 {
|
||||
// idk. should we display uneditable values?
|
||||
}
|
||||
|
||||
++index;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ConfigurationSection getCurrentNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
protected void updateValue(int clickCell, String path) {
|
||||
ItemStack item = inventory.getItem(clickCell);
|
||||
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());
|
||||
} else {
|
||||
valStr = val.toString();
|
||||
}
|
||||
List<String> lore = meta.getLore();
|
||||
if (lore == null || lore.isEmpty()) {
|
||||
meta.setLore(Arrays.asList(valStr));
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
boolean setNumber(int clickCell, String path, String input) {
|
||||
try {
|
||||
if (node.isInt(path)) {
|
||||
node.set(path, Integer.parseInt(input));
|
||||
} else if (node.isDouble(path)) {
|
||||
node.set(path, Double.parseDouble(input));
|
||||
} else if (node.isLong(path)) {
|
||||
node.set(path, Long.parseLong(input));
|
||||
}
|
||||
updateValue(clickCell, path);
|
||||
} catch (NumberFormatException e) {
|
||||
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);
|
||||
}
|
||||
|
||||
void setList(int clickCell, String path, List<String> list) {
|
||||
node.set(path, list);
|
||||
updateValue(clickCell, path);
|
||||
}
|
||||
|
||||
void save() {
|
||||
if (!edits) {
|
||||
return;
|
||||
}
|
||||
// could also check and call saveChanges()
|
||||
if (config instanceof FileConfiguration) {
|
||||
try {
|
||||
((FileConfiguration) config).save(new File(plugin.getDataFolder(), file));
|
||||
} catch (IOException ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to save config changes to " + file, ex);
|
||||
return;
|
||||
}
|
||||
} else if (config instanceof Config) {
|
||||
((Config) config).save();
|
||||
} else {
|
||||
player.sendMessage(ChatColor.RED + "Unknown configuration type '" + config.getClass().getName() + "' - Please report this error!");
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
}
|
||||
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 = "";
|
||||
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");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
return GuiUtils.createButtonItem(type, name, info != null ? info : (def != null ? (value + "\n" + def).split("\n") : null));
|
||||
}
|
||||
}
|
||||
package com.songoda.core.configuration.editor;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.configuration.Config;
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.gui.SimplePagedGui;
|
||||
import com.songoda.core.input.ChatPrompt;
|
||||
import com.songoda.core.utils.ItemUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.MemoryConfiguration;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
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;
|
||||
final ConfigurationSection node;
|
||||
final Player player;
|
||||
Method configSection_getCommentString = null;
|
||||
boolean edits = false;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
this.config = config;
|
||||
this.node = node;
|
||||
this.blankItem = GuiUtils.getBorderItem(CompatibleMaterial.LIGHT_GRAY_STAINED_GLASS_PANE);
|
||||
|
||||
if (!(parent instanceof ConfigEditorGui)) {
|
||||
setOnClose((gui) -> save());
|
||||
} else {
|
||||
setOnClose((gui) -> ((ConfigEditorGui) parent).edits |= edits);
|
||||
}
|
||||
|
||||
// if we have a ConfigSection, we can also grab comments
|
||||
try {
|
||||
configSection_getCommentString = node.getClass().getDeclaredMethod("getCommentString", String.class);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
|
||||
// decorate header
|
||||
this.setTitle(ChatColor.DARK_BLUE + file);
|
||||
this.setUseHeader(true);
|
||||
headerBackItem = footerBackItem = GuiUtils.getBorderItem(CompatibleMaterial.GRAY_STAINED_GLASS_PANE.getItem());
|
||||
final String path = node.getCurrentPath();
|
||||
this.setItem(4, configItem(CompatibleMaterial.FILLED_MAP, !path.isEmpty() ? path : file, config, !path.isEmpty() ? path : null, ChatColor.BLACK.toString()));
|
||||
this.setButton(8, GuiUtils.createButtonItem(CompatibleMaterial.OAK_DOOR, "Exit"), (event) -> event.player.closeInventory());
|
||||
|
||||
// compile list of settings
|
||||
for (String key : node.getKeys(false)) {
|
||||
if (node.isConfigurationSection(key)) {
|
||||
sections.add(key);
|
||||
} else {
|
||||
settings.add(key);
|
||||
}
|
||||
}
|
||||
|
||||
// next we need to display the config settings
|
||||
int index = 9;
|
||||
for (final String sectionKey : sections) {
|
||||
setButton(index++, configItem(CompatibleMaterial.WRITABLE_BOOK, ChatColor.YELLOW + sectionKey, node, sectionKey, "Click to open this section"),
|
||||
(event) -> event.manager.showGUI(event.player, new ConfigEditorGui(player, plugin, this, file, config, node.getConfigurationSection(sectionKey))));
|
||||
}
|
||||
|
||||
// now display individual settings
|
||||
for (final String settingKey : settings) {
|
||||
final Object val = node.get(settingKey);
|
||||
if (val == null) continue;
|
||||
else 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"),
|
||||
(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"),
|
||||
(event) -> {
|
||||
event.gui.exit();
|
||||
ChatPrompt.showPrompt(plugin, event.player, "Enter a new number value for " + settingKey + ":", response -> {
|
||||
if (!setNumber(event.slot, settingKey, response.getMessage().trim())) {
|
||||
event.player.sendMessage(ChatColor.RED + "Error: \"" + response.getMessage().trim() + "\" is not a number!");
|
||||
}
|
||||
}).setOnClose(() -> event.manager.showGUI(event.player, this))
|
||||
.setOnCancel(() -> {
|
||||
event.player.sendMessage(ChatColor.RED + "Edit canceled");
|
||||
event.manager.showGUI(event.player, this);
|
||||
});
|
||||
});
|
||||
} else if (isMaterial(val)) {
|
||||
// changing a block
|
||||
// isMaterial is more of a guess, to be honest.
|
||||
setButton(index, configItem(CompatibleMaterial.STONE, ChatColor.YELLOW + settingKey, node, settingKey, val.toString(), "Click to edit this setting"),
|
||||
(event) -> {
|
||||
SimplePagedGui paged = new SimplePagedGui(this);
|
||||
paged.setTitle(ChatColor.BLUE + settingKey);
|
||||
paged.setHeaderBackItem(headerBackItem).setFooterBackItem(footerBackItem).setDefaultItem(blankItem);
|
||||
paged.setItem(4, configItem(CompatibleMaterial.FILLED_MAP, settingKey, node, settingKey, "Choose an item to change this value to"));
|
||||
int i = 9;
|
||||
for (CompatibleMaterial mat : CompatibleMaterial.getAllValidItemMaterials()) {
|
||||
paged.setButton(i++, GuiUtils.createButtonItem(mat, mat.name()), ClickType.LEFT, (matEvent) -> {
|
||||
setMaterial(event.slot, settingKey, matEvent.clickedItem);
|
||||
matEvent.player.closeInventory();
|
||||
});
|
||||
}
|
||||
event.manager.showGUI(event.player, paged);
|
||||
});
|
||||
} else if (val instanceof String) {
|
||||
// changing a "string" value (or change to a feather for writing quill)
|
||||
setButton(index, configItem(CompatibleMaterial.STRING, ChatColor.YELLOW + settingKey, node, settingKey, val.toString(), "Click to edit this setting"),
|
||||
(event) -> {
|
||||
event.gui.exit();
|
||||
ChatPrompt.showPrompt(plugin, event.player, "Enter a new value for " + settingKey + ":", response -> {
|
||||
node.set(settingKey, response.getMessage().trim());
|
||||
updateValue(event.slot, settingKey);
|
||||
}).setOnClose(() -> event.manager.showGUI(event.player, this))
|
||||
.setOnCancel(() -> {
|
||||
event.player.sendMessage(ChatColor.RED + "Edit canceled");
|
||||
event.manager.showGUI(event.player, this);
|
||||
});
|
||||
});
|
||||
} 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 {
|
||||
// idk. should we display uneditable values?
|
||||
}
|
||||
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
public ConfigurationSection getCurrentNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
protected void updateValue(int clickCell, String path) {
|
||||
ItemStack item = inventory.getItem(clickCell);
|
||||
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());
|
||||
} else {
|
||||
valStr = val.toString();
|
||||
}
|
||||
List<String> lore = meta.getLore();
|
||||
if (lore == null || lore.isEmpty()) {
|
||||
meta.setLore(Arrays.asList(valStr));
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
boolean setNumber(int clickCell, String path, String input) {
|
||||
try {
|
||||
if (node.isInt(path)) {
|
||||
node.set(path, Integer.parseInt(input));
|
||||
} else if (node.isDouble(path)) {
|
||||
node.set(path, Double.parseDouble(input));
|
||||
} else if (node.isLong(path)) {
|
||||
node.set(path, Long.parseLong(input));
|
||||
}
|
||||
updateValue(clickCell, path);
|
||||
} catch (NumberFormatException e) {
|
||||
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);
|
||||
}
|
||||
|
||||
void setList(int clickCell, String path, List<String> list) {
|
||||
node.set(path, list);
|
||||
updateValue(clickCell, path);
|
||||
}
|
||||
|
||||
void save() {
|
||||
if (!edits) {
|
||||
return;
|
||||
}
|
||||
// could also check and call saveChanges()
|
||||
if (config instanceof FileConfiguration) {
|
||||
try {
|
||||
((FileConfiguration) config).save(new File(plugin.getDataFolder(), file));
|
||||
} catch (IOException ex) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Failed to save config changes to " + file, ex);
|
||||
return;
|
||||
}
|
||||
} else if (config instanceof Config) {
|
||||
((Config) config).save();
|
||||
} else {
|
||||
player.sendMessage(ChatColor.RED + "Unknown configuration type '" + config.getClass().getName() + "' - Please report this error!");
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
}
|
||||
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 = "";
|
||||
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");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
return GuiUtils.createButtonItem(type, name, info != null ? info : (def != null ? (value + "\n" + def).split("\n") : null));
|
||||
}
|
||||
}
|
||||
|
@ -1,85 +1,84 @@
|
||||
package com.songoda.core.configuration.editor;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.gui.SimplePagedGui;
|
||||
import com.songoda.core.input.ChatPrompt;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
public List<String> values;
|
||||
|
||||
public ConfigEditorListEditorGui(ConfigEditorGui current, String key, List<String> val) {
|
||||
super(current);
|
||||
this.current = current;
|
||||
this.blankItem = current.getDefaultItem();
|
||||
headerBackItem = footerBackItem = current.getHeaderBackItem();
|
||||
setTitle(ChatColor.DARK_BLUE + "String List Editor");
|
||||
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.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) -> {
|
||||
saveChanges = true;
|
||||
event.player.closeInventory();
|
||||
});
|
||||
this.setButton(1, GuiUtils.createButtonItem(CompatibleMaterial.CHEST, ChatColor.BLUE + "Add Item"),
|
||||
(event) -> {
|
||||
event.gui.exit();
|
||||
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);
|
||||
})
|
||||
.setOnCancel(() -> {
|
||||
event.player.sendMessage(ChatColor.RED + "Edit canceled");
|
||||
event.manager.showGUI(event.player, this);
|
||||
});
|
||||
});
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
void redraw() {
|
||||
page = 1;
|
||||
// clear old display
|
||||
if (inventory != null) {
|
||||
for (Integer i : cellItems.keySet().toArray(new Integer[0])) {
|
||||
if (i > 8) {
|
||||
cellItems.remove(i);
|
||||
conditionalButtons.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update items
|
||||
int i = 9;
|
||||
for (String item : values) {
|
||||
final int index = i - 9;
|
||||
setButton(i++, GuiUtils.createButtonItem(CompatibleMaterial.PAPER, item, "Right-click to remove"), ClickType.RIGHT, (event) -> {
|
||||
values.remove(index);
|
||||
redraw();
|
||||
});
|
||||
}
|
||||
// update display
|
||||
update();
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.configuration.editor;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.gui.SimplePagedGui;
|
||||
import com.songoda.core.input.ChatPrompt;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
public List<String> values;
|
||||
|
||||
public ConfigEditorListEditorGui(ConfigEditorGui current, String key, List<String> val) {
|
||||
super(current);
|
||||
this.current = current;
|
||||
this.blankItem = current.getDefaultItem();
|
||||
headerBackItem = footerBackItem = current.getHeaderBackItem();
|
||||
setTitle(ChatColor.DARK_BLUE + "String List Editor");
|
||||
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.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) -> {
|
||||
saveChanges = true;
|
||||
event.player.closeInventory();
|
||||
});
|
||||
this.setButton(1, GuiUtils.createButtonItem(CompatibleMaterial.CHEST, ChatColor.BLUE + "Add Item"),
|
||||
(event) -> {
|
||||
event.gui.exit();
|
||||
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);
|
||||
})
|
||||
.setOnCancel(() -> {
|
||||
event.player.sendMessage(ChatColor.RED + "Edit canceled");
|
||||
event.manager.showGUI(event.player, this);
|
||||
});
|
||||
});
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
void redraw() {
|
||||
page = 1;
|
||||
// clear old display
|
||||
if (inventory != null) {
|
||||
for (Integer i : cellItems.keySet().toArray(new Integer[0])) {
|
||||
if (i > 8) {
|
||||
cellItems.remove(i);
|
||||
conditionalButtons.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update items
|
||||
int i = 9;
|
||||
for (String item : values) {
|
||||
final int index = i - 9;
|
||||
setButton(i++, GuiUtils.createButtonItem(CompatibleMaterial.PAPER, item, "Right-click to remove"), ClickType.RIGHT, (event) -> {
|
||||
values.remove(index);
|
||||
redraw();
|
||||
});
|
||||
}
|
||||
// update display
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
@ -1,99 +1,98 @@
|
||||
package com.songoda.core.configuration.editor;
|
||||
|
||||
import com.songoda.core.SongodaPlugin;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.configuration.Config;
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.gui.SimplePagedGui;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.MemoryConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
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();
|
||||
|
||||
public PluginConfigGui(SongodaPlugin plugin) {
|
||||
this(plugin, null);
|
||||
}
|
||||
|
||||
public PluginConfigGui(SongodaPlugin plugin, Gui parent) {
|
||||
super(parent);
|
||||
this.plugin = plugin;
|
||||
|
||||
// collect list of plugins
|
||||
configs.put(plugin.getCoreConfig().getFile().getName(), plugin.getCoreConfig());
|
||||
List<Config> more = plugin.getExtraConfig();
|
||||
if (more != null && !more.isEmpty()) {
|
||||
for (Config cfg : more) {
|
||||
configs.put(cfg.getFile().getName(), cfg);
|
||||
}
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
public PluginConfigGui(JavaPlugin plugin) {
|
||||
this(plugin, null);
|
||||
}
|
||||
|
||||
public PluginConfigGui(JavaPlugin plugin, Gui parent) {
|
||||
super(parent);
|
||||
this.plugin = plugin;
|
||||
|
||||
// collect list of plugins
|
||||
configs.put("config.yml", plugin.getConfig());
|
||||
|
||||
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()) {
|
||||
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)) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
|
||||
// I guess not!
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
this.blankItem = GuiUtils.getBorderItem(CompatibleMaterial.LIGHT_GRAY_STAINED_GLASS_PANE);
|
||||
|
||||
// decorate header
|
||||
this.setTitle(ChatColor.DARK_BLUE + plugin.getName() + " Plugin Config");
|
||||
this.setUseHeader(true);
|
||||
headerBackItem = footerBackItem = GuiUtils.getBorderItem(CompatibleMaterial.GRAY_STAINED_GLASS_PANE.getItem());
|
||||
this.setButton(8, GuiUtils.createButtonItem(CompatibleMaterial.OAK_DOOR, "Exit"), (event) -> event.player.closeInventory());
|
||||
|
||||
// List out all config files that this plugin has
|
||||
int i = 9;
|
||||
for (Map.Entry<String, MemoryConfiguration> config : configs.entrySet()) {
|
||||
this.setButton(i++, GuiUtils.createButtonItem(CompatibleMaterial.BOOK, ChatColor.YELLOW + config.getKey(), "Click to edit this config"),
|
||||
(event) -> event.manager.showGUI(event.player, new ConfigEditorGui(event.player, plugin, this, config.getKey(), config.getValue())));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.configuration.editor;
|
||||
|
||||
import com.songoda.core.SongodaPlugin;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.configuration.Config;
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.gui.SimplePagedGui;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.configuration.MemoryConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
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();
|
||||
|
||||
public PluginConfigGui(SongodaPlugin plugin) {
|
||||
this(plugin, null);
|
||||
}
|
||||
|
||||
public PluginConfigGui(SongodaPlugin plugin, Gui parent) {
|
||||
super(parent);
|
||||
this.plugin = plugin;
|
||||
|
||||
// collect list of plugins
|
||||
configs.put(plugin.getCoreConfig().getFile().getName(), plugin.getCoreConfig());
|
||||
List<Config> more = plugin.getExtraConfig();
|
||||
if (more != null && !more.isEmpty()) {
|
||||
for (Config cfg : more) {
|
||||
configs.put(cfg.getFile().getName(), cfg);
|
||||
}
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
public PluginConfigGui(JavaPlugin plugin) {
|
||||
this(plugin, null);
|
||||
}
|
||||
|
||||
public PluginConfigGui(JavaPlugin plugin, Gui parent) {
|
||||
super(parent);
|
||||
this.plugin = plugin;
|
||||
|
||||
// collect list of plugins
|
||||
configs.put("config.yml", plugin.getConfig());
|
||||
|
||||
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()) {
|
||||
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)) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
|
||||
// I guess not!
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
this.blankItem = GuiUtils.getBorderItem(CompatibleMaterial.LIGHT_GRAY_STAINED_GLASS_PANE);
|
||||
|
||||
// decorate header
|
||||
this.setTitle(ChatColor.DARK_BLUE + plugin.getName() + " Plugin Config");
|
||||
this.setUseHeader(true);
|
||||
headerBackItem = footerBackItem = GuiUtils.getBorderItem(CompatibleMaterial.GRAY_STAINED_GLASS_PANE.getItem());
|
||||
this.setButton(8, GuiUtils.createButtonItem(CompatibleMaterial.OAK_DOOR, "Exit"), (event) -> event.player.closeInventory());
|
||||
|
||||
// List out all config files that this plugin has
|
||||
int i = 9;
|
||||
for (Map.Entry<String, MemoryConfiguration> config : configs.entrySet()) {
|
||||
this.setButton(i++, GuiUtils.createButtonItem(CompatibleMaterial.BOOK, ChatColor.YELLOW + config.getKey(), "Click to edit this config"),
|
||||
(event) -> event.manager.showGUI(event.player, new ConfigEditorGui(event.player, plugin, this, config.getKey(), config.getValue())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,5 +3,4 @@ package com.songoda.core.core;
|
||||
public interface PluginInfoModule {
|
||||
|
||||
void run(PluginInfo plugin);
|
||||
|
||||
}
|
||||
|
@ -1,52 +1,51 @@
|
||||
package com.songoda.core.core;
|
||||
|
||||
import com.songoda.core.SongodaCore;
|
||||
import com.songoda.core.commands.AbstractCommand;
|
||||
import com.songoda.core.gui.GuiManager;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SongodaCoreCommand extends AbstractCommand {
|
||||
|
||||
protected GuiManager guiManager;
|
||||
|
||||
public SongodaCoreCommand() {
|
||||
super(false, "songoda");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReturnType runCommand(CommandSender sender, String... args) {
|
||||
if (sender instanceof Player) {
|
||||
if (guiManager == null || guiManager.isClosed()) {
|
||||
guiManager = new GuiManager(SongodaCore.getHijackedPlugin());
|
||||
}
|
||||
guiManager.showGUI((Player) sender, new SongodaCoreOverviewGUI());
|
||||
} else {
|
||||
sender.sendMessage("/songoda diag");
|
||||
}
|
||||
return ReturnType.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode() {
|
||||
return "songoda.admin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSyntax() {
|
||||
return "/songoda";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays this interface.";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> onTab(CommandSender sender, String... args) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.core;
|
||||
|
||||
import com.songoda.core.SongodaCore;
|
||||
import com.songoda.core.commands.AbstractCommand;
|
||||
import com.songoda.core.gui.GuiManager;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SongodaCoreCommand extends AbstractCommand {
|
||||
|
||||
protected GuiManager guiManager;
|
||||
|
||||
public SongodaCoreCommand() {
|
||||
super(false, "songoda");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReturnType runCommand(CommandSender sender, String... args) {
|
||||
if (sender instanceof Player) {
|
||||
if (guiManager == null || guiManager.isClosed()) {
|
||||
guiManager = new GuiManager(SongodaCore.getHijackedPlugin());
|
||||
}
|
||||
guiManager.showGUI((Player) sender, new SongodaCoreOverviewGUI());
|
||||
} else {
|
||||
sender.sendMessage("/songoda diag");
|
||||
}
|
||||
return ReturnType.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPermissionNode() {
|
||||
return "songoda.admin";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSyntax() {
|
||||
return "/songoda";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Displays this interface.";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> onTab(CommandSender sender, String... args) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ package com.songoda.core.core;
|
||||
|
||||
import com.songoda.core.SongodaCore;
|
||||
import com.songoda.core.commands.AbstractCommand;
|
||||
import com.songoda.core.compatibility.ClassMapping;
|
||||
import com.songoda.core.compatibility.ServerProject;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import com.songoda.core.compatibility.ClassMapping;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
|
@ -25,26 +25,26 @@ final class SongodaCoreOverviewGUI extends Gui {
|
||||
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(),
|
||||
ChatColor.GRAY + "Latest Version: " + plugin.getLatestVersion(),
|
||||
ChatColor.GRAY + "Installed Version: " + plugin.getJavaPlugin().getDescription().getVersion(),
|
||||
"",
|
||||
"Change log:",
|
||||
plugin.getChangeLog(),
|
||||
"",
|
||||
ChatColor.GOLD + "Click for the marketplace page link.",
|
||||
ChatColor.GOLD + "Right Click to edit plugin settings."
|
||||
ChatColor.GOLD + plugin.getJavaPlugin().getName(),
|
||||
ChatColor.GRAY + "Latest Version: " + plugin.getLatestVersion(),
|
||||
ChatColor.GRAY + "Installed Version: " + plugin.getJavaPlugin().getDescription().getVersion(),
|
||||
"",
|
||||
"Change log:",
|
||||
plugin.getChangeLog(),
|
||||
"",
|
||||
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)));
|
||||
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."
|
||||
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)));
|
||||
|
@ -19,5 +19,4 @@ public abstract class DataMigration {
|
||||
public int getRevision() {
|
||||
return this.revision;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -100,5 +100,4 @@ public class DataMigrationManager {
|
||||
private String getMigrationsTableName() {
|
||||
return this.dataManagerAbstract.getTablePrefix() + "migrations";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,5 +30,4 @@ public interface DatabaseConnector {
|
||||
interface ConnectionCallback {
|
||||
void accept(Connection connection) throws SQLException;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -51,5 +51,4 @@ public class MySQLConnector implements DatabaseConnector {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -57,5 +57,4 @@ public class SQLiteConnector implements DatabaseConnector {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,5 +10,4 @@ public enum BackgroundType {
|
||||
private 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
@ -1,21 +1,20 @@
|
||||
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);
|
||||
|
||||
protected final InventoryType type;
|
||||
protected final int rows;
|
||||
protected final int columns;
|
||||
|
||||
private GuiType(InventoryType type, int rows, int columns) {
|
||||
this.type = type;
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
}
|
||||
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);
|
||||
|
||||
protected final InventoryType type;
|
||||
protected final int rows;
|
||||
protected final int columns;
|
||||
|
||||
private GuiType(InventoryType type, int rows, int columns) {
|
||||
this.type = type;
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
}
|
||||
}
|
||||
|
@ -1,412 +1,413 @@
|
||||
package com.songoda.core.gui;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
}
|
||||
|
||||
public static List<String> getSafeLore(String... lines) {
|
||||
return getSafeLore(Arrays.asList(lines));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a lore value that will display fine on clients using auto gui scaling
|
||||
*
|
||||
* @param lines lines to format
|
||||
* @return newline and length-corrected item lore
|
||||
*/
|
||||
public static List<String> getSafeLore(List<String> lines) {
|
||||
// fix newlines
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack createButtonItem(CompatibleMaterial mat, int amount, List<String> lore) {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack updateItem(ItemStack item, CompatibleMaterial matTo, String title, String... lore) {
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack updateItem(ItemStack item, ItemStack to, String title, String... lore) {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack updateItem(ItemStack item, CompatibleMaterial matTo, String title, List<String> lore) {
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack updateItem(ItemStack item, ItemStack to, String title, List<String> lore) {
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
package com.songoda.core.gui;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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;
|
||||
}
|
||||
|
||||
public static List<String> getSafeLore(String... lines) {
|
||||
return getSafeLore(Arrays.asList(lines));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a lore value that will display fine on clients using auto gui scaling
|
||||
*
|
||||
* @param lines lines to format
|
||||
*
|
||||
* @return newline and length-corrected item lore
|
||||
*/
|
||||
public static List<String> getSafeLore(List<String> lines) {
|
||||
// fix newlines
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack createButtonItem(CompatibleMaterial mat, int amount, List<String> lore) {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack updateItem(ItemStack item, CompatibleMaterial matTo, String title, String... lore) {
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack updateItem(ItemStack item, ItemStack to, String title, String... lore) {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack updateItem(ItemStack item, CompatibleMaterial matTo, String title, List<String> lore) {
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
public static ItemStack updateItem(ItemStack item, ItemStack to, String title, List<String> lore) {
|
||||
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);
|
||||
}
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
@ -1,187 +1,186 @@
|
||||
package com.songoda.core.gui;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.advancement.Advancement;
|
||||
import org.bukkit.advancement.AdvancementProgress;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Instance of a popup message that can be sent to a player <br>
|
||||
* Popup toast messages only work on Minecraft 1.12+ <br>
|
||||
* 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();
|
||||
|
||||
final UUID id = UUID.randomUUID();
|
||||
private final NamespacedKey key;
|
||||
private final TextComponent title;
|
||||
CompatibleMaterial icon;
|
||||
TriggerType trigger = TriggerType.IMPOSSIBLE;
|
||||
FrameType frame = FrameType.GOAL; // TASK is the default
|
||||
BackgroundType background = BackgroundType.ADVENTURE;
|
||||
|
||||
PopupMessage(Plugin source, CompatibleMaterial icon, String title) {
|
||||
this.key = new NamespacedKey(source, "popup/" + id);
|
||||
this.title = new TextComponent(title.length() < 74 ? title : (title.substring(0, 72) + "..."));
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
PopupMessage(Plugin source, CompatibleMaterial icon, String title, BackgroundType background) {
|
||||
this.key = new NamespacedKey(source, "popup/" + id);
|
||||
this.title = new TextComponent(title.length() < 74 ? title : (title.substring(0, 72) + "..."));
|
||||
this.icon = icon;
|
||||
this.background = background;
|
||||
}
|
||||
|
||||
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", "");
|
||||
advDisplay.addProperty("frame", this.frame.id);
|
||||
advDisplay.addProperty("announce_to_chat", false);
|
||||
advDisplay.addProperty("show_toast", true);
|
||||
advDisplay.addProperty("hidden", true);
|
||||
json.add("display", advDisplay);
|
||||
|
||||
JsonObject advCriteria = new JsonObject();
|
||||
json.add("criteria", advCriteria);
|
||||
|
||||
JsonObject advTrigger = new JsonObject();
|
||||
advTrigger.addProperty("trigger", this.trigger.getKey());
|
||||
/*if() {
|
||||
JsonObject advConditions = new JsonObject();
|
||||
// can add items to this list with [item,amount,data]
|
||||
advTrigger.add("conditions", advConditions);
|
||||
}*/
|
||||
advCriteria.add("mentioned", advTrigger);
|
||||
|
||||
return gson.toJson(json);
|
||||
}
|
||||
|
||||
protected void grant(final Player pl) {
|
||||
final Advancement adv = getAdvancement();
|
||||
final AdvancementProgress progress = pl.getAdvancementProgress(adv);
|
||||
|
||||
if (!progress.isDone())
|
||||
progress.getRemainingCriteria().forEach((crit) -> progress.awardCriteria(crit));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
protected void add() {
|
||||
if (!registeredMessages.contains(id)) {
|
||||
registeredMessages.add(id);
|
||||
try {
|
||||
Bukkit.getUnsafe().loadAdvancement(key, getJSON());
|
||||
} catch (IllegalArgumentException e) {
|
||||
Bukkit.getLogger().warning("Failed to create popup advancement!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void remove() {
|
||||
if (registeredMessages.contains(id)) {
|
||||
registeredMessages.remove(id);
|
||||
Bukkit.getUnsafe().removeAdvancement(key);
|
||||
}
|
||||
}
|
||||
|
||||
public Advancement getAdvancement() {
|
||||
return Bukkit.getAdvancement(key);
|
||||
}
|
||||
|
||||
public static enum FrameType {
|
||||
TASK,
|
||||
CHALLENGE,
|
||||
GOAL;
|
||||
final String id;
|
||||
|
||||
private FrameType() {
|
||||
id = name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
public static enum TriggerType {
|
||||
ARBITRARY_PLAYER_TICK(ServerVersion.V1_13, "TICK"),
|
||||
BRED_ANIMALS,
|
||||
BREWED_POTION,
|
||||
CHANGED_DIMENSION,
|
||||
CONSTRUCT_BEACON,
|
||||
CONSUME_ITEM,
|
||||
CURED_ZOMBIE_VILLAGER,
|
||||
EFFECTS_CHANGED,
|
||||
ENCHANTED_ITEM,
|
||||
ENTER_BLOCK,
|
||||
ENTITY_HURT_PLAYER,
|
||||
ENTITY_KILLED_PLAYER,
|
||||
IMPOSSIBLE,
|
||||
INVENTORY_CHANGED,
|
||||
ITEM_DURABILITY_CHANGED,
|
||||
LEVITATION,
|
||||
LOCATION,
|
||||
NETHER_TRAVEL,
|
||||
PLACED_BLOCK,
|
||||
PLAYER_HURT_ENTITY,
|
||||
PLAYER_KILL_ENTITY,
|
||||
RECIPE_UNLOCKED,
|
||||
SLEPT_IN_BED,
|
||||
SUMMONED_ENTITY,
|
||||
TAME_ANIMAL,
|
||||
TICK,
|
||||
USED_ENDER_EYE,
|
||||
USED_TOTEM,
|
||||
VILLAGER_TRADE;
|
||||
final ServerVersion minVersion;
|
||||
final String compatible;
|
||||
final String key;
|
||||
|
||||
private TriggerType() {
|
||||
this.minVersion = ServerVersion.UNKNOWN;
|
||||
this.compatible = "";
|
||||
this.key = "minecraft:" + name().toLowerCase();
|
||||
}
|
||||
|
||||
private TriggerType(ServerVersion minVersion, String compatible) {
|
||||
this.minVersion = minVersion;
|
||||
this.compatible = compatible;
|
||||
this.key = "minecraft:" + (ServerVersion.isServerVersionAtLeast(minVersion) ? name() : compatible).toLowerCase();
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
package com.songoda.core.gui;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.advancement.Advancement;
|
||||
import org.bukkit.advancement.AdvancementProgress;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Instance of a popup message that can be sent to a player <br>
|
||||
* Popup toast messages only work on Minecraft 1.12+ <br>
|
||||
* 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();
|
||||
|
||||
final UUID id = UUID.randomUUID();
|
||||
private final NamespacedKey key;
|
||||
private final TextComponent title;
|
||||
CompatibleMaterial icon;
|
||||
TriggerType trigger = TriggerType.IMPOSSIBLE;
|
||||
FrameType frame = FrameType.GOAL; // TASK is the default
|
||||
BackgroundType background = BackgroundType.ADVENTURE;
|
||||
|
||||
PopupMessage(Plugin source, CompatibleMaterial icon, String title) {
|
||||
this.key = new NamespacedKey(source, "popup/" + id);
|
||||
this.title = new TextComponent(title.length() < 74 ? title : (title.substring(0, 72) + "..."));
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
PopupMessage(Plugin source, CompatibleMaterial icon, String title, BackgroundType background) {
|
||||
this.key = new NamespacedKey(source, "popup/" + id);
|
||||
this.title = new TextComponent(title.length() < 74 ? title : (title.substring(0, 72) + "..."));
|
||||
this.icon = icon;
|
||||
this.background = background;
|
||||
}
|
||||
|
||||
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", "");
|
||||
advDisplay.addProperty("frame", this.frame.id);
|
||||
advDisplay.addProperty("announce_to_chat", false);
|
||||
advDisplay.addProperty("show_toast", true);
|
||||
advDisplay.addProperty("hidden", true);
|
||||
json.add("display", advDisplay);
|
||||
|
||||
JsonObject advCriteria = new JsonObject();
|
||||
json.add("criteria", advCriteria);
|
||||
|
||||
JsonObject advTrigger = new JsonObject();
|
||||
advTrigger.addProperty("trigger", this.trigger.getKey());
|
||||
/*if() {
|
||||
JsonObject advConditions = new JsonObject();
|
||||
// can add items to this list with [item,amount,data]
|
||||
advTrigger.add("conditions", advConditions);
|
||||
}*/
|
||||
advCriteria.add("mentioned", advTrigger);
|
||||
|
||||
return gson.toJson(json);
|
||||
}
|
||||
|
||||
protected void grant(final Player pl) {
|
||||
final Advancement adv = getAdvancement();
|
||||
final AdvancementProgress progress = pl.getAdvancementProgress(adv);
|
||||
|
||||
if (!progress.isDone())
|
||||
progress.getRemainingCriteria().forEach((crit) -> progress.awardCriteria(crit));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
protected void add() {
|
||||
if (!registeredMessages.contains(id)) {
|
||||
registeredMessages.add(id);
|
||||
try {
|
||||
Bukkit.getUnsafe().loadAdvancement(key, getJSON());
|
||||
} catch (IllegalArgumentException e) {
|
||||
Bukkit.getLogger().warning("Failed to create popup advancement!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void remove() {
|
||||
if (registeredMessages.contains(id)) {
|
||||
registeredMessages.remove(id);
|
||||
Bukkit.getUnsafe().removeAdvancement(key);
|
||||
}
|
||||
}
|
||||
|
||||
public Advancement getAdvancement() {
|
||||
return Bukkit.getAdvancement(key);
|
||||
}
|
||||
|
||||
public static enum FrameType {
|
||||
TASK,
|
||||
CHALLENGE,
|
||||
GOAL;
|
||||
final String id;
|
||||
|
||||
private FrameType() {
|
||||
id = name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
public static enum TriggerType {
|
||||
ARBITRARY_PLAYER_TICK(ServerVersion.V1_13, "TICK"),
|
||||
BRED_ANIMALS,
|
||||
BREWED_POTION,
|
||||
CHANGED_DIMENSION,
|
||||
CONSTRUCT_BEACON,
|
||||
CONSUME_ITEM,
|
||||
CURED_ZOMBIE_VILLAGER,
|
||||
EFFECTS_CHANGED,
|
||||
ENCHANTED_ITEM,
|
||||
ENTER_BLOCK,
|
||||
ENTITY_HURT_PLAYER,
|
||||
ENTITY_KILLED_PLAYER,
|
||||
IMPOSSIBLE,
|
||||
INVENTORY_CHANGED,
|
||||
ITEM_DURABILITY_CHANGED,
|
||||
LEVITATION,
|
||||
LOCATION,
|
||||
NETHER_TRAVEL,
|
||||
PLACED_BLOCK,
|
||||
PLAYER_HURT_ENTITY,
|
||||
PLAYER_KILL_ENTITY,
|
||||
RECIPE_UNLOCKED,
|
||||
SLEPT_IN_BED,
|
||||
SUMMONED_ENTITY,
|
||||
TAME_ANIMAL,
|
||||
TICK,
|
||||
USED_ENDER_EYE,
|
||||
USED_TOTEM,
|
||||
VILLAGER_TRADE;
|
||||
final ServerVersion minVersion;
|
||||
final String compatible;
|
||||
final String key;
|
||||
|
||||
private TriggerType() {
|
||||
this.minVersion = ServerVersion.UNKNOWN;
|
||||
this.compatible = "";
|
||||
this.key = "minecraft:" + name().toLowerCase();
|
||||
}
|
||||
|
||||
private TriggerType(ServerVersion minVersion, String compatible) {
|
||||
this.minVersion = minVersion;
|
||||
this.compatible = compatible;
|
||||
this.key = "minecraft:" + (ServerVersion.isServerVersionAtLeast(minVersion) ? name() : compatible).toLowerCase();
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,28 @@
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiManager;
|
||||
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;
|
||||
|
||||
public class GuiClickEvent extends GuiEvent {
|
||||
public final int slot;
|
||||
public final boolean guiClicked;
|
||||
public final ItemStack cursor, clickedItem;
|
||||
public final ClickType clickType;
|
||||
public final InventoryClickEvent event;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiManager;
|
||||
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;
|
||||
|
||||
public class GuiClickEvent extends GuiEvent {
|
||||
public final int slot;
|
||||
public final boolean guiClicked;
|
||||
public final ItemStack cursor, clickedItem;
|
||||
public final ClickType clickType;
|
||||
public final InventoryClickEvent event;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,21 @@
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class GuiDropItemEvent extends GuiEvent {
|
||||
public final ItemStack cursor;
|
||||
public final ClickType clickType;
|
||||
public final InventoryClickEvent event;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class GuiDropItemEvent extends GuiEvent {
|
||||
public final ItemStack cursor;
|
||||
public final ClickType clickType;
|
||||
public final InventoryClickEvent event;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,18 @@
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
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;
|
||||
|
||||
public GuiEvent(GuiManager manager, Gui gui, Player player) {
|
||||
this.manager = manager;
|
||||
this.gui = gui;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
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;
|
||||
|
||||
public GuiEvent(GuiManager manager, Gui gui, Player player) {
|
||||
this.manager = manager;
|
||||
this.gui = gui;
|
||||
this.player = player;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,19 @@
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiManager;
|
||||
|
||||
public class GuiPageEvent {
|
||||
|
||||
final Gui gui;
|
||||
final GuiManager manager;
|
||||
final int lastPage;
|
||||
final int page;
|
||||
|
||||
public GuiPageEvent(Gui gui, GuiManager manager, int lastPage, int page) {
|
||||
this.gui = gui;
|
||||
this.manager = manager;
|
||||
this.lastPage = lastPage;
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.gui.events;
|
||||
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiManager;
|
||||
|
||||
public class GuiPageEvent {
|
||||
|
||||
final Gui gui;
|
||||
final GuiManager manager;
|
||||
final int lastPage;
|
||||
final int page;
|
||||
|
||||
public GuiPageEvent(Gui gui, GuiManager manager, int lastPage, int page) {
|
||||
this.gui = gui;
|
||||
this.manager = manager;
|
||||
this.lastPage = lastPage;
|
||||
this.page = page;
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,6 @@ import com.songoda.core.hooks.economies.Economy;
|
||||
import com.songoda.core.utils.NumberUtils;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/**
|
||||
* A convenience class for static access to an Economy HookManager
|
||||
*/
|
||||
@ -61,6 +59,7 @@ public class EconomyManager {
|
||||
* Format the given amount to a human-readable string in this currency
|
||||
*
|
||||
* @param amt amount to display
|
||||
*
|
||||
* @return a currency string as formatted by the economy plugin
|
||||
*/
|
||||
public static String formatEconomy(double amt) {
|
||||
@ -71,13 +70,13 @@ public class EconomyManager {
|
||||
* Get the players available balance
|
||||
*
|
||||
* @param player player
|
||||
*
|
||||
* @return the amount of available balance
|
||||
*/
|
||||
public static double getBalance(OfflinePlayer player) {
|
||||
if (!manager.isEnabled())
|
||||
return 0;
|
||||
return manager.getCurrentHook().getBalance(player);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,6 +85,7 @@ public class EconomyManager {
|
||||
*
|
||||
* @param player player to check
|
||||
* @param cost minimum amount this player should have
|
||||
*
|
||||
* @return true if this player can have this amount withdrawn
|
||||
*/
|
||||
public static boolean hasBalance(OfflinePlayer player, double cost) {
|
||||
@ -98,6 +98,7 @@ public class EconomyManager {
|
||||
*
|
||||
* @param player player to check
|
||||
* @param cost amount to remove from this player
|
||||
*
|
||||
* @return true if the total amount was withdrawn successfully
|
||||
*/
|
||||
public static boolean withdrawBalance(OfflinePlayer player, double cost) {
|
||||
@ -110,6 +111,7 @@ public class EconomyManager {
|
||||
*
|
||||
* @param player player to check
|
||||
* @param amount amount to add to this player
|
||||
*
|
||||
* @return true if the total amount was added successfully
|
||||
*/
|
||||
public static boolean deposit(OfflinePlayer player, double amount) {
|
||||
|
@ -1,184 +1,189 @@
|
||||
package com.songoda.core.hooks;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
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;
|
||||
private final Map<PluginHook, T> registeredHooks = new HashMap<>();
|
||||
|
||||
public HookManager(Class typeClass) {
|
||||
this.typeClass = typeClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all supported plugins.
|
||||
*/
|
||||
public void load() {
|
||||
load(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all supported plugins.
|
||||
*
|
||||
* @param hookingPlugin plugin to pass to the hook handler
|
||||
*/
|
||||
public void load(Plugin hookingPlugin) {
|
||||
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();
|
||||
}
|
||||
loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently selected plugin hook. <br>
|
||||
* If none were set, then the first one found is used.
|
||||
*
|
||||
* @return The instance of T that was created, or null if none available.
|
||||
*/
|
||||
public T getCurrentHook() {
|
||||
return defaultHook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default hook to a different plugin, if that plugin exists. <br>
|
||||
* If the plugin is not loaded or supported,
|
||||
* the previously defined default will be used.
|
||||
*
|
||||
* @param name name of the plugin to use
|
||||
* @return true if the default was set to this plugin
|
||||
*/
|
||||
public boolean setPreferredHook(String name) {
|
||||
T hook = getHook(name);
|
||||
if (hook != null) {
|
||||
defaultHook = hook;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default hook to a different plugin, if that plugin exists. <br />
|
||||
* If the plugin is not loaded or supported,
|
||||
* the previously defined default will be used.
|
||||
*
|
||||
* @param plugin plugin to use
|
||||
* @return true if the default was set to this plugin
|
||||
*/
|
||||
public boolean setPreferredHook(PluginHook plugin) {
|
||||
T hook = getHook(plugin);
|
||||
if (hook != null) {
|
||||
defaultHook = hook;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to grab the handler for this specific plugin hook.
|
||||
*
|
||||
* @param name plugin to use
|
||||
* @return returns null if plugin is not enabled
|
||||
*/
|
||||
public T getHook(String name) {
|
||||
if (name == null)
|
||||
return null;
|
||||
final String plugin = name.trim();
|
||||
return (T) registeredHooks.get(registeredHooks.keySet().stream()
|
||||
.filter(type -> type.plugin.equalsIgnoreCase(plugin))
|
||||
.findFirst().orElse(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to grab the handler for this specific plugin hook.
|
||||
*
|
||||
* @param hook plugin to use
|
||||
* @return returns null if plugin is not enabled
|
||||
*/
|
||||
public T getHook(PluginHook hook) {
|
||||
return registeredHooks.get(hook);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab a list of all supported and loaded plugin hooks.
|
||||
*
|
||||
* @return an immutable collection of the loaded handler instances
|
||||
*/
|
||||
public Collection<T> getRegisteredHooks() {
|
||||
return Collections.unmodifiableCollection(registeredHooks.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab a list of all supported and loaded plugin hooks.
|
||||
*
|
||||
* @return an immutable collection of plugin names that are loaded.
|
||||
*/
|
||||
public List<String> getRegisteredPlugins() {
|
||||
return registeredHooks.keySet().stream()
|
||||
.map(v -> v.plugin)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all supported plugins that we can hook into.
|
||||
*
|
||||
* @return an immutable collection of plugin names that can be used.
|
||||
*/
|
||||
public List<String> getPossiblePlugins() {
|
||||
return PluginHook.getHooks(typeClass).stream()
|
||||
.map(v -> v.plugin)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a specific plugin hook is enabled.
|
||||
*
|
||||
* @param name plugin to check
|
||||
* @return true if this plugin is supported and loaded
|
||||
*/
|
||||
public boolean isEnabled(String name) {
|
||||
return getHook(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a specific plugin hook is enabled.
|
||||
*
|
||||
* @param hook plugin to check
|
||||
* @return true if this plugin is supported and loaded
|
||||
*/
|
||||
public boolean isEnabled(PluginHook hook) {
|
||||
return registeredHooks.containsKey(hook);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if there is a default hook loaded.
|
||||
*
|
||||
* @return returns false if there are no supported plugins loaded
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return defaultHook != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the default plugin being hooked into.
|
||||
*
|
||||
* @return plugin name, or null if none enabled.
|
||||
*/
|
||||
public String getName() {
|
||||
return defaultHook != null ? defaultHook.getName() : null;
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.hooks;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
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;
|
||||
private final Map<PluginHook, T> registeredHooks = new HashMap<>();
|
||||
|
||||
public HookManager(Class typeClass) {
|
||||
this.typeClass = typeClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all supported plugins.
|
||||
*/
|
||||
public void load() {
|
||||
load(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all supported plugins.
|
||||
*
|
||||
* @param hookingPlugin plugin to pass to the hook handler
|
||||
*/
|
||||
public void load(Plugin hookingPlugin) {
|
||||
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();
|
||||
}
|
||||
loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently selected plugin hook. <br>
|
||||
* If none were set, then the first one found is used.
|
||||
*
|
||||
* @return The instance of T that was created, or null if none available.
|
||||
*/
|
||||
public T getCurrentHook() {
|
||||
return defaultHook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default hook to a different plugin, if that plugin exists. <br>
|
||||
* If the plugin is not loaded or supported,
|
||||
* the previously defined default will be used.
|
||||
*
|
||||
* @param name name of the plugin to use
|
||||
*
|
||||
* @return true if the default was set to this plugin
|
||||
*/
|
||||
public boolean setPreferredHook(String name) {
|
||||
T hook = getHook(name);
|
||||
if (hook != null) {
|
||||
defaultHook = hook;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default hook to a different plugin, if that plugin exists. <br />
|
||||
* If the plugin is not loaded or supported,
|
||||
* the previously defined default will be used.
|
||||
*
|
||||
* @param plugin plugin to use
|
||||
*
|
||||
* @return true if the default was set to this plugin
|
||||
*/
|
||||
public boolean setPreferredHook(PluginHook plugin) {
|
||||
T hook = getHook(plugin);
|
||||
if (hook != null) {
|
||||
defaultHook = hook;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to grab the handler for this specific plugin hook.
|
||||
*
|
||||
* @param name plugin to use
|
||||
*
|
||||
* @return returns null if plugin is not enabled
|
||||
*/
|
||||
public T getHook(String name) {
|
||||
if (name == null)
|
||||
return null;
|
||||
final String plugin = name.trim();
|
||||
return (T) registeredHooks.get(registeredHooks.keySet().stream()
|
||||
.filter(type -> type.plugin.equalsIgnoreCase(plugin))
|
||||
.findFirst().orElse(null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to grab the handler for this specific plugin hook.
|
||||
*
|
||||
* @param hook plugin to use
|
||||
*
|
||||
* @return returns null if plugin is not enabled
|
||||
*/
|
||||
public T getHook(PluginHook hook) {
|
||||
return registeredHooks.get(hook);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab a list of all supported and loaded plugin hooks.
|
||||
*
|
||||
* @return an immutable collection of the loaded handler instances
|
||||
*/
|
||||
public Collection<T> getRegisteredHooks() {
|
||||
return Collections.unmodifiableCollection(registeredHooks.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab a list of all supported and loaded plugin hooks.
|
||||
*
|
||||
* @return an immutable collection of plugin names that are loaded.
|
||||
*/
|
||||
public List<String> getRegisteredPlugins() {
|
||||
return registeredHooks.keySet().stream()
|
||||
.map(v -> v.plugin)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all supported plugins that we can hook into.
|
||||
*
|
||||
* @return an immutable collection of plugin names that can be used.
|
||||
*/
|
||||
public List<String> getPossiblePlugins() {
|
||||
return PluginHook.getHooks(typeClass).stream()
|
||||
.map(v -> v.plugin)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a specific plugin hook is enabled.
|
||||
*
|
||||
* @param name plugin to check
|
||||
*
|
||||
* @return true if this plugin is supported and loaded
|
||||
*/
|
||||
public boolean isEnabled(String name) {
|
||||
return getHook(name) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if a specific plugin hook is enabled.
|
||||
*
|
||||
* @param hook plugin to check
|
||||
*
|
||||
* @return true if this plugin is supported and loaded
|
||||
*/
|
||||
public boolean isEnabled(PluginHook hook) {
|
||||
return registeredHooks.containsKey(hook);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if there is a default hook loaded.
|
||||
*
|
||||
* @return returns false if there are no supported plugins loaded
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return defaultHook != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the default plugin being hooked into.
|
||||
*
|
||||
* @return plugin name, or null if none enabled.
|
||||
*/
|
||||
public String getName() {
|
||||
return defaultHook != null ? defaultHook.getName() : null;
|
||||
}
|
||||
}
|
||||
|
@ -88,5 +88,4 @@ public class LogManager {
|
||||
if (manager.isEnabled())
|
||||
manager.getCurrentHook().logInteraction(player, location);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,231 +1,230 @@
|
||||
package com.songoda.core.hooks;
|
||||
|
||||
import com.songoda.core.hooks.mcmmo.McMMOHandler;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class McMMOHook {
|
||||
|
||||
static boolean canHook = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
// if this class exists, we're good to use McMMO
|
||||
Class.forName("com.gmail.nossr50.api.AbilityAPI");
|
||||
canHook = true;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void addMining(Player player, Collection<Block> blocks) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addMining(player, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addExcavation(Player player, Collection<Block> blocks) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addExcavation(player, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addHerbalism(Player player, Collection<Block> blocks) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addHerbalism(player, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addWoodcutting(Player player, Collection<Block> blocks) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addWoodcutting(player, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getAcrobaticsSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getAcrobaticsSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getAlchemySkill(Player player) {
|
||||
return canHook ? McMMOHandler.getAlchemySkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getArcherySkill(Player player) {
|
||||
return canHook ? McMMOHandler.getArcherySkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getAxesSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getAxesSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getExcavationSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getExcavationSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getFishingSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getFishingSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getHerbalismSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getHerbalismSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getMiningSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getMiningSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getRepairSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getRepairSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getSmeltingSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getSmeltingSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getSwordsSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getSwordsSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getTamingSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getTamingSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getUnarmedSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getUnarmedSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getWoodcuttingSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getWoodcuttingSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static void addAcrobatics(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addAcrobatics(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addAlchemy(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addAlchemy(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addArchery(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addArchery(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addAxes(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addAxes(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addExcavation(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addExcavation(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addFishing(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addFishing(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addHerbalism(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addHerbalism(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addMining(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addMining(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addRepair(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addRepair(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addSmelting(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addSmelting(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addSwords(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addSwords(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addTaming(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addTaming(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addUnarmed(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addUnarmed(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addWoodcutting(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addWoodcutting(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasHerbalismDoubleDrops(Player player) {
|
||||
return canHook ? McMMOHandler.hasHerbalismDoubleDrops(player) : false;
|
||||
}
|
||||
|
||||
public static boolean hasMiningDoubleDrops(Player player) {
|
||||
return canHook ? McMMOHandler.hasMiningDoubleDrops(player) : false;
|
||||
}
|
||||
|
||||
public static boolean hasWoodcuttingDoubleDrops(Player player) {
|
||||
return canHook ? McMMOHandler.hasWoodcuttingDoubleDrops(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingBerserk(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingBerserk(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingGigaDrill(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingGigaDrill(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingGreenTerra(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingGreenTerra(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingSerratedStrikes(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingSerratedStrikes(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingSkullSplitter(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingSkullSplitter(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingSuperBreaker(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingSuperBreaker(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingTreeFeller(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingTreeFeller(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isBleeding(LivingEntity victim) {
|
||||
return canHook ? McMMOHandler.isBleeding(victim) : false;
|
||||
}
|
||||
|
||||
}
|
||||
package com.songoda.core.hooks;
|
||||
|
||||
import com.songoda.core.hooks.mcmmo.McMMOHandler;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class McMMOHook {
|
||||
|
||||
static boolean canHook = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
// if this class exists, we're good to use McMMO
|
||||
Class.forName("com.gmail.nossr50.api.AbilityAPI");
|
||||
canHook = true;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void addMining(Player player, Collection<Block> blocks) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addMining(player, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addExcavation(Player player, Collection<Block> blocks) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addExcavation(player, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addHerbalism(Player player, Collection<Block> blocks) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addHerbalism(player, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addWoodcutting(Player player, Collection<Block> blocks) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addWoodcutting(player, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getAcrobaticsSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getAcrobaticsSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getAlchemySkill(Player player) {
|
||||
return canHook ? McMMOHandler.getAlchemySkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getArcherySkill(Player player) {
|
||||
return canHook ? McMMOHandler.getArcherySkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getAxesSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getAxesSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getExcavationSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getExcavationSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getFishingSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getFishingSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getHerbalismSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getHerbalismSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getMiningSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getMiningSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getRepairSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getRepairSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getSmeltingSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getSmeltingSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getSwordsSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getSwordsSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getTamingSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getTamingSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getUnarmedSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getUnarmedSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static int getWoodcuttingSkill(Player player) {
|
||||
return canHook ? McMMOHandler.getWoodcuttingSkill(player) : -1;
|
||||
}
|
||||
|
||||
public static void addAcrobatics(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addAcrobatics(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addAlchemy(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addAlchemy(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addArchery(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addArchery(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addAxes(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addAxes(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addExcavation(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addExcavation(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addFishing(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addFishing(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addHerbalism(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addHerbalism(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addMining(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addMining(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addRepair(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addRepair(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addSmelting(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addSmelting(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addSwords(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addSwords(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addTaming(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addTaming(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addUnarmed(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addUnarmed(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addWoodcutting(Player player, int xp) {
|
||||
if (canHook) {
|
||||
McMMOHandler.addWoodcutting(player, xp);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasHerbalismDoubleDrops(Player player) {
|
||||
return canHook ? McMMOHandler.hasHerbalismDoubleDrops(player) : false;
|
||||
}
|
||||
|
||||
public static boolean hasMiningDoubleDrops(Player player) {
|
||||
return canHook ? McMMOHandler.hasMiningDoubleDrops(player) : false;
|
||||
}
|
||||
|
||||
public static boolean hasWoodcuttingDoubleDrops(Player player) {
|
||||
return canHook ? McMMOHandler.hasWoodcuttingDoubleDrops(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingBerserk(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingBerserk(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingGigaDrill(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingGigaDrill(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingGreenTerra(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingGreenTerra(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingSerratedStrikes(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingSerratedStrikes(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingSkullSplitter(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingSkullSplitter(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingSuperBreaker(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingSuperBreaker(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isUsingTreeFeller(Player player) {
|
||||
return canHook ? McMMOHandler.isUsingTreeFeller(player) : false;
|
||||
}
|
||||
|
||||
public static boolean isBleeding(LivingEntity victim) {
|
||||
return canHook ? McMMOHandler.isBleeding(victim) : false;
|
||||
}
|
||||
}
|
||||
|
@ -1,163 +1,169 @@
|
||||
package com.songoda.core.hooks;
|
||||
|
||||
import com.songoda.core.hooks.economies.Economy;
|
||||
import com.songoda.core.hooks.economies.PlayerPointsEconomy;
|
||||
import com.songoda.core.hooks.economies.ReserveEconomy;
|
||||
import com.songoda.core.hooks.economies.VaultEconomy;
|
||||
import com.songoda.core.hooks.holograms.CMIHolograms;
|
||||
import com.songoda.core.hooks.holograms.Holograms;
|
||||
import com.songoda.core.hooks.holograms.HologramsHolograms;
|
||||
import com.songoda.core.hooks.holograms.HolographicDisplaysHolograms;
|
||||
import com.songoda.core.hooks.log.CoreProtectLog;
|
||||
import com.songoda.core.hooks.log.Log;
|
||||
import com.songoda.core.hooks.protection.*;
|
||||
import com.songoda.core.hooks.stackers.StackMob;
|
||||
import com.songoda.core.hooks.stackers.Stacker;
|
||||
import com.songoda.core.hooks.stackers.UltimateStacker;
|
||||
import com.songoda.core.hooks.stackers.WildStacker;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
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);
|
||||
public static final PluginHook STACKER_ULTIMATE = new PluginHook(Stacker.class, "UltimateStacker", UltimateStacker.class);
|
||||
public static final PluginHook STACKER_WILD = new PluginHook(Stacker.class, "WildStacker", WildStacker.class);
|
||||
public static final PluginHook STACKER_STACK_MOB = new PluginHook(Stacker.class, "StackMob", StackMob.class);
|
||||
public static final PluginHook HOLO_DISPLAYS = new PluginHook(Holograms.class, "HolographicDisplays", HolographicDisplaysHolograms.class);
|
||||
public static final PluginHook HOLO_HOLOGRAMS = new PluginHook(Holograms.class, "Holograms", HologramsHolograms.class);
|
||||
public static final PluginHook HOLO_CMI = new PluginHook(Holograms.class, "CMI", CMIHolograms.class);
|
||||
public static final PluginHook LOG_CORE_PROTECT = new PluginHook(Log.class, "CoreProtect", CoreProtectLog.class);
|
||||
public static final PluginHook PROTECTION_GRIEFPREVENTION = new PluginHook(Protection.class, "GriefPrevention", GriefPreventionProtection.class);
|
||||
public static final PluginHook PROTECTION_LANDS = new PluginHook(Protection.class, "Lands", LandsProtection.class);
|
||||
public static final PluginHook PROTECTION_REDPROTECT = new PluginHook(Protection.class, "RedProtect", RedProtectProtection.class);
|
||||
public static final PluginHook PROTECTION_ULTIMATECLAIMS = new PluginHook(Protection.class, "UltimateClaims", UltimateClaimsProtection.class);
|
||||
public static final PluginHook PROTECTION_BENTOBOX = new PluginHook(Protection.class, "BentoBox", BentoBoxProtection.class);
|
||||
|
||||
/******* Start Manager stuff *******/
|
||||
|
||||
protected final T hookGeneric;
|
||||
protected final String plugin;
|
||||
protected final Class managerClass;
|
||||
protected static Map<Class, PluginHook> hooks;
|
||||
protected Constructor pluginConstructor; // for passing the plugin loading the hook to the plugin hook
|
||||
|
||||
private PluginHook(T type, String pluginName, Class handler) {
|
||||
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.put(handler, this);
|
||||
// Does this class have a plugin constructor?
|
||||
try {
|
||||
pluginConstructor = handler.getDeclaredConstructor(Plugin.class);
|
||||
} catch (NoSuchMethodException | SecurityException ex) {
|
||||
// nope!
|
||||
} catch (Throwable t) {
|
||||
// (can also reach here if there is a class loader exception)
|
||||
hooks.remove(handler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a hook handler for us to use later. <br>
|
||||
* NOTE: The class passed MUST extend Hook. <br>
|
||||
* 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.
|
||||
* @return instance of the PluginHook that was added
|
||||
*/
|
||||
public static <T extends Class> PluginHook addHook(T type, String pluginName, Class handler) {
|
||||
return new PluginHook(type, pluginName, handler);
|
||||
}
|
||||
|
||||
protected static Map<PluginHook, Hook> loadHooks(Class type, Plugin plugin) {
|
||||
Map<PluginHook, Hook> loaded = new LinkedHashMap<>();
|
||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
protected static List<PluginHook> getHooks(Class type) {
|
||||
return hooks.entrySet().parallelStream()
|
||||
.filter(e -> e.getKey() == type || e.getValue().managerClass == type || type.isAssignableFrom(e.getKey()))
|
||||
.map(Map.Entry::getValue)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public String getPluginName() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
protected Object load() {
|
||||
try {
|
||||
return managerClass.cast(
|
||||
pluginConstructor != null
|
||||
? pluginConstructor.newInstance((Plugin) null)
|
||||
: managerClass.getConstructor().newInstance());
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, "Unexpected Error while creating a new Hook Manager for " + plugin, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Object load(Plugin hookingPlugin) {
|
||||
try {
|
||||
return managerClass.cast(
|
||||
pluginConstructor != null
|
||||
? pluginConstructor.newInstance(hookingPlugin)
|
||||
: managerClass.getConstructor().newInstance());
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, "Unexpected Error while creating a new Hook Manager for " + plugin, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 37 * hash + Objects.hashCode(this.plugin);
|
||||
hash = 37 * hash + Objects.hashCode(this.managerClass);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
package com.songoda.core.hooks;
|
||||
|
||||
import com.songoda.core.hooks.economies.Economy;
|
||||
import com.songoda.core.hooks.economies.PlayerPointsEconomy;
|
||||
import com.songoda.core.hooks.economies.ReserveEconomy;
|
||||
import com.songoda.core.hooks.economies.VaultEconomy;
|
||||
import com.songoda.core.hooks.holograms.CMIHolograms;
|
||||
import com.songoda.core.hooks.holograms.Holograms;
|
||||
import com.songoda.core.hooks.holograms.HologramsHolograms;
|
||||
import com.songoda.core.hooks.holograms.HolographicDisplaysHolograms;
|
||||
import com.songoda.core.hooks.log.CoreProtectLog;
|
||||
import com.songoda.core.hooks.log.Log;
|
||||
import com.songoda.core.hooks.protection.BentoBoxProtection;
|
||||
import com.songoda.core.hooks.protection.GriefPreventionProtection;
|
||||
import com.songoda.core.hooks.protection.LandsProtection;
|
||||
import com.songoda.core.hooks.protection.Protection;
|
||||
import com.songoda.core.hooks.protection.RedProtectProtection;
|
||||
import com.songoda.core.hooks.protection.UltimateClaimsProtection;
|
||||
import com.songoda.core.hooks.stackers.StackMob;
|
||||
import com.songoda.core.hooks.stackers.Stacker;
|
||||
import com.songoda.core.hooks.stackers.UltimateStacker;
|
||||
import com.songoda.core.hooks.stackers.WildStacker;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
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);
|
||||
public static final PluginHook STACKER_ULTIMATE = new PluginHook(Stacker.class, "UltimateStacker", UltimateStacker.class);
|
||||
public static final PluginHook STACKER_WILD = new PluginHook(Stacker.class, "WildStacker", WildStacker.class);
|
||||
public static final PluginHook STACKER_STACK_MOB = new PluginHook(Stacker.class, "StackMob", StackMob.class);
|
||||
public static final PluginHook HOLO_DISPLAYS = new PluginHook(Holograms.class, "HolographicDisplays", HolographicDisplaysHolograms.class);
|
||||
public static final PluginHook HOLO_HOLOGRAMS = new PluginHook(Holograms.class, "Holograms", HologramsHolograms.class);
|
||||
public static final PluginHook HOLO_CMI = new PluginHook(Holograms.class, "CMI", CMIHolograms.class);
|
||||
public static final PluginHook LOG_CORE_PROTECT = new PluginHook(Log.class, "CoreProtect", CoreProtectLog.class);
|
||||
public static final PluginHook PROTECTION_GRIEFPREVENTION = new PluginHook(Protection.class, "GriefPrevention", GriefPreventionProtection.class);
|
||||
public static final PluginHook PROTECTION_LANDS = new PluginHook(Protection.class, "Lands", LandsProtection.class);
|
||||
public static final PluginHook PROTECTION_REDPROTECT = new PluginHook(Protection.class, "RedProtect", RedProtectProtection.class);
|
||||
public static final PluginHook PROTECTION_ULTIMATECLAIMS = new PluginHook(Protection.class, "UltimateClaims", UltimateClaimsProtection.class);
|
||||
public static final PluginHook PROTECTION_BENTOBOX = new PluginHook(Protection.class, "BentoBox", BentoBoxProtection.class);
|
||||
|
||||
/******* Start Manager stuff *******/
|
||||
|
||||
protected final T hookGeneric;
|
||||
protected final String plugin;
|
||||
protected final Class managerClass;
|
||||
protected static Map<Class, PluginHook> hooks;
|
||||
protected Constructor pluginConstructor; // for passing the plugin loading the hook to the plugin hook
|
||||
|
||||
private PluginHook(T type, String pluginName, Class handler) {
|
||||
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.put(handler, this);
|
||||
// Does this class have a plugin constructor?
|
||||
try {
|
||||
pluginConstructor = handler.getDeclaredConstructor(Plugin.class);
|
||||
} catch (NoSuchMethodException | SecurityException ex) {
|
||||
// nope!
|
||||
} catch (Throwable t) {
|
||||
// (can also reach here if there is a class loader exception)
|
||||
hooks.remove(handler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a hook handler for us to use later. <br>
|
||||
* NOTE: The class passed MUST extend Hook. <br>
|
||||
* 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.
|
||||
*
|
||||
* @return instance of the PluginHook that was added
|
||||
*/
|
||||
public static <T extends Class> PluginHook addHook(T type, String pluginName, Class handler) {
|
||||
return new PluginHook(type, pluginName, handler);
|
||||
}
|
||||
|
||||
protected static Map<PluginHook, Hook> loadHooks(Class type, Plugin plugin) {
|
||||
Map<PluginHook, Hook> loaded = new LinkedHashMap<>();
|
||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
protected static List<PluginHook> getHooks(Class type) {
|
||||
return hooks.entrySet().parallelStream()
|
||||
.filter(e -> e.getKey() == type || e.getValue().managerClass == type || type.isAssignableFrom(e.getKey()))
|
||||
.map(Map.Entry::getValue)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public String getPluginName() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
protected Object load() {
|
||||
try {
|
||||
return managerClass.cast(
|
||||
pluginConstructor != null
|
||||
? pluginConstructor.newInstance((Plugin) null)
|
||||
: managerClass.getConstructor().newInstance());
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, "Unexpected Error while creating a new Hook Manager for " + plugin, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Object load(Plugin hookingPlugin) {
|
||||
try {
|
||||
return managerClass.cast(
|
||||
pluginConstructor != null
|
||||
? pluginConstructor.newInstance(hookingPlugin)
|
||||
: managerClass.getConstructor().newInstance());
|
||||
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException ex) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, "Unexpected Error while creating a new Hook Manager for " + plugin, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 37 * hash + Objects.hashCode(this.plugin);
|
||||
hash = 37 * hash + Objects.hashCode(this.managerClass);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1,152 +1,162 @@
|
||||
package com.songoda.core.hooks;
|
||||
|
||||
import com.songoda.core.hooks.worldguard.WorldGuardFlagHandler;
|
||||
import com.songoda.core.hooks.worldguard.WorldGuardRegionHandler;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class WorldGuardHook {
|
||||
|
||||
static boolean canHook = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
// if this class exists, we're good to use WG classes
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.Flag");
|
||||
canHook = true;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to register a worldGuard flag (ALLOW/DENY) <br />
|
||||
* Note: This must be called before WorldGuard loads, or it will fail.
|
||||
*
|
||||
* @param flag name of the flag to set
|
||||
* @param state default value of the flag
|
||||
*/
|
||||
public static void addHook(@NotNull String flag, boolean state) {
|
||||
if (canHook) {
|
||||
WorldGuardFlagHandler.addHook(flag, state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if WorldGuard is installed and hooked
|
||||
*
|
||||
* @return true if and only if WorldGuard exists and addHook() has been
|
||||
* called and added successfully
|
||||
*/
|
||||
public static boolean isEnabled() {
|
||||
return canHook && WorldGuardFlagHandler.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks this location to see what this flag is set to
|
||||
*
|
||||
* @param l location to check
|
||||
* @param flag ALLOW/DENY flag to check
|
||||
* @return flag state, or null if undefined
|
||||
*/
|
||||
@Nullable
|
||||
public static Boolean getBooleanFlag(@NotNull Location l, @NotNull String flag) {
|
||||
return canHook ? WorldGuardFlagHandler.getBooleanFlag(l, flag) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query all regions that are in or intersect this chunk
|
||||
*
|
||||
* @param c chunk to check for regions in
|
||||
* @param flag ALLOW/DENY flag to check
|
||||
* @return flag state, or null if undefined
|
||||
*/
|
||||
@Nullable
|
||||
public static Boolean getBooleanFlag(@NotNull Chunk c, @NotNull String flag) {
|
||||
return canHook ? WorldGuardFlagHandler.getBooleanFlag(c, flag) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the pvp flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
* @return false if the pvp flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isPvpAllowed(@NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "pvp"), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the block-break flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
* @return false if the block-break flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isBreakAllowed(@NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "block-break"), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the build flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
* @return false if the build flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isBuildAllowed(@NotNull Player player, @NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "build", player), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the use flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
* @return false if the use flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isInteractAllowed(@NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "use"), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the other-explosion flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
* @return false if the other-explosion flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isExplosionsAllowed(@NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "other-explosion"), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the mob-spawning flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
* @return false if the mob-spawning flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isMobSpawningAllowed(@NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "mob-spawning"), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param loc Location to check
|
||||
* @return A list of regions that contain this location.
|
||||
*/
|
||||
@NotNull
|
||||
public static List<String> getRegionNames(@NotNull Location loc) {
|
||||
return canHook ? WorldGuardRegionHandler.getRegionNames(loc) : Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param c Chunk to check
|
||||
* @return A list of regions that contain any part of this chunk.
|
||||
*/
|
||||
@NotNull
|
||||
public static List<String> getRegionNames(@NotNull Chunk c) {
|
||||
return canHook ? WorldGuardRegionHandler.getRegionNames(c) : Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
package com.songoda.core.hooks;
|
||||
|
||||
import com.songoda.core.hooks.worldguard.WorldGuardFlagHandler;
|
||||
import com.songoda.core.hooks.worldguard.WorldGuardRegionHandler;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class WorldGuardHook {
|
||||
|
||||
static boolean canHook = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
// if this class exists, we're good to use WG classes
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.Flag");
|
||||
canHook = true;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to register a worldGuard flag (ALLOW/DENY) <br />
|
||||
* Note: This must be called before WorldGuard loads, or it will fail.
|
||||
*
|
||||
* @param flag name of the flag to set
|
||||
* @param state default value of the flag
|
||||
*/
|
||||
public static void addHook(@NotNull String flag, boolean state) {
|
||||
if (canHook) {
|
||||
WorldGuardFlagHandler.addHook(flag, state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if WorldGuard is installed and hooked
|
||||
*
|
||||
* @return true if and only if WorldGuard exists and addHook() has been
|
||||
* called and added successfully
|
||||
*/
|
||||
public static boolean isEnabled() {
|
||||
return canHook && WorldGuardFlagHandler.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks this location to see what this flag is set to
|
||||
*
|
||||
* @param l location to check
|
||||
* @param flag ALLOW/DENY flag to check
|
||||
*
|
||||
* @return flag state, or null if undefined
|
||||
*/
|
||||
@Nullable
|
||||
public static Boolean getBooleanFlag(@NotNull Location l, @NotNull String flag) {
|
||||
return canHook ? WorldGuardFlagHandler.getBooleanFlag(l, flag) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query all regions that are in or intersect this chunk
|
||||
*
|
||||
* @param c chunk to check for regions in
|
||||
* @param flag ALLOW/DENY flag to check
|
||||
*
|
||||
* @return flag state, or null if undefined
|
||||
*/
|
||||
@Nullable
|
||||
public static Boolean getBooleanFlag(@NotNull Chunk c, @NotNull String flag) {
|
||||
return canHook ? WorldGuardFlagHandler.getBooleanFlag(c, flag) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the pvp flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
*
|
||||
* @return false if the pvp flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isPvpAllowed(@NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "pvp"), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the block-break flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
*
|
||||
* @return false if the block-break flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isBreakAllowed(@NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "block-break"), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the build flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
*
|
||||
* @return false if the build flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isBuildAllowed(@NotNull Player player, @NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "build", player), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the use flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
*
|
||||
* @return false if the use flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isInteractAllowed(@NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "use"), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the other-explosion flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
*
|
||||
* @return false if the other-explosion flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isExplosionsAllowed(@NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "other-explosion"), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the mob-spawning flag is set and is set to ALLOW
|
||||
*
|
||||
* @param loc Location to check
|
||||
*
|
||||
* @return false if the mob-spawning flag is not set for this region, or is set to DENY
|
||||
*/
|
||||
public static boolean isMobSpawningAllowed(@NotNull Location loc) {
|
||||
return canHook && Objects.equals(WorldGuardFlagHandler.getBooleanFlag(loc, "mob-spawning"), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param loc Location to check
|
||||
*
|
||||
* @return A list of regions that contain this location.
|
||||
*/
|
||||
@NotNull
|
||||
public static List<String> getRegionNames(@NotNull Location loc) {
|
||||
return canHook ? WorldGuardRegionHandler.getRegionNames(loc) : Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param c Chunk to check
|
||||
*
|
||||
* @return A list of regions that contain any part of this chunk.
|
||||
*/
|
||||
@NotNull
|
||||
public static List<String> getRegionNames(@NotNull Chunk c) {
|
||||
return canHook ? WorldGuardRegionHandler.getRegionNames(c) : Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,13 @@ package com.songoda.core.hooks.economies;
|
||||
import com.songoda.core.hooks.Hook;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public abstract class Economy implements Hook {
|
||||
|
||||
/**
|
||||
* Get the players available balance
|
||||
*
|
||||
* @param player player
|
||||
*
|
||||
* @return the amount of available balance
|
||||
*/
|
||||
public abstract double getBalance(OfflinePlayer player);
|
||||
@ -20,6 +19,7 @@ public abstract class Economy implements Hook {
|
||||
*
|
||||
* @param player player to check
|
||||
* @param cost minimum amount this player should have
|
||||
*
|
||||
* @return true if this player can have this amount withdrawn
|
||||
*/
|
||||
public abstract boolean hasBalance(OfflinePlayer player, double cost);
|
||||
@ -29,6 +29,7 @@ public abstract class Economy implements Hook {
|
||||
*
|
||||
* @param player player to check
|
||||
* @param cost amount to remove from this player
|
||||
*
|
||||
* @return true if the total amount was withdrawn successfully
|
||||
*/
|
||||
public abstract boolean withdrawBalance(OfflinePlayer player, double cost);
|
||||
@ -38,6 +39,7 @@ public abstract class Economy implements Hook {
|
||||
*
|
||||
* @param player player to check
|
||||
* @param amount amount to add to this player
|
||||
*
|
||||
* @return true if the total amount was added successfully
|
||||
*/
|
||||
public abstract boolean deposit(OfflinePlayer player, double amount);
|
||||
|
@ -35,14 +35,12 @@ public class PlayerPointsEconomy extends Economy {
|
||||
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
|
||||
|
@ -31,6 +31,7 @@ public abstract class Holograms implements Hook {
|
||||
* Center and offset this location
|
||||
*
|
||||
* @param location location to offset
|
||||
*
|
||||
* @return copy-safe location with the applied offset.
|
||||
*/
|
||||
protected final Location fixLocation(Location location) {
|
||||
|
@ -2,7 +2,6 @@ package com.songoda.core.hooks.holograms;
|
||||
|
||||
import com.gmail.filoghost.holographicdisplays.api.Hologram;
|
||||
import com.gmail.filoghost.holographicdisplays.api.HologramsAPI;
|
||||
import com.gmail.filoghost.holographicdisplays.api.line.TextLine;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,5 +18,4 @@ public abstract class Protection implements Hook {
|
||||
public abstract boolean canBreak(Player player, Location location);
|
||||
|
||||
public abstract boolean canInteract(Player player, Location location);
|
||||
|
||||
}
|
||||
|
@ -78,5 +78,4 @@ public class StackMob extends Stacker {
|
||||
public int getMinStackSize(EntityType type) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,5 +32,4 @@ public abstract class Stacker implements Hook {
|
||||
public abstract void add(LivingEntity entity, int amount);
|
||||
|
||||
public abstract int getMinStackSize(EntityType type);
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.songoda.core.hooks.stackers;
|
||||
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStack;
|
||||
import com.songoda.ultimatestacker.stackable.entity.EntityStackManager;
|
||||
import com.songoda.ultimatestacker.utils.Methods;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Item;
|
||||
|
@ -75,5 +75,4 @@ public class WildStacker extends Stacker {
|
||||
}
|
||||
return min == -1 ? 0 : min;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,414 +1,413 @@
|
||||
package com.songoda.core.hooks.worldguard;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.BukkitPlayer;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.WorldGuard;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.RegionQuery;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Hooks for adding a custom WorldGuard flag
|
||||
* <p>
|
||||
* Note: Hooks must be added before WG loads!
|
||||
*/
|
||||
public class WorldGuardFlagHandler {
|
||||
|
||||
static boolean wgPlugin;
|
||||
static Object worldGuardPlugin;
|
||||
static boolean wg_v7 = false;
|
||||
static boolean legacy_v60 = false;
|
||||
static boolean legacy_v62 = false;
|
||||
static boolean legacy_v5 = false;
|
||||
static boolean hooksInstalled = false;
|
||||
static Map<String, Object> flags = new HashMap();
|
||||
|
||||
static {
|
||||
if ((wgPlugin = (worldGuardPlugin = Bukkit.getPluginManager().getPlugin("WorldGuard")) != null)) {
|
||||
// a number of flags were introduced in 7.x that aren't in 5 or 6
|
||||
try {
|
||||
// if this class exists, we're on 7.x
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.WeatherTypeFlag");
|
||||
wg_v7 = true;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
try {
|
||||
// if this class exists, we're on 6.2
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry");
|
||||
legacy_v62 = true;
|
||||
} catch (ClassNotFoundException ex2) {
|
||||
try {
|
||||
// if this class exists, we're on 6.0
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.BuildFlag");
|
||||
legacy_v60 = true;
|
||||
} catch (ClassNotFoundException ex3) {
|
||||
try {
|
||||
// if this class exists, we're on 5.x
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag");
|
||||
legacy_v5 = true;
|
||||
} catch (ClassNotFoundException ex4) {
|
||||
// ¯\_(ツ)_/¯
|
||||
wgPlugin = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to register a worldGuard flag (ALLOW/DENY) <br />
|
||||
* Note: This must be called before WorldGuard loads, or it will fail.
|
||||
*
|
||||
* @param flag name of the flag to set
|
||||
* @param state default value of the flag
|
||||
*/
|
||||
public static void addHook(String flag, boolean state) {
|
||||
if (!wgPlugin) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (legacy_v62 || legacy_v60 || legacy_v5) {
|
||||
addLegacyHook(flag, state);
|
||||
return;
|
||||
}
|
||||
|
||||
StateFlag addFlag = new StateFlag(flag, state);
|
||||
try {
|
||||
WorldGuard.getInstance().getFlagRegistry().register(addFlag);
|
||||
flags.put(flag, addFlag);
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add flag {0} to WorldGuard", addFlag.getName());
|
||||
Object wgFlag = WorldGuard.getInstance().getFlagRegistry().get(addFlag.getName());
|
||||
if (wgFlag == null || !(wgFlag instanceof StateFlag)) {
|
||||
wgPlugin = false;
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not hook WorldGuard");
|
||||
} else {
|
||||
flags.put(flag, wgFlag);
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Loaded existing {1} {0}", new Object[]{((Flag) wgFlag).getName(), wgFlag.getClass().getSimpleName()});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reflection to add hooks
|
||||
private static void addLegacyHook(String flag, boolean state) {
|
||||
try {
|
||||
// 6.0 has the same classpath for StateFlag as the current version does
|
||||
// does this flag exist already?
|
||||
Class defaultFlagClazz = Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag");
|
||||
Field flagField = defaultFlagClazz.getField("flagsList");
|
||||
Flag<?>[] flagsOld = (Flag<?>[]) flagField.get(null);
|
||||
Flag wgFlag = Stream.of(flagsOld)
|
||||
.filter(f -> ((Flag<?>) f).getName().equalsIgnoreCase(flag))
|
||||
.findFirst().orElse(null);
|
||||
if (wgFlag != null) {
|
||||
// we already have one
|
||||
flags.put(flag, wgFlag);
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Loaded existing {1} {0}", new Object[]{wgFlag.getName(), wgFlag.getClass().getSimpleName()});
|
||||
return;
|
||||
}
|
||||
|
||||
// if not, we need to add one
|
||||
wgFlag = new StateFlag(flag, state);
|
||||
|
||||
// we need to sneak our flag into the array
|
||||
// make a copy first
|
||||
Flag<?>[] flagsNew = new Flag<?>[flagsOld.length + 1];
|
||||
System.arraycopy(flagsOld, 0, flagsNew, 0, flagsOld.length);
|
||||
|
||||
// add ours
|
||||
flagsNew[flagsNew.length - 1] = wgFlag;
|
||||
|
||||
// and put the new list into place
|
||||
setStaticField(flagField, flagsNew);
|
||||
|
||||
if (legacy_v62) { // SimpleFlagRegistry is NOT in 6.0 or 6.1
|
||||
// register this flag in the registry
|
||||
if (legacy_simpleFlagRegistryClazz == null) {
|
||||
legacy_worldGuardPlugin_flagRegistry = getPrivateField(worldGuardPlugin.getClass(), worldGuardPlugin, "flagRegistry");
|
||||
legacy_simpleFlagRegistryClazz = Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry");
|
||||
legacy_simpleFlagRegistry_get = legacy_simpleFlagRegistryClazz.getDeclaredMethod("get", String.class);
|
||||
}
|
||||
legacy_simpleFlagRegistryClazz.getDeclaredMethod("register", Flag.class).invoke(legacy_worldGuardPlugin_flagRegistry, wgFlag);
|
||||
}
|
||||
|
||||
// all good!
|
||||
flags.put(flag, wgFlag);
|
||||
} catch (Exception ex) {
|
||||
//Bukkit.getServer().getLogger().log(Level.WARNING, "Failed to set legacy WorldGuard Flags", ex);
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add flag {0} to WorldGuard " + (legacy_v62 ? "6.2" : (legacy_v60 ? "6.0" : "5")), flag);
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not hook WorldGuard");
|
||||
wgPlugin = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getPrivateField(Class<?> c, Object handle, String fieldName) throws Exception {
|
||||
Field field = c.getDeclaredField(fieldName);
|
||||
field.setAccessible(true); // This should be okay since it only runs on older versions.
|
||||
return field.get(handle);
|
||||
}
|
||||
|
||||
private static void setStaticField(Field field, Object value) throws Exception {
|
||||
field.setAccessible(true); // This should be okay since it only runs on older versions.
|
||||
Field modifier = Field.class.getDeclaredField("modifiers");
|
||||
modifier.setAccessible(true); // This should be okay since it only runs on older versions.
|
||||
modifier.setInt(field, field.getModifiers() & ~Modifier.FINAL);
|
||||
field.set(null, value);
|
||||
}
|
||||
|
||||
public static boolean isEnabled() {
|
||||
return wgPlugin;
|
||||
}
|
||||
|
||||
public static Object getFlag(String flag) {
|
||||
Object flagObj = flags.get(flag);
|
||||
|
||||
// load a flag if we don't know it
|
||||
if (flagObj == null) {
|
||||
if (wg_v7) {
|
||||
flags.put(flag, flagObj = WorldGuard.getInstance().getFlagRegistry().get(flag));
|
||||
} else if (legacy_v62) {
|
||||
try {
|
||||
if (legacy_simpleFlagRegistryClazz == null) {
|
||||
legacy_worldGuardPlugin_flagRegistry = getPrivateField(worldGuardPlugin.getClass(), worldGuardPlugin, "flagRegistry");
|
||||
legacy_simpleFlagRegistryClazz = Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry");
|
||||
legacy_simpleFlagRegistry_get = legacy_simpleFlagRegistryClazz.getDeclaredMethod("get", String.class);
|
||||
}
|
||||
flags.put(flag, flagObj = legacy_simpleFlagRegistry_get.invoke(legacy_worldGuardPlugin_flagRegistry, flag));
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab flags from WorldGuard", ex);
|
||||
}
|
||||
} else if (!legacy_loadedFlags && (legacy_v60 || legacy_v5)) {
|
||||
try {
|
||||
Class defaultFlagClazz = Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag");
|
||||
Field flagField = defaultFlagClazz.getField("flagsList");
|
||||
Flag<?>[] flagsOld = (Flag<?>[]) flagField.get(null);
|
||||
Stream.of(flagsOld).forEach(f -> flags.put(f.getName(), f));
|
||||
flagObj = flags.get(flag);
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab flags from WorldGuard", ex);
|
||||
}
|
||||
legacy_loadedFlags = true;
|
||||
}
|
||||
}
|
||||
return flagObj;
|
||||
}
|
||||
|
||||
public static Boolean getBooleanFlag(Location loc, String flag) {
|
||||
return getBooleanFlag(loc, flag, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks this location to see what this flag is set to
|
||||
*
|
||||
* @param loc location to check
|
||||
* @param flag ALLOW/DENY flag to check
|
||||
* @return flag state, or null if undefined
|
||||
*/
|
||||
public static Boolean getBooleanFlag(Location loc, String flag, Player optionalPlayer) {
|
||||
if (!wgPlugin) {
|
||||
return null;
|
||||
}
|
||||
|
||||
LocalPlayer player = optionalPlayer != null ? WorldGuardPlugin.inst().wrapPlayer(optionalPlayer) : null;
|
||||
|
||||
Object flagObj = getFlag(flag);
|
||||
|
||||
// There's a different way to get this in the old version
|
||||
if (legacy_v62 || legacy_v60 || legacy_v5) {
|
||||
return flagObj == null ? null : getBooleanFlagLegacy(loc, flagObj);
|
||||
}
|
||||
|
||||
// so, what's up?
|
||||
if (flagObj instanceof StateFlag) {
|
||||
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
|
||||
State result = query.getApplicableRegions(BukkitAdapter.adapt(loc)).queryState(player, (StateFlag) flagObj);
|
||||
return result != null ? result == State.ALLOW : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query all regions that are in or intersect this chunk
|
||||
*
|
||||
* @param c chunk to check for regions in
|
||||
* @param flag ALLOW/DENY flag to check
|
||||
* @return flag state, or null if undefined
|
||||
*/
|
||||
public static Boolean getBooleanFlag(Chunk c, String flag) {
|
||||
if (!wgPlugin) {
|
||||
return null;
|
||||
}
|
||||
Object flagObj = getFlag(flag);
|
||||
// There's a different way to get this in the old version
|
||||
if (legacy_v62 || legacy_v60 || legacy_v5) {
|
||||
return flagObj == null ? null : getBooleanFlagLegacy(c, flagObj);
|
||||
}
|
||||
|
||||
// so, what's up?
|
||||
if (flagObj instanceof StateFlag) {
|
||||
RegionManager worldManager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(c.getWorld()));
|
||||
if (worldManager == null) {
|
||||
return null;
|
||||
}
|
||||
ProtectedCuboidRegion chunkRegion = new ProtectedCuboidRegion("__TEST__",
|
||||
BlockVector3.at(c.getX() << 4, c.getWorld().getMaxHeight(), c.getZ() << 4),
|
||||
BlockVector3.at((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15));
|
||||
ApplicableRegionSet set = worldManager.getApplicableRegions(chunkRegion);
|
||||
State result = set.queryState((RegionAssociable) null, (StateFlag) flagObj);
|
||||
if (result == null && set.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return result == State.ALLOW;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Method legacy_getRegionManager = null;
|
||||
static Method legacy_getApplicableRegions_Region = null;
|
||||
static Method legacy_getApplicableRegions_Location = null;
|
||||
static Method legacy5_applicableRegionSet_getFlag = null;
|
||||
static Constructor legacy_newProtectedCuboidRegion;
|
||||
static Class legacy_blockVectorClazz;
|
||||
static Constructor legacy_newblockVector;
|
||||
static Class legacy_VectorClazz;
|
||||
static Constructor legacy_newVectorClazz;
|
||||
static Method legacy_getApplicableRegions_Vector = null;
|
||||
static Class legacy_simpleFlagRegistryClazz = null; // only used for 6.2
|
||||
static Method legacy_simpleFlagRegistry_get = null; // only used for 6.2
|
||||
static Object legacy_worldGuardPlugin_flagRegistry = null; // only used for 6.2
|
||||
static boolean legacy_loadedFlags = false;
|
||||
|
||||
private static Boolean getBooleanFlagLegacy(Location l, Object flag) {
|
||||
try {
|
||||
// cache reflection methods
|
||||
if (legacy_getRegionManager == null) {
|
||||
legacy_getRegionManager = worldGuardPlugin.getClass()
|
||||
.getDeclaredMethod("getRegionManager", org.bukkit.World.class);
|
||||
legacy_getApplicableRegions_Region = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Class.forName("com.sk89q.worldguard.protection.regions.ProtectedRegion"));
|
||||
legacy_getApplicableRegions_Location = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Location.class);
|
||||
legacy_blockVectorClazz = Class.forName("com.sk89q.worldedit.BlockVector");
|
||||
legacy_newblockVector = legacy_blockVectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_newProtectedCuboidRegion = Class.forName("com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion")
|
||||
.getConstructor(String.class, legacy_blockVectorClazz, legacy_blockVectorClazz);
|
||||
legacy_VectorClazz = Class.forName("com.sk89q.worldedit.Vector");
|
||||
legacy_newVectorClazz = legacy_VectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_getApplicableRegions_Vector = RegionManager.class.getDeclaredMethod("getApplicableRegions", legacy_VectorClazz);
|
||||
}
|
||||
|
||||
// grab the applicable manager for this world
|
||||
Object worldManager = (RegionManager) legacy_getRegionManager.invoke(worldGuardPlugin, l.getWorld());
|
||||
if (worldManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// create a vector object
|
||||
Object vec = legacy_newVectorClazz.newInstance(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||
// now look for any intersecting regions
|
||||
Object set = legacy_getApplicableRegions_Vector.invoke(worldManager, legacy_VectorClazz.cast(vec));
|
||||
|
||||
// so what's the verdict?
|
||||
State result;
|
||||
if (legacy_v62 || legacy_v60) {
|
||||
result = (State) ((ApplicableRegionSet) set).queryState((RegionAssociable) null, (StateFlag) flag);
|
||||
} else {
|
||||
// v5 has a different class signature for ApplicableRegionSet
|
||||
// also doesn't have a "queryState" function
|
||||
//getFlag(T flag)
|
||||
if (legacy5_applicableRegionSet_getFlag == null) {
|
||||
legacy5_applicableRegionSet_getFlag = Class.forName("com.sk89q.worldguard.protection.ApplicableRegionSet").getMethod("getFlag", Flag.class);
|
||||
}
|
||||
result = (State) legacy5_applicableRegionSet_getFlag.invoke(set, flag);
|
||||
}
|
||||
if (result == null && set != null && ((Iterable) set).iterator().hasNext()) {
|
||||
return null;
|
||||
}
|
||||
return result == State.ALLOW;
|
||||
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab flags from WorldGuard", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Boolean getBooleanFlagLegacy(Chunk c, Object flag) {
|
||||
// ApplicableRegionSet and RegionManager have the same classpath as the current version
|
||||
// ProtectedCuboidRegion uses a different constructor, though
|
||||
try {
|
||||
// cache reflection methods
|
||||
if (legacy_getRegionManager == null) {
|
||||
legacy_getRegionManager = worldGuardPlugin.getClass()
|
||||
.getDeclaredMethod("getRegionManager", org.bukkit.World.class);
|
||||
legacy_getApplicableRegions_Region = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Class.forName("com.sk89q.worldguard.protection.regions.ProtectedRegion"));
|
||||
legacy_getApplicableRegions_Location = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Location.class);
|
||||
legacy_blockVectorClazz = Class.forName("com.sk89q.worldedit.BlockVector");
|
||||
legacy_newblockVector = legacy_blockVectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_newProtectedCuboidRegion = Class.forName("com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion")
|
||||
.getConstructor(String.class, legacy_blockVectorClazz, legacy_blockVectorClazz);
|
||||
legacy_VectorClazz = Class.forName("com.sk89q.worldedit.Vector");
|
||||
legacy_newVectorClazz = legacy_VectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_getApplicableRegions_Vector = RegionManager.class.getDeclaredMethod("getApplicableRegions", legacy_VectorClazz);
|
||||
}
|
||||
|
||||
// grab the applicable manager for this world
|
||||
Object worldManager = (RegionManager) legacy_getRegionManager.invoke(worldGuardPlugin, c.getWorld());
|
||||
if (worldManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a legacy ProtectedCuboidRegion
|
||||
Object chunkRegion = legacy_newProtectedCuboidRegion.newInstance("__TEST__",
|
||||
legacy_newblockVector.newInstance(c.getX() << 4, c.getWorld().getMaxHeight(), c.getZ() << 4),
|
||||
legacy_newblockVector.newInstance((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15));
|
||||
|
||||
// now look for any intersecting regions
|
||||
Object set = legacy_getApplicableRegions_Region.invoke(worldManager, chunkRegion);
|
||||
|
||||
// so what's the verdict?
|
||||
State result;
|
||||
if (legacy_v62 || legacy_v60) {
|
||||
result = (State) ((ApplicableRegionSet) set).queryState((RegionAssociable) null, (StateFlag) flag);
|
||||
} else {
|
||||
// v5 has a different class signature for ApplicableRegionSet
|
||||
// also doesn't have a "queryState" function
|
||||
//getFlag(T flag)
|
||||
if (legacy5_applicableRegionSet_getFlag == null) {
|
||||
legacy5_applicableRegionSet_getFlag = Class.forName("com.sk89q.worldguard.protection.ApplicableRegionSet").getMethod("getFlag", Flag.class);
|
||||
}
|
||||
result = (State) legacy5_applicableRegionSet_getFlag.invoke(set, flag);
|
||||
}
|
||||
if (result == null && set != null && ((Iterable) set).iterator().hasNext()) {
|
||||
return null;
|
||||
}
|
||||
return result == State.ALLOW;
|
||||
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab flags from WorldGuard", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
package com.songoda.core.hooks.worldguard;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.WorldGuard;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.RegionQuery;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Hooks for adding a custom WorldGuard flag
|
||||
* <p>
|
||||
* Note: Hooks must be added before WG loads!
|
||||
*/
|
||||
public class WorldGuardFlagHandler {
|
||||
|
||||
static boolean wgPlugin;
|
||||
static Object worldGuardPlugin;
|
||||
static boolean wg_v7 = false;
|
||||
static boolean legacy_v60 = false;
|
||||
static boolean legacy_v62 = false;
|
||||
static boolean legacy_v5 = false;
|
||||
static boolean hooksInstalled = false;
|
||||
static Map<String, Object> flags = new HashMap();
|
||||
|
||||
static {
|
||||
if ((wgPlugin = (worldGuardPlugin = Bukkit.getPluginManager().getPlugin("WorldGuard")) != null)) {
|
||||
// a number of flags were introduced in 7.x that aren't in 5 or 6
|
||||
try {
|
||||
// if this class exists, we're on 7.x
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.WeatherTypeFlag");
|
||||
wg_v7 = true;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
try {
|
||||
// if this class exists, we're on 6.2
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry");
|
||||
legacy_v62 = true;
|
||||
} catch (ClassNotFoundException ex2) {
|
||||
try {
|
||||
// if this class exists, we're on 6.0
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.BuildFlag");
|
||||
legacy_v60 = true;
|
||||
} catch (ClassNotFoundException ex3) {
|
||||
try {
|
||||
// if this class exists, we're on 5.x
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag");
|
||||
legacy_v5 = true;
|
||||
} catch (ClassNotFoundException ex4) {
|
||||
// ¯\_(ツ)_/¯
|
||||
wgPlugin = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to register a worldGuard flag (ALLOW/DENY) <br />
|
||||
* Note: This must be called before WorldGuard loads, or it will fail.
|
||||
*
|
||||
* @param flag name of the flag to set
|
||||
* @param state default value of the flag
|
||||
*/
|
||||
public static void addHook(String flag, boolean state) {
|
||||
if (!wgPlugin) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (legacy_v62 || legacy_v60 || legacy_v5) {
|
||||
addLegacyHook(flag, state);
|
||||
return;
|
||||
}
|
||||
|
||||
StateFlag addFlag = new StateFlag(flag, state);
|
||||
try {
|
||||
WorldGuard.getInstance().getFlagRegistry().register(addFlag);
|
||||
flags.put(flag, addFlag);
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add flag {0} to WorldGuard", addFlag.getName());
|
||||
Object wgFlag = WorldGuard.getInstance().getFlagRegistry().get(addFlag.getName());
|
||||
if (wgFlag == null || !(wgFlag instanceof StateFlag)) {
|
||||
wgPlugin = false;
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not hook WorldGuard");
|
||||
} else {
|
||||
flags.put(flag, wgFlag);
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Loaded existing {1} {0}", new Object[] {((Flag) wgFlag).getName(), wgFlag.getClass().getSimpleName()});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reflection to add hooks
|
||||
private static void addLegacyHook(String flag, boolean state) {
|
||||
try {
|
||||
// 6.0 has the same classpath for StateFlag as the current version does
|
||||
// does this flag exist already?
|
||||
Class defaultFlagClazz = Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag");
|
||||
Field flagField = defaultFlagClazz.getField("flagsList");
|
||||
Flag<?>[] flagsOld = (Flag<?>[]) flagField.get(null);
|
||||
Flag wgFlag = Stream.of(flagsOld)
|
||||
.filter(f -> ((Flag<?>) f).getName().equalsIgnoreCase(flag))
|
||||
.findFirst().orElse(null);
|
||||
if (wgFlag != null) {
|
||||
// we already have one
|
||||
flags.put(flag, wgFlag);
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Loaded existing {1} {0}", new Object[] {wgFlag.getName(), wgFlag.getClass().getSimpleName()});
|
||||
return;
|
||||
}
|
||||
|
||||
// if not, we need to add one
|
||||
wgFlag = new StateFlag(flag, state);
|
||||
|
||||
// we need to sneak our flag into the array
|
||||
// make a copy first
|
||||
Flag<?>[] flagsNew = new Flag<?>[flagsOld.length + 1];
|
||||
System.arraycopy(flagsOld, 0, flagsNew, 0, flagsOld.length);
|
||||
|
||||
// add ours
|
||||
flagsNew[flagsNew.length - 1] = wgFlag;
|
||||
|
||||
// and put the new list into place
|
||||
setStaticField(flagField, flagsNew);
|
||||
|
||||
if (legacy_v62) { // SimpleFlagRegistry is NOT in 6.0 or 6.1
|
||||
// register this flag in the registry
|
||||
if (legacy_simpleFlagRegistryClazz == null) {
|
||||
legacy_worldGuardPlugin_flagRegistry = getPrivateField(worldGuardPlugin.getClass(), worldGuardPlugin, "flagRegistry");
|
||||
legacy_simpleFlagRegistryClazz = Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry");
|
||||
legacy_simpleFlagRegistry_get = legacy_simpleFlagRegistryClazz.getDeclaredMethod("get", String.class);
|
||||
}
|
||||
legacy_simpleFlagRegistryClazz.getDeclaredMethod("register", Flag.class).invoke(legacy_worldGuardPlugin_flagRegistry, wgFlag);
|
||||
}
|
||||
|
||||
// all good!
|
||||
flags.put(flag, wgFlag);
|
||||
} catch (Exception ex) {
|
||||
//Bukkit.getServer().getLogger().log(Level.WARNING, "Failed to set legacy WorldGuard Flags", ex);
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not add flag {0} to WorldGuard " + (legacy_v62 ? "6.2" : (legacy_v60 ? "6.0" : "5")), flag);
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not hook WorldGuard");
|
||||
wgPlugin = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getPrivateField(Class<?> c, Object handle, String fieldName) throws Exception {
|
||||
Field field = c.getDeclaredField(fieldName);
|
||||
field.setAccessible(true); // This should be okay since it only runs on older versions.
|
||||
return field.get(handle);
|
||||
}
|
||||
|
||||
private static void setStaticField(Field field, Object value) throws Exception {
|
||||
field.setAccessible(true); // This should be okay since it only runs on older versions.
|
||||
Field modifier = Field.class.getDeclaredField("modifiers");
|
||||
modifier.setAccessible(true); // This should be okay since it only runs on older versions.
|
||||
modifier.setInt(field, field.getModifiers() & ~Modifier.FINAL);
|
||||
field.set(null, value);
|
||||
}
|
||||
|
||||
public static boolean isEnabled() {
|
||||
return wgPlugin;
|
||||
}
|
||||
|
||||
public static Object getFlag(String flag) {
|
||||
Object flagObj = flags.get(flag);
|
||||
|
||||
// load a flag if we don't know it
|
||||
if (flagObj == null) {
|
||||
if (wg_v7) {
|
||||
flags.put(flag, flagObj = WorldGuard.getInstance().getFlagRegistry().get(flag));
|
||||
} else if (legacy_v62) {
|
||||
try {
|
||||
if (legacy_simpleFlagRegistryClazz == null) {
|
||||
legacy_worldGuardPlugin_flagRegistry = getPrivateField(worldGuardPlugin.getClass(), worldGuardPlugin, "flagRegistry");
|
||||
legacy_simpleFlagRegistryClazz = Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry");
|
||||
legacy_simpleFlagRegistry_get = legacy_simpleFlagRegistryClazz.getDeclaredMethod("get", String.class);
|
||||
}
|
||||
flags.put(flag, flagObj = legacy_simpleFlagRegistry_get.invoke(legacy_worldGuardPlugin_flagRegistry, flag));
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab flags from WorldGuard", ex);
|
||||
}
|
||||
} else if (!legacy_loadedFlags && (legacy_v60 || legacy_v5)) {
|
||||
try {
|
||||
Class defaultFlagClazz = Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag");
|
||||
Field flagField = defaultFlagClazz.getField("flagsList");
|
||||
Flag<?>[] flagsOld = (Flag<?>[]) flagField.get(null);
|
||||
Stream.of(flagsOld).forEach(f -> flags.put(f.getName(), f));
|
||||
flagObj = flags.get(flag);
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab flags from WorldGuard", ex);
|
||||
}
|
||||
legacy_loadedFlags = true;
|
||||
}
|
||||
}
|
||||
return flagObj;
|
||||
}
|
||||
|
||||
public static Boolean getBooleanFlag(Location loc, String flag) {
|
||||
return getBooleanFlag(loc, flag, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks this location to see what this flag is set to
|
||||
*
|
||||
* @param loc location to check
|
||||
* @param flag ALLOW/DENY flag to check
|
||||
*
|
||||
* @return flag state, or null if undefined
|
||||
*/
|
||||
public static Boolean getBooleanFlag(Location loc, String flag, Player optionalPlayer) {
|
||||
if (!wgPlugin) {
|
||||
return null;
|
||||
}
|
||||
|
||||
LocalPlayer player = optionalPlayer != null ? WorldGuardPlugin.inst().wrapPlayer(optionalPlayer) : null;
|
||||
|
||||
Object flagObj = getFlag(flag);
|
||||
|
||||
// There's a different way to get this in the old version
|
||||
if (legacy_v62 || legacy_v60 || legacy_v5) {
|
||||
return flagObj == null ? null : getBooleanFlagLegacy(loc, flagObj);
|
||||
}
|
||||
|
||||
// so, what's up?
|
||||
if (flagObj instanceof StateFlag) {
|
||||
RegionQuery query = WorldGuard.getInstance().getPlatform().getRegionContainer().createQuery();
|
||||
State result = query.getApplicableRegions(BukkitAdapter.adapt(loc)).queryState(player, (StateFlag) flagObj);
|
||||
return result != null ? result == State.ALLOW : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query all regions that are in or intersect this chunk
|
||||
*
|
||||
* @param c chunk to check for regions in
|
||||
* @param flag ALLOW/DENY flag to check
|
||||
*
|
||||
* @return flag state, or null if undefined
|
||||
*/
|
||||
public static Boolean getBooleanFlag(Chunk c, String flag) {
|
||||
if (!wgPlugin) {
|
||||
return null;
|
||||
}
|
||||
Object flagObj = getFlag(flag);
|
||||
// There's a different way to get this in the old version
|
||||
if (legacy_v62 || legacy_v60 || legacy_v5) {
|
||||
return flagObj == null ? null : getBooleanFlagLegacy(c, flagObj);
|
||||
}
|
||||
|
||||
// so, what's up?
|
||||
if (flagObj instanceof StateFlag) {
|
||||
RegionManager worldManager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(c.getWorld()));
|
||||
if (worldManager == null) {
|
||||
return null;
|
||||
}
|
||||
ProtectedCuboidRegion chunkRegion = new ProtectedCuboidRegion("__TEST__",
|
||||
BlockVector3.at(c.getX() << 4, c.getWorld().getMaxHeight(), c.getZ() << 4),
|
||||
BlockVector3.at((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15));
|
||||
ApplicableRegionSet set = worldManager.getApplicableRegions(chunkRegion);
|
||||
State result = set.queryState((RegionAssociable) null, (StateFlag) flagObj);
|
||||
if (result == null && set.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return result == State.ALLOW;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Method legacy_getRegionManager = null;
|
||||
static Method legacy_getApplicableRegions_Region = null;
|
||||
static Method legacy_getApplicableRegions_Location = null;
|
||||
static Method legacy5_applicableRegionSet_getFlag = null;
|
||||
static Constructor legacy_newProtectedCuboidRegion;
|
||||
static Class legacy_blockVectorClazz;
|
||||
static Constructor legacy_newblockVector;
|
||||
static Class legacy_VectorClazz;
|
||||
static Constructor legacy_newVectorClazz;
|
||||
static Method legacy_getApplicableRegions_Vector = null;
|
||||
static Class legacy_simpleFlagRegistryClazz = null; // only used for 6.2
|
||||
static Method legacy_simpleFlagRegistry_get = null; // only used for 6.2
|
||||
static Object legacy_worldGuardPlugin_flagRegistry = null; // only used for 6.2
|
||||
static boolean legacy_loadedFlags = false;
|
||||
|
||||
private static Boolean getBooleanFlagLegacy(Location l, Object flag) {
|
||||
try {
|
||||
// cache reflection methods
|
||||
if (legacy_getRegionManager == null) {
|
||||
legacy_getRegionManager = worldGuardPlugin.getClass()
|
||||
.getDeclaredMethod("getRegionManager", org.bukkit.World.class);
|
||||
legacy_getApplicableRegions_Region = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Class.forName("com.sk89q.worldguard.protection.regions.ProtectedRegion"));
|
||||
legacy_getApplicableRegions_Location = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Location.class);
|
||||
legacy_blockVectorClazz = Class.forName("com.sk89q.worldedit.BlockVector");
|
||||
legacy_newblockVector = legacy_blockVectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_newProtectedCuboidRegion = Class.forName("com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion")
|
||||
.getConstructor(String.class, legacy_blockVectorClazz, legacy_blockVectorClazz);
|
||||
legacy_VectorClazz = Class.forName("com.sk89q.worldedit.Vector");
|
||||
legacy_newVectorClazz = legacy_VectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_getApplicableRegions_Vector = RegionManager.class.getDeclaredMethod("getApplicableRegions", legacy_VectorClazz);
|
||||
}
|
||||
|
||||
// grab the applicable manager for this world
|
||||
Object worldManager = (RegionManager) legacy_getRegionManager.invoke(worldGuardPlugin, l.getWorld());
|
||||
if (worldManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// create a vector object
|
||||
Object vec = legacy_newVectorClazz.newInstance(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||
// now look for any intersecting regions
|
||||
Object set = legacy_getApplicableRegions_Vector.invoke(worldManager, legacy_VectorClazz.cast(vec));
|
||||
|
||||
// so what's the verdict?
|
||||
State result;
|
||||
if (legacy_v62 || legacy_v60) {
|
||||
result = (State) ((ApplicableRegionSet) set).queryState((RegionAssociable) null, (StateFlag) flag);
|
||||
} else {
|
||||
// v5 has a different class signature for ApplicableRegionSet
|
||||
// also doesn't have a "queryState" function
|
||||
//getFlag(T flag)
|
||||
if (legacy5_applicableRegionSet_getFlag == null) {
|
||||
legacy5_applicableRegionSet_getFlag = Class.forName("com.sk89q.worldguard.protection.ApplicableRegionSet").getMethod("getFlag", Flag.class);
|
||||
}
|
||||
result = (State) legacy5_applicableRegionSet_getFlag.invoke(set, flag);
|
||||
}
|
||||
if (result == null && set != null && ((Iterable) set).iterator().hasNext()) {
|
||||
return null;
|
||||
}
|
||||
return result == State.ALLOW;
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab flags from WorldGuard", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Boolean getBooleanFlagLegacy(Chunk c, Object flag) {
|
||||
// ApplicableRegionSet and RegionManager have the same classpath as the current version
|
||||
// ProtectedCuboidRegion uses a different constructor, though
|
||||
try {
|
||||
// cache reflection methods
|
||||
if (legacy_getRegionManager == null) {
|
||||
legacy_getRegionManager = worldGuardPlugin.getClass()
|
||||
.getDeclaredMethod("getRegionManager", org.bukkit.World.class);
|
||||
legacy_getApplicableRegions_Region = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Class.forName("com.sk89q.worldguard.protection.regions.ProtectedRegion"));
|
||||
legacy_getApplicableRegions_Location = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Location.class);
|
||||
legacy_blockVectorClazz = Class.forName("com.sk89q.worldedit.BlockVector");
|
||||
legacy_newblockVector = legacy_blockVectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_newProtectedCuboidRegion = Class.forName("com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion")
|
||||
.getConstructor(String.class, legacy_blockVectorClazz, legacy_blockVectorClazz);
|
||||
legacy_VectorClazz = Class.forName("com.sk89q.worldedit.Vector");
|
||||
legacy_newVectorClazz = legacy_VectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_getApplicableRegions_Vector = RegionManager.class.getDeclaredMethod("getApplicableRegions", legacy_VectorClazz);
|
||||
}
|
||||
|
||||
// grab the applicable manager for this world
|
||||
Object worldManager = (RegionManager) legacy_getRegionManager.invoke(worldGuardPlugin, c.getWorld());
|
||||
if (worldManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a legacy ProtectedCuboidRegion
|
||||
Object chunkRegion = legacy_newProtectedCuboidRegion.newInstance("__TEST__",
|
||||
legacy_newblockVector.newInstance(c.getX() << 4, c.getWorld().getMaxHeight(), c.getZ() << 4),
|
||||
legacy_newblockVector.newInstance((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15));
|
||||
|
||||
// now look for any intersecting regions
|
||||
Object set = legacy_getApplicableRegions_Region.invoke(worldManager, chunkRegion);
|
||||
|
||||
// so what's the verdict?
|
||||
State result;
|
||||
if (legacy_v62 || legacy_v60) {
|
||||
result = (State) ((ApplicableRegionSet) set).queryState((RegionAssociable) null, (StateFlag) flag);
|
||||
} else {
|
||||
// v5 has a different class signature for ApplicableRegionSet
|
||||
// also doesn't have a "queryState" function
|
||||
//getFlag(T flag)
|
||||
if (legacy5_applicableRegionSet_getFlag == null) {
|
||||
legacy5_applicableRegionSet_getFlag = Class.forName("com.sk89q.worldguard.protection.ApplicableRegionSet").getMethod("getFlag", Flag.class);
|
||||
}
|
||||
result = (State) legacy5_applicableRegionSet_getFlag.invoke(set, flag);
|
||||
}
|
||||
if (result == null && set != null && ((Iterable) set).iterator().hasNext()) {
|
||||
return null;
|
||||
}
|
||||
return result == State.ALLOW;
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab flags from WorldGuard", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,249 +1,248 @@
|
||||
package com.songoda.core.hooks.worldguard;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldguard.WorldGuard;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class WorldGuardRegionHandler {
|
||||
|
||||
static boolean wgPlugin;
|
||||
static Object worldGuardPlugin;
|
||||
static boolean wg_v7 = false;
|
||||
static boolean legacy_v60 = false;
|
||||
static boolean legacy_v62 = false;
|
||||
static boolean legacy_v5 = false;
|
||||
static Method legacy_getRegionManager = null;
|
||||
static Method legacy_getApplicableRegions_Region = null;
|
||||
static Method legacy_getApplicableRegions_Location = null;
|
||||
static Constructor legacy_newProtectedCuboidRegion;
|
||||
static Class legacy_blockVectorClazz;
|
||||
static Constructor legacy_newblockVector;
|
||||
static Class legacy_VectorClazz;
|
||||
static Constructor legacy_newVectorClazz;
|
||||
static Method legacy_getApplicableRegions_Vector = null;
|
||||
|
||||
static void init() {
|
||||
if ((wgPlugin = (worldGuardPlugin = Bukkit.getPluginManager().getPlugin("WorldGuard")) != null)) {
|
||||
// a number of flags were introduced in 7.x that aren't in 5 or 6
|
||||
try {
|
||||
// if this class exists, we're on 7.x
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.WeatherTypeFlag");
|
||||
wg_v7 = true;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
try {
|
||||
// if this class exists, we're on 6.2
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry");
|
||||
legacy_v62 = true;
|
||||
} catch (ClassNotFoundException ex2) {
|
||||
try {
|
||||
// if this class exists, we're on 6.0
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.BuildFlag");
|
||||
legacy_v60 = true;
|
||||
} catch (ClassNotFoundException ex3) {
|
||||
try {
|
||||
// if this class exists, we're on 5.x
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag");
|
||||
legacy_v5 = true;
|
||||
} catch (ClassNotFoundException ex4) {
|
||||
// ¯\_(ツ)_/¯
|
||||
wgPlugin = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wgPlugin && (legacy_v62 || legacy_v60 || legacy_v5)) {
|
||||
try {
|
||||
// cache reflection methods
|
||||
if (legacy_getRegionManager == null) {
|
||||
legacy_getRegionManager = worldGuardPlugin.getClass()
|
||||
.getDeclaredMethod("getRegionManager", org.bukkit.World.class);
|
||||
legacy_getApplicableRegions_Region = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Class.forName("com.sk89q.worldguard.protection.regions.ProtectedRegion"));
|
||||
legacy_getApplicableRegions_Location = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Location.class);
|
||||
legacy_blockVectorClazz = Class.forName("com.sk89q.worldedit.BlockVector");
|
||||
legacy_newblockVector = legacy_blockVectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_newProtectedCuboidRegion = Class.forName("com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion")
|
||||
.getConstructor(String.class, legacy_blockVectorClazz, legacy_blockVectorClazz);
|
||||
legacy_VectorClazz = Class.forName("com.sk89q.worldedit.Vector");
|
||||
legacy_newVectorClazz = legacy_VectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_getApplicableRegions_Vector = RegionManager.class.getDeclaredMethod("getApplicableRegions", legacy_VectorClazz);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
//Bukkit.getServer().getLogger().log(Level.WARNING, "Failed to set legacy WorldGuard Flags", ex);
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not load WorldGuard methods for " + (legacy_v62 ? "6.2" : (legacy_v60 ? "6.0" : "5")));
|
||||
wgPlugin = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getRegionNames(Chunk c) {
|
||||
if (worldGuardPlugin == null) {
|
||||
init();
|
||||
}
|
||||
if (!wgPlugin || c == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
} else if (legacy_v62 || legacy_v60 || legacy_v5) {
|
||||
return getRegionNamesLegacy(c);
|
||||
}
|
||||
|
||||
RegionManager worldManager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(c.getWorld()));
|
||||
if (worldManager == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
ProtectedCuboidRegion chunkRegion = new ProtectedCuboidRegion("__TEST__",
|
||||
BlockVector3.at(c.getX() << 4, c.getWorld().getMaxHeight(), c.getZ() << 4),
|
||||
BlockVector3.at((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15));
|
||||
ApplicableRegionSet set = worldManager.getApplicableRegions(chunkRegion);
|
||||
|
||||
List<String> regions = new ArrayList<>();
|
||||
List<String> parentNames = new ArrayList<>();
|
||||
|
||||
for (ProtectedRegion region : set) {
|
||||
String id = region.getId();
|
||||
|
||||
regions.add(id);
|
||||
|
||||
ProtectedRegion parent = region.getParent();
|
||||
|
||||
while (parent != null) {
|
||||
parentNames.add(parent.getId());
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
regions.removeAll(parentNames);
|
||||
|
||||
return regions;
|
||||
}
|
||||
|
||||
private static List<String> getRegionNamesLegacy(Chunk c) {
|
||||
try {
|
||||
// grab the applicable manager for this world
|
||||
Object worldManager = (RegionManager) legacy_getRegionManager.invoke(worldGuardPlugin, c.getWorld());
|
||||
if (worldManager == null) {
|
||||
return null;
|
||||
}
|
||||
// Create a legacy ProtectedCuboidRegion
|
||||
Object chunkRegion = legacy_newProtectedCuboidRegion.newInstance("__TEST__",
|
||||
legacy_newblockVector.newInstance(c.getX() << 4, c.getWorld().getMaxHeight(), c.getZ() << 4),
|
||||
legacy_newblockVector.newInstance((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15));
|
||||
|
||||
// now look for any intersecting regions
|
||||
// ApplicableRegionSet's prototype is different from v5 to v6, but they're both Iterable
|
||||
Iterable<ProtectedRegion> set = (Iterable<ProtectedRegion>) legacy_getApplicableRegions_Region.invoke(worldManager, chunkRegion);
|
||||
|
||||
List<String> regions = new ArrayList<>();
|
||||
List<String> parentNames = new ArrayList<>();
|
||||
|
||||
for (ProtectedRegion region : set) {
|
||||
String id = region.getId();
|
||||
|
||||
regions.add(id);
|
||||
|
||||
ProtectedRegion parent = region.getParent();
|
||||
|
||||
while (parent != null) {
|
||||
parentNames.add(parent.getId());
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
regions.removeAll(parentNames);
|
||||
|
||||
return regions;
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab regions from WorldGuard", ex);
|
||||
}
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
public static List<String> getRegionNames(Location loc) {
|
||||
if (worldGuardPlugin == null) {
|
||||
init();
|
||||
}
|
||||
if (!wgPlugin || loc == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
} else if (legacy_v62 || legacy_v60 || legacy_v5) {
|
||||
return getRegionNamesLegacy(loc);
|
||||
}
|
||||
|
||||
RegionManager regionManager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(loc.getWorld()));
|
||||
|
||||
if (regionManager == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
List<String> regions = new ArrayList<>();
|
||||
List<String> parentNames = new ArrayList<>();
|
||||
ApplicableRegionSet set = regionManager.getApplicableRegions(BukkitAdapter.asBlockVector(loc));
|
||||
|
||||
for (ProtectedRegion region : set) {
|
||||
String id = region.getId();
|
||||
|
||||
regions.add(id);
|
||||
|
||||
ProtectedRegion parent = region.getParent();
|
||||
|
||||
while (parent != null) {
|
||||
parentNames.add(parent.getId());
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
regions.removeAll(parentNames);
|
||||
|
||||
return regions;
|
||||
|
||||
}
|
||||
|
||||
private static List<String> getRegionNamesLegacy(Location loc) {
|
||||
try {
|
||||
// grab the applicable manager for this world
|
||||
Object worldManager = (RegionManager) legacy_getRegionManager.invoke(worldGuardPlugin, loc.getWorld());
|
||||
if (worldManager == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
// create a vector object
|
||||
Object vec = legacy_newVectorClazz.newInstance(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
// now look for any intersecting regions
|
||||
// ApplicableRegionSet's prototype is different from v5 to v6, but they're both Iterable
|
||||
Iterable<ProtectedRegion> set = (Iterable<ProtectedRegion>) legacy_getApplicableRegions_Vector.invoke(worldManager, legacy_VectorClazz.cast(vec));
|
||||
|
||||
List<String> regions = new ArrayList<>();
|
||||
List<String> parentNames = new ArrayList<>();
|
||||
|
||||
for (ProtectedRegion region : set) {
|
||||
String id = region.getId();
|
||||
|
||||
regions.add(id);
|
||||
|
||||
ProtectedRegion parent = region.getParent();
|
||||
|
||||
while (parent != null) {
|
||||
parentNames.add(parent.getId());
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
regions.removeAll(parentNames);
|
||||
|
||||
return regions;
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab regions from WorldGuard", ex);
|
||||
}
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
package com.songoda.core.hooks.worldguard;
|
||||
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldguard.WorldGuard;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class WorldGuardRegionHandler {
|
||||
|
||||
static boolean wgPlugin;
|
||||
static Object worldGuardPlugin;
|
||||
static boolean wg_v7 = false;
|
||||
static boolean legacy_v60 = false;
|
||||
static boolean legacy_v62 = false;
|
||||
static boolean legacy_v5 = false;
|
||||
static Method legacy_getRegionManager = null;
|
||||
static Method legacy_getApplicableRegions_Region = null;
|
||||
static Method legacy_getApplicableRegions_Location = null;
|
||||
static Constructor legacy_newProtectedCuboidRegion;
|
||||
static Class legacy_blockVectorClazz;
|
||||
static Constructor legacy_newblockVector;
|
||||
static Class legacy_VectorClazz;
|
||||
static Constructor legacy_newVectorClazz;
|
||||
static Method legacy_getApplicableRegions_Vector = null;
|
||||
|
||||
static void init() {
|
||||
if ((wgPlugin = (worldGuardPlugin = Bukkit.getPluginManager().getPlugin("WorldGuard")) != null)) {
|
||||
// a number of flags were introduced in 7.x that aren't in 5 or 6
|
||||
try {
|
||||
// if this class exists, we're on 7.x
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.WeatherTypeFlag");
|
||||
wg_v7 = true;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
try {
|
||||
// if this class exists, we're on 6.2
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry");
|
||||
legacy_v62 = true;
|
||||
} catch (ClassNotFoundException ex2) {
|
||||
try {
|
||||
// if this class exists, we're on 6.0
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.BuildFlag");
|
||||
legacy_v60 = true;
|
||||
} catch (ClassNotFoundException ex3) {
|
||||
try {
|
||||
// if this class exists, we're on 5.x
|
||||
Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag");
|
||||
legacy_v5 = true;
|
||||
} catch (ClassNotFoundException ex4) {
|
||||
// ¯\_(ツ)_/¯
|
||||
wgPlugin = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wgPlugin && (legacy_v62 || legacy_v60 || legacy_v5)) {
|
||||
try {
|
||||
// cache reflection methods
|
||||
if (legacy_getRegionManager == null) {
|
||||
legacy_getRegionManager = worldGuardPlugin.getClass()
|
||||
.getDeclaredMethod("getRegionManager", org.bukkit.World.class);
|
||||
legacy_getApplicableRegions_Region = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Class.forName("com.sk89q.worldguard.protection.regions.ProtectedRegion"));
|
||||
legacy_getApplicableRegions_Location = RegionManager.class.getDeclaredMethod("getApplicableRegions",
|
||||
Location.class);
|
||||
legacy_blockVectorClazz = Class.forName("com.sk89q.worldedit.BlockVector");
|
||||
legacy_newblockVector = legacy_blockVectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_newProtectedCuboidRegion = Class.forName("com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion")
|
||||
.getConstructor(String.class, legacy_blockVectorClazz, legacy_blockVectorClazz);
|
||||
legacy_VectorClazz = Class.forName("com.sk89q.worldedit.Vector");
|
||||
legacy_newVectorClazz = legacy_VectorClazz.getConstructor(int.class, int.class, int.class);
|
||||
legacy_getApplicableRegions_Vector = RegionManager.class.getDeclaredMethod("getApplicableRegions", legacy_VectorClazz);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
//Bukkit.getServer().getLogger().log(Level.WARNING, "Failed to set legacy WorldGuard Flags", ex);
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not load WorldGuard methods for " + (legacy_v62 ? "6.2" : (legacy_v60 ? "6.0" : "5")));
|
||||
wgPlugin = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getRegionNames(Chunk c) {
|
||||
if (worldGuardPlugin == null) {
|
||||
init();
|
||||
}
|
||||
if (!wgPlugin || c == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
} else if (legacy_v62 || legacy_v60 || legacy_v5) {
|
||||
return getRegionNamesLegacy(c);
|
||||
}
|
||||
|
||||
RegionManager worldManager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(c.getWorld()));
|
||||
if (worldManager == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
ProtectedCuboidRegion chunkRegion = new ProtectedCuboidRegion("__TEST__",
|
||||
BlockVector3.at(c.getX() << 4, c.getWorld().getMaxHeight(), c.getZ() << 4),
|
||||
BlockVector3.at((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15));
|
||||
ApplicableRegionSet set = worldManager.getApplicableRegions(chunkRegion);
|
||||
|
||||
List<String> regions = new ArrayList<>();
|
||||
List<String> parentNames = new ArrayList<>();
|
||||
|
||||
for (ProtectedRegion region : set) {
|
||||
String id = region.getId();
|
||||
|
||||
regions.add(id);
|
||||
|
||||
ProtectedRegion parent = region.getParent();
|
||||
|
||||
while (parent != null) {
|
||||
parentNames.add(parent.getId());
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
regions.removeAll(parentNames);
|
||||
|
||||
return regions;
|
||||
}
|
||||
|
||||
private static List<String> getRegionNamesLegacy(Chunk c) {
|
||||
try {
|
||||
// grab the applicable manager for this world
|
||||
Object worldManager = (RegionManager) legacy_getRegionManager.invoke(worldGuardPlugin, c.getWorld());
|
||||
if (worldManager == null) {
|
||||
return null;
|
||||
}
|
||||
// Create a legacy ProtectedCuboidRegion
|
||||
Object chunkRegion = legacy_newProtectedCuboidRegion.newInstance("__TEST__",
|
||||
legacy_newblockVector.newInstance(c.getX() << 4, c.getWorld().getMaxHeight(), c.getZ() << 4),
|
||||
legacy_newblockVector.newInstance((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15));
|
||||
|
||||
// now look for any intersecting regions
|
||||
// ApplicableRegionSet's prototype is different from v5 to v6, but they're both Iterable
|
||||
Iterable<ProtectedRegion> set = (Iterable<ProtectedRegion>) legacy_getApplicableRegions_Region.invoke(worldManager, chunkRegion);
|
||||
|
||||
List<String> regions = new ArrayList<>();
|
||||
List<String> parentNames = new ArrayList<>();
|
||||
|
||||
for (ProtectedRegion region : set) {
|
||||
String id = region.getId();
|
||||
|
||||
regions.add(id);
|
||||
|
||||
ProtectedRegion parent = region.getParent();
|
||||
|
||||
while (parent != null) {
|
||||
parentNames.add(parent.getId());
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
regions.removeAll(parentNames);
|
||||
|
||||
return regions;
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab regions from WorldGuard", ex);
|
||||
}
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
public static List<String> getRegionNames(Location loc) {
|
||||
if (worldGuardPlugin == null) {
|
||||
init();
|
||||
}
|
||||
if (!wgPlugin || loc == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
} else if (legacy_v62 || legacy_v60 || legacy_v5) {
|
||||
return getRegionNamesLegacy(loc);
|
||||
}
|
||||
|
||||
RegionManager regionManager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(BukkitAdapter.adapt(loc.getWorld()));
|
||||
|
||||
if (regionManager == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
List<String> regions = new ArrayList<>();
|
||||
List<String> parentNames = new ArrayList<>();
|
||||
ApplicableRegionSet set = regionManager.getApplicableRegions(BukkitAdapter.asBlockVector(loc));
|
||||
|
||||
for (ProtectedRegion region : set) {
|
||||
String id = region.getId();
|
||||
|
||||
regions.add(id);
|
||||
|
||||
ProtectedRegion parent = region.getParent();
|
||||
|
||||
while (parent != null) {
|
||||
parentNames.add(parent.getId());
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
regions.removeAll(parentNames);
|
||||
|
||||
return regions;
|
||||
}
|
||||
|
||||
private static List<String> getRegionNamesLegacy(Location loc) {
|
||||
try {
|
||||
// grab the applicable manager for this world
|
||||
Object worldManager = (RegionManager) legacy_getRegionManager.invoke(worldGuardPlugin, loc.getWorld());
|
||||
if (worldManager == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
// create a vector object
|
||||
Object vec = legacy_newVectorClazz.newInstance(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||
// now look for any intersecting regions
|
||||
// ApplicableRegionSet's prototype is different from v5 to v6, but they're both Iterable
|
||||
Iterable<ProtectedRegion> set = (Iterable<ProtectedRegion>) legacy_getApplicableRegions_Vector.invoke(worldManager, legacy_VectorClazz.cast(vec));
|
||||
|
||||
List<String> regions = new ArrayList<>();
|
||||
List<String> parentNames = new ArrayList<>();
|
||||
|
||||
for (ProtectedRegion region : set) {
|
||||
String id = region.getId();
|
||||
|
||||
regions.add(id);
|
||||
|
||||
ProtectedRegion parent = region.getParent();
|
||||
|
||||
while (parent != null) {
|
||||
parentNames.add(parent.getId());
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
regions.removeAll(parentNames);
|
||||
|
||||
return regions;
|
||||
} catch (Exception ex) {
|
||||
Bukkit.getServer().getLogger().log(Level.WARNING, "Could not grab regions from WorldGuard", ex);
|
||||
}
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
|
@ -157,5 +157,4 @@ public class ChatPrompt implements Listener {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,16 @@ import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
@ -55,6 +64,7 @@ public class Locale {
|
||||
*
|
||||
* @param plugin plugin to load from
|
||||
* @param name name of the default locale, eg "en_US"
|
||||
*
|
||||
* @return returns the loaded Locale, or null if there was an error
|
||||
*/
|
||||
public static Locale loadDefaultLocale(JavaPlugin plugin, String name) {
|
||||
@ -67,6 +77,7 @@ public class Locale {
|
||||
*
|
||||
* @param plugin plugin to load from
|
||||
* @param name name of the locale, eg "en_US"
|
||||
*
|
||||
* @return returns the loaded Locale, or null if there was an error
|
||||
*/
|
||||
public static Locale loadLocale(JavaPlugin plugin, String name) {
|
||||
@ -85,6 +96,7 @@ public class Locale {
|
||||
* Load all locales from this plugin's locale directory
|
||||
*
|
||||
* @param plugin plugin to load from
|
||||
*
|
||||
* @return returns the loaded Locales
|
||||
*/
|
||||
public static List<Locale> loadAllLocales(JavaPlugin plugin) {
|
||||
@ -130,6 +142,7 @@ public class Locale {
|
||||
* @param plugin plugin owning the locale file
|
||||
* @param locale the specific locale file to save
|
||||
* @param fileName where to save the file
|
||||
*
|
||||
* @return true if the operation was successful, false otherwise
|
||||
*/
|
||||
public static boolean saveDefaultLocale(JavaPlugin plugin, String locale, String fileName) {
|
||||
@ -142,6 +155,7 @@ public class Locale {
|
||||
* @param plugin plugin owning the locale file
|
||||
* @param in file to save
|
||||
* @param fileName the name of the file to save
|
||||
*
|
||||
* @return true if the operation was successful, false otherwise
|
||||
*/
|
||||
public static boolean saveLocale(Plugin plugin, InputStream in, String fileName) {
|
||||
@ -369,6 +383,7 @@ public class Locale {
|
||||
* Supply the Message object with the plugins prefix.
|
||||
*
|
||||
* @param message message to be applied
|
||||
*
|
||||
* @return applied message
|
||||
*/
|
||||
private Message supplyPrefix(Message message) {
|
||||
@ -379,6 +394,7 @@ public class Locale {
|
||||
* Create a new unsaved Message
|
||||
*
|
||||
* @param message the message to create
|
||||
*
|
||||
* @return the created message
|
||||
*/
|
||||
public Message newMessage(String message) {
|
||||
@ -389,6 +405,7 @@ public class Locale {
|
||||
* Get a message set for a specific node.
|
||||
*
|
||||
* @param node the node to get
|
||||
*
|
||||
* @return the message for the specified node
|
||||
*/
|
||||
public Message getMessage(String node) {
|
||||
@ -403,6 +420,7 @@ public class Locale {
|
||||
*
|
||||
* @param node the node to get
|
||||
* @param defaultValue the default value given that a value for the node was not found
|
||||
*
|
||||
* @return the message for the specified node. Default if none found
|
||||
*/
|
||||
public Message getMessageOrDefault(String node, String defaultValue) {
|
||||
|
@ -157,6 +157,7 @@ public class Message {
|
||||
*
|
||||
* @param placeholder the placeholder to replace
|
||||
* @param replacement the replacement object
|
||||
*
|
||||
* @return the modified Message
|
||||
*/
|
||||
public Message processPlaceholder(String placeholder, Object replacement) {
|
||||
@ -179,4 +180,4 @@ public class Message {
|
||||
public String toText() {
|
||||
return this.message.toText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.gui.AnvilGui;
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.utils.TextUtils;
|
||||
import com.songoda.core.lootables.loot.Loot;
|
||||
import com.songoda.core.utils.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -16,7 +16,7 @@ public abstract class AbstractGuiListEditor extends Gui {
|
||||
protected final Loot loot;
|
||||
private final Gui returnGui;
|
||||
|
||||
public AbstractGuiListEditor(Loot loot ,Gui returnGui) {
|
||||
public AbstractGuiListEditor(Loot loot, Gui returnGui) {
|
||||
super(1, returnGui);
|
||||
this.returnGui = returnGui;
|
||||
this.loot = loot;
|
||||
@ -27,19 +27,19 @@ public abstract class AbstractGuiListEditor extends Gui {
|
||||
public void paint() {
|
||||
List<String> lore = getData() == null ? new ArrayList<>() : getData();
|
||||
setButton(2, GuiUtils.createButtonItem(CompatibleMaterial.OAK_FENCE_GATE,
|
||||
TextUtils.formatText("&cBack")),
|
||||
TextUtils.formatText("&cBack")),
|
||||
(event) -> {
|
||||
guiManager.showGUI(event.player, returnGui);
|
||||
((GuiLootEditor) returnGui).paint();
|
||||
});
|
||||
setButton(6, GuiUtils.createButtonItem(CompatibleMaterial.OAK_FENCE_GATE,
|
||||
TextUtils.formatText("&cBack")),
|
||||
TextUtils.formatText("&cBack")),
|
||||
(event) -> {
|
||||
guiManager.showGUI(event.player, returnGui);
|
||||
((GuiLootEditor) returnGui).paint();
|
||||
});
|
||||
setButton(3, GuiUtils.createButtonItem(CompatibleMaterial.ARROW,
|
||||
TextUtils.formatText("&aAdd new line")),
|
||||
TextUtils.formatText("&aAdd new line")),
|
||||
(event -> {
|
||||
AnvilGui gui = new AnvilGui(event.player, this);
|
||||
gui.setAction((e -> {
|
||||
@ -62,7 +62,7 @@ public abstract class AbstractGuiListEditor extends Gui {
|
||||
: TextUtils.formatText(lore)));
|
||||
|
||||
setButton(5, GuiUtils.createButtonItem(CompatibleMaterial.ARROW,
|
||||
TextUtils.formatText("&cRemove the last line")),
|
||||
TextUtils.formatText("&cRemove the last line")),
|
||||
(event -> {
|
||||
lore.remove(lore.size() - 1);
|
||||
updateData(lore);
|
||||
|
@ -6,7 +6,6 @@ import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.lootables.loot.Loot;
|
||||
import com.songoda.core.utils.TextUtils;
|
||||
import com.songoda.core.lootables.loot.Loot;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -32,19 +31,19 @@ public class GuiEnchantEditor extends Gui {
|
||||
public void paint() {
|
||||
Map<String, Integer> lore = loot.getEnchants() == null ? new HashMap<>() : new HashMap<>(loot.getEnchants());
|
||||
setButton(2, GuiUtils.createButtonItem(CompatibleMaterial.OAK_FENCE_GATE,
|
||||
TextUtils.formatText("&cBack")),
|
||||
TextUtils.formatText("&cBack")),
|
||||
(event) -> {
|
||||
guiManager.showGUI(event.player, returnGui);
|
||||
((GuiLootEditor) returnGui).paint();
|
||||
});
|
||||
setButton(6, GuiUtils.createButtonItem(CompatibleMaterial.OAK_FENCE_GATE,
|
||||
TextUtils.formatText("&cBack")),
|
||||
TextUtils.formatText("&cBack")),
|
||||
(event) -> {
|
||||
guiManager.showGUI(event.player, returnGui);
|
||||
((GuiLootEditor) returnGui).paint();
|
||||
});
|
||||
setButton(3, GuiUtils.createButtonItem(CompatibleMaterial.ARROW,
|
||||
TextUtils.formatText("&aAdd new line")),
|
||||
TextUtils.formatText("&aAdd new line")),
|
||||
(event -> {
|
||||
AnvilGui gui = new AnvilGui(event.player, this);
|
||||
gui.setAction((e -> {
|
||||
@ -84,9 +83,9 @@ public class GuiEnchantEditor extends Gui {
|
||||
? TextUtils.formatText(Collections.singletonList("&cNo enchantments set..."))
|
||||
: TextUtils.formatText(enchantments)));
|
||||
|
||||
String lastFinal = last;
|
||||
String lastFinal = last;
|
||||
setButton(5, GuiUtils.createButtonItem(CompatibleMaterial.ARROW,
|
||||
TextUtils.formatText("&cRemove the last line")),
|
||||
TextUtils.formatText("&cRemove the last line")),
|
||||
(event -> {
|
||||
lore.remove(lastFinal);
|
||||
loot.setEnchants(lore);
|
||||
|
@ -4,10 +4,10 @@ import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.gui.AnvilGui;
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.utils.TextUtils;
|
||||
import com.songoda.core.lootables.loot.Loot;
|
||||
import com.songoda.core.lootables.loot.LootBuilder;
|
||||
import com.songoda.core.lootables.loot.LootManager;
|
||||
import com.songoda.core.utils.TextUtils;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -42,7 +42,7 @@ public class GuiLootEditor extends Gui {
|
||||
setActionForRange(0, 0, 5, 9, null);
|
||||
|
||||
setButton(8, GuiUtils.createButtonItem(CompatibleMaterial.OAK_DOOR,
|
||||
TextUtils.formatText("&cBack")),
|
||||
TextUtils.formatText("&cBack")),
|
||||
(event) -> {
|
||||
guiManager.showGUI(event.player, returnGui);
|
||||
});
|
||||
@ -60,7 +60,7 @@ public class GuiLootEditor extends Gui {
|
||||
});
|
||||
|
||||
setButton(10, GuiUtils.createButtonItem(CompatibleMaterial.PAPER,
|
||||
TextUtils.formatText("&7Name Override: &6" + (loot.getName() == null ? "None set" : loot.getName()))),
|
||||
TextUtils.formatText("&7Name Override: &6" + (loot.getName() == null ? "None set" : loot.getName()))),
|
||||
(event) -> {
|
||||
AnvilGui gui = new AnvilGui(event.player, this);
|
||||
gui.setAction((e -> {
|
||||
@ -73,8 +73,8 @@ public class GuiLootEditor extends Gui {
|
||||
});
|
||||
|
||||
setButton(11, GuiUtils.createButtonItem(CompatibleMaterial.WRITABLE_BOOK,
|
||||
TextUtils.formatText("&7Lore Override:"),
|
||||
TextUtils.formatText(loot.getLore() == null ? Collections.singletonList("&6None set") : loot.getLore())),
|
||||
TextUtils.formatText("&7Lore Override:"),
|
||||
TextUtils.formatText(loot.getLore() == null ? Collections.singletonList("&6None set") : loot.getLore())),
|
||||
(event) -> guiManager.showGUI(event.player, new GuiLoreEditor(loot, this)));
|
||||
|
||||
List<String> enchantments = new ArrayList<>();
|
||||
@ -84,22 +84,22 @@ public class GuiLootEditor extends Gui {
|
||||
enchantments.add("&6" + entry.getKey() + " " + entry.getValue());
|
||||
|
||||
setButton(12, GuiUtils.createButtonItem(CompatibleMaterial.ENCHANTED_BOOK,
|
||||
TextUtils.formatText("&7Enchantments:"),
|
||||
TextUtils.formatText(enchantments.isEmpty() ? Collections.singletonList("&6None set") : enchantments)),
|
||||
TextUtils.formatText("&7Enchantments:"),
|
||||
TextUtils.formatText(enchantments.isEmpty() ? Collections.singletonList("&6None set") : enchantments)),
|
||||
(event) -> guiManager.showGUI(event.player, new GuiEnchantEditor(loot, this)));
|
||||
|
||||
setButton(13, GuiUtils.createButtonItem(
|
||||
loot.getBurnedMaterial() == null
|
||||
? CompatibleMaterial.FIRE_CHARGE
|
||||
: loot.getBurnedMaterial(),
|
||||
TextUtils.formatText("&7Current Burned Material: &6"
|
||||
+ (loot.getBurnedMaterial() == null
|
||||
? "None"
|
||||
: loot.getBurnedMaterial().name())), TextUtils.formatText(
|
||||
Arrays.asList("",
|
||||
"&8Click to set the burned material to",
|
||||
"&8the material in your hand.")
|
||||
)),
|
||||
loot.getBurnedMaterial() == null
|
||||
? CompatibleMaterial.FIRE_CHARGE
|
||||
: loot.getBurnedMaterial(),
|
||||
TextUtils.formatText("&7Current Burned Material: &6"
|
||||
+ (loot.getBurnedMaterial() == null
|
||||
? "None"
|
||||
: loot.getBurnedMaterial().name())), TextUtils.formatText(
|
||||
Arrays.asList("",
|
||||
"&8Click to set the burned material to",
|
||||
"&8the material in your hand.")
|
||||
)),
|
||||
(event) -> {
|
||||
ItemStack stack = event.player.getInventory().getItemInMainHand();
|
||||
loot.setBurnedMaterial(CompatibleMaterial.getMaterial(stack));
|
||||
@ -107,12 +107,12 @@ public class GuiLootEditor extends Gui {
|
||||
});
|
||||
|
||||
setButton(14, GuiUtils.createButtonItem(CompatibleMaterial.CLOCK,
|
||||
TextUtils.formatText("&7Chance: &6" + loot.getChance()),
|
||||
TextUtils.formatText(
|
||||
Arrays.asList("",
|
||||
"&8Click to edit this loots",
|
||||
"&8drop chance.")
|
||||
)),
|
||||
TextUtils.formatText("&7Chance: &6" + loot.getChance()),
|
||||
TextUtils.formatText(
|
||||
Arrays.asList("",
|
||||
"&8Click to edit this loots",
|
||||
"&8drop chance.")
|
||||
)),
|
||||
(event) -> {
|
||||
AnvilGui gui = new AnvilGui(event.player, this);
|
||||
gui.setAction((e) -> {
|
||||
@ -126,7 +126,7 @@ public class GuiLootEditor extends Gui {
|
||||
});
|
||||
|
||||
setButton(15, GuiUtils.createButtonItem(CompatibleMaterial.REDSTONE,
|
||||
TextUtils.formatText("&7Min Drop Amount: &6" + loot.getMin())),
|
||||
TextUtils.formatText("&7Min Drop Amount: &6" + loot.getMin())),
|
||||
(event) -> {
|
||||
AnvilGui gui = new AnvilGui(event.player, this);
|
||||
gui.setAction((e) -> {
|
||||
@ -140,7 +140,7 @@ public class GuiLootEditor extends Gui {
|
||||
});
|
||||
|
||||
setButton(16, GuiUtils.createButtonItem(CompatibleMaterial.GLOWSTONE_DUST,
|
||||
TextUtils.formatText("&7Max Drop Amount: &6" + loot.getMax())),
|
||||
TextUtils.formatText("&7Max Drop Amount: &6" + loot.getMax())),
|
||||
(event) -> {
|
||||
AnvilGui gui = new AnvilGui(event.player, this);
|
||||
gui.setAction((e) -> {
|
||||
@ -154,7 +154,7 @@ public class GuiLootEditor extends Gui {
|
||||
});
|
||||
|
||||
setButton(17, GuiUtils.createButtonItem(CompatibleMaterial.REDSTONE,
|
||||
TextUtils.formatText("&7Min Item Damage: &6" + loot.getDamageMin())),
|
||||
TextUtils.formatText("&7Min Item Damage: &6" + loot.getDamageMin())),
|
||||
(event) -> {
|
||||
AnvilGui gui = new AnvilGui(event.player, this);
|
||||
gui.setAction((e) -> {
|
||||
@ -168,7 +168,7 @@ public class GuiLootEditor extends Gui {
|
||||
});
|
||||
|
||||
setButton(18, GuiUtils.createButtonItem(CompatibleMaterial.GLOWSTONE_DUST,
|
||||
TextUtils.formatText("&7Max Item Damage: &6" + loot.getDamageMax())),
|
||||
TextUtils.formatText("&7Max Item Damage: &6" + loot.getDamageMax())),
|
||||
(event) -> {
|
||||
AnvilGui gui = new AnvilGui(event.player, this);
|
||||
gui.setAction((e) -> {
|
||||
@ -182,7 +182,7 @@ public class GuiLootEditor extends Gui {
|
||||
});
|
||||
|
||||
setButton(19, GuiUtils.createButtonItem(CompatibleMaterial.CHEST,
|
||||
TextUtils.formatText("&7Allow Looting Enchantment?: &6" + loot.isAllowLootingEnchant())),
|
||||
TextUtils.formatText("&7Allow Looting Enchantment?: &6" + loot.isAllowLootingEnchant())),
|
||||
(event) -> {
|
||||
loot.setAllowLootingEnchant(!loot.isAllowLootingEnchant());
|
||||
paint();
|
||||
@ -190,7 +190,7 @@ public class GuiLootEditor extends Gui {
|
||||
});
|
||||
|
||||
setButton(20, GuiUtils.createButtonItem(CompatibleMaterial.REDSTONE,
|
||||
TextUtils.formatText("&7Min Child Loot Min: &6" + loot.getChildDropCountMin())),
|
||||
TextUtils.formatText("&7Min Child Loot Min: &6" + loot.getChildDropCountMin())),
|
||||
(event) -> {
|
||||
AnvilGui gui = new AnvilGui(event.player, this);
|
||||
gui.setAction((e) -> {
|
||||
@ -204,7 +204,7 @@ public class GuiLootEditor extends Gui {
|
||||
});
|
||||
|
||||
setButton(21, GuiUtils.createButtonItem(CompatibleMaterial.GLOWSTONE_DUST,
|
||||
TextUtils.formatText("&7Min Child Loot Max: &6" + loot.getChildDropCountMax())),
|
||||
TextUtils.formatText("&7Min Child Loot Max: &6" + loot.getChildDropCountMax())),
|
||||
(event) -> {
|
||||
AnvilGui gui = new AnvilGui(event.player, this);
|
||||
gui.setAction((e) -> {
|
||||
@ -224,8 +224,8 @@ public class GuiLootEditor extends Gui {
|
||||
entities.add("&6" + entity.name());
|
||||
|
||||
setButton(22, GuiUtils.createButtonItem(CompatibleMaterial.ENCHANTED_BOOK,
|
||||
TextUtils.formatText("&7Only Drop For:"),
|
||||
TextUtils.formatText(entities)),
|
||||
TextUtils.formatText("&7Only Drop For:"),
|
||||
TextUtils.formatText(entities)),
|
||||
(event) -> guiManager.showGUI(event.player, new GuiEntityEditor(loot, this)));
|
||||
|
||||
setButton(4, 0, GuiUtils.createButtonItem(CompatibleMaterial.LIME_DYE, TextUtils.formatText("&aCreate new Child Loot")),
|
||||
|
@ -4,11 +4,11 @@ import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.gui.AnvilGui;
|
||||
import com.songoda.core.gui.Gui;
|
||||
import com.songoda.core.gui.GuiUtils;
|
||||
import com.songoda.core.utils.TextUtils;
|
||||
import com.songoda.core.lootables.loot.Loot;
|
||||
import com.songoda.core.lootables.loot.LootBuilder;
|
||||
import com.songoda.core.lootables.loot.LootManager;
|
||||
import com.songoda.core.lootables.loot.Lootable;
|
||||
import com.songoda.core.utils.TextUtils;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
|
@ -37,7 +37,7 @@ public class DropUtils {
|
||||
commands.add(drop.getCommand());
|
||||
|
||||
if (drop.getXp() != 0)
|
||||
xp.add(drop.getXp());
|
||||
xp.add(drop.getXp());
|
||||
}
|
||||
|
||||
event.getDrops().clear();
|
||||
@ -65,5 +65,4 @@ public class DropUtils {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -161,7 +161,6 @@ public class Loot {
|
||||
this.enchants = enchants;
|
||||
}
|
||||
|
||||
|
||||
public void setEnchantChances(Map<String, Double> enchants) {
|
||||
this.enchantChances = enchants;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.songoda.core.lootables.loot;
|
||||
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.lootables.loot.objects.EnchantChance;
|
||||
import org.bukkit.entity.EntityType;
|
||||
@ -35,7 +34,7 @@ public final class LootBuilder {
|
||||
public LootBuilder addEnchants(Tuple... tuples) {
|
||||
Map<String, Integer> enchants = new HashMap<>();
|
||||
for (Tuple tuple : tuples)
|
||||
enchants.put((String)tuple.getKey(), (int)tuple.getValue());
|
||||
enchants.put((String) tuple.getKey(), (int) tuple.getValue());
|
||||
this.loot.setEnchants(enchants);
|
||||
return this;
|
||||
}
|
||||
@ -118,7 +117,7 @@ public final class LootBuilder {
|
||||
this.loot.setRequireCharged(require);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Loot build() {
|
||||
return this.loot;
|
||||
}
|
||||
@ -140,4 +139,4 @@ public final class LootBuilder {
|
||||
return this.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +140,6 @@ public class LootManager {
|
||||
addLootable(lootable);
|
||||
|
||||
reader.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -164,7 +163,6 @@ public class LootManager {
|
||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
gson.toJson(lootable, writer);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class Eval {
|
||||
public double parse() {
|
||||
nextChar();
|
||||
double x = parseExpression();
|
||||
if (pos < toParse.length()) throw new RuntimeException(warningMessage + "Unexpected: " + (char)ch);
|
||||
if (pos < toParse.length()) throw new RuntimeException(warningMessage + "Unexpected: " + (char) ch);
|
||||
return x;
|
||||
}
|
||||
|
||||
@ -39,8 +39,8 @@ public class Eval {
|
||||
|
||||
private double parseExpression() {
|
||||
double x = parseTerm();
|
||||
for (;;) {
|
||||
if (eat('+')) x += parseTerm(); // addition
|
||||
for (; ; ) {
|
||||
if (eat('+')) x += parseTerm(); // addition
|
||||
else if (eat('-')) x -= parseTerm(); // subtraction
|
||||
else return x;
|
||||
}
|
||||
@ -48,8 +48,8 @@ public class Eval {
|
||||
|
||||
private double parseTerm() {
|
||||
double x = parseFactor();
|
||||
for (;;) {
|
||||
if (eat('*')) x *= parseFactor(); // multiplication
|
||||
for (; ; ) {
|
||||
if (eat('*')) x *= parseFactor(); // multiplication
|
||||
else if (eat('/')) x /= parseFactor(); // division
|
||||
else return x;
|
||||
}
|
||||
@ -77,7 +77,7 @@ public class Eval {
|
||||
else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
|
||||
else throw new RuntimeException(warningMessage + "Unknown function: " + func);
|
||||
} else {
|
||||
throw new RuntimeException(warningMessage + "Unexpected: " + (char)ch);
|
||||
throw new RuntimeException(warningMessage + "Unexpected: " + (char) ch);
|
||||
}
|
||||
|
||||
if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,341 +1,340 @@
|
||||
package com.songoda.core.utils;
|
||||
|
||||
import com.songoda.core.compatibility.ClassMapping;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.Ageable;
|
||||
import org.bukkit.block.data.AnaloguePowerable;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Powerable;
|
||||
import org.bukkit.block.data.type.Door;
|
||||
import org.bukkit.block.data.type.Gate;
|
||||
import org.bukkit.block.data.type.Switch;
|
||||
import org.bukkit.block.data.type.TrapDoor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class BlockUtilsModern {
|
||||
|
||||
protected static void _updatePressurePlateModern(Block plate, int power) {
|
||||
BlockData blockData = plate.getBlockData();
|
||||
boolean update = false;
|
||||
if (blockData instanceof AnaloguePowerable) {
|
||||
AnaloguePowerable a = (AnaloguePowerable) blockData;
|
||||
int toPower = Math.min(a.getMaximumPower(), power);
|
||||
if ((update = toPower != a.getPower())) {
|
||||
a.setPower(toPower);
|
||||
plate.setBlockData(a);
|
||||
}
|
||||
} else if (blockData instanceof Powerable) {
|
||||
Powerable p = (Powerable) blockData;
|
||||
if ((update = p.isPowered() != (power != 0))) {
|
||||
p.setPowered(power != 0);
|
||||
plate.setBlockData(p);
|
||||
}
|
||||
}
|
||||
if (update) {
|
||||
_updateRedstoneNeighbours(plate);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void _toggleLeverModern(Block lever) {
|
||||
BlockData blockData = lever.getBlockData();
|
||||
if (blockData instanceof Switch) {
|
||||
Switch s = (Switch) blockData;
|
||||
s.setPowered(!s.isPowered());
|
||||
lever.setBlockData(s);
|
||||
_updateRedstoneNeighbours(lever);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void _pressButtonModern(Block button) {
|
||||
BlockData blockData = button.getBlockData();
|
||||
if (blockData instanceof Switch) {
|
||||
Switch s = (Switch) blockData;
|
||||
s.setPowered(true);
|
||||
button.setBlockData(s);
|
||||
_updateRedstoneNeighbours(button);
|
||||
}
|
||||
}
|
||||
|
||||
static void _releaseButtonModern(Block button) {
|
||||
BlockData blockData = button.getBlockData();
|
||||
if (blockData instanceof Switch) {
|
||||
Switch s = (Switch) blockData;
|
||||
s.setPowered(false);
|
||||
button.setBlockData(s);
|
||||
_updateRedstoneNeighbours(button);
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> clazzCraftWorld;
|
||||
private static Class<?> clazzCraftBlock;
|
||||
private static Class<?> clazzLeverBlock;
|
||||
private static Class<?> clazzButtonBlock;
|
||||
private static Class<?> clazzPressurePlateBlock;
|
||||
private static Method craftWorld_getHandle, craftBlock_getNMS, craftBlock_getPostition, craftBlockData_getState,
|
||||
nmsLever_updateNeighbours, nmsButton_updateNeighbours, nmsPlate_updateNeighbours, nmsBlockData_getBlock;
|
||||
|
||||
static {
|
||||
try {
|
||||
// Cache reflection.
|
||||
|
||||
clazzCraftWorld = ClassMapping.CRAFT_WORLD.getClazz();
|
||||
clazzCraftBlock = ClassMapping.CRAFT_BLOCK.getClazz();
|
||||
|
||||
craftWorld_getHandle = clazzCraftWorld.getMethod("getHandle");
|
||||
craftBlock_getPostition = clazzCraftBlock.getDeclaredMethod("getPosition");
|
||||
|
||||
craftBlock_getNMS = clazzCraftBlock.getDeclaredMethod("getNMS");
|
||||
Class<?> clazzBlockData = ClassMapping.BLOCK_BASE.getClazz("BlockData");
|
||||
nmsBlockData_getBlock = clazzBlockData.getDeclaredMethod("getBlock");
|
||||
|
||||
Class<?> clazzCraftBlockData = ClassMapping.CRAFT_BLOCK_DATA.getClazz();
|
||||
craftBlockData_getState = clazzCraftBlockData.getDeclaredMethod("getState");
|
||||
|
||||
Class<?> clazzWorld = ClassMapping.WORLD.getClazz();
|
||||
Class<?> clazzBlockState = ClassMapping.I_BLOCK_DATA.getClazz();
|
||||
Class<?> clazzBlockPos = ClassMapping.BLOCK_POSITION.getClazz();
|
||||
clazzLeverBlock = ClassMapping.BLOCK_LEVER.getClazz();
|
||||
clazzButtonBlock = ClassMapping.BLOCK_BUTTON_ABSTRACT.getClazz();
|
||||
clazzPressurePlateBlock = ClassMapping.BLOCK_PRESSURE_PLATE_ABSTRACT.getClazz();
|
||||
|
||||
// nmsLever_updateNeighbours, nmsButton_updateNeighbours, nmsPlate_updateNeighbours
|
||||
nmsLever_updateNeighbours = clazzLeverBlock.getDeclaredMethod(ServerVersion.isServerVersionAbove(ServerVersion.V1_13)
|
||||
? "e" : "b", clazzBlockState, clazzWorld, clazzBlockPos);
|
||||
nmsLever_updateNeighbours.setAccessible(true);
|
||||
|
||||
nmsButton_updateNeighbours = clazzButtonBlock.getDeclaredMethod(ServerVersion.isServerVersionAbove(ServerVersion.V1_13)
|
||||
? "f" : "c", clazzBlockState, clazzWorld, clazzBlockPos);
|
||||
nmsButton_updateNeighbours.setAccessible(true);
|
||||
|
||||
nmsPlate_updateNeighbours = clazzPressurePlateBlock.getDeclaredMethod("a", clazzWorld, clazzBlockPos);
|
||||
nmsPlate_updateNeighbours.setAccessible(true);
|
||||
} catch (Throwable ex) {
|
||||
Logger.getLogger(BlockUtilsModern.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void _updateRedstoneNeighbours(Block block) {
|
||||
try {
|
||||
// spigot made some changes to how data updates work in 1.13+
|
||||
// updating the data value of a redstone power source
|
||||
// does NOT update attatched block power,
|
||||
// even if you update the block state. (Still broken last I checked in 1.15.2)
|
||||
// so now we're going to manually call the updateNeighbours block method
|
||||
|
||||
// invoke and cast objects.
|
||||
Object cworld = clazzCraftWorld.cast(block.getWorld());
|
||||
Object mworld = craftWorld_getHandle.invoke(cworld);
|
||||
Object cblock = clazzCraftBlock.cast(block);
|
||||
Object mblock = nmsBlockData_getBlock.invoke(craftBlock_getNMS.invoke(cblock));
|
||||
Object mpos = craftBlock_getPostition.invoke(cblock);
|
||||
|
||||
//System.out.println(mblock.getClass());
|
||||
// now for testing stuff
|
||||
if (clazzLeverBlock.isAssignableFrom(mblock.getClass())) {
|
||||
final Object mstate = craftBlockData_getState.invoke(block.getBlockData());
|
||||
nmsLever_updateNeighbours.invoke(mblock, mstate, mworld, mpos);
|
||||
} else if (clazzButtonBlock.isAssignableFrom(mblock.getClass())) {
|
||||
final Object mstate = craftBlockData_getState.invoke(block.getBlockData());
|
||||
nmsButton_updateNeighbours.invoke(mblock, mstate, mworld, mpos);
|
||||
} else if (clazzPressurePlateBlock.isAssignableFrom(mblock.getClass())) {
|
||||
nmsPlate_updateNeighbours.invoke(mblock, mworld, mpos);
|
||||
} else {
|
||||
System.out.println("Unknown redstone: " + mblock.getClass().getName());
|
||||
}
|
||||
//
|
||||
// if(mblock instanceof net.minecraft.server.v1_15_R1.BlockLever) {
|
||||
// Method updateNeighbours = net.minecraft.server.v1_15_R1.BlockLever.class.getDeclaredMethod("e", net.minecraft.server.v1_15_R1.IBlockData.class, net.minecraft.server.v1_15_R1.World.class, net.minecraft.server.v1_15_R1.BlockPosition.class);
|
||||
// updateNeighbours.setAccessible(true);
|
||||
// // IBlockData = block state after being powered
|
||||
//
|
||||
// updateNeighbours.invoke(mblock,
|
||||
// ((org.bukkit.craftbukkit.v1_15_R1.block.data.CraftBlockData) block.getBlockData()).getState(),
|
||||
// mworld,
|
||||
// mpos);
|
||||
// } else if(mblock instanceof net.minecraft.server.v1_15_R1.BlockButtonAbstract) {
|
||||
// Method updateNeighbours = net.minecraft.server.v1_15_R1.BlockButtonAbstract.class.getDeclaredMethod("f", net.minecraft.server.v1_15_R1.IBlockData.class, net.minecraft.server.v1_15_R1.World.class, net.minecraft.server.v1_15_R1.BlockPosition.class);
|
||||
// updateNeighbours.setAccessible(true);
|
||||
// // IBlockData = block state after being powered
|
||||
//
|
||||
// updateNeighbours.invoke(mblock,
|
||||
// ((org.bukkit.craftbukkit.v1_15_R1.block.data.CraftBlockData) block.getBlockData()).getState(),
|
||||
// mworld,
|
||||
// mpos);
|
||||
// } else if(mblock instanceof net.minecraft.server.v1_15_R1.BlockPressurePlateAbstract) {
|
||||
// Method updateNeighbours = net.minecraft.server.v1_15_R1.BlockPressurePlateAbstract.class.getDeclaredMethod("a", net.minecraft.server.v1_15_R1.World.class, net.minecraft.server.v1_15_R1.BlockPosition.class);
|
||||
// updateNeighbours.setAccessible(true);
|
||||
// // IBlockData = block state after being powered
|
||||
//
|
||||
// updateNeighbours.invoke(mblock,
|
||||
// mworld,
|
||||
// mpos);
|
||||
// }
|
||||
} catch (Throwable ex) {
|
||||
Logger.getLogger(BlockUtilsModern.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void _toggleDoorStatesModern(boolean allowDoorToOpen, Block... doors) {
|
||||
for (Block door : doors) {
|
||||
BlockData blockData;
|
||||
if (door == null || !((blockData = door.getBlockData()) instanceof Door)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Door data = (Door) blockData;
|
||||
if (!allowDoorToOpen && !data.isOpen()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The lower half of the door contains the open/close state
|
||||
if (data.getHalf() == Bisected.Half.TOP) {
|
||||
Block lowerHalf = door.getRelative(BlockFace.DOWN);
|
||||
if (lowerHalf.getBlockData() instanceof Door) {
|
||||
Door lowerData = (Door) lowerHalf.getBlockData();
|
||||
lowerData.setOpen(!data.isOpen());
|
||||
lowerHalf.setBlockData(lowerData);
|
||||
}
|
||||
} else {
|
||||
data.setOpen(!data.isOpen());
|
||||
door.setBlockData(data);
|
||||
}
|
||||
|
||||
// Play the door open/close sound
|
||||
door.getWorld().playEffect(door.getLocation(), Effect.DOOR_TOGGLE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected static Block _getDoubleDoorModern(Block block) {
|
||||
BlockData bd = block.getBlockData();
|
||||
Block door = null;
|
||||
if (bd instanceof Door) {
|
||||
final Door d = (Door) bd;
|
||||
final BlockFace face = d.getFacing();
|
||||
if (face.getModX() == 0) {
|
||||
if (d.getHinge() == Door.Hinge.RIGHT) {
|
||||
door = block.getRelative(face.getModZ(), 0, 0);
|
||||
} else {
|
||||
door = block.getRelative(-face.getModZ(), 0, 0);
|
||||
}
|
||||
} else {
|
||||
if (d.getHinge() == Door.Hinge.RIGHT) {
|
||||
door = block.getRelative(0, 0, -face.getModX());
|
||||
} else {
|
||||
door = block.getRelative(0, 0, face.getModX());
|
||||
}
|
||||
}
|
||||
}
|
||||
return door != null && door.getBlockData() instanceof Door
|
||||
&& ((Door) door.getBlockData()).getHinge() != ((Door) bd).getHinge() ? door : null;
|
||||
}
|
||||
|
||||
protected static BlockFace _getDoorClosedDirectionModern(Block door) {
|
||||
if (BlockUtils.DOORS.contains(door.getType())) {
|
||||
BlockData bd = door.getBlockData();
|
||||
if (bd instanceof Door) {
|
||||
Door d = (Door) bd;
|
||||
|
||||
// The lower half of the door contains the open/close state
|
||||
if (d.getHalf() == Bisected.Half.TOP) {
|
||||
door = door.getRelative(BlockFace.DOWN);
|
||||
if (door.getBlockData() instanceof Door) {
|
||||
d = (Door) door.getBlockData();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final BlockFace face = d.getFacing();
|
||||
// now we /could/ also correct for the hinge (top block), it's not needed information
|
||||
if (face.getModX() == 0) {
|
||||
return d.isOpen() ? BlockFace.EAST : BlockFace.SOUTH;
|
||||
} else {
|
||||
return d.isOpen() ? BlockFace.SOUTH : BlockFace.EAST;
|
||||
}
|
||||
}
|
||||
} else if (BlockUtils.FENCE_GATES.contains(door.getType())) {
|
||||
BlockData bd = door.getBlockData();
|
||||
if (bd instanceof Gate) {
|
||||
Gate g = (Gate) bd;
|
||||
final BlockFace face = g.getFacing();
|
||||
if (face.getModX() == 0) {
|
||||
return g.isOpen() ? BlockFace.EAST : BlockFace.SOUTH;
|
||||
} else {
|
||||
return g.isOpen() ? BlockFace.SOUTH : BlockFace.EAST;
|
||||
}
|
||||
}
|
||||
} else if (BlockUtils.TRAP_DOORS.contains(door.getType())) {
|
||||
BlockData bd = door.getBlockData();
|
||||
if (bd instanceof TrapDoor) {
|
||||
TrapDoor t = (TrapDoor) bd;
|
||||
if (!t.isOpen()) {
|
||||
return BlockFace.UP;
|
||||
} else {
|
||||
return t.getFacing();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static boolean _isCropFullyGrown(Block block) {
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
return ((Ageable) data).getAge() == ((Ageable) data).getMaximumAge();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static int _getMaxGrowthStage(Block block) {
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
return ((Ageable) data).getMaximumAge();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected static int _getMaxGrowthStage(Material material) {
|
||||
BlockData data = material.createBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
return ((Ageable) data).getMaximumAge();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void _setGrowthStage(Block block, int stage) {
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
((Ageable) data).setAge(Math.max(0, Math.min(stage, ((Ageable) data).getMaximumAge())));
|
||||
block.setBlockData(data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void _incrementGrowthStage(Block block) {
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
final int max = ((Ageable) data).getMaximumAge();
|
||||
final int age = ((Ageable) data).getAge();
|
||||
if (age < max) {
|
||||
((Ageable) data).setAge(age + 1);
|
||||
block.setBlockData(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void _resetGrowthStage(Block block) {
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
((Ageable) data).setAge(0);
|
||||
block.setBlockData(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.songoda.core.utils;
|
||||
|
||||
import com.songoda.core.compatibility.ClassMapping;
|
||||
import com.songoda.core.compatibility.ServerVersion;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.Ageable;
|
||||
import org.bukkit.block.data.AnaloguePowerable;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Powerable;
|
||||
import org.bukkit.block.data.type.Door;
|
||||
import org.bukkit.block.data.type.Gate;
|
||||
import org.bukkit.block.data.type.Switch;
|
||||
import org.bukkit.block.data.type.TrapDoor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class BlockUtilsModern {
|
||||
|
||||
protected static void _updatePressurePlateModern(Block plate, int power) {
|
||||
BlockData blockData = plate.getBlockData();
|
||||
boolean update = false;
|
||||
if (blockData instanceof AnaloguePowerable) {
|
||||
AnaloguePowerable a = (AnaloguePowerable) blockData;
|
||||
int toPower = Math.min(a.getMaximumPower(), power);
|
||||
if ((update = toPower != a.getPower())) {
|
||||
a.setPower(toPower);
|
||||
plate.setBlockData(a);
|
||||
}
|
||||
} else if (blockData instanceof Powerable) {
|
||||
Powerable p = (Powerable) blockData;
|
||||
if ((update = p.isPowered() != (power != 0))) {
|
||||
p.setPowered(power != 0);
|
||||
plate.setBlockData(p);
|
||||
}
|
||||
}
|
||||
if (update) {
|
||||
_updateRedstoneNeighbours(plate);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void _toggleLeverModern(Block lever) {
|
||||
BlockData blockData = lever.getBlockData();
|
||||
if (blockData instanceof Switch) {
|
||||
Switch s = (Switch) blockData;
|
||||
s.setPowered(!s.isPowered());
|
||||
lever.setBlockData(s);
|
||||
_updateRedstoneNeighbours(lever);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void _pressButtonModern(Block button) {
|
||||
BlockData blockData = button.getBlockData();
|
||||
if (blockData instanceof Switch) {
|
||||
Switch s = (Switch) blockData;
|
||||
s.setPowered(true);
|
||||
button.setBlockData(s);
|
||||
_updateRedstoneNeighbours(button);
|
||||
}
|
||||
}
|
||||
|
||||
static void _releaseButtonModern(Block button) {
|
||||
BlockData blockData = button.getBlockData();
|
||||
if (blockData instanceof Switch) {
|
||||
Switch s = (Switch) blockData;
|
||||
s.setPowered(false);
|
||||
button.setBlockData(s);
|
||||
_updateRedstoneNeighbours(button);
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> clazzCraftWorld;
|
||||
private static Class<?> clazzCraftBlock;
|
||||
private static Class<?> clazzLeverBlock;
|
||||
private static Class<?> clazzButtonBlock;
|
||||
private static Class<?> clazzPressurePlateBlock;
|
||||
private static Method craftWorld_getHandle, craftBlock_getNMS, craftBlock_getPostition, craftBlockData_getState,
|
||||
nmsLever_updateNeighbours, nmsButton_updateNeighbours, nmsPlate_updateNeighbours, nmsBlockData_getBlock;
|
||||
|
||||
static {
|
||||
try {
|
||||
// Cache reflection.
|
||||
|
||||
clazzCraftWorld = ClassMapping.CRAFT_WORLD.getClazz();
|
||||
clazzCraftBlock = ClassMapping.CRAFT_BLOCK.getClazz();
|
||||
|
||||
craftWorld_getHandle = clazzCraftWorld.getMethod("getHandle");
|
||||
craftBlock_getPostition = clazzCraftBlock.getDeclaredMethod("getPosition");
|
||||
|
||||
craftBlock_getNMS = clazzCraftBlock.getDeclaredMethod("getNMS");
|
||||
Class<?> clazzBlockData = ClassMapping.BLOCK_BASE.getClazz("BlockData");
|
||||
nmsBlockData_getBlock = clazzBlockData.getDeclaredMethod("getBlock");
|
||||
|
||||
Class<?> clazzCraftBlockData = ClassMapping.CRAFT_BLOCK_DATA.getClazz();
|
||||
craftBlockData_getState = clazzCraftBlockData.getDeclaredMethod("getState");
|
||||
|
||||
Class<?> clazzWorld = ClassMapping.WORLD.getClazz();
|
||||
Class<?> clazzBlockState = ClassMapping.I_BLOCK_DATA.getClazz();
|
||||
Class<?> clazzBlockPos = ClassMapping.BLOCK_POSITION.getClazz();
|
||||
clazzLeverBlock = ClassMapping.BLOCK_LEVER.getClazz();
|
||||
clazzButtonBlock = ClassMapping.BLOCK_BUTTON_ABSTRACT.getClazz();
|
||||
clazzPressurePlateBlock = ClassMapping.BLOCK_PRESSURE_PLATE_ABSTRACT.getClazz();
|
||||
|
||||
// nmsLever_updateNeighbours, nmsButton_updateNeighbours, nmsPlate_updateNeighbours
|
||||
nmsLever_updateNeighbours = clazzLeverBlock.getDeclaredMethod(ServerVersion.isServerVersionAbove(ServerVersion.V1_13)
|
||||
? "e" : "b", clazzBlockState, clazzWorld, clazzBlockPos);
|
||||
nmsLever_updateNeighbours.setAccessible(true);
|
||||
|
||||
nmsButton_updateNeighbours = clazzButtonBlock.getDeclaredMethod(ServerVersion.isServerVersionAbove(ServerVersion.V1_13)
|
||||
? "f" : "c", clazzBlockState, clazzWorld, clazzBlockPos);
|
||||
nmsButton_updateNeighbours.setAccessible(true);
|
||||
|
||||
nmsPlate_updateNeighbours = clazzPressurePlateBlock.getDeclaredMethod("a", clazzWorld, clazzBlockPos);
|
||||
nmsPlate_updateNeighbours.setAccessible(true);
|
||||
} catch (Throwable ex) {
|
||||
Logger.getLogger(BlockUtilsModern.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void _updateRedstoneNeighbours(Block block) {
|
||||
try {
|
||||
// spigot made some changes to how data updates work in 1.13+
|
||||
// updating the data value of a redstone power source
|
||||
// does NOT update attatched block power,
|
||||
// even if you update the block state. (Still broken last I checked in 1.15.2)
|
||||
// so now we're going to manually call the updateNeighbours block method
|
||||
|
||||
// invoke and cast objects.
|
||||
Object cworld = clazzCraftWorld.cast(block.getWorld());
|
||||
Object mworld = craftWorld_getHandle.invoke(cworld);
|
||||
Object cblock = clazzCraftBlock.cast(block);
|
||||
Object mblock = nmsBlockData_getBlock.invoke(craftBlock_getNMS.invoke(cblock));
|
||||
Object mpos = craftBlock_getPostition.invoke(cblock);
|
||||
|
||||
//System.out.println(mblock.getClass());
|
||||
// now for testing stuff
|
||||
if (clazzLeverBlock.isAssignableFrom(mblock.getClass())) {
|
||||
final Object mstate = craftBlockData_getState.invoke(block.getBlockData());
|
||||
nmsLever_updateNeighbours.invoke(mblock, mstate, mworld, mpos);
|
||||
} else if (clazzButtonBlock.isAssignableFrom(mblock.getClass())) {
|
||||
final Object mstate = craftBlockData_getState.invoke(block.getBlockData());
|
||||
nmsButton_updateNeighbours.invoke(mblock, mstate, mworld, mpos);
|
||||
} else if (clazzPressurePlateBlock.isAssignableFrom(mblock.getClass())) {
|
||||
nmsPlate_updateNeighbours.invoke(mblock, mworld, mpos);
|
||||
} else {
|
||||
System.out.println("Unknown redstone: " + mblock.getClass().getName());
|
||||
}
|
||||
//
|
||||
// if(mblock instanceof net.minecraft.server.v1_15_R1.BlockLever) {
|
||||
// Method updateNeighbours = net.minecraft.server.v1_15_R1.BlockLever.class.getDeclaredMethod("e", net.minecraft.server.v1_15_R1.IBlockData.class, net.minecraft.server.v1_15_R1.World.class, net.minecraft.server.v1_15_R1.BlockPosition.class);
|
||||
// updateNeighbours.setAccessible(true);
|
||||
// // IBlockData = block state after being powered
|
||||
//
|
||||
// updateNeighbours.invoke(mblock,
|
||||
// ((org.bukkit.craftbukkit.v1_15_R1.block.data.CraftBlockData) block.getBlockData()).getState(),
|
||||
// mworld,
|
||||
// mpos);
|
||||
// } else if(mblock instanceof net.minecraft.server.v1_15_R1.BlockButtonAbstract) {
|
||||
// Method updateNeighbours = net.minecraft.server.v1_15_R1.BlockButtonAbstract.class.getDeclaredMethod("f", net.minecraft.server.v1_15_R1.IBlockData.class, net.minecraft.server.v1_15_R1.World.class, net.minecraft.server.v1_15_R1.BlockPosition.class);
|
||||
// updateNeighbours.setAccessible(true);
|
||||
// // IBlockData = block state after being powered
|
||||
//
|
||||
// updateNeighbours.invoke(mblock,
|
||||
// ((org.bukkit.craftbukkit.v1_15_R1.block.data.CraftBlockData) block.getBlockData()).getState(),
|
||||
// mworld,
|
||||
// mpos);
|
||||
// } else if(mblock instanceof net.minecraft.server.v1_15_R1.BlockPressurePlateAbstract) {
|
||||
// Method updateNeighbours = net.minecraft.server.v1_15_R1.BlockPressurePlateAbstract.class.getDeclaredMethod("a", net.minecraft.server.v1_15_R1.World.class, net.minecraft.server.v1_15_R1.BlockPosition.class);
|
||||
// updateNeighbours.setAccessible(true);
|
||||
// // IBlockData = block state after being powered
|
||||
//
|
||||
// updateNeighbours.invoke(mblock,
|
||||
// mworld,
|
||||
// mpos);
|
||||
// }
|
||||
} catch (Throwable ex) {
|
||||
Logger.getLogger(BlockUtilsModern.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void _toggleDoorStatesModern(boolean allowDoorToOpen, Block... doors) {
|
||||
for (Block door : doors) {
|
||||
BlockData blockData;
|
||||
if (door == null || !((blockData = door.getBlockData()) instanceof Door)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Door data = (Door) blockData;
|
||||
if (!allowDoorToOpen && !data.isOpen()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The lower half of the door contains the open/close state
|
||||
if (data.getHalf() == Bisected.Half.TOP) {
|
||||
Block lowerHalf = door.getRelative(BlockFace.DOWN);
|
||||
if (lowerHalf.getBlockData() instanceof Door) {
|
||||
Door lowerData = (Door) lowerHalf.getBlockData();
|
||||
lowerData.setOpen(!data.isOpen());
|
||||
lowerHalf.setBlockData(lowerData);
|
||||
}
|
||||
} else {
|
||||
data.setOpen(!data.isOpen());
|
||||
door.setBlockData(data);
|
||||
}
|
||||
|
||||
// Play the door open/close sound
|
||||
door.getWorld().playEffect(door.getLocation(), Effect.DOOR_TOGGLE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected static Block _getDoubleDoorModern(Block block) {
|
||||
BlockData bd = block.getBlockData();
|
||||
Block door = null;
|
||||
if (bd instanceof Door) {
|
||||
final Door d = (Door) bd;
|
||||
final BlockFace face = d.getFacing();
|
||||
if (face.getModX() == 0) {
|
||||
if (d.getHinge() == Door.Hinge.RIGHT) {
|
||||
door = block.getRelative(face.getModZ(), 0, 0);
|
||||
} else {
|
||||
door = block.getRelative(-face.getModZ(), 0, 0);
|
||||
}
|
||||
} else {
|
||||
if (d.getHinge() == Door.Hinge.RIGHT) {
|
||||
door = block.getRelative(0, 0, -face.getModX());
|
||||
} else {
|
||||
door = block.getRelative(0, 0, face.getModX());
|
||||
}
|
||||
}
|
||||
}
|
||||
return door != null && door.getBlockData() instanceof Door
|
||||
&& ((Door) door.getBlockData()).getHinge() != ((Door) bd).getHinge() ? door : null;
|
||||
}
|
||||
|
||||
protected static BlockFace _getDoorClosedDirectionModern(Block door) {
|
||||
if (BlockUtils.DOORS.contains(door.getType())) {
|
||||
BlockData bd = door.getBlockData();
|
||||
if (bd instanceof Door) {
|
||||
Door d = (Door) bd;
|
||||
|
||||
// The lower half of the door contains the open/close state
|
||||
if (d.getHalf() == Bisected.Half.TOP) {
|
||||
door = door.getRelative(BlockFace.DOWN);
|
||||
if (door.getBlockData() instanceof Door) {
|
||||
d = (Door) door.getBlockData();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final BlockFace face = d.getFacing();
|
||||
// now we /could/ also correct for the hinge (top block), it's not needed information
|
||||
if (face.getModX() == 0) {
|
||||
return d.isOpen() ? BlockFace.EAST : BlockFace.SOUTH;
|
||||
} else {
|
||||
return d.isOpen() ? BlockFace.SOUTH : BlockFace.EAST;
|
||||
}
|
||||
}
|
||||
} else if (BlockUtils.FENCE_GATES.contains(door.getType())) {
|
||||
BlockData bd = door.getBlockData();
|
||||
if (bd instanceof Gate) {
|
||||
Gate g = (Gate) bd;
|
||||
final BlockFace face = g.getFacing();
|
||||
if (face.getModX() == 0) {
|
||||
return g.isOpen() ? BlockFace.EAST : BlockFace.SOUTH;
|
||||
} else {
|
||||
return g.isOpen() ? BlockFace.SOUTH : BlockFace.EAST;
|
||||
}
|
||||
}
|
||||
} else if (BlockUtils.TRAP_DOORS.contains(door.getType())) {
|
||||
BlockData bd = door.getBlockData();
|
||||
if (bd instanceof TrapDoor) {
|
||||
TrapDoor t = (TrapDoor) bd;
|
||||
if (!t.isOpen()) {
|
||||
return BlockFace.UP;
|
||||
} else {
|
||||
return t.getFacing();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static boolean _isCropFullyGrown(Block block) {
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
return ((Ageable) data).getAge() == ((Ageable) data).getMaximumAge();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static int _getMaxGrowthStage(Block block) {
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
return ((Ageable) data).getMaximumAge();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected static int _getMaxGrowthStage(Material material) {
|
||||
BlockData data = material.createBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
return ((Ageable) data).getMaximumAge();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void _setGrowthStage(Block block, int stage) {
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
((Ageable) data).setAge(Math.max(0, Math.min(stage, ((Ageable) data).getMaximumAge())));
|
||||
block.setBlockData(data);
|
||||
}
|
||||
}
|
||||
|
||||
public static void _incrementGrowthStage(Block block) {
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
final int max = ((Ageable) data).getMaximumAge();
|
||||
final int age = ((Ageable) data).getAge();
|
||||
if (age < max) {
|
||||
((Ageable) data).setAge(age + 1);
|
||||
block.setBlockData(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void _resetGrowthStage(Block block) {
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof Ageable) {
|
||||
((Ageable) data).setAge(0);
|
||||
block.setBlockData(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,6 @@ public class ColorUtils {
|
||||
public B getBlue() {
|
||||
return blue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static ColorCode fromRGB(int r, int g, int b) {
|
||||
@ -64,5 +63,4 @@ public class ColorUtils {
|
||||
});
|
||||
return closest.firstEntry().getValue();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.songoda.core.utils;
|
||||
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import com.songoda.core.compatibility.ClassMapping;
|
||||
import com.songoda.core.compatibility.CompatibleMaterial;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
|
@ -20,6 +20,7 @@ public class ItemSerializer {
|
||||
* A method to serialize an {@link ItemStack} list to Base64 String.
|
||||
*
|
||||
* @param items to turn into a Base64 String.
|
||||
*
|
||||
* @return Base64 string of the items.
|
||||
*/
|
||||
public static String toBase64(List<ItemStack> items) {
|
||||
@ -48,6 +49,7 @@ public class ItemSerializer {
|
||||
* Gets a list of ItemStacks from Base64 string.
|
||||
*
|
||||
* @param data Base64 string to convert to ItemStack list.
|
||||
*
|
||||
* @return ItemStack array created from the Base64 string.
|
||||
*/
|
||||
public static List<ItemStack> fromBase64(String data) {
|
||||
@ -72,7 +74,9 @@ public class ItemSerializer {
|
||||
|
||||
/**
|
||||
* Deserialize a byte array into an ItemStack.
|
||||
*
|
||||
* @param data Data to deserialize.
|
||||
*
|
||||
* @return Deserialized ItemStack.
|
||||
*/
|
||||
public static ItemStack deserializeItem(byte[] data) {
|
||||
@ -88,7 +92,9 @@ public class ItemSerializer {
|
||||
|
||||
/**
|
||||
* Serialize an ItemStack into a byte array.
|
||||
*
|
||||
* @param item Item to serialize.
|
||||
*
|
||||
* @return Serialized data.
|
||||
*/
|
||||
public static byte[] serializeItem(ItemStack item) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,5 +21,4 @@ public class LocationUtils {
|
||||
l.getY() >= y1 && l.getY() <= y2 &&
|
||||
l.getZ() >= z1 && l.getZ() <= z2;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,8 +45,8 @@ public class Metrics {
|
||||
if (System.getProperty("bstats.relocatecheck") == null || !System.getProperty("bstats.relocatecheck").equals("false")) {
|
||||
// Maven's Relocate is clever and changes strings, too. So we have to use this little "trick" ... :D
|
||||
final String defaultPackage = new String(
|
||||
new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
|
||||
final String examplePackage = new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
|
||||
new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's', '.', 'b', 'u', 'k', 'k', 'i', 't'});
|
||||
final String examplePackage = new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
|
||||
// We want to make sure nobody just copy & pastes the example and use the wrong package names
|
||||
if (Metrics.class.getPackage().getName().equals(defaultPackage) || Metrics.class.getPackage().getName().equals(examplePackage)) {
|
||||
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
|
||||
@ -316,6 +316,7 @@ public class Metrics {
|
||||
*
|
||||
* @param plugin Any plugin. It's just used to get a logger instance.
|
||||
* @param data The data to send.
|
||||
*
|
||||
* @throws Exception If the request failed.
|
||||
*/
|
||||
private static void sendData(Plugin plugin, JSONObject data) throws Exception {
|
||||
@ -367,7 +368,9 @@ public class Metrics {
|
||||
* Gzips the given String.
|
||||
*
|
||||
* @param str The string to gzip.
|
||||
*
|
||||
* @return The gzipped String.
|
||||
*
|
||||
* @throws IOException If the compression failed.
|
||||
*/
|
||||
private static byte[] compress(final String str) throws IOException {
|
||||
@ -421,7 +424,6 @@ public class Metrics {
|
||||
}
|
||||
|
||||
protected abstract JSONObject getChartData() throws Exception;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -577,7 +579,6 @@ public class Metrics {
|
||||
data.put("value", value);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -622,7 +623,6 @@ public class Metrics {
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -660,7 +660,6 @@ public class Metrics {
|
||||
data.put("values", values);
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -710,5 +709,4 @@ public class Metrics {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class NumberUtils {
|
||||
if (count < 1000) return String.valueOf(count);
|
||||
int exp = (int) (Math.log(count) / Math.log(1000));
|
||||
return String.format("%.1f%c", count / Math.pow(1000, exp),
|
||||
"kMGTPE".charAt(exp-1)).replace(".0", "");
|
||||
"kMGTPE".charAt(exp - 1)).replace(".0", "");
|
||||
}
|
||||
|
||||
public static boolean isInt(String number) {
|
||||
@ -43,5 +43,4 @@ public class NumberUtils {
|
||||
return false;
|
||||
return s.matches("[-+]?\\d*\\.?\\d+");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,230 +1,236 @@
|
||||
package com.songoda.core.utils;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PlayerUtils {
|
||||
|
||||
static Random random = new Random();
|
||||
|
||||
public static void sendMessages(Player player, String... messages) {
|
||||
for (String message : messages)
|
||||
player.sendMessage(message);
|
||||
}
|
||||
|
||||
public static void sendMessages(Player player, List<String> messages) {
|
||||
for (String message : messages)
|
||||
player.sendMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all of the players that this player can "see"
|
||||
*
|
||||
* @param sender user to check against, or null for all players
|
||||
* @param startingWith optional query to test: only players whose game names
|
||||
* start with this
|
||||
* @return list of player names that are "visible" to the player
|
||||
*/
|
||||
public static List<String> getVisiblePlayerNames(CommandSender sender, String startingWith) {
|
||||
Player player = sender instanceof Player ? (Player) sender : null;
|
||||
final String startsWith = startingWith == null || startingWith.isEmpty() ? null : startingWith.toLowerCase();
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p != player)
|
||||
.filter(p -> startsWith == null || p.getName().toLowerCase().startsWith(startsWith))
|
||||
.filter(p -> player == null || (player.canSee(p) && p.getMetadata("vanished").isEmpty()))
|
||||
.map(Player::getName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all of the players that this player can "see"
|
||||
*
|
||||
* @param sender user to check against, or null for all players
|
||||
* @param startingWith optional query to test: only players whose game names
|
||||
* start with this
|
||||
* @return list of player names that are "visible" to the player
|
||||
*/
|
||||
public static List<String> getVisiblePlayerDisplayNames(CommandSender sender, String startingWith) {
|
||||
Player player = sender instanceof Player ? (Player) sender : null;
|
||||
final String startsWith = startingWith == null || startingWith.isEmpty() ? null : startingWith.replaceAll("[^a-zA-Z]", "").toLowerCase();
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p != player)
|
||||
.filter(p -> startsWith == null || p.getDisplayName().replaceAll("[^a-zA-Z]", "").toLowerCase().startsWith(startsWith))
|
||||
.filter(p -> player == null || (player.canSee(p) && p.getMetadata("vanished").isEmpty()))
|
||||
.map(Player::getDisplayName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all of the players that this player can "see"
|
||||
*
|
||||
* @param sender user to check against, or null for all players
|
||||
* @param startingWith optional query to test: only players whose game names
|
||||
* start with this
|
||||
* @return list of players that are "visible" to the player
|
||||
*/
|
||||
public static List<Player> getVisiblePlayers(CommandSender sender, String startingWith) {
|
||||
Player player = sender instanceof Player ? (Player) sender : null;
|
||||
final String startsWith = startingWith == null || startingWith.isEmpty() ? null : startingWith.toLowerCase();
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p != player)
|
||||
.filter(p -> startsWith == null || p.getName().toLowerCase().startsWith(startsWith))
|
||||
.filter(p -> player == null || (player.canSee(p) && p.getMetadata("vanished").isEmpty()))
|
||||
.map(p -> (Player) p)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all online player names that start with a string.
|
||||
*
|
||||
* @param us Ourselves / who is requesting the list. Will not return this player.
|
||||
* @param startsWith All names returned must start with this input string
|
||||
* @return List of matching player IGN
|
||||
*/
|
||||
public static List<String> getAllPlayers(CommandSender us, String startsWith) {
|
||||
final String arg = startsWith.toLowerCase();
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> us != p && p.getName().startsWith(arg))
|
||||
.map(Player::getName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all online player names that start with a string.
|
||||
*
|
||||
* @param us Ourselves / who is requesting the list. Will not return this player.
|
||||
* @param startsWith All names returned must start with this input string
|
||||
* @return List of matching player display names
|
||||
*/
|
||||
public static List<String> getAllPlayersDisplay(CommandSender us, String startsWith) {
|
||||
final String arg = startsWith.replaceAll("[^a-zA-Z]", "").toLowerCase();
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> us != p && p.getDisplayName().replaceAll("[^a-zA-Z]", "").startsWith(arg))
|
||||
.map(Player::getDisplayName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for and grab the closest match for a provided player name. <br />
|
||||
* Also checks player display names if there is not an exact match.
|
||||
*
|
||||
* @param player player to search for
|
||||
* @return Player that closest matches the input name, or null if none found
|
||||
*/
|
||||
public static Player findPlayer(String player) {
|
||||
Player found = Bukkit.getServer().getPlayer(player);
|
||||
if (found == null) {
|
||||
final String searchName = player.toLowerCase();
|
||||
final String searchDisplayName = player.replaceAll("[^a-zA-Z]", "").toLowerCase();
|
||||
int d = 999;
|
||||
for (Player p2 : Bukkit.getOnlinePlayers()) {
|
||||
final String test;
|
||||
if (p2.getName().toLowerCase().startsWith(searchName)) {
|
||||
int d2 = p2.getName().length() - searchName.length();
|
||||
if (d2 < d) {
|
||||
found = p2;
|
||||
d = d2;
|
||||
} else if (d2 == d) {
|
||||
found = null;
|
||||
}
|
||||
} else if ((test = p2.getDisplayName().replaceAll("[^a-zA-Z]", "")).toLowerCase().startsWith(searchDisplayName)) {
|
||||
int d2 = test.length() - searchDisplayName.length();
|
||||
if (d2 < d) {
|
||||
found = p2;
|
||||
d = d2;
|
||||
} else if (d2 == d) {
|
||||
found = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public static Player getRandomPlayer() {
|
||||
final Collection<? extends Player> all = Bukkit.getOnlinePlayers();
|
||||
final Iterator<? extends Player> alli = all.iterator();
|
||||
int pick = random.nextInt(all.size());
|
||||
for (; pick > 0; --pick) {
|
||||
alli.next();
|
||||
}
|
||||
return alli.hasNext() ? alli.next() : null;
|
||||
}
|
||||
|
||||
public static void giveItem(Player player, ItemStack item) {
|
||||
if (player == null || !player.isOnline() || item == null) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, ItemStack> leftover = player.getInventory().addItem(item);
|
||||
if (!leftover.isEmpty()) {
|
||||
leftover.values().stream().forEach(it -> player.getWorld().dropItemNaturally(player.getLocation(), it));
|
||||
}
|
||||
}
|
||||
|
||||
public static void giveItem(Player player, ItemStack... items) {
|
||||
if (player == null || !player.isOnline() || items == null || items.length == 0) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, ItemStack> leftover = player.getInventory().addItem(items);
|
||||
if (!leftover.isEmpty()) {
|
||||
final World world = player.getWorld();
|
||||
final Location location = player.getLocation();
|
||||
leftover.values().stream().forEach(it -> world.dropItemNaturally(location, it));
|
||||
}
|
||||
}
|
||||
|
||||
public static void giveItem(Player player, Collection<ItemStack> items) {
|
||||
if (player == null || !player.isOnline() || items == null || items.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, ItemStack> leftover = player.getInventory().addItem(items.toArray(new ItemStack[items.size()]));
|
||||
if (!leftover.isEmpty()) {
|
||||
final World world = player.getWorld();
|
||||
final Location location = player.getLocation();
|
||||
leftover.values().stream().forEach(it -> world.dropItemNaturally(location, it));
|
||||
}
|
||||
}
|
||||
|
||||
public static int getNumberFromPermission(Player player, String permission, int def) {
|
||||
final Set<PermissionAttachmentInfo> permissions = player.getEffectivePermissions();
|
||||
|
||||
boolean set = false;
|
||||
int highest = 0;
|
||||
|
||||
for (PermissionAttachmentInfo info : permissions) {
|
||||
|
||||
final String perm = info.getPermission();
|
||||
|
||||
if (!perm.startsWith(permission)) continue;
|
||||
|
||||
final int index = perm.lastIndexOf('.');
|
||||
|
||||
if (index == -1 || index == perm.length()) continue;
|
||||
|
||||
String numStr = perm.substring(perm.lastIndexOf('.') + 1);
|
||||
if (numStr.equals("*")) return def;
|
||||
|
||||
final int number = Integer.parseInt(numStr);
|
||||
|
||||
if (number >= highest) {
|
||||
highest = number;
|
||||
set = true;
|
||||
}
|
||||
}
|
||||
|
||||
return set ? highest : def;
|
||||
}
|
||||
}
|
||||
package com.songoda.core.utils;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PlayerUtils {
|
||||
|
||||
static Random random = new Random();
|
||||
|
||||
public static void sendMessages(Player player, String... messages) {
|
||||
for (String message : messages)
|
||||
player.sendMessage(message);
|
||||
}
|
||||
|
||||
public static void sendMessages(Player player, List<String> messages) {
|
||||
for (String message : messages)
|
||||
player.sendMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all of the players that this player can "see"
|
||||
*
|
||||
* @param sender user to check against, or null for all players
|
||||
* @param startingWith optional query to test: only players whose game names
|
||||
* start with this
|
||||
*
|
||||
* @return list of player names that are "visible" to the player
|
||||
*/
|
||||
public static List<String> getVisiblePlayerNames(CommandSender sender, String startingWith) {
|
||||
Player player = sender instanceof Player ? (Player) sender : null;
|
||||
final String startsWith = startingWith == null || startingWith.isEmpty() ? null : startingWith.toLowerCase();
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p != player)
|
||||
.filter(p -> startsWith == null || p.getName().toLowerCase().startsWith(startsWith))
|
||||
.filter(p -> player == null || (player.canSee(p) && p.getMetadata("vanished").isEmpty()))
|
||||
.map(Player::getName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all of the players that this player can "see"
|
||||
*
|
||||
* @param sender user to check against, or null for all players
|
||||
* @param startingWith optional query to test: only players whose game names
|
||||
* start with this
|
||||
*
|
||||
* @return list of player names that are "visible" to the player
|
||||
*/
|
||||
public static List<String> getVisiblePlayerDisplayNames(CommandSender sender, String startingWith) {
|
||||
Player player = sender instanceof Player ? (Player) sender : null;
|
||||
final String startsWith = startingWith == null || startingWith.isEmpty() ? null : startingWith.replaceAll("[^a-zA-Z]", "").toLowerCase();
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p != player)
|
||||
.filter(p -> startsWith == null || p.getDisplayName().replaceAll("[^a-zA-Z]", "").toLowerCase().startsWith(startsWith))
|
||||
.filter(p -> player == null || (player.canSee(p) && p.getMetadata("vanished").isEmpty()))
|
||||
.map(Player::getDisplayName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all of the players that this player can "see"
|
||||
*
|
||||
* @param sender user to check against, or null for all players
|
||||
* @param startingWith optional query to test: only players whose game names
|
||||
* start with this
|
||||
*
|
||||
* @return list of players that are "visible" to the player
|
||||
*/
|
||||
public static List<Player> getVisiblePlayers(CommandSender sender, String startingWith) {
|
||||
Player player = sender instanceof Player ? (Player) sender : null;
|
||||
final String startsWith = startingWith == null || startingWith.isEmpty() ? null : startingWith.toLowerCase();
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> p != player)
|
||||
.filter(p -> startsWith == null || p.getName().toLowerCase().startsWith(startsWith))
|
||||
.filter(p -> player == null || (player.canSee(p) && p.getMetadata("vanished").isEmpty()))
|
||||
.map(p -> (Player) p)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all online player names that start with a string.
|
||||
*
|
||||
* @param us Ourselves / who is requesting the list. Will not return this player.
|
||||
* @param startsWith All names returned must start with this input string
|
||||
*
|
||||
* @return List of matching player IGN
|
||||
*/
|
||||
public static List<String> getAllPlayers(CommandSender us, String startsWith) {
|
||||
final String arg = startsWith.toLowerCase();
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> us != p && p.getName().startsWith(arg))
|
||||
.map(Player::getName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all online player names that start with a string.
|
||||
*
|
||||
* @param us Ourselves / who is requesting the list. Will not return this player.
|
||||
* @param startsWith All names returned must start with this input string
|
||||
*
|
||||
* @return List of matching player display names
|
||||
*/
|
||||
public static List<String> getAllPlayersDisplay(CommandSender us, String startsWith) {
|
||||
final String arg = startsWith.replaceAll("[^a-zA-Z]", "").toLowerCase();
|
||||
return Bukkit.getOnlinePlayers().stream()
|
||||
.filter(p -> us != p && p.getDisplayName().replaceAll("[^a-zA-Z]", "").startsWith(arg))
|
||||
.map(Player::getDisplayName)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for and grab the closest match for a provided player name. <br />
|
||||
* Also checks player display names if there is not an exact match.
|
||||
*
|
||||
* @param player player to search for
|
||||
*
|
||||
* @return Player that closest matches the input name, or null if none found
|
||||
*/
|
||||
public static Player findPlayer(String player) {
|
||||
Player found = Bukkit.getServer().getPlayer(player);
|
||||
if (found == null) {
|
||||
final String searchName = player.toLowerCase();
|
||||
final String searchDisplayName = player.replaceAll("[^a-zA-Z]", "").toLowerCase();
|
||||
int d = 999;
|
||||
for (Player p2 : Bukkit.getOnlinePlayers()) {
|
||||
final String test;
|
||||
if (p2.getName().toLowerCase().startsWith(searchName)) {
|
||||
int d2 = p2.getName().length() - searchName.length();
|
||||
if (d2 < d) {
|
||||
found = p2;
|
||||
d = d2;
|
||||
} else if (d2 == d) {
|
||||
found = null;
|
||||
}
|
||||
} else if ((test = p2.getDisplayName().replaceAll("[^a-zA-Z]", "")).toLowerCase().startsWith(searchDisplayName)) {
|
||||
int d2 = test.length() - searchDisplayName.length();
|
||||
if (d2 < d) {
|
||||
found = p2;
|
||||
d = d2;
|
||||
} else if (d2 == d) {
|
||||
found = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
public static Player getRandomPlayer() {
|
||||
final Collection<? extends Player> all = Bukkit.getOnlinePlayers();
|
||||
final Iterator<? extends Player> alli = all.iterator();
|
||||
int pick = random.nextInt(all.size());
|
||||
for (; pick > 0; --pick) {
|
||||
alli.next();
|
||||
}
|
||||
return alli.hasNext() ? alli.next() : null;
|
||||
}
|
||||
|
||||
public static void giveItem(Player player, ItemStack item) {
|
||||
if (player == null || !player.isOnline() || item == null) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, ItemStack> leftover = player.getInventory().addItem(item);
|
||||
if (!leftover.isEmpty()) {
|
||||
leftover.values().stream().forEach(it -> player.getWorld().dropItemNaturally(player.getLocation(), it));
|
||||
}
|
||||
}
|
||||
|
||||
public static void giveItem(Player player, ItemStack... items) {
|
||||
if (player == null || !player.isOnline() || items == null || items.length == 0) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, ItemStack> leftover = player.getInventory().addItem(items);
|
||||
if (!leftover.isEmpty()) {
|
||||
final World world = player.getWorld();
|
||||
final Location location = player.getLocation();
|
||||
leftover.values().stream().forEach(it -> world.dropItemNaturally(location, it));
|
||||
}
|
||||
}
|
||||
|
||||
public static void giveItem(Player player, Collection<ItemStack> items) {
|
||||
if (player == null || !player.isOnline() || items == null || items.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Map<Integer, ItemStack> leftover = player.getInventory().addItem(items.toArray(new ItemStack[items.size()]));
|
||||
if (!leftover.isEmpty()) {
|
||||
final World world = player.getWorld();
|
||||
final Location location = player.getLocation();
|
||||
leftover.values().stream().forEach(it -> world.dropItemNaturally(location, it));
|
||||
}
|
||||
}
|
||||
|
||||
public static int getNumberFromPermission(Player player, String permission, int def) {
|
||||
final Set<PermissionAttachmentInfo> permissions = player.getEffectivePermissions();
|
||||
|
||||
boolean set = false;
|
||||
int highest = 0;
|
||||
|
||||
for (PermissionAttachmentInfo info : permissions) {
|
||||
|
||||
final String perm = info.getPermission();
|
||||
|
||||
if (!perm.startsWith(permission)) continue;
|
||||
|
||||
final int index = perm.lastIndexOf('.');
|
||||
|
||||
if (index == -1 || index == perm.length()) continue;
|
||||
|
||||
String numStr = perm.substring(perm.lastIndexOf('.') + 1);
|
||||
if (numStr.equals("*")) return def;
|
||||
|
||||
final int number = Integer.parseInt(numStr);
|
||||
|
||||
if (number >= highest) {
|
||||
highest = number;
|
||||
set = true;
|
||||
}
|
||||
}
|
||||
|
||||
return set ? highest : def;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user