Merge branch 'development'

This commit is contained in:
Christian Koop 2024-03-24 11:16:50 +01:00
commit c9405d3809
No known key found for this signature in database
GPG Key ID: 89A8181384E010A3
45 changed files with 1185 additions and 1216 deletions

View File

@ -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

13
.github/FUNDING.yml vendored
View File

@ -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/+' ]

View File

@ -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

95
.github/workflows/build.yml vendored Normal file
View File

@ -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 }}

View File

@ -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

42
.github/workflows/sonarcloud.yml vendored Normal file
View File

@ -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 }}

11
.gitignore vendored
View File

@ -1,5 +1,10 @@
/target/
# JetBrains IDEs
## JetBrains IDEs
/.idea/
*.iml
## Maven
/**/target/
dependency-reduced-pom.xml
## Misc.
.DS_Store

69
EpicAnchors-API/pom.xml Normal file
View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.craftaro</groupId>
<artifactId>EpicAnchors-Parent</artifactId>
<version>3.1.1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>EpicAnchors-API</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<doclint>all,-missing</doclint>
<links>
<link>https://hub.spigotmc.org/javadocs/spigot/</link>
</links>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.craftaro</groupId>
<artifactId>CraftaroCore</artifactId>
<version>${craftaro.coreVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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<Anchor> searchAnchors(Location center, double searchRadius);
List<Anchor> 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<Anchor> 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.
* <br>
* Other plugins can grant access to other players (e.g. friends).
* <br>
* 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<Anchor> anchors);
}

View File

@ -1,4 +1,4 @@
package com.songoda.epicanchors.utils;
package com.craftaro.epicanchors.utils;
import org.jetbrains.annotations.Nullable;

109
EpicAnchors-Plugin/pom.xml Normal file
View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.craftaro</groupId>
<artifactId>EpicAnchors-Parent</artifactId>
<version>3.1.1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>EpicAnchors-Plugin</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>${project.parent.name}-${project.version}</finalName>
<shadedArtifactAttached>false</shadedArtifactAttached>
<useDependencyReducedPomInJar>true</useDependencyReducedPomInJar>
<minimizeJar>true</minimizeJar>
<relocations>
<relocation>
<pattern>com.craftaro.core</pattern>
<shadedPattern>com.craftaro.epicanchors.core</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/**</exclude>
<exclude>LICENSE</exclude>
<exclude>LICENSE.**</exclude>
</excludes>
</filter>
<filter>
<artifact>com.craftaro:CraftaroCore</artifact>
<excludeDefaults>false</excludeDefaults>
<includes>
<include>**/nms/v*/**</include>
</includes>
<excludes>
<exclude>**/third_party/org/apache/**</exclude>
<exclude>**/third_party/net/kyori/**</exclude>
<exclude>**/third_party/com/zaxxer/**</exclude>
<exclude>**/third_party/org/jooq/**</exclude>
<exclude>**/third_party/org/mariadb/**</exclude>
<exclude>**/third_party/com/h2database/**</exclude>
<exclude>**/third_party/org/h2/**</exclude>
<exclude>**/third_party/com/cryptomorin/**</exclude>
<exclude>**/third_party/org/reactivestreams/**</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>com.craftaro</groupId>
<artifactId>EpicAnchors-API</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.craftaro</groupId>
<artifactId>CraftaroCore</artifactId>
<version>${craftaro.coreVersion}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -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;
}

View File

@ -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<World, Set<Anchor>> anchors = new HashMap<>(3);
private final Set<Player> 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<Anchor> anchorSet : anchors.values()) {
for (Set<Anchor> 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<Anchor> set = anchors.get(world);
Set<Anchor> 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<Anchor> set = anchors.get(b.getWorld());
Location bLoc = block.getLocation();
Set<Anchor> 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<Anchor> set = anchors.get(chunk.getWorld());
Set<Anchor> 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<Anchor> searchAnchors(Location center, double searchRadius) {
return searchAnchors(center, searchRadius, false);
}
@Override
public List<Anchor> searchAnchors(Location center, double searchRadius, boolean ignoreHeight) {
List<Anchor> 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<Anchor> 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<Anchor> value : anchors.values()) {
for (Set<Anchor> 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.
* <br>
* Other plugins can grant access to other players (e.g. friends).
* <br>
* 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<Anchor> anchors) {
// are holograms enabled?
if (!Settings.HOLOGRAMS.getBoolean() || !HologramManager.getManager().isEnabled()) return;
@ -432,12 +396,12 @@ public class AnchorManager {
for (Anchor anchor : anchors) {
List<String> 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());
}
}

View File

@ -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);
}
}

View File

@ -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<String> onTab(CommandSender commandSender, String... strings) {
protected List<String> onTab(CommandSender sender, String... args) {
return Collections.emptyList();
}

View File

@ -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<String> onTab(CommandSender commandSender, String... args) {
protected List<String> onTab(CommandSender sender, String... args) {
if (args.length == 1) {
Set<String> players = new HashSet<>();

View File

@ -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;
}

View File

@ -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<String> onTab(CommandSender commandSender, String... strings) {
protected List<String> onTab(CommandSender sender, String... args) {
return Collections.emptyList();
}

View File

@ -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;

View File

@ -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<Boolean> 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<List<Anchor>> callback) {
List<Anchor> 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<Anchor> 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<AnchorMigration.LegacyAnchorEntry> anchorEntries, UpdateCallback callback) {
this.databaseConnector.connect((con) -> {
public void migrateAnchor(List<LegacyYamlAnchorsMigrator.LegacyAnchorEntry> 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<Anchor> 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");
}
}
}

View File

@ -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();
}
}

View File

@ -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];
}

View File

@ -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)" +
");");
}
}
}

View File

@ -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));
}

View File

@ -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<Boolean> handler;
public DestroyConfirmationGui(EpicAnchors plugin, Anchor anchor, Callback<Boolean> 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));
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}

View File

@ -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<String, Integer> m = count.entrySet().stream()
Map<String, Integer> sortedEntitiyCount = count.entrySet()
.stream()
.sorted(Map.Entry.<String, Integer>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<String, Integer> entry : m.entrySet()) {
String entityName = WordUtils.capitalize(entry.getKey().toLowerCase(), new char[] {'_'}).replace("_", "");
for (Map.Entry<String, Integer> entry : sortedEntitiyCount.entrySet()) {
String entityName = WordUtils.capitalize(entry.getKey().toLowerCase(), new char[]{'_'}).replace("_", "");
e.getPlayer().sendMessage("§a" + entityName + "§7:§r " + entry.getValue());
}

View File

@ -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());
}
}

View File

@ -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<Chunk> alreadyTicked = new HashSet<>();
Anchor[] anchorsInWorld = this.anchorManager.getAnchors(world);
List<Anchor> toUpdateHolo = new ArrayList<>(anchorsInWorld.length);
List<Chunk> 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<Chunk> getChunksWithPlayers(World world) {
List<Player> playersInWorld = world.getPlayers();
List<Chunk> 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;
}
}

View File

@ -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);
}
}

View File

@ -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<Boolean> 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);
}
}

View File

@ -1,4 +1,4 @@
package com.songoda.epicanchors.utils;
package com.craftaro.epicanchors.utils;
import org.jetbrains.annotations.Nullable;

View File

@ -1,4 +1,4 @@
package com.songoda.epicanchors.utils;
package com.craftaro.epicanchors.utils;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;

View File

@ -1,4 +1,4 @@
package com.songoda.epicanchors.utils;
package com.craftaro.epicanchors.utils;
import org.bukkit.Chunk;
import org.bukkit.World;

View File

@ -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:

143
pom.xml
View File

@ -4,154 +4,63 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.songoda</groupId>
<artifactId>EpicAnchors</artifactId>
<version>2.2.7</version>
<groupId>com.craftaro</groupId>
<artifactId>EpicAnchors-Parent</artifactId>
<packaging>pom</packaging>
<version>3.1.1</version>
<!-- Run 'mvn versions:set -DgenerateBackupPoms=false -DnewVersion=X.Y.Z-DEV' to update version recursively -->
<modules>
<module>EpicAnchors-API</module>
<module>EpicAnchors-Plugin</module>
</modules>
<name>EpicAnchors</name>
<description>Allow your players to keep chunks loaded for a limited amount of time for a cost.</description>
<url>https://songoda.com/marketplace/product/31</url>
<url>https://craftaro.com/marketplace/product/31</url>
<properties>
<java.version>1.8</java.version>
<java.release>8</java.release>
<craftaro.coreVersion>3.0.1-SNAPSHOT</craftaro.coreVersion>
<maven.compiler.release>8</maven.compiler.release>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<sonar.projectKey>songoda_EpicAnchors</sonar.projectKey>
<sonar.organization>songoda</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.moduleKey>${project.groupId}:${project.artifactId}</sonar.moduleKey>
</properties>
<issueManagement>
<url>https://support.songoda.com/servicedesk/customer/portal/3</url>
<system>Jira Service Desk</system>
<url>https://discord.gg/craftaro</url>
<system>Discord server</system>
</issueManagement>
<scm>
<url>https://github.com/songoda/EpicAnchors</url>
<connection>scm:git:git:github.com/songoda/EpicAnchors.git</connection>
<url>https://github.com/craftaro/EpicAnchors</url>
<connection>scm:git:git://github.com/craftaro/EpicAnchors.git</connection>
</scm>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<release>${java.release}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>${project.name}-${project.version}</finalName>
<createDependencyReducedPom>false</createDependencyReducedPom>
<minimizeJar>true</minimizeJar>
<relocations>
<relocation>
<pattern>com.songoda.core</pattern>
<shadedPattern>com.songoda.epicanchors.core</shadedPattern>
</relocation>
<relocation>
<pattern>epicanchors.nms</pattern>
<shadedPattern>com.songoda.epicanchors.nms</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/**</exclude>
<exclude>LICENSE</exclude>
<exclude>LICENSE.**</exclude>
</excludes>
</filter>
<filter>
<artifact>org.jetbrains:annotations</artifact>
<excludes>
<exclude>**</exclude>
</excludes>
</filter>
<filter>
<artifact>com.songoda:epicanchors-v*</artifact>
<includes>
<include>**</include>
</includes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<repositories>
<repository>
<id>spigotmc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
<id>craftaro-minecraft-plugins</id>
<url>https://repo.craftaro.com/repository/minecraft-plugins/</url>
</repository>
<repository>
<id>songoda-public</id>
<url>https://repo.songoda.com/repository/public/</url>
<id>SpigotMC</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore</artifactId>
<version>2.6.20</version>
<scope>compile</scope>
</dependency>
<!-- Dev dependencies -->
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.0.1</version>
<scope>compile</scope>
<version>24.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -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)" +
");");
}
}
}

View File

@ -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<Boolean> handler;
public DestroyConfirmationGui(EpicAnchors plugin, Anchor anchor, Callback<Boolean> 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));
}
}

View File

@ -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<Chunk> alreadyTicked = new HashSet<>();
Anchor[] anchorsInWorld = this.anchorManager.getAnchors(world);
List<Anchor> 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);
}
}
}

View File

@ -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;
}
}