Merge branch 'development'

This commit is contained in:
Christian Koop 2021-07-12 16:15:45 +02:00
commit d366d51820
No known key found for this signature in database
GPG Key ID: 89A8181384E010A3
49 changed files with 972 additions and 477 deletions

311
.editorconfig Normal file
View File

@ -0,0 +1,311 @@
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
# max_line_length = 120
tab_width = 4
trim_trailing_whitespace = true
ij_continuation_indent_size = 8
ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on
ij_formatter_tags_enabled = false
ij_smart_tabs = false
ij_visual_guides = none
ij_wrap_on_typing = false
[*.java]
ij_smart_tabs = true
ij_java_align_consecutive_assignments = false
ij_java_align_consecutive_variable_declarations = false
ij_java_align_group_field_declarations = false
ij_java_align_multiline_annotation_parameters = false
ij_java_align_multiline_array_initializer_expression = false
ij_java_align_multiline_assignment = false
ij_java_align_multiline_binary_operation = false
ij_java_align_multiline_chained_methods = false
ij_java_align_multiline_extends_list = false
ij_java_align_multiline_for = true
ij_java_align_multiline_method_parentheses = false
ij_java_align_multiline_parameters = true
ij_java_align_multiline_parameters_in_calls = false
ij_java_align_multiline_parenthesized_expression = false
ij_java_align_multiline_records = true
ij_java_align_multiline_resources = true
ij_java_align_multiline_ternary_operation = false
ij_java_align_multiline_text_blocks = false
ij_java_align_multiline_throws_list = false
ij_java_align_subsequent_simple_methods = false
ij_java_align_throws_keyword = false
ij_java_annotation_parameter_wrap = off
ij_java_array_initializer_new_line_after_left_brace = false
ij_java_array_initializer_right_brace_on_new_line = false
ij_java_array_initializer_wrap = off
ij_java_assert_statement_colon_on_next_line = false
ij_java_assert_statement_wrap = off
ij_java_assignment_wrap = off
ij_java_binary_operation_sign_on_next_line = false
ij_java_binary_operation_wrap = off
ij_java_blank_lines_after_anonymous_class_header = 0
ij_java_blank_lines_after_class_header = 0
ij_java_blank_lines_after_imports = 1
ij_java_blank_lines_after_package = 1
ij_java_blank_lines_around_class = 1
ij_java_blank_lines_around_field = 0
ij_java_blank_lines_around_field_in_interface = 0
ij_java_blank_lines_around_initializer = 1
ij_java_blank_lines_around_method = 1
ij_java_blank_lines_around_method_in_interface = 1
ij_java_blank_lines_before_class_end = 0
ij_java_blank_lines_before_imports = 1
ij_java_blank_lines_before_method_body = 0
ij_java_blank_lines_before_package = 0
ij_java_block_brace_style = end_of_line
ij_java_block_comment_at_first_column = true
ij_java_builder_methods = none
ij_java_call_parameters_new_line_after_left_paren = false
ij_java_call_parameters_right_paren_on_new_line = false
ij_java_call_parameters_wrap = off
ij_java_case_statement_on_separate_line = true
ij_java_catch_on_new_line = false
ij_java_class_annotation_wrap = split_into_lines
ij_java_class_brace_style = end_of_line
ij_java_class_count_to_use_import_on_demand = 15
ij_java_class_names_in_javadoc = 1
ij_java_do_not_indent_top_level_class_members = false
ij_java_do_not_wrap_after_single_annotation = false
ij_java_do_while_brace_force = never
ij_java_doc_add_blank_line_after_description = true
ij_java_doc_add_blank_line_after_param_comments = true
ij_java_doc_add_blank_line_after_return = true
ij_java_doc_add_p_tag_on_empty_lines = true
ij_java_doc_align_exception_comments = true
ij_java_doc_align_param_comments = true
ij_java_doc_do_not_wrap_if_one_line = true
ij_java_doc_enable_formatting = true
ij_java_doc_enable_leading_asterisks = true
ij_java_doc_indent_on_continuation = true
ij_java_doc_keep_empty_lines = true
ij_java_doc_keep_empty_parameter_tag = true
ij_java_doc_keep_empty_return_tag = true
ij_java_doc_keep_empty_throws_tag = true
ij_java_doc_keep_invalid_tags = true
ij_java_doc_param_description_on_new_line = false
ij_java_doc_preserve_line_breaks = false
ij_java_doc_use_throws_not_exception_tag = true
ij_java_else_on_new_line = false
ij_java_enum_constants_wrap = off
ij_java_extends_keyword_wrap = off
ij_java_extends_list_wrap = off
ij_java_field_annotation_wrap = split_into_lines
ij_java_finally_on_new_line = false
ij_java_for_brace_force = never
ij_java_for_statement_new_line_after_left_paren = false
ij_java_for_statement_right_paren_on_new_line = false
ij_java_for_statement_wrap = off
ij_java_generate_final_locals = false
ij_java_generate_final_parameters = false
ij_java_if_brace_force = never
ij_java_imports_layout = *, |, javax.**, java.**, |, $*
ij_java_indent_case_from_switch = true
ij_java_insert_inner_class_imports = false
ij_java_insert_override_annotation = true
ij_java_keep_blank_lines_before_right_brace = 0
ij_java_keep_blank_lines_between_package_declaration_and_header = 0
ij_java_keep_blank_lines_in_code = 1
ij_java_keep_blank_lines_in_declarations = 1
ij_java_keep_builder_methods_indents = false
ij_java_keep_control_statement_in_one_line = true
ij_java_keep_first_column_comment = true
ij_java_keep_indents_on_empty_lines = false
ij_java_keep_line_breaks = true
ij_java_keep_multiple_expressions_in_one_line = false
ij_java_keep_simple_blocks_in_one_line = false
ij_java_keep_simple_classes_in_one_line = true
ij_java_keep_simple_lambdas_in_one_line = true
ij_java_keep_simple_methods_in_one_line = true
ij_java_label_indent_absolute = false
ij_java_label_indent_size = 0
ij_java_lambda_brace_style = end_of_line
ij_java_layout_static_imports_separately = true
ij_java_line_comment_add_space = false
ij_java_line_comment_at_first_column = true
ij_java_method_annotation_wrap = split_into_lines
ij_java_method_brace_style = end_of_line
ij_java_method_call_chain_wrap = off
ij_java_method_parameters_new_line_after_left_paren = false
ij_java_method_parameters_right_paren_on_new_line = false
ij_java_method_parameters_wrap = off
ij_java_modifier_list_wrap = false
ij_java_names_count_to_use_import_on_demand = 9
ij_java_new_line_after_lparen_in_record_header = false
ij_java_packages_to_use_import_on_demand = _java.awt.*, _javax.swing.*
ij_java_parameter_annotation_wrap = off
ij_java_parentheses_expression_new_line_after_left_paren = false
ij_java_parentheses_expression_right_paren_on_new_line = false
ij_java_place_assignment_sign_on_next_line = false
ij_java_prefer_longer_names = true
ij_java_prefer_parameters_wrap = false
ij_java_record_components_wrap = normal
ij_java_repeat_synchronized = true
ij_java_replace_instanceof_and_cast = true
ij_java_replace_null_check = true
ij_java_replace_sum_lambda_with_method_ref = true
ij_java_resource_list_new_line_after_left_paren = false
ij_java_resource_list_right_paren_on_new_line = false
ij_java_resource_list_wrap = off
ij_java_rparen_on_new_line_in_record_header = false
ij_java_space_after_closing_angle_bracket_in_type_argument = false
ij_java_space_after_colon = true
ij_java_space_after_comma = true
ij_java_space_after_comma_in_type_arguments = true
ij_java_space_after_for_semicolon = true
ij_java_space_after_quest = true
ij_java_space_after_type_cast = true
ij_java_space_before_annotation_array_initializer_left_brace = false
ij_java_space_before_annotation_parameter_list = false
ij_java_space_before_array_initializer_left_brace = true
ij_java_space_before_catch_keyword = true
ij_java_space_before_catch_left_brace = true
ij_java_space_before_catch_parentheses = true
ij_java_space_before_class_left_brace = true
ij_java_space_before_colon = true
ij_java_space_before_colon_in_foreach = true
ij_java_space_before_comma = false
ij_java_space_before_do_left_brace = true
ij_java_space_before_else_keyword = true
ij_java_space_before_else_left_brace = true
ij_java_space_before_finally_keyword = true
ij_java_space_before_finally_left_brace = true
ij_java_space_before_for_left_brace = true
ij_java_space_before_for_parentheses = true
ij_java_space_before_for_semicolon = false
ij_java_space_before_if_left_brace = true
ij_java_space_before_if_parentheses = true
ij_java_space_before_method_call_parentheses = false
ij_java_space_before_method_left_brace = true
ij_java_space_before_method_parentheses = false
ij_java_space_before_opening_angle_bracket_in_type_parameter = false
ij_java_space_before_quest = true
ij_java_space_before_switch_left_brace = true
ij_java_space_before_switch_parentheses = true
ij_java_space_before_synchronized_left_brace = true
ij_java_space_before_synchronized_parentheses = true
ij_java_space_before_try_left_brace = true
ij_java_space_before_try_parentheses = true
ij_java_space_before_type_parameter_list = false
ij_java_space_before_while_keyword = true
ij_java_space_before_while_left_brace = true
ij_java_space_before_while_parentheses = true
ij_java_space_inside_one_line_enum_braces = false
ij_java_space_within_empty_array_initializer_braces = true
ij_java_space_within_empty_method_call_parentheses = false
ij_java_space_within_empty_method_parentheses = false
ij_java_spaces_around_additive_operators = true
ij_java_spaces_around_assignment_operators = true
ij_java_spaces_around_bitwise_operators = true
ij_java_spaces_around_equality_operators = true
ij_java_spaces_around_lambda_arrow = true
ij_java_spaces_around_logical_operators = true
ij_java_spaces_around_method_ref_dbl_colon = false
ij_java_spaces_around_multiplicative_operators = true
ij_java_spaces_around_relational_operators = true
ij_java_spaces_around_shift_operators = true
ij_java_spaces_around_type_bounds_in_type_parameters = true
ij_java_spaces_around_unary_operator = false
ij_java_spaces_within_angle_brackets = false
ij_java_spaces_within_annotation_parentheses = false
ij_java_spaces_within_array_initializer_braces = false
ij_java_spaces_within_braces = true
ij_java_spaces_within_brackets = false
ij_java_spaces_within_cast_parentheses = false
ij_java_spaces_within_catch_parentheses = false
ij_java_spaces_within_for_parentheses = false
ij_java_spaces_within_if_parentheses = false
ij_java_spaces_within_method_call_parentheses = false
ij_java_spaces_within_method_parentheses = false
ij_java_spaces_within_parentheses = false
ij_java_spaces_within_record_header = false
ij_java_spaces_within_switch_parentheses = false
ij_java_spaces_within_synchronized_parentheses = false
ij_java_spaces_within_try_parentheses = false
ij_java_spaces_within_while_parentheses = false
ij_java_special_else_if_treatment = true
ij_java_subclass_name_suffix = Impl
ij_java_ternary_operation_signs_on_next_line = false
ij_java_ternary_operation_wrap = off
ij_java_test_name_suffix = Test
ij_java_throws_keyword_wrap = off
ij_java_throws_list_wrap = off
ij_java_use_external_annotations = false
ij_java_use_fq_class_names = false
ij_java_use_relative_indents = false
ij_java_use_single_class_imports = true
ij_java_variable_annotation_wrap = off
ij_java_visibility = public
ij_java_while_brace_force = never
ij_java_while_on_new_line = false
ij_java_wrap_comments = false
ij_java_wrap_first_method_in_call_chain = false
ij_java_wrap_long_lines = false
[*.properties]
ij_properties_align_group_field_declarations = false
ij_properties_keep_blank_lines = false
ij_properties_key_value_delimiter = equals
ij_properties_spaces_around_key_value_delimiter = false
[.editorconfig]
ij_editorconfig_align_group_field_declarations = false
ij_editorconfig_space_after_colon = false
ij_editorconfig_space_after_comma = true
ij_editorconfig_space_before_colon = false
ij_editorconfig_space_before_comma = false
ij_editorconfig_spaces_around_assignment_operators = true
[{*.ant, *.fxml, *.jhm, *.jnlp, *.jrxml, *.pom, *.rng, *.tld, *.wsdl, *.xml, *.xsd, *.xsl, *.xslt, *.xul}]
ij_xml_align_attributes = true
ij_xml_align_text = false
ij_xml_attribute_wrap = normal
ij_xml_block_comment_at_first_column = true
ij_xml_keep_blank_lines = 2
ij_xml_keep_indents_on_empty_lines = false
ij_xml_keep_line_breaks = true
ij_xml_keep_line_breaks_in_text = true
ij_xml_keep_whitespaces = false
ij_xml_keep_whitespaces_around_cdata = preserve
ij_xml_keep_whitespaces_inside_cdata = false
ij_xml_line_comment_at_first_column = true
ij_xml_space_after_tag_name = false
ij_xml_space_around_equals_in_attribute = false
ij_xml_space_inside_empty_tag = false
ij_xml_text_wrap = normal
[{*.markdown, *.md}]
indent_size = 2
tab_width = 2
ij_markdown_force_one_space_after_blockquote_symbol = true
ij_markdown_force_one_space_after_header_symbol = true
ij_markdown_force_one_space_after_list_bullet = true
ij_markdown_force_one_space_between_words = true
ij_markdown_keep_indents_on_empty_lines = false
ij_markdown_max_lines_around_block_elements = 1
ij_markdown_max_lines_around_header = 1
ij_markdown_max_lines_between_paragraphs = 1
ij_markdown_min_lines_around_block_elements = 1
ij_markdown_min_lines_around_header = 1
ij_markdown_min_lines_between_paragraphs = 1
[{*.yaml, *.yml, *.lang}]
indent_size = 2
ij_yaml_align_values_properties = do_not_align
ij_yaml_autoinsert_sequence_marker = true
ij_yaml_block_mapping_on_new_line = false
ij_yaml_indent_sequence_value = true
ij_yaml_keep_indents_on_empty_lines = false
ij_yaml_keep_line_breaks = true
ij_yaml_sequence_on_new_line = false
ij_yaml_space_before_colon = false
ij_yaml_spaces_within_braces = true
ij_yaml_spaces_within_brackets = true

12
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: songoda
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

9
.gitignore vendored
View File

@ -1,4 +1,5 @@
\.idea
\target
EpicVouchers.iml
dependency-reduced-pom.xml
/target/
# JetBrains IDEs
/.idea/
*.iml

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>SPIGOT</platformType>
</autoDetectTypes>
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.spigotmc:spigot:1.13.2" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.spigotmc:spigot:1.14" level="project" />
<orderEntry type="library" name="Maven: com.songoda:songodaupdater:1" level="project" />
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.2" level="project" />
<orderEntry type="library" name="Maven: co.aikar:acf-bukkit:0.5.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: co.aikar:acf-core:0.5.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: co.aikar:Table:1.0.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: co.aikar:DelegatingMap:1.0.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: co.aikar:locales:1.0-SNAPSHOT" level="project" />
<orderEntry type="library" name="Maven: net.jodah:expiringmap:0.5.8" level="project" />
<orderEntry type="library" name="Maven: co.aikar:minecraft-timings:1.0.4" level="project" />
<orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" />
<orderEntry type="library" name="Maven: org.bstats:bstats-bukkit:1.4" level="project" />
</component>
</module>

View File

@ -6,4 +6,4 @@ The same distribution rights and limitations above shall similarly apply to any
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

222
README.md
View File

@ -1,97 +1,125 @@
<p align="center">
<img src="https://proxy.songoda.com/200/https://cdn2.songoda.com/products/epicvouchers/5EJsLZfmeHcwy9rIY0dAgnzqR4rL4iCKAEyjgjIk.png" alt="EpicVouchers" />
</p>
<h1 align="center">EpicVouchers</h1>
<p align="center">
<b>Create vouchers that players can claim for rewards with seemingly infinite possibilities. Customize your servers vouchers through an intuitive in-game editor.</b>
<p align="center">
<img alt="Discord" src="https://img.shields.io/discord/293212540723396608?color=7289DA&label=Discord&logo=discord&logoColor=7289DA&link=https://discord.gg/songoda"> <img alt="Patreon" src="https://img.shields.io/badge/-Support_on_Patreon-F96854.svg?logo=patreon&style=flat&logoColor=white&link=https://wwww.patreon.com/join/songoda"> <br/> <img alt="Latest" src="https://img.shields.io/badge/-ver_2.1.18-4078C0.svg?logo=github&style=flat&logoColor-white&color=blue&label=Latest&labelColor=black"> <img alt="quality" src="https://img.shields.io/codacy/grade/4123a753597e43c89a93df5bbfb353ee"> <img alt="Last Updated" src="https://img.shields.io/github/last-commit/songoda/EpicVouchers"> <br/> <img alt="Servers" src="https://img.shields.io/bstats/servers/4209"> <img alt="Maintained" src="https://img.shields.io/maintenance/yes/2020">
<br />
## Table of Contents
* [Introduction](#introduction)
* [Marketplace](#marketplace)
* [Documentation](#documentation)
* [Developers API](#developers-api)
* [Support](#support)
* [Suggestions](#suggestions)
## Introduction
EpicVouchers is simple to use voucher plugin, that gives you the ability to reward players automatically without needing to give them permission to a command or manually run a command on a player yourself. This plugin is perfect for cosmetic rewards, selling in-game ranks, crate and kit rewards, unique shop designs, etc. The plugin also features an in-game GUI that allows you to create, edit and delete vouchers without needing to configurate the files, or restart/reload the server to apply the changes. It's a perfect plugin for production servers, and gives you unlimited ways to reward your loyal players easily.
## Marketplace
You can visit [our marketplace](https://songoda.com/marketplace/product/epicvouchers-advanced-vouchers-by-gui.25) to download EpicVouchers as well as take a look at many other fantastic plugins which are sure to catch your eye.
## Documentation
You can find all the information about the plugin, including dependencies, commands, permissions, incompatible plugins on [our wiki](https://wiki.songoda.com/Epic_Vouchers). Feel free to also contribute to the wiki as a way to help others in the community with using the plugin.
## Developers API
Here is an example with built-in methods for developers that want to use the EpicVouchers API for their own resources. This is a pretty long example, so take that into consideration when looking at the example, but I am sure that you will understand the usage of it quickly.
```ruby
@EventHandler
public void redeemListener(VoucherRedeemEvent event) {
# Returns the player that redeemed the voucher.
Player player = event.getPlayer();
# Returns the name of the redeemed voucher.
String voucher = event.getVoucher();
# Returns the ItemStack of the redeemed voucher.
ItemStack item = event.getItem();
# Returns if the voucher was redeemed manual or not.
boolean manual = event.getManual();
# Returns if the event is cancelled or not.
boolean cancelled = event.isCancelled();
# Get a list of handlers for this event.
HandlerList handlers = event.getHandlers();
# Cancel the event with a boolean.
event.isCancelled(true);
}
@EventHandler
public void forceListener(ForceRedeemEvent event) {
# Returns the player that redeemed the voucher.
Player player = event.getPlayer();
# Returns the name of the redeemed voucher.
String voucher = event.getVoucher();
# Returns the amount of vouchers that were redeemed.
int amount = event.getAmount();
# Returns the sender that forced the players.
CommandSender sender = event.getSender();
# Returns if the event is cancelled or not.
boolean cancelled = event.isCancelled();
# Get a list of handlers for this event.
HandlerList handlers = event.getHandlers();
# Cancel the event with a boolean.
event.isCancelled(true);
}
@EventHandler
public void receiveListener(VoucherReceiveEvent event) {
# Returns the player that received the voucher.
Player player = event.getPlayer();
# Returns the name of the received voucher.
String voucher = event.getVoucher();
# Returns the ItemStack of the received voucher.
ItemStack item = event.getItem();
# Returns the amount of vouchers that were received.
int amount = event.getAmount();
# Returns the sender that gave the vouchers.
CommandSender sender = event.getSender();
# Returns if the event is cancelled or not.
boolean cancelled = event.isCancelled();
# Get a list of handlers for this event.
HandlerList handlers = event.getHandlers();
# Cancel the event with a boolean.
event.isCancelled(true);
}
```
## Support
If you encounter any issues while using the plugin, feel free to create a ticket on [our support desk](https://support.songoda.com).
## Suggestions
For suggestions about features you think should be added to the plugin to increase its functionality, feel free to create a thread over on [our feedback site](https://feedback.songoda.com).
<!--suppress HtmlDeprecatedAttribute -->
<div align="center">
<img alt="EpicVouchers" src="https://cdn2.songoda.com/products/epicvouchers/JXt9xdI2AsSKfhFeUgy8fY14pPUAwhLRxJE5zeet.gif">
# EpicVouchers
**Create vouchers that players can claim for rewards with seemingly infinite possibilities.**
**Customize your servers vouchers through an intuitive in-game editor.**
<!-- Shields -->
[![Discord](https://img.shields.io/discord/293212540723396608?color=7289DA&label=Discord&logo=discord&logoColor=7289DA)](https://discord.gg/songoda)
[![Patreon](https://img.shields.io/badge/-Support_on_Patreon-F96854.svg?logo=patreon&style=flat&logoColor=white)](https://www.patreon.com/join/songoda)
<br>
[![Latest version](https://img.shields.io/github/v/tag/songoda/EpicVouchers?include_prereleases&label=Latest&logo=github&labelColor=black)](https://songoda.com/marketplace/product/25)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=songoda_EpicVouchers&metric=alert_status)](https://sonarcloud.io/dashboard?id=songoda_EpicVouchers)
[![GitHub last commit](https://img.shields.io/github/last-commit/songoda/EpicVouchers?label=Last+commit)](https://github.com/songoda/EpicVouchers/commits)
<br>
[![bStats Servers](https://img.shields.io/bstats/servers/4209?label=Servers)](https://bstats.org/plugin/bukkit/EpicVouchers/4209)
</div>
## Table of Contents
* [Introduction](#introduction)
* [Marketplace](#marketplace)
* [Documentation](#documentation)
* [Developers API](#developers-api)
* [Support](#support)
* [Suggestions](#suggestions)
## Introduction
EpicVouchers is simple to use voucher plugin, that gives you the ability to reward players automatically without needing
to give them permission to a command or manually run a command on a player yourself. This plugin is perfect for cosmetic
rewards, selling in-game ranks, crate and kit rewards, unique shop designs, etc. The plugin also features an in-game GUI
that allows you to create, edit and delete vouchers without needing to configurate the files, or restart/reload the
server to apply the changes. It's a perfect plugin for production servers, and gives you unlimited ways to reward your
loyal players easily.
## Marketplace
You can visit [our marketplace](https://songoda.com/marketplace/product/25) to download EpicVouchers as well as take a
look at many other fantastic plugins which are sure to catch your eye.
## Documentation
You can find all the information about EpicAnchors, including dependencies, commands, permissions and incompatible
plugins on [our wiki](https://wiki.songoda.com/Epic_Vouchers).
Feel free to also contribute to the wiki as a way to help others in the community with using the plugin.
## Developers API
Here is an example with built-in methods for developers that want to use the EpicVouchers API for their own resources.
This is a pretty long example, so take that into consideration when looking at the example, but I am sure that you will
understand the usage of it quickly.
```java
public class VouchersExample implements Listener {
@EventHandler
public void onRedeem(VoucherRedeemEvent event) {
// Returns the player that redeemed the voucher.
Player player = event.getPlayer();
// Returns the name of the redeemed voucher.
String voucher = event.getVoucher();
// Returns the ItemStack of the redeemed voucher.
ItemStack item = event.getItem();
// Returns if the voucher was redeemed manual or not.
boolean manual = event.getManual();
// Returns if the event is cancelled or not.
boolean cancelled = event.isCancelled();
// Get a list of handlers for this event.
HandlerList handlers = event.getHandlers();
// Cancel the event with a boolean.
event.setCancelled(true);
}
@EventHandler
public void onForceRedeem(ForceRedeemEvent event) {
// Returns the player that redeemed the voucher.
Player player = event.getPlayer();
// Returns the name of the redeemed voucher.
String voucher = event.getVoucher();
// Returns the amount of vouchers that were redeemed.
int amount = event.getAmount();
// Returns the sender that forced the players.
CommandSender sender = event.getSender();
// Returns if the event is cancelled or not.
boolean cancelled = event.isCancelled();
// Get a list of handlers for this event.
HandlerList handlers = event.getHandlers();
// Cancel the event with a boolean.
event.setCancelled(true);
}
@EventHandler
public void onReceive(VoucherReceiveEvent event) {
// Returns the player that received the voucher.
Player player = event.getPlayer();
// Returns the name of the received voucher.
String voucher = event.getVoucher();
// Returns the ItemStack of the received voucher.
ItemStack item = event.getItem();
// Returns the amount of vouchers that were received.
int amount = event.getAmount();
// Returns the sender that gave the vouchers.
CommandSender sender = event.getSender();
// Returns if the event is cancelled or not.
boolean cancelled = event.isCancelled();
// Get a list of handlers for this event.
HandlerList handlers = event.getHandlers();
// Cancel the event with a boolean.
event.setCancelled(true);
}
}
```
## Support
If you encounter any issues while using the plugin, feel free to create a ticket
on [our support desk](https://support.songoda.com).
## Suggestions
For suggestions about features you think should be added to the plugin to increase its functionality, feel free to
create a thread over on [our feedback site](https://feedback.songoda.com).

View File

@ -1,20 +0,0 @@
Hey loves,
Thanks for downloading our plugin ^_^ In order to
run it you will need a plugin called arconix. It
basically takes a bunch of methods that we use all
over the place throughout our plugin lineup and
stores it in one place so we don't have to write
new code every time we need to get something simple
done. So make sure to stay up to date with the latest
updates for it.
Link to download:
https://gitlab.com/Songoda/Arconix/-/jobs/artifacts/master/download?job=build
If you need help you can always join our
discord in which is listed at the bottom of all of
our plugin pages.
Enjoy <3
Brianna & The Songoda Team.

68
pom.xml
View File

@ -1,47 +1,45 @@
<project xmlns="http://maven.apache.org/POM/4.0.0">
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.songoda</groupId>
<artifactId>EpicVouchers</artifactId>
<modelVersion>4.0.0</modelVersion>
<version>2.1.21</version>
<version>2.1.22a2</version>
<name>EpicVouchers</name>
<description>Enhance your server with awesome customizable vouchers with a lot of features.</description>
<url>https://songoda.com/marketplace/product/25</url>
<properties>
<java.version>1.8</java.version>
<java.release>8</java.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<defaultGoal>clean install</defaultGoal>
<finalName>EpicVouchers-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<file>${project.build.directory}/classes/plugin.yml</file>
<replacements>
<replacement>
<token>maven-version-number</token>
<value>${project.version}</value>
</replacement>
</replacements>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0-SNAPSHOT</version>
<executions>
<execution>
<id>shaded</id>
@ -49,14 +47,17 @@
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createDependencyReducedPom>false</createDependencyReducedPom>
<artifactSet>
<includes>
<include>com.songoda:SongodaCore</include>
</includes>
</artifactSet>
<filters>
<filter>
<artifact>*:*</artifact>
@ -67,6 +68,7 @@
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>com.songoda.core</pattern>
@ -78,6 +80,7 @@
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
@ -85,18 +88,21 @@
</resource>
</resources>
</build>
<pluginRepositories>
<pluginRepository>
<id>apache.snapshots</id>
<url>https://repository.apache.org/snapshots/</url>
</pluginRepository>
</pluginRepositories>
<repositories>
<repository>
<id>public</id>
<id>songoda-public</id>
<url>https://repo.songoda.com/repository/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
@ -104,16 +110,18 @@
<version>1.17</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.songoda</groupId>
<artifactId>SongodaCore</artifactId>
<version>LATEST</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@ -6,13 +6,22 @@ import com.songoda.core.commands.CommandManager;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.configuration.Config;
import com.songoda.core.gui.GuiManager;
import com.songoda.epicvouchers.commands.*;
import com.songoda.epicvouchers.commands.CommandEditor;
import com.songoda.epicvouchers.commands.CommandEpicVouchers;
import com.songoda.epicvouchers.commands.CommandForce;
import com.songoda.epicvouchers.commands.CommandForceAll;
import com.songoda.epicvouchers.commands.CommandGive;
import com.songoda.epicvouchers.commands.CommandGiveAll;
import com.songoda.epicvouchers.commands.CommandList;
import com.songoda.epicvouchers.commands.CommandReload;
import com.songoda.epicvouchers.handlers.Connections;
import com.songoda.epicvouchers.libraries.inventory.FastInv;
import com.songoda.epicvouchers.libraries.inventory.IconInv;
import com.songoda.epicvouchers.listeners.PlayerCommandListener;
import com.songoda.epicvouchers.listeners.PlayerInteractListener;
import com.songoda.epicvouchers.settings.Settings;
import com.songoda.epicvouchers.utils.Callback;
import com.songoda.epicvouchers.utils.ThreadSync;
import com.songoda.epicvouchers.voucher.CoolDownManager;
import com.songoda.epicvouchers.voucher.Voucher;
import com.songoda.epicvouchers.voucher.VoucherExecutor;
@ -23,11 +32,11 @@ import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.plugin.PluginManager;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class EpicVouchers extends SongodaPlugin {
private static EpicVouchers INSTANCE;
private final GuiManager guiManager = new GuiManager(this);
@ -37,7 +46,7 @@ public class EpicVouchers extends SongodaPlugin {
private Connections connections;
private CoolDownManager coolDowns;
private VoucherExecutor voucherExecutor;
private Config vouchersConfig = new Config(this, "vouchers.yml");
private final Config vouchersConfig = new Config(this, "vouchers.yml");
public static EpicVouchers getInstance() {
return INSTANCE;
@ -94,117 +103,169 @@ public class EpicVouchers extends SongodaPlugin {
@Override
public void onDataLoad() {
if (!new File(this.getDataFolder(), "vouchers.yml").exists())
if (!new File(this.getDataFolder(), "vouchers.yml").exists()) {
saveResource("vouchers.yml", false);
vouchersConfig.load();
}
synchronized (vouchersConfig) {
vouchersConfig.load();
}
loadVouchersFromFile();
connections.openMySQL();
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, this::saveVouchers, 6000, 6000);
// FIXME: Config system needs to be greatly redone and only write changes when changes were made - Maybe even split it into multiple smaler files
// Issue https://support.songoda.com/browse/SD-8155 has been hotfixed by writing changes to the file async and blocking the main thread when needed. This requires the use of `synchronized`
// and expects every modifying code to use it (thread-safety)
// Large vouchers.yml files cause huge performance problems otherwise...
// Example file for testing: https://support.songoda.com/secure/attachment/17258/17258_vouchers.yml
Bukkit.getScheduler().scheduleSyncRepeatingTask(this,
() -> saveVouchersAsync(ex -> {
if (ex != null) {
ex.printStackTrace();
}
}), 5 * 60 * 20, 5 * 60 * 20); // 5 minutes
}
private void loadVouchersFromFile() {
voucherManager.clearVouchers();
synchronized (vouchersConfig) {
voucherManager.clearVouchers();
if (vouchersConfig.contains("vouchers")) {
for (String key : vouchersConfig.getConfigurationSection("vouchers").getKeys(false)) {
Voucher voucher = new Voucher(key, this);
ConfigurationSection cs = vouchersConfig.getConfigurationSection("vouchers." + key);
if (vouchersConfig.contains("vouchers")) {
for (String key : vouchersConfig.getConfigurationSection("vouchers").getKeys(false)) {
Voucher voucher = new Voucher(key, this);
ConfigurationSection cs = vouchersConfig.getConfigurationSection("vouchers." + key);
Material material;
String stringMaterial = cs.getString("material");
Material material;
String stringMaterial = cs.getString("material");
if (stringMaterial == null || stringMaterial.isEmpty()) {
material = Material.PAPER;
} else {
material = Material.matchMaterial(stringMaterial);
if (material == null) material = Material.PAPER;
if (stringMaterial == null || stringMaterial.isEmpty()) {
material = Material.PAPER;
} else {
material = Material.matchMaterial(stringMaterial);
if (material == null) material = Material.PAPER;
}
voucher.setPermission(cs.getString("permission", ""))
.setMaterial(material)
.setData((short) cs.getInt("data", 0))
.setName(cs.getString("name", "default"))
.setLore(cs.getStringList("lore"))
.setTexture(cs.getString("texture", ""))
.setGlow(cs.getBoolean("glow", false))
.setConfirm(cs.getBoolean("confirm", true))
.setUnbreakable(cs.getBoolean("unbreakable", false))
.setHideAttributes(cs.getBoolean("hide-attributes", false))
.setRemoveItem(cs.getBoolean("remove-item", true))
.setHealPlayer(cs.getBoolean("heal-player", false))
.setSmiteEffect(cs.getBoolean("smite-effect", false))
.setCoolDown(cs.getInt("coolDown", 0))
.setBroadcasts(cs.getStringList("broadcasts"))
.setMessages(cs.getStringList("messages"))
.setCommands(cs.getStringList("commands"))
.setActionBar(cs.getString("actionbar"))
.setTitle(cs.getString("titles.title"))
.setSubTitle(cs.getString("titles.subtitle"))
.setTitleFadeIn(cs.getInt("titles.fade-in", 0))
.setTitleStay(cs.getInt("titles.stay", 0))
.setTitleFadeOut(cs.getInt("titles.fade-out", 0))
.setSound(cs.getString("sounds.sound"))
.setSoundPitch(cs.getInt("sounds.pitch", 0))
.setParticle(cs.getString("particles.particle"))
.setParticleAmount(cs.getInt("particles.amount", 0))
.setEffect(cs.getString("effects.effect"))
.setEffectAmplifier(cs.getInt("effects.amplifier"))
.setItemStack(cs.getItemStack("itemstack", null));
voucherManager.addVoucher(voucher);
}
voucher.setPermission(cs.getString("permission", ""))
.setMaterial(material)
.setData((short) cs.getInt("data", 0))
.setName(cs.getString("name", "default"))
.setLore(cs.getStringList("lore"))
.setTexture(cs.getString("texture", ""))
.setGlow(cs.getBoolean("glow", false))
.setConfirm(cs.getBoolean("confirm", true))
.setUnbreakable(cs.getBoolean("unbreakable", false))
.setHideAttributes(cs.getBoolean("hide-attributes", false))
.setRemoveItem(cs.getBoolean("remove-item", true))
.setHealPlayer(cs.getBoolean("heal-player", false))
.setSmiteEffect(cs.getBoolean("smite-effect", false))
.setCoolDown(cs.getInt("coolDown", 0))
.setBroadcasts(cs.getStringList("broadcasts"))
.setMessages(cs.getStringList("messages"))
.setCommands(cs.getStringList("commands"))
.setActionBar(cs.getString("actionbar"))
.setTitle(cs.getString("titles.title"))
.setSubTitle(cs.getString("titles.subtitle"))
.setTitleFadeIn(cs.getInt("titles.fade-in", 0))
.setTitleStay(cs.getInt("titles.stay", 0))
.setTitleFadeOut(cs.getInt("titles.fade-out", 0))
.setSound(cs.getString("sounds.sound"))
.setSoundPitch(cs.getInt("sounds.pitch", 0))
.setParticle(cs.getString("particles.particle"))
.setParticleAmount(cs.getInt("particles.amount", 0))
.setEffect(cs.getString("effects.effect"))
.setEffectAmplifier(cs.getInt("effects.amplifier"))
.setItemStack(cs.getItemStack("itemstack", null));
voucherManager.addVoucher(voucher);
}
}
}
private void saveVouchers() {
for (String voucherName : vouchersConfig.getConfigurationSection("vouchers").getKeys(false)) {
if (voucherManager.getVouchers().stream().noneMatch(voucher -> voucher.getKey().equals(voucherName)))
vouchersConfig.set("vouchers." + voucherName, null);
}
ThreadSync tSync = new ThreadSync();
for (Voucher voucher : voucherManager.getVouchers()) {
String prefix = "vouchers." + voucher.getKey() + ".";
vouchersConfig.set(prefix + "permission", voucher.getPermission());
vouchersConfig.set(prefix + "material", voucher.getMaterial().name());
vouchersConfig.set(prefix + "data", voucher.getData());
vouchersConfig.set(prefix + "name", voucher.getName());
vouchersConfig.set(prefix + "lore", voucher.getLore());
vouchersConfig.set(prefix + "texture", voucher.getTexture());
vouchersConfig.set(prefix + "glow", voucher.isGlow());
vouchersConfig.set(prefix + "confirm", voucher.isConfirm());
vouchersConfig.set(prefix + "unbreakable", voucher.isUnbreakable());
vouchersConfig.set(prefix + "hide-attributes", voucher.isHideAttributes());
vouchersConfig.set(prefix + "remove-item", voucher.isRemoveItem());
vouchersConfig.set(prefix + "heal-player", voucher.isHealPlayer());
vouchersConfig.set(prefix + "smite-effect", voucher.isSmiteEffect());
vouchersConfig.set(prefix + "coolDown", voucher.getCoolDown());
vouchersConfig.set(prefix + "broadcasts", voucher.getBroadcasts());
vouchersConfig.set(prefix + "messages", voucher.getMessages());
vouchersConfig.set(prefix + "commands", voucher.getCommands());
vouchersConfig.set(prefix + "actionbar", voucher.getActionBar());
vouchersConfig.set(prefix + "titles.title", voucher.getTitle());
vouchersConfig.set(prefix + "titles.subtitle", voucher.getSubTitle());
vouchersConfig.set(prefix + "titles.fade-in", voucher.getTitleFadeIn());
vouchersConfig.set(prefix + "titles.stay", voucher.getTitleStay());
vouchersConfig.set(prefix + "titles.fade-out", voucher.getTitleFadeOut());
vouchersConfig.set(prefix + "sounds.sound", voucher.getSound());
vouchersConfig.set(prefix + "sounds.pitch", voucher.getSoundPitch());
vouchersConfig.set(prefix + "particles.particle", voucher.getParticle());
vouchersConfig.set(prefix + "particles.amount", voucher.getParticleAmount());
vouchersConfig.set(prefix + "effects.effect", voucher.getEffect());
vouchersConfig.set(prefix + "effects.amplifier", voucher.getEffectAmplifier());
vouchersConfig.set(prefix + "itemstack", voucher.getItemStack());
}
vouchersConfig.saveChanges();
saveVouchersAsync(ex -> {
if (ex != null) {
ex.printStackTrace();
}
tSync.release();
});
tSync.waitForRelease();
}
private void saveVouchersAsync(Callback callback) {
new Thread(() -> {
try {
synchronized (vouchersConfig) {
Collection<Voucher> voucherList = voucherManager.getVouchers();
ConfigurationSection cfgSec = vouchersConfig.getConfigurationSection("vouchers");
if (cfgSec != null) {
for (String voucherName : cfgSec.getKeys(false)) {
if (voucherList.stream().noneMatch(voucher -> voucher.getKey().equals(voucherName))) {
vouchersConfig.set("vouchers." + voucherName, null);
}
}
}
for (Voucher voucher : voucherList) {
String prefix = "vouchers." + voucher.getKey() + ".";
vouchersConfig.set(prefix + "permission", voucher.getPermission());
vouchersConfig.set(prefix + "material", voucher.getMaterial().name());
vouchersConfig.set(prefix + "data", voucher.getData());
vouchersConfig.set(prefix + "name", voucher.getName());
vouchersConfig.set(prefix + "lore", voucher.getLore());
vouchersConfig.set(prefix + "texture", voucher.getTexture());
vouchersConfig.set(prefix + "glow", voucher.isGlow());
vouchersConfig.set(prefix + "confirm", voucher.isConfirm());
vouchersConfig.set(prefix + "unbreakable", voucher.isUnbreakable());
vouchersConfig.set(prefix + "hide-attributes", voucher.isHideAttributes());
vouchersConfig.set(prefix + "remove-item", voucher.isRemoveItem());
vouchersConfig.set(prefix + "heal-player", voucher.isHealPlayer());
vouchersConfig.set(prefix + "smite-effect", voucher.isSmiteEffect());
vouchersConfig.set(prefix + "coolDown", voucher.getCoolDown());
vouchersConfig.set(prefix + "broadcasts", voucher.getBroadcasts());
vouchersConfig.set(prefix + "messages", voucher.getMessages());
vouchersConfig.set(prefix + "commands", voucher.getCommands());
vouchersConfig.set(prefix + "actionbar", voucher.getActionBar());
vouchersConfig.set(prefix + "titles.title", voucher.getTitle());
vouchersConfig.set(prefix + "titles.subtitle", voucher.getSubTitle());
vouchersConfig.set(prefix + "titles.fade-in", voucher.getTitleFadeIn());
vouchersConfig.set(prefix + "titles.stay", voucher.getTitleStay());
vouchersConfig.set(prefix + "titles.fade-out", voucher.getTitleFadeOut());
vouchersConfig.set(prefix + "sounds.sound", voucher.getSound());
vouchersConfig.set(prefix + "sounds.pitch", voucher.getSoundPitch());
vouchersConfig.set(prefix + "particles.particle", voucher.getParticle());
vouchersConfig.set(prefix + "particles.amount", voucher.getParticleAmount());
vouchersConfig.set(prefix + "effects.effect", voucher.getEffect());
vouchersConfig.set(prefix + "effects.amplifier", voucher.getEffectAmplifier());
vouchersConfig.set(prefix + "itemstack", voucher.getItemStack());
}
vouchersConfig.saveChanges();
callback.accept(null);
}
} catch (Exception ex) {
callback.accept(ex);
}
}, getName() + "-AsyncConfigSave").start();
}
@Override
public void onConfigReload() {
vouchersConfig.load();
synchronized (vouchersConfig) {
vouchersConfig.load();
}
loadVouchersFromFile();
this.setLocale(getConfig().getString("System.Language Mode"), true);
this.locale.reloadMessages();
}
@ -226,10 +287,6 @@ public class EpicVouchers extends SongodaPlugin {
return this.voucherExecutor;
}
public Config getVouchersConfig() {
return this.vouchersConfig;
}
public CommandManager getCommandManager() {
return commandManager;
}
@ -241,4 +298,4 @@ public class EpicVouchers extends SongodaPlugin {
public GuiManager getGuiManager() {
return guiManager;
}
}
}

View File

@ -9,7 +9,6 @@ import org.bukkit.entity.Player;
import java.util.List;
public class CommandEditor extends AbstractCommand {
final EpicVouchers instance;
public CommandEditor(EpicVouchers instance) {

View File

@ -8,7 +8,6 @@ import org.bukkit.command.CommandSender;
import java.util.List;
public class CommandEpicVouchers extends AbstractCommand {
final EpicVouchers instance;
public CommandEpicVouchers(EpicVouchers instance) {

View File

@ -5,17 +5,13 @@ import com.songoda.epicvouchers.EpicVouchers;
import com.songoda.epicvouchers.voucher.Voucher;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class CommandForce extends AbstractCommand {
final EpicVouchers instance;
public CommandForce(EpicVouchers instance) {
@ -51,14 +47,23 @@ public class CommandForce extends AbstractCommand {
@Override
protected List<String> onTab(CommandSender sender, String... args) {
List<String> result = new ArrayList<>();
if (args.length == 1) {
return Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName).collect(Collectors.toList());
for (Player online : Bukkit.getOnlinePlayers()) {
result.add(online.getName());
}
} else if (args.length == 2) {
return instance.getVoucherManager().getVouchers().stream().map(Voucher::getKey).collect(Collectors.toList());
for (Voucher voucher : instance.getVoucherManager().getVouchers()) {
result.add(voucher.getKey());
}
} else if (args.length == 3) {
return Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
for (int i = 0; i < 10; ++i) {
result.add(String.valueOf(i + 1));
}
}
return null;
return result;
}
@Override

View File

@ -7,12 +7,9 @@ import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class CommandForceAll extends AbstractCommand {
final EpicVouchers instance;
public CommandForceAll(EpicVouchers instance) {
@ -42,12 +39,19 @@ public class CommandForceAll extends AbstractCommand {
@Override
protected List<String> onTab(CommandSender sender, String... args) {
List<String> result = new ArrayList<>();
if (args.length == 1) {
return instance.getVoucherManager().getVouchers().stream().map(Voucher::getKey).collect(Collectors.toList());
for (Voucher voucher : instance.getVoucherManager().getVouchers()) {
result.add(voucher.getKey());
}
} else if (args.length == 2) {
return Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
for (int i = 0; i < 10; ++i) {
result.add(String.valueOf(i + 1));
}
}
return null;
return result;
}
@Override

View File

@ -2,21 +2,16 @@ package com.songoda.epicvouchers.commands;
import com.songoda.core.commands.AbstractCommand;
import com.songoda.epicvouchers.EpicVouchers;
import com.songoda.epicvouchers.menus.VoucherMenu;
import com.songoda.epicvouchers.voucher.Voucher;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class CommandGive extends AbstractCommand {
final EpicVouchers instance;
public CommandGive(EpicVouchers instance) {
@ -47,14 +42,23 @@ public class CommandGive extends AbstractCommand {
@Override
protected List<String> onTab(CommandSender sender, String... args) {
List<String> result = new ArrayList<>();
if (args.length == 1) {
return Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName).collect(Collectors.toList());
for (Player online : Bukkit.getOnlinePlayers()) {
result.add(online.getName());
}
} else if (args.length == 2) {
return instance.getVoucherManager().getVouchers().stream().map(Voucher::getKey).collect(Collectors.toList());
for (Voucher voucher : instance.getVoucherManager().getVouchers()) {
result.add(voucher.getKey());
}
} else if (args.length == 3) {
return Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
for (int i = 0; i < 10; ++i) {
result.add(String.valueOf(i + 1));
}
}
return null;
return result;
}
@Override

View File

@ -3,19 +3,12 @@ package com.songoda.epicvouchers.commands;
import com.songoda.core.commands.AbstractCommand;
import com.songoda.epicvouchers.EpicVouchers;
import com.songoda.epicvouchers.voucher.Voucher;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class CommandGiveAll extends AbstractCommand {
final EpicVouchers instance;
public CommandGiveAll(EpicVouchers instance) {
@ -40,12 +33,19 @@ public class CommandGiveAll extends AbstractCommand {
@Override
protected List<String> onTab(CommandSender sender, String... args) {
List<String> result = new ArrayList<>();
if (args.length == 1) {
return instance.getVoucherManager().getVouchers().stream().map(Voucher::getKey).collect(Collectors.toList());
for (Voucher voucher : instance.getVoucherManager().getVouchers()) {
result.add(voucher.getKey());
}
} else if (args.length == 2) {
return Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
for (int i = 0; i < 10; ++i) {
result.add(String.valueOf(i + 1));
}
}
return null;
return result;
}
@Override

View File

@ -2,16 +2,13 @@ package com.songoda.epicvouchers.commands;
import com.songoda.core.commands.AbstractCommand;
import com.songoda.epicvouchers.EpicVouchers;
import com.songoda.epicvouchers.menus.VoucherMenu;
import com.songoda.epicvouchers.voucher.Voucher;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.stream.Collectors;
import java.util.StringJoiner;
public class CommandList extends AbstractCommand {
final EpicVouchers instance;
public CommandList(EpicVouchers instance) {
@ -21,10 +18,15 @@ public class CommandList extends AbstractCommand {
@Override
protected ReturnType runCommand(CommandSender sender, String... args) {
StringJoiner joiner = new StringJoiner(", ");
for (Voucher voucher : instance.getVoucherManager().getVouchers()) {
joiner.add(voucher.getKey());
}
instance.getLocale().getMessage("command.list.list")
.processPlaceholder("list",
instance.getVoucherManager().getVouchers().stream().map(Voucher::getKey).collect(Collectors.joining(", ")))
.processPlaceholder("list", joiner.toString())
.sendPrefixedMessage(sender);
return ReturnType.SUCCESS;
}

View File

@ -7,7 +7,6 @@ import org.bukkit.command.CommandSender;
import java.util.List;
public class CommandReload extends AbstractCommand {
final EpicVouchers instance;
public CommandReload(EpicVouchers instance) {

View File

@ -7,7 +7,6 @@ import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class ForceRedeemEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Player player;
@ -48,6 +47,7 @@ public class ForceRedeemEvent extends Event implements Cancellable {
this.cancelled = cancelled;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
@ -55,5 +55,4 @@ public class ForceRedeemEvent extends Event implements Cancellable {
public static HandlerList getHandlerList() {
return handlers;
}
}
}

View File

@ -4,10 +4,13 @@ import com.songoda.core.utils.TextUtils;
import com.songoda.epicvouchers.EpicVouchers;
import org.bukkit.entity.Player;
import java.sql.*;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.Timestamp;
public class Connections {
private final EpicVouchers instance;
private Connection connection;
@ -26,7 +29,6 @@ public class Connections {
String mysqlUsername = instance.getConfig().getString("Database.Username");
String mysqlPassword = instance.getConfig().getString("Database.Password");
connection = DriverManager.getConnection("jdbc:mysql://" + mysqlIP + ":" + mysqlPort + "/" + mysqlDatabase + "?useSSL=true?autoReconnect=true", mysqlUsername, mysqlPassword);
System.out.println(TextUtils.formatText("&fSuccessfully created a connection with MySQL."));
} catch (Exception error) {
@ -66,5 +68,4 @@ public class Connections {
error.printStackTrace();
}
}
}
}

View File

@ -7,7 +7,11 @@ import org.bukkit.block.banner.Pattern;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.*;
import org.bukkit.inventory.meta.BannerMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
@ -18,13 +22,12 @@ import java.util.Set;
/**
* A complete {@link ItemStack} inventory for FastInv (only works on 1.8+).
*
* <p>
* The project is on <a href="https://github.com/MrMicky-FR/FastInv">GitHub</a>
*
* @author MrMicky
*/
public class ItemBuilder {
private final ItemStack item;
private ItemMeta meta;

View File

@ -4,7 +4,11 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.*;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
@ -25,13 +29,12 @@ import java.util.Set;
* @version 2.0.3 - Now supports async operations
*/
public class FastInv implements InventoryHolder {
private static Plugin plugin = null;
private boolean cancelTasksOnClose = true, cancelled = true;
private Set<FastInvCloseListener> closeListeners = new HashSet<>();
private Set<FastInvClickListener> clickListeners = new HashSet<>();
private Map<Integer, FastInvClickListener> itemListeners = new HashMap<>();
private Set<BukkitTask> tasks = new HashSet<>();
private final Set<FastInvCloseListener> closeListeners = new HashSet<>();
private final Set<FastInvClickListener> clickListeners = new HashSet<>();
private final Map<Integer, FastInvClickListener> itemListeners = new HashMap<>();
private final Set<BukkitTask> tasks = new HashSet<>();
private Inventory inventory;
/**
@ -67,6 +70,7 @@ public class FastInv implements InventoryHolder {
*
* @param type The type of the menus.
* @param title The title of the menus.
*
* @throws IllegalStateException if FastInv is not init with FastInv.init(Plugin plugin)
*/
public FastInv(InventoryType type, String title) {
@ -103,6 +107,7 @@ public class FastInv implements InventoryHolder {
* Add an {@link ItemStack} to the menus.
*
* @param item The item to add
*
* @return This FastInv instance, for chaining.
*/
public FastInv addItem(ItemStack item) {
@ -114,6 +119,7 @@ public class FastInv implements InventoryHolder {
*
* @param item The item to add.
* @param listener The {@link FastInvClickListener} for the item.
*
* @return This FastInv instance, for chaining.
*/
public FastInv addItem(ItemStack item, FastInvClickListener listener) {
@ -131,6 +137,7 @@ public class FastInv implements InventoryHolder {
*
* @param slot The slot of the item.
* @param item The item to add.
*
* @return This FastInv instance, for chaining.
*/
public FastInv addItem(int slot, ItemStack item) {
@ -140,8 +147,9 @@ public class FastInv implements InventoryHolder {
/**
* Add an {@link ItemStack} to the menus on specific slot with a {@link FastInvClickListener} to handle clicks.
*
* @param slot The slot of the item.
* @param itemStack The icon to add.
* @param slot The slot of the item.
* @param itemStack The icon to add.
*
* @return This FastInv instance, for chaining.
*/
public FastInv addItem(int slot, ItemStack itemStack, FastInvClickListener listener) {
@ -164,6 +172,7 @@ public class FastInv implements InventoryHolder {
* @param slotFrom Starting slot to put the item in.
* @param slotTo Ending slot to put the item in.
* @param item The item to add.
*
* @return This FastInv instance, for chaining.
*/
public FastInv addItem(int slotFrom, int slotTo, ItemStack item) {
@ -177,6 +186,7 @@ public class FastInv implements InventoryHolder {
* @param slotTo Ending slot to put the item in.
* @param item The item to add.
* @param listener The IconClickListener for the item.
*
* @return This FastInv instance, for chaining.
*/
public FastInv addItem(int slotFrom, int slotTo, ItemStack item, FastInvClickListener listener) {
@ -191,6 +201,7 @@ public class FastInv implements InventoryHolder {
*
* @param slots The slot of the item.
* @param item The item to add.
*
* @return This FastInv instance, for chaining.
*/
public FastInv addItem(int[] slots, ItemStack item) {
@ -201,6 +212,7 @@ public class FastInv implements InventoryHolder {
* Add an {@link ItemStack} to the menus on the edges.
*
* @param item The item to add.
*
* @return This FastInv instance, for chaining.
*/
public FastInv edge(ItemStack item) {
@ -223,6 +235,7 @@ public class FastInv implements InventoryHolder {
* @param slots The slots to place the item.
* @param item The item to add.
* @param listener The IconClickListener for the item.
*
* @return This FastInv instance, for chaining.
*/
public FastInv addItem(int[] slots, ItemStack item, FastInvClickListener listener) {
@ -243,7 +256,7 @@ public class FastInv implements InventoryHolder {
return this;
}
public FastInv fill(ItemStack itemStack) {
public FastInv fill(ItemStack itemStack) {
return fill(itemStack, null);
}
@ -251,6 +264,7 @@ public class FastInv implements InventoryHolder {
* Add a {@link FastInvCloseListener} to listen on menus close.
*
* @param listener The {@link FastInvCloseListener} to add.
*
* @return This FastInv instance, for chaining.
*/
public FastInv onClose(FastInvCloseListener listener) {
@ -262,6 +276,7 @@ public class FastInv implements InventoryHolder {
* Add a {@link FastInvClickListener} to listen on menus click.
*
* @param listener The {@link FastInvClickListener} to add.
*
* @return This FastInv instance, for chaining.
*/
public FastInv onClick(FastInvClickListener listener) {
@ -283,6 +298,7 @@ public class FastInv implements InventoryHolder {
*
* @param period Delay between each run.
* @param runnable The {@link Runnable} task to run.
*
* @return This FastInv instance, for chaining.
*/
public FastInv onUpdate(long period, Runnable runnable) {
@ -295,6 +311,7 @@ public class FastInv implements InventoryHolder {
* @param delay Ticks to wait before starting the task.
* @param period Delay between each run.
* @param runnable The {@link Runnable} task to run.
*
* @return This FastInv instance, for chaining
*/
public FastInv onUpdate(long delay, long period, Runnable runnable) {
@ -355,8 +372,8 @@ public class FastInv implements InventoryHolder {
public static abstract class FastInvEvent {
private Player player;
private FastInv inventory;
private final Player player;
private final FastInv inventory;
private boolean cancelled;
FastInvEvent(Player player, FastInv inventory, boolean cancelled) {
@ -404,10 +421,10 @@ public class FastInv implements InventoryHolder {
public static class FastInvClickEvent extends FastInvEvent {
private int slot;
private ItemStack item;
private InventoryAction action;
private ClickType clickType;
private final int slot;
private final ItemStack item;
private final InventoryAction action;
private final ClickType clickType;
private FastInvClickEvent(Player player, FastInv inventory, int slot, ItemStack item,
boolean cancelled, InventoryAction action, ClickType clickType) {
@ -532,6 +549,7 @@ public class FastInv implements InventoryHolder {
* Set if the tasks will be cancel on menus close.
*
* @param cancelTasksOnClose Set if the tasks will be cancel
*
* @return This FastInv instance, for chaining.
*/
public FastInv setCancelTasksOnClose(boolean cancelTasksOnClose) {

View File

@ -5,7 +5,11 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.*;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
@ -27,13 +31,12 @@ import java.util.function.Consumer;
* @version 2.0.3 - Now supports async operations
*/
public class IconInv implements InventoryHolder {
private static Plugin plugin = null;
private boolean cancelTasksOnClose = true, cancelled = true;
private Set<IconInvCloseListener> closeListeners = new HashSet<>();
private Set<IconClickListener> clickListeners = new HashSet<>();
private Map<Integer, Icon> itemListeners = new HashMap<>();
private Set<BukkitTask> tasks = new HashSet<>();
private final Set<IconInvCloseListener> closeListeners = new HashSet<>();
private final Set<IconClickListener> clickListeners = new HashSet<>();
private final Map<Integer, Icon> itemListeners = new HashMap<>();
private final Set<BukkitTask> tasks = new HashSet<>();
private Inventory inventory;
/**
@ -69,6 +72,7 @@ public class IconInv implements InventoryHolder {
*
* @param type The type of the menus.
* @param title The title of the menus.
*
* @throws IllegalStateException if FastInv is not init with FastInv.init(Plugin plugin)
*/
public IconInv(InventoryType type, String title) {
@ -104,7 +108,8 @@ public class IconInv implements InventoryHolder {
/**
* Add an {@link ItemStack} to the menus with a {@link IconClickListener} to handle clicks.
*
* @param icon The icon to add.
* @param icon The icon to add.
*
* @return This FastInv instance, for chaining.
*/
public IconInv addIcon(Icon icon) {
@ -122,6 +127,7 @@ public class IconInv implements InventoryHolder {
*
* @param slot The slot of the item.
* @param icon The icon to add.
*
* @return This FastInv instance, for chaining.
*/
public IconInv addIcon(int slot, Icon icon) {
@ -139,6 +145,7 @@ public class IconInv implements InventoryHolder {
* @param slotFrom Starting slot to put the item in.
* @param slotTo Ending slot to put the item in.
* @param icon The icon to add.
*
* @return This FastInv instance, for chaining.
*/
public IconInv addIcon(int slotFrom, int slotTo, Icon icon) {
@ -152,6 +159,7 @@ public class IconInv implements InventoryHolder {
* Add an {@link ItemStack} to the menus on the edges.
*
* @param icon The icon to add.
*
* @return This FastInv instance, for chaining.
*/
public IconInv edge(Icon icon) {
@ -171,8 +179,9 @@ public class IconInv implements InventoryHolder {
/**
* Add an {@link ItemStack} to the menus on multiples slots with a {@link IconClickListener} to handle click.
*
* @param slots The slots to place the item.
* @param icon The icon to add.
* @param slots The slots to place the item.
* @param icon The icon to add.
*
* @return This FastInv instance, for chaining.
*/
public IconInv addIcon(int[] slots, Icon icon) {
@ -209,6 +218,7 @@ public class IconInv implements InventoryHolder {
* Add a {@link IconInvCloseListener} to listen on menus close.
*
* @param listener The {@link IconInvCloseListener} to add.
*
* @return This FastInv instance, for chaining.
*/
public IconInv onClose(IconInvCloseListener listener) {
@ -220,6 +230,7 @@ public class IconInv implements InventoryHolder {
* Add a {@link IconClickListener} to listen on menus click.
*
* @param listener The {@link IconClickListener} to add.
*
* @return This FastInv instance, for chaining.
*/
public IconInv onClick(IconClickListener listener) {
@ -232,6 +243,7 @@ public class IconInv implements InventoryHolder {
*
* @param period Delay between each run.
* @param runnable The {@link Runnable} task to run.
*
* @return This FastInv instance, for chaining.
*/
public IconInv onUpdate(long period, Runnable runnable) {
@ -244,6 +256,7 @@ public class IconInv implements InventoryHolder {
* @param delay Ticks to wait before starting the task.
* @param period Delay between each run.
* @param runnable The {@link Runnable} task to run.
*
* @return This FastInv instance, for chaining
*/
public IconInv onUpdate(long delay, long period, Runnable runnable) {
@ -298,6 +311,7 @@ public class IconInv implements InventoryHolder {
* Set if the tasks will be cancel on menus close.
*
* @param cancelTasksOnClose Set if the tasks will be cancel
*
* @return This FastInv instance, for chaining.
*/
public IconInv setCancelTasksOnClose(boolean cancelTasksOnClose) {
@ -314,9 +328,8 @@ public class IconInv implements InventoryHolder {
}
public static abstract class IconEvent {
private Player player;
private IconInv inventory;
private final Player player;
private final IconInv inventory;
private boolean cancelled;
IconEvent(Player player, IconInv inventory, boolean cancelled) {
@ -363,11 +376,10 @@ public class IconInv implements InventoryHolder {
}
public static class IconClickEvent extends IconEvent {
private int slot;
private ItemStack item;
private InventoryAction action;
private ClickType clickType;
private final int slot;
private final ItemStack item;
private final InventoryAction action;
private final ClickType clickType;
private IconClickEvent(Player player, IconInv inventory, int slot, ItemStack item,
boolean cancelled, InventoryAction action, ClickType clickType) {

View File

@ -6,11 +6,11 @@ import org.bukkit.inventory.ItemStack;
import java.util.function.Consumer;
public class Icon {
private ItemStack itemStack;
private Consumer<IconClickEvent> consumer;
private final ItemStack itemStack;
private final Consumer<IconClickEvent> consumer;
public Icon(ItemStack itemStack) {
this(itemStack, event -> {});
this(itemStack, event -> { });
}
public Icon(ItemStack item, Consumer<IconClickEvent> consumer) {

View File

@ -16,15 +16,17 @@ import static org.bukkit.Material.PAPER;
public class ListEntryIcon extends Icon {
public ListEntryIcon(EpicVouchers instance, String entry, BiConsumer<Player, String> onRemove, BiConsumer<Player, Pair<String, String>> onEdit) {
super(new ItemBuilder(PAPER).name(YELLOW + entry).lore(GRAY + "Right click to edit",
GRAY + "Left click to remove").build(), event -> {
if (event.getClickType() == ClickType.LEFT) {
onRemove.accept(event.getPlayer(), entry);
super(new ItemBuilder(PAPER)
.name(YELLOW + entry)
.lore(GRAY + "Right click to edit", GRAY + "Left click to remove")
.build(), clickEvent -> {
if (clickEvent.getClickType() == ClickType.LEFT) {
onRemove.accept(clickEvent.getPlayer(), entry);
return;
}
ChatPrompt.showPrompt(instance, event.getPlayer(), aevent -> {
Bukkit.getScheduler().runTaskLater(instance, () -> onEdit.accept(event.getPlayer(), new Pair<>(entry, aevent.getMessage().trim())), 1L);
});
ChatPrompt.showPrompt(instance, clickEvent.getPlayer(),
pEvent -> Bukkit.getScheduler().runTaskLater(instance,
() -> onEdit.accept(clickEvent.getPlayer(), new Pair<>(entry, pEvent.getMessage().trim())), 1L));
});
}
}

View File

@ -19,7 +19,6 @@ import static org.bukkit.ChatColor.GRAY;
import static org.bukkit.ChatColor.WHITE;
public class StringIcon extends Icon {
public StringIcon(EpicVouchers instance, String string, String current, BiConsumer<Player, String> consumer) {
this(instance, string, current, consumer, s -> true);
}
@ -57,10 +56,8 @@ public class StringIcon extends Icon {
}
event.getPlayer().sendMessage(TextUtils.formatText("&7Successfully set to &r" + msg + "&7."));
Bukkit.getScheduler().runTaskLater(instance, () -> consumer.accept(event.getPlayer(), msg), 1L);
});
});
}
});
}
}

View File

@ -14,7 +14,7 @@ public class ToggleableIcon extends Icon {
super(new ItemBuilder(Material.PAPER)
.name(ChatColor.YELLOW + displayname)
.lore(state ? ChatColor.GREEN + "ENABLED" : ChatColor.RED + "DISABLED")
.build(), event -> {});
.build(), event -> { });
this.consumer = consumer;
}

View File

@ -8,7 +8,6 @@ import java.util.HashMap;
import java.util.UUID;
public class PlayerCommandListener implements Listener {
private static final HashMap<UUID, String> commands = new HashMap<>();
@EventHandler
@ -23,8 +22,8 @@ public class PlayerCommandListener implements Listener {
public static void addCommand(UUID uuid, String command) {
commands.put(uuid, command);
}
public static void removeCommand(UUID uuid) {
commands.remove(uuid);
}
}
}

View File

@ -3,6 +3,7 @@ package com.songoda.epicvouchers.listeners;
import com.songoda.core.nms.NmsManager;
import com.songoda.core.nms.nbt.NBTItem;
import com.songoda.epicvouchers.EpicVouchers;
import com.songoda.epicvouchers.utils.CachedSet;
import com.songoda.epicvouchers.voucher.Voucher;
import org.bukkit.ChatColor;
import org.bukkit.event.EventHandler;
@ -13,47 +14,64 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class PlayerInteractListener implements Listener {
private final EpicVouchers instance;
private final CachedSet<ItemStack> checkedLegacyVouchers = new CachedSet<>(3 * 60);
public PlayerInteractListener(EpicVouchers instance) {
this.instance = instance;
}
@EventHandler
public void voucherListener(PlayerInteractEvent event) {
final ItemStack item = event.getItem();
if (item == null || (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK))
return;
public void voucherListener(PlayerInteractEvent e) {
ItemStack item = e.getItem();
final NBTItem itemNbt = NmsManager.getNbt().of(item);
if (item != null && (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK)) {
NBTItem itemNbt = NmsManager.getNbt().of(item);
for (Voucher voucher : instance.getVoucherManager().getVouchers()) {
final ItemStack voucherItem = voucher.toItemStack();
boolean itemHasVoucher = itemNbt.has("epicvouchers:voucher");
String itemVoucherValue = itemNbt.getString("epicvouchers:voucher");
// Check voucher NBT.
if (itemNbt.has("epicvouchers:voucher") && itemNbt.getNBTObject("epicvouchers:voucher").asString().equals(voucher.getKey())) {
event.setCancelled(true);
voucher.redeemVoucher(event);
continue;
boolean legacyChecked = checkedLegacyVouchers.contains(item);
if (itemHasVoucher || !legacyChecked) {
boolean shouldBeLegacyCached = !itemHasVoucher;
for (Voucher voucher : instance.getVoucherManager().getVouchers()) {
// Check voucher NBT.
if (itemHasVoucher && itemVoucherValue.equals(voucher.getKey())) {
e.setCancelled(true);
voucher.redeemVoucher(e);
break;
}
// TODO: eventually make the legacy check configurable as a lot of players (and vouchers) quickly cause lag
// Legacy crap.
// does the item they're holding match this voucher?
ItemStack voucherItem = voucher.toItemStack();
if ((voucherItem == null || voucherItem.isSimilar(item)) &&
item.getType() == voucher.getMaterial() &&
item.getDurability() == voucher.getData()) {
// material matches - verify the name + lore
ItemMeta meta = item.getItemMeta();
if (meta != null && meta.hasDisplayName()
&& ChatColor.stripColor(meta.getDisplayName()).equals(ChatColor.stripColor(voucher.getName(true)))
&& (!meta.hasLore() || meta.getLore().equals(voucher.getLore(true)))) {
e.setCancelled(true);
voucher.redeemVoucher(e);
shouldBeLegacyCached = false;
break;
}
}
}
if (shouldBeLegacyCached) {
this.checkedLegacyVouchers.add(item);
}
}
// Legacy crap.
// does the item they're holding match this voucher?
if (voucherItem != null && !voucherItem.isSimilar(item)) continue;
else if (item.getType() != voucher.getMaterial() || item.getDurability() != voucher.getData()) continue;
else {
// material matches - verify the name + lore
final ItemMeta meta = item.getItemMeta();
if (meta == null || !meta.hasDisplayName()
|| !ChatColor.stripColor(meta.getDisplayName()).equals(ChatColor.stripColor(voucher.getName(true)))
|| (meta.hasLore() && !meta.getLore().equals(voucher.getLore(true))))
continue;
}
event.setCancelled(true);
voucher.redeemVoucher(event);
}
}
}
}

View File

@ -20,7 +20,6 @@ import static org.bukkit.ChatColor.YELLOW;
import static org.bukkit.Material.BARRIER;
public class ActionMenu extends FastInv {
public ActionMenu(EpicVouchers instance, Voucher voucher) {
super(27, "Give menu");

View File

@ -1,7 +1,6 @@
package com.songoda.epicvouchers.menus;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.epicvouchers.EpicVouchers;
import com.songoda.epicvouchers.libraries.ItemBuilder;
import com.songoda.epicvouchers.libraries.inventory.FastInv;
@ -13,7 +12,6 @@ import static org.bukkit.enchantments.Enchantment.DURABILITY;
import static org.bukkit.inventory.ItemFlag.HIDE_ENCHANTS;
public class ConfirmMenu extends FastInv {
public ConfirmMenu(EpicVouchers instance, Runnable success, Runnable failure) {
super(27, instance.getLocale().getMessage("interface.confirmsettings.title").getMessage());

View File

@ -1,7 +1,6 @@
package com.songoda.epicvouchers.menus;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.utils.TextUtils;
import com.songoda.epicvouchers.EpicVouchers;
import com.songoda.epicvouchers.libraries.ItemBuilder;
@ -9,14 +8,15 @@ import com.songoda.epicvouchers.libraries.inventory.FastInv;
import com.songoda.epicvouchers.menus.sub.editor.SetItemMenu;
import com.songoda.epicvouchers.voucher.Voucher;
import org.bukkit.ChatColor;
import org.bukkit.inventory.ItemStack;
import static org.bukkit.ChatColor.GRAY;
import static org.bukkit.ChatColor.YELLOW;
import static org.bukkit.Material.*;
import static org.bukkit.Material.BARRIER;
import static org.bukkit.Material.BOOK;
import static org.bukkit.Material.FEATHER;
import static org.bukkit.Material.STONE;
public class OptionMenu extends FastInv {
public OptionMenu(EpicVouchers instance, Voucher voucher) {
super(27, "Options: " + voucher.getKey());
@ -45,5 +45,4 @@ public class OptionMenu extends FastInv {
fill(new ItemBuilder(CompatibleMaterial.GRAY_STAINED_GLASS_PANE.getItem()).name(ChatColor.RESET.toString()).build());
}
}

View File

@ -63,7 +63,7 @@ public class VoucherEditorMenu extends IconInv {
}));
addIcon(11, new StringIcon(instance, "Material", voucher.getMaterial().toString(), (player, editString) -> {
if(editString.contains(":")) {
if (editString.contains(":")) {
voucher.setData(Short.parseShort(editString.split(":")[1]));
voucher.setMaterial(Material.valueOf(editString.split(":")[0]));
} else {
@ -72,11 +72,11 @@ public class VoucherEditorMenu extends IconInv {
reopen(player);
}, string -> {
if (string.isEmpty()) {
if (string.isEmpty()) {
return false;
}
if(string.contains(":") && string.split(":").length == 2) {
if (string.contains(":") && string.split(":").length == 2) {
String[] split = string.split(":");
return Material.matchMaterial(split[0]) != null && StringUtils.isNumeric(split[1]);
}

View File

@ -15,9 +15,13 @@ import org.bukkit.inventory.ItemStack;
import static org.bukkit.Material.PAPER;
public class VoucherMenu extends IconInv {
public VoucherMenu(EpicVouchers instance) {
super((int) (Math.ceil(instance.getVoucherManager().getVouchers().size() / 9.0) * 9 + (instance.getVoucherManager().getVouchers().size() % 9 == 0 ? 9 : 0)), "Vouchers");
// FIXME: Having too many vouchers throws an error:
// Size for custom inventory must be a multiple of 9 between 9 and 54 slots (got 594)
// Applied hotfix to use a maximum size of 54
// Example file: https://support.songoda.com/secure/attachment/17258/17258_vouchers.yml
super(Math.min((int) (Math.ceil(instance.getVoucherManager().getVouchers().size() / 9.0) * 9 + (instance.getVoucherManager().getVouchers().size() % 9 == 0 ? 9 : 0)), 54), "Vouchers");
for (Voucher voucher : instance.getVoucherManager().getVouchers()) {
if (getInventory().firstEmpty() != -1) {
@ -54,5 +58,4 @@ public class VoucherMenu extends IconInv {
new ItemStack(Material.valueOf("GRAY_STAINED_GLASS_PANE")) :
new ItemStack(Material.valueOf("STAINED_GLASS_PANE"), 1, (short) 7)).name(ChatColor.RESET.toString()).build()));
}
}

View File

@ -12,4 +12,4 @@ public class GiveMenu extends PlayersMenu {
public GiveMenu(EpicVouchers instance, Voucher voucher) {
super(instance, voucher, "Give Menu", (who, player) -> voucher.give(who, Collections.singletonList(player), 1), new ArrayList<>(Bukkit.getOnlinePlayers()));
}
}
}

View File

@ -35,6 +35,5 @@ public class EffectsMenu extends IconInv {
.name(YELLOW + "Return")
.lore(GRAY + "Return to the editor")
.build(), event -> new VoucherEditorMenu(instance, voucher).open(event.getPlayer()));
}
}

View File

@ -30,6 +30,5 @@ public class ParticlesMenu extends IconInv {
.name(YELLOW + "Return")
.lore(GRAY + "Return to the editor")
.build(), event -> new VoucherEditorMenu(instance, voucher).open(event.getPlayer()));
}
}

View File

@ -15,7 +15,6 @@ import static org.bukkit.ChatColor.GRAY;
import static org.bukkit.ChatColor.YELLOW;
public class SetItemMenu extends FastInv {
public SetItemMenu(EpicVouchers instance, Voucher voucher) {
super(27, "Set item");
@ -74,6 +73,5 @@ public class SetItemMenu extends FastInv {
new OptionMenu(instance, voucher).open(event.getPlayer());
});
}
}

View File

@ -14,11 +14,13 @@ import org.bukkit.Material;
import java.util.List;
import java.util.stream.Collectors;
import static org.bukkit.ChatColor.*;
import static org.bukkit.ChatColor.DARK_GRAY;
import static org.bukkit.ChatColor.GRAY;
import static org.bukkit.ChatColor.GREEN;
import static org.bukkit.ChatColor.YELLOW;
import static org.bukkit.Material.PAPER;
public class StringListMenu extends IconInv {
public StringListMenu(EpicVouchers instance, String key, List<String> list, String toEdit, Voucher voucher) {
super((int) ((list.isEmpty() ? 9 : Math.ceil(list.size() / 9.0) * 9) + 9), key);
int size = getInventory().getSize();
@ -35,10 +37,9 @@ public class StringListMenu extends IconInv {
addIcon(size - 1, new ItemBuilder(PAPER).name(GREEN + "Add to list").build(), event -> {
ChatPrompt.showPrompt(instance, event.getPlayer(), TextUtils.formatText("Enter a new value."), aevent -> {
list.add(aevent.getMessage().trim());
voucher.saveSetting(key.toLowerCase(), list);
list.add(aevent.getMessage().trim());
voucher.saveSetting(key.toLowerCase(), list);
Bukkit.getScheduler().runTaskLater(instance, () -> new StringListMenu(instance, key, list, toEdit, voucher).open(event.getPlayer()), 1L);
});
});
@ -54,6 +55,5 @@ public class StringListMenu extends IconInv {
new StringListMenu(instance, key, list, toEdit, voucher).open(player);
}));
}
}
}

View File

@ -45,6 +45,5 @@ public class TitlesMenu extends IconInv {
.name(YELLOW + "Return")
.lore(GRAY + "Return to the editor")
.build(), event -> new VoucherEditorMenu(instance, voucher).open(event.getPlayer()));
}
}

View File

@ -9,7 +9,6 @@ import org.bukkit.event.Listener;
* Created by songo on 6/4/2017.
*/
public class Settings implements Listener {
static final Config config = EpicVouchers.getInstance().getCoreConfig();
public static final ConfigSetting FILL_GLASS = new ConfigSetting(config, "Interface.Fill Interfaces With Glass", true);
@ -31,4 +30,4 @@ public class Settings implements Listener {
config.setAutoremove(true).setAutosave(true);
config.saveChanges();
}
}
}

View File

@ -0,0 +1,40 @@
package com.songoda.epicvouchers.utils;
import java.util.Map;
import java.util.WeakHashMap;
public class CachedSet<K> {
private final Map<K, Long> cache = new WeakHashMap<>();
private final int ttl;
private long lastClear = System.currentTimeMillis();
/**
* @param ttl Time-To-Live in seconds
*/
public CachedSet(int ttl) {
this.ttl = ttl * 1000;
}
public void add(K obj) {
this.cache.put(obj, System.currentTimeMillis());
}
public boolean contains(K obj) {
if (shouldClear()) {
clearStale();
}
return this.cache.computeIfPresent(obj, (k, aLong) -> System.currentTimeMillis()) != null;
}
public void clearStale() {
this.cache.entrySet().removeIf(entry -> System.currentTimeMillis() - entry.getValue() >= ttl);
this.lastClear = System.currentTimeMillis();
}
private boolean shouldClear() {
return !this.cache.isEmpty() && System.currentTimeMillis() - lastClear > ttl;
}
}

View File

@ -0,0 +1,6 @@
package com.songoda.epicvouchers.utils;
// TODO: Copied from EpicAnchors - Move to SongodaCore (maybe rename too?)
public interface Callback {
void accept(Exception ex);
}

View File

@ -1,20 +1,22 @@
package com.songoda.epicvouchers.utils;
import java.io.Serializable;
import java.util.Objects;
/**
* <p>A convenience class to represent name-value pairs.</p>
*
* @since JavaFX 2.0
*/
public class Pair<K,V> implements Serializable{
public class Pair<K, V> implements Serializable {
/**
* Key of this <code>Pair</code>.
*/
private String key;
private final String key;
/**
* Gets the key for this pair.
*
* @return key for this pair
*/
public String getKey() { return key; }
@ -22,17 +24,19 @@ public class Pair<K,V> implements Serializable{
/**
* Value of this this <code>Pair</code>.
*/
private String value;
private final String value;
/**
* Gets the value for this pair.
*
* @return value for this pair
*/
public String getValue() { return value; }
/**
* Creates a new pair
* @param key The key for this pair
*
* @param key The key for this pair
* @param value The value to use for this pair
*/
public Pair(String key, String value) {
@ -46,7 +50,7 @@ public class Pair<K,V> implements Serializable{
*
* <p>The default name/value delimiter '=' is always used.</p>
*
* @return <code>String</code> representation of this <code>Pair</code>
* @return <code>String</code> representation of this <code>Pair</code>
*/
@Override
public String toString() {
@ -83,20 +87,18 @@ public class Pair<K,V> implements Serializable{
* both the names and values are equal.</p>
*
* @param o the <code>Object</code> to test for
* equality with this <code>Pair</code>
* equality with this <code>Pair</code>
*
* @return <code>true</code> if the given <code>Object</code> is
* equal to this <code>Pair</code> else <code>false</code>
* equal to this <code>Pair</code> else <code>false</code>
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof Pair) {
Pair pair = (Pair) o;
if (key != null ? !key.equals(pair.key) : pair.key != null) return false;
if (value != null ? !value.equals(pair.value) : pair.value != null) return false;
return true;
}
return false;
if (o == null || getClass() != o.getClass()) return false;
Pair<?, ?> pair = (Pair<?, ?>) o;
return Objects.equals(key, pair.key) && Objects.equals(value, pair.value);
}
}

View File

@ -0,0 +1,31 @@
package com.songoda.epicvouchers.utils;
import java.util.concurrent.atomic.AtomicReference;
// TODO: Copied from EpicAnchors - Move to SongodaCore
public class ThreadSync {
private final Object syncObj = new Object();
private final AtomicReference<Boolean> waiting = new AtomicReference<>(true);
public void waitForRelease() {
synchronized (syncObj) {
while (waiting.get()) {
try {
syncObj.wait();
} catch (Exception ignore) {
}
}
}
}
public void release() {
synchronized (syncObj) {
waiting.set(false);
syncObj.notifyAll();
}
}
public void reset() {
waiting.set(true);
}
}

View File

@ -8,7 +8,6 @@ import java.util.Map;
import java.util.UUID;
public class CoolDownManager {
private final Map<UUID, Long> entries = new HashMap<>();
private final EpicVouchers instance;
@ -22,9 +21,9 @@ public class CoolDownManager {
}
if (voucher.getCoolDown() != 0) {
entries.put(uuid, System.currentTimeMillis() + voucher.getCoolDown() * 1000);
entries.put(uuid, System.currentTimeMillis() + voucher.getCoolDown() * 1000L);
} else {
entries.put(uuid, System.currentTimeMillis() + instance.getConfig().getInt("Main.Cooldown Delay") * 1000);
entries.put(uuid, System.currentTimeMillis() + instance.getConfig().getInt("Main.Cooldown Delay") * 1000L);
}
}
@ -52,4 +51,4 @@ public class CoolDownManager {
return (time - System.currentTimeMillis()) / 1000;
}
}
}

View File

@ -30,7 +30,6 @@ import static org.bukkit.Material.PAPER;
@Accessors(chain = true)
public class Voucher {
private final String key;
private final EpicVouchers instance;
private String permission = "";
@ -236,8 +235,7 @@ public class Voucher {
if (confirm) {
new ConfirmMenu(instance,
() -> instance.getVoucherExecutor().redeemVoucher(player, this, event.getItem(), true, event),
() -> {
})
() -> { })
.open(player);
} else {
instance.getVoucherExecutor().redeemVoucher(player, this, event.getItem(), true, event);

View File

@ -1,9 +1,10 @@
package com.songoda.epicvouchers.voucher;
import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class VoucherManager {
private final Map<String, Voucher> registeredVouchers = new HashMap<>();
public Voucher addVoucher(Voucher voucher) {

View File

@ -1,13 +1,16 @@
name: EpicVouchers
main: com.songoda.epicvouchers.EpicVouchers
version: maven-version-number
author: Songoda
website: https://songoda.host/epicvouchers
description: Enhance your server with awesome customizable vouchers with a lot of features.
name: ${project.name}
description: ${project.description}
version: ${project.version}
api-version: 1.13
main: com.songoda.epicvouchers.EpicVouchers
author: Songoda
website: ${project.url}
commands:
epicvouchers:
description: View information on this plugin.
default: true
aliases: [ev]
usage: /ev
usage: /ev

View File

@ -51,4 +51,4 @@ vouchers:
effects:
effect: "SPEED"
amplifier: 2
duration: 10
duration: 10