diff --git a/.editorconfig b/.editorconfig index 9737e6f..f7c773b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,6 @@ +root = true + + [*] charset = utf-8 end_of_line = lf @@ -10,302 +13,14 @@ 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 +ij_formatter_tags_enabled = true -[*.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}] +[{*.yaml,*.yml,*.json,*.graphqlconfig,*.har,*.jsb2,*.jsb3,*.webmanifest,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}] 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}] + +[{*.markdown,*.md,*.html,*.htm,*.ng,*.sht,*.shtm,*.shtml,*.ts,*.ats,*.js,*.cjs,*.bash,*.sh,*.zsh}] 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 +tab_width = 2 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index c4daa16..1ef9dcf 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,12 +1 @@ -# 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'] +custom: [ 'https://craftaro.to/+' ] diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2ffd14f..fec9b26 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,18 +1,16 @@ # Please see the documentation for all configuration options: -# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file version: 2 updates: - - package-ecosystem: "maven" - directory: "/" - target-branch: "development" + - package-ecosystem: maven + directory: / + target-branch: development schedule: - interval: "monthly" - ignore: - - dependency-name: "com.songoda:SongodaCore" + interval: monthly - - package-ecosystem: "github-actions" - directory: "/" - target-branch: "development" + - package-ecosystem: github-actions + directory: / + target-branch: development schedule: - interval: "monthly" + interval: monthly diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..ab94f2e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,95 @@ +name: Build + +on: + push: + branches: [ master, development ] + tags: + - 'v*' + pull_request: + types: [ opened, synchronize, reopened ] + +permissions: read-all + +env: + DEPLOYMENT_POM_PATH: ./EpicAnchors-API/pom.xml + DEPLOYMENT_ARTIFACT_DIR: ./EpicAnchors-API/target + DEPLOYMENT_ARTIFACT_SELECTOR: EpicAnchors-API-*.jar + PLUGIN_ARTIFACT_DIR: ./EpicAnchors-Plugin/target + PLUGIN_ARTIFACT_SELECTOR: EpicAnchors-*.jar + +jobs: + Build: + name: Build + Deploy + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Prepare Workspace + uses: craftaro/GH-Commons/.github/actions/setup_workspace@master + with: + maven_username: ${{ secrets.PLUGINS_MAVEN_REPO_USERNAME }} + maven_password: ${{ secrets.PLUGINS_MAVEN_REPO_PASSWORD }} + + - name: Set project version + uses: craftaro/GH-Commons/.github/actions/maven_set_project_version@master + with: + append_snapshot: ${{ github.ref_type == 'tag' && 'false' || 'true' }} + version: ${{ github.ref_type == 'tag' && github.ref_name || '' }} + increment_version: ${{ github.ref_type != 'tag' && 'patch' || '' }} + increment_version_only_if_not_snapshot_version: ${{ github.ref == 'refs/heads/development' && 'true' || 'false' }} + + - name: Build with Maven + run: mvn -B -Duser.name="GitHub Actions on $GITHUB_REPOSITORY (id=$GITHUB_RUN_ID)" clean package + + - name: Sign jar archives + uses: craftaro/GH-Commons/.github/actions/sign_jars@master + with: + jar_file_selector: ${{ env.DEPLOYMENT_ARTIFACT_DIR }}/${{ env.DEPLOYMENT_ARTIFACT_SELECTOR }} + keystore_gpg_encrypted: ${{ secrets.PLUGINS_JARSIGNER_KEYSTORE_GPG }} + keystore_gpg_password: ${{ secrets.PLUGINS_JARSIGNER_KEYSTORE_GPG_PASSWORD }} + keystore_password: ${{ secrets.PLUGINS_JARSIGNER_KEYSTORE_PASSWORD }} + + - name: Upload Build Artifacts [API] + uses: actions/upload-artifact@v4 + with: + name: ${{ github.event.repository.name }}-API + path: ${{ env.DEPLOYMENT_ARTIFACT_DIR }}/${{ env.DEPLOYMENT_ARTIFACT_SELECTOR }} + + - name: Upload Build Artifacts [Plugin] + uses: actions/upload-artifact@v4 + with: + name: ${{ github.event.repository.name }} + path: ${{ env.PLUGIN_ARTIFACT_DIR }}/${{ env.PLUGIN_ARTIFACT_SELECTOR }} + + - name: Deploy to Maven repo + if: ${{ github.event_name == 'push' }} + uses: craftaro/GH-Commons/.github/actions/maven_deploy@master + with: + repository_url: ${{ vars.PLUGINS_MAVEN_REPO_URL_RELEASE }} + repository_url_snapshots: ${{ vars.PLUGINS_MAVEN_REPO_URL_SNAPSHOT }} + maven_pom_path: ${{ env.DEPLOYMENT_POM_PATH }} + maven_out_dir: ${{ env.DEPLOYMENT_ARTIFACT_DIR }} + + - name: Deploy parent pom.xml to Maven repo + if: ${{ github.event_name == 'push' }} + uses: craftaro/GH-Commons/.github/actions/maven_deploy@master + with: + repository_url: ${{ vars.PLUGINS_MAVEN_REPO_URL_RELEASE }} + repository_url_snapshots: ${{ vars.PLUGINS_MAVEN_REPO_URL_SNAPSHOT }} + only_deploy_pom: true + maven_out_dir: ${{ env.DEPLOYMENT_ARTIFACT_DIR }} + + discord_webhook: + name: Send Discord Webhook + runs-on: ubuntu-latest + + needs: [ Build ] + if: ${{ always() && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development' || github.ref_type == 'tag') }} + + steps: + - uses: actions/checkout@v4 + - name: Notify Webhook + uses: craftaro/GH-Commons/.github/actions/discord_send_job_results@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + webhook_url: ${{ secrets.DISCORD_BUILD_STATUS_WEBHOOK }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml deleted file mode 100644 index 99f9481..0000000 --- a/.github/workflows/maven.yml +++ /dev/null @@ -1,96 +0,0 @@ -name: 'Build & Test' - -on: - push: - branches: [ master, development ] - pull_request: - types: [ opened, synchronize, reopened ] - -jobs: - build: - name: Build - runs-on: ubuntu-latest - steps: - # Setup Java - - uses: actions/setup-java@v3 - with: - java-version: 16 - distribution: adopt - - # Checkout project files - - uses: actions/checkout@v3 - - # Caches - - name: 'Cache: Maven' - uses: actions/cache@v3 - 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: EpicAnchors-*.jar' - uses: actions/upload-artifact@v3 - with: - name: EpicAnchors-artifacts - path: ./target/EpicAnchors-*.jar - - ## - # Discord Webhook - # TODO: Extract into external Action for better re-usability (and readability) [Copied SongodaCore] - ## - - name: 'Discord Webhook (Success)' - if: ${{ success() && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development') }} - continue-on-error: true - run: | - curl -X POST --data "{\"content\":null,\"embeds\":[{\"title\":\"Build succeeded!\",\"description\":\"The build with the ID #$GITHUB_RUN_NUMBER has succeeded!\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\",\"color\":5490477,\"fields\":[{\"name\":\"Branch\",\"value\":\"$GITHUB_REF\",\"inline\":true}],\"author\":{\"name\":\"$GITHUB_REPOSITORY\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY\",\"icon_url\":\"$GITHUB_SERVER_URL/songoda.png\"},\"footer\":{\"text\":\"Initiated by $GITHUB_ACTOR\",\"icon_url\":\"$GITHUB_SERVER_URL/$GITHUB_ACTOR.png\"}}],\"username\":\"OctoAgent\",\"avatar_url\":\"https://github.githubassets.com/images/modules/logos_page/Octocat.png\"}" --header 'Content-Type: application/json' $DISCORD_WEBHOOK - env: - DISCORD_WEBHOOK: ${{ secrets.DISCORD_BUILD_STATUS_WEBHOOK }} - - name: 'Discord Webhook (Failure)' - if: ${{ failure() && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/development') }} - continue-on-error: true - run: | - curl -X POST --data "{\"content\":null,\"embeds\":[{\"title\":\"Build failed!\",\"description\":\"The build with the ID #$GITHUB_RUN_NUMBER has failed!\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\",\"color\":15611419,\"fields\":[{\"name\":\"Branch\",\"value\":\"$GITHUB_REF\",\"inline\":true}],\"author\":{\"name\":\"$GITHUB_REPOSITORY\",\"url\":\"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY\",\"icon_url\":\"$GITHUB_SERVER_URL/songoda.png\"},\"footer\":{\"text\":\"Initiated by $GITHUB_ACTOR\",\"icon_url\":\"$GITHUB_SERVER_URL/$GITHUB_ACTOR.png\"}}],\"username\":\"OctoAgent\",\"avatar_url\":\"https://github.githubassets.com/images/modules/logos_page/Octocat.png\"}" --header "Content-Type:application/json" $DISCORD_WEBHOOK - env: - DISCORD_WEBHOOK: ${{ secrets.DISCORD_BUILD_STATUS_WEBHOOK }} - - - sonarcloud: - name: SonarCloud - runs-on: ubuntu-latest - steps: - # Setup Java - - uses: actions/setup-java@v3 - with: - java-version: 11 - distribution: adopt - - # Checkout project files - - uses: actions/checkout@v3 - with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - # Caches - - name: 'Cache: Maven' - uses: actions/cache@v3 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-maven- - - name: 'Cache: SonarCloud' - uses: actions/cache@v3 - with: - path: ~/.sonar/cache - key: ${{ runner.os }}-sonar - restore-keys: ${{ runner.os }}-sonar - - # SonarCloud static analysis - - name: SonarCloud - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 0000000..34660ae --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,42 @@ +name: SonarCloud + +on: + push: + branches: [ master, development ] + workflow_dispatch: + +permissions: read-all + +env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_ORGANIZATION: craftaro + SONAR_PROJECT_KEY: craftaro_EpicAnchors + +jobs: + Analyze: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Prepare Workspace + uses: craftaro/GH-Commons/.github/actions/setup_workspace@master + + - name: 'Cache: SonarCloud' + uses: actions/cache@v4 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + + - name: Analyze project + run: > + mvn -B \ + verify \ + org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \ + -Dsonar.host.url=https://sonarcloud.io \ + "-Dsonar.organization=$SONAR_ORGANIZATION" \ + "-Dsonar.projectKey=$SONAR_PROJECT_KEY" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 600a1f2..28d2db2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,10 @@ -/target/ - -# JetBrains IDEs +## JetBrains IDEs /.idea/ *.iml + +## Maven +/**/target/ +dependency-reduced-pom.xml + +## Misc. +.DS_Store diff --git a/EpicAnchors-API/pom.xml b/EpicAnchors-API/pom.xml new file mode 100644 index 0000000..3f996fc --- /dev/null +++ b/EpicAnchors-API/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + + + com.craftaro + EpicAnchors-Parent + 3.1.1 + ../pom.xml + + EpicAnchors-API + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.6.3 + + + + + jar + + + + + + all,-missing + + https://hub.spigotmc.org/javadocs/spigot/ + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.3.0 + + + + + jar + + + + + + + + + + com.craftaro + CraftaroCore + ${craftaro.coreVersion} + provided + + + + org.spigotmc + spigot-api + 1.8-R0.1-SNAPSHOT + provided + + + diff --git a/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/EpicAnchorsApi.java b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/EpicAnchorsApi.java new file mode 100644 index 0000000..42a7e88 --- /dev/null +++ b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/EpicAnchorsApi.java @@ -0,0 +1,29 @@ +package com.craftaro.epicanchors; + +import com.craftaro.epicanchors.api.AnchorManager; + +public final class EpicAnchorsApi { + private static EpicAnchorsApi instance; + + private final AnchorManager anchorManager; + + private EpicAnchorsApi(AnchorManager anchorManager) { + this.anchorManager = anchorManager; + } + + public AnchorManager getAnchorManager() { + return this.anchorManager; + } + + public static EpicAnchorsApi getApi() { + return instance; + } + + static void initApi(AnchorManager anchorManager) { + if (instance != null) { + throw new IllegalStateException("EpicAnchorsApi already initialized"); + } + + instance = new EpicAnchorsApi(anchorManager); + } +} diff --git a/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/Anchor.java b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/Anchor.java new file mode 100644 index 0000000..e7345c0 --- /dev/null +++ b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/Anchor.java @@ -0,0 +1,34 @@ +package com.craftaro.epicanchors.api; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public interface Anchor { + int getDbId(); + + UUID getOwner(); + + boolean isLegacy(); + + @NotNull Location getLocation(); + + @NotNull World getWorld(); + + @NotNull Chunk getChunk(); + + int getTicksLeft(); + + @SuppressWarnings("unused") + void setTicksLeft(int ticksLeft); + + @SuppressWarnings("UnusedReturnValue") + int addTicksLeft(int ticks); + + int removeTicksLeft(int ticks); + + boolean isInfinite(); +} diff --git a/src/main/java/com/songoda/epicanchors/api/AnchorAccessCheck.java b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/AnchorAccessCheck.java similarity index 69% rename from src/main/java/com/songoda/epicanchors/api/AnchorAccessCheck.java rename to EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/AnchorAccessCheck.java index 66b58f5..ddb6221 100644 --- a/src/main/java/com/songoda/epicanchors/api/AnchorAccessCheck.java +++ b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/AnchorAccessCheck.java @@ -1,6 +1,5 @@ -package com.songoda.epicanchors.api; +package com.craftaro.epicanchors.api; -import com.songoda.epicanchors.Anchor; import org.jetbrains.annotations.NotNull; import java.util.UUID; diff --git a/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/AnchorManager.java b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/AnchorManager.java new file mode 100644 index 0000000..19e7c24 --- /dev/null +++ b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/api/AnchorManager.java @@ -0,0 +1,88 @@ +package com.craftaro.epicanchors.api; + +import com.craftaro.epicanchors.utils.Callback; +import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.UUID; + +public interface AnchorManager { + String NBT_TICKS_KEY = "EpicAnchors_Ticks".toLowerCase(); + + boolean isReady(World world); + + Anchor[] getAnchors(@NotNull World world); + + @Nullable Anchor getAnchor(@NotNull Block block); + + boolean isAnchor(@NotNull Block block); + + boolean hasAnchor(@NotNull Chunk chunk); + + List searchAnchors(Location center, double searchRadius); + + List searchAnchors(Location center, double searchRadius, boolean ignoreHeight); + + /** + * Creates a new anchor at a given location + * + * @param loc The block location for the anchor + * @param ticks The amount of ticks the anchor lives or -1 for infinite + */ + void createAnchor(@NotNull Location loc, @NotNull UUID owner, int ticks, @Nullable Callback callback); + + void destroyAnchor(@NotNull Anchor anchor); + + void destroyAnchor(@NotNull Anchor anchor, boolean forceSkipItemDrop); + + void registerAccessCheck(AnchorAccessCheck accessCheck); + + /** + * @param accessCheck The {@link AnchorAccessCheck} to remove + * @return true if the {@link AnchorAccessCheck} has been found and removed, false otherwise + */ + boolean unregisterAccessCheck(AnchorAccessCheck accessCheck); + + /** + * @deprecated Use {@link #hasAccess(Anchor, UUID)} instead + */ + @Deprecated + boolean hasAccess(@NotNull Anchor anchor, @NotNull OfflinePlayer p); + + /** + * Checks if a player has access to an Anchor. By default, only the owner has access to an Anchor. + *
+ * Other plugins can grant access to other players (e.g. friends). + *
+ * Legacy anchors without an owner automatically grant access to all players. + * + * @return true if the player may access the Anchor, false otherwise + * @see #registerAccessCheck(AnchorAccessCheck) + */ + boolean hasAccess(@NotNull Anchor anchor, @NotNull UUID uuid); + + + ItemStack createAnchorItem(int ticks); + + ItemStack createAnchorItem(int ticks, Material material); + + ItemStack createAnchorItem(int ticks, XMaterial material); + + boolean toggleChunkVisualized(Player p); + + void setChunksVisualized(Player p, boolean visualize); + + boolean hasChunksVisualized(Player p); + + void updateHolograms(List anchors); +} diff --git a/src/main/java/com/songoda/epicanchors/utils/Callback.java b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/utils/Callback.java similarity index 76% rename from src/main/java/com/songoda/epicanchors/utils/Callback.java rename to EpicAnchors-API/src/main/java/com/craftaro/epicanchors/utils/Callback.java index 894e449..cb0f3a3 100644 --- a/src/main/java/com/songoda/epicanchors/utils/Callback.java +++ b/EpicAnchors-API/src/main/java/com/craftaro/epicanchors/utils/Callback.java @@ -1,4 +1,4 @@ -package com.songoda.epicanchors.utils; +package com.craftaro.epicanchors.utils; import org.jetbrains.annotations.Nullable; diff --git a/EpicAnchors-Plugin/pom.xml b/EpicAnchors-Plugin/pom.xml new file mode 100644 index 0000000..5716d3b --- /dev/null +++ b/EpicAnchors-Plugin/pom.xml @@ -0,0 +1,109 @@ + + + 4.0.0 + + + com.craftaro + EpicAnchors-Parent + 3.1.1 + ../pom.xml + + EpicAnchors-Plugin + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.2 + + + + package + + shade + + + + ${project.parent.name}-${project.version} + + false + true + true + + + + com.craftaro.core + com.craftaro.epicanchors.core + + + + + + *:* + + + META-INF/** + LICENSE + LICENSE.** + + + + + com.craftaro:CraftaroCore + false + + **/nms/v*/** + + + **/third_party/org/apache/** + **/third_party/net/kyori/** + **/third_party/com/zaxxer/** + **/third_party/org/jooq/** + **/third_party/org/mariadb/** + **/third_party/com/h2database/** + **/third_party/org/h2/** + **/third_party/com/cryptomorin/** + **/third_party/org/reactivestreams/** + + + + + + + + + + + + src/main/resources + true + + + + + + + com.craftaro + EpicAnchors-API + ${project.parent.version} + compile + + + + com.craftaro + CraftaroCore + ${craftaro.coreVersion} + compile + + + + org.spigotmc + spigot-api + 1.8-R0.1-SNAPSHOT + provided + + + diff --git a/src/main/java/com/songoda/epicanchors/Anchor.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorImpl.java similarity index 88% rename from src/main/java/com/songoda/epicanchors/Anchor.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorImpl.java index 2268a61..c63feef 100644 --- a/src/main/java/com/songoda/epicanchors/Anchor.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorImpl.java @@ -1,6 +1,7 @@ -package com.songoda.epicanchors; +package com.craftaro.epicanchors; -import com.songoda.epicanchors.utils.WorldUtils; +import com.craftaro.epicanchors.api.Anchor; +import com.craftaro.epicanchors.utils.WorldUtils; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -12,7 +13,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Objects; import java.util.UUID; -public class Anchor { +public class AnchorImpl implements Anchor { private final int dbId; private final UUID owner; @@ -20,7 +21,7 @@ public class Anchor { private final Location location; private int ticksLeft; - public Anchor(int dbId, @Nullable UUID owner, @NotNull Location location, int ticksLeft) { + public AnchorImpl(int dbId, @Nullable UUID owner, @NotNull Location location, int ticksLeft) { if (dbId <= 0) throw new IllegalArgumentException("Invalid value for dbId"); if (ticksLeft <= 0 && ticksLeft != -1) throw new IllegalArgumentException("Invalid value for ticksLeft"); @@ -66,34 +67,42 @@ public class Anchor { } } + @Override public int getDbId() { return this.dbId; } + @Override public UUID getOwner() { return this.owner; } + @Override public boolean isLegacy() { return this.owner == null; } + @Override public @NotNull Location getLocation() { return this.location.clone(); } + @Override public @NotNull World getWorld() { return this.location.getWorld(); } + @Override public @NotNull Chunk getChunk() { return this.location.getChunk(); } + @Override public int getTicksLeft() { return this.ticksLeft; } + @Override @SuppressWarnings("unused") public void setTicksLeft(int ticksLeft) { if (ticksLeft < 0) throw new IllegalArgumentException("Invalid value for ticksLeft"); @@ -101,6 +110,7 @@ public class Anchor { this.ticksLeft = ticksLeft; } + @Override @SuppressWarnings("UnusedReturnValue") public int addTicksLeft(int ticks) { if (!isInfinite()) { @@ -110,6 +120,7 @@ public class Anchor { return this.ticksLeft; } + @Override public int removeTicksLeft(int ticks) { if (!isInfinite()) { this.ticksLeft -= ticks; @@ -122,6 +133,7 @@ public class Anchor { return this.ticksLeft; } + @Override public boolean isInfinite() { return this.ticksLeft == -1; } diff --git a/src/main/java/com/songoda/epicanchors/AnchorManager.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorManagerImpl.java similarity index 74% rename from src/main/java/com/songoda/epicanchors/AnchorManager.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorManagerImpl.java index 592f02c..6b10c2f 100644 --- a/src/main/java/com/songoda/epicanchors/AnchorManager.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/AnchorManagerImpl.java @@ -1,19 +1,22 @@ -package com.songoda.epicanchors; +package com.craftaro.epicanchors; -import com.songoda.core.SongodaPlugin; -import com.songoda.core.compatibility.CompatibleMaterial; -import com.songoda.core.compatibility.CompatibleParticleHandler; -import com.songoda.core.compatibility.CompatibleSound; -import com.songoda.core.hooks.HologramManager; -import com.songoda.core.third_party.de.tr7zw.nbtapi.NBTItem; -import com.songoda.core.utils.TextUtils; -import com.songoda.core.utils.TimeUtils; -import com.songoda.epicanchors.api.AnchorAccessCheck; -import com.songoda.epicanchors.files.DataManager; -import com.songoda.epicanchors.files.Settings; -import com.songoda.epicanchors.utils.Callback; -import com.songoda.epicanchors.utils.UpdateCallback; -import com.songoda.epicanchors.utils.Utils; +import com.craftaro.core.SongodaPlugin; +import com.craftaro.core.compatibility.CompatibleMaterial; +import com.craftaro.core.compatibility.CompatibleParticleHandler; +import com.craftaro.core.hooks.HologramManager; +import com.craftaro.core.third_party.de.tr7zw.nbtapi.NBTItem; +import com.craftaro.core.utils.TextUtils; +import com.craftaro.core.utils.TimeUtils; +import com.craftaro.epicanchors.api.Anchor; +import com.craftaro.epicanchors.api.AnchorAccessCheck; +import com.craftaro.epicanchors.api.AnchorManager; +import com.craftaro.epicanchors.files.AnchorsDataManager; +import com.craftaro.epicanchors.files.Settings; +import com.craftaro.epicanchors.utils.Callback; +import com.craftaro.epicanchors.utils.UpdateCallback; +import com.craftaro.epicanchors.utils.Utils; +import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; +import com.craftaro.third_party.com.cryptomorin.xseries.XSound; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -39,12 +42,12 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; -public class AnchorManager { +public class AnchorManagerImpl implements AnchorManager { private static final String ERR_WORLD_NOT_READY = "EpicAnchors has not finished initializing that world yet"; - private static final String NBT_TICKS_KEY = "EpicAnchors_Ticks".toLowerCase(); + private static final String HOLOGRAM_PREFIX = "Anchor_"; private final SongodaPlugin plugin; - private final DataManager dataManager; + private final AnchorsDataManager dataManager; private final Map> anchors = new HashMap<>(3); private final Set visualizedChunk = new HashSet<>(); @@ -52,19 +55,19 @@ public class AnchorManager { private boolean ready; - public AnchorManager(SongodaPlugin plugin, DataManager dataManager) { + public AnchorManagerImpl(SongodaPlugin plugin, AnchorsDataManager dataManager) { this.plugin = Objects.requireNonNull(plugin); this.dataManager = Objects.requireNonNull(dataManager); } protected void saveAll() { - for (Set anchorSet : anchors.values()) { + for (Set anchorSet : this.anchors.values()) { this.dataManager.updateAnchors(anchorSet, null); } } protected void deInitAll() { - for (World world : anchors.keySet().toArray(new World[0])) { + for (World world : this.anchors.keySet().toArray(new World[0])) { deInitAnchors(world); } } @@ -82,12 +85,12 @@ public class AnchorManager { this.dataManager.getAnchors(world, (ex, result) -> { if (ex == null) { - this.anchors.computeIfAbsent(world, k -> new HashSet<>()); + this.anchors.computeIfAbsent(world, key -> new HashSet<>()); for (Anchor anchor : result) { - anchor.init(this.plugin); + ((AnchorImpl) anchor).init(this.plugin); - this.anchors.computeIfAbsent(anchor.getWorld(), k -> new HashSet<>()) + this.anchors.computeIfAbsent(anchor.getWorld(), key -> new HashSet<>()) .add(anchor); } @@ -102,7 +105,7 @@ public class AnchorManager { if (callback != null) { callback.accept(ex); } else { - Utils.logException(this.plugin, ex, "SQLite"); + Utils.logException(this.plugin, ex, "H2"); } } }); @@ -115,7 +118,7 @@ public class AnchorManager { this.dataManager.updateAnchors(tmpAnchors, null); for (Anchor anchor : tmpAnchors) { - anchor.deInit(this.plugin); + ((AnchorImpl) anchor).deInit(this.plugin); } } } @@ -123,18 +126,19 @@ public class AnchorManager { protected void setReady() { this.ready = true; - Bukkit.getScheduler().runTaskTimer(plugin, this::saveAll, 20L * 60 * 5, 20L * 60 * 5); + Bukkit.getScheduler().runTaskTimer(this.plugin, this::saveAll, 20L * 60 * 5, 20L * 60 * 5); } - @SuppressWarnings("BooleanMethodIsAlwaysInverted") + @Override public boolean isReady(World world) { - return this.ready && anchors.containsKey(world); + return this.ready && this.anchors.containsKey(world); } /* Getter */ + @Override public Anchor[] getAnchors(@NotNull World world) { - Set set = anchors.get(world); + Set set = this.anchors.get(world); if (set != null) { return set.toArray(new Anchor[0]); @@ -143,13 +147,14 @@ public class AnchorManager { return new Anchor[0]; } - public @Nullable Anchor getAnchor(@NotNull Block b) { - if (!isReady(b.getWorld())) { + @Override + public @Nullable Anchor getAnchor(@NotNull Block block) { + if (!isReady(block.getWorld())) { throw new IllegalStateException(ERR_WORLD_NOT_READY); } - Location bLoc = b.getLocation(); - Set set = anchors.get(b.getWorld()); + Location bLoc = block.getLocation(); + Set set = this.anchors.get(block.getWorld()); if (set != null) { for (Anchor anchor : set) { @@ -162,16 +167,18 @@ public class AnchorManager { return null; } - public boolean isAnchor(@NotNull Block b) { - return getAnchor(b) != null; + @Override + public boolean isAnchor(@NotNull Block block) { + return getAnchor(block) != null; } + @Override public boolean hasAnchor(@NotNull Chunk chunk) { if (!isReady(chunk.getWorld())) { throw new IllegalStateException(ERR_WORLD_NOT_READY); } - Set set = anchors.get(chunk.getWorld()); + Set set = this.anchors.get(chunk.getWorld()); if (set != null) { for (Anchor anchor : set) { @@ -184,11 +191,13 @@ public class AnchorManager { return false; } + @Override @SuppressWarnings("unused") public List searchAnchors(Location center, double searchRadius) { return searchAnchors(center, searchRadius, false); } + @Override public List searchAnchors(Location center, double searchRadius, boolean ignoreHeight) { List result = new ArrayList<>(); @@ -214,12 +223,7 @@ public class AnchorManager { /* Create 'n Destroy */ - /** - * Creates a new anchor at a given location - * - * @param loc The block location for the anchor - * @param ticks The amount of ticks the anchor lives or -1 for infinite - */ + @Override public void createAnchor(@NotNull Location loc, @NotNull UUID owner, int ticks, @Nullable Callback callback) { if (!isReady(loc.getWorld())) { throw new IllegalStateException(ERR_WORLD_NOT_READY); @@ -230,14 +234,14 @@ public class AnchorManager { if (callback != null) { callback.accept(ex, null); } else { - Utils.logException(this.plugin, ex, "SQLite"); + Utils.logException(this.plugin, ex, "H2"); } } else { Bukkit.getScheduler().runTask(this.plugin, () -> { - Block b = loc.getBlock(); - b.setType(Settings.MATERIAL.getMaterial().getMaterial()); + Block block = loc.getBlock(); + block.setType(Settings.MATERIAL.getMaterial().parseMaterial()); - anchors.computeIfAbsent(anchor.getWorld(), k -> new HashSet<>()) + this.anchors.computeIfAbsent(anchor.getWorld(), key -> new HashSet<>()) .add(anchor); updateHologram(anchor); @@ -250,16 +254,18 @@ public class AnchorManager { }); } + @Override public void destroyAnchor(@NotNull Anchor anchor) { destroyAnchor(anchor, false); } + @Override public void destroyAnchor(@NotNull Anchor anchor, boolean forceSkipItemDrop) { if (!isReady(anchor.getWorld())) { throw new IllegalStateException(ERR_WORLD_NOT_READY); } - for (Set value : anchors.values()) { + for (Set value : this.anchors.values()) { value.remove(anchor); } @@ -269,7 +275,7 @@ public class AnchorManager { Block anchorBlock = anchorLoc.getBlock(); Material anchorMaterial = anchorBlock.getType(); - if (anchorBlock.getType() == Settings.MATERIAL.getMaterial().getMaterial()) { + if (anchorBlock.getType() == Settings.MATERIAL.getMaterial().parseMaterial()) { anchorBlock.setType(Material.AIR); } @@ -281,49 +287,35 @@ public class AnchorManager { } // Particles & Sound - anchor.getWorld().playSound(anchorLoc, CompatibleSound.ENTITY_GENERIC_EXPLODE.getSound(), 10, 10); + XSound.ENTITY_GENERIC_EXPLODE.play(anchorLoc, 10, 10); CompatibleParticleHandler.spawnParticles(CompatibleParticleHandler.ParticleType.getParticle(Settings.PARTICLE_DESTROY.getString()), anchor.getLocation().add(.5, .5, .5), 100, .5, .5, .5); - anchor.deInit(this.plugin); + ((AnchorImpl) anchor).deInit(this.plugin); this.dataManager.deleteAnchorAsync(anchor); } /* Anchor access */ - @SuppressWarnings("unused") + @Override public void registerAccessCheck(AnchorAccessCheck accessCheck) { - if (!accessChecks.contains(accessCheck)) { + if (!this.accessChecks.contains(accessCheck)) { // Adding at the start of the list makes sure the default check is - accessChecks.add(accessCheck); + this.accessChecks.add(accessCheck); } } - /** - * @param accessCheck The {@link AnchorAccessCheck} to remove - * - * @return true if the {@link AnchorAccessCheck} has been found and removed, false otherwise - */ - @SuppressWarnings("unused") + @Override public boolean unregisterAccessCheck(AnchorAccessCheck accessCheck) { - return accessChecks.remove(accessCheck); + return this.accessChecks.remove(accessCheck); } + @Override public boolean hasAccess(@NotNull Anchor anchor, @NotNull OfflinePlayer p) { return hasAccess(anchor, p.getUniqueId()); } - /** - * Checks if a player has access to an Anchor. By default only the owner has access to an Anchor. - *
- * Other plugins can grant access to other players (e.g. friends). - *
- * Legacy anchors without an owner automatically grant access to all players. - * - * @return true if the player may access the Anchor, false otherwise - * - * @see #registerAccessCheck(AnchorAccessCheck) - */ + @Override public boolean hasAccess(@NotNull Anchor anchor, @NotNull UUID uuid) { if (anchor.isLegacy() || anchor.getOwner().equals(uuid)) return true; @@ -338,18 +330,21 @@ public class AnchorManager { /* Anchor item */ + @Override public ItemStack createAnchorItem(int ticks) { return createAnchorItem(ticks, Settings.MATERIAL.getMaterial()); } + @Override public ItemStack createAnchorItem(int ticks, Material material) { - return createAnchorItem(ticks, CompatibleMaterial.getMaterial(material)); + return createAnchorItem(ticks, CompatibleMaterial.getMaterial(material).get()); } - public ItemStack createAnchorItem(int ticks, CompatibleMaterial material) { + @Override + public ItemStack createAnchorItem(int ticks, XMaterial material) { if (ticks <= 0 && ticks != -1) throw new IllegalArgumentException(); - ItemStack item = material.getItem(); + ItemStack item = material.parseItem(); ItemMeta meta = item.getItemMeta(); assert meta != null; @@ -363,43 +358,9 @@ public class AnchorManager { return nbtItem.getItem(); } - public static int getTicksFromItem(ItemStack item) { - if (item == null || item.getType() == Material.AIR) { - return 0; - } - - NBTItem nbtItem = new NBTItem(item); - - if (nbtItem.hasTag(NBT_TICKS_KEY)) { - return nbtItem.getInteger(NBT_TICKS_KEY); - } - - // Legacy code (pre v2) to stay cross-version compatible - if (Settings.MATERIAL.getMaterial().getMaterial() == item.getType()) { - if (nbtItem.hasTag("ticks")) { - int result = nbtItem.getInteger("ticks"); - - return result == -99 ? -1 : result; - } - - // Tries to get the ticks remaining from hidden text - if (item.hasItemMeta() && - item.getItemMeta().hasDisplayName() && - item.getItemMeta().getDisplayName().contains(":")) { - try { - int result = Integer.parseInt(item.getItemMeta().getDisplayName().replace("§", "").split(":")[0]); - - return result == -99 ? -1 : result; - } catch (NumberFormatException ignore) { - } - } - } - - return 0; - } - /* Chunk visualization */ + @Override public boolean toggleChunkVisualized(Player p) { boolean visualize = !hasChunksVisualized(p); @@ -408,6 +369,7 @@ public class AnchorManager { return visualize; } + @Override public void setChunksVisualized(Player p, boolean visualize) { if (visualize) { this.visualizedChunk.add(p); @@ -416,6 +378,7 @@ public class AnchorManager { } } + @Override @SuppressWarnings("BooleanMethodIsAlwaysInverted") public boolean hasChunksVisualized(Player p) { return this.visualizedChunk.contains(p); @@ -423,6 +386,7 @@ public class AnchorManager { /* Holograms */ + @Override public void updateHolograms(List anchors) { // are holograms enabled? if (!Settings.HOLOGRAMS.getBoolean() || !HologramManager.getManager().isEnabled()) return; @@ -432,12 +396,12 @@ public class AnchorManager { for (Anchor anchor : anchors) { List lines = Collections.singletonList(formatAnchorText(anchor.getTicksLeft(), true)); - if (!HologramManager.isHologramLoaded("Anchor#" + anchor.getDbId())) { - HologramManager.createHologram("Anchor#" + anchor.getDbId(), anchor.getLocation(), lines); + if (!HologramManager.isHologramLoaded(HOLOGRAM_PREFIX + anchor.getDbId())) { + HologramManager.createHologram(HOLOGRAM_PREFIX + anchor.getDbId(), anchor.getLocation(), lines); continue; } - hologramData.put("Anchor#" + anchor.getDbId(), lines); + hologramData.put(HOLOGRAM_PREFIX + anchor.getDbId(), lines); } // Create the holograms @@ -473,7 +437,42 @@ public class AnchorManager { return TextUtils.formatText(Settings.NAME_TAG.getString().replace("{REMAINING}", remaining)); } + public static int getTicksFromItem(ItemStack item) { + if (item == null || item.getType() == Material.AIR) { + return 0; + } + + NBTItem nbtItem = new NBTItem(item); + + if (nbtItem.hasTag(NBT_TICKS_KEY)) { + return nbtItem.getInteger(NBT_TICKS_KEY); + } + + // Legacy code (pre v2) to stay cross-version compatible + if (Settings.MATERIAL.getMaterial().parseMaterial() == item.getType()) { + if (nbtItem.hasTag("ticks")) { + int result = nbtItem.getInteger("ticks"); + + return result == -99 ? -1 : result; + } + + // Tries to get the ticks remaining from hidden text + if (item.hasItemMeta() && + item.getItemMeta().hasDisplayName() && + item.getItemMeta().getDisplayName().contains(":")) { + try { + int result = Integer.parseInt(item.getItemMeta().getDisplayName().replace("§", "").split(":")[0]); + + return result == -99 ? -1 : result; + } catch (NumberFormatException ignore) { + } + } + } + + return 0; + } + private static void removeHologram(Anchor anchor) { - HologramManager.removeHologram("Anchor#" + anchor.getDbId()); + HologramManager.removeHologram(HOLOGRAM_PREFIX + anchor.getDbId()); } } diff --git a/src/main/java/com/songoda/epicanchors/EpicAnchors.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/EpicAnchors.java similarity index 57% rename from src/main/java/com/songoda/epicanchors/EpicAnchors.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/EpicAnchors.java index ed63ade..bbb58ee 100644 --- a/src/main/java/com/songoda/epicanchors/EpicAnchors.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/EpicAnchors.java @@ -1,30 +1,30 @@ -package com.songoda.epicanchors; +package com.craftaro.epicanchors; -import com.songoda.core.SongodaCore; -import com.songoda.core.SongodaPlugin; -import com.songoda.core.commands.CommandManager; -import com.songoda.core.compatibility.CompatibleMaterial; -import com.songoda.core.configuration.Config; -import com.songoda.core.database.DatabaseConnector; -import com.songoda.core.database.SQLiteConnector; -import com.songoda.core.gui.GuiManager; -import com.songoda.core.hooks.EconomyManager; -import com.songoda.core.hooks.HologramManager; -import com.songoda.epicanchors.commands.EpicAnchorsCommand; -import com.songoda.epicanchors.commands.sub.GiveCommand; -import com.songoda.epicanchors.commands.sub.ReloadCommand; -import com.songoda.epicanchors.commands.sub.SettingsCommand; -import com.songoda.epicanchors.commands.sub.ShowCommand; -import com.songoda.epicanchors.files.DataManager; -import com.songoda.epicanchors.files.Settings; -import com.songoda.epicanchors.files.migration.AnchorMigration; -import com.songoda.epicanchors.files.migration._1_InitialMigration; -import com.songoda.epicanchors.listener.AnchorListener; -import com.songoda.epicanchors.listener.BlockListener; -import com.songoda.epicanchors.listener.WorldListener; -import com.songoda.epicanchors.tasks.AnchorTask; -import com.songoda.epicanchors.tasks.VisualizeTask; -import com.songoda.epicanchors.utils.ThreadSync; +import com.craftaro.core.SongodaCore; +import com.craftaro.core.SongodaPlugin; +import com.craftaro.core.commands.CommandManager; +import com.craftaro.core.configuration.Config; +import com.craftaro.core.dependency.Dependency; +import com.craftaro.core.gui.GuiManager; +import com.craftaro.core.hooks.EconomyManager; +import com.craftaro.core.hooks.HologramManager; +import com.craftaro.epicanchors.api.AnchorManager; +import com.craftaro.epicanchors.commands.EpicAnchorsCommand; +import com.craftaro.epicanchors.commands.sub.GiveCommand; +import com.craftaro.epicanchors.commands.sub.ReloadCommand; +import com.craftaro.epicanchors.commands.sub.SettingsCommand; +import com.craftaro.epicanchors.commands.sub.ShowCommand; +import com.craftaro.epicanchors.files.AnchorsDataManager; +import com.craftaro.epicanchors.files.Settings; +import com.craftaro.epicanchors.files.migration.LegacyYamlAnchorsMigrator; +import com.craftaro.epicanchors.files.migration._1_InitialMigration; +import com.craftaro.epicanchors.listener.AnchorListener; +import com.craftaro.epicanchors.listener.BlockListener; +import com.craftaro.epicanchors.listener.WorldListener; +import com.craftaro.epicanchors.tasks.AnchorTask; +import com.craftaro.epicanchors.tasks.VisualizeTask; +import com.craftaro.epicanchors.utils.ThreadSync; +import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.plugin.PluginManager; @@ -35,9 +35,9 @@ import java.util.logging.Level; public final class EpicAnchors extends SongodaPlugin { private GuiManager guiManager; - private AnchorManager anchorManager; + private AnchorManagerImpl anchorManager; - private DataManager dataManager; + private AnchorsDataManager dataManager; @Override public void onPluginLoad() { @@ -45,19 +45,12 @@ public final class EpicAnchors extends SongodaPlugin { @Override public void onPluginEnable() { - // Songoda Updater - SongodaCore.registerPlugin(this, 31, CompatibleMaterial.END_PORTAL_FRAME); + SongodaCore.registerPlugin(this, 31, XMaterial.END_PORTAL_FRAME); - // Initialize database - this.getLogger().info("Initializing SQLite..."); - DatabaseConnector dbCon = new SQLiteConnector(this); - this.dataManager = new DataManager(dbCon, this); - AnchorMigration anchorMigration = new AnchorMigration(dbCon, this.dataManager, - new _1_InitialMigration()); - anchorMigration.runMigrations(); + initializeDataManager(); - anchorMigration.migrateLegacyData(this); - this.anchorManager = new AnchorManager(this, this.dataManager); + this.anchorManager = new AnchorManagerImpl(this, this.dataManager); + EpicAnchorsApi.initApi(this.anchorManager); // Economy [1/2] EconomyManager.load(); @@ -74,7 +67,7 @@ public final class EpicAnchors extends SongodaPlugin { // Event Listener this.guiManager = new GuiManager(this); - guiManager.init(); + this.guiManager.init(); PluginManager pluginManager = Bukkit.getPluginManager(); pluginManager.registerEvents(new WorldListener( world -> this.anchorManager.initAnchorsAsync(world, null), @@ -150,4 +143,19 @@ public final class EpicAnchors extends SongodaPlugin { public AnchorManager getAnchorManager() { return this.anchorManager; } + + @Override + public Config getDatabaseConfig() { + Config staticDatabaseConfig = new Config(); + staticDatabaseConfig.set("Connection Settings.Type", "H2"); + staticDatabaseConfig.set("Connection Settings.Pool Size", 1); + return staticDatabaseConfig; + } + + private void initializeDataManager() { + super.initDatabase(new _1_InitialMigration()); + + this.dataManager = new AnchorsDataManager(this); + LegacyYamlAnchorsMigrator.migrateLegacyData(this, this.dataManager); + } } diff --git a/src/main/java/com/songoda/epicanchors/commands/EpicAnchorsCommand.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/EpicAnchorsCommand.java similarity index 80% rename from src/main/java/com/songoda/epicanchors/commands/EpicAnchorsCommand.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/EpicAnchorsCommand.java index f8cf8a3..049ba9c 100644 --- a/src/main/java/com/songoda/epicanchors/commands/EpicAnchorsCommand.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/EpicAnchorsCommand.java @@ -1,8 +1,8 @@ -package com.songoda.epicanchors.commands; +package com.craftaro.epicanchors.commands; -import com.songoda.core.commands.AbstractCommand; -import com.songoda.core.commands.CommandManager; -import com.songoda.epicanchors.EpicAnchors; +import com.craftaro.core.commands.AbstractCommand; +import com.craftaro.core.commands.CommandManager; +import com.craftaro.epicanchors.EpicAnchors; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; @@ -24,7 +24,7 @@ public class EpicAnchorsCommand extends AbstractCommand { protected ReturnType runCommand(CommandSender sender, String... args) { sender.sendMessage(""); this.plugin.getLocale().newMessage("&7Version " + this.plugin.getDescription().getVersion() - + " Created with <3 by &5&l&oSongoda").sendPrefixedMessage(sender); + + " Created with <3 by &5&l&oCraftaro").sendPrefixedMessage(sender); for (AbstractCommand cmd : this.commandManager.getAllCommands()) { if (cmd.getPermissionNode() == null || sender.hasPermission(cmd.getPermissionNode())) { @@ -38,7 +38,7 @@ public class EpicAnchorsCommand extends AbstractCommand { } @Override - protected List onTab(CommandSender commandSender, String... strings) { + protected List onTab(CommandSender sender, String... args) { return Collections.emptyList(); } diff --git a/src/main/java/com/songoda/epicanchors/commands/sub/GiveCommand.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/GiveCommand.java similarity index 76% rename from src/main/java/com/songoda/epicanchors/commands/sub/GiveCommand.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/GiveCommand.java index c90c96c..2b1968b 100644 --- a/src/main/java/com/songoda/epicanchors/commands/sub/GiveCommand.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/GiveCommand.java @@ -1,8 +1,8 @@ -package com.songoda.epicanchors.commands.sub; +package com.craftaro.epicanchors.commands.sub; -import com.songoda.core.commands.AbstractCommand; -import com.songoda.epicanchors.EpicAnchors; -import com.songoda.epicanchors.utils.Utils; +import com.craftaro.core.commands.AbstractCommand; +import com.craftaro.epicanchors.EpicAnchors; +import com.craftaro.epicanchors.utils.Utils; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -32,7 +32,7 @@ public class GiveCommand extends AbstractCommand { if (target == null && !args[0].trim().equalsIgnoreCase("all") && !args[0].trim().equalsIgnoreCase("@a")) { - plugin.getLocale().newMessage("&cThat is not a player...").sendPrefixedMessage(sender); + this.plugin.getLocale().newMessage("&cThat is not a player...").sendPrefixedMessage(sender); return ReturnType.SYNTAX_ERROR; } @@ -40,22 +40,22 @@ public class GiveCommand extends AbstractCommand { ItemStack itemStack; if (Utils.isInt(args[1]) && Integer.parseInt(args[1]) > 0) { - itemStack = plugin.getAnchorManager().createAnchorItem(Integer.parseInt(args[1]) * 20 * 60 * 60); + itemStack = this.plugin.getAnchorManager().createAnchorItem(Integer.parseInt(args[1]) * 20 * 60 * 60); } else if (args[1].equalsIgnoreCase("infinite")) { - itemStack = plugin.getAnchorManager().createAnchorItem(-1); + itemStack = this.plugin.getAnchorManager().createAnchorItem(-1); } else { - plugin.getLocale().newMessage("&cYou can only use positive whole numbers...").sendPrefixedMessage(sender); + this.plugin.getLocale().newMessage("&cYou can only use positive whole numbers...").sendPrefixedMessage(sender); return ReturnType.FAILURE; } if (target != null) { target.getInventory().addItem(itemStack); - plugin.getLocale().getMessage("command.give.success").sendPrefixedMessage(target); + this.plugin.getLocale().getMessage("command.give.success").sendPrefixedMessage(target); } else { for (Player online : Bukkit.getOnlinePlayers()) { online.getInventory().addItem(itemStack); - plugin.getLocale().getMessage("command.give.success").sendPrefixedMessage(online); + this.plugin.getLocale().getMessage("command.give.success").sendPrefixedMessage(online); } } @@ -63,7 +63,7 @@ public class GiveCommand extends AbstractCommand { } @Override - protected List onTab(CommandSender commandSender, String... args) { + protected List onTab(CommandSender sender, String... args) { if (args.length == 1) { Set players = new HashSet<>(); diff --git a/src/main/java/com/songoda/epicanchors/commands/sub/ReloadCommand.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/ReloadCommand.java similarity index 75% rename from src/main/java/com/songoda/epicanchors/commands/sub/ReloadCommand.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/ReloadCommand.java index e8a7ccd..a00909f 100644 --- a/src/main/java/com/songoda/epicanchors/commands/sub/ReloadCommand.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/ReloadCommand.java @@ -1,7 +1,7 @@ -package com.songoda.epicanchors.commands.sub; +package com.craftaro.epicanchors.commands.sub; -import com.songoda.core.commands.AbstractCommand; -import com.songoda.epicanchors.EpicAnchors; +import com.craftaro.core.commands.AbstractCommand; +import com.craftaro.epicanchors.EpicAnchors; import org.bukkit.command.CommandSender; import java.util.Collections; @@ -17,8 +17,8 @@ public class ReloadCommand extends AbstractCommand { @Override protected ReturnType runCommand(CommandSender sender, String... args) { - plugin.reloadConfig(); - plugin.getLocale().getMessage("&7Configuration and Language files reloaded.").sendPrefixedMessage(sender); + this.plugin.reloadConfig(); + this.plugin.getLocale().getMessage("&7Configuration and Language files reloaded.").sendPrefixedMessage(sender); return ReturnType.SUCCESS; } diff --git a/src/main/java/com/songoda/epicanchors/commands/sub/SettingsCommand.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/SettingsCommand.java similarity index 70% rename from src/main/java/com/songoda/epicanchors/commands/sub/SettingsCommand.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/SettingsCommand.java index eaa4733..d3afba5 100644 --- a/src/main/java/com/songoda/epicanchors/commands/sub/SettingsCommand.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/SettingsCommand.java @@ -1,9 +1,9 @@ -package com.songoda.epicanchors.commands.sub; +package com.craftaro.epicanchors.commands.sub; -import com.songoda.core.commands.AbstractCommand; -import com.songoda.core.configuration.editor.PluginConfigGui; -import com.songoda.core.gui.GuiManager; -import com.songoda.epicanchors.EpicAnchors; +import com.craftaro.core.commands.AbstractCommand; +import com.craftaro.core.configuration.editor.PluginConfigGui; +import com.craftaro.core.gui.GuiManager; +import com.craftaro.epicanchors.EpicAnchors; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -23,13 +23,13 @@ public class SettingsCommand extends AbstractCommand { @Override protected ReturnType runCommand(CommandSender sender, String... args) { - guiManager.showGUI((Player) sender, new PluginConfigGui(instance)); + this.guiManager.showGUI((Player) sender, new PluginConfigGui(this.instance)); return AbstractCommand.ReturnType.SUCCESS; } @Override - protected List onTab(CommandSender commandSender, String... strings) { + protected List onTab(CommandSender sender, String... args) { return Collections.emptyList(); } diff --git a/src/main/java/com/songoda/epicanchors/commands/sub/ShowCommand.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/ShowCommand.java similarity index 84% rename from src/main/java/com/songoda/epicanchors/commands/sub/ShowCommand.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/ShowCommand.java index 63bd88a..227d1f0 100644 --- a/src/main/java/com/songoda/epicanchors/commands/sub/ShowCommand.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/commands/sub/ShowCommand.java @@ -1,7 +1,7 @@ -package com.songoda.epicanchors.commands.sub; +package com.craftaro.epicanchors.commands.sub; -import com.songoda.core.commands.AbstractCommand; -import com.songoda.epicanchors.EpicAnchors; +import com.craftaro.core.commands.AbstractCommand; +import com.craftaro.epicanchors.EpicAnchors; import net.md_5.bungee.api.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -30,7 +30,7 @@ public class ShowCommand extends AbstractCommand { boolean visualize = this.plugin.getAnchorManager().toggleChunkVisualized((Player) sender); - plugin.getLocale().getMessage("command.show." + (visualize ? "start" : "stop")) + this.plugin.getLocale().getMessage("command.show." + (visualize ? "start" : "stop")) .sendPrefixedMessage(sender); return ReturnType.SUCCESS; diff --git a/src/main/java/com/songoda/epicanchors/files/DataManager.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/AnchorsDataManager.java similarity index 68% rename from src/main/java/com/songoda/epicanchors/files/DataManager.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/AnchorsDataManager.java index 21ad7d0..999c595 100644 --- a/src/main/java/com/songoda/epicanchors/files/DataManager.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/AnchorsDataManager.java @@ -1,16 +1,16 @@ -package com.songoda.epicanchors.files; +package com.craftaro.epicanchors.files; -import com.songoda.core.database.DataManagerAbstract; -import com.songoda.core.database.DatabaseConnector; -import com.songoda.epicanchors.Anchor; -import com.songoda.epicanchors.files.migration.AnchorMigration; -import com.songoda.epicanchors.utils.Callback; -import com.songoda.epicanchors.utils.UpdateCallback; -import com.songoda.epicanchors.utils.Utils; +import com.craftaro.core.SongodaPlugin; +import com.craftaro.core.database.DatabaseConnector; +import com.craftaro.epicanchors.AnchorImpl; +import com.craftaro.epicanchors.api.Anchor; +import com.craftaro.epicanchors.files.migration.LegacyYamlAnchorsMigrator; +import com.craftaro.epicanchors.utils.Callback; +import com.craftaro.epicanchors.utils.UpdateCallback; +import com.craftaro.epicanchors.utils.Utils; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,38 +27,35 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -public class DataManager extends DataManagerAbstract { +public class AnchorsDataManager { private final ExecutorService thread = Executors.newSingleThreadExecutor(); + private final SongodaPlugin plugin; - private final String anchorTable; - - public DataManager(DatabaseConnector databaseConnector, Plugin plugin) { - super(databaseConnector, plugin); - - this.anchorTable = getTableName(super.getTablePrefix(), "anchors"); + public AnchorsDataManager(SongodaPlugin plugin) { + this.plugin = plugin; } public void close() { - if (!this.thread.isShutdown()) { - this.thread.shutdown(); - - try { - if (!this.thread.awaitTermination(60, TimeUnit.SECONDS)) { - // Try stopping the thread forcefully (there is basically no hope left for the data) - this.thread.shutdownNow(); - } - } catch (InterruptedException ex) { - Utils.logException(super.plugin, ex); - } - - this.databaseConnector.closeConnection(); + if (this.thread.isShutdown()) { + return; } + + this.thread.shutdown(); + try { + if (!this.thread.awaitTermination(60, TimeUnit.SECONDS)) { + // Try stopping the thread forcefully (there is basically no hope left for the data) + this.thread.shutdownNow(); + } + } catch (InterruptedException ex) { + Utils.logException(this.plugin, ex); + } + + this.plugin.getDataManager().shutdown(); } public void exists(@NotNull String worldName, int x, int y, int z, @NotNull Callback callback) { - this.databaseConnector.connect((con) -> { - try (PreparedStatement ps = con.prepareStatement("SELECT id FROM " + this.anchorTable + - " WHERE world_name =? AND x =? AND y =? AND z=?;")) { + getDatabaseConnector().connect((con) -> { + try (PreparedStatement ps = con.prepareStatement("SELECT id FROM " + getAnchorTable() + " WHERE world_name =? AND x =? AND y =? AND z=?;")) { ps.setString(1, worldName); ps.setInt(2, x); ps.setInt(3, y); @@ -76,9 +73,8 @@ public class DataManager extends DataManagerAbstract { public void getAnchors(@Nullable World world, @NotNull Callback> callback) { List result = new ArrayList<>(); - this.databaseConnector.connect((con) -> { - try (PreparedStatement ps = con.prepareStatement("SELECT * FROM " + this.anchorTable + - (world != null ? " WHERE world_name =?" : "") + ";")) { + getDatabaseConnector().connect((con) -> { + try (PreparedStatement ps = con.prepareStatement("SELECT * FROM " + getAnchorTable() + (world != null ? " WHERE world_name =?" : "") + ";")) { if (world != null) { ps.setString(1, world.getName()); } @@ -101,11 +97,10 @@ public class DataManager extends DataManagerAbstract { } public void insertAnchor(Location loc, UUID owner, int ticks, Callback callback) { - this.databaseConnector.connect((con) -> { - try (PreparedStatement ps = con.prepareStatement("INSERT INTO " + this.anchorTable + - "(owner, world_name,x,y,z, ticks_left) VALUES (?,?,?,?,?, ?);");// Future SQLite version might support 'RETURNING *' - PreparedStatement psFetch = con.prepareStatement("SELECT * FROM " + this.anchorTable + - " WHERE world_name =? AND x =? AND y =? AND z=?;")) { + getDatabaseConnector().connect((con) -> { + try (PreparedStatement ps = con.prepareStatement("INSERT INTO " + getAnchorTable() + "(owner, world_name,x,y,z, ticks_left) VALUES (?,?,?,?,?, ?);"); // Future SQLite version might support 'RETURNING *' + PreparedStatement psFetch = con.prepareStatement("SELECT * FROM " + getAnchorTable() + " WHERE world_name =? AND x =? AND y =? AND z=?;") + ) { ps.setString(1, owner != null ? owner.toString() : null); ps.setString(2, Objects.requireNonNull(loc.getWorld()).getName()); @@ -136,15 +131,14 @@ public class DataManager extends DataManagerAbstract { }); } - public void migrateAnchor(List anchorEntries, UpdateCallback callback) { - this.databaseConnector.connect((con) -> { + public void migrateAnchor(List anchorEntries, UpdateCallback callback) { + getDatabaseConnector().connect((con) -> { con.setAutoCommit(false); SQLException err = null; - try (PreparedStatement ps = con.prepareStatement("INSERT INTO " + this.anchorTable + - "(world_name,x,y,z, ticks_left) VALUES (?,?,?,?, ?);")) { - for (AnchorMigration.LegacyAnchorEntry entry : anchorEntries) { + try (PreparedStatement ps = con.prepareStatement("INSERT INTO " + getAnchorTable() + "(world_name,x,y,z, ticks_left) VALUES (?,?,?,?, ?);")) { + for (LegacyYamlAnchorsMigrator.LegacyAnchorEntry entry : anchorEntries) { ps.setString(1, entry.worldName); ps.setInt(2, entry.x); ps.setInt(3, entry.y); @@ -159,7 +153,7 @@ public class DataManager extends DataManagerAbstract { for (int i : batchRes) { if (i < 0 && i != Statement.SUCCESS_NO_INFO) { - throw new AssertionError("Batch-INSERT failed for at least one statement with code " + i + ""); + throw new AssertionError("Batch-INSERT failed for at least one statement with code " + i); } } } catch (SQLException ex) { @@ -181,14 +175,13 @@ public class DataManager extends DataManagerAbstract { } public void updateAnchors(Collection anchors, UpdateCallback callback) { - this.databaseConnector.connect((con) -> { + getDatabaseConnector().connect((con) -> { con.setAutoCommit(false); SQLException err = null; for (Anchor anchor : anchors) { - try (PreparedStatement ps = con.prepareStatement("UPDATE " + this.anchorTable + - " SET ticks_left =? WHERE id =?;")) { + try (PreparedStatement ps = con.prepareStatement("UPDATE " + getAnchorTable() + " SET ticks_left =? WHERE id =?;")) { ps.setInt(1, anchor.getTicksLeft()); ps.setInt(2, anchor.getDbId()); @@ -219,9 +212,8 @@ public class DataManager extends DataManagerAbstract { public void deleteAnchorAsync(Anchor anchor, UpdateCallback callback) { this.thread.execute(() -> - this.databaseConnector.connect((con) -> { - try (PreparedStatement ps = con.prepareStatement("DELETE FROM " + this.anchorTable + - " WHERE id =?;")) { + getDatabaseConnector().connect((con) -> { + try (PreparedStatement ps = con.prepareStatement("DELETE FROM " + getAnchorTable() + " WHERE id =?;")) { ps.setInt(1, anchor.getDbId()); ps.executeUpdate(); @@ -234,20 +226,22 @@ public class DataManager extends DataManagerAbstract { ); } - public static String getTableName(String prefix, String name) { - String result = prefix + name; + public String getAnchorTable() { + return getAnchorTable(this.plugin.getDataManager().getTablePrefix()); + } - if (!result.matches("[a-z0-9_]+")) { - throw new IllegalStateException("The generated table name '" + result + "' contains invalid characters"); - } + public static String getAnchorTable(String prefix) { + return prefix + "anchors"; + } - return result; + private DatabaseConnector getDatabaseConnector() { + return this.plugin.getDataManager().getDatabaseConnector(); } private Anchor extractAnchor(ResultSet rs) throws SQLException { String ownerStr = rs.getString("owner"); - return new Anchor(rs.getInt("id"), + return new AnchorImpl(rs.getInt("id"), ownerStr != null ? UUID.fromString(ownerStr) : null, new Location(Bukkit.getWorld(rs.getString("world_name")), rs.getInt("x"), @@ -260,7 +254,7 @@ public class DataManager extends DataManagerAbstract { if (callback != null) { callback.accept(ex); } else if (ex != null) { - Utils.logException(this.plugin, ex, "SQLite"); + Utils.logException(this.plugin, ex, "H2"); } } @@ -268,7 +262,7 @@ public class DataManager extends DataManagerAbstract { if (callback != null) { callback.accept(ex, null); } else { - Utils.logException(this.plugin, ex, "SQLite"); + Utils.logException(this.plugin, ex, "H2"); } } } diff --git a/src/main/java/com/songoda/epicanchors/files/Settings.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/Settings.java similarity index 59% rename from src/main/java/com/songoda/epicanchors/files/Settings.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/Settings.java index 599409f..168a995 100644 --- a/src/main/java/com/songoda/epicanchors/files/Settings.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/Settings.java @@ -1,11 +1,12 @@ -package com.songoda.epicanchors.files; +package com.craftaro.epicanchors.files; -import com.songoda.core.compatibility.CompatibleMaterial; -import com.songoda.core.compatibility.CompatibleParticleHandler; -import com.songoda.core.configuration.Config; -import com.songoda.core.configuration.ConfigSetting; -import com.songoda.core.hooks.EconomyManager; -import com.songoda.epicanchors.EpicAnchors; +import com.craftaro.core.compatibility.CompatibleMaterial; +import com.craftaro.core.compatibility.CompatibleParticleHandler; +import com.craftaro.core.configuration.Config; +import com.craftaro.core.configuration.ConfigSetting; +import com.craftaro.core.hooks.EconomyManager; +import com.craftaro.epicanchors.EpicAnchors; +import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; import org.bukkit.plugin.java.JavaPlugin; public class Settings { @@ -13,60 +14,60 @@ public class Settings { throw new IllegalStateException("Utility class"); } - public static final Config config = JavaPlugin.getPlugin(EpicAnchors.class).getCoreConfig(); + public static final Config CONFIG = JavaPlugin.getPlugin(EpicAnchors.class).getCoreConfig(); - public static final ConfigSetting NAME_TAG = new ConfigSetting(config, "Main.Name Tag", + public static final ConfigSetting NAME_TAG = new ConfigSetting(CONFIG, "Main.Name Tag", "&6Anchor &8(&7{REMAINING}&8)", "The anchor name tag used on the item and in the hologram."); - public static final ConfigSetting LORE = new ConfigSetting(config, "Main.Anchor Lore", + public static final ConfigSetting LORE = new ConfigSetting(CONFIG, "Main.Anchor Lore", "&7Place down to keep that chunk\n&7loaded until the time runs out.", "The lore on the anchor item."); - public static final ConfigSetting MATERIAL = new ConfigSetting(config, "Main.Anchor Block Material", - CompatibleMaterial.END_PORTAL_FRAME.name(), "The material an anchor is represented with?"); + public static final ConfigSetting MATERIAL = new ConfigSetting(CONFIG, "Main.Anchor Block Material", + XMaterial.END_PORTAL_FRAME.name(), "The material an anchor is represented with?"); - public static final ConfigSetting ADD_TIME_WITH_XP = new ConfigSetting(config, "Main.Add Time With XP", true, + public static final ConfigSetting ADD_TIME_WITH_XP = new ConfigSetting(CONFIG, "Main.Add Time With XP", true, "Should players be able to add time to their anchors by using experience?"); - public static final ConfigSetting XP_COST = new ConfigSetting(config, "Main.XP Cost", 10, + public static final ConfigSetting XP_COST = new ConfigSetting(CONFIG, "Main.XP Cost", 10, "The cost in experience levels to add 30 minutes to an anchor."); - public static final ConfigSetting ADD_TIME_WITH_ECONOMY = new ConfigSetting(config, "Main.Add Time With Economy", true, + public static final ConfigSetting ADD_TIME_WITH_ECONOMY = new ConfigSetting(CONFIG, "Main.Add Time With Economy", true, "Should players be able to add time to their anchors by using economy?"); - public static final ConfigSetting ECONOMY_COST = new ConfigSetting(config, "Main.Economy Cost", 5000.0, + public static final ConfigSetting ECONOMY_COST = new ConfigSetting(CONFIG, "Main.Economy Cost", 5000.0, "The cost in economy to add 30 minutes to an anchor."); - public static final ConfigSetting ALLOW_ANCHOR_BREAKING = new ConfigSetting(config, "Main.Allow Anchor Breaking", false, + public static final ConfigSetting ALLOW_ANCHOR_BREAKING = new ConfigSetting(CONFIG, "Main.Allow Anchor Breaking", false, "Should players be able to break anchors and get an item dropped?"); - public static final ConfigSetting HOLOGRAMS = new ConfigSetting(config, "Main.Holograms", true, + public static final ConfigSetting HOLOGRAMS = new ConfigSetting(CONFIG, "Main.Holograms", true, "Toggle holograms showing above anchors."); @SuppressWarnings("unchecked") - public static final ConfigSetting ECONOMY_PLUGIN = new ConfigSetting(config, "Main.Economy", EconomyManager.getEconomy() == null ? "Vault" : EconomyManager.getEconomy().getName(), + public static final ConfigSetting ECONOMY_PLUGIN = new ConfigSetting(CONFIG, "Main.Economy", EconomyManager.getEconomy() == null ? "Vault" : EconomyManager.getEconomy().getName(), "Which economy plugin should be used?", "Supported plugins you have installed: \"" + String.join(", ", EconomyManager.getManager().getRegisteredPlugins()) + "\"."); - public static final ConfigSetting ECO_ICON = new ConfigSetting(config, "Interfaces.Economy Icon", CompatibleMaterial.SUNFLOWER.name(), + public static final ConfigSetting ECO_ICON = new ConfigSetting(CONFIG, "Interfaces.Economy Icon", XMaterial.SUNFLOWER.name(), "Item to be displayed as the icon for economy upgrades."); - public static final ConfigSetting XP_ICON = new ConfigSetting(config, "Interfaces.XP Icon", CompatibleMaterial.EXPERIENCE_BOTTLE.name(), + public static final ConfigSetting XP_ICON = new ConfigSetting(CONFIG, "Interfaces.XP Icon", XMaterial.EXPERIENCE_BOTTLE.name(), "Item to be displayed as the icon for XP upgrades."); - public static final ConfigSetting GLASS_TYPE_1 = new ConfigSetting(config, "Interfaces.Glass Type 1", CompatibleMaterial.GRAY_STAINED_GLASS_PANE.name()); - public static final ConfigSetting GLASS_TYPE_2 = new ConfigSetting(config, "Interfaces.Glass Type 2", CompatibleMaterial.BLUE_STAINED_GLASS_PANE.name()); - public static final ConfigSetting GLASS_TYPE_3 = new ConfigSetting(config, "Interfaces.Glass Type 3", CompatibleMaterial.LIGHT_BLUE_STAINED_GLASS_PANE.name()); + public static final ConfigSetting GLASS_TYPE_1 = new ConfigSetting(CONFIG, "Interfaces.Glass Type 1", XMaterial.GRAY_STAINED_GLASS_PANE.name()); + public static final ConfigSetting GLASS_TYPE_2 = new ConfigSetting(CONFIG, "Interfaces.Glass Type 2", XMaterial.BLUE_STAINED_GLASS_PANE.name()); + public static final ConfigSetting GLASS_TYPE_3 = new ConfigSetting(CONFIG, "Interfaces.Glass Type 3", XMaterial.LIGHT_BLUE_STAINED_GLASS_PANE.name()); - public static final ConfigSetting PARTICLE_DESTROY = new ConfigSetting(config, "Particles.Destroy", + public static final ConfigSetting PARTICLE_DESTROY = new ConfigSetting(CONFIG, "Particles.Destroy", CompatibleParticleHandler.ParticleType.LAVA.name()); - public static final ConfigSetting PARTICLE_UPGRADE = new ConfigSetting(config, "Particles.Upgrade", + public static final ConfigSetting PARTICLE_UPGRADE = new ConfigSetting(CONFIG, "Particles.Upgrade", CompatibleParticleHandler.ParticleType.SPELL_WITCH.name()); - public static final ConfigSetting PARTICLE_VISUALIZER = new ConfigSetting(config, "Particles.Visualizer", + public static final ConfigSetting PARTICLE_VISUALIZER = new ConfigSetting(CONFIG, "Particles.Visualizer", CompatibleParticleHandler.ParticleType.VILLAGER_HAPPY.name()); - public static final ConfigSetting LANGUAGE = new ConfigSetting(config, "System.Language Mode", "en_US", + public static final ConfigSetting LANGUAGE = new ConfigSetting(CONFIG, "System.Language Mode", "en_US", "The enabled language file.", "More language files (if available) can be found in the plugins data folder."); @@ -75,31 +76,31 @@ public class Settings { * called after EconomyManager load */ public static void setupConfig() { - config.load(); - config.setAutoremove(true) + CONFIG.load(); + CONFIG.setAutoremove(true) .setAutosave(true); // convert glass pane settings int color; if ((color = GLASS_TYPE_1.getInt(-1)) != -1) { - config.set(GLASS_TYPE_1.getKey(), CompatibleMaterial.getGlassPaneColor(color).name()); + CONFIG.set(GLASS_TYPE_1.getKey(), CompatibleMaterial.getGlassPaneForColor(color).name()); } if ((color = GLASS_TYPE_2.getInt(-1)) != -1) { - config.set(GLASS_TYPE_2.getKey(), CompatibleMaterial.getGlassPaneColor(color).name()); + CONFIG.set(GLASS_TYPE_2.getKey(), CompatibleMaterial.getGlassPaneForColor(color).name()); } if ((color = GLASS_TYPE_3.getInt(-1)) != -1) { - config.set(GLASS_TYPE_3.getKey(), CompatibleMaterial.getGlassPaneColor(color).name()); + CONFIG.set(GLASS_TYPE_3.getKey(), CompatibleMaterial.getGlassPaneForColor(color).name()); } // convert economy settings - if (config.getBoolean("Economy.Use Vault Economy") && EconomyManager.getManager().isEnabled("Vault")) { - config.set("Main.Economy", "Vault"); - } else if (config.getBoolean("Economy.Use Reserve Economy") && EconomyManager.getManager().isEnabled("Reserve")) { - config.set("Main.Economy", "Reserve"); - } else if (config.getBoolean("Economy.Use Player Points Economy") && EconomyManager.getManager().isEnabled("PlayerPoints")) { - config.set("Main.Economy", "PlayerPoints"); + if (CONFIG.getBoolean("Economy.Use Vault Economy") && EconomyManager.getManager().isEnabled("Vault")) { + CONFIG.set("Main.Economy", "Vault"); + } else if (CONFIG.getBoolean("Economy.Use Reserve Economy") && EconomyManager.getManager().isEnabled("Reserve")) { + CONFIG.set("Main.Economy", "Reserve"); + } else if (CONFIG.getBoolean("Economy.Use Player Points Economy") && EconomyManager.getManager().isEnabled("PlayerPoints")) { + CONFIG.set("Main.Economy", "PlayerPoints"); } - config.saveChanges(); + CONFIG.saveChanges(); } } diff --git a/src/main/java/com/songoda/epicanchors/files/migration/AnchorMigration.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/LegacyYamlAnchorsMigrator.java similarity index 82% rename from src/main/java/com/songoda/epicanchors/files/migration/AnchorMigration.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/LegacyYamlAnchorsMigrator.java index 891830c..48b9df6 100644 --- a/src/main/java/com/songoda/epicanchors/files/migration/AnchorMigration.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/LegacyYamlAnchorsMigrator.java @@ -1,12 +1,9 @@ -package com.songoda.epicanchors.files.migration; +package com.craftaro.epicanchors.files.migration; -import com.songoda.core.configuration.Config; -import com.songoda.core.configuration.ConfigSection; -import com.songoda.core.database.DataMigration; -import com.songoda.core.database.DataMigrationManager; -import com.songoda.core.database.DatabaseConnector; -import com.songoda.epicanchors.files.DataManager; -import com.songoda.epicanchors.utils.ThreadSync; +import com.craftaro.core.configuration.Config; +import com.craftaro.core.configuration.ConfigSection; +import com.craftaro.epicanchors.files.AnchorsDataManager; +import com.craftaro.epicanchors.utils.ThreadSync; import org.bukkit.Location; import org.bukkit.plugin.Plugin; @@ -18,16 +15,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; -public class AnchorMigration extends DataMigrationManager { - private final DataManager dataManager; - - public AnchorMigration(DatabaseConnector databaseConnector, DataManager dataManager, DataMigration... migrations) { - super(databaseConnector, dataManager, migrations); - - this.dataManager = dataManager; - } - - public void migrateLegacyData(Plugin plugin) { +public class LegacyYamlAnchorsMigrator { + public static void migrateLegacyData(Plugin plugin, AnchorsDataManager dataManager) { long start = System.nanoTime(); AtomicBoolean abortMigration = new AtomicBoolean(false); @@ -94,7 +83,7 @@ public class AnchorMigration extends DataMigrationManager { if (!abortMigration.get()) { int finalMigratedAnchors = migratedAnchors; - this.dataManager.migrateAnchor(anchorQueue, ex -> { + dataManager.migrateAnchor(anchorQueue, ex -> { long end = System.nanoTime(); if (ex == null) { @@ -114,7 +103,7 @@ public class AnchorMigration extends DataMigrationManager { } } - private String[] deserializeLegacyLocation(String str) { + private static String[] deserializeLegacyLocation(String str) { if (str == null || str.isEmpty()) { return new String[0]; } diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/_1_InitialMigration.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/_1_InitialMigration.java new file mode 100644 index 0000000..f260e66 --- /dev/null +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/files/migration/_1_InitialMigration.java @@ -0,0 +1,31 @@ +package com.craftaro.epicanchors.files.migration; + +import com.craftaro.core.database.DataMigration; +import com.craftaro.epicanchors.files.AnchorsDataManager; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +public class _1_InitialMigration extends DataMigration { + public _1_InitialMigration() { + super(1); + } + + @Override + public void migrate(Connection connection, String tablePrefix) throws SQLException { + try (Statement statement = connection.createStatement()) { + statement.execute( + "CREATE TABLE " + AnchorsDataManager.getAnchorTable(tablePrefix) + + "(" + + "id INTEGER NOT NULL PRIMARY KEY auto_increment," + + "world_name TEXT NOT NULL," + + "x INTEGER NOT NULL," + + "y INTEGER NOT NULL," + + "z INTEGER NOT NULL," + + "ticks_left INTEGER NOT NULL," + + "owner VARCHAR(36)" + + ");"); + } + } +} diff --git a/src/main/java/com/songoda/epicanchors/guis/AnchorGui.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/guis/AnchorGui.java similarity index 75% rename from src/main/java/com/songoda/epicanchors/guis/AnchorGui.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/guis/AnchorGui.java index 83d4fb9..878dee9 100644 --- a/src/main/java/com/songoda/epicanchors/guis/AnchorGui.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/guis/AnchorGui.java @@ -1,16 +1,16 @@ -package com.songoda.epicanchors.guis; +package com.craftaro.epicanchors.guis; -import com.songoda.core.compatibility.CompatibleMaterial; -import com.songoda.core.compatibility.CompatibleParticleHandler; -import com.songoda.core.compatibility.CompatibleSound; -import com.songoda.core.gui.Gui; -import com.songoda.core.gui.GuiUtils; -import com.songoda.core.hooks.EconomyManager; -import com.songoda.core.utils.TextUtils; -import com.songoda.core.utils.TimeUtils; -import com.songoda.epicanchors.Anchor; -import com.songoda.epicanchors.EpicAnchors; -import com.songoda.epicanchors.files.Settings; +import com.craftaro.core.compatibility.CompatibleParticleHandler; +import com.craftaro.core.gui.Gui; +import com.craftaro.core.gui.GuiUtils; +import com.craftaro.core.hooks.EconomyManager; +import com.craftaro.core.utils.TextUtils; +import com.craftaro.core.utils.TimeUtils; +import com.craftaro.epicanchors.EpicAnchors; +import com.craftaro.epicanchors.api.Anchor; +import com.craftaro.epicanchors.files.Settings; +import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; +import com.craftaro.third_party.com.cryptomorin.xseries.XSound; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.GameMode; @@ -36,26 +36,26 @@ public class AnchorGui extends Gui { prepareGui(this.plugin, this, this.anchor); if (Settings.ADD_TIME_WITH_XP.getBoolean()) { - String itemName = plugin.getLocale().getMessage("interface.button.addtimewithxp").getMessage(); - String itemLore = plugin.getLocale().getMessage("interface.button.addtimewithxplore") + String itemName = this.plugin.getLocale().getMessage("interface.button.addtimewithxp").getMessage(); + String itemLore = this.plugin.getLocale().getMessage("interface.button.addtimewithxplore") .processPlaceholder("cost", Settings.XP_COST.getInt()) .getMessage(); setButton(11, - GuiUtils.createButtonItem(Settings.XP_ICON.getMaterial(CompatibleMaterial.EXPERIENCE_BOTTLE), itemName, itemLore), - event -> buyTime(anchor, event.player, false)); + GuiUtils.createButtonItem(Settings.XP_ICON.getMaterial(XMaterial.EXPERIENCE_BOTTLE), itemName, itemLore), + event -> buyTime(this.anchor, event.player, false)); } if (EconomyManager.isEnabled() && Settings.ADD_TIME_WITH_ECONOMY.getBoolean()) { - String itemName = plugin.getLocale().getMessage("interface.button.addtimewitheconomy").getMessage(); - String itemLore = plugin.getLocale().getMessage("interface.button.addtimewitheconomylore") + String itemName = this.plugin.getLocale().getMessage("interface.button.addtimewitheconomy").getMessage(); + String itemLore = this.plugin.getLocale().getMessage("interface.button.addtimewitheconomylore") // EconomyManager#formatEconomy adds its own prefix/suffix .processPlaceholder("cost", EconomyManager.formatEconomy(Settings.ECONOMY_COST.getDouble())) .getMessage(); setButton(15, - GuiUtils.createButtonItem(Settings.ECO_ICON.getMaterial(CompatibleMaterial.SUNFLOWER), itemName, itemLore), - event -> buyTime(anchor, event.player, true)); + GuiUtils.createButtonItem(Settings.ECO_ICON.getMaterial(XMaterial.SUNFLOWER), itemName, itemLore), + event -> buyTime(this.anchor, event.player, true)); } } @@ -84,7 +84,7 @@ public class AnchorGui extends Gui { if (success) { anchor.addTicksLeft(20 * 60 * 30); // 30 minutes - p.playSound(p.getLocation(), CompatibleSound.ENTITY_PLAYER_LEVELUP.getSound(), 0.6F, 15); + XSound.ENTITY_PLAYER_LEVELUP.play(p, .6f, 15); CompatibleParticleHandler.spawnParticles(CompatibleParticleHandler.ParticleType.getParticle(Settings.PARTICLE_UPGRADE.getString()), anchor.getLocation().add(.5, .5, .5), 100, .5, .5, .5); } else { @@ -112,7 +112,7 @@ public class AnchorGui extends Gui { ChatColor.GRAY + TimeUtils.makeReadable((long) ((anchor.getTicksLeft() / 20.0) * 1000)) + " remaining."; gui.setItem(13, GuiUtils.createButtonItem(plugin.getAnchorManager().createAnchorItem( - anchor.getTicksLeft(), anchor.getLocation().getBlock().getType()), + anchor.getTicksLeft(), anchor.getLocation().getBlock().getType()), itemName, itemLore)); } diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/guis/DestroyConfirmationGui.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/guis/DestroyConfirmationGui.java new file mode 100644 index 0000000..f987fe1 --- /dev/null +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/guis/DestroyConfirmationGui.java @@ -0,0 +1,64 @@ +package com.craftaro.epicanchors.guis; + +import com.craftaro.core.gui.Gui; +import com.craftaro.core.gui.GuiUtils; +import com.craftaro.core.gui.methods.Closable; +import com.craftaro.core.utils.TextUtils; +import com.craftaro.epicanchors.EpicAnchors; +import com.craftaro.epicanchors.api.Anchor; +import com.craftaro.epicanchors.files.Settings; +import com.craftaro.epicanchors.utils.Callback; +import com.craftaro.third_party.com.cryptomorin.xseries.XMaterial; + +public class DestroyConfirmationGui extends Gui { + private final EpicAnchors plugin; + private final Anchor anchor; + + private Callback handler; + + public DestroyConfirmationGui(EpicAnchors plugin, Anchor anchor, Callback callback) { + this.plugin = plugin; + this.anchor = anchor; + + this.handler = (ex, result) -> { + this.handler = null; + this.close(); + + callback.accept(ex, result); + }; + + this.setRows(3); + this.setTitle(TextUtils.formatText(plugin.getLocale().getMessage("interface.anchor.title").getMessage())); + + constructGUI(); + AnchorGui.runPreparedGuiTask(this.plugin, this, this.anchor); + + Closable currClosable = this.closer; + this.closer = event -> { + currClosable.onClose(event); + + if (this.handler != null) { + this.handler.accept(null, false); + } + }; + } + + private void constructGUI() { + AnchorGui.prepareGui(this.plugin, this, this.anchor); + + String cancelLore = this.plugin.getLocale().getMessage("interface.button.cancelDestroyLore").getMessage(); + String confirmLore = this.plugin.getLocale().getMessage("interface.button." + + (Settings.ALLOW_ANCHOR_BREAKING.getBoolean() ? "confirmDestroyLore" : "confirmDestroyLoreNoDrops")) + .getMessage(); + + setButton(11, GuiUtils.createButtonItem(XMaterial.RED_TERRACOTTA, + this.plugin.getLocale().getMessage("interface.button.cancelDestroy").getMessage(), + cancelLore.isEmpty() ? new String[0] : new String[]{cancelLore}), + event -> this.handler.accept(null, false)); + + setButton(15, GuiUtils.createButtonItem(XMaterial.GREEN_TERRACOTTA, + this.plugin.getLocale().getMessage("interface.button.confirmDestroy").getMessage(), + confirmLore.isEmpty() ? new String[0] : new String[]{confirmLore}), + event -> this.handler.accept(null, true)); + } +} diff --git a/src/main/java/com/songoda/epicanchors/listener/AnchorListener.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/AnchorListener.java similarity index 70% rename from src/main/java/com/songoda/epicanchors/listener/AnchorListener.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/AnchorListener.java index 543fc53..184d940 100644 --- a/src/main/java/com/songoda/epicanchors/listener/AnchorListener.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/AnchorListener.java @@ -1,15 +1,15 @@ -package com.songoda.epicanchors.listener; +package com.craftaro.epicanchors.listener; -import com.songoda.core.compatibility.CompatibleHand; -import com.songoda.core.compatibility.CompatibleParticleHandler; -import com.songoda.core.compatibility.CompatibleSound; -import com.songoda.epicanchors.Anchor; -import com.songoda.epicanchors.AnchorManager; -import com.songoda.epicanchors.EpicAnchors; -import com.songoda.epicanchors.files.Settings; -import com.songoda.epicanchors.guis.AnchorGui; -import com.songoda.epicanchors.guis.DestroyConfirmationGui; -import com.songoda.epicanchors.utils.Utils; +import com.craftaro.core.compatibility.CompatibleHand; +import com.craftaro.core.compatibility.CompatibleParticleHandler; +import com.craftaro.epicanchors.AnchorManagerImpl; +import com.craftaro.epicanchors.EpicAnchors; +import com.craftaro.epicanchors.api.Anchor; +import com.craftaro.epicanchors.files.Settings; +import com.craftaro.epicanchors.guis.AnchorGui; +import com.craftaro.epicanchors.guis.DestroyConfirmationGui; +import com.craftaro.epicanchors.utils.Utils; +import com.craftaro.third_party.com.cryptomorin.xseries.XSound; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Material; @@ -36,30 +36,30 @@ public class AnchorListener implements Listener { if (item.hasItemMeta() && item.getItemMeta().hasDisplayName() && - Settings.MATERIAL.getMaterial().getMaterial() == e.getBlock().getType()) { - if (!plugin.getAnchorManager().isReady(e.getBlock().getWorld())) { + Settings.MATERIAL.getMaterial().parseMaterial() == e.getBlock().getType()) { + if (!this.plugin.getAnchorManager().isReady(e.getBlock().getWorld())) { e.setCancelled(true); e.getPlayer().sendMessage("Anchors are still being initialized - Please wait a moment"); // TODO } else { - int ticksLeft = AnchorManager.getTicksFromItem(item); + int ticksLeft = AnchorManagerImpl.getTicksFromItem(item); if (ticksLeft != 0) { boolean dropOnErr = e.getPlayer().getGameMode() != GameMode.CREATIVE; - plugin.getAnchorManager().createAnchor(e.getBlock().getLocation(), e.getPlayer().getUniqueId(), ticksLeft, + this.plugin.getAnchorManager().createAnchor(e.getBlock().getLocation(), e.getPlayer().getUniqueId(), ticksLeft, (ex, result) -> { if (ex != null) { - Utils.logException(this.plugin, ex, "SQLite"); + Utils.logException(this.plugin, ex, "H2"); e.getPlayer().sendMessage("Error creating anchor!"); // TODO Bukkit.getScheduler().runTask(this.plugin, () -> { - if (Settings.MATERIAL.getMaterial().getMaterial() == e.getBlock().getType()) { + if (Settings.MATERIAL.getMaterial().parseMaterial() == e.getBlock().getType()) { e.getBlock().setType(Material.AIR); } if (dropOnErr) { e.getBlock().getWorld().dropItemNaturally(e.getBlock().getLocation(), - plugin.getAnchorManager().createAnchorItem(ticksLeft, item.getType())); + this.plugin.getAnchorManager().createAnchorItem(ticksLeft, item.getType())); } }); } @@ -72,16 +72,16 @@ public class AnchorListener implements Listener { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onBlockInteract(PlayerInteractEvent e) { if (e.getClickedBlock() == null || - !plugin.getAnchorManager().isReady(e.getClickedBlock().getWorld())) return; + !this.plugin.getAnchorManager().isReady(e.getClickedBlock().getWorld())) return; Player p = e.getPlayer(); - Anchor anchor = plugin.getAnchorManager().getAnchor(e.getClickedBlock()); + Anchor anchor = this.plugin.getAnchorManager().getAnchor(e.getClickedBlock()); if (anchor != null) { e.setCancelled(true); if (p.hasPermission("EpicAnchors.admin") || - this.plugin.getAnchorManager().hasAccess(anchor, p)) { + this.plugin.getAnchorManager().hasAccess(anchor, p.getUniqueId())) { if (e.getAction() == Action.LEFT_CLICK_BLOCK) { // Destroy anchor this.plugin.getGuiManager().showGUI(e.getPlayer(), new DestroyConfirmationGui(this.plugin, anchor, (ex, result) -> { @@ -90,13 +90,13 @@ public class AnchorListener implements Listener { Bukkit.getPluginManager().callEvent(blockBreakEvent); if (!blockBreakEvent.isCancelled()) { - plugin.getAnchorManager().destroyAnchor(anchor); + this.plugin.getAnchorManager().destroyAnchor(anchor); } } })); } else if (e.getAction() == Action.RIGHT_CLICK_BLOCK) { // Manage anchor ItemStack item = CompatibleHand.MAIN_HAND.getItem(e.getPlayer()); - int itemTicks = AnchorManager.getTicksFromItem(item); + int itemTicks = AnchorManagerImpl.getTicksFromItem(item); if (itemTicks != 0) { if (!anchor.isInfinite()) { @@ -110,16 +110,16 @@ public class AnchorListener implements Listener { CompatibleHand.MAIN_HAND.takeItem(p, 1); } - p.playSound(p.getLocation(), CompatibleSound.ENTITY_PLAYER_LEVELUP.getSound(), .6F, 15); + XSound.ENTITY_PLAYER_LEVELUP.play(p, .6f, 15); CompatibleParticleHandler.spawnParticles(CompatibleParticleHandler.ParticleType.getParticle(Settings.PARTICLE_UPGRADE.getString()), anchor.getLocation().add(.5, .5, .5), 100, .5, .5, .5); } } else { - plugin.getGuiManager().showGUI(p, new AnchorGui(plugin, anchor)); + this.plugin.getGuiManager().showGUI(p, new AnchorGui(this.plugin, anchor)); } } } else { - plugin.getLocale().getMessage("event.general.nopermission").sendMessage(p); + this.plugin.getLocale().getMessage("event.general.nopermission").sendMessage(p); } } } diff --git a/src/main/java/com/songoda/epicanchors/listener/BlockListener.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/BlockListener.java similarity index 81% rename from src/main/java/com/songoda/epicanchors/listener/BlockListener.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/BlockListener.java index fb0ab77..0b34ea3 100644 --- a/src/main/java/com/songoda/epicanchors/listener/BlockListener.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/BlockListener.java @@ -1,6 +1,6 @@ -package com.songoda.epicanchors.listener; +package com.craftaro.epicanchors.listener; -import com.songoda.epicanchors.AnchorManager; +import com.craftaro.epicanchors.api.AnchorManager; import org.bukkit.block.Block; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -22,7 +22,7 @@ public class BlockListener implements Listener { private void onBlockBurn(BlockBurnEvent e) { if (!this.manager.isReady(e.getBlock().getWorld())) return; - if (manager.isAnchor(e.getBlock())) { + if (this.manager.isAnchor(e.getBlock())) { e.setCancelled(true); } } @@ -31,7 +31,7 @@ public class BlockListener implements Listener { private void onBlockPiston(BlockPistonExtendEvent e) { if (!this.manager.isReady(e.getBlock().getWorld())) return; - if (manager.isAnchor(e.getBlock())) { + if (this.manager.isAnchor(e.getBlock())) { e.setCancelled(true); } } @@ -40,7 +40,7 @@ public class BlockListener implements Listener { private void onBlockPiston(BlockPistonRetractEvent e) { if (!this.manager.isReady(e.getBlock().getWorld())) return; - if (manager.isAnchor(e.getBlock())) { + if (this.manager.isAnchor(e.getBlock())) { e.setCancelled(true); } } @@ -49,7 +49,7 @@ public class BlockListener implements Listener { private void onBlockPhysics(BlockPhysicsEvent e) { if (!this.manager.isReady(e.getBlock().getWorld())) return; - if (manager.isAnchor(e.getBlock())) { + if (this.manager.isAnchor(e.getBlock())) { e.setCancelled(true); } } @@ -58,7 +58,7 @@ public class BlockListener implements Listener { private void onBlockPiston(LeavesDecayEvent e) { if (!this.manager.isReady(e.getBlock().getWorld())) return; - if (manager.isAnchor(e.getBlock())) { + if (this.manager.isAnchor(e.getBlock())) { e.setCancelled(true); } } @@ -67,8 +67,8 @@ public class BlockListener implements Listener { public void onPortalCreation(PortalCreateEvent e) { if (!this.manager.isReady(e.getWorld())) return; - for (Block b : e.getBlocks()) { - if (manager.isAnchor(b)) { + for (Block block : e.getBlocks()) { + if (this.manager.isAnchor(block)) { e.setCancelled(true); break; } diff --git a/src/main/java/com/songoda/epicanchors/listener/DebugListener.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/DebugListener.java similarity index 90% rename from src/main/java/com/songoda/epicanchors/listener/DebugListener.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/DebugListener.java index b1f5b90..c5973a2 100644 --- a/src/main/java/com/songoda/epicanchors/listener/DebugListener.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/DebugListener.java @@ -1,6 +1,6 @@ -package com.songoda.epicanchors.listener; +package com.craftaro.epicanchors.listener; -import com.songoda.epicanchors.EpicAnchors; +import com.craftaro.epicanchors.EpicAnchors; import org.apache.commons.lang.WordUtils; import org.bukkit.Chunk; import org.bukkit.Location; @@ -83,22 +83,22 @@ public class DebugListener implements Listener { if (e.isSneaking()) { e.getPlayer().sendMessage("§e§lEntities"); for (Entity entity : chunk.getEntities()) { - count.compute(entity.getType().name(), (k, v) -> v == null ? 1 : v + 1); + count.compute(entity.getType().name(), (key, value) -> value == null ? 1 : value + 1); } } else { e.getPlayer().sendMessage("§e§lTileEntities"); for (BlockState blockState : chunk.getTileEntities()) { - count.compute(blockState.getType().name(), (k, v) -> v == null ? 1 : v + 1); + count.compute(blockState.getType().name(), (key, value) -> value == null ? 1 : value + 1); } } - Map m = count.entrySet().stream() + Map sortedEntitiyCount = count.entrySet() + .stream() .sorted(Map.Entry.comparingByValue().reversed()) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, - (e1, e2) -> e1, LinkedHashMap::new)); + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); - for (Map.Entry entry : m.entrySet()) { - String entityName = WordUtils.capitalize(entry.getKey().toLowerCase(), new char[] {'_'}).replace("_", ""); + for (Map.Entry entry : sortedEntitiyCount.entrySet()) { + String entityName = WordUtils.capitalize(entry.getKey().toLowerCase(), new char[]{'_'}).replace("_", ""); e.getPlayer().sendMessage("§a" + entityName + "§7:§r " + entry.getValue()); } diff --git a/src/main/java/com/songoda/epicanchors/listener/WorldListener.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/WorldListener.java similarity index 85% rename from src/main/java/com/songoda/epicanchors/listener/WorldListener.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/WorldListener.java index 8e389ab..7dc1e0b 100644 --- a/src/main/java/com/songoda/epicanchors/listener/WorldListener.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/listener/WorldListener.java @@ -1,4 +1,4 @@ -package com.songoda.epicanchors.listener; +package com.craftaro.epicanchors.listener; import org.bukkit.World; import org.bukkit.event.EventHandler; @@ -20,11 +20,11 @@ public class WorldListener implements Listener { @EventHandler(priority = EventPriority.MONITOR) private void onWorldLoad(WorldLoadEvent e) { - initAnchorsInWorld.accept(e.getWorld()); + this.initAnchorsInWorld.accept(e.getWorld()); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) private void onWorldUnload(WorldUnloadEvent e) { - deInitAnchorsInWorld.accept(e.getWorld()); + this.deInitAnchorsInWorld.accept(e.getWorld()); } } diff --git a/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/tasks/AnchorTask.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/tasks/AnchorTask.java new file mode 100644 index 0000000..ab3f794 --- /dev/null +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/tasks/AnchorTask.java @@ -0,0 +1,153 @@ +package com.craftaro.epicanchors.tasks; + +import com.craftaro.core.nms.Nms; +import com.craftaro.core.nms.UnsupportedServerVersionException; +import com.craftaro.epicanchors.EpicAnchors; +import com.craftaro.epicanchors.api.Anchor; +import com.craftaro.epicanchors.api.AnchorManager; +import com.craftaro.epicanchors.utils.Utils; +import com.craftaro.epicanchors.utils.WorldUtils; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; + +/** + * More information about what types of game ticks there are and what does what: https://minecraft.fandom.com/wiki/Tick + */ +public class AnchorTask extends BukkitRunnable { + private static final int TASK_INTERVAL = 3; + + private final EpicAnchors plugin; + private final AnchorManager anchorManager; + + private boolean randomTicksFailed; + private boolean spawnerTicksFailed; + + public AnchorTask(EpicAnchors plugin) { + this.plugin = plugin; + this.anchorManager = plugin.getAnchorManager(); + } + + public void startTask() { + runTaskTimer(this.plugin, TASK_INTERVAL, TASK_INTERVAL); + } + + @Override + public void run() { + try { + for (World world : Bukkit.getWorlds()) { + if (!this.anchorManager.isReady(world)) return; + + int randomTicksToDo = WorldUtils.getRandomTickSpeed(world) * TASK_INTERVAL; + + Set alreadyTicked = new HashSet<>(); + Anchor[] anchorsInWorld = this.anchorManager.getAnchors(world); + List toUpdateHolo = new ArrayList<>(anchorsInWorld.length); + + List chunksWithPlayers = getChunksWithPlayers(world); + for (Anchor anchor : anchorsInWorld) { + Chunk chunk = anchor.getChunk(); + + if (alreadyTicked.add(chunk)) { + // Having a chunk loaded takes care of entities and weather (https://minecraft.fandom.com/wiki/Tick#Chunk_tick) + loadChunk(chunk); + + executeTicksForInactiveSpawners(chunk); + + if (!chunksWithPlayers.contains(chunk)) { + executeRandomTick(chunk, randomTicksToDo); + } + } + + if (updateAnchorTimeLeftAndCheckIfHologramsNeedsUpdate(anchor)) { + toUpdateHolo.add(anchor); + } + } + + this.anchorManager.updateHolograms(toUpdateHolo); + } + } catch (Exception ex) { + Utils.logException(this.plugin, ex); + } + } + + private List getChunksWithPlayers(World world) { + List playersInWorld = world.getPlayers(); + + List chunksWithPlayers = new ArrayList<>(playersInWorld.size()); + for (Player p : playersInWorld) { + chunksWithPlayers.add(p.getLocation().getChunk()); + } + return chunksWithPlayers; + } + + private void loadChunk(Chunk chunk) { + if (chunk.isLoaded()) { + // Loading an already loaded chunk still fires the ChunkLoadEvent and might have a huge + // impact on performance if other plugins do not expect that either... + return; + } + + WorldUtils.loadAnchoredChunk(chunk, this.plugin); + } + + private void executeTicksForInactiveSpawners(Chunk chunk) { + if (this.spawnerTicksFailed) { + return; + } + + try { + Nms.getImplementations().getWorld().tickInactiveSpawners(chunk, TASK_INTERVAL); + } catch (UnsupportedServerVersionException | ReflectiveOperationException | IncompatibleClassChangeError ex) { + this.plugin.getLogger().log(Level.SEVERE, ex, + () -> "Failed to do spawner ticks on this server implementation(/version) - " + + "Skipping further spawner ticks."); + + this.spawnerTicksFailed = true; + } + } + + private void executeRandomTick(Chunk chunk, int randomTicks) { + if (this.randomTicksFailed) { + return; + } + + try { + Nms.getImplementations().getWorld().randomTickChunk(chunk, randomTicks); + } catch (UnsupportedServerVersionException | ReflectiveOperationException | IncompatibleClassChangeError ex) { + this.plugin.getLogger().log(Level.SEVERE, ex, + () -> "Failed to do random ticks on this server implementation(/version) - " + + "Skipping further random ticks."); + + this.randomTicksFailed = true; + } + } + + private boolean updateAnchorTimeLeftAndCheckIfHologramsNeedsUpdate(Anchor anchor) { + // TODO: Only update hologram if a player is nearby + // Simplify player location to chunks to potentially group players + // Use the server view distance to calculate minimum distance to count as not-nearby + + if (!anchor.isInfinite()) { + int ticksLeft = anchor.removeTicksLeft(TASK_INTERVAL); + + if (ticksLeft == 0) { + this.anchorManager.destroyAnchor(anchor); + } else { + return true; + } + } else { + return true; + } + + return false; + } +} diff --git a/src/main/java/com/songoda/epicanchors/tasks/VisualizeTask.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/tasks/VisualizeTask.java similarity index 76% rename from src/main/java/com/songoda/epicanchors/tasks/VisualizeTask.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/tasks/VisualizeTask.java index b0b1b0b..fa085b4 100644 --- a/src/main/java/com/songoda/epicanchors/tasks/VisualizeTask.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/tasks/VisualizeTask.java @@ -1,9 +1,9 @@ -package com.songoda.epicanchors.tasks; +package com.craftaro.epicanchors.tasks; -import com.songoda.core.compatibility.CompatibleParticleHandler; -import com.songoda.epicanchors.Anchor; -import com.songoda.epicanchors.EpicAnchors; -import com.songoda.epicanchors.files.Settings; +import com.craftaro.core.compatibility.CompatibleParticleHandler; +import com.craftaro.epicanchors.EpicAnchors; +import com.craftaro.epicanchors.api.Anchor; +import com.craftaro.epicanchors.files.Settings; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; @@ -30,7 +30,7 @@ public class VisualizeTask extends BukkitRunnable { } public void startTask() { - runTaskTimer(plugin, TASK_INTERVAL, TASK_INTERVAL); + runTaskTimer(this.plugin, TASK_INTERVAL, TASK_INTERVAL); } @Override @@ -55,10 +55,10 @@ public class VisualizeTask extends BukkitRunnable { Location pLoc = p.getLocation(); // start and stop chunk coordinates - int cxi = (pLoc.getBlockX() >> 4) - radius; - int cxn = cxi + radius * 2; - int czi = (pLoc.getBlockZ() >> 4) - radius; - int czn = czi + radius * 2; + int cxi = (pLoc.getBlockX() >> 4) - this.radius; + int cxn = cxi + this.radius * 2; + int czi = (pLoc.getBlockZ() >> 4) - this.radius; + int czn = czi + this.radius * 2; // loop through the chunks to find applicable ones for (int cx = cxi; cx < cxn; ++cx) { @@ -66,7 +66,7 @@ public class VisualizeTask extends BukkitRunnable { Chunk chunk = world.getChunkAt(cx, cz); if (loadedChunks.contains(chunk)) { - chunksToVisualize.computeIfAbsent(chunk, k -> new HashSet<>()) + chunksToVisualize.computeIfAbsent(chunk, key -> new HashSet<>()) .add(p); } } @@ -91,17 +91,17 @@ public class VisualizeTask extends BukkitRunnable { startY = maxY - 1; } - Block b = entry.getKey().getBlock(x, startY, z); + Block block = entry.getKey().getBlock(x, startY, z); for (int i = 0; i < 12; ++i) { - if (b.getType().isSolid()) break; + if (block.getType().isSolid()) break; - b = b.getRelative(BlockFace.DOWN); + block = block.getRelative(BlockFace.DOWN); } - if (!b.isEmpty() && !b.getRelative(BlockFace.UP).getType().isOccluding()) { + if (!block.isEmpty() && !block.getRelative(BlockFace.UP).getType().isOccluding()) { CompatibleParticleHandler.spawnParticles(particleType, - b.getLocation().add(.5, 1.5, .5), + block.getLocation().add(.5, 1.5, .5), 0, 0, 0, 0, 1, p); } } diff --git a/src/main/java/com/songoda/epicanchors/utils/ThreadSync.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/ThreadSync.java similarity index 59% rename from src/main/java/com/songoda/epicanchors/utils/ThreadSync.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/ThreadSync.java index cd24b20..8f5c73a 100644 --- a/src/main/java/com/songoda/epicanchors/utils/ThreadSync.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/ThreadSync.java @@ -1,4 +1,4 @@ -package com.songoda.epicanchors.utils; +package com.craftaro.epicanchors.utils; import java.util.concurrent.atomic.AtomicReference; @@ -7,10 +7,10 @@ public class ThreadSync { private final AtomicReference waiting = new AtomicReference<>(true); public void waitForRelease() { - synchronized (syncObj) { - while (waiting.get()) { + synchronized (this.syncObj) { + while (this.waiting.get()) { try { - syncObj.wait(); + this.syncObj.wait(); } catch (Exception ignore) { } } @@ -18,13 +18,13 @@ public class ThreadSync { } public void release() { - synchronized (syncObj) { - waiting.set(false); - syncObj.notifyAll(); + synchronized (this.syncObj) { + this.waiting.set(false); + this.syncObj.notifyAll(); } } public void reset() { - waiting.set(true); + this.waiting.set(true); } } diff --git a/src/main/java/com/songoda/epicanchors/utils/UpdateCallback.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/UpdateCallback.java similarity index 75% rename from src/main/java/com/songoda/epicanchors/utils/UpdateCallback.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/UpdateCallback.java index bd1a609..5a628dd 100644 --- a/src/main/java/com/songoda/epicanchors/utils/UpdateCallback.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/UpdateCallback.java @@ -1,4 +1,4 @@ -package com.songoda.epicanchors.utils; +package com.craftaro.epicanchors.utils; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/songoda/epicanchors/utils/Utils.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/Utils.java similarity index 97% rename from src/main/java/com/songoda/epicanchors/utils/Utils.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/Utils.java index 6549354..99988a4 100644 --- a/src/main/java/com/songoda/epicanchors/utils/Utils.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/Utils.java @@ -1,4 +1,4 @@ -package com.songoda.epicanchors.utils; +package com.craftaro.epicanchors.utils; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/com/songoda/epicanchors/utils/WorldUtils.java b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/WorldUtils.java similarity index 97% rename from src/main/java/com/songoda/epicanchors/utils/WorldUtils.java rename to EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/WorldUtils.java index 810ab31..6f7a537 100644 --- a/src/main/java/com/songoda/epicanchors/utils/WorldUtils.java +++ b/EpicAnchors-Plugin/src/main/java/com/craftaro/epicanchors/utils/WorldUtils.java @@ -1,4 +1,4 @@ -package com.songoda.epicanchors.utils; +package com.craftaro.epicanchors.utils; import org.bukkit.Chunk; import org.bukkit.World; diff --git a/src/main/resources/en_US.lang b/EpicAnchors-Plugin/src/main/resources/en_US.lang similarity index 100% rename from src/main/resources/en_US.lang rename to EpicAnchors-Plugin/src/main/resources/en_US.lang diff --git a/src/main/resources/plugin.yml b/EpicAnchors-Plugin/src/main/resources/plugin.yml similarity index 67% rename from src/main/resources/plugin.yml rename to EpicAnchors-Plugin/src/main/resources/plugin.yml index a5da9fe..b4d7bcb 100644 --- a/src/main/resources/plugin.yml +++ b/EpicAnchors-Plugin/src/main/resources/plugin.yml @@ -1,17 +1,18 @@ -name: ${project.name} -description: ${project.description} +name: ${project.parent.name} +description: ${project.parent.description} version: ${project.version} api-version: 1.13 -main: com.songoda.epicanchors.EpicAnchors +main: com.craftaro.epicanchors.EpicAnchors softdepend: - Holograms - HolographicDisplays - Vault + - DecentHolograms -author: Songoda +author: Craftaro authors: [ SpraxDev ] -website: ${project.url} +website: ${project.parent.url} commands: EpicAnchors: diff --git a/pom.xml b/pom.xml index b23df24..f9efe32 100644 --- a/pom.xml +++ b/pom.xml @@ -4,154 +4,63 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.songoda - EpicAnchors - 2.2.7 + com.craftaro + EpicAnchors-Parent + pom + 3.1.1 + + + + EpicAnchors-API + EpicAnchors-Plugin + EpicAnchors Allow your players to keep chunks loaded for a limited amount of time for a cost. - https://songoda.com/marketplace/product/31 + https://craftaro.com/marketplace/product/31 - 1.8 - 8 + 3.0.1-SNAPSHOT + + 8 + 1.8 + 1.8 UTF-8 - songoda_EpicAnchors - songoda https://sonarcloud.io ${project.groupId}:${project.artifactId} - https://support.songoda.com/servicedesk/customer/portal/3 - Jira Service Desk + https://discord.gg/craftaro + Discord server - https://github.com/songoda/EpicAnchors - scm:git:git:github.com/songoda/EpicAnchors.git + https://github.com/craftaro/EpicAnchors + scm:git:git://github.com/craftaro/EpicAnchors.git - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - - ${java.version} - ${java.version} - - ${java.release} - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.4.1 - - - - package - - - shade - - - - ${project.name}-${project.version} - - false - true - - - - com.songoda.core - com.songoda.epicanchors.core - - - - epicanchors.nms - com.songoda.epicanchors.nms - - - - - - *:* - - - META-INF/** - LICENSE - LICENSE.** - - - - - org.jetbrains:annotations - - ** - - - - - com.songoda:epicanchors-v* - - ** - - - - - - - - - - - - src/main/resources - true - - - - - spigotmc-repo - https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + craftaro-minecraft-plugins + https://repo.craftaro.com/repository/minecraft-plugins/ - songoda-public - https://repo.songoda.com/repository/public/ + SpigotMC + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - - org.spigotmc - spigot-api - 1.8-R0.1-SNAPSHOT - provided - - - - com.songoda - SongodaCore - 2.6.20 - compile - - org.jetbrains annotations - 24.0.1 - compile + 24.1.0 + provided diff --git a/src/main/java/com/songoda/epicanchors/files/migration/_1_InitialMigration.java b/src/main/java/com/songoda/epicanchors/files/migration/_1_InitialMigration.java deleted file mode 100644 index 2a6b88b..0000000 --- a/src/main/java/com/songoda/epicanchors/files/migration/_1_InitialMigration.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.songoda.epicanchors.files.migration; - -import com.songoda.core.database.DataMigration; -import com.songoda.epicanchors.files.DataManager; - -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; - -public class _1_InitialMigration extends DataMigration { - public _1_InitialMigration() { - super(1); - } - - @Override - public void migrate(Connection connection, String tablePrefix) throws SQLException { - try (Statement statement = connection.createStatement()) { - statement.execute("CREATE TABLE " + DataManager.getTableName(tablePrefix, "anchors") + "(" + - "id INTEGER NOT NULL," + - "world_name TEXT NOT NULL," + - "x INTEGER NOT NULL," + - "y INTEGER NOT NULL," + - "z INTEGER NOT NULL," + - "ticks_left INTEGER NOT NULL," + - "owner VARCHAR(36)," + - "PRIMARY KEY(id AUTOINCREMENT)" + - ");"); - } - } -} diff --git a/src/main/java/com/songoda/epicanchors/guis/DestroyConfirmationGui.java b/src/main/java/com/songoda/epicanchors/guis/DestroyConfirmationGui.java deleted file mode 100644 index 8eda9ac..0000000 --- a/src/main/java/com/songoda/epicanchors/guis/DestroyConfirmationGui.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.songoda.epicanchors.guis; - -import com.songoda.core.compatibility.CompatibleMaterial; -import com.songoda.core.gui.Gui; -import com.songoda.core.gui.GuiUtils; -import com.songoda.core.gui.methods.Closable; -import com.songoda.core.utils.TextUtils; -import com.songoda.epicanchors.Anchor; -import com.songoda.epicanchors.EpicAnchors; -import com.songoda.epicanchors.files.Settings; -import com.songoda.epicanchors.utils.Callback; - -public class DestroyConfirmationGui extends Gui { - private final EpicAnchors plugin; - private final Anchor anchor; - - private Callback handler; - - public DestroyConfirmationGui(EpicAnchors plugin, Anchor anchor, Callback callback) { - this.plugin = plugin; - this.anchor = anchor; - - this.handler = (ex, result) -> { - this.handler = null; - this.close(); - - callback.accept(ex, result); - }; - - this.setRows(3); - this.setTitle(TextUtils.formatText(plugin.getLocale().getMessage("interface.anchor.title").getMessage())); - - constructGUI(); - AnchorGui.runPreparedGuiTask(this.plugin, this, this.anchor); - - Closable currClosable = this.closer; - this.closer = event -> { - currClosable.onClose(event); - - if (this.handler != null) { - this.handler.accept(null, false); - } - }; - } - - private void constructGUI() { - AnchorGui.prepareGui(this.plugin, this, this.anchor); - - String cancelLore = plugin.getLocale().getMessage("interface.button.cancelDestroyLore").getMessage(); - String confirmLore = plugin.getLocale().getMessage("interface.button." + - (Settings.ALLOW_ANCHOR_BREAKING.getBoolean() ? "confirmDestroyLore" : "confirmDestroyLoreNoDrops")) - .getMessage(); - - setButton(11, GuiUtils.createButtonItem(CompatibleMaterial.RED_TERRACOTTA, - plugin.getLocale().getMessage("interface.button.cancelDestroy").getMessage(), - cancelLore.isEmpty() ? new String[0] : new String[] {cancelLore}), - event -> this.handler.accept(null, false)); - - setButton(15, GuiUtils.createButtonItem(CompatibleMaterial.GREEN_TERRACOTTA, - plugin.getLocale().getMessage("interface.button.confirmDestroy").getMessage(), - confirmLore.isEmpty() ? new String[0] : new String[] {confirmLore}), - event -> this.handler.accept(null, true)); - } -} diff --git a/src/main/java/com/songoda/epicanchors/tasks/AnchorTask.java b/src/main/java/com/songoda/epicanchors/tasks/AnchorTask.java deleted file mode 100644 index c7226f6..0000000 --- a/src/main/java/com/songoda/epicanchors/tasks/AnchorTask.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.songoda.epicanchors.tasks; - -import com.songoda.core.nms.NmsManager; -import com.songoda.epicanchors.Anchor; -import com.songoda.epicanchors.AnchorManager; -import com.songoda.epicanchors.EpicAnchors; -import com.songoda.epicanchors.utils.Utils; -import com.songoda.epicanchors.utils.WorldUtils; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.logging.Level; - -/** - * More information about what types of game ticks there are and what does what: https://minecraft.fandom.com/wiki/Tick - */ -public class AnchorTask extends BukkitRunnable { - private static final int TASK_INTERVAL = 3; - - private final EpicAnchors plugin; - private final AnchorManager anchorManager; - - private boolean randomTicksFailed; - private boolean spawnerTicksFailed; - - public AnchorTask(EpicAnchors plugin) { - this.plugin = plugin; - this.anchorManager = plugin.getAnchorManager(); - } - - public void startTask() { - runTaskTimer(this.plugin, TASK_INTERVAL, TASK_INTERVAL); - } - - @Override - public void run() { - try { - for (World world : Bukkit.getWorlds()) { - if (!this.anchorManager.isReady(world)) return; - - int randomTicks = WorldUtils.getRandomTickSpeed(world) * TASK_INTERVAL; - - Set alreadyTicked = new HashSet<>(); - Anchor[] anchorsInWorld = this.anchorManager.getAnchors(world); - List toUpdateHolo = new ArrayList<>(anchorsInWorld.length); - - // Skip all chunks with players in them - for (Player pInWorld : world.getPlayers()) { - alreadyTicked.add(pInWorld.getLocation().getChunk()); - } - - for (Anchor anchor : anchorsInWorld) { - Chunk chunk = anchor.getChunk(); - - // Tick the anchor's chunk (but not multiple times) - if (alreadyTicked.add(chunk)) { - // Having a chunk loaded takes care of entities and weather (https://minecraft.fandom.com/wiki/Tick#Chunk_tick) - if (!chunk.isLoaded()) { - // Loading an already loaded chunk still fires the ChunkLoadEvent and might have a huge - // impact on performance if other plugins do not expect that either... - - WorldUtils.loadAnchoredChunk(chunk, this.plugin); - } - - if (!randomTicksFailed) { - try { - NmsManager.getWorld().randomTickChunk(chunk, randomTicks); - } catch (ReflectiveOperationException ex) { - this.plugin.getLogger().log(Level.SEVERE, ex, - () -> "Failed to do random ticks on this server implementation(/version) - " + - "Skipping further random ticks."); - - randomTicksFailed = true; - } - } - - if (!spawnerTicksFailed) { - try { - NmsManager.getWorld().tickInactiveSpawners(chunk, TASK_INTERVAL); - } catch (ReflectiveOperationException ex) { - this.plugin.getLogger().log(Level.SEVERE, ex, - () -> "Failed to do spawner ticks on this server implementation(/version) - " + - "Skipping further spawner ticks."); - - spawnerTicksFailed = true; - } - } - } - - // TODO: Only update hologram if a player is nearby - // Simplify player location to chunks to potentially group players - // Use the server view distance to calculate minimum distance to count as not-nearby - - // Destroy anchors and queue hologram update - if (!anchor.isInfinite()) { - int ticksLeft = anchor.removeTicksLeft(3); - - if (ticksLeft == 0) { - this.anchorManager.destroyAnchor(anchor); - } else { - toUpdateHolo.add(anchor); - } - } else { - toUpdateHolo.add(anchor); - } - } - - // Update holograms on queued anchors - anchorManager.updateHolograms(toUpdateHolo); - } - } catch (Exception ex) { - Utils.logException(this.plugin, ex); - } - } -} diff --git a/src/main/java/com/songoda/epicanchors/utils/ReflectionUtils.java b/src/main/java/com/songoda/epicanchors/utils/ReflectionUtils.java deleted file mode 100644 index 2c3d452..0000000 --- a/src/main/java/com/songoda/epicanchors/utils/ReflectionUtils.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.songoda.epicanchors.utils; - -import java.lang.reflect.Field; - -public class ReflectionUtils { - private ReflectionUtils() { - throw new IllegalStateException("Utility class"); - } - - public static Object getFieldValue(Object instance, String fieldName) throws NoSuchFieldException, IllegalAccessException { - Field f = getField(instance, fieldName); - boolean accessible = f.isAccessible(); - - f.setAccessible(true); - - Object result = f.get(instance); - - f.setAccessible(accessible); - - return result; - } - - public static void setFieldValue(Object instance, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { - Field f = getField(instance, fieldName); - boolean accessible = f.isAccessible(); - - f.setAccessible(true); - - f.set(instance, value); - - f.setAccessible(accessible); - } - - private static Field getField(Object instance, String fieldName) throws NoSuchFieldException { - Field f = null; - - Class currClass = instance.getClass(); - do { - try { - f = currClass.getDeclaredField(fieldName); - } catch (NoSuchFieldException ex) { - currClass = currClass.getSuperclass(); - - if (currClass == null) { - throw ex; - } - } - } while (f == null); - - return f; - } -}