diff --git a/.editorconfig b/.editorconfig index 1c53c29c2..30cfb5ef7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,137 +13,151 @@ ij_formatter_off_tag = @formatter:off ij_formatter_on_tag = @formatter:on ij_formatter_tags_enabled = false ij_smart_tabs = false +ij_visual_guides = 140 ij_wrap_on_typing = false [*.java] +ij_visual_guides = none 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_annotation_parameters = true +ij_java_align_multiline_array_initializer_expression = true +ij_java_align_multiline_assignment = true +ij_java_align_multiline_binary_operation = true +ij_java_align_multiline_chained_methods = true +ij_java_align_multiline_extends_list = true ij_java_align_multiline_for = true -ij_java_align_multiline_method_parentheses = false +ij_java_align_multiline_method_parentheses = true 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_parameters_in_calls = true +ij_java_align_multiline_parenthesized_expression = true 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_align_multiline_ternary_operation = true +ij_java_align_multiline_text_blocks = true +ij_java_align_multiline_throws_list = true +ij_java_align_subsequent_simple_methods = true +ij_java_align_throws_keyword = true +ij_java_annotation_parameter_wrap = on_every_item +ij_java_array_initializer_new_line_after_left_brace = true +ij_java_array_initializer_right_brace_on_new_line = true +ij_java_array_initializer_wrap = normal +ij_java_assert_statement_colon_on_next_line = true +ij_java_assert_statement_wrap = on_every_item +ij_java_assignment_wrap = normal ij_java_binary_operation_sign_on_next_line = false -ij_java_binary_operation_wrap = off +ij_java_binary_operation_wrap = normal 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_imports = 2 ij_java_blank_lines_after_package = 1 -ij_java_blank_lines_around_class = 1 +ij_java_blank_lines_around_class = 2 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_initializer = 0 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_blank_lines_before_package = 1 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_call_parameters_wrap = normal 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 = 30 -ij_java_class_names_in_javadoc = 1 +ij_java_class_count_to_use_import_on_demand = 200 +ij_java_class_names_in_javadoc = 3 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 = false -ij_java_doc_add_blank_line_after_return = false +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 = false ij_java_doc_enable_formatting = true ij_java_doc_enable_leading_asterisks = true -ij_java_doc_indent_on_continuation = false +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_preserve_line_breaks = true 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_entity_dd_suffix = EJB +ij_java_entity_eb_suffix = Bean +ij_java_entity_hi_suffix = Home +ij_java_entity_lhi_prefix = Local +ij_java_entity_lhi_suffix = Home +ij_java_entity_li_prefix = Local +ij_java_entity_pk_class = java.lang.String +ij_java_entity_vo_suffix = VO +ij_java_enum_constants_wrap = split_into_lines +ij_java_extends_keyword_wrap = normal +ij_java_extends_list_wrap = on_every_item 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_for_statement_wrap = on_every_item 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_imports_layout = *, |, javax.**, java.**, |, com.dfsek.terra.**, |, $org.junit.jupiter.api.Assertions.**, |, $* ij_java_indent_case_from_switch = true -ij_java_insert_inner_class_imports = false +ij_java_insert_inner_class_imports = true ij_java_insert_override_annotation = true ij_java_keep_blank_lines_before_right_brace = 2 -ij_java_keep_blank_lines_between_package_declaration_and_header = 2 +ij_java_keep_blank_lines_between_package_declaration_and_header = 1 ij_java_keep_blank_lines_in_code = 2 ij_java_keep_blank_lines_in_declarations = 2 +ij_java_keep_builder_methods_indents = true 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_first_column_comment = false +ij_java_keep_indents_on_empty_lines = true 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_blocks_in_one_line = true ij_java_keep_simple_classes_in_one_line = false -ij_java_keep_simple_lambdas_in_one_line = false -ij_java_keep_simple_methods_in_one_line = false +ij_java_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_message_dd_suffix = EJB +ij_java_message_eb_suffix = Bean 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_call_chain_wrap = on_every_item 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_method_parameters_wrap = normal ij_java_modifier_list_wrap = false -ij_java_names_count_to_use_import_on_demand = 3 +ij_java_names_count_to_use_import_on_demand = 50 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_packages_to_use_import_on_demand = $org.junit.jupiter.api.Assertions.* +ij_java_parameter_annotation_wrap = on_every_item 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_prefer_parameters_wrap = true ij_java_record_components_wrap = normal ij_java_repeat_synchronized = true ij_java_replace_instanceof_and_cast = false @@ -151,8 +165,15 @@ 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_resource_list_wrap = on_every_item ij_java_rparen_on_new_line_in_record_header = false +ij_java_session_dd_suffix = EJB +ij_java_session_eb_suffix = Bean +ij_java_session_hi_suffix = Home +ij_java_session_lhi_prefix = Local +ij_java_session_lhi_suffix = Home +ij_java_session_li_prefix = Local +ij_java_session_si_suffix = Service ij_java_space_after_closing_angle_bracket_in_type_argument = false ij_java_space_after_colon = true ij_java_space_after_comma = true @@ -162,7 +183,7 @@ 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_array_initializer_left_brace = false ij_java_space_before_catch_keyword = true ij_java_space_before_catch_left_brace = true ij_java_space_before_catch_parentheses = false @@ -196,7 +217,7 @@ ij_java_space_before_while_keyword = true ij_java_space_before_while_left_brace = true ij_java_space_before_while_parentheses = false ij_java_space_inside_one_line_enum_braces = false -ij_java_space_within_empty_array_initializer_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 @@ -213,8 +234,8 @@ 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 = false +ij_java_spaces_within_array_initializer_braces = true +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 @@ -223,80 +244,276 @@ 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_ternary_operation_signs_on_next_line = true +ij_java_ternary_operation_wrap = on_every_item ij_java_test_name_suffix = Test -ij_java_throws_keyword_wrap = off -ij_java_throws_list_wrap = off +ij_java_throws_keyword_wrap = normal +ij_java_throws_list_wrap = normal 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_variable_annotation_wrap = on_every_item 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_comments = true ij_java_wrap_first_method_in_call_chain = false -ij_java_wrap_long_lines = false +ij_java_wrap_long_lines = true -[{*.gradle.kts,*.kt,*.kts,*.main.kts}] -ij_kotlin_align_in_columns_case_branch = false +[.editorconfig] +ij_visual_guides = none +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 + +[{*.gant, *.gradle, *.groovy, *.gson, *.gy}] +ij_visual_guides = none +ij_groovy_align_group_field_declarations = false +ij_groovy_align_multiline_array_initializer_expression = false +ij_groovy_align_multiline_assignment = false +ij_groovy_align_multiline_binary_operation = false +ij_groovy_align_multiline_chained_methods = false +ij_groovy_align_multiline_extends_list = false +ij_groovy_align_multiline_for = true +ij_groovy_align_multiline_list_or_map = true +ij_groovy_align_multiline_method_parentheses = false +ij_groovy_align_multiline_parameters = true +ij_groovy_align_multiline_parameters_in_calls = false +ij_groovy_align_multiline_resources = true +ij_groovy_align_multiline_ternary_operation = false +ij_groovy_align_multiline_throws_list = false +ij_groovy_align_named_args_in_map = true +ij_groovy_align_throws_keyword = false +ij_groovy_array_initializer_new_line_after_left_brace = false +ij_groovy_array_initializer_right_brace_on_new_line = false +ij_groovy_array_initializer_wrap = off +ij_groovy_assert_statement_wrap = off +ij_groovy_assignment_wrap = off +ij_groovy_binary_operation_wrap = off +ij_groovy_blank_lines_after_class_header = 0 +ij_groovy_blank_lines_after_imports = 1 +ij_groovy_blank_lines_after_package = 1 +ij_groovy_blank_lines_around_class = 1 +ij_groovy_blank_lines_around_field = 0 +ij_groovy_blank_lines_around_field_in_interface = 0 +ij_groovy_blank_lines_around_method = 1 +ij_groovy_blank_lines_around_method_in_interface = 1 +ij_groovy_blank_lines_before_imports = 1 +ij_groovy_blank_lines_before_method_body = 0 +ij_groovy_blank_lines_before_package = 0 +ij_groovy_block_brace_style = end_of_line +ij_groovy_block_comment_at_first_column = true +ij_groovy_call_parameters_new_line_after_left_paren = false +ij_groovy_call_parameters_right_paren_on_new_line = false +ij_groovy_call_parameters_wrap = off +ij_groovy_catch_on_new_line = false +ij_groovy_class_annotation_wrap = split_into_lines +ij_groovy_class_brace_style = end_of_line +ij_groovy_class_count_to_use_import_on_demand = 5 +ij_groovy_do_while_brace_force = never +ij_groovy_else_on_new_line = false +ij_groovy_enum_constants_wrap = off +ij_groovy_extends_keyword_wrap = off +ij_groovy_extends_list_wrap = off +ij_groovy_field_annotation_wrap = split_into_lines +ij_groovy_finally_on_new_line = false +ij_groovy_for_brace_force = never +ij_groovy_for_statement_new_line_after_left_paren = false +ij_groovy_for_statement_right_paren_on_new_line = false +ij_groovy_for_statement_wrap = off +ij_groovy_if_brace_force = never +ij_groovy_import_annotation_wrap = 2 +ij_groovy_imports_layout = *, |, javax.**, java.**, |, $* +ij_groovy_indent_case_from_switch = true +ij_groovy_indent_label_blocks = true +ij_groovy_insert_inner_class_imports = false +ij_groovy_keep_blank_lines_before_right_brace = 2 +ij_groovy_keep_blank_lines_in_code = 2 +ij_groovy_keep_blank_lines_in_declarations = 2 +ij_groovy_keep_control_statement_in_one_line = true +ij_groovy_keep_first_column_comment = true +ij_groovy_keep_indents_on_empty_lines = false +ij_groovy_keep_line_breaks = true +ij_groovy_keep_multiple_expressions_in_one_line = false +ij_groovy_keep_simple_blocks_in_one_line = false +ij_groovy_keep_simple_classes_in_one_line = true +ij_groovy_keep_simple_lambdas_in_one_line = true +ij_groovy_keep_simple_methods_in_one_line = true +ij_groovy_label_indent_absolute = false +ij_groovy_label_indent_size = 0 +ij_groovy_lambda_brace_style = end_of_line +ij_groovy_layout_static_imports_separately = true +ij_groovy_line_comment_add_space = false +ij_groovy_line_comment_at_first_column = true +ij_groovy_method_annotation_wrap = split_into_lines +ij_groovy_method_brace_style = end_of_line +ij_groovy_method_call_chain_wrap = off +ij_groovy_method_parameters_new_line_after_left_paren = false +ij_groovy_method_parameters_right_paren_on_new_line = false +ij_groovy_method_parameters_wrap = off +ij_groovy_modifier_list_wrap = false +ij_groovy_names_count_to_use_import_on_demand = 3 +ij_groovy_parameter_annotation_wrap = off +ij_groovy_parentheses_expression_new_line_after_left_paren = false +ij_groovy_parentheses_expression_right_paren_on_new_line = false +ij_groovy_prefer_parameters_wrap = false +ij_groovy_resource_list_new_line_after_left_paren = false +ij_groovy_resource_list_right_paren_on_new_line = false +ij_groovy_resource_list_wrap = off +ij_groovy_space_after_assert_separator = true +ij_groovy_space_after_colon = true +ij_groovy_space_after_comma = true +ij_groovy_space_after_comma_in_type_arguments = true +ij_groovy_space_after_for_semicolon = true +ij_groovy_space_after_quest = true +ij_groovy_space_after_type_cast = true +ij_groovy_space_before_annotation_parameter_list = false +ij_groovy_space_before_array_initializer_left_brace = false +ij_groovy_space_before_assert_separator = false +ij_groovy_space_before_catch_keyword = true +ij_groovy_space_before_catch_left_brace = true +ij_groovy_space_before_catch_parentheses = true +ij_groovy_space_before_class_left_brace = true +ij_groovy_space_before_closure_left_brace = true +ij_groovy_space_before_colon = true +ij_groovy_space_before_comma = false +ij_groovy_space_before_do_left_brace = true +ij_groovy_space_before_else_keyword = true +ij_groovy_space_before_else_left_brace = true +ij_groovy_space_before_finally_keyword = true +ij_groovy_space_before_finally_left_brace = true +ij_groovy_space_before_for_left_brace = true +ij_groovy_space_before_for_parentheses = true +ij_groovy_space_before_for_semicolon = false +ij_groovy_space_before_if_left_brace = true +ij_groovy_space_before_if_parentheses = true +ij_groovy_space_before_method_call_parentheses = false +ij_groovy_space_before_method_left_brace = true +ij_groovy_space_before_method_parentheses = false +ij_groovy_space_before_quest = true +ij_groovy_space_before_switch_left_brace = true +ij_groovy_space_before_switch_parentheses = true +ij_groovy_space_before_synchronized_left_brace = true +ij_groovy_space_before_synchronized_parentheses = true +ij_groovy_space_before_try_left_brace = true +ij_groovy_space_before_try_parentheses = true +ij_groovy_space_before_while_keyword = true +ij_groovy_space_before_while_left_brace = true +ij_groovy_space_before_while_parentheses = true +ij_groovy_space_in_named_argument = true +ij_groovy_space_in_named_argument_before_colon = false +ij_groovy_space_within_empty_array_initializer_braces = false +ij_groovy_space_within_empty_method_call_parentheses = false +ij_groovy_spaces_around_additive_operators = true +ij_groovy_spaces_around_assignment_operators = true +ij_groovy_spaces_around_bitwise_operators = true +ij_groovy_spaces_around_equality_operators = true +ij_groovy_spaces_around_lambda_arrow = true +ij_groovy_spaces_around_logical_operators = true +ij_groovy_spaces_around_multiplicative_operators = true +ij_groovy_spaces_around_regex_operators = true +ij_groovy_spaces_around_relational_operators = true +ij_groovy_spaces_around_shift_operators = true +ij_groovy_spaces_within_annotation_parentheses = false +ij_groovy_spaces_within_array_initializer_braces = false +ij_groovy_spaces_within_braces = true +ij_groovy_spaces_within_brackets = false +ij_groovy_spaces_within_cast_parentheses = false +ij_groovy_spaces_within_catch_parentheses = false +ij_groovy_spaces_within_for_parentheses = false +ij_groovy_spaces_within_gstring_injection_braces = false +ij_groovy_spaces_within_if_parentheses = false +ij_groovy_spaces_within_list_or_map = false +ij_groovy_spaces_within_method_call_parentheses = false +ij_groovy_spaces_within_method_parentheses = false +ij_groovy_spaces_within_parentheses = false +ij_groovy_spaces_within_switch_parentheses = false +ij_groovy_spaces_within_synchronized_parentheses = false +ij_groovy_spaces_within_try_parentheses = false +ij_groovy_spaces_within_tuple_expression = false +ij_groovy_spaces_within_while_parentheses = false +ij_groovy_special_else_if_treatment = true +ij_groovy_ternary_operation_wrap = off +ij_groovy_throws_keyword_wrap = off +ij_groovy_throws_list_wrap = off +ij_groovy_use_flying_geese_braces = false +ij_groovy_use_fq_class_names = false +ij_groovy_use_fq_class_names_in_javadoc = true +ij_groovy_use_relative_indents = false +ij_groovy_use_single_class_imports = true +ij_groovy_variable_annotation_wrap = off +ij_groovy_while_brace_force = never +ij_groovy_while_on_new_line = false +ij_groovy_wrap_long_lines = false + +[{*.gql, *.graphql, *.graphqls}] +ij_visual_guides = none + +[{*.kt, *.kts}] +ij_visual_guides = none +ij_kotlin_align_in_columns_case_branch = true ij_kotlin_align_multiline_binary_operation = false -ij_kotlin_align_multiline_extends_list = false -ij_kotlin_align_multiline_method_parentheses = false +ij_kotlin_align_multiline_extends_list = true +ij_kotlin_align_multiline_method_parentheses = true ij_kotlin_align_multiline_parameters = true -ij_kotlin_align_multiline_parameters_in_calls = false +ij_kotlin_align_multiline_parameters_in_calls = true ij_kotlin_allow_trailing_comma = false ij_kotlin_allow_trailing_comma_on_call_site = false -ij_kotlin_assignment_wrap = off +ij_kotlin_assignment_wrap = normal ij_kotlin_blank_lines_after_class_header = 0 -ij_kotlin_blank_lines_around_block_when_branches = 0 +ij_kotlin_blank_lines_around_block_when_branches = 1 ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1 ij_kotlin_block_comment_at_first_column = true -ij_kotlin_call_parameters_new_line_after_left_paren = false -ij_kotlin_call_parameters_right_paren_on_new_line = false -ij_kotlin_call_parameters_wrap = off +ij_kotlin_call_parameters_new_line_after_left_paren = true +ij_kotlin_call_parameters_right_paren_on_new_line = true +ij_kotlin_call_parameters_wrap = on_every_item ij_kotlin_catch_on_new_line = false ij_kotlin_class_annotation_wrap = split_into_lines -ij_kotlin_continuation_indent_for_chained_calls = true -ij_kotlin_continuation_indent_for_expression_bodies = true -ij_kotlin_continuation_indent_in_argument_lists = true -ij_kotlin_continuation_indent_in_elvis = true -ij_kotlin_continuation_indent_in_if_conditions = true -ij_kotlin_continuation_indent_in_parameter_lists = true -ij_kotlin_continuation_indent_in_supertype_lists = true +ij_kotlin_continuation_indent_for_chained_calls = false +ij_kotlin_continuation_indent_for_expression_bodies = false +ij_kotlin_continuation_indent_in_argument_lists = false +ij_kotlin_continuation_indent_in_elvis = false +ij_kotlin_continuation_indent_in_if_conditions = false +ij_kotlin_continuation_indent_in_parameter_lists = false +ij_kotlin_continuation_indent_in_supertype_lists = false ij_kotlin_else_on_new_line = false -ij_kotlin_enum_constants_wrap = off -ij_kotlin_extends_list_wrap = off -ij_kotlin_field_annotation_wrap = split_into_lines +ij_kotlin_enum_constants_wrap = on_every_item +ij_kotlin_extends_list_wrap = normal +ij_kotlin_field_annotation_wrap = on_every_item ij_kotlin_finally_on_new_line = false -ij_kotlin_if_rparen_on_new_line = false +ij_kotlin_if_rparen_on_new_line = true ij_kotlin_import_nested_classes = false +ij_kotlin_imports_layout = *, java.*, javax.*, kotlin.** ij_kotlin_insert_whitespaces_in_simple_one_line_method = true -ij_kotlin_keep_blank_lines_before_right_brace = 2 +ij_kotlin_keep_blank_lines_before_right_brace = 1 ij_kotlin_keep_blank_lines_in_code = 2 ij_kotlin_keep_blank_lines_in_declarations = 2 ij_kotlin_keep_first_column_comment = true -ij_kotlin_keep_indents_on_empty_lines = false +ij_kotlin_keep_indents_on_empty_lines = true ij_kotlin_keep_line_breaks = true ij_kotlin_lbrace_on_next_line = false ij_kotlin_line_comment_add_space = false ij_kotlin_line_comment_at_first_column = true -ij_kotlin_method_annotation_wrap = split_into_lines -ij_kotlin_method_call_chain_wrap = off -ij_kotlin_method_parameters_new_line_after_left_paren = false -ij_kotlin_method_parameters_right_paren_on_new_line = false -ij_kotlin_method_parameters_wrap = off -ij_kotlin_name_count_to_use_star_import = 5 -ij_kotlin_name_count_to_use_star_import_for_members = 3 -ij_kotlin_parameter_annotation_wrap = off +ij_kotlin_method_annotation_wrap = on_every_item +ij_kotlin_method_call_chain_wrap = normal +ij_kotlin_method_parameters_new_line_after_left_paren = true +ij_kotlin_method_parameters_right_paren_on_new_line = true +ij_kotlin_method_parameters_wrap = on_every_item +ij_kotlin_name_count_to_use_star_import = 2147483647 +ij_kotlin_name_count_to_use_star_import_for_members = 2147483647 +ij_kotlin_packages_to_use_import_on_demand = java.util.*, kotlinx.android.synthetic.*, io.ktor.* +ij_kotlin_parameter_annotation_wrap = on_every_item ij_kotlin_space_after_comma = true ij_kotlin_space_after_extend_colon = true ij_kotlin_space_after_type_colon = true @@ -315,33 +532,63 @@ ij_kotlin_spaces_around_equality_operators = true ij_kotlin_spaces_around_function_type_arrow = true ij_kotlin_spaces_around_logical_operators = true ij_kotlin_spaces_around_multiplicative_operators = true -ij_kotlin_spaces_around_range = false +ij_kotlin_spaces_around_range = true ij_kotlin_spaces_around_relational_operators = true ij_kotlin_spaces_around_unary_operator = false ij_kotlin_spaces_around_when_arrow = true -ij_kotlin_variable_annotation_wrap = off +ij_kotlin_variable_annotation_wrap = on_every_item ij_kotlin_while_on_new_line = false ij_kotlin_wrap_elvis_expressions = 1 -ij_kotlin_wrap_expression_body_functions = 0 +ij_kotlin_wrap_expression_body_functions = 1 ij_kotlin_wrap_first_method_in_call_chain = false -[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config}] -indent_size = 2 -ij_json_keep_blank_lines_in_code = 0 +[{*.graphqlconfig, *.har, *.jsb2, *.jsb3, *.json, .babelrc, .eslintrc, .stylelintrc, bowerrc, jest.config, mcmod.info, pack.mcmeta}] +ij_visual_guides = none +ij_json_keep_blank_lines_in_code = 1 ij_json_keep_indents_on_empty_lines = false ij_json_keep_line_breaks = true ij_json_space_after_colon = true ij_json_space_after_comma = true ij_json_space_before_colon = true ij_json_space_before_comma = false -ij_json_spaces_within_braces = false -ij_json_spaces_within_brackets = false +ij_json_spaces_within_braces = true +ij_json_spaces_within_brackets = true ij_json_wrap_long_lines = false -[{*.yaml,*.yml}] +[{*.markdown, *.md}] +max_line_length = 80 +ij_visual_guides = 80 +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 + +[{*.properties, spring.handlers, spring.schemas}] +ij_visual_guides = none +ij_properties_align_group_field_declarations = false +ij_properties_keep_blank_lines = false +ij_properties_key_value_delimiter = equals +ij_properties_spaces_around_key_value_delimiter = false + +[{*.yaml, *.yml}] indent_size = 2 +ij_visual_guides = none +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 = true 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 + + diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md index 9a1b69189..d074cff47 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.md @@ -37,9 +37,12 @@ assignees: "" --> - [ ] I have checked that I am on the latest version of Terra. -- [ ] I have searched the github issue tracker for similar issues, including closed ones. -- [ ] I have made sure that this is not a bug with another mod or plugin, and it is Terra that is causing the issue. -- [ ] I have checked that this is an issue with Terra and not an issue with the pack I am using. +- [ ] I have searched the github issue tracker for similar issues, including + closed ones. +- [ ] I have made sure that this is not a bug with another mod or plugin, and it + is Terra that is causing the issue. +- [ ] I have checked that this is an issue with Terra and not an issue with the + pack I am using. - [ ] I have attached a copy of the `latest.log` file - [ ] I have filled out and provided all the appropriate information. diff --git a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md index 090354420..c247ba306 100644 --- a/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +++ b/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md @@ -31,9 +31,11 @@ assignees: "" --> - [ ] I have checked that I am on the latest version of Terra. -- [ ] I have searched github for similar features requests, including closed ones, and found none. +- [ ] I have searched github for similar features requests, including closed + ones, and found none. - [ ] I believe this is within the scope of Terra. -- [ ] This feature request is for *all* of Terra, and isn't something that should be implemented by a pack or addon. +- [ ] This feature request is for *all* of Terra, and isn't something that + should be implemented by a pack or addon. ## Feature Description diff --git a/.github/ISSUE_TEMPLATE/OTHER_ISSUES.md b/.github/ISSUE_TEMPLATE/OTHER_ISSUES.md index 1677fab03..a28780af8 100644 --- a/.github/ISSUE_TEMPLATE/OTHER_ISSUES.md +++ b/.github/ISSUE_TEMPLATE/OTHER_ISSUES.md @@ -1,6 +1,7 @@ --- name: "Other Issue" -about: "Use this template if your issue doesn't accurately fit into any of the other categories." +about: "Use this template if your issue doesn't accurately fit into any of the +other categories." title: "" labels: "Type: Question, Status: Pending" assignees: "" @@ -8,4 +9,5 @@ assignees: "" --- ## Describe the issue + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 9c7f2e470..4611034c8 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,11 +1,11 @@ blank_issues_enabled: false contact_links: - - name: Which Issue Template do I Choose? - url: https://github.com/PolyhedralDev/Terra/wiki/How-To-Choose-An-Issue-Template + - name: Which Issue Template do I Choose? + url: https://github.com/PolyhedralDev/Terra/wiki/How-To-Choose-An-Issue-Template about: Click this if you don't know which issue template to select. This will help you make sure you choose the right one and provide enough information for us to help you. - - name: Terra Wiki - url: https://github.com/PolyhedralDev/Terra/wiki + - name: Terra Wiki + url: https://github.com/PolyhedralDev/Terra/wiki about: Documentation for all things Terra. - - name: Join the Support Discord - url: https://discord.dfsek.com + - name: Join the Support Discord + url: https://discord.dfsek.com about: If you have a basic support question, join the Discord instead. \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9db773e99..6d34c7720 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -33,9 +33,11 @@ -- [ ] I am the original author of this code, and I am willing to release it under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html). -- [ ] I am not the original author of this code, but it is in public domain or released - under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html) or a compatible license. +- [ ] I am the original author of this code, and I am willing to release it + under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html). +- [ ] I am not the original author of this code, but it is in public domain or + released under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html) or a + compatible license. - [ ] Build system -- [ ] Documentation +- [ ] + Documentation - [ ] New Feature - [ ] Performance -- [ ] Refactoring -- [ ] Repository +- [ ] + Refactoring +- [ ] + Repository - [ ] Revert - [ ] Style - [ ] Tests -- [ ] Translation +- [ ] + Translation #### Compatiblity -- [ ] Breaking change +- [ ] Breaking + change - [ ] Non-Breaking change. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index af9b7a546..000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,40 +0,0 @@ -# This workflow will build a Java project with Gradle -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle - -name: Java CI with Gradle - -on: - push: - tags: - - "v*" # Push events to matching v*, i.e. v1.0, v20.15.10 - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - - name: Build Terra - run: gradle shadowJar - - - name: Upload artifacts - uses: actions/upload-artifact@v2 - with: - name: Package - path: build/libs - - - name: Publish release - uses: marvinpinto/action-automatic-releases@latest - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - prerelease: false - files: | - build/libs/Terra-*.jar - LICENSE - \ No newline at end of file diff --git a/.gitignore b/.gitignore index cde9583f4..c93edc41f 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,8 @@ hs_err_pid* .idea/**/dictionaries .idea/**/shelf +.idea/ + # Generated files .idea/**/contentModel.xml @@ -127,17 +129,120 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser -# Ignore Gradle build output directory -build -/target/ +### Windows template +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db -.idea/sonarlint/** -.idea/codeStyles/** -.idea/**.xml -.idea/modules/**.iml +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Linux template +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### Application +# Archive love files +*.log.gz + +# binary files +*.bin + +# Database files +*.db + +# Cache files +*.meta +*.data + +### JEnv template +# JEnv local Java version configuration file +.java-version + +# Used by previous versions of JEnv +.jenv-version + +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +### NetBeans template +**/nbproject/private/ +**/nbproject/Makefile-*.mk +**/nbproject/Package-*.bash +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +### +**/target/ -!lib/*.jar /run/ -idea/** -testDir/ \ No newline at end of file +**/testDir/ \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index b2d97634b..d0f7e32c0 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -2,32 +2,41 @@ # TL;DR -Polyhedral Development is dedicated to providing a harassment-free experience for everyone, regardless of gender, gender identity and -expression, preferred pronouns, sexual orientation, disability, physical appearance, age, race, religion, etc. We do not tolerate harassment -of participants in any form. +Polyhedral Development is dedicated to providing a harassment-free experience +for everyone, regardless of gender, gender identity and expression, preferred +pronouns, sexual orientation, disability, physical appearance, age, race, +religion, etc. We do not tolerate harassment of participants in any form. -This code of conduct applies to all Terra community spaces, including the github discussions tab, our -[community discord server](https://discord.gg/PXUEbbF), the [community subreddit](https://reddit.com/r/TerraGenerator), or any other Terra -space, both online and off. Anyone in violation of this code, as determined by the applicable moderators, may be subject to verbal warning, -expulsion from these spaces, or future events and activities for an undetermined amount of time. +This code of conduct applies to all Terra community spaces, including the github +discussions tab, our [community discord server](https://discord.gg/PXUEbbF), +the [community subreddit](https://reddit.com/r/TerraGenerator), or any other +Terra space, both online and off. Anyone in violation of this code, as +determined by the applicable moderators, may be subject to verbal warning, +expulsion from these spaces, or future events and activities for an undetermined +amount of time. -Some Terra community spaces may have additional rules in place, which will be made clearly available to all participants. Participants are -responsible for knowing and abiding by these rules. +Some Terra community spaces may have additional rules in place, which will be +made clearly available to all participants. Participants are responsible for +knowing and abiding by these rules. # Longer version -Polyhedral Development is dedicated to providing a harassment-free experience for everyone. We do not tolerate harassment of participants in -any form. +Polyhedral Development is dedicated to providing a harassment-free experience +for everyone. We do not tolerate harassment of participants in any form. ## When and How to Use These Guidelines -This code of conduct applies to all Terra community spaces, both online and off. This applies to the github discussion tab, -the [Polyhedral Development community discord server](https://discord.gg/PXUEbbF), and any other Terra community. In addition, we may choose -to invoke them in instances of harassment outside the Terra communities, and we will punish the responsible individuals appropriately. We -will not tolerate harassment in any form, even outside of Terra. +This code of conduct applies to all Terra community spaces, both online and off. +This applies to the github discussion tab, the +[Polyhedral Development community discord server](https://discord.gg/PXUEbbF), +and any other Terra community. In addition, we may choose to invoke them in +instances of harassment outside the Terra communities, and we will punish the +responsible individuals appropriately. We will not tolerate harassment in any +form, even outside of Terra. -Some Terra spaces may have additional rules in place, which will be made clearly available to participants. Participants are responsible for -knowing and abiding by these rules, in addition to this code of conduct. +Some Terra spaces may have additional rules in place, which will be made clearly +available to participants. Participants are responsible for knowing and abiding +by these rules, in addition to this code of conduct. ## Expected Behavior @@ -35,33 +44,43 @@ The following behaviors are expected of all members of the Terra community: ### Be Respectful -Value each other's ideas, styles and viewpoints. We may not always agree, but disagreement is no excuse for poor manners. Be open to -different possibilities and to being wrong. Be respectful in all interactions and communications, especially when debating the merits of -different options. Be aware of your impact and how intense interactions may be affecting people. Be direct, constructive and positive. Take -responsibility for your impact, and your mistakes – if someone says they have been harmed through your words or actions, listen carefully, -apologize sincerely, and correct the behavior going forward. +Value each other's ideas, styles and viewpoints. We may not always agree, but +disagreement is no excuse for poor manners. Be open to different possibilities +and to being wrong. Be respectful in all interactions and communications, +especially when debating the merits of different options. Be aware of your +impact and how intense interactions may be affecting people. Be direct, +constructive and positive. Take responsibility for your impact, and your +mistakes – if someone says they have been harmed through your words or actions, +listen carefully, apologize sincerely, and correct the behavior going forward. #### Be Prepared to Admit When You are Wrong -Any member of the Terra community should always be open to new ideas and must always be open to the possibility of being wrong. Nobody can -always be right, and we are only human; we are [fallible](https://www.merriam-webster.com/dictionary/fallible) by nature. It is okay to make -mistakes, but we must be willing to admit when we make one. +Any member of the Terra community should always be open to new ideas and must +always be open to the possibility of being wrong. Nobody can always be right, +and we are only human; we are +[fallible](https://www.merriam-webster.com/dictionary/fallible) by nature. It is +okay to make mistakes, but we must be willing to admit when we make one. ### Be Direct but Professional -We are likely to have some discussions about if and when criticism is respectful and when it's not. We must be able to speak directly when -we disagree and when we think we need to improve. We cannot withhold hard truths. Doing so respectfully is hard, doing so when others don't -seem to be listening is harder, and hearing such comments when one is the recipient can be even harder still. We need to be honest and -direct, as well as respectful. +We are likely to have some discussions about if and when criticism is respectful +and when it's not. We must be able to speak directly when we disagree and when +we think we need to improve. We cannot withhold hard truths. Doing so +respectfully is hard, doing so when others don't seem to be listening is harder, +and hearing such comments when one is the recipient can be even harder still. We +need to be honest and direct, as well as respectful. ### Be Inclusive -Seek diverse perspectives. Diversity of views and of people on teams powers innovation, even if it is not always comfortable. Encourage all -voices. Help new perspectives be heard and listen actively. If you find yourself dominating a discussion, it is especially important to step -back and encourage other voices to join in. Be aware of how much time is taken up by dominant members of the group. Provide alternative ways -to contribute or participate when possible. +Seek diverse perspectives. Diversity of views and of people on teams powers +innovation, even if it is not always comfortable. Encourage all voices. Help new +perspectives be heard and listen actively. If you find yourself dominating a +discussion, it is especially important to step back and encourage other voices +to join in. Be aware of how much time is taken up by dominant members of the +group. Provide alternative ways to contribute or participate when possible. -Be inclusive of everyone in an interaction, respecting and facilitating people's participation whether they are: +Be inclusive of everyone in an interaction, respecting and facilitating people's +participation whether they are: - Not native language speakers - Coming from a different culture @@ -70,47 +89,60 @@ Be inclusive of everyone in an interaction, respecting and facilitating people's - Facing other challenges to participate - Or anything else. Be respectful of *everyone* at *all times*. -Think about how you might facilitate alternative ways to contribute or participate. If you find yourself dominating a discussion, step back. -Make way for other voices and listen actively to them. +Think about how you might facilitate alternative ways to contribute or +participate. If you find yourself dominating a discussion, step back. Make way +for other voices and listen actively to them. ### Understand Different Perspectives -Our goal should not be to "win" every disagreement or argument. A more productive goal is to be open to ideas that make our own ideas -better. Strive to be an example for inclusive thinking. "Winning" is when different perspectives make our work richer and stronger. That -means, you must pay attention to all ideas proposed. Don't disregard one without giving it the attention it deserves. +Our goal should not be to "win" every disagreement or argument. A more +productive goal is to be open to ideas that make our own ideas better. Strive to +be an example for inclusive thinking. "Winning" is when different perspectives +make our work richer and stronger. That means, you must pay attention to all +ideas proposed. Don't disregard one without giving it the attention it deserves. ### Appreciate and Accommodate Our Similarities and Differences -People come from many cultures and backgrounds. Cultural differences can encompass everything from official religious observances to -personal habits to clothing. Be respectful of anyone with different cultural practices, attitudes and beliefs. Work to eliminate your own -biases, prejudices and discriminatory practices. Think of others' needs from their point of view. Use preferred titles (including -pronouns[\[1\]](#1)) and the appropriate tone of voice. Respect people's right to privacy and confidentiality. Be open to -learning from and educating others as well as educating yourself; it is unrealistic to expect someone to know the cultural practices of -every ethnic and cultural group. Therefore we must be ready to correct someone if they make a mistake, and must be ready ourselves to change -and learn if we make a mistake. +People come from many cultures and backgrounds. Cultural differences can +encompass everything from official religious observances to personal habits to +clothing. Be respectful of anyone with different cultural practices, attitudes +and beliefs. Work to eliminate your own biases, prejudices and discriminatory +practices. Think of others' needs from their point of view. Use preferred +titles (including pronouns[\[1\]](#1)) and the appropriate tone of +voice. Respect people's right to privacy and confidentiality. Be open to +learning from and educating others as well as educating yourself; it is +unrealistic to expect someone to know the cultural practices of every ethnic and +cultural group. Therefore we must be ready to correct someone if they make a +mistake, and must be ready ourselves to change and learn if we make a mistake. ### Lead by Example -By matching your actions with your words, you become a person others want to follow. Your actions influence others to behave and respond in -ways that are valuable and appropriate for our organizational outcomes. Design your community and your work for inclusion. Hold yourself and -others accountable for inclusive behaviors. +By matching your actions with your words, you become a person others want to +follow. Your actions influence others to behave and respond in ways that are +valuable and appropriate for our organizational outcomes. Design your community +and your work for inclusion. Hold yourself and others accountable for inclusive +behaviors. ## Behavior That Will Not Be Tolerated -The following behaviors are considered to be unacceptable and will not be tolerated: +The following behaviors are considered to be unacceptable and will not be +tolerated: ### Violence and Threats of Violence -Violence and threats of violence are not acceptable - online or offline. This includes incitement of violence toward any individual, -including encouraging a person to commit self-harm, engage in self-harm, or put themselves in a negative position (e.g. one which can lead -to an increase of depression, etc.). +Violence and threats of violence are not acceptable - online or offline. This +includes incitement of violence toward any individual, including encouraging a +person to commit self-harm, engage in self-harm, or put themselves in a negative +position (e.g. one which can lead to an increase of depression, etc.). ### Personal Attacks -Conflicts will inevitably arise, but frustration should never turn into a personal attack. It is not okay to insult, demean or belittle -others. Attacking someone for their opinions, beliefs and ideas is not acceptable. It is important to speak directly when we disagree and -when we think we need to improve, but such discussions must be conducted respectfully and professionally, remaining focused on the issue at -hand. +Conflicts will inevitably arise, but frustration should never turn into a +personal attack. It is not okay to insult, demean or belittle others. Attacking +someone for their opinions, beliefs and ideas is not acceptable. It is important +to speak directly when we disagree and when we think we need to improve, but +such discussions must be conducted respectfully and professionally, remaining +focused on the issue at hand. ### Derogatory Language @@ -135,30 +167,40 @@ Offensive, unwelcome, or hurtful comments related to: - Socioeconomic status - Religion - Employment -- Or anything really. Just don't be offensive towards people, insult them, or make unwanted comments. +- Or anything really. Just don't be offensive towards people, insult them, or + make unwanted comments. -is not acceptable. This includes deliberately referring to someone by a gender that they do not identify with, and/or questioning the -legitimacy of an individual's gender identity. If you're unsure if a word is derogatory, don't use it. This also includes repeated subtle -and/or indirect discrimination; when asked to stop, stop the behavior in question. +is not acceptable. This includes deliberately referring to someone by a gender +that they do not identify with, and/or questioning the legitimacy of an +individual's gender identity. If you're unsure if a word is derogatory, don't +use it. This also includes repeated subtle and/or indirect discrimination; when +asked to stop, stop the behavior in question. ### Unwelcome Sexual Attention or Physical Contact -Unwelcome sexual attention or unwelcome physical contact is not acceptable. This includes sexualized comments, jokes or imagery in -interactions, communications or presentation materials, as well as inappropriate touching, groping, or sexual advances. Additionally, -touching a person without permission, including sensitive areas such as their hair, pregnant stomach, mobility device (wheelchair, scooter, -etc) or tattoos is unacceptable. This includes physically blocking or intimidating another person. Physical contact or simulated physical -contact (e.g. emojis like ":​kiss:", ":hug:", or ":kiss_mark:", textual descriptions like "\*hug\*", "\*backrub\*", or "\*kisses -you\*", etc.) without affirmative consent or after a request to stop will not be accepted. +Unwelcome sexual attention or unwelcome physical contact is not acceptable. This +includes sexualized comments, jokes or imagery in interactions, communications +or presentation materials, as well as inappropriate touching, groping, or sexual +advances. Additionally, touching a person without permission, including +sensitive areas such as their hair, pregnant stomach, mobility device ( +wheelchair, scooter, etc) or tattoos is unacceptable. This includes physically +blocking or intimidating another person. Physical contact or simulated physical +contact (e.g. emojis like ":​kiss:", ":hug:", or ":kiss_mark:", textual +descriptions like "\*hug\*", "\*backrub\*", or "\*kisses you\*", etc.) without +affirmative consent or after a request to stop will not be accepted. ### Sexual Behaviour Where it is Not Appropriate -Uninvited or off-topic sexual images, text, or behaviour in spaces where they're not appropriate will not be accepted whatsoever. We are an -open community, which means spaces must be appropriate for all ages, and everybody must feel comfortable. Discussion of sexual things, will -be prohibited unless otherwise noted. +Uninvited or off-topic sexual images, text, or behaviour in spaces where they're +not appropriate will not be accepted whatsoever. We are an open community, which +means spaces must be appropriate for all ages, and everybody must feel +comfortable. Discussion of sexual things, will be prohibited unless otherwise +noted. ### Discussion of Sensitive Topics -Discussion of sensitive topics when asked to stop, or when not appropriate. Including, but not limited to: +Discussion of sensitive topics when asked to stop, or when not appropriate. +Including, but not limited to: - Anything sexual - Gore @@ -167,171 +209,241 @@ Discussion of sensitive topics when asked to stop, or when not appropriate. Incl - Anything related to death - Or really anything that someone may be sensitive about. -shall not be tolerated. As a community for all ages and all kinds of people, we must cater to everyone, and must make sure everyone feels -comfortable here. Repeatedly breaking someone else's boundaries will not be tolerated. +shall not be tolerated. As a community for all ages and all kinds of people, we +must cater to everyone, and must make sure everyone feels comfortable here. +Repeatedly breaking someone else's boundaries will not be tolerated. ### Disruptive Behavior -Sustained disruption of events, forums, or meetings, online or otherwise, including talks and presentations, will not be tolerated. This -includes: +Sustained disruption of events, forums, or meetings, online or otherwise, +including talks and presentations, will not be tolerated. This includes: - 'Talking over', 'heckling', or otherwise disrupting speakers. -- Making derogatory comments about someone else's choices, pushing people to do something they do not wish to do, talking about their - choices or personal preferences to others, or pressuring them to do something they don't wish to - physically or through jeering. +- Making derogatory comments about someone else's choices, pushing people to do + something they do not wish to do, talking about their choices or personal + preferences to others, or pressuring them to do something they don't wish to - + physically or through jeering. - Behaviour that intentionally disrupts an event. - Otherwise influencing actions that may cause hostility in the session. ### Influencing Unacceptable Behavior -We will treat influencing or leading such activities the same way we treat the activities themselves, and thus the same consequences apply. -To make someone do something bad is the same thing as if you were to do it yourself, and we will not tolerate it. +We will treat influencing or leading such activities the same way we treat the +activities themselves, and thus the same consequences apply. To make someone do +something bad is the same thing as if you were to do it yourself, and we will +not tolerate it. ### Stalking or Following -Stalking or following in any form (offline or online) is unnacceptable. In addition, you may not take pictures or record video of others -without their express permission or when asked to stop. Any individual may also request for you to delete all footage you have of them, even -if you took it with their prior consent. +Stalking or following in any form (offline or online) is unnacceptable. In +addition, you may not take pictures or record video of others without their +express permission or when asked to stop. Any individual may also request for +you to delete all footage you have of them, even if you took it with their prior +consent. ### Publication of Personal Information -The publication of personally identifying information (commonly known as "[doxxing](https://en.wikipedia.org/wiki/Doxing)") is directly -prohibited. You may not publish information that someone wants to keep private, unless it is necessary to protect vulnerable people from -intentional abuse. Addditionally, you may not deliberately "out" any aspect of a person's identity without their consent, this includes -gender, pronouns, sexual identity, etc. +The publication of personally identifying information (commonly known +as "[doxxing](https://en.wikipedia.org/wiki/Doxing)") is directly prohibited. +You may not publish information that someone wants to keep private, unless it is +necessary to protect vulnerable people from intentional abuse. Addditionally, +you may not deliberately "out" any aspect of a person's identity without their +consent, this includes gender, pronouns, sexual identity, etc. -Unless it pretains to a case of harassment, as outlined here, in which case some personally identifying information may need to be brought -up in private with the appropriate moderation team to help aid our efforts in keeping the community safe. +Unless it pretains to a case of harassment, as outlined here, in which case some +personally identifying information may need to be brought up in private with the +appropriate moderation team to help aid our efforts in keeping the community +safe. ### Deliberate Misuse of Pronouns[\[1\]](#1) or Names -As an inclusive community, we must respect everyone. That means respecting the pronouns or names they wish for us to use. Deliberate -misgendering, misuse of preferred pronouns[\[1\]](#1), or use of 'dead' or rejected names is not to be tolerated. (If someone -*accidentally* uses the incorrect pronouns, gender, or name, politely ask them to use the correct pronouns/gender/name. But if they are to -continue using the incorrect pronouns, gender, or name, then you should escalate and report them to us.) +As an inclusive community, we must respect everyone. That means respecting the +pronouns or names they wish for us to use. Deliberate misgendering, misuse of +preferred pronouns[\[1\]](#1), or use of 'dead' or rejected names is +not to be tolerated. (If someone +*accidentally* uses the incorrect pronouns, gender, or name, politely ask them +to use the correct pronouns/gender/name. But if they are to continue using the +incorrect pronouns, gender, or name, then you should escalate and report them to +us.) ### Not Stopping After Multiple Requests -If someone asks you to stop doing something, then you should stop. Continuing to do it may be considered harassment, and can lead you to be -removed from our community. +If someone asks you to stop doing something, then you should stop. Continuing to +do it may be considered harassment, and can lead you to be removed from our +community. ## Complains We May Ignore -Additionally, Terra prioritizes marginalized people's safety over privileged people's comfort. We reserve the right to ignore complaints -regarding: +Additionally, Terra prioritizes marginalized people's safety over privileged +people's comfort. We reserve the right to ignore complaints regarding: -- Claims of discrimination against non-marginalized or oppressed groups (eg. being 'superphobic', meaning to not support people who are - 'superstraight', which is a dog whistle for transphobic groups, or being 'cisphobic' without large amounts of evidence, etc.), or claims - of discrimination with no evidence. (Basically, don't report 'cisphobia' to us, because it doesn't exist. But if someone is mocking you or - making fun of you for being cis, and it is *really* getting out of hand, then do tell us.) -- Reasonable communication of boundaries, such as "leave me alone," "go away," or "I'm not discussing this with you." (If someone is asking - you to stop, that is not reason for you to report them as harassing you.) -- Communicating in a 'tone' you don't find [congenial](https://www.thefreedictionary.com/congenial). (You may not report someone for - harassment for being 'annoyed with you' or 'talking sternly to you') -- Criticizing or calling out racist, sexist, discriminatory, or otherwise oppressive behavior or assumptions. (You may not say that someone - is harassing you if they are telling you to stop discriminating against someone.) -- Disagreements that do not qualify as harassment. If you have a simple disagreement with someone, and they have not been discriminating to - anyone, in any form, then we will not take action against them. Two people are allowed to disagree on things without it getting toxic. +- Claims of discrimination against non-marginalized or oppressed groups (eg. + being 'superphobic', meaning to not support people who are + 'superstraight', which is a dog whistle for transphobic groups, or being ' + cisphobic' without large amounts of evidence, etc.), or claims of + discrimination with no evidence. (Basically, don't report 'cisphobia' to us, + because it doesn't exist. But if someone is mocking you or making fun of you + for being cis, and it is *really* getting out of hand, then do tell us.) +- Reasonable communication of boundaries, such as "leave me alone," "go away," + or "I'm not discussing this with you." (If someone is asking you to stop, that + is not reason for you to report them as harassing you.) +- Communicating in a 'tone' you don't + find [congenial](https://www.thefreedictionary.com/congenial). (You may not + report someone for harassment for being 'annoyed with you' or 'talking sternly + to you') +- Criticizing or calling out racist, sexist, discriminatory, or otherwise + oppressive behavior or assumptions. (You may not say that someone is harassing + you if they are telling you to stop discriminating against someone.) +- Disagreements that do not qualify as harassment. If you have a simple + disagreement with someone, and they have not been discriminating to anyone, in + any form, then we will not take action against them. Two people are allowed to + disagree on things without it getting toxic. -We may also additionally choose to enact punishment for submitting a complaint in bad-faith or without adequate justification, if we deem -necessary; if you're submitting a complaint just to troll or to annoy people, we may choose to have you banned or removed from the community -spaces. Don't waste our time. +We may also additionally choose to enact punishment for submitting a complaint +in bad-faith or without adequate justification, if we deem necessary; if you're +submitting a complaint just to troll or to annoy people, we may choose to have +you banned or removed from the community spaces. Don't waste our time. -In order to protect volunteers from abuse and burnout, we reserve the right to reject any report we believe to have been made in bad faith -or with misintent. Reports intended to silence legitimate criticism may be deleted without response. +In order to protect volunteers from abuse and burnout, we reserve the right to +reject any report we believe to have been made in bad faith or with misintent. +Reports intended to silence legitimate criticism may be deleted without +response. ## Reporting -Terra has a global moderation team which is currently comprised of the following members: +Terra has a global moderation team which is currently comprised of the following +members: - solonovamax - - discord: [@solonovamax#6983](https://discord.com/channels/@me/566146322273402881)* + - + discord: [@solonovamax#6983](https://discord.com/channels/@me/566146322273402881)* - github: [@solonovamax](https://github.com/solonovamax) - - email: [solonovamax@12oclockpoint.com](mailto:solonovamax@12oclockpoint.com) + - + email: [solonovamax@12oclockpoint.com](mailto:solonovamax@12oclockpoint.com) - dfsek - - discord: [@dfsek#4208](https://discord.com/channels/@me/378350362236682240)* + - + discord: [@dfsek#4208](https://discord.com/channels/@me/378350362236682240)* - github: [@dfsek](https://github.com/dfsek) - email: [dfsek@protonmail.com](mailto:dfsek@protonmail.com) - duplex (duplexsystem) - - discord: [@Duplex#0797](https://discord.com/channels/@me/356822848641171456)* + - + discord: [@Duplex#0797](https://discord.com/channels/@me/356822848641171456)* - github: [@duplexsystem](https://github.com/duplexsystem) - email: [duplexsys@protonmail.com](mailto:duplexsys@protonmail.com) -\* The preferred method of communication is through discord. Although we will still be responsive on the other platforms, we will be more -responsive on discord. +\* The preferred method of communication is through discord. Although we will +still be responsive on the other platforms, we will be more responsive on +discord. These are people you can contact for anything regarding this code of conduct. -If you are being harassed by a member of the Terra community, or by someone in a Terra community space, notice that someone else is being -harassed, or have any other concerns, please contact a moderator of the platform it occurred on, or someone on the global moderation team. -If the person who is harassing you is on the global moderation team, they will [recuse](https://www.thefreedictionary.com/recuse) themselves -from handling your incident. (Meaning: if you are reporting someone on the team, they will not be involved in the discussion.) We will -respond within a reasonable time frame, but generally within about 1 day. +If you are being harassed by a member of the Terra community, or by someone in a +Terra community space, notice that someone else is being harassed, or have any +other concerns, please contact a moderator of the platform it occurred on, or +someone on the global moderation team. If the person who is harassing you is on +the global moderation team, they +will [recuse](https://www.thefreedictionary.com/recuse) themselves from handling +your incident. (Meaning: if you are reporting someone on the team, they will not +be involved in the discussion.) We will respond within a reasonable time frame, +but generally within about 1 day. -This code of conduct applies to Terra community spaces, but if you are being harassed by a member of Terra *outside* our spaces, we still -want to know about it as we may choose to take action within our community. We will take all good-faith reports seriously and will always -attempt to handle them appropriately. This includes harassment outside our spaces and harassment that took place at any point in time. The -moderation team reserves the right to exclude people from Terra communities based on their past behavior, including behavior outside Terra -spaces and behavior towards people who are not in Terra. +This code of conduct applies to Terra community spaces, but if you are being +harassed by a member of Terra *outside* our spaces, we still want to know about +it as we may choose to take action within our community. We will take all +good-faith reports seriously and will always attempt to handle them +appropriately. This includes harassment outside our spaces and harassment that +took place at any point in time. The moderation team reserves the right to +exclude people from Terra communities based on their past behavior, including +behavior outside Terra spaces and behavior towards people who are not in Terra. -Note: although we only have the ability to moderate official community spaces, if you are being harassed by someone in a non-official -community space, and the moderation team of that platform refuses to do anything to help you (or even if they *do* help you), then you -should notify us so that we may take appropriate action. +Note: although we only have the ability to moderate official community spaces, +if you are being harassed by someone in a non-official community space, and the +moderation team of that platform refuses to do anything to help you (or even if +they *do* help you), then you should notify us so that we may take appropriate +action. -We will respect confidentiality requests for the purpose of protecting victims of abuse. At our discretion, we may publicly name a person -which we have received harassment complaints about, or privately warn third parties about them, but only if we believe that doing so will -increase the safety of Terra community members or the general public. We will not name harassment victims or reporters of harassment -(assuming the report was made in good-faith) without their explicit consent; all reports will remain anonymous by default. +We will respect confidentiality requests for the purpose of protecting victims +of abuse. At our discretion, we may publicly name a person which we have +received harassment complaints about, or privately warn third parties about +them, but only if we believe that doing so will increase the safety of Terra +community members or the general public. We will not name harassment victims or +reporters of harassment +(assuming the report was made in good-faith) without their explicit consent; all +reports will remain anonymous by default. ## Consequences of Unacceptable Behavior -Participants asked to stop any harassing behavior are expected to comply immediately. Whether or not you comply immediately, you may still -face consequences for you actions, but if the harasser doesn't comply immediately then we may choose to take additional actions to protect -the Terra community members or the individual being harassed. +Participants asked to stop any harassing behavior are expected to comply +immediately. Whether or not you comply immediately, you may still face +consequences for you actions, but if the harasser doesn't comply immediately +then we may choose to take additional actions to protect the Terra community +members or the individual being harassed. -Violation of this code can result in being asked to leave an event or online space, either temporarily or for the duration of the event, or -being banned from participation in spaces, or future events and activities in perpetuity. If a participant engages in harassing behavior, -the global moderation team may take any action they deem appropriate, up to and including expulsion from all Terra community spaces and -identification of the participant as a harasser to other Terra community members or the general public. Bad behavior from any community +Violation of this code can result in being asked to leave an event or online +space, either temporarily or for the duration of the event, or being banned from +participation in spaces, or future events and activities in perpetuity. If a +participant engages in harassing behavior, the global moderation team may take +any action they deem appropriate, up to and including expulsion from all Terra +community spaces and identification of the participant as a harasser to other +Terra community members or the general public. Bad behavior from any community member, including those with decision-making authority, will not be tolerated. -In addition, any participants who abuse the reporting process will be considered to be in violation of these guidelines and subject to -consequences. False reporting, especially to retaliate or exclude, will not be accepted or tolerated. +In addition, any participants who abuse the reporting process will be considered +to be in violation of these guidelines and subject to consequences. False +reporting, especially to retaliate or exclude, will not be accepted or +tolerated. ## Questions -if you have further questions for anything not addressed here, you may open an issue on this github repo, or contact a member of the global -moderation team. +if you have further questions for anything not addressed here, you may open an +issue on this github repo, or contact a member of the global moderation team. ## License and Attribution This set of guidelines is distributed under a -[Creative Commons Attribution-ShareAlike license](https://creativecommons.org/licenses/by-sa/3.0/). +[Creative Commons Attribution-ShareAlike license](https://creativecommons.org/licenses/by-sa/3.0/) +. These guidelines have been adapted from -[Mozilla's Community Participation Guidelines](https://www.mozilla.org/en-US/about/governance/policies/participation/), which were adapted -from: +[Mozilla's Community Participation Guidelines](https://www.mozilla.org/en-US/about/governance/policies/participation/) +, which were adapted from: - Mozilla's original Community Participation Guidelines - The [Ubuntu Code of Conduct](https://ubuntu.com/community/code-of-conduct) -- Mozilla's [View Source Conference Code of Conduct](https://viewsourceconf.org/berlin-2016/code-of-conduct/) -- And the [Rust Language Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct) +- -which in turn were based on [Stumptown Syndicate's Citizen Code of Conduct](http://citizencodeofconduct.org/), along with some adapted text -from the [LGBTQ in Technology Code of Conduct](https://lgbtq.technology/coc.html) and -the [WisCon code of conduct](http://wiscon.net/policies/anti-harassment/code-of-conduct/). +Mozilla's [View Source Conference Code of Conduct](https://viewsourceconf.org/berlin-2016/code-of-conduct/) + +- And + the [Rust Language Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct) + +which in turn were based +on [Stumptown Syndicate's Citizen Code of Conduct](http://citizencodeofconduct.org/) +, along with some adapted text from +the [LGBTQ in Technology Code of Conduct](https://lgbtq.technology/coc.html) and +the [WisCon code of conduct](http://wiscon.net/policies/anti-harassment/code-of-conduct/) +. It was then modified by solonovamax with various inclusions from -the [LGBTQ in Technology Code of Conduct](https://lgbtq.technology/coc.html) and a few other sources. +the [LGBTQ in Technology Code of Conduct](https://lgbtq.technology/coc.html) and +a few other sources. ## Notes #### \[1\] -You provide a set of pronouns that everyone is comfortable addressing you with. Although some people are comfortable -using [neopronouns](https://www.mypronouns.org/neopronouns), not everyone is. Therefore, if you use neopronouns, you should have at *least* -one set of more common pronouns (One of he/him, she/her, or they/them; it doesn't matter which one. Anyone who doesn't respect your basic -pronouns will be removed from the community.) that people may use, should they so choose, as some people are not comfortable -using [neopronouns](https://www.mypronouns.org/neopronouns). But if someone refuses to use your more common pronouns, you should report them -to us. Additionally, you may not ask people to use unreasonable pronouns, such as 'acab/acabself', 'that/bitch', 'ur/mom', or -'dream/dreamself' (pronouns related to real people, eg. the minecraft youtuber 'dreamwastaken'). Doing so will be considered mockery of -individuals who use non-standard pronouns and is very disrespectful. \ No newline at end of file +You provide a set of pronouns that everyone is comfortable addressing you with. +Although some people are comfortable +using [neopronouns](https://www.mypronouns.org/neopronouns), not everyone is. +Therefore, if you use neopronouns, you should have at *least* +one set of more common pronouns (One of he/him, she/her, or they/them; it +doesn't matter which one. Anyone who doesn't respect your basic pronouns will be +removed from the community.) that people may use, should they so choose, as some +people are not comfortable +using [neopronouns](https://www.mypronouns.org/neopronouns). But if someone +refuses to use your more common pronouns, you should report them to us. +Additionally, you may not ask people to use unreasonable pronouns, such as ' +acab/acabself', 'that/bitch', 'ur/mom', or +'dream/dreamself' (pronouns related to real people, eg. the minecraft youtuber ' +dreamwastaken'). Doing so will be considered mockery of individuals who use +non-standard pronouns and is very disrespectful. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 743a1face..bbb72ecad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,17 +1,22 @@ # Contributing to Terra -First off, thank you for considering contributing to Terra. It's people like you that make Terra such a great tool. +First off, thank you for considering contributing to Terra. It's people like you +that make Terra such a great tool. -Following these guidelines helps to effectively use the time of the developers managing and developing this open source project, making it -more enjoyable for all of us. +Following these guidelines helps to effectively use the time of the developers +managing and developing this open source project, making it more enjoyable for +all of us. -Terra is an open source project and we love to receive contributions from our community, you! There are many ways to contribute, from -writing tutorials or blog posts, improving the documentation, submitting bug reports and feature requests or writing code which can be -incorporated into Terra. +Terra is an open source project and we love to receive contributions from our +community, you! There are many ways to contribute, from writing tutorials or +blog posts, improving the documentation, submitting bug reports and feature +requests or writing code which can be incorporated into Terra. -The following is a set of guidelines for contributing to Terra and its packages, which are hosted in -the [PolyhedralDev Organization](https://github.com/PolyhedralDev) on GitHub. These are mostly guidelines, not rules. Use your best -judgment, and feel free to propose changes to this document in a pull request. +The following is a set of guidelines for contributing to Terra and its packages, +which are hosted in +the [PolyhedralDev Organization](https://github.com/PolyhedralDev) on GitHub. +These are mostly guidelines, not rules. Use your best judgment, and feel free to +propose changes to this document in a pull request. #### Table Of Contents @@ -51,8 +56,10 @@ judgment, and feel free to propose changes to this document in a pull request. ## Code of Conduct -This project and everyone participating in it is governed by the [Terra of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected -to uphold this code. Please report unacceptable behavior to [Terra global moderation team](CODE_OF_CONDUCT.md#Reporting). +This project and everyone participating in it is governed by +the [Terra of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected +to uphold this code. Please report unacceptable behavior +to [Terra global moderation team](CODE_OF_CONDUCT.md#Reporting). ## I don't want to read this whole thing I just have a question!!! @@ -66,160 +73,219 @@ We have an official discord server where you can request help from various users ### Your First Contribution -Unsure where to begin contributing to Terra? You can start by looking through "beginner" and "help wanted" issues: +Unsure where to begin contributing to Terra? You can start by looking through " +beginner" and "help wanted" issues: -- [Beginner issues](https://github.com/PolyhedralDev/Terra/labels/Note%3A%20Good%20First%20Issue) - issues which should be friendly to - anyone new to terra. -- [Help wanted issues](https://github.com/PolyhedralDev/Terra/labels/Note%3A%20Help%20Wanted) - issues which should be a bit more involved - than "beginner" issues. +- [Beginner issues](https://github.com/PolyhedralDev/Terra/labels/Note%3A%20Good%20First%20Issue) + - issues which should be friendly to anyone new to terra. +- [Help wanted issues](https://github.com/PolyhedralDev/Terra/labels/Note%3A%20Help%20Wanted) + - issues which should be a bit more involved than "beginner" issues. New to github? Working on your first Pull Request? Check out [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github) to get you up on your feet. -At this point, you're ready to make your changes! Feel free to ask for help; everyone is a beginner at first! +At this point, you're ready to make your changes! Feel free to ask for help; +everyone is a beginner at first! -If a maintainer asks you to "rebase" your PR, they're saying that a lot of code has changed, and that you need to update your branch so it's -easier to merge. +If a maintainer asks you to "rebase" your PR, they're saying that a lot of code +has changed, and that you need to update your branch so it's easier to merge. ### Reporting Bugs -This section guides you through submitting a bug report for Terra. Following these guidelines helps maintainers and the community understand -your report, and spend their time fixing the issue instead of understanding what you mean. +This section guides you through submitting a bug report for Terra. Following +these guidelines helps maintainers and the community understand your report, and +spend their time fixing the issue instead of understanding what you mean. -Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create -one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). +Before creating bug reports, please +check [this list](#before-submitting-a-bug-report) as you might find out that +you don't need to create one. When you are creating a bug report, +please [include as many details as possible](#how-do-i-submit-a-good-bug-report) +. > **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. #### Before Submitting A Bug Report -- Join the [discord server](https://discord.dfsek.com) to help resolve simple issues. -- You must be on the LATEST version of Terra to receive any support. There is no support for older versions of Terra. -- Make sure that this is not a *specific* compatibility issue with another terrain generation mod. Do not request *specific* compatibility - with mods or plugins (e.g. "Compatibility with TechCraft v7"). That should be implemented in an addon, **not** in the main project. - *General* compatibility (e.g. "Ability to pull Vanilla/Modded features from parent biomes") will be considered in the main project. -- Search for any [already existing issues](https://github.com/PolyhedralDev/Terra/issues?q=is%3Aissue+) open with your problem. If you open - a duplicate, it will be closed as such. -- Make sure that it is actually Terra causing the issue, and not another mod/plugin. You can do this by testing to see if you can recreate - the issue without Terra installed. -- Double check that this is not an issue with a specific Terra *pack* or Terra *addon*, and instead applies to all of Terra. -- Include a copy of the latest.log file. Putting *just* the exception is not enough. We need to be able to check that there wasn't anything - else before that caused it. -- Be sure to fill out all the required information and give descriptions of everything. +- Join the [discord server](https://discord.dfsek.com) to help resolve simple + issues. +- You must be on the LATEST version of Terra to receive any support. There is no + support for older versions of Terra. +- Make sure that this is not a *specific* compatibility issue with another + terrain generation mod. Do not request *specific* compatibility with mods or + plugins (e.g. "Compatibility with TechCraft v7"). That should be implemented + in an addon, **not** in the platform project. + *General* compatibility (e.g. "Ability to pull Vanilla/Modded features from + parent biomes") will be considered in the platform project. +- Search for + any [already existing issues](https://github.com/PolyhedralDev/Terra/issues?q=is%3Aissue+) + open with your problem. If you open a duplicate, it will be closed as such. +- Make sure that it is actually Terra causing the issue, and not another + mod/plugin. You can do this by testing to see if you can recreate the issue + without Terra installed. +- Double check that this is not an issue with a specific Terra *pack* or Terra * + addon*, and instead applies to all of Terra. +- Include a copy of the latest.log file. Putting *just* the exception is not + enough. We need to be able to check that there wasn't anything else before + that caused it. +- Be sure to fill out all the required information and give descriptions of + everything. #### How Do I Submit A (Good) Bug Report? Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/) -. [Create an issue](https://github.com/PolyhedralDev/Terra/issues/new) and provide the prerequisite information by filling in the Bug Report -template. +. [Create an issue](https://github.com/PolyhedralDev/Terra/issues/new) and +provide the prerequisite information by filling in the Bug Report template. -Explain the problem and include additional details to help maintainers reproduce the problem: +Explain the problem and include additional details to help maintainers reproduce +the problem: - **Use a clear and descriptive title** for the issue to identify the problem. -- **Describe the exact steps which reproduce the problem** in as many details as possible. When listing steps, **don't just say what you - did, but explain how you did it**. +- **Describe the exact steps which reproduce the problem** in as many details as + possible. When listing steps, **don't just say what you did, but explain how + you did it**. - **Provide specific examples to demonstrate the steps**. -- **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. +- **Describe the behavior you observed after following the steps** and point out + what exactly is the problem with that behavior. - **Explain which behavior you expected to see instead and why.** -- **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more - information using the guidelines below. +- **If the problem wasn't triggered by a specific action**, describe what you + were doing before the problem happened and share more information using the + guidelines below. Include details about your configuration and environment: -- **Which version of Terra are you using?** You can get the exact version by running `/te version`. -- **What's the name and version of the platform you're using**? (eg. Spigot, Fabric, Paper, etc.) +- **Which version of Terra are you using?** You can get the exact version by + running `/te version`. +- **What's the name and version of the platform you're using**? (eg. Spigot, + Fabric, Paper, etc.) - **Which external plugins or mods do you have installed?** -- **Which Terra packs do you have installed?** You can get that list by running `/te packs`. -- **Which Terra addons do you have installed?** You can get that list by running `/te addons`. +- **Which Terra packs do you have installed?** You can get that list by + running `/te packs`. +- **Which Terra addons do you have installed?** You can get that list by + running `/te addons`. ### Suggesting Enhancements -This section guides you through submitting an enhancement suggestion for Terra, including completely new features and minor improvements to -existing functionality. Following these guidelines helps maintainers and the community understand your suggestion and find related -suggestions. +This section guides you through submitting an enhancement suggestion for Terra, +including completely new features and minor improvements to existing +functionality. Following these guidelines helps maintainers and the community +understand your suggestion and find related suggestions. -Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that -you don't need to create one. When you are creating an enhancement suggestion, -please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). +Before creating enhancement suggestions, please +check [this list](#before-submitting-an-enhancement-suggestion) as you might +find out that you don't need to create one. When you are creating an enhancement +suggestion, +please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion) +. #### Before Submitting An Enhancement Suggestion -- You must be on the **LATEST** version of Terra to make sure your feature hasn't been added yet. -- Search for any [already existing issues](https://github.com/PolyhedralDev/Terra/issues?q=is%3Aissue+) (Including closed!) with your - problem. If you open a duplicate, it will be closed as such. +- You must be on the **LATEST** version of Terra to make sure your feature + hasn't been added yet. +- Search for + any [already existing issues](https://github.com/PolyhedralDev/Terra/issues?q=is%3Aissue+) ( + Including closed!) with your problem. If you open a duplicate, it will be + closed as such. - Verify that this is actually within the scope of Terra. -- Be sure that this is not a feature request that should be made for a specific Terra *pack*, and instead applies to all of Terra. -- Be sure that this is not something that should be implemented as a Terra addon, and instead applies to all of Terra. -- Make sure that you attach a copy of the latest.log file, if there are any exceptions thrown in the console. Putting *just* the exception - **is not enough**. We need to be able to check that there wasn't anything else before that caused it. +- Be sure that this is not a feature request that should be made for a specific + Terra *pack*, and instead applies to all of Terra. +- Be sure that this is not something that should be implemented as a Terra + addon, and instead applies to all of Terra. +- Make sure that you attach a copy of the latest.log file, if there are any + exceptions thrown in the console. Putting *just* the exception + **is not enough**. We need to be able to check that there wasn't anything else + before that caused it. #### How Do I Submit A (Good) Enhancement Suggestion? -Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). Create an issue on our main repository -and provide the following information: +Enhancement suggestions are tracked +as [GitHub issues](https://guides.github.com/features/issues/). Create an issue +on our platform repository and provide the following information: -- **Use a clear and descriptive title** for the issue to identify the suggestion. -- **Provide a step-by-step description of the suggested enhancement** in as many details as possible. +- **Use a clear and descriptive title** for the issue to identify the + suggestion. +- **Provide a step-by-step description of the suggested enhancement** in as many + details as possible. - **Provide specific examples to demonstrate the steps**. -- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. -- **Explain why this enhancement would be useful** to most Terra users and isn't something that can or should be implemented as an addon. +- **Describe the current behavior** and **explain which behavior you expected to + see instead** and why. +- **Explain why this enhancement would be useful** to most Terra users and isn't + something that can or should be implemented as an addon. ### Pull Requests This section guides you through submitting a pull request for Terra. -While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete -additional design work, tests, or other changes before your pull request can be ultimately accepted. +While the prerequisites above must be satisfied prior to having your pull +request reviewed, the reviewer(s) may ask you to complete additional design +work, tests, or other changes before your pull request can be ultimately +accepted. #### Before Submitting A Pull Request -- You must be on the **LATEST** version of Terra to make sure your feature hasn't been added yet. -- Search for any [already existing issues](https://github.com/PolyhedralDev/Terra/issues?q=is%3Aissue+) (Including closed!) with your - problem. If you open a duplicate, it will be closed as such. +- You must be on the **LATEST** version of Terra to make sure your feature + hasn't been added yet. +- Search for + any [already existing issues](https://github.com/PolyhedralDev/Terra/issues?q=is%3Aissue+) ( + Including closed!) with your problem. If you open a duplicate, it will be + closed as such. - Verify that this is actually within the scope of Terra. -- Be sure that this is not a feature request that should be made for a specific Terra *pack*, and instead applies to all of Terra. -- Be sure that this is not something that should be implemented as a Terra addon, and instead applies to all of Terra. -- Make sure that you attach a copy of the latest.log file, if there are any exceptions thrown in the console. Putting *just* the - exception **is not enough**. We need to be able to check that there wasn't anything else before that caused it. +- Be sure that this is not a feature request that should be made for a specific + Terra *pack*, and instead applies to all of Terra. +- Be sure that this is not something that should be implemented as a Terra + addon, and instead applies to all of Terra. +- Make sure that you attach a copy of the latest.log file, if there are any + exceptions thrown in the console. Putting *just* the exception **is not + enough**. We need to be able to check that there wasn't anything else before + that caused it. #### How Do I Submit A (Good) Pull Request? -Pull Requests are tracked as [GitHub Pull Requests](https://guides.github.com/activities/forking/#making-a-pull-request). Create a pr on our -main repository and provide the following information: +Pull Requests are tracked +as [GitHub Pull Requests](https://guides.github.com/activities/forking/#making-a-pull-request) +. Create a pr on our platform repository and provide the following information: - **Use a clear and descriptive title** to identify the pull request. - **State what this pull request adds/fixes**. -- **Be sure that you are the owner of the code you contributed** or that it can be licensed under the GPLv3. -- **Provide a description goals and non-goals of the pull request** in as many details as possible. -- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. -- **Explain why this enhancement would be useful** to most Terra users and isn't something that can or should be implemented as an addon. +- **Be sure that you are the owner of the code you contributed** or that it can + be licensed under the GPLv3. +- **Provide a description goals and non-goals of the pull request** in as many + details as possible. +- **Describe the current behavior** and **explain which behavior you expected to + see instead** and why. +- **Explain why this enhancement would be useful** to most Terra users and isn't + something that can or should be implemented as an addon. ## Styleguides ### Git Commits -Following this is not mandatory, but rather a set of guidelines. As long as your commit messages aren't absolutely awful, it's probably -fine. But it would be nice if you followed them. +Following this is not mandatory, but rather a set of guidelines. As long as your +commit messages aren't absolutely awful, it's probably fine. But it would be +nice if you followed them. #### Committing -When you commit code, try to avoid committing large amounts of code in a single go. Splitting up code into smaller commits is much nicer and -makes it easier to trace a feature to a single commit. +When you commit code, try to avoid committing large amounts of code in a single +go. Splitting up code into smaller commits is much nicer and makes it easier to +trace a feature to a single commit. -Try to stick to one feature/fix/etc. per commit. A good rule of thumb is if you need to use the word "and" in the subject line, then it -should probably™ be two commits. +Try to stick to one feature/fix/etc. per commit. A good rule of thumb is if you +need to use the word "and" in the subject line, then it should probably™ be two +commits. #### Git Commit Messages -- Subject line must fit the following format: `: `. Type must be one of the following: +- Subject line must fit the following format: `: `. Type + must be one of the following: - Build: Changes that affect the build system or external dependencies. - Docs: Documentation only changes. - Feat: A new feature. - Fix: A bug fix. - Perf: Performance improvements. - Refactor: Refactoring sections of the codebase. - - Repo: Changes to the repository structure that do not affect code. (Eg. modification of the `README.md` file, etc.) + - Repo: Changes to the repository structure that do not affect code. (Eg. + modification of the `README.md` file, etc.) - Revert: Revert a previous commit. - Style: Code style updates. - Test: Anything related to testing. @@ -266,7 +332,8 @@ should probably™ be two commits. ### Code Styleguide -Use an IDE with support for `.editorconfig` files. There is an included editorconfig file in the base of the project so that your IDE should +Use an IDE with support for `.editorconfig` files. There is an included +editorconfig file in the base of the project so that your IDE should automatically use the correct code style settings. ### Documentation Styleguide @@ -279,41 +346,56 @@ TODO #### General Compatibility -General compatibility (example: injection of Vanilla structures/features/carvers into packs) is acceptable in the main project. +General compatibility (example: injection of Vanilla structures/features/carvers +into packs) is acceptable in the platform project. -- General compatibility features should be *disabled by default*. Having things auto-injected causes unpredictable behaviour that is - annoying to diagnose. General-compatibility options should have config values attached which are disabled by default. -- These config options should also be *simple to use*. Think of the people who will be using these compatibility options. They want to flick - a switch and have things be compatible. That means that a majority of compatibility options should stay in `pack.yml`, to make it simple - to go into a pack and turn on specific compatibilities. This does *not* mean that more advanced compatibility options are off the table, - for example, look at Feature compatibility, where features can either be automatically injected, *or* configured individually per Terra - biome, depending on how much control the user wants. +- General compatibility features should be *disabled by default*. Having things + auto-injected causes unpredictable behaviour that is annoying to diagnose. + General-compatibility options should have config values attached which are + disabled by default. +- These config options should also be *simple to use*. Think of the people who + will be using these compatibility options. They want to flick a switch and + have things be compatible. That means that a majority of compatibility options + should stay in `pack.yml`, to make it simple to go into a pack and turn on + specific compatibilities. This does *not* mean that more advanced + compatibility options are off the table, for example, look at Feature + compatibility, where features can either be automatically injected, *or* + configured individually per Terra biome, depending on how much control the + user wants. #### Specific Compatibility -Specific compatibility should *not* be put in the main project. (Example: Adding the ability to generate TechCraft v7's doo-dads with a -TerraScript function) +Specific compatibility should *not* be put in the platform project. (Example: +Adding the ability to generate TechCraft v7's doo-dads with a TerraScript +function) -Having specific compatibilities leads to tons of extra dependencies to keep track of, as well as adding lots of additional stuff to -maintain. It quickly becomes a mess. Especially when most users will never need to use this feature. +Having specific compatibilities leads to tons of extra dependencies to keep +track of, as well as adding lots of additional stuff to maintain. It quickly +becomes a mess. Especially when most users will never need to use this feature. -We have designed an addon API for exactly this purpose. **Specific compatibilities are welcome and encouraged, in the form of addons.** +We have designed an addon API for exactly this purpose. **Specific +compatibilities are welcome and encouraged, in the form of addons.** ### Platform-Agnostic Design -Terra must, at all times, remain platform agnostic. This means it must be able to run on theoretically any voxel based platform. Including -non-minecraft games like Terasology. +Terra must, at all times, remain platform agnostic. This means it must be able +to run on theoretically any voxel based platform. Including non-minecraft games +like Terasology. -When adding a new feature to `common`, make no assumptions about what platform it'll be running on. +When adding a new feature to `common`, make no assumptions about what platform +it'll be running on. Examples: - Don't assume the world height is 256. -- Don't assume that a specific block, item, or entity exists. (Eg. don't assume there exists a block called `minecraft:grass_block`) +- Don't assume that a specific block, item, or entity exists. (Eg. don't assume + there exists a block called `minecraft:grass_block`) ### Data-Driven -When adding a new feature, make it abstract. Don't make assumptions about "specific use cases." If you can only think of a few use cases, -your idea should probably be generalized. +When adding a new feature, make it abstract. Don't make assumptions about " +specific use cases." If you can only think of a few use cases, your idea should +probably be generalized. -You must use configs effectively. Make configs that are *powerful* but also *make sense* and are \[easy\] to use. \ No newline at end of file +You must use configs effectively. Make configs that are *powerful* but also * +make sense* and are \[easy\] to use. \ No newline at end of file diff --git a/LICENSE b/LICENSE index f288702d2..64c1cd516 100644 --- a/LICENSE +++ b/LICENSE @@ -1,674 +1,21 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/README.md b/README.md index 0b0eb8b93..77e2e511e 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,108 @@ +Terra Logo + # Terra -Terra is an incredibly powerful free & open-source data-driven, platform-agnostic world generator. It allows you to create a world exactly -to your specifications, with no knowledge of Java required. +Terra is a modern world generation modding platform, primarily for Minecraft. +Terra allows complete customization of world generation with an advanced API, +tightly integrated with a powerful configuration system. + +Terra consists of several parts: + +* A voxel world generation API with emphasis on configuration and extensibility +* Several platform implementations, the layer between the API and the platform + it's running on. +* An addon loader, which allows addons to interface with the Terra API in a + platform-agnostic setting +* Several "core addons," which implement the "default" configurations of Terra. + These addons can be thought of as the config "standard library" + +Terra currently officially supports the Fabric mod loader and the Bukkit API +(Paper and friends). We welcome Pull Requests implementing additional platforms! ## Downloads: -* Paper+ servers (Paper, Tuinity, Purpur, etc): [SpigotMC](https://www.spigotmc.org/resources/85151/) -* Fabric: [Modrinth](https://modrinth.com/mod/terra) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/terra-world-generator) -* Forge **(ALPHA - NOT PRODUCTION-READY)**: [Modrinth](https://modrinth.com/mod/terra) / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/terra-world-generator) +* Fabric: [Modrinth](https://modrinth.com/mod/terra) + / [CurseForge](https://www.curseforge.com/minecraft/mc-mods/terra-world-generator) +* Paper+ servers (Paper, Tuinity, Purpur, + etc): [SpigotMC](https://www.spigotmc.org/resources/85151/) ## Building and Running Terra -To build, simply run `./gradlew build` (`gradlew.bat build` on Windows). This will build all platforms, and -produce JARs in `platforms//build/libs` +To build, simply run `./gradlew build` (`gradlew.bat build` on Windows). This +will build all platforms, and produce JARs in `platforms//build/libs` ### Production JARs: + * Bukkit: `Terra--shaded.jar` * Fabric: `Terra--shaded-mapped.jar` -* Forge: `Terra--shaded.jar` ### Building a Specific Platform + To build a specific platform, run `gradlew :platforms::build`. JARs are produced in `platforms//build/libs`. ### Running Minecraft in the IDE + To run Minecraft with Terra in the IDE (for testing) use the following tasks: + * Bukkit - * `installPaper` - Install a [Paper](https://github.com/PaperMC/Paper) test server. (Only needs to be run once). - * `installPurpur` - Install a [Purpur](https://github.com/pl3xgaming/Purpur) test server. (Only needs to be run once). - * `runPaper` - Run the Paper test server with Terra (`installPaper` must have been run previously). - * `runPurpur` - Run the Purpur test server with Terra (`installPurpur` must have been run previously). + * `installPaper` - Install a [Paper](https://github.com/PaperMC/Paper) test + server. (Only needs to be run once). + * `installPurpur` - Install a [Purpur](https://github.com/pl3xgaming/Purpur) + test server. (Only needs to be run once). + * `runPaper` - Run the Paper test server with Terra (`installPaper` must + have been run previously). + * `runPurpur` - Run the Purpur test server with Terra (`installPurpur` must + have been run previously). * Fabric - * `runClient` - Run a Minecraft Fabric client with Terra installed. - * `runServer` - Run a Minecraft Fabric server with Terra installed. -* Forge - * `runClient` - Run a Minecraft Forge client with Terra installed. - * `runServer` - Run a Minecraft Forge server with Terra installed. + * `runClient` - Run a Minecraft Fabric client with Terra installed. + * `runServer` - Run a Minecraft Fabric server with Terra installed. + ## Contributing -Contributions are welcome! If you want to see a feature in Terra, please, open an issue, or implement it yourself and -submit a PR! -Join the discord [here](https://discord.gg/PXUEbbF) if you would like to talk more about the project! + +Contributions are welcome! If you want to see a feature in Terra, please, open +an issue, or implement it yourself and submit a PR! +Join the discord [here](https://discord.gg/PXUEbbF) if you would like to talk +more about the project! + +## Licensing + +Parts of Terra are licensed under either the MIT License or the GNU General +Public License, version 3.0. + +* Our API is licensed under the [MIT License](LICENSE), to ensure that everyone + is able to freely use it however they want. +* Our core addons are also licensed under the [MIT License](LICENSE), to ensure + that people can freely use code from them to learn and make their own addons, + without worrying about GPL infection. +* Our platform-agnostic implementations and platform implementations are + licensed under + the [GNU General Public License, version 3.0](common/implementation/LICENSE), + to ensure that they remain free software wherever they are used. + +If you're not sure which license a particular file is under, check: + +* The file's header +* The LICENSE file in the closest parent folder of the file in question ## Beta -Terra is still in beta! While it is stable, it is not feature-complete. There is a lot to be added! + +Terra is still in beta! While it is stable, it is not feature-complete. There is +a lot to be added! + +## Special Thanks + +[![YourKit-Logo](https://www.yourkit.com/images/yklogo.png)](https://www.yourkit.com/) + +YourKit has granted Polyhedral Development an open-source license to their +outstanding Java profiler, allowing us to make our software as performant as it +can be! + +YourKit supports open source projects with innovative and intelligent tools for +monitoring and profiling Java and .NET applications. YourKit is the creator of +the +[YourKit Java Profiler](https://www.yourkit.com/java/profiler/), +[YourKit .NET Profiler](https://www.yourkit.com/.net/profiler/), +and [YourKit YouMonitor](https://www.yourkit.com/youmonitor/). + diff --git a/build.gradle.kts b/build.gradle.kts index 00a312eb4..1bfd4a707 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,38 +1,57 @@ -import com.dfsek.terra.getGitHash +preRelease(true) + +versionProjects(":common:api", version("6.0.0")) +versionProjects(":common:implementation", version("6.0.0")) +versionProjects(":platforms", version("6.0.0")) -val versionObj = Version("5", "4", "2", true) allprojects { - version = versionObj group = "com.dfsek.terra" - + + configureCompilation() + configureDependencies() + configurePublishing() + tasks.withType().configureEach { options.isFork = true options.isIncremental = true } + tasks.withType().configureEach { useJUnitPlatform() - + maxHeapSize = "2G" ignoreFailures = false failFast = true maxParallelForks = (Runtime.getRuntime().availableProcessors() - 1).takeIf { it > 0 } ?: 1 - - reports.html.isEnabled = false - reports.junitXml.isEnabled = false + + reports.html.required.set(false) + reports.junitXml.required.set(false) } - -} -/** - * Version class that does version stuff. - */ -@Suppress("MemberVisibilityCanBePrivate") -class Version(val major: String, val minor: String, val revision: String, val preRelease: Boolean = false) { - - override fun toString(): String { - return if (!preRelease) - "$major.$minor.$revision" - else //Only use git hash if it's a prerelease. - "$major.$minor.$revision-BETA+${getGitHash()}" + + tasks.withType().configureEach { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } + + tasks.withType().configureEach { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } +} + +afterEvaluate { + forImmediateSubProjects(":platforms") { + configureDistribution() + } + forSubProjects(":common:addons") { + apply(plugin = "com.github.johnrengelman.shadow") + + tasks.named("build") { + finalizedBy(tasks.named("shadowJar")) + } + + dependencies { + "compileOnly"(project(":common:api")) + "testImplementation"(project(":common:api")) + } } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index ecf0454d8..06ce4a579 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -6,8 +6,13 @@ plugins { repositories { mavenCentral() gradlePluginPortal() + maven { url = uri("https://repo.codemc.org/repository/maven-public") } } dependencies { - "implementation"("com.github.jengelman.gradle.plugins:shadow:+") + implementation("gradle.plugin.com.github.jengelman.gradle.plugins:shadow:+") + implementation("org.ow2.asm:asm:9.2") + implementation("org.ow2.asm:asm-tree:9.2") + implementation("com.dfsek.tectonic:common:4.2.0") + implementation("org.yaml:snakeyaml:1.27") } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/AddonConfig.kt b/buildSrc/src/main/kotlin/AddonConfig.kt new file mode 100644 index 000000000..cf76ebbe0 --- /dev/null +++ b/buildSrc/src/main/kotlin/AddonConfig.kt @@ -0,0 +1,42 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import java.io.File +import java.util.function.Predicate +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.jvm.tasks.Jar +import org.gradle.kotlin.dsl.extra +import kotlin.streams.asStream + + +/** + * Configures a directory where addons will be put. + */ +fun Project.addonDir(dir: File, task: Task) { + task.doFirst { + dir.parentFile.mkdirs() + matchingAddons(dir) { + it.name.startsWith("Terra-") // Assume everything that starts with Terra- is a core addon. + }.forEach { + println("Deleting old addon: " + it.absolutePath) + it.delete() + } + forSubProjects(":common:addons") { + val jar = tasks.named("shadowJar").get() as ShadowJar + + val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else "" + val target = File(dir, boot + jar.archiveFileName.get()) + + val base = "${jar.archiveBaseName.get()}-${version}" + + println("Copying addon ${jar.archiveFileName.get()} to ${target.absolutePath}. Base name: $base") + + jar.archiveFile.orNull?.asFile?.copyTo(target) + } + } +} + +fun matchingAddons(dir: File, matcher: Predicate): Set { + val matching = HashSet() + dir.walk().asStream().filter(matcher).forEach(matching::add) + return matching +} diff --git a/buildSrc/src/main/kotlin/CompilationConfig.kt b/buildSrc/src/main/kotlin/CompilationConfig.kt new file mode 100644 index 000000000..952b91091 --- /dev/null +++ b/buildSrc/src/main/kotlin/CompilationConfig.kt @@ -0,0 +1,78 @@ +import com.dfsek.terra.tectonicdoc.TectonicDocPlugin +import org.apache.tools.ant.filters.ReplaceTokens +import org.gradle.api.JavaVersion +import org.gradle.api.Project +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.tasks.bundling.Jar +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.api.tasks.javadoc.Javadoc +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.filter +import org.gradle.kotlin.dsl.getByName +import org.gradle.kotlin.dsl.register +import org.gradle.kotlin.dsl.withType +import org.gradle.language.jvm.tasks.ProcessResources + +fun Project.configureCompilation() { + apply(plugin = "maven-publish") + apply(plugin = "java") + apply(plugin = "java-library") + apply(plugin = "idea") + apply() + + configure { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + tasks.withType { + options.encoding = "UTF-8" + doFirst { + options.compilerArgs.add("-Xlint:all") + } + } + + tasks.withType { + include("**/*.*") + filter( + "tokens" to mapOf( + "DESCRIPTION" to properties["terra.description"], + "WIKI" to properties["terra.wiki"], + "SOURCE" to properties["terra.source"], + "ISSUES" to properties["terra.issues"], + "LICENSE" to properties["terra.license"] + ) + ) + } + + afterEvaluate { + tasks.withType { + include("**/*.*") + filter( + "tokens" to mapOf( + "VERSION" to version.toString() + ) + ) + } + } + + tasks.withType { + options.encoding = "UTF-8" + } + + tasks.withType { + archiveBaseName.set("Terra-${archiveBaseName.get()}") + from("../LICENSE", "../../LICENSE") + } + + tasks.register("sourcesJar") { + archiveClassifier.set("sources") + } + + tasks.register("javadocJar") { + dependsOn("javadoc") + archiveClassifier.set("javadoc") + from(tasks.getByName("javadoc").destinationDir) + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/DependencyConfig.kt b/buildSrc/src/main/kotlin/DependencyConfig.kt new file mode 100644 index 000000000..ecc0a8229 --- /dev/null +++ b/buildSrc/src/main/kotlin/DependencyConfig.kt @@ -0,0 +1,47 @@ +import org.gradle.api.Project +import org.gradle.kotlin.dsl.creating +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.getValue +import org.gradle.kotlin.dsl.getting +import org.gradle.kotlin.dsl.maven +import org.gradle.kotlin.dsl.repositories + +fun Project.configureDependencies() { + val testImplementation by configurations.getting + val compileOnly by configurations.getting + + val api by configurations.getting + val implementation by configurations.getting + + val shaded by configurations.creating + + @Suppress("UNUSED_VARIABLE") + val shadedApi by configurations.creating { + shaded.extendsFrom(this) + api.extendsFrom(this) + } + + @Suppress("UNUSED_VARIABLE") + val shadedImplementation by configurations.creating { + shaded.extendsFrom(this) + implementation.extendsFrom(this) + } + + repositories { + mavenCentral() + gradlePluginPortal() + maven("https://maven.fabricmc.net/") + maven("https://repo.codemc.org/repository/maven-public") + maven("https://repo.codemc.io/repository/nms/") + maven("https://papermc.io/repo/repository/maven-public/") + } + + dependencies { + testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0") + testImplementation("org.junit.jupiter:junit-jupiter-engine:5.7.0") + compileOnly("org.jetbrains:annotations:23.0.0") + + compileOnly("com.google.guava:guava:30.0-jre") + testImplementation("com.google.guava:guava:30.0-jre") + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/DistributionConfig.kt b/buildSrc/src/main/kotlin/DistributionConfig.kt new file mode 100644 index 000000000..b03af16f8 --- /dev/null +++ b/buildSrc/src/main/kotlin/DistributionConfig.kt @@ -0,0 +1,143 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import java.io.File +import java.io.FileWriter +import java.net.URL +import java.nio.file.FileSystems +import java.nio.file.Files +import java.nio.file.StandardCopyOption +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.plugins.BasePluginExtension +import org.gradle.jvm.tasks.Jar +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.extra +import org.gradle.kotlin.dsl.get +import org.gradle.kotlin.dsl.named +import org.yaml.snakeyaml.DumperOptions +import org.yaml.snakeyaml.Yaml + +fun Project.configureDistribution() { + apply(plugin = "com.github.johnrengelman.shadow") + + val downloadDefaultPacks = tasks.create("downloadDefaultPacks") { + group = "terra" + doFirst { + file("${buildDir}/resources/main/packs/").deleteRecursively() + val defaultPackUrl = URL("https://github.com/PolyhedralDev/TerraOverworldConfig/releases/download/latest/default.zip") + downloadPack(defaultPackUrl, project) + } + } + + val installAddons = tasks.create("installAddons") { + group = "terra" + forSubProjects(":common:addons") { + afterEvaluate { + dependsOn(getJarTask()) + } + } + + doLast { + // https://github.com/johnrengelman/shadow/issues/111 + val dest = tasks.named("shadowJar").get().archiveFile.get().asFile.toPath() + + FileSystems.newFileSystem(dest, mapOf("create" to "false"), null).use { fs -> + forSubProjects(":common:addons") { + val jar = getJarTask() + + println("Packaging addon ${jar.archiveFileName.get()} to $dest. size: ${jar.archiveFile.get().asFile.length() / 1024}KB") + + val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else "" + val addonPath = fs.getPath("/addons/$boot${jar.archiveFileName.get()}"); + + if(!Files.exists(addonPath)) { + Files.createDirectories(addonPath.parent) + Files.createFile(addonPath) + Files.copy(jar.archiveFile.get().asFile.toPath(), addonPath, StandardCopyOption.REPLACE_EXISTING) + } + + } + } + } + } + + val generateResourceManifest = tasks.create("generateResourceManifest") { + group = "terra" + dependsOn(downloadDefaultPacks) + doLast { + val resources = HashMap>() + val packsDir = File("${project.buildDir}/resources/main/packs/") + + packsDir.walkTopDown().forEach { + if (it.isDirectory || !it.name.endsWith(".zip")) return@forEach + resources.computeIfAbsent("packs") { ArrayList() }.add(it.name) + } + + val langDir = File("${project(":common:implementation").buildDir}/resources/main/lang/") + + langDir.walkTopDown().forEach { + if (it.isDirectory || !it.name.endsWith(".yml")) return@forEach + resources.computeIfAbsent("lang") { ArrayList() }.add(it.name) + } + + forSubProjects(":common:addons") { + val jar = getJarTask().archiveFileName.get() + resources.computeIfAbsent( + if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "addons/bootstrap" + else "addons" + ) { ArrayList() }.add(jar) + } + + val options = DumperOptions() + options.indent = 2 + options.indentWithIndicator = true + options.indicatorIndent = 2 + options.isPrettyFlow = true + options.defaultFlowStyle = DumperOptions.FlowStyle.BLOCK + options.defaultScalarStyle = DumperOptions.ScalarStyle.DOUBLE_QUOTED + + val yaml = Yaml(options) + + val manifest = File("${project.buildDir}/resources/main/resources.yml") + + if (manifest.exists()) manifest.delete() + manifest.createNewFile() + yaml.dump(resources, FileWriter(manifest)) + } + } + + tasks["processResources"].dependsOn(generateResourceManifest) + + + tasks.named("shadowJar") { + // Tell shadow to download the packs + dependsOn(downloadDefaultPacks) + configurations = listOf(project.configurations["shaded"]) + archiveClassifier.set("shaded") + setVersion(project.version) + relocate("org.apache.commons", "com.dfsek.terra.lib.commons") + relocate("org.objectweb.asm", "com.dfsek.terra.lib.asm") + relocate("com.dfsek.paralithic", "com.dfsek.terra.lib.paralithic") + relocate("org.json", "com.dfsek.terra.lib.json") + relocate("org.yaml", "com.dfsek.terra.lib.yaml") + + finalizedBy(installAddons) + } + + configure { + archivesName.set(project.name) + } + + tasks.named("build") { + dependsOn(tasks["shadowJar"]) + } +} + +fun downloadPack(packUrl: URL, project: Project) { + val fileName = packUrl.file.substring(packUrl.file.lastIndexOf("/")) + val file = File("${project.buildDir}/resources/main/packs/${fileName}") + file.parentFile.mkdirs() + file.outputStream().write(packUrl.readBytes()) +} + +fun Project.getJarTask() = tasks.named("shadowJar").get() as ShadowJar diff --git a/buildSrc/src/main/kotlin/PublishingConfig.kt b/buildSrc/src/main/kotlin/PublishingConfig.kt new file mode 100644 index 000000000..820010a78 --- /dev/null +++ b/buildSrc/src/main/kotlin/PublishingConfig.kt @@ -0,0 +1,34 @@ +import org.gradle.api.Project +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.get +import org.gradle.kotlin.dsl.maven +import org.gradle.kotlin.dsl.provideDelegate + +fun Project.configurePublishing() { + configure { + publications { + create("mavenJava") { + from(components["java"]) + } + } + + repositories { + val mavenUrl = "https://repo.codemc.io/repository/maven-releases/" + //val mavenSnapshotUrl = "https://repo.codemc.io/repository/maven-snapshots/" + + maven(mavenUrl) { + val mavenUsername: String? by project + val mavenPassword: String? by project + if (mavenUsername != null && mavenPassword != null) { + credentials { + username = mavenUsername + password = mavenPassword + } + } + } + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Utils.kt b/buildSrc/src/main/kotlin/Utils.kt new file mode 100644 index 000000000..b775871b0 --- /dev/null +++ b/buildSrc/src/main/kotlin/Utils.kt @@ -0,0 +1,56 @@ +import java.io.ByteArrayOutputStream +import org.gradle.api.Action +import org.gradle.api.Project + + +var isPrerelease = false + + +fun Project.getGitHash(): String { + val stdout = ByteArrayOutputStream() + exec { + commandLine = mutableListOf("git", "rev-parse", "--short", "HEAD") + standardOutput = stdout + } + return stdout.toString().trim() +} + +fun Project.gitClone(name: String) { + val stdout = ByteArrayOutputStream() + exec { + commandLine = mutableListOf("git", "clone", name) + standardOutput = stdout + } +} + +fun Project.forSubProjects(project: String, action: Action) { + project(project).subprojects.forEach { + action.execute(it) + } +} + +fun Project.forImmediateSubProjects(project: String, action: Action) { + project(project).childProjects.forEach { + action.execute(it.value) + } +} + +fun preRelease(preRelease: Boolean) { + isPrerelease = preRelease +} + +fun Project.versionProjects(project: String, version: String) { + forSubProjects(project) { + this.version = version + println("Setting version of $path to $version") + } + project(project).version = version + println("Setting version of $project to $version") +} + +fun Project.version(version: String): String { + return if (!isPrerelease) + version + else //Only use git hash if it's a prerelease. + "$version-BETA+${getGitHash()}" +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt new file mode 100644 index 000000000..01e403932 --- /dev/null +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -0,0 +1,38 @@ +object Versions { + object Libraries { + const val tectonic = "4.2.0" + const val paralithic = "0.7.0" + const val strata = "1.1.1" + + const val cloud = "1.6.2" + + const val slf4j = "1.7.36" + const val log4j_slf4j_impl = "2.14.1" + + object Internal { + const val apacheText = "1.9" + const val jafama = "2.3.2" + const val apacheIO = "2.6" + const val fastutil = "8.5.6" + } + } + + object Fabric { + const val fabricLoader = "0.14.2" + const val fabricAPI = "0.53.4+1.18.2" + const val minecraft = "1.18.2" + const val yarn = "$minecraft+build.3" + const val permissionsAPI = "0.1-SNAPSHOT" + } + + object Bukkit { + const val paper = "1.18-R0.1-SNAPSHOT" + const val paperLib = "1.0.5" + } + + object Sponge { + const val sponge = "9.0.0-SNAPSHOT" + const val mixin = "0.8.2" + const val minecraft = "1.17.1" + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt deleted file mode 100644 index 3f10dc573..000000000 --- a/buildSrc/src/main/kotlin/com/dfsek/terra/CommonConfig.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra - -import org.gradle.api.Project -import org.gradle.api.tasks.testing.Test -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.withType -import java.io.ByteArrayOutputStream - -fun Project.configureCommon() { - configureDependencies() - configureCompilation() - configureDistribution() - - version = rootProject.version -} - -fun Project.getGitHash(): String { - val stdout = ByteArrayOutputStream() - exec { - commandLine = mutableListOf("git", "rev-parse", "--short", "HEAD") - standardOutput = stdout - } - return stdout.toString().trim() -} - -fun Project.gitClone(name: String) { - val stdout = ByteArrayOutputStream() - exec { - commandLine = mutableListOf("git", "clone", name) - standardOutput = stdout - } -} diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt deleted file mode 100644 index c48a7de3b..000000000 --- a/buildSrc/src/main/kotlin/com/dfsek/terra/CompilationConfig.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.dfsek.terra - -import org.gradle.api.JavaVersion -import org.gradle.api.Project -import org.gradle.api.plugins.JavaPluginConvention -import org.gradle.api.tasks.bundling.Jar -import org.gradle.api.tasks.compile.JavaCompile -import org.gradle.api.tasks.javadoc.Javadoc -import org.gradle.kotlin.dsl.* -import org.gradle.language.jvm.tasks.ProcessResources - -fun Project.configureCompilation() { - apply(plugin = "maven-publish") - apply(plugin = "idea") - - configure { - sourceCompatibility = JavaVersion.VERSION_16 - targetCompatibility = JavaVersion.VERSION_16 - } - - tasks.withType { - options.encoding = "UTF-8" - doFirst { - options.compilerArgs.add("-Xlint:all") - } - } - - tasks.withType { - include("**/*.*") - filter( - "tokens" to mapOf( - "VERSION" to project.version.toString(), - "DESCRIPTION" to project.properties["terra.description"], - "WIKI" to project.properties["terra.wiki"], - "SOURCE" to project.properties["terra.source"], - "ISSUES" to project.properties["terra.issues"], - "LICENSE" to project.properties["terra.license"] - ) - ) - } - - tasks.withType { - options.encoding = "UTF-8" - } - - tasks.withType { - archiveBaseName.set("Terra-${archiveBaseName.get()}") - from("../LICENSE", "../../LICENSE") - } - - tasks.register("sourcesJar") { - archiveClassifier.set("sources") - } - - tasks.register("javadocJar") { - dependsOn("javadoc") - archiveClassifier.set("javadoc") - from(tasks.getByName("javadoc").destinationDir) - } -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt deleted file mode 100644 index a73154b3f..000000000 --- a/buildSrc/src/main/kotlin/com/dfsek/terra/DependencyConfig.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra - -import org.gradle.api.Project -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.invoke -import org.gradle.kotlin.dsl.repositories - -fun Project.configureDependencies() { - apply(plugin = "java") - apply(plugin = "java-library") - - configurations { - val shaded = create("shaded") - val shadedApi = create("shadedApi") - shaded.extendsFrom(shadedApi) - getByName("api").extendsFrom(shadedApi) - val shadedImplementation = create("shadedImplementation") - shaded.extendsFrom(shadedImplementation) - getByName("implementation").extendsFrom(shadedImplementation) - } - - repositories { - maven { url = uri("https://maven.enginehub.org/repo/") } - maven { url = uri("https://repo.codemc.org/repository/maven-public") } - maven { url = uri("https://papermc.io/repo/repository/maven-public/") } - maven { url = uri("https://maven.fabricmc.net/") } - gradlePluginPortal() - jcenter() - mavenCentral() - } - - dependencies { - "testImplementation"("org.junit.jupiter:junit-jupiter-api:5.7.0") - "testImplementation"("org.junit.jupiter:junit-jupiter-engine:5.7.0") - "api"("org.jetbrains:annotations:20.1.0") - } -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/DistributionConfig.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/DistributionConfig.kt deleted file mode 100644 index ee81dc9b8..000000000 --- a/buildSrc/src/main/kotlin/com/dfsek/terra/DistributionConfig.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.dfsek.terra - -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import org.gradle.api.DefaultTask -import org.gradle.api.Project -import org.gradle.api.plugins.BasePluginConvention -import org.gradle.api.tasks.bundling.Jar -import org.gradle.api.tasks.javadoc.Javadoc -import org.gradle.kotlin.dsl.* -import java.io.File -import java.net.URL - -fun Project.configureDistribution() { - apply(plugin = "java-library") - apply(plugin = "com.github.johnrengelman.shadow") - - val downloadDefaultPacks = tasks.create("downloadDefaultPacks") { - group = "terra" - doFirst { - file("${buildDir}/resources/main/packs/").deleteRecursively() - - val defaultPackUrl = URL("https://github.com/PolyhedralDev/TerraDefaultConfig/releases/download/latest/default.zip") - downloadPack(defaultPackUrl, project) - val netherPackUrl = URL("https://github.com/PolyhedralDev/TerraDefaultConfig/releases/download/latest/nether.zip") - downloadPack(netherPackUrl, project) - } - } - tasks["processResources"].dependsOn(downloadDefaultPacks) - - tasks.named("shadowJar") { - // Tell shadow to download the packs - dependsOn(downloadDefaultPacks) - - configurations = listOf(project.configurations["shaded"]) - - archiveClassifier.set("shaded") - setVersion(project.version) - relocate("org.apache.commons", "com.dfsek.terra.lib.commons") - relocate("net.jafama", "com.dfsek.terra.lib.jafama") - relocate("org.objectweb.asm", "com.dfsek.terra.lib.asm") - relocate("com.google.errorprone", "com.dfsek.terra.lib.google.errorprone") - relocate("com.google.j2objc", "com.dfsek.terra.lib.google.j2objc") - relocate("org.checkerframework", "com.dfsek.terra.lib.checkerframework") - relocate("org.javax.annotation", "com.dfsek.terra.lib.javax.annotation") - relocate("org.json", "com.dfsek.terra.lib.json") - relocate("org.yaml", "com.dfsek.terra.lib.yaml") - minimize() - } - convention.getPlugin().archivesBaseName = project.name - - tasks.named("build") { - dependsOn(tasks["shadowJar"]) - } -} - -fun downloadPack(packUrl: URL, project: Project) { - val fileName = packUrl.file.substring(packUrl.file.lastIndexOf("/")) - val file = File("${project.buildDir}/resources/main/packs/${fileName}") - file.parentFile.mkdirs() - file.outputStream().write(packUrl.readBytes()) -} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/tectonicdoc/DocumentedTemplate.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/tectonicdoc/DocumentedTemplate.kt new file mode 100644 index 000000000..c7eac1f83 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/tectonicdoc/DocumentedTemplate.kt @@ -0,0 +1,20 @@ +package com.dfsek.terra.tectonicdoc + +class DocumentedTemplate(private val name: String) { + private val template = HashMap() + + fun add(name: String, content: String) { + template[name] = content + } + + fun format(): String { + val builder = StringBuilder("# ").append(name).append("\n\n") + template.forEach { name, content -> + builder + .append("### $name\n\n") + .append(content) + .append("\n\n") + } + return builder.toString() + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/tectonicdoc/GenerateDocsTask.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/tectonicdoc/GenerateDocsTask.kt new file mode 100644 index 000000000..30f515355 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/tectonicdoc/GenerateDocsTask.kt @@ -0,0 +1,150 @@ +package com.dfsek.terra.tectonicdoc + +import com.dfsek.tectonic.api.config.template.annotations.Description +import com.dfsek.tectonic.api.config.template.annotations.Final +import com.dfsek.tectonic.api.config.template.annotations.Value +import java.io.File +import java.io.FileInputStream +import java.io.InputStream +import org.gradle.api.DefaultTask +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.tasks.TaskAction +import org.objectweb.asm.ClassReader +import org.objectweb.asm.tree.ClassNode +import org.objectweb.asm.tree.FieldNode + + +abstract class GenerateDocsTask : DefaultTask() { + @TaskAction + fun generateDocs() { + project.extensions.getByType(JavaPluginExtension::class.java).sourceSets.forEach { sources -> + val classes = HashMap() + sources.java.classesDirectory.get().asFileTree.forEach { file -> + if (file.name.endsWith(".class")) { + val node = createClassNode(FileInputStream(file)) + if (node.fields.stream().anyMatch { field -> + field.visibleAnnotations?.stream()?.anyMatch { + it.desc.equals(descriptor(Value::class.java.canonicalName)) + } == true + }) { + var name = sources + .java + .classesDirectory + .get() + .asFile + .toPath() + .relativize(file.toPath()) + .toString() + .substringBeforeLast('.') + if (name.endsWith("Template")) { + name = name.substringBeforeLast("Template") + } + classes[name] = node + } + } + } + + val docsDir = File(project.buildDir, "tectonic") + docsDir.mkdirs() + + classes.forEach { (name, clazz) -> + val template = DocumentedTemplate(name.substringAfterLast('/')) + clazz.fields + .stream() + .filter { field -> + field.visibleAnnotations?.stream()?.anyMatch { + it.desc.equals(descriptor(Value::class.java.canonicalName)) + } == true + }.forEach { field -> + val annotations = field.visibleAnnotations + + val description = StringBuilder() + + annotations.stream().filter { + it.desc.equals(descriptor(Description::class.java.canonicalName)) + }.forEach { + description.append(it.values[1]) + } + + val keyName = StringBuilder() + + if (annotations.stream().anyMatch { it.desc.equals(descriptor(Final::class.java.canonicalName)) }) { + keyName.append("final ") + } + + keyName.append(getType(field)) + .append(" ") + + annotations.stream().filter { + it.desc.equals(descriptor(Value::class.java.canonicalName)) + }.forEach { + keyName.append(it.values[1]) + } + + template.add(keyName.toString(), description.toString().ifBlank { + println("No description provided for field " + field.name + " in class " + name) + "*No description provided.*" + }) + } + + + val save = File(docsDir, "$name.md") + if (save.exists()) save.delete() + save.parentFile.mkdirs() + save.createNewFile() + save.writeText(template.format()) + } + } + } + + private fun getType(node: FieldNode): String { + if (node.signature != null) { + return generic(node.signature) + } + return descriptorToHumanReadable(node.desc).substringAfterLast('.') + } + + private fun generic(type: String): String { + val clean = descriptorToHumanReadable(type) + + if (clean.contains('<')) { + val typeIndex = clean.indexOf('<') + return clean.substring(0, typeIndex + 1).substringAfterLast('.') + generic(clean.substring(typeIndex + 1)) + "\\>" + } + + return clean.substringAfterLast('.') + } + + private fun createClassNode(input: InputStream): ClassNode { + val reader = ClassReader(input) + val node = ClassNode() + try { + reader.accept(node, ClassReader.EXPAND_FRAMES) + } catch (e: Exception) { + reader.accept(node, ClassReader.SKIP_FRAMES or ClassReader.SKIP_DEBUG) + } + return node + } + + private fun descriptorToHumanReadable(descriptor: String): String { + if (descriptor.startsWith('L')) { + return descriptor.substring(1).substringBeforeLast(';').replace('/', '.') + } + if (descriptor.startsWith("[")) { + return "${descriptorToHumanReadable(descriptor.substring(1))}[]" + } + return when (descriptor) { + "B" -> "byte" + "C" -> "char" + "I" -> "int" + "D" -> "double" + "F" -> "float" + "J" -> "long" + "S" -> "short" + "Z" -> "boolean" + else -> descriptor + } + } + + private fun descriptor(name: String): String = "L${name.replace('.', '/')};" +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/dfsek/terra/tectonicdoc/TectonicDocPlugin.kt b/buildSrc/src/main/kotlin/com/dfsek/terra/tectonicdoc/TectonicDocPlugin.kt new file mode 100644 index 000000000..2fbd0f8fd --- /dev/null +++ b/buildSrc/src/main/kotlin/com/dfsek/terra/tectonicdoc/TectonicDocPlugin.kt @@ -0,0 +1,10 @@ +package com.dfsek.terra.tectonicdoc + +import org.gradle.api.Plugin +import org.gradle.api.Project + +class TectonicDocPlugin : Plugin { + override fun apply(project: Project) { + project.tasks.create("generateDocs", GenerateDocsTask::class.java) + } +} \ No newline at end of file diff --git a/common/addons/README.md b/common/addons/README.md new file mode 100644 index 000000000..1ee000423 --- /dev/null +++ b/common/addons/README.md @@ -0,0 +1,4 @@ +# Core Addons + +This directory contains the modularized "core addons" that implement Terra's +default behavior. \ No newline at end of file diff --git a/common/addons/api-addon-loader/LICENSE b/common/addons/api-addon-loader/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/api-addon-loader/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/api-addon-loader/README.md b/common/addons/api-addon-loader/README.md new file mode 100644 index 000000000..4e553600f --- /dev/null +++ b/common/addons/api-addon-loader/README.md @@ -0,0 +1,3 @@ +# api addon loader + +Loads dependencies as addons \ No newline at end of file diff --git a/common/addons/api-addon-loader/build.gradle.kts b/common/addons/api-addon-loader/build.gradle.kts new file mode 100644 index 000000000..6f47aeb33 --- /dev/null +++ b/common/addons/api-addon-loader/build.gradle.kts @@ -0,0 +1,12 @@ +version = version("0.1.0") + +dependencies { +} + +tasks.withType { + manifest { + attributes("Terra-Bootstrap-Addon-Entry-Point" to "com.dfsek.terra.addon.loader.ApiAddonLoader") + } +} + +project.extra.set("bootstrap", true) \ No newline at end of file diff --git a/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddon.java b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddon.java new file mode 100644 index 000000000..ba68e0434 --- /dev/null +++ b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddon.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.addon.loader; + +import ca.solostudios.strata.version.Version; + +import com.dfsek.terra.api.addon.BaseAddon; + + +public class ApiAddon implements BaseAddon { + private final Version version; + private final String id; + + public ApiAddon(Version version, String id) { + this.version = version; + this.id = id; + } + + @Override + public Version getVersion() { + return version; + } + + @Override + public String getID() { + return id; + } +} diff --git a/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonClassLoader.java b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonClassLoader.java new file mode 100644 index 000000000..2bcfb9236 --- /dev/null +++ b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonClassLoader.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addon.loader; + +import java.net.URL; +import java.net.URLClassLoader; + + +public class ApiAddonClassLoader extends URLClassLoader { + static { + ClassLoader.registerAsParallelCapable(); + } + + public ApiAddonClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } +} diff --git a/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonLoader.java b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonLoader.java new file mode 100644 index 000000000..b8350c778 --- /dev/null +++ b/common/addons/api-addon-loader/src/main/java/com/dfsek/terra/addon/loader/ApiAddonLoader.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addon.loader; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.version.Version; + +import java.nio.file.Path; +import java.util.Collections; + +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.addon.bootstrap.BootstrapAddonClassLoader; +import com.dfsek.terra.api.addon.bootstrap.BootstrapBaseAddon; + + +public class ApiAddonLoader implements BootstrapBaseAddon { + private static final Version VERSION = Versions.getVersion(1, 0, 0); + + @Override + public Iterable loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent) { + + return Collections.emptySet(); + } + + @Override + public String getID() { + return "API"; + } + + @Override + public Version getVersion() { + return VERSION; + } +} diff --git a/common/addons/biome-provider-image/LICENSE b/common/addons/biome-provider-image/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/biome-provider-image/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/biome-provider-image/README.md b/common/addons/biome-provider-image/README.md new file mode 100644 index 000000000..49e9b8fdb --- /dev/null +++ b/common/addons/biome-provider-image/README.md @@ -0,0 +1,6 @@ +# biome-provider-image + +Implements and registers the `IMAGE` biome provider, a biome provider which +generates biomes from an image, using the `color` attribute of biomes. + +This addon registers the provider type, and all associated config options. \ No newline at end of file diff --git a/common/addons/biome-provider-image/build.gradle.kts b/common/addons/biome-provider-image/build.gradle.kts new file mode 100644 index 000000000..15145b578 --- /dev/null +++ b/common/addons/biome-provider-image/build.gradle.kts @@ -0,0 +1,11 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("net.jafama", "com.dfsek.terra.addons.biome.image.lib.jafama") +} \ No newline at end of file diff --git a/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProvider.java b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProvider.java new file mode 100644 index 000000000..3c3fa90f5 --- /dev/null +++ b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProvider.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.image; + +import net.jafama.FastMath; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class ImageBiomeProvider implements BiomeProvider { + private final Map colorBiomeMap = new HashMap<>(); + private final BufferedImage image; + private final int resolution; + private final Align align; + + public ImageBiomeProvider(Set registry, BufferedImage image, int resolution, Align align) { + this.image = image; + this.resolution = resolution; + this.align = align; + registry.forEach(biome -> colorBiomeMap.put(new Color(biome.getColor()), biome)); + } + + private static int distance(Color a, Color b) { + return FastMath.abs(a.getRed() - b.getRed()) + FastMath.abs(a.getGreen() - b.getGreen()) + FastMath.abs(a.getBlue() - b.getBlue()); + } + + @Override + public Biome getBiome(int x, int y, int z, long seed) { + x /= resolution; + z /= resolution; + Color color = align.getColor(image, x, z); + return colorBiomeMap.get(colorBiomeMap.keySet() + .stream() + .reduce(colorBiomeMap.keySet().stream().findAny().orElseThrow(IllegalStateException::new), + (running, element) -> { + int d1 = distance(color, running); + int d2 = distance(color, element); + return d1 < d2 ? running : element; + })); + } + + @Override + public Iterable getBiomes() { + return colorBiomeMap.values(); + } + + public enum Align { + CENTER { + @Override + public Color getColor(BufferedImage image, int x, int z) { + return new Color(image.getRGB(FastMath.floorMod(x - image.getWidth() / 2, image.getWidth()), + FastMath.floorMod(z - image.getHeight() / 2, image.getHeight()))); + } + }, + NONE { + @Override + public Color getColor(BufferedImage image, int x, int z) { + return new Color(image.getRGB(FastMath.floorMod(x, image.getWidth()), FastMath.floorMod(z, image.getHeight()))); + } + }; + + public abstract Color getColor(BufferedImage image, int x, int z); + } +} diff --git a/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProviderAddon.java b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProviderAddon.java new file mode 100644 index 000000000..5db8dd51f --- /dev/null +++ b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageBiomeProviderAddon.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.image; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class ImageBiomeProviderAddon implements AddonInitializer { + public static final TypeKey>> PROVIDER_REGISTRY_KEY = new TypeKey<>() { + }; + + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + CheckedRegistry>> providerRegistry = event.getPack().getOrCreateRegistry( + PROVIDER_REGISTRY_KEY); + providerRegistry.register(addon.key("IMAGE"), + () -> new ImageProviderTemplate(event.getPack().getRegistry(Biome.class))); + }) + .failThrough(); + } +} diff --git a/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageProviderTemplate.java b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageProviderTemplate.java new file mode 100644 index 000000000..6bb683eca --- /dev/null +++ b/common/addons/biome-provider-image/src/main/java/com/dfsek/terra/addons/biome/image/ImageProviderTemplate.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.image; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Description; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.awt.image.BufferedImage; +import java.util.HashSet; + +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +@SuppressWarnings("FieldMayBeFinal") +public class ImageProviderTemplate implements ObjectTemplate { + private final Registry biomes; + @Value("resolution") + @Default + @Description("Sets the resolution at which to sample the image.") + private int resolution = 1; + @Value("image.name") + @Description("Sets the location of the image on the filesystem, relative to the pack root.") + private BufferedImage image; + @Value("image.align") + @Description("Sets the alignment style to use for the image.") + private ImageBiomeProvider.Align align; + + public ImageProviderTemplate(Registry set) { + this.biomes = set; + } + + @Override + public BiomeProvider get() { + return new ImageBiomeProvider(new HashSet<>(biomes.entries()), image, resolution, align); + } +} diff --git a/common/addons/biome-provider-image/src/main/resources/terra.addon.yml b/common/addons/biome-provider-image/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..3fd86ad52 --- /dev/null +++ b/common/addons/biome-provider-image/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: biome-provider-image +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.biome.image.ImageBiomeProviderAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/biome-provider-pipeline/LICENSE b/common/addons/biome-provider-pipeline/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/biome-provider-pipeline/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/biome-provider-pipeline/README.md b/common/addons/biome-provider-pipeline/README.md new file mode 100644 index 000000000..9e55109a7 --- /dev/null +++ b/common/addons/biome-provider-pipeline/README.md @@ -0,0 +1,7 @@ +# biome-provider-pipeline + +Implements the Biome Pipeline, a procedural biome provider that uses a series +of "stages" to apply "mutations" to a 2D grid of biomes. + +This addon registers the `PIPELINE` biome provider type, and all associated +configurations. \ No newline at end of file diff --git a/common/addons/biome-provider-pipeline/build.gradle.kts b/common/addons/biome-provider-pipeline/build.gradle.kts new file mode 100644 index 000000000..9342c3cad --- /dev/null +++ b/common/addons/biome-provider-pipeline/build.gradle.kts @@ -0,0 +1,14 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + implementation("com.github.ben-manes.caffeine:caffeine:3.1.0") + + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("com.github.benmanes.caffeine", "com.dfsek.terra.addons.biome.pipeline.lib.caffeine") + relocate("net.jafama", "com.dfsek.terra.addons.biome.pipeline.lib.jafama") +} \ No newline at end of file diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomeHolderImpl.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomeHolderImpl.java new file mode 100644 index 000000000..57304011b --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomeHolderImpl.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline; + +import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder; +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeExpander; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator; +import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.api.util.vector.Vector2; + + +public class BiomeHolderImpl implements BiomeHolder { + private final Vector2.Mutable origin; + private final int width; + private final int offset; + private BiomeDelegate[][] biomes; + + public BiomeHolderImpl(int width, Vector2.Mutable origin) { + width += 4; + this.width = width; + biomes = new BiomeDelegate[width][width]; + this.origin = origin; + this.offset = 2; + } + + private BiomeHolderImpl(BiomeDelegate[][] biomes, Vector2.Mutable origin, int width, int offset) { + this.biomes = biomes; + this.origin = origin; + this.width = width; + this.offset = 2 * offset; + } + + @Override + public BiomeHolder expand(BiomeExpander expander, long seed) { + BiomeDelegate[][] old = biomes; + int newWidth = width * 2 - 1; + + biomes = new BiomeDelegate[newWidth][newWidth]; + + for(int x = 0; x < width; x++) { + for(int z = 0; z < width; z++) { + biomes[x * 2][z * 2] = old[x][z]; + if(z != width - 1) + biomes[x * 2][z * 2 + 1] = expander.getBetween(x + origin.getX(), z + 1 + origin.getZ(), seed, old[x][z], + old[x][z + 1]); + if(x != width - 1) + biomes[x * 2 + 1][z * 2] = expander.getBetween(x + 1 + origin.getX(), z + origin.getZ(), seed, old[x][z], + old[x + 1][z]); + if(x != width - 1 && z != width - 1) + biomes[x * 2 + 1][z * 2 + 1] = expander.getBetween(x + 1 + origin.getX(), z + 1 + origin.getZ(), seed, old[x][z], + old[x + 1][z + 1], old[x][z + 1], old[x + 1][z]); + } + } + return new BiomeHolderImpl(biomes, origin.setX(origin.getX() * 2 - 1).setZ(origin.getZ() * 2 - 1), newWidth, offset); + } + + @Override + public void mutate(BiomeMutator mutator, long seed) { + for(int x = 0; x < width; x++) { + for(int z = 0; z < width; z++) { + BiomeMutator.ViewPoint viewPoint = new BiomeMutator.ViewPoint(this, x, z); + biomes[x][z] = mutator.mutate(viewPoint, x + origin.getX(), z + origin.getZ(), seed); + } + } + } + + @Override + public void fill(BiomeSource source, long seed) { + for(int x = 0; x < width; x++) { + for(int z = 0; z < width; z++) { + biomes[x][z] = source.getBiome(origin.getX() + x, origin.getZ() + z, seed); + } + } + } + + @Override + public BiomeDelegate getBiome(int x, int z) { + x += offset; + z += offset; + return getBiomeRaw(x, z); + } + + @Override + public BiomeDelegate getBiomeRaw(int x, int z) { + if(x >= width || z >= width || x < 0 || z < 0) return null; + return biomes[x][z]; + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipeline.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipeline.java new file mode 100644 index 000000000..8a4be5d7d --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipeline.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder; +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.api.util.vector.Vector2; + + +public class BiomePipeline { + private final BiomeSource source; + private final List stages; + private final int size; + private final int init; + + private BiomePipeline(BiomeSource source, List stages, int size, int init) { + this.source = source; + this.stages = stages; + this.size = size; + this.init = init; + } + + /** + * Get biomes in a chunk + * + * @param x Chunk X coord + * @param z Chunk Z coord + * + * @return BiomeHolder containing biomes. + */ + public BiomeHolder getBiomes(int x, int z, long seed) { + BiomeHolder holder = new BiomeHolderImpl(init, Vector2.of(x * (init - 1), z * (init - 1)).mutable()); + holder.fill(source, seed); + for(Stage stage : stages) holder = stage.apply(holder, seed); + return holder; + } + + public BiomeSource getSource() { + return source; + } + + public List getStages() { + return Collections.unmodifiableList(stages); + } + + public int getSize() { + return size; + } + + public static final class BiomePipelineBuilder { + private final int init; + private final List stages = new ArrayList<>(); + private int expand; + + public BiomePipelineBuilder(int init) { + this.init = init; + expand = init; + } + + public BiomePipeline build(BiomeSource source) { + for(Stage stage : stages) { + if(stage.isExpansion()) expand = expand * 2 - 1; + } + + return new BiomePipeline(source, stages, expand, init); + } + + public BiomePipelineBuilder addStage(Stage stage) { + stages.add(stage); + return this; + } + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineAddon.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineAddon.java new file mode 100644 index 000000000..42aa95b0e --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineAddon.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.config.BiomeDelegateLoader; +import com.dfsek.terra.addons.biome.pipeline.config.BiomePipelineTemplate; +import com.dfsek.terra.addons.biome.pipeline.config.SamplerSourceTemplate; +import com.dfsek.terra.addons.biome.pipeline.config.stage.expander.ExpanderStageTemplate; +import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderListMutatorTemplate; +import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderMutatorTemplate; +import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceListMutatorTemplate; +import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceMutatorTemplate; +import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.SmoothMutatorTemplate; +import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class BiomePipelineAddon implements AddonInitializer { + + public static final TypeKey>> SOURCE_REGISTRY_KEY = new TypeKey<>() { + }; + + public static final TypeKey>> STAGE_REGISTRY_KEY = new TypeKey<>() { + }; + public static final TypeKey>> PROVIDER_REGISTRY_KEY = new TypeKey<>() { + }; + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + CheckedRegistry>> providerRegistry = event.getPack().getOrCreateRegistry( + PROVIDER_REGISTRY_KEY); + providerRegistry.register(addon.key("PIPELINE"), BiomePipelineTemplate::new); + }) + .then(event -> { + CheckedRegistry>> sourceRegistry = event.getPack().getOrCreateRegistry( + SOURCE_REGISTRY_KEY); + sourceRegistry.register(addon.key("SAMPLER"), SamplerSourceTemplate::new); + }) + .then(event -> { + CheckedRegistry>> stageRegistry = event.getPack().getOrCreateRegistry( + STAGE_REGISTRY_KEY); + stageRegistry.register(addon.key("FRACTAL_EXPAND"), ExpanderStageTemplate::new); + stageRegistry.register(addon.key("SMOOTH"), SmoothMutatorTemplate::new); + stageRegistry.register(addon.key("REPLACE"), ReplaceMutatorTemplate::new); + stageRegistry.register(addon.key("REPLACE_LIST"), ReplaceListMutatorTemplate::new); + stageRegistry.register(addon.key("BORDER"), BorderMutatorTemplate::new); + stageRegistry.register(addon.key("BORDER_LIST"), BorderListMutatorTemplate::new); + }) + .failThrough(); + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPostLoadEvent.class) + .then(event -> { + Registry biomeRegistry = event.getPack().getRegistry(Biome.class); + event.getPack().applyLoader(BiomeDelegate.class, new BiomeDelegateLoader(biomeRegistry)); + }); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java new file mode 100644 index 000000000..bef494a0f --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/BiomePipelineProvider.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline; + +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import net.jafama.FastMath; + +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.StreamSupport; + +import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder; +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.registry.key.StringIdentifiable; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class BiomePipelineProvider implements BiomeProvider { + private final LoadingCache holderCache; + private final BiomePipeline pipeline; + private final int resolution; + private final NoiseSampler mutator; + private final double noiseAmp; + + private final Set biomes; + + public BiomePipelineProvider(BiomePipeline pipeline, int resolution, NoiseSampler mutator, double noiseAmp) { + this.resolution = resolution; + this.mutator = mutator; + this.noiseAmp = noiseAmp; + holderCache = Caffeine.newBuilder() + .maximumSize(1024) + .build(key -> pipeline.getBiomes(key.x, key.z, key.seed)); + this.pipeline = pipeline; + + Set biomeSet = new HashSet<>(); + pipeline.getSource().getBiomes().forEach(biomeSet::add); + Iterable result = biomeSet; + for(Stage stage : pipeline.getStages()) { + result = stage.getBiomes(result); // pass through all stages + } + this.biomes = new HashSet<>(); + Iterable finalResult = result; + result.forEach(biomeDelegate -> { + if(biomeDelegate.isEphemeral()) { + + StringBuilder biomeList = new StringBuilder("\n"); + StreamSupport.stream(finalResult.spliterator(), false) + .sorted(Comparator.comparing(StringIdentifiable::getID)) + .forEach(delegate -> biomeList + .append(" - ") + .append(delegate.getID()) + .append(':') + .append(delegate.getClass().getCanonicalName()) + .append('\n')); + throw new IllegalArgumentException("Biome Pipeline leaks ephemeral biome \"" + biomeDelegate.getID() + + "\". Ensure there is a stage to guarantee replacement of the ephemeral biome. Biomes: " + + biomeList); + } + this.biomes.add(biomeDelegate.getBiome()); + }); + } + + @Override + public Biome getBiome(int x, int y, int z, long seed) { + x += mutator.noise(seed + 1, x, z) * noiseAmp; + z += mutator.noise(seed + 2, x, z) * noiseAmp; + + + x = FastMath.floorToInt(FastMath.floorDiv(x, resolution)); + + z = FastMath.floorToInt(FastMath.floorDiv(z, resolution)); + + int fdX = FastMath.floorDiv(x, pipeline.getSize()); + int fdZ = FastMath.floorDiv(z, pipeline.getSize()); + return holderCache.get(new SeededVector(fdX, fdZ, seed)).getBiome(x - fdX * pipeline.getSize(), + z - fdZ * pipeline.getSize()).getBiome(); + } + + @Override + public Iterable getBiomes() { + return biomes; + } + + private record SeededVector(int x, int z, long seed) { + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/BiomeHolder.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/BiomeHolder.java new file mode 100644 index 000000000..26bb63315 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/BiomeHolder.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.api; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeExpander; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator; +import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource; + + +public interface BiomeHolder { + BiomeHolder expand(BiomeExpander expander, long seed); + + void mutate(BiomeMutator mutator, long seed); + + void fill(BiomeSource source, long seed); + + BiomeDelegate getBiome(int x, int z); + + BiomeDelegate getBiomeRaw(int x, int z); +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/BiomeDelegate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/BiomeDelegate.java new file mode 100644 index 000000000..7e339285a --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/BiomeDelegate.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.addons.biome.pipeline.api.delegate; + +import java.util.Set; + +import com.dfsek.terra.api.registry.key.StringIdentifiable; +import com.dfsek.terra.api.world.biome.Biome; + + +public interface BiomeDelegate extends StringIdentifiable { + static BiomeDelegate ephemeral(String id) { + return new EphemeralBiomeDelegate(id); + } + + static BiomeDelegate from(Biome biome) { + return new DelegatedBiome(biome); + } + + static BiomeDelegate self() { + return SelfDelegate.INSTANCE; + } + + Biome getBiome(); + + Set getTags(); + + default boolean isEphemeral() { + return false; + } + + default boolean isSelf() { + return false; + } + + +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/DelegatedBiome.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/DelegatedBiome.java new file mode 100644 index 000000000..4085f6a43 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/DelegatedBiome.java @@ -0,0 +1,40 @@ +package com.dfsek.terra.addons.biome.pipeline.api.delegate; + +import java.util.Set; + +import com.dfsek.terra.api.world.biome.Biome; + + +final class DelegatedBiome implements BiomeDelegate { + private final Biome biome; + + public DelegatedBiome(Biome biome) { + this.biome = biome; + } + + @Override + public Biome getBiome() { + return biome; + } + + @Override + public int hashCode() { + return biome.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof DelegatedBiome that)) return false; + return that.biome.equals(this.biome); + } + + @Override + public Set getTags() { + return biome.getTags(); + } + + @Override + public String getID() { + return biome.getID(); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/EphemeralBiomeDelegate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/EphemeralBiomeDelegate.java new file mode 100644 index 000000000..d02221f1b --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/EphemeralBiomeDelegate.java @@ -0,0 +1,51 @@ +package com.dfsek.terra.addons.biome.pipeline.api.delegate; + +import java.util.HashSet; +import java.util.Set; + +import com.dfsek.terra.api.world.biome.Biome; + + +final class EphemeralBiomeDelegate implements BiomeDelegate { + private final Set tags; + private final String id; + + public EphemeralBiomeDelegate(String id) { + this.id = id; + tags = new HashSet<>(); + tags.add(id); + tags.add("ALL"); + } + + @Override + public Biome getBiome() { + throw new UnsupportedOperationException("Cannot get biome from ephemeral delegate"); + } + + @Override + public Set getTags() { + return tags; + } + + @Override + public String getID() { + return id; + } + + @Override + public boolean isEphemeral() { + return true; + } + + @Override + public int hashCode() { + return id.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof EphemeralBiomeDelegate that)) return false; + + return this.id.equals(that.id); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/SelfDelegate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/SelfDelegate.java new file mode 100644 index 000000000..60b744059 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/delegate/SelfDelegate.java @@ -0,0 +1,40 @@ +package com.dfsek.terra.addons.biome.pipeline.api.delegate; + +import java.util.Collections; +import java.util.Set; + +import com.dfsek.terra.api.world.biome.Biome; + + +final class SelfDelegate implements BiomeDelegate { + public static final SelfDelegate INSTANCE = new SelfDelegate(); + + private SelfDelegate() { + + } + + @Override + public Biome getBiome() { + throw new UnsupportedOperationException("Cannot get biome from self delegate"); + } + + @Override + public boolean isSelf() { + return true; + } + + @Override + public boolean isEphemeral() { + return true; + } + + @Override + public Set getTags() { + return Collections.emptySet(); + } + + @Override + public String getID() { + return "SELF"; + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/stage/Stage.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/stage/Stage.java new file mode 100644 index 000000000..fb4b1007b --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/stage/Stage.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.api.stage; + +import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder; +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; + + +public interface Stage { + BiomeHolder apply(BiomeHolder in, long seed); + + boolean isExpansion(); + + Iterable getBiomes(Iterable biomes); +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/stage/type/BiomeExpander.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/stage/type/BiomeExpander.java new file mode 100644 index 000000000..c3e721c08 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/stage/type/BiomeExpander.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.api.stage.type; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; + + +public interface BiomeExpander { + BiomeDelegate getBetween(double x, double z, long seed, BiomeDelegate... others); +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/stage/type/BiomeMutator.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/stage/type/BiomeMutator.java new file mode 100644 index 000000000..f7cc3b7bd --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/api/stage/type/BiomeMutator.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.api.stage.type; + +import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder; +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; + + +public interface BiomeMutator { + BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed); + + default Iterable getBiomes(Iterable biomes) { + return biomes; + } + + class ViewPoint { + private final BiomeHolder biomes; + private final int offX; + private final int offZ; + + public ViewPoint(BiomeHolder biomes, int offX, int offZ) { + this.biomes = biomes; + this.offX = offX; + this.offZ = offZ; + } + + + public BiomeDelegate getBiome(int x, int z) { + return biomes.getBiomeRaw(x + offX, z + offZ); + } + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomeDelegateLoader.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomeDelegateLoader.java new file mode 100644 index 000000000..c416e4804 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomeDelegateLoader.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.addons.biome.pipeline.config; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.world.biome.Biome; + + +public class BiomeDelegateLoader implements TypeLoader { + private final Registry biomeRegistry; + + public BiomeDelegateLoader(Registry biomeRegistry) { + this.biomeRegistry = biomeRegistry; + } + + @Override + public BiomeDelegate load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) + throws LoadException { + if(c.equals("SELF")) return BiomeDelegate.self(); + return biomeRegistry + .getByID((String) c) + .map(BiomeDelegate::from) + .orElseGet(() -> BiomeDelegate.ephemeral((String) c)); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomePipelineTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomePipelineTemplate.java new file mode 100644 index 000000000..e35d621e2 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomePipelineTemplate.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Description; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.List; + +import com.dfsek.terra.addons.biome.pipeline.BiomePipeline; +import com.dfsek.terra.addons.biome.pipeline.BiomePipelineProvider; +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +@SuppressWarnings({ "FieldMayBeFinal", "unused" }) +public class BiomePipelineTemplate extends BiomeProviderTemplate { + @Value("pipeline.initial-size") + @Default + @Description(""" + The initial size of biome chunks. This value must be at least 2. + This is not the final size of biome chunks. Final chunks will be much larger. + + It is recommended to keep biome chunks' final size in the range of [50, 300] + to prevent performance issues. To calculate the size of biome chunks, simply + take initial-size and for each expand stage, multiply the running value by 2 + and subtract 1. (The size is also printed to the server console if you + have debug mode enabled)""") + private @Meta int initialSize = 2; + + @Value("pipeline.source") + @Description("The Biome Source to use for initial population of biomes.") + private @Meta BiomeSource source; + + @Value("pipeline.stages") + @Description("A list of pipeline stages to apply to the result of #source") + private @Meta List<@Meta Stage> stages; + + @Override + public BiomeProvider get() { + BiomePipeline.BiomePipelineBuilder biomePipelineBuilder = new BiomePipeline.BiomePipelineBuilder(initialSize); + stages.forEach(biomePipelineBuilder::addStage); + BiomePipeline pipeline = biomePipelineBuilder.build(source); + return new BiomePipelineProvider(pipeline, resolution, blend, blendAmp); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomeProviderTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomeProviderTemplate.java new file mode 100644 index 000000000..a6df1f200 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomeProviderTemplate.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Description; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public abstract class BiomeProviderTemplate implements ObjectTemplate { + @Value("resolution") + @Default + @Description(""" + The resolution at which to sample biomes. + + Larger values are quadratically faster, but produce lower quality results. + For example, a value of 3 would sample every 3 blocks.""") + protected @Meta int resolution = 1; + @Value("blend.sampler") + @Default + @Description("A sampler to use for blending the edges of biomes via domain warping.") + protected @Meta NoiseSampler blend = NoiseSampler.zero(); + @Value("blend.amplitude") + @Default + @Description("The amplitude at which to perform blending.") + protected @Meta double blendAmp = 0d; +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/SamplerSourceTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/SamplerSourceTemplate.java new file mode 100644 index 000000000..2ba70b608 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/SamplerSourceTemplate.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config; + +import com.dfsek.tectonic.api.config.template.annotations.Description; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource; +import com.dfsek.terra.addons.biome.pipeline.source.SamplerSource; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class SamplerSourceTemplate extends SourceTemplate { + @Value("sampler") + @Description("The sampler used to distribute biomes.") + private @Meta NoiseSampler noise; + + @Value("biomes") + @Description("The biomes to be distributed.") + private @Meta ProbabilityCollection<@Meta BiomeDelegate> biomes; + + @Override + public BiomeSource get() { + return new SamplerSource(biomes, noise); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/SourceTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/SourceTemplate.java new file mode 100644 index 000000000..c80ec0cee --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/SourceTemplate.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.biome.pipeline.source.BiomeSource; + + +public abstract class SourceTemplate implements ObjectTemplate { + +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/StageTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/StageTemplate.java new file mode 100644 index 000000000..ba4bee85d --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/StageTemplate.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config.stage; + +import com.dfsek.tectonic.api.config.template.annotations.Description; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public abstract class StageTemplate implements ObjectTemplate { + @Value("sampler") + @Description("Sampler to use for stage distribution.") + protected @Meta NoiseSampler noise; +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/expander/ExpanderStageTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/expander/ExpanderStageTemplate.java new file mode 100644 index 000000000..8f66315ef --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/expander/ExpanderStageTemplate.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config.stage.expander; + +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate; +import com.dfsek.terra.addons.biome.pipeline.expand.FractalExpander; +import com.dfsek.terra.addons.biome.pipeline.stages.ExpanderStage; + + +public class ExpanderStageTemplate extends StageTemplate { + @Override + public Stage get() { + return new ExpanderStage(new FractalExpander(noise)); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/BorderListMutatorTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/BorderListMutatorTemplate.java new file mode 100644 index 000000000..fcf523e44 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/BorderListMutatorTemplate.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.Map; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate; +import com.dfsek.terra.addons.biome.pipeline.mutator.BorderListMutator; +import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +@SuppressWarnings("unused") +public class BorderListMutatorTemplate extends StageTemplate { + @Value("from") + private @Meta String from; + + @Value("default-replace") + private @Meta String defaultReplace; + + @Value("default-to") + private @Meta ProbabilityCollection<@Meta BiomeDelegate> defaultTo; + + @Value("replace") + private @Meta Map<@Meta BiomeDelegate, @Meta ProbabilityCollection<@Meta BiomeDelegate>> replace; + + + @Override + public Stage get() { + return new MutatorStage(new BorderListMutator(replace, from, defaultReplace, noise, defaultTo)); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/BorderMutatorTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/BorderMutatorTemplate.java new file mode 100644 index 000000000..4db9e4e99 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/BorderMutatorTemplate.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate; +import com.dfsek.terra.addons.biome.pipeline.mutator.BorderMutator; +import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +@SuppressWarnings("unused") +public class BorderMutatorTemplate extends StageTemplate { + @Value("from") + private @Meta String from; + + @Value("replace") + private @Meta String replace; + + @Value("to") + private @Meta ProbabilityCollection<@Meta BiomeDelegate> to; + + @Override + public Stage get() { + return new MutatorStage(new BorderMutator(from, replace, noise, to)); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/ReplaceListMutatorTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/ReplaceListMutatorTemplate.java new file mode 100644 index 000000000..5713b3ff0 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/ReplaceListMutatorTemplate.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.Map; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate; +import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceListMutator; +import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +@SuppressWarnings("unused") +public class ReplaceListMutatorTemplate extends StageTemplate { + @Value("default-from") + private @Meta String defaultFrom; + + @Value("default-to") + private @Meta ProbabilityCollection<@Meta BiomeDelegate> defaultTo; + + @Value("to") + private @Meta Map<@Meta BiomeDelegate, @Meta ProbabilityCollection<@Meta BiomeDelegate>> replace; + + @Override + public Stage get() { + return new MutatorStage(new ReplaceListMutator(replace, defaultFrom, defaultTo, noise)); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/ReplaceMutatorTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/ReplaceMutatorTemplate.java new file mode 100644 index 000000000..dae592e2b --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/ReplaceMutatorTemplate.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate; +import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceMutator; +import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +@SuppressWarnings("unused") +public class ReplaceMutatorTemplate extends StageTemplate { + @Value("from") + private @Meta String from; + + @Value("to") + private @Meta ProbabilityCollection<@Meta BiomeDelegate> to; + + @Override + public Stage get() { + return new MutatorStage(new ReplaceMutator(from, to, noise)); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/SmoothMutatorTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/SmoothMutatorTemplate.java new file mode 100644 index 000000000..b26dce902 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/stage/mutator/SmoothMutatorTemplate.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator; + +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate; +import com.dfsek.terra.addons.biome.pipeline.mutator.SmoothMutator; +import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage; + + +public class SmoothMutatorTemplate extends StageTemplate { + @Override + public Stage get() { + return new MutatorStage(new SmoothMutator(noise)); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/expand/FractalExpander.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/expand/FractalExpander.java new file mode 100644 index 000000000..50d36a5c4 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/expand/FractalExpander.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.expand; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeExpander; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.MathUtil; + + +public class FractalExpander implements BiomeExpander { + private final NoiseSampler sampler; + + public FractalExpander(NoiseSampler sampler) { + this.sampler = sampler; + } + + @Override + public BiomeDelegate getBetween(double x, double z, long seed, BiomeDelegate... others) { + return others[MathUtil.normalizeIndex(sampler.noise(seed, x, z), others.length)]; + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/BorderListMutator.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/BorderListMutator.java new file mode 100644 index 000000000..59f6dd9b4 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/BorderListMutator.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.mutator; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class BorderListMutator implements BiomeMutator { + private final String border; + private final NoiseSampler noiseSampler; + private final ProbabilityCollection replaceDefault; + private final String defaultReplace; + private final Map> replace; + + public BorderListMutator(Map> replace, String border, String defaultReplace, + NoiseSampler noiseSampler, ProbabilityCollection replaceDefault) { + this.border = border; + this.noiseSampler = noiseSampler; + this.replaceDefault = replaceDefault; + this.defaultReplace = defaultReplace; + this.replace = replace; + } + + @Override + public BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed) { + BiomeDelegate origin = viewPoint.getBiome(0, 0); + if(origin.getTags().contains(defaultReplace)) { + for(int xi = -1; xi <= 1; xi++) { + for(int zi = -1; zi <= 1; zi++) { + if(xi == 0 && zi == 0) continue; + BiomeDelegate current = viewPoint.getBiome(xi, zi); + if(current != null && current.getTags().contains(border)) { + if(replace.containsKey(origin)) { + BiomeDelegate biome = replace.get(origin).get(noiseSampler, x, z, seed); + return biome.isSelf() ? origin : biome; + } + BiomeDelegate biome = replaceDefault.get(noiseSampler, x, z, seed); + return biome.isSelf() ? origin : biome; + } + } + } + } + return origin; + } + + @Override + public Iterable getBiomes(Iterable biomes) { + Set biomeSet = new HashSet<>(); + biomes.forEach(biomeSet::add); + biomeSet.addAll(replaceDefault.getContents().stream().filter(Predicate.not(BiomeDelegate::isSelf)).toList()); + replace.forEach((biome, collection) -> biomeSet.addAll(collection.getContents())); + return biomeSet; + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/BorderMutator.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/BorderMutator.java new file mode 100644 index 000000000..5755719f4 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/BorderMutator.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.mutator; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class BorderMutator implements BiomeMutator { + private final String border; + private final NoiseSampler noiseSampler; + private final ProbabilityCollection replace; + private final String replaceTag; + + public BorderMutator(String border, String replaceTag, NoiseSampler noiseSampler, ProbabilityCollection replace) { + this.border = border; + this.noiseSampler = noiseSampler; + this.replace = replace; + this.replaceTag = replaceTag; + } + + @Override + public BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed) { + BiomeDelegate origin = viewPoint.getBiome(0, 0); + if(origin.getTags().contains(replaceTag)) { + for(int xi = -1; xi <= 1; xi++) { + for(int zi = -1; zi <= 1; zi++) { + if(xi == 0 && zi == 0) continue; + BiomeDelegate current = viewPoint.getBiome(xi, zi); + if(current != null && current.getTags().contains(border)) { + BiomeDelegate biome = replace.get(noiseSampler, x, z, seed); + return biome.isSelf() ? origin : biome; + } + } + } + } + return origin; + } + + @Override + public Iterable getBiomes(Iterable biomes) { + Set biomeSet = new HashSet<>(); + biomes.forEach(biomeSet::add); + biomeSet.addAll( + replace + .getContents() + .stream() + .filter( + Predicate.not(BiomeDelegate::isSelf) + ) + .toList() + ); + return biomeSet; + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/ReplaceListMutator.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/ReplaceListMutator.java new file mode 100644 index 000000000..51a74c285 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/ReplaceListMutator.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.mutator; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class ReplaceListMutator implements BiomeMutator { + private final Map> replace; + private final NoiseSampler sampler; + private final ProbabilityCollection replaceDefault; + private final String defaultTag; + + public ReplaceListMutator(Map> replace, String defaultTag, + ProbabilityCollection replaceDefault, NoiseSampler sampler) { + this.replace = replace; + this.sampler = sampler; + this.defaultTag = defaultTag; + this.replaceDefault = replaceDefault; + } + + @Override + public BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed) { + BiomeDelegate center = viewPoint.getBiome(0, 0); + if(replace.containsKey(center)) { + BiomeDelegate biome = replace.get(center).get(sampler, x, z, seed); + return biome.isSelf() ? viewPoint.getBiome(0, 0) : biome; + } + if(viewPoint.getBiome(0, 0).getTags().contains(defaultTag)) { + BiomeDelegate biome = replaceDefault.get(sampler, x, z, seed); + return biome.isSelf() ? viewPoint.getBiome(0, 0) : biome; + } + return center; + } + + @Override + public Iterable getBiomes(Iterable biomes) { + Set biomeSet = new HashSet<>(); + + Set reject = new HashSet<>(); + + biomes.forEach(biome -> { + if(!biome.getTags().contains(defaultTag) && !replace.containsKey(biome)) { + biomeSet.add(biome); + } else { + reject.add(biome); + } + }); + biomeSet.addAll(replaceDefault.getContents().stream().flatMap(terraBiome -> { + if(terraBiome.isSelf()) return reject.stream(); + return Stream.of(terraBiome); + }).toList()); + replace.forEach((biome, collection) -> biomeSet.addAll(collection.getContents().stream().map(terraBiome -> { + if(terraBiome.isSelf()) return biome; + return terraBiome; + }).toList())); + return biomeSet; + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/ReplaceMutator.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/ReplaceMutator.java new file mode 100644 index 000000000..cec3e5e9e --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/ReplaceMutator.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.mutator; + +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Stream; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class ReplaceMutator implements BiomeMutator { + private final String replaceableTag; + private final ProbabilityCollection replace; + private final NoiseSampler sampler; + + public ReplaceMutator(String replaceable, ProbabilityCollection replace, NoiseSampler sampler) { + this.replaceableTag = replaceable; + this.replace = replace; + this.sampler = sampler; + } + + @Override + public BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed) { + if(viewPoint.getBiome(0, 0).getTags().contains(replaceableTag)) { + BiomeDelegate biome = replace.get(sampler, x, z, seed); + return biome.isSelf() ? viewPoint.getBiome(0, 0) : biome; + } + return viewPoint.getBiome(0, 0); + } + + @Override + public Iterable getBiomes(Iterable biomes) { + Set biomeSet = new HashSet<>(); + Set reject = new HashSet<>(); + biomes.forEach(biome -> { + if(!biome.getTags().contains(replaceableTag)) { + biomeSet.add(biome); + } else { + reject.add(biome); + } + }); + biomeSet.addAll(replace.getContents().stream().flatMap(terraBiome -> { + if(terraBiome.isSelf()) return reject.stream(); + return Stream.of(terraBiome); + }).toList()); + return biomeSet; + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/SmoothMutator.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/SmoothMutator.java new file mode 100644 index 000000000..4785216e8 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/mutator/SmoothMutator.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.mutator; + +import java.util.Objects; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.MathUtil; + + +public class SmoothMutator implements BiomeMutator { + + private final NoiseSampler sampler; + + public SmoothMutator(NoiseSampler sampler) { + this.sampler = sampler; + } + + @Override + public BiomeDelegate mutate(ViewPoint viewPoint, double x, double z, long seed) { + BiomeDelegate top = viewPoint.getBiome(1, 0); + BiomeDelegate bottom = viewPoint.getBiome(-1, 0); + BiomeDelegate left = viewPoint.getBiome(0, 1); + BiomeDelegate right = viewPoint.getBiome(0, -1); + + + boolean vert = Objects.equals(top, bottom) && top != null; + boolean horiz = Objects.equals(left, right) && left != null; + + if(vert && horiz) { + return MathUtil.normalizeIndex(sampler.noise(seed, x, z), 2) == 0 ? left : top; + } + + if(vert) return top; + if(horiz) return left; + + return viewPoint.getBiome(0, 0); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/source/BiomeSource.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/source/BiomeSource.java new file mode 100644 index 000000000..d56151f07 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/source/BiomeSource.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.source; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; + + +public interface BiomeSource { + BiomeDelegate getBiome(double x, double z, long seed); + + Iterable getBiomes(); +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/source/SamplerSource.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/source/SamplerSource.java new file mode 100644 index 000000000..62656ac17 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/source/SamplerSource.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.source; + +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class SamplerSource implements BiomeSource { + private final ProbabilityCollection biomes; + private final NoiseSampler sampler; + + public SamplerSource(ProbabilityCollection biomes, NoiseSampler sampler) { + this.biomes = biomes; + this.sampler = sampler; + } + + @Override + public BiomeDelegate getBiome(double x, double z, long seed) { + return biomes.get(sampler, x, z, seed); + } + + @Override + public Iterable getBiomes() { + return biomes.getContents(); + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/stages/ExpanderStage.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/stages/ExpanderStage.java new file mode 100644 index 000000000..e99c13e6b --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/stages/ExpanderStage.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.stages; + +import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder; +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeExpander; + + +public class ExpanderStage implements Stage { + private final BiomeExpander expander; + + public ExpanderStage(BiomeExpander expander) { + this.expander = expander; + } + + @Override + public BiomeHolder apply(BiomeHolder in, long seed) { + return in.expand(expander, seed); + } + + @Override + public boolean isExpansion() { + return true; + } + + @Override + public Iterable getBiomes(Iterable biomes) { + return biomes; + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/stages/MutatorStage.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/stages/MutatorStage.java new file mode 100644 index 000000000..8a9a06aae --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/stages/MutatorStage.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.pipeline.stages; + +import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder; +import com.dfsek.terra.addons.biome.pipeline.api.delegate.BiomeDelegate; +import com.dfsek.terra.addons.biome.pipeline.api.stage.Stage; +import com.dfsek.terra.addons.biome.pipeline.api.stage.type.BiomeMutator; + + +public class MutatorStage implements Stage { + private final BiomeMutator mutator; + + public MutatorStage(BiomeMutator mutator) { + this.mutator = mutator; + } + + @Override + public BiomeHolder apply(BiomeHolder in, long seed) { + in.mutate(mutator, seed); + return in; + } + + @Override + public boolean isExpansion() { + return false; + } + + @Override + public Iterable getBiomes(Iterable biomes) { + return mutator.getBiomes(biomes); + } + + public enum Type { + REPLACE, + REPLACE_LIST, + BORDER, + BORDER_LIST, + SMOOTH + } +} diff --git a/common/addons/biome-provider-pipeline/src/main/resources/terra.addon.yml b/common/addons/biome-provider-pipeline/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..abd2555a5 --- /dev/null +++ b/common/addons/biome-provider-pipeline/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: biome-provider-pipeline +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.biome.pipeline.BiomePipelineAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/biome-provider-single/LICENSE b/common/addons/biome-provider-single/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/biome-provider-single/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/biome-provider-single/README.md b/common/addons/biome-provider-single/README.md new file mode 100644 index 000000000..3bea8cbb5 --- /dev/null +++ b/common/addons/biome-provider-single/README.md @@ -0,0 +1,4 @@ +# biome-provider-single + +Registers and configures the `SINGLE` biome provider, a biome provider which +accepts a single biome to generate continuously. \ No newline at end of file diff --git a/common/addons/biome-provider-single/build.gradle.kts b/common/addons/biome-provider-single/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/biome-provider-single/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProvider.java b/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProvider.java new file mode 100644 index 000000000..0ca97bfbc --- /dev/null +++ b/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.single; + +import java.util.Collections; + +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class SingleBiomeProvider implements BiomeProvider { + private final Biome biome; + + public SingleBiomeProvider(Biome biome) { + this.biome = biome; + } + + @Override + public Biome getBiome(int x, int y, int z, long seed) { + return biome; + } + + @Override + public Iterable getBiomes() { + return Collections.singleton(biome); + } +} diff --git a/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProviderAddon.java b/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProviderAddon.java new file mode 100644 index 000000000..ecf4a9c7b --- /dev/null +++ b/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProviderAddon.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.single; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class SingleBiomeProviderAddon implements AddonInitializer { + public static final TypeKey>> PROVIDER_REGISTRY_KEY = new TypeKey<>() { + }; + + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + CheckedRegistry>> providerRegistry = event.getPack().getOrCreateRegistry( + PROVIDER_REGISTRY_KEY); + providerRegistry.register(addon.key("SINGLE"), SingleBiomeProviderTemplate::new); + }) + .failThrough(); + } +} diff --git a/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProviderTemplate.java b/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProviderTemplate.java new file mode 100644 index 000000000..707553ccd --- /dev/null +++ b/common/addons/biome-provider-single/src/main/java/com/dfsek/terra/addons/biome/single/SingleBiomeProviderTemplate.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.single; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class SingleBiomeProviderTemplate implements ObjectTemplate { + @Value("biome") + private @Meta Biome biome; + + @Override + public BiomeProvider get() { + return new SingleBiomeProvider(biome); + } +} diff --git a/common/addons/biome-provider-single/src/main/resources/terra.addon.yml b/common/addons/biome-provider-single/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..d986179f3 --- /dev/null +++ b/common/addons/biome-provider-single/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: biome-provider-single +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.biome.single.SingleBiomeProviderAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/chunk-generator-noise-3d/LICENSE b/common/addons/chunk-generator-noise-3d/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/chunk-generator-noise-3d/README.md b/common/addons/chunk-generator-noise-3d/README.md new file mode 100644 index 000000000..b235df2e6 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/README.md @@ -0,0 +1,4 @@ +# chunk-generator-noise-3d + +Registers the `NOISE_3D` chunk generator, a chunk generator which uses biomes' +samplers in 3D to generate chunk data. \ No newline at end of file diff --git a/common/addons/chunk-generator-noise-3d/build.gradle.kts b/common/addons/chunk-generator-noise-3d/build.gradle.kts new file mode 100644 index 000000000..36e6012d7 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/build.gradle.kts @@ -0,0 +1,12 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("net.jafama", "com.dfsek.terra.addons.chunkgenerator.lib.jafama") +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java new file mode 100644 index 000000000..a36f9093b --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/NoiseChunkGenerator3DAddon.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator; + +import com.dfsek.terra.addons.chunkgenerator.config.NoiseChunkGeneratorPackConfigTemplate; +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseConfigTemplate; +import com.dfsek.terra.addons.chunkgenerator.config.palette.BiomePaletteTemplate; +import com.dfsek.terra.addons.chunkgenerator.config.palette.SlantLayer; +import com.dfsek.terra.addons.chunkgenerator.generation.NoiseChunkGenerator3D; +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider; + + +public class NoiseChunkGenerator3DAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + NoiseChunkGeneratorPackConfigTemplate config = event.loadTemplate(new NoiseChunkGeneratorPackConfigTemplate()); + + event.getPack() + .getOrCreateRegistry(ChunkGeneratorProvider.class) + .register(addon.key("NOISE_3D"), + pack -> new NoiseChunkGenerator3D(platform, config.getElevationBlend(), config.getHorizontalRes(), + config.getVerticalRes())); + event.getPack() + .applyLoader(SlantLayer.class, SlantLayer::new); + }) + .failThrough(); + + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigurationLoadEvent.class) + .then(event -> { + if(event.is(Biome.class)) { + event.getLoadedObject(Biome.class).getContext().put(event.load(new BiomePaletteTemplate(platform)).get()); + event.getLoadedObject(Biome.class).getContext().put(event.load(new BiomeNoiseConfigTemplate()).get()); + } + }) + .failThrough(); + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/NoiseChunkGeneratorPackConfigTemplate.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/NoiseChunkGeneratorPackConfigTemplate.java new file mode 100644 index 000000000..e636ae400 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/NoiseChunkGeneratorPackConfigTemplate.java @@ -0,0 +1,34 @@ +package com.dfsek.terra.addons.chunkgenerator.config; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.api.config.meta.Meta; + + +public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate { + @Value("blend.terrain.elevation") + @Default + private @Meta int elevationBlend = 4; + + @Value("carving.resolution.horizontal") + @Default + private @Meta int horizontalRes = 4; + + @Value("carving.resolution.vertical") + @Default + private @Meta int verticalRes = 2; + + public int getElevationBlend() { + return elevationBlend; + } + + public int getHorizontalRes() { + return horizontalRes; + } + + public int getVerticalRes() { + return verticalRes; + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java new file mode 100644 index 000000000..14d3c97d2 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseConfigTemplate.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.addons.chunkgenerator.config.noise; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class BiomeNoiseConfigTemplate implements ObjectTemplate { + @Value("terrain.sampler") + private @Meta NoiseSampler baseSampler; + + @Value("terrain.sampler-2d") + @Default + private @Meta NoiseSampler elevationSampler = NoiseSampler.zero(); + + @Value("carving.sampler") + @Default + private @Meta NoiseSampler carvingSampler = NoiseSampler.zero(); + + @Value("terrain.blend.distance") + @Default + private @Meta int blendDistance = 3; + + @Value("terrain.blend.weight") + @Default + private @Meta double blendWeight = 1; + + @Value("terrain.blend.step") + @Default + private @Meta int blendStep = 4; + + @Value("terrain.blend.weight-2d") + @Default + private @Meta double elevationWeight = 1; + + @Override + public BiomeNoiseProperties get() { + return new BiomeNoiseProperties(baseSampler, elevationSampler, carvingSampler, blendDistance, blendStep, blendWeight, + elevationWeight); + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseProperties.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseProperties.java new file mode 100644 index 000000000..76abd5059 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/noise/BiomeNoiseProperties.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.addons.chunkgenerator.config.noise; + +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.properties.Properties; + + +public record BiomeNoiseProperties(NoiseSampler base, + NoiseSampler elevation, + NoiseSampler carving, + int blendDistance, + int blendStep, + double blendWeight, + double elevationWeight) implements Properties { + +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/BiomePaletteTemplate.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/BiomePaletteTemplate.java new file mode 100644 index 000000000..3497bdd75 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/BiomePaletteTemplate.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.config.palette; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Description; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder; +import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolderBuilder; +import com.dfsek.terra.addons.chunkgenerator.palette.SlantHolder; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class BiomePaletteTemplate implements ObjectTemplate { + private final Platform platform; + + @Value("slant") + @Default + @Description("The slant palettes to use in this biome.") + private @Meta List<@Meta SlantLayer> slant = Collections.emptyList(); + + @Value("slant-depth") + @Default + @Description("The maximum depth at which to apply a slant palette.") + private @Meta int slantDepth = Integer.MAX_VALUE; + + @Value("palette") + @Description("The palettes to use in this biome.") + private @Meta List<@Meta Map<@Meta Palette, @Meta Integer>> palettes; + + @Value("ocean.level") + @Description("Sea level in this biome. Defaults to zero") + @Default + private @Meta int seaLevel = 0; + + @Value("ocean.palette") + @Description("The palette to use for the ocean in this biome. Defaults to a blank palette.") + @Default + private @Meta Palette oceanPalette = new Palette() { + @Override + public BlockState get(int layer, double x, double y, double z, long seed) { + return platform.getWorldHandle().air(); + } + }; + + public BiomePaletteTemplate(Platform platform) { this.platform = platform; } + + @Override + public PaletteInfo get() { + PaletteHolderBuilder builder = new PaletteHolderBuilder(); + for(Map layer : palettes) { + for(Entry entry : layer.entrySet()) { + builder.add(entry.getValue(), entry.getKey()); + } + } + + TreeMap slantLayers = new TreeMap<>(); + double minThreshold = Double.MAX_VALUE; + + for(SlantLayer layer : slant) { + double threshold = layer.getThreshold(); + if(threshold < minThreshold) minThreshold = threshold; + slantLayers.put(threshold, layer.getPalette()); + } + + return new PaletteInfo(builder.build(), SlantHolder.of(slantLayers, minThreshold), oceanPalette, seaLevel, slantDepth); + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/PaletteInfo.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/PaletteInfo.java new file mode 100644 index 000000000..d866446a3 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/PaletteInfo.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.config.palette; + +import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder; +import com.dfsek.terra.addons.chunkgenerator.palette.SlantHolder; +import com.dfsek.terra.api.properties.Properties; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public record PaletteInfo(PaletteHolder paletteHolder, + SlantHolder slantHolder, + Palette ocean, + int seaLevel, + int maxSlantDepth) implements Properties { +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/SlantLayer.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/SlantLayer.java new file mode 100644 index 000000000..d63cbbb46 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/SlantLayer.java @@ -0,0 +1,42 @@ +package com.dfsek.terra.addons.chunkgenerator.config.palette; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder; +import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolderBuilder; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class SlantLayer implements ObjectTemplate { + @Value("threshold") + private @Meta double threshold; + + @Value("palette") + private @Meta List<@Meta Map<@Meta Palette, @Meta Integer>> palettes; + + @Override + public SlantLayer get() { + return this; + } + + public double getThreshold() { + return threshold; + } + + public PaletteHolder getPalette() { + PaletteHolderBuilder builder = new PaletteHolderBuilder(); + for(Map layer : palettes) { + for(Entry entry : layer.entrySet()) { + builder.add(entry.getValue(), entry.getKey()); + } + } + + return builder.build(); + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/NoiseChunkGenerator3D.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/NoiseChunkGenerator3D.java new file mode 100644 index 000000000..300cdbfcc --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/NoiseChunkGenerator3D.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.generation; + + +import net.jafama.FastMath; +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.addons.chunkgenerator.config.palette.PaletteInfo; +import com.dfsek.terra.addons.chunkgenerator.generation.math.PaletteUtil; +import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.LazilyEvaluatedInterpolator; +import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D; +import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; +import com.dfsek.terra.api.world.info.WorldProperties; + + +public class NoiseChunkGenerator3D implements ChunkGenerator { + private final Platform platform; + + private final SamplerProvider samplerCache; + + private final BlockState air; + + private final int carverHorizontalResolution; + private final int carverVerticalResolution; + + public NoiseChunkGenerator3D(Platform platform, int elevationBlend, int carverHorizontalResolution, + int carverVerticalResolution) { + this.platform = platform; + this.air = platform.getWorldHandle().air(); + this.carverHorizontalResolution = carverHorizontalResolution; + this.carverVerticalResolution = carverVerticalResolution; + this.samplerCache = new SamplerProvider(platform, elevationBlend); + } + + @Override + @SuppressWarnings("try") + public void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldProperties world, + @NotNull BiomeProvider biomeProvider, + int chunkX, int chunkZ) { + platform.getProfiler().push("chunk_base_3d"); + int xOrig = (chunkX << 4); + int zOrig = (chunkZ << 4); + + Sampler3D sampler = samplerCache.getChunk(chunkX, chunkZ, world, biomeProvider); + + long seed = world.getSeed(); + + LazilyEvaluatedInterpolator carver = new LazilyEvaluatedInterpolator(biomeProvider, + chunkX, + chunkZ, + world.getMaxHeight(), + world.getMinHeight(), + carverHorizontalResolution, + carverVerticalResolution, + seed); + for(int x = 0; x < 16; x++) { + for(int z = 0; z < 16; z++) { + int paletteLevel = 0; + + int cx = xOrig + x; + int cz = zOrig + z; + + Biome biome = biomeProvider.getBiome(cx, 0, cz, seed); + + PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); + + int sea = paletteInfo.seaLevel(); + Palette seaPalette = paletteInfo.ocean(); + + BlockState data; + for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { + if(sampler.sample(x, y, z) > 0) { + if(carver.sample(x, y, z) <= 0) { + data = PaletteUtil.getPalette(x, y, z, sampler, paletteInfo, paletteLevel).get(paletteLevel, cx, y, cz, + seed); + chunk.setBlock(x, y, z, data); + } + + paletteLevel++; + } else if(y <= sea) { + chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig, seed)); + paletteLevel = 0; + } else { + paletteLevel = 0; + } + } + } + } + platform.getProfiler().pop("chunk_base_3d"); + } + + @Override + public BlockState getBlock(WorldProperties world, int x, int y, int z, BiomeProvider biomeProvider) { + Biome biome = biomeProvider.getBiome(x, y, z, world.getSeed()); + Sampler3D sampler = samplerCache.get(x, z, world, biomeProvider); + + PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); + + int fdX = FastMath.floorMod(x, 16); + int fdZ = FastMath.floorMod(z, 16); + + Palette palette = PaletteUtil.getPalette(fdX, y, fdZ, sampler, paletteInfo, 0); + double noise = sampler.sample(fdX, y, fdZ); + if(noise > 0) { + int level = 0; + for(int yi = world.getMaxHeight() - 1; yi > y; yi--) { + if(sampler.sample(fdX, yi, fdZ) > 0) level++; + else level = 0; + } + return palette.get(level, x, y, z, world.getSeed()); + } else if(y <= paletteInfo.seaLevel()) { + return paletteInfo.ocean().get(paletteInfo.seaLevel() - y, x, y, z, world.getSeed()); + } else return air; + } + + @Override + public Palette getPalette(int x, int y, int z, WorldProperties world, BiomeProvider biomeProvider) { + return biomeProvider.getBiome(x, y, z, world.getSeed()).getContext().get(PaletteInfo.class).paletteHolder().getPalette(y); + } + + public SamplerProvider samplerProvider() { + return samplerCache; + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/PaletteUtil.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/PaletteUtil.java new file mode 100644 index 000000000..d649cf4f2 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/PaletteUtil.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.generation.math; + +import com.dfsek.terra.addons.chunkgenerator.config.palette.PaletteInfo; +import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D; +import com.dfsek.terra.addons.chunkgenerator.palette.SlantHolder; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public final class PaletteUtil { + /** + * Derivative constant. + */ + private static final double DERIVATIVE_DIST = 0.55; + + public static Palette getPalette(int x, int y, int z, Sampler3D sampler, PaletteInfo paletteInfo, int depth) { + SlantHolder slant = paletteInfo.slantHolder(); + if(!slant.isEmpty() && depth <= paletteInfo.maxSlantDepth()) { + double slope = derivative(sampler, x, y, z); + if(slope > slant.getMinSlope()) { + return slant.getPalette(slope).getPalette(y); + } + } + + return paletteInfo.paletteHolder().getPalette(y); + } + + public static double derivative(Sampler3D sampler, double x, double y, double z) { + double baseSample = sampler.sample(x, y, z); + + double xVal1 = (sampler.sample(x + DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST; + double xVal2 = (sampler.sample(x - DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST; + double zVal1 = (sampler.sample(x, y, z + DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST; + double zVal2 = (sampler.sample(x, y, z - DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST; + double yVal1 = (sampler.sample(x, y + DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST; + double yVal2 = (sampler.sample(x, y - DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST; + + return Math.sqrt(((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1))); + } +} \ No newline at end of file diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java new file mode 100644 index 000000000..9f8cb782f --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ChunkInterpolator.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; + +import net.jafama.FastMath; + +import java.util.HashMap; +import java.util.Map; + +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; +import com.dfsek.terra.api.util.mutable.MutableInteger; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +/** + * Class to abstract away the Interpolators needed to generate a chunk.
+ * Contains method to get interpolated noise at a coordinate within the chunk. + */ +public class ChunkInterpolator { + private final Interpolator3[][][] interpGrid; + private final long seed; + + private final int min; + private final int max; + + /** + * Instantiates a 3D ChunkInterpolator3D at a pair of chunk coordinates. + * + * @param chunkX X coordinate of the chunk. + * @param chunkZ Z coordinate of the chunk. + * @param provider Biome Provider to use for biome fetching. + * @param min + * @param max + */ + public ChunkInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int min, int max) { + this.min = min; + this.max = max; + this.seed = seed; + + int xOrigin = chunkX << 4; + int zOrigin = chunkZ << 4; + + int range = this.max - this.min + 1; + + int size = range >> 2; + + interpGrid = new Interpolator3[4][size][4]; + + double[][][] noiseStorage = new double[5][5][size + 1]; + + for(int x = 0; x < 5; x++) { + for(int z = 0; z < 5; z++) { + BiomeNoiseProperties generationSettings = provider.getBiome(xOrigin + (x << 2), 0, zOrigin + (z << 2), seed) + .getContext() + .get(BiomeNoiseProperties.class); + Map genMap = new HashMap<>(); + + int step = generationSettings.blendStep(); + int blend = generationSettings.blendDistance(); + + for(int xi = -blend; xi <= blend; xi++) { + for(int zi = -blend; zi <= blend; zi++) { + genMap.computeIfAbsent( + provider.getBiome(xOrigin + (x << 2) + (xi * step), 0, zOrigin + (z << 2) + (zi * step), seed) + .getContext() + .get(BiomeNoiseProperties.class), + g -> new MutableInteger(0)).increment(); // Increment by 1 + } + } + + for(int y = 0; y < size + 1; y++) { + noiseStorage[x][z][y] = computeNoise(genMap, (x << 2) + xOrigin, (y << 2) + this.min, (z << 2) + zOrigin); + } + } + } + + for(int x = 0; x < 4; x++) { + for(int z = 0; z < 4; z++) { + for(int y = 0; y < size; y++) { + interpGrid[x][y][z] = new Interpolator3( + noiseStorage[x][z][y], + noiseStorage[x + 1][z][y], + noiseStorage[x][z][y + 1], + noiseStorage[x + 1][z][y + 1], + noiseStorage[x][z + 1][y], + noiseStorage[x + 1][z + 1][y], + noiseStorage[x][z + 1][y + 1], + noiseStorage[x + 1][z + 1][y + 1]); + } + } + } + } + + private static int reRange(int value, int high) { + return FastMath.max(FastMath.min(value, high), 0); + } + + public double computeNoise(BiomeNoiseProperties generationSettings, double x, double y, double z) { + return generationSettings.base().noise(seed, x, y, z); + } + + public double computeNoise(Map gens, double x, double y, double z) { + double n = 0; + double div = 0; + for(Map.Entry entry : gens.entrySet()) { + BiomeNoiseProperties gen = entry.getKey(); + int weight = entry.getValue().get(); + double noise = computeNoise(gen, x, y, z); + + n += noise * weight; + div += gen.blendWeight() * weight; + } + return n / div; + } + + /** + * Gets the noise at a pair of internal chunk coordinates. + * + * @param x The internal X coordinate (0-15). + * @param z The internal Z coordinate (0-15). + * + * @return double - The interpolated noise at the coordinates. + */ + public double getNoise(double x, double y, double z) { + return interpGrid[reRange(((int) x) / 4, 3)][(FastMath.max(FastMath.min(((int) y), max), min) - min) / 4][reRange(((int) z) / 4, + 3)].trilerp( + (x % 4) / 4, (y % 4) / 4, (z % 4) / 4); + } + + public double getNoise(int x, int y, int z) { + return interpGrid[x / 4][(y - min) / 4][z / 4].trilerp( + (double) (x & 3) / 4, // x & 3 == x % 4 + (double) (y & 3) / 4, // x & 3 == x % 4 + (double) (z & 3) / 4 // x & 3 == x % 4 + ); + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java new file mode 100644 index 000000000..0342ca751 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/ElevationInterpolator.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; + +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class ElevationInterpolator { + private final double[][] values = new double[18][18]; + + public ElevationInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int smooth) { + int xOrigin = chunkX << 4; + int zOrigin = chunkZ << 4; + + BiomeNoiseProperties[][] gens = new BiomeNoiseProperties[18 + 2 * smooth][18 + 2 * smooth]; + + // Precompute generators. + for(int x = -1 - smooth; x <= 16 + smooth; x++) { + for(int z = -1 - smooth; z <= 16 + smooth; z++) { + gens[x + 1 + smooth][z + 1 + smooth] = provider.getBiome(xOrigin + x, 0, zOrigin + z, seed).getContext().get( + BiomeNoiseProperties.class); + } + } + + for(int x = -1; x <= 16; x++) { + for(int z = -1; z <= 16; z++) { + double noise = 0; + double div = 0; + + BiomeNoiseProperties center = gens[x + 1 + smooth][z + 1 + smooth]; + boolean same = true; + + for(int xi = -smooth; xi <= smooth; xi++) { + for(int zi = -smooth; zi <= smooth; zi++) { + if(gens[x + 1 + smooth + xi][z + 1 + smooth + zi] != + center) { // test referential equality because thats all we need to know + same = false; + break; + } + } + } + + if(same) { + values[x + 1][z + 1] = center.elevation().noise(seed, xOrigin + x, zOrigin + z); // no weighting needed! + } else { + for(int xi = -smooth; xi <= smooth; xi++) { + for(int zi = -smooth; zi <= smooth; zi++) { + BiomeNoiseProperties gen = gens[x + 1 + smooth + xi][z + 1 + smooth + zi]; + noise += gen.elevation().noise(seed, xOrigin + x, zOrigin + z) * gen.elevationWeight(); + div += gen.elevationWeight(); + } + } + values[x + 1][z + 1] = noise / div; + } + } + } + } + + public double getElevation(int x, int z) { + return values[x + 1][z + 1]; + } +} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/Interpolator.java similarity index 79% rename from common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator.java rename to common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/Interpolator.java index bf002e8a4..e96e15879 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/Interpolator.java @@ -1,11 +1,18 @@ -package com.dfsek.terra.world.generation.math.interpolation; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; /** * Class for bilinear interpolation of values arranged on a unit square. */ public class Interpolator { private final double v0, v1, v2, v3; - + /** * Constructs an interpolator with given values as vertices of a unit square. * @@ -20,24 +27,26 @@ public class Interpolator { this.v2 = v2; this.v3 = v3; } - + /** * 1D Linear interpolation between 2 points 1 unit apart. * * @param t - Distance from v0. Total distance between v0 and v1 is 1 unit. * @param v0 - Value at v0. * @param v1 - Value at v1. + * * @return double - The interpolated value. */ public static double lerp(double t, double v0, double v1) { return v0 + t * (v1 - v0); } - + /** * 2D Bilinear interpolation between 4 points on a unit square. * * @param s - X value * @param t - Z value + * * @return double - The interpolated value. */ public double bilerp(double s, double t) { diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator3.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/Interpolator3.java similarity index 81% rename from common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator3.java rename to common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/Interpolator3.java index c7a7c0275..804770b42 100644 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/Interpolator3.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/Interpolator3.java @@ -1,4 +1,11 @@ -package com.dfsek.terra.world.generation.math.interpolation; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; /** * Class for bilinear interpolation of values arranged on a unit square. @@ -6,7 +13,7 @@ package com.dfsek.terra.world.generation.math.interpolation; public class Interpolator3 { private final Interpolator bottom; private final Interpolator top; - + /** * Constructs an interpolator with given values as vertices of a unit cube. * * @param _000 The value at (t, u, v) = (0, 0, 0). @@ -25,7 +32,7 @@ public class Interpolator3 { this.top = new Interpolator(_000, _010, _001, _011); this.bottom = new Interpolator(_100, _110, _101, _111); } - + public double trilerp(double x, double y, double z) { return Interpolator.lerp(x, top.bilerp(y, z), bottom.bilerp(y, z)); } diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java new file mode 100644 index 000000000..34c20ad97 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/interpolation/LazilyEvaluatedInterpolator.java @@ -0,0 +1,106 @@ +package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + +import static com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.Interpolator.lerp; + + +public class LazilyEvaluatedInterpolator { + private final Double[][][] samples; + + private final NoiseSampler[][] samplers; + + private final int chunkX; + private final int chunkZ; + + private final int horizontalRes; + private final int verticalRes; + + private final BiomeProvider biomeProvider; + + private final long seed; + private final int min; + + public LazilyEvaluatedInterpolator(BiomeProvider biomeProvider, int cx, int cz, int max, int min, int horizontalRes, int verticalRes, + long seed) { + int hSamples = FastMath.ceilToInt(16.0 / horizontalRes); + int vSamples = FastMath.ceilToInt((double) (max - min) / verticalRes); + samples = new Double[hSamples + 1][vSamples + 1][hSamples + 1]; + samplers = new NoiseSampler[hSamples + 1][hSamples + 1]; + this.chunkX = cx << 4; + this.chunkZ = cz << 4; + this.horizontalRes = horizontalRes; + this.verticalRes = verticalRes; + this.biomeProvider = biomeProvider; + this.seed = seed; + this.min = min; + } + + private double sample(int x, int y, int z, int ox, int oy, int oz) { + Double sample = samples[x][y][z]; + if(sample == null) { + int xi = ox + chunkX; + int zi = oz + chunkZ; + + NoiseSampler sampler = samplers[x][z]; + if(sampler == null) { + sampler = biomeProvider.getBiome(xi, y, zi, seed).getContext().get(BiomeNoiseProperties.class).carving(); + samplers[x][z] = sampler; + } + + sample = sampler.noise(seed, xi, oy, zi); + samples[x][y][z] = sample; + } + return sample; + } + + public double sample(int x, int y, int z) { + int xIndex = x / horizontalRes; + int yIndex = (y - min) / verticalRes; + int zIndex = z / horizontalRes; + + double sample_0_0_0 = sample(xIndex, yIndex, zIndex, x, y, z); + + boolean yRange = y % verticalRes == 0; + if(x % horizontalRes == 0 && yRange && z % horizontalRes == 0) { // we're at the sampling point + return sample_0_0_0; + } + + double sample_0_0_1 = sample(xIndex, yIndex, zIndex + 1, x, y, z + horizontalRes); + + double sample_1_0_0 = sample(xIndex + 1, yIndex, zIndex, x + horizontalRes, y, z); + double sample_1_0_1 = sample(xIndex + 1, yIndex, zIndex + 1, x + horizontalRes, y, z + horizontalRes); + + double xFrac = (double) (x % horizontalRes) / horizontalRes; + double zFrac = (double) (z % horizontalRes) / horizontalRes; + double lerp_bottom_0 = lerp(zFrac, sample_0_0_0, sample_0_0_1); + double lerp_bottom_1 = lerp(zFrac, sample_1_0_0, sample_1_0_1); + + double lerp_bottom = lerp(xFrac, lerp_bottom_0, lerp_bottom_1); + + if(yRange) { // we can do bilerp + return lerp_bottom; + } + + double yFrac = (double) FastMath.floorMod(y, verticalRes) / verticalRes; + + + double sample_0_1_0 = sample(xIndex, yIndex + 1, zIndex, x, y + verticalRes, z); + double sample_0_1_1 = sample(xIndex, yIndex + 1, zIndex + 1, x, y + verticalRes, z + horizontalRes); + + + double sample_1_1_0 = sample(xIndex + 1, yIndex + 1, zIndex, x + horizontalRes, y + verticalRes, z); + double sample_1_1_1 = sample(xIndex + 1, yIndex + 1, zIndex + 1, x + horizontalRes, y + verticalRes, z + horizontalRes); + + double lerp_top_0 = lerp(zFrac, sample_0_1_0, sample_0_1_1); + double lerp_top_1 = lerp(zFrac, sample_1_1_0, sample_1_1_1); + + double lerp_top = lerp(xFrac, lerp_top_0, lerp_top_1); + + return lerp(yFrac, lerp_bottom, lerp_top); + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java new file mode 100644 index 000000000..ea98b0af6 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/Sampler3D.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.generation.math.samplers; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.ChunkInterpolator; +import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.ElevationInterpolator; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class Sampler3D { + private final ChunkInterpolator interpolator; + private final ElevationInterpolator elevationInterpolator; + + public Sampler3D(int x, int z, long seed, int minHeight, int maxHeight, BiomeProvider provider, int elevationSmooth) { + this.interpolator = new ChunkInterpolator(seed, x, z, provider, + minHeight, maxHeight); + this.elevationInterpolator = new ElevationInterpolator(seed, x, z, provider, elevationSmooth); + } + + public double sample(double x, double y, double z) { + return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); + } + + public double sample(int x, int y, int z) { + return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java new file mode 100644 index 000000000..30fcb016a --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/samplers/SamplerProvider.java @@ -0,0 +1,59 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.addons.chunkgenerator.generation.math.samplers; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import net.jafama.FastMath; + +import java.util.concurrent.ExecutionException; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.info.WorldProperties; + + +public class SamplerProvider { + private final Cache cache; + private final int elevationSmooth; + + public SamplerProvider(Platform platform, int elevationSmooth) { + this.elevationSmooth = elevationSmooth; + cache = CacheBuilder.newBuilder().maximumSize(platform.getTerraConfig().getSamplerCache()).build(); + } + + public Sampler3D get(int x, int z, WorldProperties world, BiomeProvider provider) { + int cx = FastMath.floorDiv(x, 16); + int cz = FastMath.floorDiv(z, 16); + return getChunk(cx, cz, world, provider); + } + + public Sampler3D getChunk(int cx, int cz, WorldProperties world, BiomeProvider provider) { + WorldContext context = new WorldContext(cx, cz, world.getSeed(), world.getMinHeight(), world.getMaxHeight()); + try { + return cache.get(context, + () -> new Sampler3D(context.cx, context.cz, context.seed, context.minHeight, context.maxHeight, provider, + elevationSmooth)); + } catch(ExecutionException e) { + throw new RuntimeException(e); + } + } + + private record WorldContext(int cx, int cz, long seed, int minHeight, int maxHeight) { + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/PaletteHolder.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/PaletteHolder.java new file mode 100644 index 000000000..2451d063c --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/PaletteHolder.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.palette; + +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class PaletteHolder { + private final Palette[] palettes; + private final int offset; + + protected PaletteHolder(Palette[] palettes, int offset) { + this.palettes = palettes; + this.offset = offset; + } + + public Palette getPalette(int y) { + int index = y + offset; + return index >= 0 + ? index < palettes.length + ? palettes[index] + : palettes[palettes.length - 1] + : palettes[0]; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolderBuilder.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/PaletteHolderBuilder.java similarity index 54% rename from common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolderBuilder.java rename to common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/PaletteHolderBuilder.java index d2b67335e..693939c75 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolderBuilder.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/PaletteHolderBuilder.java @@ -1,30 +1,37 @@ -package com.dfsek.terra.api.world.palette.holder; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.palette; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.world.palette.Palette; import net.jafama.FastMath; import java.util.Map; import java.util.TreeMap; -public class PaletteHolderBuilder { - private final TreeMap> paletteMap = new TreeMap<>(); +import com.dfsek.terra.api.world.chunk.generation.util.Palette; - public PaletteHolderBuilder add(int y, Palette palette) { + +public class PaletteHolderBuilder { + private final TreeMap paletteMap = new TreeMap<>(); + + public PaletteHolderBuilder add(int y, Palette palette) { paletteMap.put(y, palette); return this; } - - @SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"}) + public PaletteHolder build() { - + int min = FastMath.min(paletteMap.keySet().stream().min(Integer::compareTo).orElse(0), 0); int max = FastMath.max(paletteMap.keySet().stream().max(Integer::compareTo).orElse(255), 255); - - Palette[] palettes = new Palette[paletteMap.lastKey() + 1 - min]; + + Palette[] palettes = new Palette[paletteMap.lastKey() + 1 - min]; for(int y = min; y <= FastMath.max(paletteMap.lastKey(), max); y++) { - Palette d = null; - for(Map.Entry> e : paletteMap.entrySet()) { + Palette d = null; + for(Map.Entry e : paletteMap.entrySet()) { if(e.getKey() >= y) { d = e.getValue(); break; diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/SlantHolder.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/SlantHolder.java new file mode 100644 index 000000000..6ceacee24 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/SlantHolder.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.chunkgenerator.palette; + + +import java.util.Map.Entry; +import java.util.TreeMap; + + +public class SlantHolder { + private final TreeMap layers; + private final double minSlope; + + private SlantHolder(TreeMap layers, double minSlope) { + this.layers = layers; + this.minSlope = minSlope; + } + + public static SlantHolder of(TreeMap layers, double minSlope) { + if(layers.size() == 1) { + Entry firstEntry = layers.firstEntry(); + return new Single(firstEntry.getValue(), minSlope); + } + return new SlantHolder(layers, minSlope); + } + + public boolean isEmpty() { + return layers.isEmpty(); + } + + public PaletteHolder getPalette(double slope) { + return layers.floorEntry(slope).getValue(); + } + + public double getMinSlope() { + return minSlope; + } + + private static final class Single extends SlantHolder { + + private final PaletteHolder layers; + + public Single(PaletteHolder layers, double minSlope) { + super(of(minSlope, layers), minSlope); + this.layers = layers; + } + + private static TreeMap of(double v, PaletteHolder layer) { + TreeMap map = new TreeMap<>(); + map.put(v, layer); + return map; + } + + @Override + public PaletteHolder getPalette(double slope) { + return layers; + } + } +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/resources/terra.addon.yml b/common/addons/chunk-generator-noise-3d/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..76eed7bb9 --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: chunk-generator-noise-3d +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.chunkgenerator.NoiseChunkGenerator3DAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/command-addons/build.gradle.kts b/common/addons/command-addons/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/command-addons/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/command-addons/src/main/java/com/dfsek/terra/addons/commands/addons/AddonsCommandAddon.java b/common/addons/command-addons/src/main/java/com/dfsek/terra/addons/commands/addons/AddonsCommandAddon.java new file mode 100644 index 000000000..289ed09e9 --- /dev/null +++ b/common/addons/command-addons/src/main/java/com/dfsek/terra/addons/commands/addons/AddonsCommandAddon.java @@ -0,0 +1,69 @@ +package com.dfsek.terra.addons.commands.addons; + +import cloud.commandframework.ArgumentDescription; +import cloud.commandframework.CommandManager; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.command.arguments.RegistryArgument; +import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class AddonsCommandAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, CommandRegistrationEvent.class) + .then(event -> { + CommandManager manager = event.getCommandManager(); + + manager.command( + manager.commandBuilder("addons", ArgumentDescription.of("List installed Terra addons")) + .permission("terra.addons") + .handler(context -> { + StringBuilder addons = new StringBuilder("Installed addons:\n"); + platform.getAddons() + .forEach(addon -> addons + .append(" - ") + .append(addon.getID()) + .append('@') + .append(addon.getVersion().getFormatted()) + .append('\n')); + context.getSender().sendMessage(addons.toString()); + }) + ) + .command( + manager.commandBuilder("addons") + .argument(RegistryArgument.of("addon", platform.getAddons())) + .permission("terra.addons.info") + .handler(context -> { + BaseAddon addon = context.get("addon"); + StringBuilder addonInfo = new StringBuilder("Addon ").append(addon.getID()).append('\n'); + + addonInfo.append("Version: ").append(addon.getVersion().getFormatted()).append('\n'); + + addonInfo.append("Dependencies:\n"); + addon.getDependencies().forEach((id, versions) -> addonInfo + .append(" - ") + .append(id) + .append('@') + .append(versions.getFormatted()) + .append('\n')); + context.getSender().sendMessage(addonInfo.toString()); + }) + ); + }); + } +} diff --git a/common/addons/command-addons/src/main/resources/terra.addon.yml b/common/addons/command-addons/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..87f5b5454 --- /dev/null +++ b/common/addons/command-addons/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: command-addons +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.commands.addons.AddonsCommandAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/command-packs/build.gradle.kts b/common/addons/command-packs/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/command-packs/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/command-packs/src/main/java/com/dfsek/terra/addons/commands/packs/PacksCommandAddon.java b/common/addons/command-packs/src/main/java/com/dfsek/terra/addons/commands/packs/PacksCommandAddon.java new file mode 100644 index 000000000..7a5326552 --- /dev/null +++ b/common/addons/command-packs/src/main/java/com/dfsek/terra/addons/commands/packs/PacksCommandAddon.java @@ -0,0 +1,88 @@ +package com.dfsek.terra.addons.commands.packs; + +import cloud.commandframework.ArgumentDescription; +import cloud.commandframework.CommandManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.command.arguments.RegistryArgument; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class PacksCommandAddon implements AddonInitializer { + private static final Logger logger = LoggerFactory.getLogger(PacksCommandAddon.class); + + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, CommandRegistrationEvent.class) + .then(event -> { + CommandManager manager = event.getCommandManager(); + + manager.command( + manager.commandBuilder("packs", ArgumentDescription.of("List installed config packs")) + .permission("terra.packs") + .handler(context -> { + StringBuilder packs = new StringBuilder("Installed packs:\n"); + platform.getConfigRegistry().forEach(pack -> packs.append(" - ") + .append(pack.getID()) + .append('@') + .append(pack.getVersion().getFormatted())); + context.getSender().sendMessage(packs.toString()); + }) + ) + .command( + manager.commandBuilder("packs") + .literal("info", ArgumentDescription.of("Get information about a pack")) + .permission("terra.packs.info") + .argument(RegistryArgument.of("pack", platform.getConfigRegistry())) + .handler(context -> { + ConfigPack pack = context.get("pack"); + StringBuilder packInfo = new StringBuilder("Pack ").append(pack.getID()).append('\n'); + + packInfo.append("Version: ").append(pack.getVersion().getFormatted()).append('\n'); + packInfo.append("Author: ").append(pack.getAuthor()).append('\n'); + + packInfo.append("Addon Dependencies:\n"); + pack.addons().forEach((id, versions) -> packInfo + .append(" - ") + .append(id.getID()) + .append('@') + .append(versions.getFormatted()) + .append('\n')); + context.getSender().sendMessage(packInfo.toString()); + })) + .command( + manager.commandBuilder("packs") + .literal("reload", ArgumentDescription.of("Reload config packs")) + .permission("terra.packs.reload") + .handler(context -> { + context.getSender().sendMessage("Reloading Terra..."); + logger.info("Reloading Terra..."); + if(platform.reload()) { + logger.info("Terra reloaded successfully."); + context.getSender().sendMessage("Terra reloaded successfully."); + } else { + logger.error("Terra failed to reload."); + context.getSender().sendMessage( + "Terra failed to reload. See logs for more information."); + } + })); + }); + } +} diff --git a/common/addons/command-packs/src/main/resources/terra.addon.yml b/common/addons/command-packs/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..4efeb9c99 --- /dev/null +++ b/common/addons/command-packs/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: command-packs +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.commands.packs.PacksCommandAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/command-profiler/build.gradle.kts b/common/addons/command-profiler/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/command-profiler/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/command-profiler/src/main/java/com/dfsek/terra/addons/commands/profiler/ProfilerCommandAddon.java b/common/addons/command-profiler/src/main/java/com/dfsek/terra/addons/commands/profiler/ProfilerCommandAddon.java new file mode 100644 index 000000000..adf966845 --- /dev/null +++ b/common/addons/command-profiler/src/main/java/com/dfsek/terra/addons/commands/profiler/ProfilerCommandAddon.java @@ -0,0 +1,74 @@ +package com.dfsek.terra.addons.commands.profiler; + +import cloud.commandframework.ArgumentDescription; +import cloud.commandframework.CommandManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class ProfilerCommandAddon implements AddonInitializer { + private static final Logger logger = LoggerFactory.getLogger(ProfilerCommandAddon.class); + + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, CommandRegistrationEvent.class) + .then(event -> { + CommandManager manager = event.getCommandManager(); + manager + .command( + manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) + .literal("start", ArgumentDescription.of("Start profiling"), "st") + .permission("terra.profiler.start") + .handler(context -> { + platform.getProfiler().start(); + context.getSender().sendMessage("Profiling started."); + })) + .command( + manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) + .literal("stop", ArgumentDescription.of("Stop profiling"), "s") + .permission("terra.profiler.stop") + .handler(context -> { + platform.getProfiler().stop(); + context.getSender().sendMessage("Profiling stopped."); + })) + .command( + manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) + .literal("query", ArgumentDescription.of("Query profiler results"), "q") + .permission("terra.profiler.query") + .handler(context -> { + StringBuilder data = new StringBuilder("Terra Profiler data: \n"); + platform.getProfiler().getTimings().forEach((id, timings) -> data.append(id) + .append(": ") + .append(timings.toString()) + .append('\n')); + logger.info(data.toString()); + context.getSender().sendMessage("Profiling data dumped to console."); + })) + .command( + manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) + .literal("reset", ArgumentDescription.of("Reset the profiler"), "r") + .permission("terra.profiler.reset") + .handler(context -> { + platform.getProfiler().reset(); + context.getSender().sendMessage("Profiler reset."); + })); + }); + } +} diff --git a/common/addons/command-profiler/src/main/resources/terra.addon.yml b/common/addons/command-profiler/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..3ce8d72ab --- /dev/null +++ b/common/addons/command-profiler/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: command-profiler +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.commands.profiler.ProfilerCommandAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/command-structures/build.gradle.kts b/common/addons/command-structures/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/command-structures/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/command-structures/src/main/java/com/dfsek/terra/addons/commands/structure/StructureCommandAddon.java b/common/addons/command-structures/src/main/java/com/dfsek/terra/addons/commands/structure/StructureCommandAddon.java new file mode 100644 index 000000000..ce98abfce --- /dev/null +++ b/common/addons/command-structures/src/main/java/com/dfsek/terra/addons/commands/structure/StructureCommandAddon.java @@ -0,0 +1,67 @@ +package com.dfsek.terra.addons.commands.structure; + +import cloud.commandframework.ArgumentDescription; +import cloud.commandframework.CommandManager; +import cloud.commandframework.arguments.standard.EnumArgument; +import cloud.commandframework.arguments.standard.LongArgument; +import cloud.commandframework.context.CommandContext; + +import java.util.Random; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.command.arguments.RegistryArgument; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class StructureCommandAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + private static Registry getStructureRegistry(CommandContext sender) { + return sender.getSender().getEntity().orElseThrow().world().getPack().getRegistry(Structure.class); + } + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, CommandRegistrationEvent.class) + .then(event -> { + CommandManager manager = event.getCommandManager(); + + manager.command( + manager.commandBuilder("structures", ArgumentDescription.of("Manage or generate structures")) + .literal("generate") + .argument(RegistryArgument.builder("structure", + StructureCommandAddon::getStructureRegistry, + TypeKey.of(Structure.class))) + .argument(LongArgument.optional("seed", 0)) + .argument(EnumArgument.optional(Rotation.class, "rotation", Rotation.NONE)) + .handler(context -> { + Structure structure = context.get("structure"); + Entity sender = context.getSender().getEntity().orElseThrow(); + structure.generate( + sender.position().toInt(), + sender.world(), + ((Long) context.get("seed") == 0) ? new Random() : new Random(context.get("seed")), + context.get("rotation") + ); + }) + .permission("terra.structures.generate") + ); + }); + } +} diff --git a/common/addons/command-structures/src/main/resources/terra.addon.yml b/common/addons/command-structures/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..c41fc088e --- /dev/null +++ b/common/addons/command-structures/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: command-structures +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.commands.structure.StructureCommandAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/config-biome/LICENSE b/common/addons/config-biome/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/config-biome/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/config-biome/README.md b/common/addons/config-biome/README.md new file mode 100644 index 000000000..4070828ac --- /dev/null +++ b/common/addons/config-biome/README.md @@ -0,0 +1,3 @@ +# config-biome + +Registers the default configuration for Terra Biomes, `BIOME`. \ No newline at end of file diff --git a/common/addons/config-biome/build.gradle.kts b/common/addons/config-biome/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/config-biome/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeAddon.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeAddon.java new file mode 100644 index 000000000..e850400e8 --- /dev/null +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeAddon.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome; + +import com.dfsek.terra.addons.biome.holder.PaletteHolder; +import com.dfsek.terra.addons.biome.holder.PaletteHolderLoader; +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class BiomeAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + event.getPack().registerConfigType(new BiomeConfigType(event.getPack()), addon.key("BIOME"), 1000); + event.getPack().applyLoader(PaletteHolder.class, new PaletteHolderLoader()); + }) + .failThrough(); + } +} diff --git a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeConfigType.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeConfigType.java new file mode 100644 index 000000000..ccf3c09a6 --- /dev/null +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeConfigType.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.Biome; + + +public class BiomeConfigType implements ConfigType { + public static final TypeKey BIOME_TYPE_TOKEN = new TypeKey<>() { + }; + private final BiomeFactory factory; + + public BiomeConfigType(ConfigPack pack) { + this.factory = new BiomeFactory(pack); + } + + @Override + public BiomeTemplate getTemplate(ConfigPack pack, Platform platform) { + return new BiomeTemplate(pack, platform); + } + + @Override + public ConfigFactory getFactory() { + return factory; + } + + @Override + public TypeKey getTypeKey() { + return BIOME_TYPE_TOKEN; + } +} diff --git a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeFactory.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeFactory.java new file mode 100644 index 000000000..0f84c609c --- /dev/null +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeFactory.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.Biome; + + +public class BiomeFactory implements ConfigFactory { + private final ConfigPack pack; + + public BiomeFactory(ConfigPack pack) { + this.pack = pack; + } + + @Override + public Biome build(BiomeTemplate template, Platform platform) { + return new UserDefinedBiome(template.getVanilla(), template); + } +} diff --git a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeTemplate.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeTemplate.java new file mode 100644 index 000000000..656a3949a --- /dev/null +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/BiomeTemplate.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Final; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.AbstractableTemplate; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.world.biome.PlatformBiome; + + +@SuppressWarnings({ "FieldMayBeFinal", "unused" }) +public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTemplate { + private final ConfigPack pack; + + @Value("id") + @Final + private @Meta String id; + + @Value("extends") + @Final + @Default + private List extended = Collections.emptyList(); + + @Value("vanilla") + private @Meta PlatformBiome vanilla; + + @Value("color") + @Final + @Default + private @Meta int color = 0; + @Value("tags") + @Default + private @Meta Set<@Meta String> tags = new HashSet<>(); + + public BiomeTemplate(ConfigPack pack, Platform platform) { + this.pack = pack; + } + + @Override + public boolean validate() { + color |= 0xff000000; // Alpha adjustment + return true; + } + + public List getExtended() { + return extended; + } + + public Set getTags() { + return tags; + } + + public int getColor() { + return color; + } + + public ConfigPack getPack() { + return pack; + } + + public String getID() { + return id; + } + + public PlatformBiome getVanilla() { + return vanilla; + } +} diff --git a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/PaletteSettingsImpl.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/PaletteSettingsImpl.java new file mode 100644 index 000000000..82cd6e902 --- /dev/null +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/PaletteSettingsImpl.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome; + +import com.dfsek.terra.addons.biome.holder.PaletteHolder; +import com.dfsek.terra.api.world.biome.PaletteSettings; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class PaletteSettingsImpl implements PaletteSettings { + private final PaletteHolder palette; + + public PaletteSettingsImpl(PaletteHolder palette) { + this.palette = palette; + } + + @Override + public Palette getPalette(int y) { + return palette.getPalette(y); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/UserDefinedBiome.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/UserDefinedBiome.java similarity index 56% rename from common/src/main/java/com/dfsek/terra/api/world/biome/UserDefinedBiome.java rename to common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/UserDefinedBiome.java index b6e5d9570..cf0d09ac4 100644 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/UserDefinedBiome.java +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/UserDefinedBiome.java @@ -1,71 +1,77 @@ -package com.dfsek.terra.api.world.biome; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.world.generation.WorldGenerator; +package com.dfsek.terra.addons.biome; import java.util.Set; +import com.dfsek.terra.api.properties.Context; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.biome.PlatformBiome; + + /** * Class representing a config-defined biome */ -public class UserDefinedBiome implements TerraBiome { - private final WorldGenerator gen; - private final ProbabilityCollection vanilla; +public class UserDefinedBiome implements Biome { + private final PlatformBiome vanilla; private final String id; private final BiomeTemplate config; private final int color; private final Set tags; - - - public UserDefinedBiome(ProbabilityCollection vanilla, WorldGenerator gen, BiomeTemplate config) { + + private final Context context = new Context(); + + public UserDefinedBiome(PlatformBiome vanilla, BiomeTemplate config) { this.vanilla = vanilla; - this.gen = gen; this.id = config.getID(); this.config = config; this.color = config.getColor(); this.tags = config.getTags(); tags.add("BIOME:" + id); + tags.add("ALL"); } - + + @Override + public String toString() { + return "{BIOME:" + getID() + "}"; + } + /** * Gets the Vanilla biomes to represent the custom biome. * * @return Collection of biomes to represent the custom biome. */ @Override - public ProbabilityCollection getVanillaBiomes() { + public PlatformBiome getPlatformBiome() { return vanilla; } - - @Override - public String getID() { - return id; - } - - public BiomeTemplate getConfig() { - return config; - } - - @Override - public Generator getGenerator(World w) { - return gen; - } - + @Override public int getColor() { return color; } - + @Override public Set getTags() { return tags; } - + @Override - public String toString() { - return "{BIOME:" + getID() + "}"; + public String getID() { + return id; + } + + public BiomeTemplate getConfig() { + return config; + } + + @Override + public Context getContext() { + return context; } } diff --git a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolder.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolder.java new file mode 100644 index 000000000..416263f8d --- /dev/null +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolder.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.holder; + +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class PaletteHolder { + private final Palette[] palettes; + private final int offset; + + protected PaletteHolder(Palette[] palettes, int offset) { + this.palettes = palettes; + this.offset = offset; + } + + public Palette getPalette(int y) { + int index = y + offset; + return index >= 0 + ? index < palettes.length + ? palettes[index] + : palettes[palettes.length - 1] + : palettes[0]; + } +} diff --git a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolderBuilder.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolderBuilder.java new file mode 100644 index 000000000..c2a082038 --- /dev/null +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolderBuilder.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.holder; + +import java.util.Map; +import java.util.TreeMap; + +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class PaletteHolderBuilder { + private final TreeMap paletteMap = new TreeMap<>(); + + public PaletteHolderBuilder add(int y, Palette palette) { + paletteMap.put(y, palette); + return this; + } + + public PaletteHolder build() { + + int min = Math.min(paletteMap.keySet().stream().min(Integer::compareTo).orElse(0), 0); + int max = Math.max(paletteMap.keySet().stream().max(Integer::compareTo).orElse(255), 255); + + Palette[] palettes = new Palette[paletteMap.lastKey() + 1 - min]; + for(int y = min; y <= Math.max(paletteMap.lastKey(), max); y++) { + Palette d = null; + for(Map.Entry e : paletteMap.entrySet()) { + if(e.getKey() >= y) { + d = e.getValue(); + break; + } + } + if(d == null) throw new IllegalArgumentException("No palette for Y=" + y); + palettes[y - min] = d; + } + return new PaletteHolder(palettes, -min); + } +} diff --git a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolderLoader.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolderLoader.java new file mode 100644 index 000000000..005f0152b --- /dev/null +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolderLoader.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.biome.holder; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.List; +import java.util.Map; + +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class PaletteHolderLoader implements TypeLoader { + @SuppressWarnings("unchecked") + @Override + public PaletteHolder load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader, DepthTracker depthTracker) + throws LoadException { + List> palette = (List>) o; + PaletteHolderBuilder builder = new PaletteHolderBuilder(); + for(Map layer : palette) { + for(Map.Entry entry : layer.entrySet()) { + builder.add(entry.getValue(), configLoader.loadType(Palette.class, entry.getKey(), depthTracker)); + } + } + return builder.build(); + } +} diff --git a/common/addons/config-biome/src/main/resources/terra.addon.yml b/common/addons/config-biome/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..f669208b1 --- /dev/null +++ b/common/addons/config-biome/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: config-biome +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.biome.BiomeAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/config-distributors/LICENSE b/common/addons/config-distributors/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/config-distributors/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/config-distributors/build.gradle.kts b/common/addons/config-distributors/build.gradle.kts new file mode 100644 index 000000000..e38fb40ee --- /dev/null +++ b/common/addons/config-distributors/build.gradle.kts @@ -0,0 +1,12 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("net.jafama", "com.dfsek.terra.addons.feature.distributor.lib.jafama") +} \ No newline at end of file diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/DistributorAddon.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/DistributorAddon.java new file mode 100644 index 000000000..2227a499d --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/DistributorAddon.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.feature.distributor.config.AndDistributorTemplate; +import com.dfsek.terra.addons.feature.distributor.config.NoDistributorTemplate; +import com.dfsek.terra.addons.feature.distributor.config.OrDistributorTemplate; +import com.dfsek.terra.addons.feature.distributor.config.PaddedGridDistributorTemplate; +import com.dfsek.terra.addons.feature.distributor.config.PointSetDistributorTemplate; +import com.dfsek.terra.addons.feature.distributor.config.SamplerDistributorTemplate; +import com.dfsek.terra.addons.feature.distributor.config.XorDistributorTemplate; +import com.dfsek.terra.addons.feature.distributor.config.YesDistributorTemplate; +import com.dfsek.terra.addons.feature.distributor.util.Point; +import com.dfsek.terra.addons.feature.distributor.util.PointTemplate; +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.structure.feature.Distributor; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class DistributorAddon implements AddonInitializer { + public static final TypeKey>> DISTRIBUTOR_TOKEN = new TypeKey<>() { + }; + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + CheckedRegistry>> distributorRegistry = event + .getPack() + .getOrCreateRegistry(DISTRIBUTOR_TOKEN); + + distributorRegistry.register(addon.key("SAMPLER"), SamplerDistributorTemplate::new); + distributorRegistry.register(addon.key("POINTS"), PointSetDistributorTemplate::new); + distributorRegistry.register(addon.key("PADDED_GRID"), PaddedGridDistributorTemplate::new); + distributorRegistry.register(addon.key("AND"), AndDistributorTemplate::new); + distributorRegistry.register(addon.key("OR"), OrDistributorTemplate::new); + distributorRegistry.register(addon.key("XOR"), XorDistributorTemplate::new); + distributorRegistry.register(addon.key("YES"), YesDistributorTemplate::new); + distributorRegistry.register(addon.key("NO"), NoDistributorTemplate::new); + + event.getPack() + .applyLoader(Point.class, PointTemplate::new); + }) + .failThrough(); + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/AndDistributorTemplate.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/AndDistributorTemplate.java new file mode 100644 index 000000000..960feb0dd --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/AndDistributorTemplate.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.config; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; + +import java.util.List; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Distributor; + + +public class AndDistributorTemplate implements ObjectTemplate, ValidatedConfigTemplate { + @Value("distributors") + private @Meta List<@Meta Distributor> distributors; + + + @Override + public Distributor get() { + Distributor current = distributors.remove(0); + while(!distributors.isEmpty()) { + current = current.and(distributors.remove(0)); + } + return current; + } + + @Override + public boolean validate() throws ValidationException { + if(distributors.isEmpty()) throw new ValidationException("AND Distributor must specify at least 1 distributor."); + return true; + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/NoDistributorTemplate.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/NoDistributorTemplate.java new file mode 100644 index 000000000..bf2ba424f --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/NoDistributorTemplate.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.config; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.api.structure.feature.Distributor; + + +public class NoDistributorTemplate implements ObjectTemplate { + @Override + public Distributor get() { + return Distributor.no(); + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/OrDistributorTemplate.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/OrDistributorTemplate.java new file mode 100644 index 000000000..e7a754085 --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/OrDistributorTemplate.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.config; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; + +import java.util.List; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Distributor; + + +public class OrDistributorTemplate implements ObjectTemplate, ValidatedConfigTemplate { + @Value("distributors") + private @Meta List<@Meta Distributor> distributors; + + + @Override + public Distributor get() { + Distributor current = distributors.remove(0); + while(!distributors.isEmpty()) { + current = current.or(distributors.remove(0)); + } + return current; + } + + @Override + public boolean validate() throws ValidationException { + if(distributors.isEmpty()) throw new ValidationException("OR Distributor must specify at least 1 distributor."); + return true; + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/PaddedGridDistributorTemplate.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/PaddedGridDistributorTemplate.java new file mode 100644 index 000000000..ff77d18be --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/PaddedGridDistributorTemplate.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.addons.feature.distributor.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.distributor.distributors.PaddedGridDistributor; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Distributor; + + +public class PaddedGridDistributorTemplate implements ObjectTemplate { + @Value("width") + private @Meta int width; + + @Value("padding") + private @Meta int padding; + + @Value("salt") + private @Meta int salt; + + @Override + public Distributor get() { + return new PaddedGridDistributor(width, padding, salt); + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/PointSetDistributorTemplate.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/PointSetDistributorTemplate.java new file mode 100644 index 000000000..a36f09dac --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/PointSetDistributorTemplate.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.Set; + +import com.dfsek.terra.addons.feature.distributor.distributors.PointSetDistributor; +import com.dfsek.terra.addons.feature.distributor.util.Point; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Distributor; + + +public class PointSetDistributorTemplate implements ObjectTemplate { + @Value("points") + private @Meta Set<@Meta Point> points; + + @Override + public Distributor get() { + return new PointSetDistributor(points); + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/SamplerDistributorTemplate.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/SamplerDistributorTemplate.java new file mode 100644 index 000000000..53bc81751 --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/SamplerDistributorTemplate.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.config; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.distributor.distributors.SamplerDistributor; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.structure.feature.Distributor; + + +@SuppressWarnings("FieldMayBeFinal") +public class SamplerDistributorTemplate implements ObjectTemplate { + @Value("threshold") + @Default + private @Meta double threshold = 0; + @Value("sampler") + private @Meta NoiseSampler noise; + + @Override + public Distributor get() { + return new SamplerDistributor(noise, threshold); + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/XorDistributorTemplate.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/XorDistributorTemplate.java new file mode 100644 index 000000000..663d1ce7e --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/XorDistributorTemplate.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.config; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; + +import java.util.List; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Distributor; + + +public class XorDistributorTemplate implements ObjectTemplate, ValidatedConfigTemplate { + @Value("distributors") + private @Meta List<@Meta Distributor> distributors; + + + @Override + public Distributor get() { + Distributor current = distributors.remove(0); + while(!distributors.isEmpty()) { + current = current.xor(distributors.remove(0)); + } + return current; + } + + @Override + public boolean validate() throws ValidationException { + if(distributors.isEmpty()) throw new ValidationException("XOR Distributor must specify at least 1 distributor."); + return true; + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/YesDistributorTemplate.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/YesDistributorTemplate.java new file mode 100644 index 000000000..16cf8b23e --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/config/YesDistributorTemplate.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.config; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.api.structure.feature.Distributor; + + +public class YesDistributorTemplate implements ObjectTemplate { + @Override + public Distributor get() { + return Distributor.yes(); + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/PaddedGridDistributor.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/PaddedGridDistributor.java new file mode 100644 index 000000000..bb380e034 --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/PaddedGridDistributor.java @@ -0,0 +1,45 @@ +package com.dfsek.terra.addons.feature.distributor.distributors; + +import net.jafama.FastMath; + +import java.util.Random; + +import com.dfsek.terra.api.structure.feature.Distributor; +import com.dfsek.terra.api.util.MathUtil; + + +public class PaddedGridDistributor implements Distributor { + private final int width; + + private final int cellWidth; + + private final int salt; + + public PaddedGridDistributor(int width, int padding, int salt) { + this.width = width; + this.salt = salt; + this.cellWidth = width + padding; + } + + private static long murmur64(long h) { + h ^= h >>> 33; + h *= 0xff51afd7ed558ccdL; + h ^= h >>> 33; + h *= 0xc4ceb9fe1a85ec53L; + h ^= h >>> 33; + return h; + } + + @Override + public boolean matches(int x, int z, long seed) { + int cellX = FastMath.floorDiv(x, cellWidth); + int cellZ = FastMath.floorDiv(z, cellWidth); + + Random random = new Random((murmur64(MathUtil.squash(cellX, cellZ)) ^ seed) + salt); + + int pointX = random.nextInt(width) + cellX * cellWidth; + int pointZ = random.nextInt(width) + cellZ * cellWidth; + + return x == pointX && z == pointZ; + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/PointSetDistributor.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/PointSetDistributor.java new file mode 100644 index 000000000..19af51ec2 --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/PointSetDistributor.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.distributors; + +import java.util.Set; + +import com.dfsek.terra.addons.feature.distributor.util.Point; +import com.dfsek.terra.api.structure.feature.Distributor; + + +public class PointSetDistributor implements Distributor { + private final Set points; + + public PointSetDistributor(Set points) { + this.points = points; + } + + @Override + public boolean matches(int x, int z, long seed) { + return points.contains(new Point(x, z)); + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/SamplerDistributor.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/SamplerDistributor.java new file mode 100644 index 000000000..ebe0dfdc4 --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/SamplerDistributor.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.distributors; + +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.structure.feature.Distributor; + + +public class SamplerDistributor implements Distributor { + private final NoiseSampler sampler; + + private final double threshold; + + public SamplerDistributor(NoiseSampler sampler, double threshold) { + this.sampler = sampler; + this.threshold = threshold; + } + + @Override + public boolean matches(int x, int z, long seed) { + return sampler.noise(seed, x, z) < threshold; + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/util/Point.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/util/Point.java new file mode 100644 index 000000000..ec06b2071 --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/util/Point.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.util; + +public class Point { + private final int x; + private final int z; + + private final int hash; + + public Point(int x, int z) { + this.x = x; + this.z = z; + this.hash = 31 * x + z; + } + + public int getX() { + return x; + } + + public int getZ() { + return z; + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Point that)) return false; + return this.x == that.x && this.z == that.z; + } +} diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/util/PointTemplate.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/util/PointTemplate.java new file mode 100644 index 000000000..2f74a4048 --- /dev/null +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/util/PointTemplate.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.distributor.util; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.api.config.meta.Meta; + + +public class PointTemplate implements ObjectTemplate { + @Value("x") + private @Meta int x; + + @Value("z") + private @Meta int z; + + @Override + public Point get() { + return new Point(x, z); + } +} diff --git a/common/addons/config-distributors/src/main/resources/terra.addon.yml b/common/addons/config-distributors/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..6e4c98a4a --- /dev/null +++ b/common/addons/config-distributors/src/main/resources/terra.addon.yml @@ -0,0 +1,15 @@ +schema-version: 1 +contributors: + - Terra contributors +id: config-distributors +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.feature.distributor.DistributorAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License +depends: + config-feature: "1.+" + generation-stage-feature: "1.+" \ No newline at end of file diff --git a/common/addons/config-feature/LICENSE b/common/addons/config-feature/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/config-feature/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/config-feature/build.gradle.kts b/common/addons/config-feature/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/config-feature/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/ConfiguredFeature.java b/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/ConfiguredFeature.java new file mode 100644 index 000000000..5ce901736 --- /dev/null +++ b/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/ConfiguredFeature.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature; + +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.structure.feature.Distributor; +import com.dfsek.terra.api.structure.feature.Feature; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; +import com.dfsek.terra.api.world.WritableWorld; + + +public class ConfiguredFeature implements Feature { + private final ProbabilityCollection structures; + + private final NoiseSampler structureSelector; + private final Distributor distributor; + private final Locator locator; + + private final String id; + + public ConfiguredFeature(ProbabilityCollection structures, NoiseSampler structureSelector, Distributor distributor, + Locator locator, String id) { + this.structures = structures; + this.structureSelector = structureSelector; + this.distributor = distributor; + this.locator = locator; + this.id = id; + } + + @Override + public Structure getStructure(WritableWorld world, int x, int y, int z) { + return structures.get(structureSelector, x, y, z, world.getSeed()); + } + + @Override + public Distributor getDistributor() { + return distributor; + } + + @Override + public Locator getLocator() { + return locator; + } + + @Override + public String getID() { + return id; + } +} diff --git a/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureAddon.java b/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureAddon.java new file mode 100644 index 000000000..07d8ba9d9 --- /dev/null +++ b/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureAddon.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class FeatureAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> event.getPack().registerConfigType(new FeatureConfigType(), addon.key("FEATURE"), 500)) + .failThrough(); + } +} diff --git a/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureConfigType.java b/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureConfigType.java new file mode 100644 index 000000000..8c241d97d --- /dev/null +++ b/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureConfigType.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.structure.feature.Feature; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class FeatureConfigType implements ConfigType { + public static final TypeKey FEATURE_TYPE_KEY = new TypeKey<>() { + }; + + private final FeatureFactory factory = new FeatureFactory(); + + @Override + public FeatureTemplate getTemplate(ConfigPack pack, Platform platform) { + return new FeatureTemplate(); + } + + @Override + public ConfigFactory getFactory() { + return factory; + } + + @Override + public TypeKey getTypeKey() { + return FEATURE_TYPE_KEY; + } +} diff --git a/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureFactory.java b/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureFactory.java new file mode 100644 index 000000000..81c03ade5 --- /dev/null +++ b/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureFactory.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature; + +import com.dfsek.tectonic.api.exception.LoadException; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.structure.feature.Feature; + + +public class FeatureFactory implements ConfigFactory { + @Override + public Feature build(FeatureTemplate config, Platform platform) throws LoadException { + return new ConfiguredFeature(config.getStructures(), config.getStructureNoise(), config.getDistributor(), config.getLocator(), + config.getID()); + } +} diff --git a/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureTemplate.java b/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureTemplate.java new file mode 100644 index 000000000..06ba2dd6f --- /dev/null +++ b/common/addons/config-feature/src/main/java/com/dfsek/terra/addons/feature/FeatureTemplate.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature; + +import com.dfsek.tectonic.api.config.template.annotations.Final; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.api.config.AbstractableTemplate; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.structure.feature.Distributor; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class FeatureTemplate implements AbstractableTemplate { + @Value("id") + @Final + private String id; + + @Value("distributor") + private @Meta Distributor distributor; + + @Value("locator") + private @Meta Locator locator; + + @Value("structures.distribution") + private @Meta NoiseSampler structureNoise; + + @Value("structures.structures") + private @Meta ProbabilityCollection structures; + + @Override + public String getID() { + return id; + } + + public Distributor getDistributor() { + return distributor; + } + + public Locator getLocator() { + return locator; + } + + public NoiseSampler getStructureNoise() { + return structureNoise; + } + + public ProbabilityCollection getStructures() { + return structures; + } +} diff --git a/common/addons/config-feature/src/main/resources/terra.addon.yml b/common/addons/config-feature/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..cb17b4b76 --- /dev/null +++ b/common/addons/config-feature/src/main/resources/terra.addon.yml @@ -0,0 +1,14 @@ +schema-version: 1 +contributors: + - Terra contributors +id: config-feature +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.feature.FeatureAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License +depends: + generation-stage-feature: "1.+" \ No newline at end of file diff --git a/common/addons/config-flora/LICENSE b/common/addons/config-flora/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/config-flora/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/config-flora/README.md b/common/addons/config-flora/README.md new file mode 100644 index 000000000..6ce6deaa8 --- /dev/null +++ b/common/addons/config-flora/README.md @@ -0,0 +1,3 @@ +# config-flora + +Registers the default configuration for Terra Flora, `FLORA`. \ No newline at end of file diff --git a/common/addons/config-flora/build.gradle.kts b/common/addons/config-flora/build.gradle.kts new file mode 100644 index 000000000..9e1e78d1f --- /dev/null +++ b/common/addons/config-flora/build.gradle.kts @@ -0,0 +1,11 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("net.jafama", "com.dfsek.terra.addons.flora.lib.jafama") +} diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraAddon.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraAddon.java new file mode 100644 index 000000000..68b43b364 --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraAddon.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.flora; + +import com.dfsek.terra.addons.flora.config.BlockLayerTemplate; +import com.dfsek.terra.addons.flora.flora.gen.BlockLayer; +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class FloraAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + event.getPack().registerConfigType(new FloraConfigType(), addon.key("FLORA"), 2); + event.getPack().applyLoader(BlockLayer.class, BlockLayerTemplate::new); + }) + .failThrough(); + } +} diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraConfigType.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraConfigType.java new file mode 100644 index 000000000..1a2b3085a --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraConfigType.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.flora; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class FloraConfigType implements ConfigType { + public static final TypeKey FLORA_TYPE_TOKEN = new TypeKey<>() { + }; + private final FloraFactory factory = new FloraFactory(); + + @Override + public FloraTemplate getTemplate(ConfigPack pack, Platform platform) { + return new FloraTemplate(); + } + + @Override + public ConfigFactory getFactory() { + return factory; + } + + @Override + public TypeKey getTypeKey() { + return FLORA_TYPE_TOKEN; + } +} diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraFactory.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraFactory.java new file mode 100644 index 000000000..96bd55087 --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraFactory.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.flora; + +import com.dfsek.terra.addons.flora.flora.gen.TerraFlora; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.structure.Structure; + + +public class FloraFactory implements ConfigFactory { + @Override + public TerraFlora build(FloraTemplate config, Platform platform) { + return new TerraFlora(config.getLayers(), config.doPhysics(), config.isCeiling(), + config.getRotatable(), + config.getNoiseDistribution(), config.getID()); + } +} diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraTemplate.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraTemplate.java new file mode 100644 index 000000000..2fe1b02d1 --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/FloraTemplate.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.flora; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Final; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.List; + +import com.dfsek.terra.addons.flora.flora.gen.BlockLayer; +import com.dfsek.terra.api.config.AbstractableTemplate; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.MaterialSet; + + +@SuppressWarnings({ "FieldMayBeFinal", "unused" }) +public class FloraTemplate implements AbstractableTemplate { + @Value("id") + @Final + private String id; + @Value("rotatable") + @Default + private @Meta MaterialSet rotatable = MaterialSet.empty(); + + @Value("physics") + @Default + private @Meta boolean doPhysics = false; + + @Value("ceiling") + @Default + private @Meta boolean ceiling = false; + + @Value("layers") + private @Meta List<@Meta BlockLayer> layers; + + @Value("layer-distribution") + private @Meta NoiseSampler noiseDistribution; + + public boolean doPhysics() { + return doPhysics; + } + + public NoiseSampler getNoiseDistribution() { + return noiseDistribution; + } + + public List getLayers() { + return layers; + } + + public String getID() { + return id; + } + + public boolean isCeiling() { + return ceiling; + } + + public MaterialSet getRotatable() { + return rotatable; + } +} diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/config/BlockLayerTemplate.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/config/BlockLayerTemplate.java new file mode 100644 index 000000000..5c5cde303 --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/config/BlockLayerTemplate.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.flora.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.flora.flora.gen.BlockLayer; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class BlockLayerTemplate implements ObjectTemplate { + @Value("layers") + private @Meta int layers; + + @Value("materials") + private @Meta ProbabilityCollection data; + + @Override + public BlockLayer get() { + return new BlockLayer(layers, data); + } +} diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/BlockLayer.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/BlockLayer.java new file mode 100644 index 000000000..d2694adcc --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/BlockLayer.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.flora.flora.gen; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class BlockLayer { + private final int layers; + private final ProbabilityCollection blocks; + + public BlockLayer(int layers, ProbabilityCollection blocks) { + this.layers = layers; + this.blocks = blocks; + } + + public int getLayers() { + return layers; + } + + public ProbabilityCollection getBlocks() { + return blocks; + } +} diff --git a/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/TerraFlora.java b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/TerraFlora.java new file mode 100644 index 000000000..31fbf1558 --- /dev/null +++ b/common/addons/config-flora/src/main/java/com/dfsek/terra/addons/flora/flora/gen/TerraFlora.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.flora.flora.gen; + +import net.jafama.FastMath; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +import java.util.Random; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.block.state.properties.enums.Direction; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.collection.MaterialSet; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.WritableWorld; + + +public class TerraFlora implements Structure { + private final List> layers; + private final boolean physics; + private final boolean ceiling; + + private final MaterialSet testRotation; + + private final NoiseSampler distribution; + + private final String id; + + public TerraFlora(List layers, boolean physics, boolean ceiling, + MaterialSet testRotation, + NoiseSampler distribution, String id) { + this.physics = physics; + this.testRotation = testRotation; + this.ceiling = ceiling; + this.distribution = distribution; + this.id = id; + + this.layers = new ArrayList<>(); + layers.forEach(layer -> { + for(int i = 0; i < layer.getLayers(); i++) { + this.layers.add(layer.getBlocks()); + } + }); + } + + private void test(EnumSet faces, Direction f, Vector3Int b, WritableWorld world) { + if(testRotation.contains( + world.getBlockState(b.getX() + f.getModX(), b.getY() + f.getModY(), b.getZ() + f.getModZ()).getBlockType())) + faces.add(f); + } + + private ProbabilityCollection getStateCollection(int layer) { + return layers.get(FastMath.max(FastMath.min(layer, layers.size() - 1), 0)); + } + + private EnumSet getFaces(Vector3Int b, WritableWorld world) { + EnumSet faces = EnumSet.noneOf(Direction.class); + test(faces, Direction.NORTH, b, world); + test(faces, Direction.SOUTH, b, world); + test(faces, Direction.EAST, b, world); + test(faces, Direction.WEST, b, world); + return faces; + } + + @Override + public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { + boolean doRotation = testRotation.size() > 0; + int size = layers.size(); + int c = ceiling ? -1 : 1; + + EnumSet faces = doRotation ? getFaces(location.mutable().add(0, c, 0).immutable(), world) : EnumSet.noneOf( + Direction.class); + if(doRotation && faces.size() == 0) return false; // Don't plant if no faces are valid. + + for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor + int lvl = (FastMath.abs(i)); + BlockState data = getStateCollection((ceiling ? lvl : size - lvl - 1)).get(distribution, location.getX(), location.getY(), + location.getZ(), world.getSeed()); + if(doRotation) { + Direction oneFace = new ArrayList<>(faces).get( + new Random(location.getX() ^ location.getZ()).nextInt(faces.size())); // Get random face. + } + world.setBlockState(location.mutable().add(0, i + c, 0).immutable(), data, physics); + } + return true; + } +} diff --git a/common/addons/config-flora/src/main/resources/terra.addon.yml b/common/addons/config-flora/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..b464bed94 --- /dev/null +++ b/common/addons/config-flora/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: config-flora +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.flora.FloraAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/config-locators/LICENSE b/common/addons/config-locators/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/config-locators/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/config-locators/build.gradle.kts b/common/addons/config-locators/build.gradle.kts new file mode 100644 index 000000000..99485164c --- /dev/null +++ b/common/addons/config-locators/build.gradle.kts @@ -0,0 +1,12 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("net.jafama", "com.dfsek.terra.addons.feature.locator.lib.jafama") +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/LocatorAddon.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/LocatorAddon.java new file mode 100644 index 000000000..a0166076e --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/LocatorAddon.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.feature.locator.config.AdjacentPatternLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.AndLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.GaussianRandomLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.OrLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.PatternLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.RandomLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.Sampler3DLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.SamplerLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.SurfaceLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.TopLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.XorLocatorTemplate; +import com.dfsek.terra.addons.feature.locator.config.pattern.AirMatchPatternTemplate; +import com.dfsek.terra.addons.feature.locator.config.pattern.AndPatternTemplate; +import com.dfsek.terra.addons.feature.locator.config.pattern.BlockSetMatchPatternTemplate; +import com.dfsek.terra.addons.feature.locator.config.pattern.NotPatternTemplate; +import com.dfsek.terra.addons.feature.locator.config.pattern.OrPatternTemplate; +import com.dfsek.terra.addons.feature.locator.config.pattern.SingleBlockMatchPatternTemplate; +import com.dfsek.terra.addons.feature.locator.config.pattern.SolidMatchPatternTemplate; +import com.dfsek.terra.addons.feature.locator.config.pattern.XorPatternTemplate; +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class LocatorAddon implements AddonInitializer { + + public static final TypeKey>> LOCATOR_TOKEN = new TypeKey<>() { + }; + public static final TypeKey>> PATTERN_TOKEN = new TypeKey<>() { + }; + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + CheckedRegistry>> locatorRegistry = event.getPack().getOrCreateRegistry(LOCATOR_TOKEN); + locatorRegistry.register(addon.key("SURFACE"), SurfaceLocatorTemplate::new); + locatorRegistry.register(addon.key("TOP"), TopLocatorTemplate::new); + + locatorRegistry.register(addon.key("RANDOM"), RandomLocatorTemplate::new); + locatorRegistry.register(addon.key("GAUSSIAN_RANDOM"), GaussianRandomLocatorTemplate::new); + + locatorRegistry.register(addon.key("PATTERN"), PatternLocatorTemplate::new); + locatorRegistry.register(addon.key("ADJACENT_PATTERN"), AdjacentPatternLocatorTemplate::new); + + locatorRegistry.register(addon.key("SAMPLER"), SamplerLocatorTemplate::new); + locatorRegistry.register(addon.key("SAMPLER_3D"), Sampler3DLocatorTemplate::new); + + locatorRegistry.register(addon.key("AND"), AndLocatorTemplate::new); + locatorRegistry.register(addon.key("OR"), OrLocatorTemplate::new); + locatorRegistry.register(addon.key("XOR"), XorLocatorTemplate::new); + }) + .then(event -> { + CheckedRegistry>> patternRegistry = event.getPack().getOrCreateRegistry(PATTERN_TOKEN); + patternRegistry.register(addon.key("MATCH_AIR"), AirMatchPatternTemplate::new); + patternRegistry.register(addon.key("MATCH_SOLID"), SolidMatchPatternTemplate::new); + patternRegistry.register(addon.key("MATCH"), SingleBlockMatchPatternTemplate::new); + patternRegistry.register(addon.key("MATCH_SET"), BlockSetMatchPatternTemplate::new); + + patternRegistry.register(addon.key("AND"), AndPatternTemplate::new); + patternRegistry.register(addon.key("OR"), OrPatternTemplate::new); + patternRegistry.register(addon.key("XOR"), XorPatternTemplate::new); + patternRegistry.register(addon.key("NOT"), NotPatternTemplate::new); + }) + .failThrough(); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/AdjacentPatternLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/AdjacentPatternLocatorTemplate.java new file mode 100644 index 000000000..3db17212b --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/AdjacentPatternLocatorTemplate.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.locators.AdjacentPatternLocator; +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; + + +@SuppressWarnings({ "FieldCanBeLocal", "FieldMayBeFinal" }) +public class AdjacentPatternLocatorTemplate implements ObjectTemplate { + @Value("range") + private @Meta Range range; + + @Value("pattern") + private @Meta Pattern pattern; + + @Value("match-all") + @Default + private @Meta boolean matchAll = false; + + @Override + public Locator get() { + return new AdjacentPatternLocator(pattern, range, matchAll); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/AndLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/AndLocatorTemplate.java new file mode 100644 index 000000000..4463c6973 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/AndLocatorTemplate.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; + +import java.util.List; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Locator; + + +public class AndLocatorTemplate implements ObjectTemplate, ValidatedConfigTemplate { + @Value("locators") + private @Meta List<@Meta Locator> locators; + + @Override + public Locator get() { + Locator current = locators.remove(0); + while(!locators.isEmpty()) { + current = current.and(locators.remove(0)); + } + return current; + } + + @Override + public boolean validate() throws ValidationException { + if(locators.isEmpty()) throw new ValidationException("AND Pattern must specify at least 1 pattern."); + return true; + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/GaussianRandomLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/GaussianRandomLocatorTemplate.java new file mode 100644 index 000000000..80af89793 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/GaussianRandomLocatorTemplate.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.locators.GaussianRandomLocator; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; + + +@SuppressWarnings("FieldMayBeFinal") +public class GaussianRandomLocatorTemplate implements ObjectTemplate { + @Value("height") + private @Meta Range height; + + @Value("amount") + private @Meta Range amount; + + @Value("standard-deviation") + private @Meta double standardDeviation; + + @Value("salt") + @Default + private @Meta int salt = 0; + + @Override + public Locator get() { + return new GaussianRandomLocator(height, amount, standardDeviation, salt); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/OrLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/OrLocatorTemplate.java new file mode 100644 index 000000000..3c56dfe24 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/OrLocatorTemplate.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; + +import java.util.List; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Locator; + + +public class OrLocatorTemplate implements ObjectTemplate, ValidatedConfigTemplate { + @Value("locators") + private @Meta List<@Meta Locator> locators; + + @Override + public Locator get() { + Locator current = locators.remove(0); + while(!locators.isEmpty()) { + current = current.or(locators.remove(0)); + } + return current; + } + + @Override + public boolean validate() throws ValidationException { + if(locators.isEmpty()) throw new ValidationException("OR Pattern must specify at least 1 pattern."); + return true; + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/PatternLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/PatternLocatorTemplate.java new file mode 100644 index 000000000..34d0a1e62 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/PatternLocatorTemplate.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.locators.PatternLocator; +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; + + +public class PatternLocatorTemplate implements ObjectTemplate { + @Value("range") + private @Meta Range range; + + @Value("pattern") + private @Meta Pattern pattern; + + @Override + public Locator get() { + return new PatternLocator(pattern, range); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/RandomLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/RandomLocatorTemplate.java new file mode 100644 index 000000000..9bdb3f6db --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/RandomLocatorTemplate.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.locators.RandomLocator; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; + + +@SuppressWarnings("FieldMayBeFinal") +public class RandomLocatorTemplate implements ObjectTemplate { + @Value("height") + private @Meta Range height; + + @Value("amount") + private @Meta Range amount; + + @Value("salt") + @Default + private @Meta int salt = 0; + + @Override + public Locator get() { + return new RandomLocator(height, amount, salt); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/Sampler3DLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/Sampler3DLocatorTemplate.java new file mode 100644 index 000000000..9a57fd14c --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/Sampler3DLocatorTemplate.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.locators.Sampler3DLocator; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.structure.feature.Locator; + + +public class Sampler3DLocatorTemplate implements ObjectTemplate { + @Value("sampler") + private @Meta NoiseSampler sampler; + + @Override + public Locator get() { + return new Sampler3DLocator(sampler); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/SamplerLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/SamplerLocatorTemplate.java new file mode 100644 index 000000000..6f27af76e --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/SamplerLocatorTemplate.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.List; + +import com.dfsek.terra.addons.feature.locator.locators.SamplerLocator; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.structure.feature.Locator; + + +public class SamplerLocatorTemplate implements ObjectTemplate { + @Value("samplers") + private @Meta List<@Meta NoiseSampler> samplers; + + @Override + public Locator get() { + return new SamplerLocator(samplers); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/SurfaceLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/SurfaceLocatorTemplate.java new file mode 100644 index 000000000..991bdb050 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/SurfaceLocatorTemplate.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.locators.SurfaceLocator; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; + + +public class SurfaceLocatorTemplate implements ObjectTemplate { + @Value("range") + private @Meta Range range; + + @Override + public Locator get() { + return new SurfaceLocator(range); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/TopLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/TopLocatorTemplate.java new file mode 100644 index 000000000..9b2e82f06 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/TopLocatorTemplate.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.locators.TopLocator; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; + + +public class TopLocatorTemplate implements ObjectTemplate { + + @Value("range") + private @Meta Range range; + + @Override + public Locator get() { + return new TopLocator(range); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/XorLocatorTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/XorLocatorTemplate.java new file mode 100644 index 000000000..d8c400660 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/XorLocatorTemplate.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; + +import java.util.List; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.feature.Locator; + + +public class XorLocatorTemplate implements ObjectTemplate, ValidatedConfigTemplate { + @Value("locators") + private @Meta List<@Meta Locator> locators; + + @Override + public Locator get() { + Locator current = locators.remove(0); + while(!locators.isEmpty()) { + current = current.xor(locators.remove(0)); + } + return current; + } + + @Override + public boolean validate() throws ValidationException { + if(locators.isEmpty()) throw new ValidationException("XOR Pattern must specify at least 1 pattern."); + return true; + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/AirMatchPatternTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/AirMatchPatternTemplate.java new file mode 100644 index 000000000..8099fba9d --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/AirMatchPatternTemplate.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config.pattern; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.patterns.MatchPattern; +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.Range; + + +public class AirMatchPatternTemplate implements ObjectTemplate { + @Value("offset") + private @Meta Range offset; + + + @Override + public Pattern get() { + return new MatchPattern(offset, BlockState::isAir); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/AndPatternTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/AndPatternTemplate.java new file mode 100644 index 000000000..84e443466 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/AndPatternTemplate.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config.pattern; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; + +import java.util.List; + +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.config.meta.Meta; + + +public class AndPatternTemplate implements ObjectTemplate, ValidatedConfigTemplate { + @Value("patterns") + private @Meta List<@Meta Pattern> patterns; + + @Override + public Pattern get() { + Pattern current = patterns.remove(0); + while(!patterns.isEmpty()) { + current = current.and(patterns.remove(0)); + } + return current; + } + + @Override + public boolean validate() throws ValidationException { + if(patterns.isEmpty()) throw new ValidationException("AND Pattern must specify at least 1 pattern."); + return true; + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/BlockSetMatchPatternTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/BlockSetMatchPatternTemplate.java new file mode 100644 index 000000000..c08391727 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/BlockSetMatchPatternTemplate.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config.pattern; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.patterns.MatchPattern; +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.util.collection.MaterialSet; + + +public class BlockSetMatchPatternTemplate implements ObjectTemplate { + @Value("blocks") + private @Meta MaterialSet blocks; + + @Value("offset") + private @Meta Range offset; + + @Override + public Pattern get() { + return new MatchPattern(offset, blockState -> blocks.contains(blockState.getBlockType())); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/NotPatternTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/NotPatternTemplate.java new file mode 100644 index 000000000..c4d66a2d9 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/NotPatternTemplate.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config.pattern; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.config.meta.Meta; + + +public class NotPatternTemplate implements ObjectTemplate { + @Value("pattern") + private @Meta Pattern pattern; + + @Override + public Pattern get() { + return pattern.not(); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/OrPatternTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/OrPatternTemplate.java new file mode 100644 index 000000000..9c3d1d1fd --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/OrPatternTemplate.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config.pattern; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; + +import java.util.List; + +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.config.meta.Meta; + + +public class OrPatternTemplate implements ObjectTemplate, ValidatedConfigTemplate { + @Value("patterns") + private @Meta List<@Meta Pattern> patterns; + + @Override + public Pattern get() { + Pattern current = patterns.remove(0); + while(!patterns.isEmpty()) { + current = current.or(patterns.remove(0)); + } + return current; + } + + @Override + public boolean validate() throws ValidationException { + if(patterns.isEmpty()) throw new ValidationException("AND Pattern must specify at least 1 pattern."); + return true; + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/SingleBlockMatchPatternTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/SingleBlockMatchPatternTemplate.java new file mode 100644 index 000000000..f3f5ddaeb --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/SingleBlockMatchPatternTemplate.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config.pattern; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.patterns.MatchPattern; +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.Range; + + +public class SingleBlockMatchPatternTemplate implements ObjectTemplate { + @Value("block") + private @Meta BlockState block; + + @Value("offset") + private @Meta Range offset; + + + @Override + public Pattern get() { + return new MatchPattern(offset, block::matches); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/SolidMatchPatternTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/SolidMatchPatternTemplate.java new file mode 100644 index 000000000..fa56d6c3e --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/SolidMatchPatternTemplate.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config.pattern; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.feature.locator.patterns.MatchPattern; +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.util.Range; + + +public class SolidMatchPatternTemplate implements ObjectTemplate { + @Value("offset") + private Range offset; + + @Override + public Pattern get() { + return new MatchPattern(offset, blockState -> blockState.getBlockType().isSolid()); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/XorPatternTemplate.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/XorPatternTemplate.java new file mode 100644 index 000000000..16479a279 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/config/pattern/XorPatternTemplate.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.config.pattern; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; + +import java.util.List; + +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.config.meta.Meta; + + +public class XorPatternTemplate implements ObjectTemplate, ValidatedConfigTemplate { + @Value("patterns") + private @Meta List<@Meta Pattern> patterns; + + @Override + public Pattern get() { + Pattern current = patterns.remove(0); + while(!patterns.isEmpty()) { + current = current.xor(patterns.remove(0)); + } + return current; + } + + @Override + public boolean validate() throws ValidationException { + if(patterns.isEmpty()) throw new ValidationException("AND Pattern must specify at least 1 pattern."); + return true; + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java new file mode 100644 index 000000000..55fc2c2b3 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/AdjacentPatternLocator.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.locators; + +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.structure.feature.BinaryColumn; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.world.chunk.generation.util.Column; + + +public class AdjacentPatternLocator implements Locator { + private final Pattern pattern; + private final Range search; + private final boolean matchAll; + + public AdjacentPatternLocator(Pattern pattern, Range search, boolean matchAll) { + this.pattern = pattern; + this.search = search; + this.matchAll = matchAll; + } + + @Override + public BinaryColumn getSuitableCoordinates(Column column) { + return new BinaryColumn(search, y -> isValid(y, column)); + } + + private boolean isValid(int y, Column column) { + if(matchAll) { + return pattern.matches(y, column.adjacent(0, -1)) && + pattern.matches(y, column.adjacent(0, 1)) && + pattern.matches(y, column.adjacent(-1, 0)) && + pattern.matches(y, column.adjacent(1, 0)); + } else { + return pattern.matches(y, column.adjacent(0, -1)) || + pattern.matches(y, column.adjacent(0, 1)) || + pattern.matches(y, column.adjacent(-1, 0)) || + pattern.matches(y, column.adjacent(1, 0)); + } + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/GaussianRandomLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/GaussianRandomLocator.java new file mode 100644 index 000000000..16fb827e5 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/GaussianRandomLocator.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.locators; + +import java.util.Random; + +import com.dfsek.terra.api.structure.feature.BinaryColumn; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.world.chunk.generation.util.Column; +import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder; + + +public class GaussianRandomLocator implements Locator { + private final double mean; + + private final Range points; + + private final double standardDeviation; + + private final int salt; + + + public GaussianRandomLocator(Range height, Range points, double standardDeviation, int salt) { + this.mean = (height.getMax() + height.getMin()) / 2.0; + this.points = points; + this.standardDeviation = standardDeviation; + this.salt = salt; + } + + @Override + public BinaryColumn getSuitableCoordinates(Column column) { + long seed = column.getWorld().getSeed(); + seed = 31 * seed + column.getX(); + seed = 31 * seed + column.getZ(); + seed += salt; + + Random r = new Random(seed); + + int size = points.get(r); + + + BinaryColumnBuilder results = column.newBinaryColumn(); + for(int i = 0; i < size; i++) { + int h = (int) r.nextGaussian(mean, standardDeviation); + if(h >= column.getMaxY() || h < column.getMinY()) continue; + results.set(h); + } + + return results.build(); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java new file mode 100644 index 000000000..f3f525af9 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/PatternLocator.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.locators; + +import com.dfsek.terra.addons.feature.locator.patterns.Pattern; +import com.dfsek.terra.api.structure.feature.BinaryColumn; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.world.chunk.generation.util.Column; + + +public class PatternLocator implements Locator { + private final Pattern pattern; + private final Range search; + + public PatternLocator(Pattern pattern, Range search) { + this.pattern = pattern; + this.search = search; + } + + @Override + public BinaryColumn getSuitableCoordinates(Column column) { + return new BinaryColumn(search, y -> pattern.matches(y, column)); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/RandomLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/RandomLocator.java new file mode 100644 index 000000000..fc86878ff --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/RandomLocator.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.locators; + +import java.util.Random; + +import com.dfsek.terra.api.structure.feature.BinaryColumn; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.world.chunk.generation.util.Column; +import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder; + + +public class RandomLocator implements Locator { + private final Range height; + + private final Range points; + + private final int salt; + + public RandomLocator(Range height, Range points, int salt) { + this.height = height; + this.points = points; + this.salt = salt; + } + + @Override + public BinaryColumn getSuitableCoordinates(Column column) { + long seed = column.getWorld().getSeed(); + seed = 31 * seed + column.getX(); + seed = 31 * seed + column.getZ(); + seed += salt; + + Random r = new Random(seed); + + int size = points.get(r); + + BinaryColumnBuilder results = column.newBinaryColumn(); + for(int i = 0; i < size; i++) { + int h = height.get(r); + if(h >= column.getMaxY() || h < column.getMinY()) continue; + results.set(h); + } + + return results.build(); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/Sampler3DLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/Sampler3DLocator.java new file mode 100644 index 000000000..f4691cd36 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/Sampler3DLocator.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.locators; + +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.structure.feature.BinaryColumn; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.world.chunk.generation.util.Column; + + +public class Sampler3DLocator implements Locator { + private final NoiseSampler sampler; + + public Sampler3DLocator(NoiseSampler sampler) { + this.sampler = sampler; + } + + @Override + public BinaryColumn getSuitableCoordinates(Column column) { + long seed = column.getWorld().getSeed(); + int x = column.getX(); + int z = column.getZ(); + return column.newBinaryColumn(y -> sampler.noise(seed, x, y, z) > 0); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SamplerLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SamplerLocator.java new file mode 100644 index 000000000..3a2ff8330 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SamplerLocator.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.locators; + +import java.util.List; + +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.structure.feature.BinaryColumn; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.world.chunk.generation.util.Column; +import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder; + + +public class SamplerLocator implements Locator { + private final List samplers; + + public SamplerLocator(List samplers) { + this.samplers = samplers; + } + + @Override + public BinaryColumn getSuitableCoordinates(Column column) { + BinaryColumnBuilder results = column.newBinaryColumn(); + + long seed = column.getWorld().getSeed(); + samplers.forEach(sampler -> { + int y = floorToInt(sampler.noise(seed, column.getX(), column.getZ())); + if(y >= column.getMaxY() || y < column.getMinY()) return; + results.set(y); + }); + + return results.build(); + } + + private static int floorToInt(double value) { + int valueInt = (int)value; + if (value < 0.0) { + if (value == (double)valueInt) { + return valueInt; + } else { + return valueInt == Integer.MIN_VALUE ? valueInt : valueInt - 1; + } + } else { + return valueInt; + } + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java new file mode 100644 index 000000000..c56f583d2 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/SurfaceLocator.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.locators; + +import com.dfsek.terra.api.structure.feature.BinaryColumn; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.world.chunk.generation.util.Column; +import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder; + + +public class SurfaceLocator implements Locator { + private final Range search; + + public SurfaceLocator(Range search) { + this.search = search; + } + + @Override + public BinaryColumn getSuitableCoordinates(Column column) { + BinaryColumnBuilder builder = column.newBinaryColumn(); + for(int y : search) { + if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) { + builder.set(y); + } + } + return builder.build(); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/TopLocator.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/TopLocator.java new file mode 100644 index 000000000..f9e8e0ea6 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/locators/TopLocator.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.locators; + +import com.dfsek.terra.api.structure.feature.BinaryColumn; +import com.dfsek.terra.api.structure.feature.Locator; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.world.chunk.generation.util.Column; + + +public class TopLocator implements Locator { + private final Range search; + + public TopLocator(Range search) { + this.search = search; + } + + @Override + public BinaryColumn getSuitableCoordinates(Column column) { + for(int y : search) { + if(column.getBlock(y).isAir() && !column.getBlock(y - 1).isAir()) { + return new BinaryColumn(y, y + 1, yi -> true); + } + } + return BinaryColumn.getNull(); + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java new file mode 100644 index 000000000..3ef1c3fbb --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/MatchPattern.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.patterns; + +import java.util.function.Predicate; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.world.chunk.generation.util.Column; + + +public class MatchPattern implements Pattern { + private final Range range; + private final Predicate matches; + + public MatchPattern(Range range, Predicate matches) { + this.range = range; + this.matches = matches; + } + + @Override + public boolean matches(int y, Column column) { + for(int i : range) { + if(!matches.test(column.getBlock(y + i))) return false; + } + return true; + } +} diff --git a/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java new file mode 100644 index 000000000..dbe909943 --- /dev/null +++ b/common/addons/config-locators/src/main/java/com/dfsek/terra/addons/feature/locator/patterns/Pattern.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.feature.locator.patterns; + +import com.dfsek.terra.api.world.chunk.generation.util.Column; + + +public interface Pattern { + boolean matches(int y, Column column); + + default Pattern and(Pattern that) { + return (y, column) -> this.matches(y, column) && that.matches(y, column); + } + + default Pattern or(Pattern that) { + return (y, column) -> this.matches(y, column) || that.matches(y, column); + } + + default Pattern xor(Pattern that) { + return (y, column) -> this.matches(y, column) ^ that.matches(y, column); + } + + default Pattern not() { + return (y, column) -> !this.matches(y, column); + } +} diff --git a/common/addons/config-locators/src/main/resources/terra.addon.yml b/common/addons/config-locators/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..e84bf800d --- /dev/null +++ b/common/addons/config-locators/src/main/resources/terra.addon.yml @@ -0,0 +1,15 @@ +schema-version: 1 +contributors: + - Terra contributors +id: config-locators +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.feature.locator.LocatorAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License +depends: + config-feature: "1.+" + generation-stage-feature: "1.+" \ No newline at end of file diff --git a/common/addons/config-noise-function/LICENSE b/common/addons/config-noise-function/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/config-noise-function/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/config-noise-function/README.md b/common/addons/config-noise-function/README.md new file mode 100644 index 000000000..435757b55 --- /dev/null +++ b/common/addons/config-noise-function/README.md @@ -0,0 +1,3 @@ +# config-noise-function + +Registers the default noise functions. \ No newline at end of file diff --git a/common/addons/config-noise-function/build.gradle.kts b/common/addons/config-noise-function/build.gradle.kts new file mode 100644 index 000000000..f51d5e878 --- /dev/null +++ b/common/addons/config-noise-function/build.gradle.kts @@ -0,0 +1,16 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + api("com.dfsek", "paralithic", Versions.Libraries.paralithic) + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + + +tasks.named("shadowJar") { + relocate("com.dfsek.paralithic", "com.dfsek.terra.addons.noise.lib.paralithic") + relocate("net.jafama", "com.dfsek.terra.addons.noise.lib.jafama") +} \ No newline at end of file diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java new file mode 100644 index 000000000..06bf082b9 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Supplier; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; +import com.dfsek.terra.addons.noise.config.templates.BinaryArithmeticTemplate; +import com.dfsek.terra.addons.noise.config.templates.DomainWarpTemplate; +import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; +import com.dfsek.terra.addons.noise.config.templates.ImageSamplerTemplate; +import com.dfsek.terra.addons.noise.config.templates.KernelTemplate; +import com.dfsek.terra.addons.noise.config.templates.LinearHeightmapSamplerTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.CellularNoiseTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.ConstantNoiseTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.ExpressionFunctionTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.GaborNoiseTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.SimpleNoiseTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.fractal.BrownianMotionTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.fractal.PingPongTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.fractal.RidgedFractalTemplate; +import com.dfsek.terra.addons.noise.config.templates.normalizer.ClampNormalizerTemplate; +import com.dfsek.terra.addons.noise.config.templates.normalizer.LinearNormalizerTemplate; +import com.dfsek.terra.addons.noise.config.templates.normalizer.NormalNormalizerTemplate; +import com.dfsek.terra.addons.noise.config.templates.normalizer.PosterizationNormalizerTemplate; +import com.dfsek.terra.addons.noise.config.templates.normalizer.ProbabilityNormalizerTemplate; +import com.dfsek.terra.addons.noise.config.templates.normalizer.ScaleNormalizerTemplate; +import com.dfsek.terra.addons.noise.samplers.arithmetic.AdditionSampler; +import com.dfsek.terra.addons.noise.samplers.arithmetic.DivisionSampler; +import com.dfsek.terra.addons.noise.samplers.arithmetic.MaxSampler; +import com.dfsek.terra.addons.noise.samplers.arithmetic.MinSampler; +import com.dfsek.terra.addons.noise.samplers.arithmetic.MultiplicationSampler; +import com.dfsek.terra.addons.noise.samplers.arithmetic.SubtractionSampler; +import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler; +import com.dfsek.terra.addons.noise.samplers.noise.random.GaussianNoiseSampler; +import com.dfsek.terra.addons.noise.samplers.noise.random.PositiveWhiteNoiseSampler; +import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler; +import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2SSampler; +import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler; +import com.dfsek.terra.addons.noise.samplers.noise.simplex.PerlinSampler; +import com.dfsek.terra.addons.noise.samplers.noise.simplex.SimplexSampler; +import com.dfsek.terra.addons.noise.samplers.noise.value.ValueCubicSampler; +import com.dfsek.terra.addons.noise.samplers.noise.value.ValueSampler; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class NoiseAddon implements AddonInitializer { + public static final TypeKey>> NOISE_SAMPLER_TOKEN = new TypeKey<>() { + }; + @Inject + private Platform plugin; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + plugin.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + CheckedRegistry>> noiseRegistry = event.getPack().getOrCreateRegistry( + NOISE_SAMPLER_TOKEN); + event.getPack() + .applyLoader(CellularSampler.DistanceFunction.class, + (type, o, loader, depthTracker) -> CellularSampler.DistanceFunction.valueOf((String) o)) + .applyLoader(CellularSampler.ReturnType.class, + (type, o, loader, depthTracker) -> CellularSampler.ReturnType.valueOf((String) o)) + .applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new) + .applyLoader(FunctionTemplate.class, FunctionTemplate::new); + + noiseRegistry.register(addon.key("LINEAR"), LinearNormalizerTemplate::new); + noiseRegistry.register(addon.key("NORMAL"), NormalNormalizerTemplate::new); + noiseRegistry.register(addon.key("CLAMP"), ClampNormalizerTemplate::new); + noiseRegistry.register(addon.key("PROBABILITY"), ProbabilityNormalizerTemplate::new); + noiseRegistry.register(addon.key("SCALE"), ScaleNormalizerTemplate::new); + noiseRegistry.register(addon.key("POSTERIZATION"), PosterizationNormalizerTemplate::new); + + noiseRegistry.register(addon.key("IMAGE"), ImageSamplerTemplate::new); + + noiseRegistry.register(addon.key("DOMAIN_WARP"), DomainWarpTemplate::new); + + noiseRegistry.register(addon.key("FBM"), BrownianMotionTemplate::new); + noiseRegistry.register(addon.key("PING_PONG"), PingPongTemplate::new); + noiseRegistry.register(addon.key("RIDGED"), RidgedFractalTemplate::new); + + noiseRegistry.register(addon.key("OPEN_SIMPLEX_2"), () -> new SimpleNoiseTemplate(OpenSimplex2Sampler::new)); + noiseRegistry.register(addon.key("OPEN_SIMPLEX_2S"), () -> new SimpleNoiseTemplate(OpenSimplex2SSampler::new)); + noiseRegistry.register(addon.key("PERLIN"), () -> new SimpleNoiseTemplate(PerlinSampler::new)); + noiseRegistry.register(addon.key("SIMPLEX"), () -> new SimpleNoiseTemplate(SimplexSampler::new)); + noiseRegistry.register(addon.key("GABOR"), GaborNoiseTemplate::new); + + + noiseRegistry.register(addon.key("VALUE"), () -> new SimpleNoiseTemplate(ValueSampler::new)); + noiseRegistry.register(addon.key("VALUE_CUBIC"), () -> new SimpleNoiseTemplate(ValueCubicSampler::new)); + + noiseRegistry.register(addon.key("CELLULAR"), CellularNoiseTemplate::new); + + noiseRegistry.register(addon.key("WHITE_NOISE"), () -> new SimpleNoiseTemplate(WhiteNoiseSampler::new)); + noiseRegistry.register(addon.key("POSITIVE_WHITE_NOISE"), () -> new SimpleNoiseTemplate(PositiveWhiteNoiseSampler::new)); + noiseRegistry.register(addon.key("GAUSSIAN"), () -> new SimpleNoiseTemplate(GaussianNoiseSampler::new)); + + noiseRegistry.register(addon.key("CONSTANT"), ConstantNoiseTemplate::new); + + noiseRegistry.register(addon.key("KERNEL"), KernelTemplate::new); + + noiseRegistry.register(addon.key("LINEAR_HEIGHTMAP"), LinearHeightmapSamplerTemplate::new); + + noiseRegistry.register(addon.key("ADD"), () -> new BinaryArithmeticTemplate<>(AdditionSampler::new)); + noiseRegistry.register(addon.key("SUB"), () -> new BinaryArithmeticTemplate<>(SubtractionSampler::new)); + noiseRegistry.register(addon.key("MUL"), () -> new BinaryArithmeticTemplate<>(MultiplicationSampler::new)); + noiseRegistry.register(addon.key("DIV"), () -> new BinaryArithmeticTemplate<>(DivisionSampler::new)); + noiseRegistry.register(addon.key("MAX"), () -> new BinaryArithmeticTemplate<>(MaxSampler::new)); + noiseRegistry.register(addon.key("MIN"), () -> new BinaryArithmeticTemplate<>(MinSampler::new)); + + + Map packSamplers = new LinkedHashMap<>(); + Map packFunctions = new LinkedHashMap<>(); + noiseRegistry.register(addon.key("EXPRESSION"), () -> new ExpressionFunctionTemplate(packSamplers, packFunctions)); + + + NoiseConfigPackTemplate template = event.loadTemplate(new NoiseConfigPackTemplate()); + packSamplers.putAll(template.getSamplers()); + packFunctions.putAll(template.getFunctions()); + event.getPack().getContext().put(template); + }) + .priority(50) + .failThrough(); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java new file mode 100644 index 000000000..155f4c45c --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; +import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.properties.Properties; + + +@SuppressWarnings("FieldMayBeFinal") +public class NoiseConfigPackTemplate implements ConfigTemplate, Properties { + @Value("samplers") + @Default + private @Meta Map noiseBuilderMap = new LinkedHashMap<>(); + + @Value("functions") + @Default + private @Meta LinkedHashMap expressions = new LinkedHashMap<>(); + + public Map getSamplers() { + return noiseBuilderMap; + } + + public LinkedHashMap getFunctions() { + return expressions; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/DimensionApplicableNoiseSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/DimensionApplicableNoiseSampler.java new file mode 100644 index 000000000..9c54e81e7 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/DimensionApplicableNoiseSampler.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class DimensionApplicableNoiseSampler implements ObjectTemplate { + @Value("dimensions") + private @Meta int dimensions; + + @Value(".") + private @Meta NoiseSampler sampler; + + @Override + public DimensionApplicableNoiseSampler get() { + return this; + } + + public int getDimensions() { + return dimensions; + } + + public NoiseSampler getSampler() { + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/BinaryArithmeticTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/BinaryArithmeticTemplate.java new file mode 100644 index 000000000..2f05af842 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/BinaryArithmeticTemplate.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.function.BiFunction; + +import com.dfsek.terra.addons.noise.samplers.arithmetic.BinaryArithmeticSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class BinaryArithmeticTemplate extends SamplerTemplate { + private final BiFunction function; + @Value("left") + private @Meta NoiseSampler left; + @Value("right") + private @Meta NoiseSampler right; + + public BinaryArithmeticTemplate(BiFunction function) { + this.function = function; + } + + @Override + public T get() { + return function.apply(left, right); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/DomainWarpTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/DomainWarpTemplate.java new file mode 100644 index 000000000..375059cba --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/DomainWarpTemplate.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.samplers.DomainWarpedSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class DomainWarpTemplate extends SamplerTemplate { + @Value("warp") + private @Meta NoiseSampler warp; + + @Value("sampler") + private @Meta NoiseSampler function; + + @Value("amplitude") + @Default + private @Meta double amplitude = 1; + + @Override + public NoiseSampler get() { + return new DomainWarpedSampler(function, warp, amplitude); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/FunctionTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/FunctionTemplate.java new file mode 100644 index 000000000..a7a18efdd --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/FunctionTemplate.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Objects; + +import com.dfsek.terra.api.config.meta.Meta; + + +@SuppressWarnings("unused") +public class FunctionTemplate implements ObjectTemplate { + @Value("arguments") + private List args; + + @Value("expression") + private @Meta String function; + + @Value("functions") + @Default + private @Meta LinkedHashMap functions = new LinkedHashMap<>(); + + @Override + public FunctionTemplate get() { + return this; + } + + public List getArgs() { + return args; + } + + public String getFunction() { + return function; + } + + public LinkedHashMap getFunctions() { + return functions; + } + + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + FunctionTemplate that = (FunctionTemplate) o; + return args.equals(that.args) && function.equals(that.function) && functions.equals(that.functions); + } + + @Override + public int hashCode() { + return Objects.hash(args, function, functions); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/ImageSamplerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/ImageSamplerTemplate.java new file mode 100644 index 000000000..4aaf2d511 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/ImageSamplerTemplate.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.awt.image.BufferedImage; + +import com.dfsek.terra.addons.noise.samplers.ImageSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class ImageSamplerTemplate extends SamplerTemplate { + + @Value("image") + private @Meta BufferedImage image; + + @Value("frequency") + private @Meta double frequency; + + @Value("channel") + private ImageSampler.@Meta Channel channel; + + @Override + public NoiseSampler get() { + return new ImageSampler(image, channel, frequency); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/KernelTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/KernelTemplate.java similarity index 51% rename from common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/KernelTemplate.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/KernelTemplate.java index 0fc8db115..2d5f8e4fe 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/KernelTemplate.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/KernelTemplate.java @@ -1,61 +1,69 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ValidatedConfigTemplate; -import com.dfsek.tectonic.exception.ValidationException; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.KernelSampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.exception.ValidationException; import java.util.List; -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class KernelTemplate extends SamplerTemplate implements ValidatedConfigTemplate { +import com.dfsek.terra.addons.noise.samplers.KernelSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class KernelTemplate extends SamplerTemplate { + @Value("kernel") - private List> kernel; - + private @Meta List<@Meta List<@Meta Double>> kernel; + @Value("factor") @Default - private double factor = 1; - - @Value("function") - private NoiseSeeded function; - + private @Meta double factor = 1; + + @Value("sampler") + private @Meta NoiseSampler function; + @Value("frequency") @Default - private double frequency = 1; - + private @Meta double frequency = 1; + @Override - public NoiseSampler apply(Long seed) { + public NoiseSampler get() { double[][] k = new double[kernel.size()][kernel.get(0).size()]; - + for(int x = 0; x < kernel.size(); x++) { for(int y = 0; y < kernel.get(x).size(); y++) { k[x][y] = kernel.get(x).get(y) * factor; } } - - KernelSampler sampler = new KernelSampler(k, function.apply(seed)); + + KernelSampler sampler = new KernelSampler(k, function); sampler.setFrequency(frequency); return sampler; } - + @Override public boolean validate() throws ValidationException { - + if(kernel.isEmpty()) throw new ValidationException("Kernel must not be empty."); - + int len = kernel.get(0).size(); - + if(len == 0) throw new ValidationException("Kernel row must contain data."); - + for(int i = 0; i < kernel.size(); i++) { if(kernel.get(i).size() != len) throw new ValidationException("Kernel row " + i + " size mismatch. Expected " + len + ", found " + kernel.get(i).size()); } - + return super.validate(); } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/LinearHeightmapSamplerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/LinearHeightmapSamplerTemplate.java new file mode 100644 index 000000000..3185ea9c3 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/LinearHeightmapSamplerTemplate.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.samplers.LinearHeightmapSampler; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings("FieldMayBeFinal") +public class LinearHeightmapSamplerTemplate extends SamplerTemplate { + @Value("sampler") + @Default + private NoiseSampler sampler = NoiseSampler.zero(); + + @Value("base") + private double base; + + @Value("scale") + @Default + private double scale = 1; + + @Override + public NoiseSampler get() { + return new LinearHeightmapSampler(sampler, scale, base); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/SamplerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/SamplerTemplate.java new file mode 100644 index 000000000..4253d9df1 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/SamplerTemplate.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates; + +import com.dfsek.tectonic.api.config.template.ValidatedConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.exception.ValidationException; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings("FieldMayBeFinal") +public abstract class SamplerTemplate implements ValidatedConfigTemplate, ObjectTemplate { + @Value("dimensions") + @Default + private @Meta int dimensions = 2; + + @Override + public boolean validate() throws ValidationException { + if(dimensions != 2 && dimensions != 3) throw new ValidationException("Illegal amount of dimensions: " + dimensions); + return true; + } + + public int getDimensions() { + return dimensions; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/CellularNoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/CellularNoiseTemplate.java new file mode 100644 index 000000000..48468b995 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/CellularNoiseTemplate.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.noise; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler; +import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings("FieldMayBeFinal") +public class CellularNoiseTemplate extends NoiseTemplate { + @Value("distance") + @Default + private CellularSampler.@Meta DistanceFunction cellularDistanceFunction = CellularSampler.DistanceFunction.EuclideanSq; + + @Value("return") + @Default + private CellularSampler.@Meta ReturnType cellularReturnType = CellularSampler.ReturnType.Distance; + + @Value("jitter") + @Default + private @Meta double cellularJitter = 1.0D; + + + @Value("lookup") + @Default + private @Meta NoiseSampler lookup = new OpenSimplex2Sampler(); + + @Override + public NoiseSampler get() { + CellularSampler sampler = new CellularSampler(); + sampler.setNoiseLookup(lookup); + sampler.setFrequency(frequency); + sampler.setJitterModifier(cellularJitter); + sampler.setReturnType(cellularReturnType); + sampler.setDistanceFunction(cellularDistanceFunction); + sampler.setSalt(salt); + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ConstantNoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ConstantNoiseTemplate.java new file mode 100644 index 000000000..bff00602a --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ConstantNoiseTemplate.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.noise; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.samplers.noise.ConstantSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings("FieldMayBeFinal") +public class ConstantNoiseTemplate extends SamplerTemplate { + @Value("value") + @Default + private @Meta double value = 0d; + + @Override + public NoiseSampler get() { + return new ConstantSampler(value); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ExpressionFunctionTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ExpressionFunctionTemplate.java new file mode 100644 index 000000000..a15cc8e61 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/ExpressionFunctionTemplate.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.noise; + +import com.dfsek.paralithic.eval.tokenizer.ParseException; +import com.dfsek.paralithic.functions.Function; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; +import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; +import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.paralithic.defined.UserDefinedFunction; +import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction2; +import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction3; +import com.dfsek.terra.addons.noise.samplers.noise.ExpressionFunction; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "FieldMayBeFinal", "unused" }) +public class ExpressionFunctionTemplate extends SamplerTemplate { + private final Map otherFunctions; + private final Map globalFunctions; + @Value("variables") + @Default + private @Meta Map vars = new HashMap<>(); + @Value("expression") + private @Meta String expression; + @Value("samplers") + @Default + private @Meta LinkedHashMap samplers = new LinkedHashMap<>(); + @Value("functions") + @Default + private @Meta LinkedHashMap functions = new LinkedHashMap<>(); + + public ExpressionFunctionTemplate(Map otherFunctions, Map samplers) { + this.otherFunctions = otherFunctions; + this.globalFunctions = samplers; + } + + @Override + public NoiseSampler get() { + try { + Map noiseFunctionMap = generateFunctions(); + return new ExpressionFunction(noiseFunctionMap, expression, vars); + } catch(ParseException e) { + throw new RuntimeException("Failed to parse expression.", e); + } + } + + private Map generateFunctions() throws ParseException { + Map noiseFunctionMap = new HashMap<>(); + + for(Map.Entry entry : globalFunctions.entrySet()) { + noiseFunctionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue())); + } + + for(Map.Entry entry : functions.entrySet()) { + noiseFunctionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue())); + } + + otherFunctions.forEach((id, function) -> { + if(function.getDimensions() == 2) { + noiseFunctionMap.put(id, new NoiseFunction2(function.getSampler())); + } else noiseFunctionMap.put(id, new NoiseFunction3(function.getSampler())); + }); + + samplers.forEach((id, function) -> { + if(function.getDimensions() == 2) { + noiseFunctionMap.put(id, new NoiseFunction2(function.getSampler())); + } else noiseFunctionMap.put(id, new NoiseFunction3(function.getSampler())); + }); + + return noiseFunctionMap; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/GaborNoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/GaborNoiseTemplate.java new file mode 100644 index 000000000..681fb3bfb --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/GaborNoiseTemplate.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.noise; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.samplers.noise.GaborNoiseSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings("FieldMayBeFinal") +public class GaborNoiseTemplate extends NoiseTemplate { + @Value("rotation") + @Default + private @Meta double rotation = 0.25; + + @Value("isotropic") + @Default + private @Meta boolean isotropic = true; + + @Value("deviation") + @Default + private @Meta double deviation = 1.0; + + @Value("impulses") + @Default + private @Meta double impulses = 64d; + + @Value("frequency_0") + @Default + private @Meta double f0 = 0.625; + + @Override + public NoiseSampler get() { + GaborNoiseSampler gaborNoiseSampler = new GaborNoiseSampler(); + gaborNoiseSampler.setFrequency(frequency); + gaborNoiseSampler.setRotation(rotation); + gaborNoiseSampler.setIsotropic(isotropic); + gaborNoiseSampler.setDeviation(deviation); + gaborNoiseSampler.setImpulsesPerKernel(impulses); + gaborNoiseSampler.setFrequency0(f0); + gaborNoiseSampler.setSalt(salt); + return gaborNoiseSampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/NoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/NoiseTemplate.java new file mode 100644 index 000000000..c5ca4a058 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/NoiseTemplate.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.noise; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; +import com.dfsek.terra.api.config.meta.Meta; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public abstract class NoiseTemplate extends SamplerTemplate { + @Value("frequency") + @Default + protected @Meta double frequency = 0.02d; + + @Value("salt") + @Default + protected @Meta long salt = 0; +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/SimpleNoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/SimpleNoiseTemplate.java new file mode 100644 index 000000000..241997fd7 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/SimpleNoiseTemplate.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.noise; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class SimpleNoiseTemplate extends NoiseTemplate { + private final Supplier samplerSupplier; + + public SimpleNoiseTemplate(Supplier samplerSupplier) { + this.samplerSupplier = samplerSupplier; + } + + @Override + public NoiseSampler get() { + NoiseFunction sampler = samplerSupplier.get(); + sampler.setFrequency(frequency); + sampler.setSalt(salt); + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/BrownianMotionTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/BrownianMotionTemplate.java new file mode 100644 index 000000000..a35e2e6b5 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/BrownianMotionTemplate.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.noise.fractal; + +import com.dfsek.terra.addons.noise.samplers.noise.fractal.BrownianMotionSampler; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class BrownianMotionTemplate extends FractalTemplate { + @Override + public NoiseSampler get() { + BrownianMotionSampler sampler = new BrownianMotionSampler(function); + sampler.setGain(fractalGain); + sampler.setLacunarity(fractalLacunarity); + sampler.setOctaves(octaves); + sampler.setWeightedStrength(weightedStrength); + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/FractalTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/FractalTemplate.java new file mode 100644 index 000000000..f0534c098 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/FractalTemplate.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.noise.fractal; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.samplers.noise.fractal.FractalNoiseFunction; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public abstract class FractalTemplate extends SamplerTemplate { + @Value("octaves") + @Default + protected @Meta int octaves = 3; + + @Value("gain") + @Default + protected @Meta double fractalGain = 0.5D; + + @Value("lacunarity") + @Default + protected @Meta double fractalLacunarity = 2.0D; + + @Value("weighted-strength") + @Default + protected @Meta double weightedStrength = 0.0D; + + @Value("sampler") + protected @Meta NoiseSampler function; +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/PingPongTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/PingPongTemplate.java new file mode 100644 index 000000000..319cc9d54 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/PingPongTemplate.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.noise.fractal; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.samplers.noise.fractal.PingPongSampler; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class PingPongTemplate extends FractalTemplate { + @Value("ping-pong") + @Default + private @Meta double pingPong = 2.0D; + + @Override + public NoiseSampler get() { + PingPongSampler sampler = new PingPongSampler(function); + sampler.setGain(fractalGain); + sampler.setLacunarity(fractalLacunarity); + sampler.setOctaves(octaves); + sampler.setWeightedStrength(weightedStrength); + sampler.setPingPongStrength(pingPong); + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/RidgedFractalTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/RidgedFractalTemplate.java new file mode 100644 index 000000000..ccf0eaa67 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/fractal/RidgedFractalTemplate.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.noise.fractal; + +import com.dfsek.terra.addons.noise.samplers.noise.fractal.RidgedFractalSampler; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class RidgedFractalTemplate extends FractalTemplate { + @Override + public NoiseSampler get() { + RidgedFractalSampler sampler = new RidgedFractalSampler(function); + sampler.setGain(fractalGain); + sampler.setLacunarity(fractalLacunarity); + sampler.setOctaves(octaves); + sampler.setWeightedStrength(weightedStrength); + return sampler; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ClampNormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ClampNormalizerTemplate.java new file mode 100644 index 000000000..cc4603f73 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ClampNormalizerTemplate.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.normalizer.ClampNormalizer; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class ClampNormalizerTemplate extends NormalizerTemplate { + @Value("max") + private @Meta double max; + + @Value("min") + private @Meta double min; + + @Override + public NoiseSampler get() { + return new ClampNormalizer(function, min, max); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/LinearNormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/LinearNormalizerTemplate.java new file mode 100644 index 000000000..b6d22d280 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/LinearNormalizerTemplate.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.normalizer.LinearNormalizer; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class LinearNormalizerTemplate extends NormalizerTemplate { + @Value("max") + private @Meta double max; + + @Value("min") + private @Meta double min; + + @Override + public NoiseSampler get() { + return new LinearNormalizer(function, min, max); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalNormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalNormalizerTemplate.java new file mode 100644 index 000000000..b60f3d9e4 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalNormalizerTemplate.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.normalizer.NormalNormalizer; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class NormalNormalizerTemplate extends NormalizerTemplate { + @Value("mean") + private @Meta double mean; + + @Value("standard-deviation") + private @Meta double stdDev; + + @Value("groups") + @Default + private @Meta int groups = 16384; + + @Override + public NoiseSampler get() { + return new NormalNormalizer(function, groups, mean, stdDev); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalizerTemplate.java new file mode 100644 index 000000000..608377de0 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/NormalizerTemplate.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.config.templates.SamplerTemplate; +import com.dfsek.terra.addons.noise.normalizer.Normalizer; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public abstract class NormalizerTemplate extends SamplerTemplate { + @Value("sampler") + protected @Meta NoiseSampler function; +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/PosterizationNormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/PosterizationNormalizerTemplate.java new file mode 100644 index 000000000..8ea32e6a5 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/PosterizationNormalizerTemplate.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.normalizer.PosterizationNormalizer; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class PosterizationNormalizerTemplate extends NormalizerTemplate { + @Value("steps") + private @Meta int steps; + + @Override + public NoiseSampler get() { + return new PosterizationNormalizer(function, steps); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ProbabilityNormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ProbabilityNormalizerTemplate.java new file mode 100644 index 000000000..4b78ce4e9 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ProbabilityNormalizerTemplate.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.terra.addons.noise.normalizer.ProbabilityNormalizer; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class ProbabilityNormalizerTemplate extends NormalizerTemplate { + @Override + public NoiseSampler get() { + return new ProbabilityNormalizer(function); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ScaleNormalizerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ScaleNormalizerTemplate.java new file mode 100644 index 000000000..767c7aaca --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/normalizer/ScaleNormalizerTemplate.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.addons.noise.config.templates.normalizer; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.addons.noise.normalizer.ScaleNormalizer; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class ScaleNormalizerTemplate extends NormalizerTemplate { + @Value("amplitude") + private @Meta double amplitude; + + @Override + public NoiseSampler get() { + return new ScaleNormalizer(function, amplitude); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/ClampNormalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ClampNormalizer.java similarity index 56% rename from common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/ClampNormalizer.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ClampNormalizer.java index dee3ddfd8..62836d966 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/ClampNormalizer.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ClampNormalizer.java @@ -1,18 +1,27 @@ -package com.dfsek.terra.api.math.noise.normalizer; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.normalizer; -import com.dfsek.terra.api.math.noise.NoiseSampler; import net.jafama.FastMath; +import com.dfsek.terra.api.noise.NoiseSampler; + + public class ClampNormalizer extends Normalizer { private final double min; private final double max; - + public ClampNormalizer(NoiseSampler sampler, double min, double max) { super(sampler); this.min = min; this.max = max; } - + @Override public double normalize(double in) { return FastMath.max(FastMath.min(in, max), min); diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/LinearNormalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/LinearNormalizer.java similarity index 57% rename from common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/LinearNormalizer.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/LinearNormalizer.java index 69adfabb3..aaa598948 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/LinearNormalizer.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/LinearNormalizer.java @@ -1,6 +1,14 @@ -package com.dfsek.terra.api.math.noise.normalizer; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.normalizer; + +import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.NoiseSampler; /** * Normalizer to linearly scale data's range. @@ -8,13 +16,13 @@ import com.dfsek.terra.api.math.noise.NoiseSampler; public class LinearNormalizer extends Normalizer { private final double min; private final double max; - + public LinearNormalizer(NoiseSampler sampler, double min, double max) { super(sampler); this.min = min; this.max = max; } - + @Override public double normalize(double in) { return (in - min) * (2 / (max - min)) - 1; diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/NormalNormalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/NormalNormalizer.java similarity index 75% rename from common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/NormalNormalizer.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/NormalNormalizer.java index faeef8963..132efd3c2 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/NormalNormalizer.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/NormalNormalizer.java @@ -1,25 +1,34 @@ -package com.dfsek.terra.api.math.noise.normalizer; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.normalizer; -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.math.noise.NoiseSampler; import net.jafama.FastMath; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.MathUtil; + + /** * Normalizer to redistribute normally distributed data to a continuous distribution via an automatically generated lookup table. */ public class NormalNormalizer extends Normalizer { - + private final double[] lookup; - + public NormalNormalizer(NoiseSampler sampler, int buckets, double mean, double standardDeviation) { super(sampler); this.lookup = new double[buckets]; - + for(int i = 0; i < buckets; i++) { lookup[i] = MathUtil.normalInverse((double) i / buckets, mean, standardDeviation); } } - + @Override public double normalize(double in) { int start = 0; @@ -34,12 +43,12 @@ public class NormalNormalizer extends Normalizer { } double left = FastMath.abs(lookup[start] - in); double right = FastMath.abs(lookup[end] - in); - + double fin; if(left <= right) { fin = (double) start / (lookup.length); } else fin = (double) end / (lookup.length); - + return (fin - 0.5) * 2; } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/Normalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/Normalizer.java new file mode 100644 index 000000000..526afe137 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/Normalizer.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.normalizer; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public abstract class Normalizer implements NoiseSampler { + private final NoiseSampler sampler; + + public Normalizer(NoiseSampler sampler) { + this.sampler = sampler; + } + + public abstract double normalize(double in); + + @Override + public double noise(long seed, double x, double y) { + return normalize(sampler.noise(seed, x, y)); + } + + @Override + public double noise(long seed, double x, double y, double z) { + return normalize(sampler.noise(seed, x, y, z)); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/PosterizationNormalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/PosterizationNormalizer.java new file mode 100644 index 000000000..bdf1c90d9 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/PosterizationNormalizer.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.normalizer; + +import net.jafama.FastMath; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class PosterizationNormalizer extends Normalizer { + private final double stepSize; + + public PosterizationNormalizer(NoiseSampler sampler, int steps) { + super(sampler); + this.stepSize = 2.0 / (steps - 1); + } + + @Override + public double normalize(double in) { + return FastMath.roundToInt((in + 1) / stepSize) * stepSize - 1; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ProbabilityNormalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ProbabilityNormalizer.java new file mode 100644 index 000000000..010973441 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ProbabilityNormalizer.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.addons.noise.normalizer; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class ProbabilityNormalizer extends Normalizer { + public ProbabilityNormalizer(NoiseSampler sampler) { + super(sampler); + } + + @Override + public double normalize(double in) { + return (in + 1) / 2; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ScaleNormalizer.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ScaleNormalizer.java new file mode 100644 index 000000000..07b3bd267 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/normalizer/ScaleNormalizer.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.addons.noise.normalizer; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class ScaleNormalizer extends Normalizer { + private final double scale; + + public ScaleNormalizer(NoiseSampler sampler, double scale) { + super(sampler); + this.scale = scale; + } + + @Override + public double normalize(double in) { + return in * scale; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java new file mode 100644 index 000000000..fe72ed070 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/defined/UserDefinedFunction.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.paralithic.defined; + +import com.dfsek.paralithic.Expression; +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; +import com.dfsek.paralithic.functions.dynamic.Context; +import com.dfsek.paralithic.functions.dynamic.DynamicFunction; +import com.dfsek.paralithic.node.Statefulness; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; + + +public class UserDefinedFunction implements DynamicFunction { + private final Expression expression; + private final int args; + + private static final Map CACHE = new HashMap<>(); + + protected UserDefinedFunction(Expression expression, int args) { + this.expression = expression; + this.args = args; + } + + public static UserDefinedFunction newInstance(FunctionTemplate template) throws ParseException { + UserDefinedFunction function = CACHE.get(template); + if(function == null) { + Parser parser = new Parser(); + Scope parent = new Scope(); + + Scope functionScope = new Scope().withParent(parent); + + template.getArgs().forEach(functionScope::addInvocationVariable); + + for(Entry entry : template.getFunctions().entrySet()) { + String id = entry.getKey(); + FunctionTemplate nest = entry.getValue(); + parser.registerFunction(id, newInstance(nest)); + } + + function = new UserDefinedFunction(parser.parse(template.getFunction(), functionScope), template.getArgs().size()); + CACHE.put(template, function); + } + return function; + } + + @Override + public double eval(double... args) { + return expression.evaluate(args); + } + + @Override + public double eval(Context context, double... args) { + return expression.evaluate(context, args); + } + + @Override + public int getArgNumber() { + return args; + } + + @Override + public Statefulness statefulness() { + return Statefulness.STATELESS; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction2.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction2.java new file mode 100644 index 000000000..ccd2b419f --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction2.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.paralithic.noise; + +import com.dfsek.paralithic.functions.dynamic.Context; +import com.dfsek.paralithic.functions.dynamic.DynamicFunction; +import com.dfsek.paralithic.node.Statefulness; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class NoiseFunction2 implements DynamicFunction { + private final NoiseSampler gen; + + public NoiseFunction2(NoiseSampler gen) { + this.gen = gen; + } + + @Override + public double eval(double... args) { + throw new UnsupportedOperationException("Cannot evaluate seeded function without seed context."); + } + + @Override + public double eval(Context context, double... args) { + return gen.noise(((SeedContext) context).getSeed(), args[0], args[1]); + } + + @Override + public int getArgNumber() { + return 2; + } + + @Override + public Statefulness statefulness() { + return Statefulness.CONTEXTUAL; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction3.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction3.java new file mode 100644 index 000000000..f56015f90 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/NoiseFunction3.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.paralithic.noise; + +import com.dfsek.paralithic.functions.dynamic.Context; +import com.dfsek.paralithic.functions.dynamic.DynamicFunction; +import com.dfsek.paralithic.node.Statefulness; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class NoiseFunction3 implements DynamicFunction { + private final NoiseSampler gen; + + public NoiseFunction3(NoiseSampler gen) { + this.gen = gen; + } + + @Override + public double eval(double... args) { + throw new UnsupportedOperationException("Cannot evaluate seeded function without seed context."); + } + + @Override + public double eval(Context context, double... args) { + return gen.noise(((SeedContext) context).getSeed(), args[0], args[1], args[2]); + } + + @Override + public int getArgNumber() { + return 3; + } + + @Override + public Statefulness statefulness() { + return Statefulness.CONTEXTUAL; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SeedContext.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SeedContext.java new file mode 100644 index 000000000..d5fc7128d --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SeedContext.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.paralithic.noise; + +import com.dfsek.paralithic.functions.dynamic.Context; + + +public class SeedContext implements Context { + private final long seed; + + public SeedContext(long seed) { + this.seed = seed; + } + + public long getSeed() { + return seed; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/DomainWarpedSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/DomainWarpedSampler.java new file mode 100644 index 000000000..2ead08442 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/DomainWarpedSampler.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class DomainWarpedSampler implements NoiseSampler { + private final NoiseSampler function; + private final NoiseSampler warp; + private final double amplitude; + + public DomainWarpedSampler(NoiseSampler function, NoiseSampler warp, double amplitude) { + this.function = function; + this.warp = warp; + this.amplitude = amplitude; + } + + @Override + public double noise(long seed, double x, double y) { + return function.noise(seed++, + x + warp.noise(seed++, x, y) * amplitude, + y + warp.noise(seed, x, y) * amplitude + ); + } + + @Override + public double noise(long seed, double x, double y, double z) { + return function.noise(seed++, + x + warp.noise(seed++, x, y, z) * amplitude, + y + warp.noise(seed++, x, y, z) * amplitude, + z + warp.noise(seed, x, y, z) * amplitude + ); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ImageSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/ImageSampler.java similarity index 61% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ImageSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/ImageSampler.java index a5b31b808..5016d7954 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ImageSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/ImageSampler.java @@ -1,70 +1,75 @@ -package com.dfsek.terra.api.math.noise.samplers; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers; -import com.dfsek.terra.api.math.noise.NoiseSampler; import net.jafama.FastMath; import java.awt.image.BufferedImage; +import com.dfsek.terra.api.noise.NoiseSampler; + + public class ImageSampler implements NoiseSampler { private final BufferedImage image; private final Channel channel; - + private final double frequency; - + public ImageSampler(BufferedImage image, Channel channel, double frequency) { this.image = image; this.channel = channel; this.frequency = frequency; } - + @Override - public double getNoise(double x, double y) { - return ((channel.getChannel(image.getRGB(FastMath.floorMod(FastMath.floorToInt(x * frequency), image.getWidth()), FastMath.floorMod(FastMath.floorToInt(y * frequency), image.getHeight()))) / 255D) - 0.5) * 2; + public double noise(long seed, double x, double y) { + return ((channel.getChannel(image.getRGB(FastMath.floorMod(FastMath.floorToInt(x * frequency), image.getWidth()), + FastMath.floorMod(FastMath.floorToInt(y * frequency), image.getHeight()))) / 255D) - 0.5) * + 2; } - + @Override - public double getNoise(double x, double y, double z) { - return getNoise(x, y); + public double noise(long seed, double x, double y, double z) { + return noise(seed, x, y); } - - @Override - public double getNoiseSeeded(int seed, double x, double y) { - return getNoise(x, y); - } - - @Override - public double getNoiseSeeded(int seed, double x, double y, double z) { - return getNoise(x, y, z); - } - + public enum Channel { RED { @Override public int getChannel(int mashed) { return (mashed >> 16) & 0xff; } - }, GREEN { + }, + GREEN { @Override public int getChannel(int mashed) { return (mashed >> 8) & 0xff; } - }, BLUE { + }, + BLUE { @Override public int getChannel(int mashed) { return mashed & 0xff; } - }, GRAYSCALE { + }, + GRAYSCALE { @Override public int getChannel(int mashed) { return (RED.getChannel(mashed) + GREEN.getChannel(mashed) + BLUE.getChannel(mashed)) / 3; } - }, ALPHA { + }, + ALPHA { @Override public int getChannel(int mashed) { return (mashed >> 24) & 0xff; } }; - + public abstract int getChannel(int mashed); } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/KernelSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/KernelSampler.java similarity index 53% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/KernelSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/KernelSampler.java index 695135e5c..05997df7f 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/KernelSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/KernelSampler.java @@ -1,59 +1,63 @@ -package com.dfsek.terra.api.math.noise.samplers; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers; + +import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.NoiseSampler; public class KernelSampler implements NoiseSampler { private final double[][] kernel; private final NoiseSampler in; private double frequency = 1; - + public KernelSampler(double[][] kernel, NoiseSampler in) { this.kernel = kernel; this.in = in; } - - @Override - public double getNoise(double x, double y) { - return getNoiseSeeded(0, x, y); + + public void setFrequency(double frequency) { + this.frequency = frequency; } - + @Override - public double getNoise(double x, double y, double z) { - return getNoiseSeeded(0, x, y, z); - } - - @Override - public double getNoiseSeeded(int seed, double x, double y) { + public double noise(long seed, double x, double y) { x *= frequency; y *= frequency; double accumulator = 0; - + for(int kx = 0; kx < kernel.length; kx++) { for(int ky = 0; ky < kernel[kx].length; ky++) { - accumulator += in.getNoise(x + kx, y + ky) * kernel[kx][ky]; + double k = kernel[kx][ky]; + if(k != 0) { + accumulator += in.noise(seed, x + kx, y + ky) * k; + } } } - + return accumulator; } - + @Override - public double getNoiseSeeded(int seed, double x, double y, double z) { + public double noise(long seed, double x, double y, double z) { x *= frequency; y *= frequency; z *= frequency; double accumulator = 0; - + for(int kx = 0; kx < kernel.length; kx++) { for(int ky = 0; ky < kernel[kx].length; ky++) { - accumulator += in.getNoise(x + kx, y, z + ky) * kernel[kx][ky]; + double k = kernel[kx][ky]; + if(k != 0) { + accumulator += in.noise(seed, x + kx, y, z + ky) * k; + } } } - + return accumulator; } - - public void setFrequency(double frequency) { - this.frequency = frequency; - } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/LinearHeightmapSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/LinearHeightmapSampler.java new file mode 100644 index 000000000..1f7726034 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/LinearHeightmapSampler.java @@ -0,0 +1,27 @@ +package com.dfsek.terra.addons.noise.samplers; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class LinearHeightmapSampler implements NoiseSampler { + private final NoiseSampler sampler; + private final double scale; + private final double base; + + public LinearHeightmapSampler(NoiseSampler sampler, double scale, double base) { + this.sampler = sampler; + this.scale = scale; + this.base = base; + } + + + @Override + public double noise(long seed, double x, double y) { + return noise(seed, x, 0, y); + } + + @Override + public double noise(long seed, double x, double y, double z) { + return -y + base + sampler.noise(seed, x, y, z) * scale; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/AdditionSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/AdditionSampler.java new file mode 100644 index 000000000..65835b4ae --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/AdditionSampler.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.addons.noise.samplers.arithmetic; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class AdditionSampler extends BinaryArithmeticSampler { + public AdditionSampler(NoiseSampler left, NoiseSampler right) { + super(left, right); + } + + @Override + public double operate(double left, double right) { + return left + right; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/BinaryArithmeticSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/BinaryArithmeticSampler.java new file mode 100644 index 000000000..eb18a60a0 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/BinaryArithmeticSampler.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.addons.noise.samplers.arithmetic; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public abstract class BinaryArithmeticSampler implements NoiseSampler { + private final NoiseSampler left; + private final NoiseSampler right; + + protected BinaryArithmeticSampler(NoiseSampler left, NoiseSampler right) { + this.left = left; + this.right = right; + } + + @Override + public double noise(long seed, double x, double y) { + return operate(left.noise(seed, x, y), right.noise(seed, x, y)); + } + + @Override + public double noise(long seed, double x, double y, double z) { + return operate(left.noise(seed, x, y, z), right.noise(seed, x, y, z)); + } + + public abstract double operate(double left, double right); +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/DivisionSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/DivisionSampler.java new file mode 100644 index 000000000..c1b22231f --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/DivisionSampler.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.addons.noise.samplers.arithmetic; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class DivisionSampler extends BinaryArithmeticSampler { + public DivisionSampler(NoiseSampler left, NoiseSampler right) { + super(left, right); + } + + @Override + public double operate(double left, double right) { + return left / right; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/MaxSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/MaxSampler.java new file mode 100644 index 000000000..4a6521dd3 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/MaxSampler.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.addons.noise.samplers.arithmetic; + +import net.jafama.FastMath; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class MaxSampler extends BinaryArithmeticSampler { + public MaxSampler(NoiseSampler left, NoiseSampler right) { + super(left, right); + } + + @Override + public double operate(double left, double right) { + return FastMath.max(left, right); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/MinSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/MinSampler.java new file mode 100644 index 000000000..7e7ee7087 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/MinSampler.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.addons.noise.samplers.arithmetic; + +import net.jafama.FastMath; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class MinSampler extends BinaryArithmeticSampler { + public MinSampler(NoiseSampler left, NoiseSampler right) { + super(left, right); + } + + @Override + public double operate(double left, double right) { + return FastMath.min(left, right); + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/MultiplicationSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/MultiplicationSampler.java new file mode 100644 index 000000000..235e433ec --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/MultiplicationSampler.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.addons.noise.samplers.arithmetic; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class MultiplicationSampler extends BinaryArithmeticSampler { + public MultiplicationSampler(NoiseSampler left, NoiseSampler right) { + super(left, right); + } + + @Override + public double operate(double left, double right) { + return left * right; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/SubtractionSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/SubtractionSampler.java new file mode 100644 index 000000000..6136682d9 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/arithmetic/SubtractionSampler.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.addons.noise.samplers.arithmetic; + +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class SubtractionSampler extends BinaryArithmeticSampler { + public SubtractionSampler(NoiseSampler left, NoiseSampler right) { + super(left, right); + } + + @Override + public double operate(double left, double right) { + return left - right; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/CellularSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/CellularSampler.java similarity index 86% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/CellularSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/CellularSampler.java index b5488a8dd..f31f81a3f 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/CellularSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/CellularSampler.java @@ -1,9 +1,17 @@ -package com.dfsek.terra.api.math.noise.samplers.noise; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler; +import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; /** * NoiseSampler implementation for Cellular (Voronoi/Worley) Noise. @@ -117,7 +125,7 @@ public class CellularSampler extends NoiseFunction { -0.1842489331d, -0.9777375055d, -0.1004076743d, 0, 0.0775473789d, -0.9111505856d, 0.4047110257d, 0, 0.1399838409d, 0.7601631212d, -0.6344734459d, 0, 0.4484419361d, -0.845289248d, 0.2904925424d, 0 }; - + private static final double[] RAND_VECS_2D = { -0.2700222198d, -0.9628540911d, 0.3863092627d, -0.9223693152d, 0.04444859006d, -0.999011673d, -0.5992523158d, -0.8005602176d, -0.7819280288d, 0.6233687174d, 0.9464672271d, 0.3227999196d, -0.6514146797d, -0.7587218957d, 0.9378472289d, 0.347048376d, @@ -183,76 +191,77 @@ public class CellularSampler extends NoiseFunction { -0.6995302564d, 0.7146029809d, 0.5263414922d, -0.85027327d, -0.5395221479d, 0.841971408d, 0.6579370318d, 0.7530729462d, 0.01426758847d, -0.9998982128d, -0.6734383991d, 0.7392433447d, 0.639412098d, -0.7688642071d, 0.9211571421d, 0.3891908523d, -0.146637214d, -0.9891903394d, -0.782318098d, 0.6228791163d, -0.5039610839d, -0.8637263605d, -0.7743120191d, -0.6328039957d, - }; - - + }; + + private DistanceFunction distanceFunction = DistanceFunction.EuclideanSq; private ReturnType returnType = ReturnType.Distance; private double jitterModifier = 1.0; - + private NoiseSampler noiseLookup; - - public CellularSampler(int seed) { - super(seed); - noiseLookup = new OpenSimplex2Sampler(seed); + + public CellularSampler() { + noiseLookup = new OpenSimplex2Sampler(); } - + public void setDistanceFunction(DistanceFunction distanceFunction) { this.distanceFunction = distanceFunction; } - + public void setJitterModifier(double jitterModifier) { this.jitterModifier = jitterModifier; } - + public void setNoiseLookup(NoiseSampler noiseLookup) { this.noiseLookup = noiseLookup; } - + public void setReturnType(ReturnType returnType) { this.returnType = returnType; } - + @Override - public double getNoiseRaw(int seed, double x, double y) { + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; int xr = fastRound(x); int yr = fastRound(y); - + double distance0 = Double.MAX_VALUE; double distance1 = Double.MAX_VALUE; double distance2 = Double.MAX_VALUE; - + int closestHash = 0; - + double cellularJitter = 0.43701595 * jitterModifier; - + int xPrimed = (xr - 1) * PRIME_X; int yPrimedBase = (yr - 1) * PRIME_Y; - - Vector2 center = new Vector2(x, y); - + + double centerX = x; + double centerY = y; + switch(distanceFunction) { default: case Euclidean: case EuclideanSq: for(int xi = xr - 1; xi <= xr + 1; xi++) { int yPrimed = yPrimedBase; - + for(int yi = yr - 1; yi <= yr + 1; yi++) { int hash = hash(seed, xPrimed, yPrimed); int idx = hash & (255 << 1); - + double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter; double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter; - + double newDistance = vecX * vecX + vecY * vecY; - + distance1 = fastMax(fastMin(distance1, newDistance), distance0); if(newDistance < distance0) { distance0 = newDistance; closestHash = hash; - center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); - center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency); + centerX = ((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); + centerY = ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency); } else if(newDistance < distance1) { distance2 = distance1; distance1 = newDistance; @@ -267,22 +276,22 @@ public class CellularSampler extends NoiseFunction { case Manhattan: for(int xi = xr - 1; xi <= xr + 1; xi++) { int yPrimed = yPrimedBase; - + for(int yi = yr - 1; yi <= yr + 1; yi++) { int hash = hash(seed, xPrimed, yPrimed); int idx = hash & (255 << 1); - + double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter; double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter; - + double newDistance = fastAbs(vecX) + fastAbs(vecY); - + distance1 = fastMax(fastMin(distance1, newDistance), distance0); if(newDistance < distance0) { distance0 = newDistance; closestHash = hash; - center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); - center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency); + centerX = ((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); + centerY = ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency); } else if(newDistance < distance1) { distance2 = distance1; distance1 = newDistance; @@ -297,22 +306,22 @@ public class CellularSampler extends NoiseFunction { case Hybrid: for(int xi = xr - 1; xi <= xr + 1; xi++) { int yPrimed = yPrimedBase; - + for(int yi = yr - 1; yi <= yr + 1; yi++) { int hash = hash(seed, xPrimed, yPrimed); int idx = hash & (255 << 1); - + double vecX = (xi - x) + RAND_VECS_2D[idx] * cellularJitter; double vecY = (yi - y) + RAND_VECS_2D[idx | 1] * cellularJitter; - + double newDistance = (fastAbs(vecX) + fastAbs(vecY)) + (vecX * vecX + vecY * vecY); - + distance1 = fastMax(fastMin(distance1, newDistance), distance0); if(newDistance < distance0) { distance0 = newDistance; closestHash = hash; - center.setX((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); - center.setZ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency); + centerX = ((xi + RAND_VECS_2D[idx] * cellularJitter) / frequency); + centerY = ((yi + RAND_VECS_2D[idx | 1] * cellularJitter) / frequency); } else if(newDistance < distance1) { distance2 = distance1; distance1 = newDistance; @@ -325,90 +334,79 @@ public class CellularSampler extends NoiseFunction { } break; } - + if(distanceFunction == DistanceFunction.Euclidean && returnType != ReturnType.CellValue) { distance0 = fastSqrt(distance0); if(returnType != ReturnType.CellValue) { distance1 = fastSqrt(distance1); } } - - switch(returnType) { - case CellValue: - return closestHash * (1 / 2147483648.0); - case Distance: - return distance0 - 1; - case Distance2: - return distance1 - 1; - case Distance2Add: - return (distance1 + distance0) * 0.5 - 1; - case Distance2Sub: - return distance1 - distance0 - 1; - case Distance2Mul: - return distance1 * distance0 * 0.5 - 1; - case Distance2Div: - return distance0 / distance1 - 1; - case NoiseLookup: - return noiseLookup.getNoise(center.getX(), center.getZ()); - case Distance3: - return distance2 - 1; - case Distance3Add: - return (distance2 + distance0) * 0.5 - 1; - case Distance3Sub: - return distance2 - distance0 - 1; - case Distance3Mul: - return distance2 * distance0 - 1; - case Distance3Div: - return distance0 / distance2 - 1; - default: - return 0; - } + + return switch(returnType) { + case CellValue -> closestHash * (1 / 2147483648.0); + case Distance -> distance0 - 1; + case Distance2 -> distance1 - 1; + case Distance2Add -> (distance1 + distance0) * 0.5 - 1; + case Distance2Sub -> distance1 - distance0 - 1; + case Distance2Mul -> distance1 * distance0 * 0.5 - 1; + case Distance2Div -> distance0 / distance1 - 1; + case NoiseLookup -> noiseLookup.noise(sl, centerX, centerY); + case Distance3 -> distance2 - 1; + case Distance3Add -> (distance2 + distance0) * 0.5 - 1; + case Distance3Sub -> distance2 - distance0 - 1; + case Distance3Mul -> distance2 * distance0 - 1; + case Distance3Div -> distance0 / distance2 - 1; + case Angle -> FastMath.atan2(y / frequency - centerY, x / frequency - centerX); + }; } - + @Override - public double getNoiseRaw(int seed, double x, double y, double z) { + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; int xr = fastRound(x); int yr = fastRound(y); int zr = fastRound(z); - + double distance0 = Double.MAX_VALUE; double distance1 = Double.MAX_VALUE; double distance2 = Double.MAX_VALUE; int closestHash = 0; - + double cellularJitter = 0.39614353 * jitterModifier; - + int xPrimed = (xr - 1) * PRIME_X; int yPrimedBase = (yr - 1) * PRIME_Y; int zPrimedBase = (zr - 1) * PRIME_Z; - - Vector3 center = new Vector3(x, y, z); - + + double centerX = x; + double centerY = y; + double centerZ = z; + switch(distanceFunction) { case Euclidean: case EuclideanSq: for(int xi = xr - 1; xi <= xr + 1; xi++) { int yPrimed = yPrimedBase; - + for(int yi = yr - 1; yi <= yr + 1; yi++) { int zPrimed = zPrimedBase; - + for(int zi = zr - 1; zi <= zr + 1; zi++) { int hash = hash(seed, xPrimed, yPrimed, zPrimed); int idx = hash & (255 << 2); - + double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter; double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter; double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter; - + double newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ; - + if(newDistance < distance0) { distance0 = newDistance; closestHash = hash; - center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); - center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); - center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency); + centerX = ((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); + centerY = ((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); + centerZ = ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency); } else if(newDistance < distance1) { distance2 = distance1; distance1 = newDistance; @@ -425,26 +423,26 @@ public class CellularSampler extends NoiseFunction { case Manhattan: for(int xi = xr - 1; xi <= xr + 1; xi++) { int yPrimed = yPrimedBase; - + for(int yi = yr - 1; yi <= yr + 1; yi++) { int zPrimed = zPrimedBase; - + for(int zi = zr - 1; zi <= zr + 1; zi++) { int hash = hash(seed, xPrimed, yPrimed, zPrimed); int idx = hash & (255 << 2); - + double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter; double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter; double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter; - + double newDistance = fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ); - + if(newDistance < distance0) { distance0 = newDistance; closestHash = hash; - center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); - center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); - center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency); + centerX = ((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); + centerY = ((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); + centerZ = ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency); } else if(newDistance < distance1) { distance2 = distance1; distance1 = newDistance; @@ -461,28 +459,28 @@ public class CellularSampler extends NoiseFunction { case Hybrid: for(int xi = xr - 1; xi <= xr + 1; xi++) { int yPrimed = yPrimedBase; - + for(int yi = yr - 1; yi <= yr + 1; yi++) { int zPrimed = zPrimedBase; - + for(int zi = zr - 1; zi <= zr + 1; zi++) { int hash = hash(seed, xPrimed, yPrimed, zPrimed); int idx = hash & (255 << 2); - + double vecX = (xi - x) + RAND_VECS_3D[idx] * cellularJitter; double vecY = (yi - y) + RAND_VECS_3D[idx | 1] * cellularJitter; double vecZ = (zi - z) + RAND_VECS_3D[idx | 2] * cellularJitter; - + double newDistance = (fastAbs(vecX) + fastAbs(vecY) + fastAbs(vecZ)) + - (vecX * vecX + vecY * vecY + vecZ * vecZ); - + (vecX * vecX + vecY * vecY + vecZ * vecZ); + distance1 = fastMax(fastMin(distance1, newDistance), distance0); if(newDistance < distance0) { distance0 = newDistance; closestHash = hash; - center.setX((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); - center.setY((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); - center.setZ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency); + centerX = ((xi + RAND_VECS_3D[idx] * cellularJitter) / frequency); + centerY = ((yi + RAND_VECS_3D[idx | 1] * cellularJitter) / frequency); + centerZ = ((zi + RAND_VECS_3D[idx | 2] * cellularJitter) / frequency); } else if(newDistance < distance1) { distance2 = distance1; distance1 = newDistance; @@ -499,54 +497,40 @@ public class CellularSampler extends NoiseFunction { default: break; } - + if(distanceFunction == DistanceFunction.Euclidean && returnType != ReturnType.CellValue) { distance0 = fastSqrt(distance0); if(returnType != ReturnType.CellValue) { distance1 = fastSqrt(distance1); } } - - switch(returnType) { - case CellValue: - return closestHash * (1 / 2147483648.0); - case Distance: - return distance0 - 1; - case Distance2: - return distance1 - 1; - case Distance2Add: - return (distance1 + distance0) * 0.5 - 1; - case Distance2Sub: - return distance1 - distance0 - 1; - case Distance2Mul: - return distance1 * distance0 * 0.5 - 1; - case Distance2Div: - return distance0 / distance1 - 1; - case NoiseLookup: - return noiseLookup.getNoise(center.getX(), center.getY(), center.getZ()); - case Distance3: - return distance2 - 1; - case Distance3Add: - return (distance2 + distance0) * 0.5 - 1; - case Distance3Sub: - return distance2 - distance0 - 1; - case Distance3Mul: - return distance2 * distance0 - 1; - case Distance3Div: - return distance0 / distance2 - 1; - default: - return 0; - } + + return switch(returnType) { + case CellValue -> closestHash * (1 / 2147483648.0); + case Distance -> distance0 - 1; + case Distance2 -> distance1 - 1; + case Distance2Add -> (distance1 + distance0) * 0.5 - 1; + case Distance2Sub -> distance1 - distance0 - 1; + case Distance2Mul -> distance1 * distance0 * 0.5 - 1; + case Distance2Div -> distance0 / distance1 - 1; + case NoiseLookup -> noiseLookup.noise(sl, centerX, centerY, centerZ); + case Distance3 -> distance2 - 1; + case Distance3Add -> (distance2 + distance0) * 0.5 - 1; + case Distance3Sub -> distance2 - distance0 - 1; + case Distance3Mul -> distance2 * distance0 - 1; + case Distance3Div -> distance0 / distance2 - 1; + case Angle -> FastMath.atan2(y / frequency - centerY, x / frequency - centerX); + }; } - + public enum DistanceFunction { Euclidean, EuclideanSq, Manhattan, Hybrid } - - + + public enum ReturnType { CellValue, Distance, @@ -560,6 +544,7 @@ public class CellularSampler extends NoiseFunction { Distance3Add, Distance3Sub, Distance3Mul, - Distance3Div + Distance3Div, + Angle } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ConstantSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ConstantSampler.java new file mode 100644 index 000000000..9aa9c85d1 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ConstantSampler.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise; + +/** + * Sampler3D implementation that returns a constant. + */ +public class ConstantSampler extends NoiseFunction { + private final double constant; + + public ConstantSampler(double constant) { + this.constant = constant; + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + return constant; + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + return constant; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/ExpressionFunction.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ExpressionFunction.java similarity index 59% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/ExpressionFunction.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ExpressionFunction.java index 305aa1075..c2d93ed2f 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/ExpressionFunction.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/ExpressionFunction.java @@ -1,4 +1,11 @@ -package com.dfsek.terra.api.math.noise.samplers.noise; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise; import com.dfsek.paralithic.Expression; import com.dfsek.paralithic.eval.parser.Parser; @@ -8,36 +15,38 @@ import com.dfsek.paralithic.functions.Function; import java.util.Map; +import com.dfsek.terra.addons.noise.paralithic.noise.SeedContext; + + /** * NoiseSampler implementation using a Paralithic expression. */ public class ExpressionFunction extends NoiseFunction { private final Expression expression; - + public ExpressionFunction(Map functions, String eq, Map vars) throws ParseException { - super(0); Parser p = new Parser(); Scope scope = new Scope(); - + scope.addInvocationVariable("x"); scope.addInvocationVariable("y"); scope.addInvocationVariable("z"); - + vars.forEach(scope::create); - + functions.forEach(p::registerFunction); - + expression = p.parse(eq, scope); frequency = 1; } - + @Override - public double getNoiseRaw(int seed, double x, double y) { - return expression.evaluate(x, 0, y); + public double getNoiseRaw(long seed, double x, double y) { + return expression.evaluate(new SeedContext(seed), x, 0, y); } - + @Override - public double getNoiseRaw(int seed, double x, double y, double z) { - return expression.evaluate(x, y, z); + public double getNoiseRaw(long seed, double x, double y, double z) { + return expression.evaluate(new SeedContext(seed), x, y, z); } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/GaborNoiseSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/GaborNoiseSampler.java similarity index 75% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/GaborNoiseSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/GaborNoiseSampler.java index 93f006dc4..816b6f35e 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/GaborNoiseSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/GaborNoiseSampler.java @@ -1,72 +1,44 @@ -package com.dfsek.terra.api.math.noise.samplers.noise; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise; -import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; import net.jafama.FastMath; +import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler; + + public class GaborNoiseSampler extends NoiseFunction { private final WhiteNoiseSampler rand; private double k = 1.0; private double a = 0.1; private double f0 = 0.625; private double kernelRadius = (FastMath.sqrt(-FastMath.log(0.05) / Math.PI) / a); - private double omega0 = Math.PI * 0.25; - private boolean isotropic = true; private double impulsesPerKernel = 64d; private double impulseDensity = (impulsesPerKernel / (Math.PI * kernelRadius * kernelRadius)); - private double impulsesPerCell = impulseDensity * kernelRadius * kernelRadius; private double g = FastMath.exp(-impulsesPerCell); - - - public GaborNoiseSampler(int seed) { - super(seed); - rand = new WhiteNoiseSampler(seed); + + private double omega0 = Math.PI * 0.25; + private boolean isotropic = true; + + + public GaborNoiseSampler() { + rand = new WhiteNoiseSampler(); } - - public void setIsotropic(boolean isotropic) { - this.isotropic = isotropic; - } - - public void setImpulsesPerKernel(double impulsesPerKernel) { - this.impulsesPerKernel = impulsesPerKernel; - recalculateRadiusAndDensity(); - } - - public void setA(double a) { - this.a = a; - recalculateRadiusAndDensity(); - } - - public void setFrequency0(double f0) { - this.f0 = f0; - } - - public void setRotation(double omega0) { - this.omega0 = Math.PI * omega0; - } - - public void setDeviation(double k) { - this.k = k; - } - + private void recalculateRadiusAndDensity() { kernelRadius = (FastMath.sqrt(-FastMath.log(0.05) / Math.PI) / this.a); impulseDensity = (impulsesPerKernel / (Math.PI * kernelRadius * kernelRadius)); impulsesPerCell = impulseDensity * kernelRadius * kernelRadius; g = FastMath.exp(-impulsesPerCell); } - - @Override - public double getNoiseRaw(int seed, double x, double z) { - return gaborNoise(seed, x, z); - } - - @Override - public double getNoiseRaw(int seed, double x, double y, double z) { - return gaborNoise(seed, x, z); - } - - private double gaborNoise(int seed, double x, double y) { + + private double gaborNoise(long seed, double x, double y) { x /= kernelRadius; y /= kernelRadius; int xi = fastFloor(x); @@ -81,25 +53,63 @@ public class GaborNoiseSampler extends NoiseFunction { } return noise; } - - private double calculateCell(int seed, int xi, int yi, double x, double y) { + + private double calculateCell(long seed, int xi, int yi, double x, double y) { long mashedSeed = murmur64(31L * xi + yi) + seed; - + double gaussianSource = (rand.getNoiseRaw(mashedSeed++) + 1) / 2; int impulses = 0; while(gaussianSource > g) { impulses++; gaussianSource *= (rand.getNoiseRaw(mashedSeed++) + 1) / 2; } - + double noise = 0; for(int i = 0; i < impulses; i++) { - noise += rand.getNoiseRaw(mashedSeed++) * gabor(isotropic ? (rand.getNoiseRaw(mashedSeed++) + 1) * Math.PI : omega0, x * kernelRadius, y * kernelRadius); + noise += rand.getNoiseRaw(mashedSeed++) * gabor(isotropic ? (rand.getNoiseRaw(mashedSeed++) + 1) * Math.PI : omega0, + x * kernelRadius, y * kernelRadius); } return noise; } - + private double gabor(double omega_0, double x, double y) { - return k * (FastMath.exp(-Math.PI * (a * a) * (x * x + y * y)) * fastCos(2 * Math.PI * f0 * (x * fastCos(omega_0) + y * fastSin(omega_0)))); + return k * (FastMath.exp(-Math.PI * (a * a) * (x * x + y * y)) * fastCos(2 * Math.PI * f0 * (x * fastCos(omega_0) + y * fastSin( + omega_0)))); + } + + public void setA(double a) { + this.a = a; + recalculateRadiusAndDensity(); + } + + public void setDeviation(double k) { + this.k = k; + } + + public void setFrequency0(double f0) { + this.f0 = f0; + } + + public void setImpulsesPerKernel(double impulsesPerKernel) { + this.impulsesPerKernel = impulsesPerKernel; + recalculateRadiusAndDensity(); + } + + public void setIsotropic(boolean isotropic) { + this.isotropic = isotropic; + } + + public void setRotation(double omega0) { + this.omega0 = Math.PI * omega0; + } + + @Override + public double getNoiseRaw(long seed, double x, double z) { + return gaborNoise(seed, x, z); + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + return gaborNoise(seed, x, z); } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/NoiseFunction.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/NoiseFunction.java similarity index 74% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/NoiseFunction.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/NoiseFunction.java index 1266c3762..a1a788ebb 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/NoiseFunction.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/NoiseFunction.java @@ -1,100 +1,104 @@ -package com.dfsek.terra.api.math.noise.samplers.noise; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise; -import com.dfsek.terra.api.math.noise.NoiseSampler; import net.jafama.FastMath; +import com.dfsek.terra.api.noise.NoiseSampler; + + @SuppressWarnings("ManualMinMaxCalculation") public abstract class NoiseFunction implements NoiseSampler { // Hashing protected static final int PRIME_X = 501125321; protected static final int PRIME_Y = 1136930381; protected static final int PRIME_Z = 1720413743; - - - protected double frequency = 0.02d; - protected int seed; - - public NoiseFunction(int seed) { - this.seed = seed; - } - - protected static int fastFloor(double f) { - return f >= 0 ? (int) f : (int) f - 1; - } - static final int precision = 100; - - protected static int hash(int seed, int xPrimed, int yPrimed, int zPrimed) { - int hash = seed ^ xPrimed ^ yPrimed ^ zPrimed; - - hash *= 0x27d4eb2d; - return hash; - } - - protected static int hash(int seed, int xPrimed, int yPrimed) { - int hash = seed ^ xPrimed ^ yPrimed; - - hash *= 0x27d4eb2d; - return hash; - } - static final int modulus = 360 * precision; - - protected static int fastRound(double f) { - return f >= 0 ? (int) (f + 0.5f) : (int) (f - 0.5); - } - - protected static double lerp(double a, double b, double t) { - return a + t * (b - a); - } - - protected static double interpHermite(double t) { - return t * t * (3 - 2 * t); - } - - protected static double interpQuintic(double t) { - return t * t * t * (t * (t * 6 - 15) + 10); - } - - protected static double cubicLerp(double a, double b, double c, double d, double t) { - double p = (d - c) - (a - b); - return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b; - } - - protected static double fastMin(double a, double b) { - return a < b ? a : b; - } - - protected static double fastMax(double a, double b) { - return a > b ? a : b; - } - - protected static double fastAbs(double f) { - return f < 0 ? -f : f; - } - - protected static double fastSqrt(double f) { - return FastMath.sqrt(f); - } - static final double[] sin = new double[360 * 100]; // lookup table - static { for(int i = 0; i < sin.length; i++) { sin[i] = (float) Math.sin((double) (i) / (precision)); } } - + protected double frequency = 0.02d; + protected long salt; + + public NoiseFunction() { + this.salt = 0; + } + + protected static int fastFloor(double f) { + return f >= 0 ? (int) f : (int) f - 1; + } + + protected static int hash(int seed, int xPrimed, int yPrimed, int zPrimed) { + int hash = seed ^ xPrimed ^ yPrimed ^ zPrimed; + + hash *= 0x27d4eb2d; + return hash; + } + + protected static int hash(int seed, int xPrimed, int yPrimed) { + int hash = seed ^ xPrimed ^ yPrimed; + + hash *= 0x27d4eb2d; + return hash; + } + + protected static int fastRound(double f) { + return f >= 0 ? (int) (f + 0.5f) : (int) (f - 0.5); + } + + protected static double lerp(double a, double b, double t) { + return a + t * (b - a); + } + + protected static double interpHermite(double t) { + return t * t * (3 - 2 * t); + } + + protected static double interpQuintic(double t) { + return t * t * t * (t * (t * 6 - 15) + 10); + } + + protected static double cubicLerp(double a, double b, double c, double d, double t) { + double p = (d - c) - (a - b); + return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b; + } + + protected static double fastMin(double a, double b) { + return a < b ? a : b; + } + + protected static double fastMax(double a, double b) { + return a > b ? a : b; + } + + protected static double fastAbs(double f) { + return f < 0 ? -f : f; + } + + protected static double fastSqrt(double f) { + return FastMath.sqrt(f); + } + protected static int fastCeil(double f) { int i = (int) f; if(i < f) i++; return i; } - + /** * Murmur64 hashing function * * @param h Input value + * * @return Hashed value */ protected static long murmur64(long h) { @@ -105,53 +109,42 @@ public abstract class NoiseFunction implements NoiseSampler { h ^= h >>> 33; return h; } - - private static double sinLookup(int a) { - return a >= 0 ? sin[a % (modulus)] : -sin[-a % (modulus)]; - } - + protected static double fastSin(double a) { return sinLookup((int) (a * precision + 0.5f)); } - + protected static double fastCos(double a) { return sinLookup((int) ((a + Math.PI / 2) * precision + 0.5f)); } - - - public void setSeed(int seed) { - this.seed = seed; + + private static double sinLookup(int a) { + return a >= 0 ? sin[a % (modulus)] : -sin[-a % (modulus)]; } - + + public void setSalt(long salt) { + this.salt = salt; + } + public double getFrequency() { return frequency; } - + public void setFrequency(double frequency) { this.frequency = frequency; } - + @Override - public double getNoise(double x, double y) { - return getNoiseSeeded(seed, x, y); + public double noise(long seed, double x, double y) { + return getNoiseRaw(seed + salt, x * frequency, y * frequency); } - + @Override - public double getNoise(double x, double y, double z) { - return getNoiseSeeded(seed, x, y, z); + public double noise(long seed, double x, double y, double z) { + return getNoiseRaw(seed + salt, x * frequency, y * frequency, z * frequency); } - - @Override - public double getNoiseSeeded(int seed, double x, double y) { - return getNoiseRaw(seed, x * frequency, y * frequency); - } - - @Override - public double getNoiseSeeded(int seed, double x, double y, double z) { - return getNoiseRaw(seed, x * frequency, y * frequency, z * frequency); - } - - public abstract double getNoiseRaw(int seed, double x, double y); - - public abstract double getNoiseRaw(int seed, double x, double y, double z); + + public abstract double getNoiseRaw(long seed, double x, double y); + + public abstract double getNoiseRaw(long seed, double x, double y, double z); } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/BrownianMotionSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/BrownianMotionSampler.java similarity index 52% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/BrownianMotionSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/BrownianMotionSampler.java index 5233dd2b5..91a7fb3fc 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/BrownianMotionSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/BrownianMotionSampler.java @@ -1,46 +1,54 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.fractal; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.fractal; + +import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.NoiseSampler; public class BrownianMotionSampler extends FractalNoiseFunction { - public BrownianMotionSampler(int seed, NoiseSampler input) { - super(seed, input); + public BrownianMotionSampler(NoiseSampler input) { + super(input); } - + @Override - public double getNoiseRaw(int seed, double x, double y) { + public double getNoiseRaw(long seed, double x, double y) { double sum = 0; double amp = fractalBounding; - + for(int i = 0; i < octaves; i++) { - double noise = input.getNoiseSeeded(seed++, x, y); + double noise = input.noise(seed++, x, y); sum += noise * amp; amp *= lerp(1.0, fastMin(noise + 1, 2) * 0.5, weightedStrength); - + x *= lacunarity; y *= lacunarity; amp *= gain; } - + return sum; } - + @Override - public double getNoiseRaw(int seed, double x, double y, double z) { + public double getNoiseRaw(long seed, double x, double y, double z) { double sum = 0; double amp = fractalBounding; - + for(int i = 0; i < octaves; i++) { - double noise = input.getNoiseSeeded(seed++, x, y, z); + double noise = input.noise(seed++, x, y, z); sum += noise * amp; amp *= lerp(1.0, (noise + 1) * 0.5, weightedStrength); - + x *= lacunarity; y *= lacunarity; z *= lacunarity; amp *= gain; } - + return sum; } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/FractalNoiseFunction.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/FractalNoiseFunction.java similarity index 70% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/FractalNoiseFunction.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/FractalNoiseFunction.java index 471184951..f24e59f39 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/FractalNoiseFunction.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/FractalNoiseFunction.java @@ -1,7 +1,15 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.fractal; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.fractal; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; +import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction; public abstract class FractalNoiseFunction extends NoiseFunction { protected final NoiseSampler input; @@ -10,17 +18,12 @@ public abstract class FractalNoiseFunction extends NoiseFunction { protected double gain = 0.5; protected double lacunarity = 2.0d; protected double weightedStrength = 0.0d; - - public FractalNoiseFunction(int seed, NoiseSampler input) { - super(seed); + + public FractalNoiseFunction(NoiseSampler input) { this.input = input; frequency = 1; } - - public void setWeightedStrength(double weightedStrength) { - this.weightedStrength = weightedStrength; - } - + protected void calculateFractalBounding() { double gain = fastAbs(this.gain); double amp = gain; @@ -31,18 +34,22 @@ public abstract class FractalNoiseFunction extends NoiseFunction { } fractalBounding = 1 / ampFractal; } - - public void setOctaves(int octaves) { - this.octaves = octaves; - calculateFractalBounding(); - } - + public void setGain(double gain) { this.gain = gain; calculateFractalBounding(); } - + public void setLacunarity(double lacunarity) { this.lacunarity = lacunarity; } + + public void setOctaves(int octaves) { + this.octaves = octaves; + calculateFractalBounding(); + } + + public void setWeightedStrength(double weightedStrength) { + this.weightedStrength = weightedStrength; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/PingPongSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/PingPongSampler.java similarity index 56% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/PingPongSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/PingPongSampler.java index bf5f0a4b2..b5f9fdd50 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/PingPongSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/PingPongSampler.java @@ -1,58 +1,66 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.fractal; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.fractal; + +import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.NoiseSampler; public class PingPongSampler extends FractalNoiseFunction { private double pingPongStrength = 2.0; - - public PingPongSampler(int seed, NoiseSampler input) { - super(seed, input); + + public PingPongSampler(NoiseSampler input) { + super(input); } - - + + private static double pingPong(double t) { t -= (int) (t * 0.5f) << 1; return t < 1 ? t : 2 - t; } - + public void setPingPongStrength(double strength) { this.pingPongStrength = strength; } - + @Override - public double getNoiseRaw(int seed, double x, double y) { + public double getNoiseRaw(long seed, double x, double y) { double sum = 0; double amp = fractalBounding; - + for(int i = 0; i < octaves; i++) { - double noise = pingPong((input.getNoiseSeeded(seed++, x, y) + 1) * pingPongStrength); + double noise = pingPong((input.noise(seed++, x, y) + 1) * pingPongStrength); sum += (noise - 0.5) * 2 * amp; amp *= lerp(1.0, noise, weightedStrength); - + x *= lacunarity; y *= lacunarity; amp *= gain; } - + return sum; } - + @Override - public double getNoiseRaw(int seed, double x, double y, double z) { + public double getNoiseRaw(long seed, double x, double y, double z) { double sum = 0; double amp = fractalBounding; - + for(int i = 0; i < octaves; i++) { - double noise = pingPong((input.getNoiseSeeded(seed++, x, y, z) + 1) * pingPongStrength); + double noise = pingPong((input.noise(seed++, x, y, z) + 1) * pingPongStrength); sum += (noise - 0.5) * 2 * amp; amp *= lerp(1.0, noise, weightedStrength); - + x *= lacunarity; y *= lacunarity; z *= lacunarity; amp *= gain; } - + return sum; } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/RidgedFractalSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/RidgedFractalSampler.java similarity index 51% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/RidgedFractalSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/RidgedFractalSampler.java index 08dfbb2ed..9569a8971 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/fractal/RidgedFractalSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/fractal/RidgedFractalSampler.java @@ -1,47 +1,55 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.fractal; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.fractal; + +import com.dfsek.terra.api.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.NoiseSampler; public class RidgedFractalSampler extends FractalNoiseFunction { - - public RidgedFractalSampler(int seed, NoiseSampler input) { - super(seed, input); + + public RidgedFractalSampler(NoiseSampler input) { + super(input); } - + @Override - public double getNoiseRaw(int seed, double x, double y) { + public double getNoiseRaw(long seed, double x, double y) { double sum = 0; double amp = fractalBounding; - + for(int i = 0; i < octaves; i++) { - double noise = fastAbs(input.getNoiseSeeded(seed++, x, y)); + double noise = fastAbs(input.noise(seed++, x, y)); sum += (noise * -2 + 1) * amp; amp *= lerp(1.0, 1 - noise, weightedStrength); - + x *= lacunarity; y *= lacunarity; amp *= gain; } - + return sum; } - + @Override - public double getNoiseRaw(int seed, double x, double y, double z) { + public double getNoiseRaw(long seed, double x, double y, double z) { double sum = 0; double amp = fractalBounding; - + for(int i = 0; i < octaves; i++) { - double noise = fastAbs(input.getNoiseSeeded(seed++, x, y, z)); + double noise = fastAbs(input.noise(seed++, x, y, z)); sum += (noise * -2 + 1) * amp; amp *= lerp(1.0, 1 - noise, weightedStrength); - + x *= lacunarity; y *= lacunarity; z *= lacunarity; amp *= gain; } - + return sum; } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/GaussianNoiseSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/GaussianNoiseSampler.java new file mode 100644 index 000000000..11047a8fc --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/GaussianNoiseSampler.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.random; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; + + +/** + * NoiseSampler implementation to provide random, normally distributed (Gaussian) noise. + */ +public class GaussianNoiseSampler extends NoiseFunction { + private final WhiteNoiseSampler whiteNoiseSampler; // Back with a white noise sampler. + + public GaussianNoiseSampler() { + whiteNoiseSampler = new WhiteNoiseSampler(); + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + double v1, v2, s; + do { + v1 = whiteNoiseSampler.noise(seed++, x, y); + v2 = whiteNoiseSampler.noise(seed++, x, y); + s = v1 * v1 + v2 * v2; + } while(s >= 1 || s == 0); + double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s); + return v1 * multiplier; + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + double v1, v2, s; + do { + v1 = whiteNoiseSampler.noise(seed++, x, y, z); + v2 = whiteNoiseSampler.noise(seed++, x, y, z); + s = v1 * v1 + v2 * v2; + } while(s >= 1 || s == 0); + double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s); + return v1 * multiplier; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/PositiveWhiteNoiseSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/PositiveWhiteNoiseSampler.java new file mode 100644 index 000000000..4046cdef4 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/PositiveWhiteNoiseSampler.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.random; + +/** + * NoiseSampler implementation to produce random, uniformly distributed (white) noise. + */ +public class PositiveWhiteNoiseSampler extends WhiteNoiseSampler { + private static final long POSITIVE_POW1 = 0b01111111111L << 52; + // Bits that when applied to the exponent/sign section of a double, produce a positive number with a power of 1. + + public double getNoiseRaw(long seed) { + return (Double.longBitsToDouble((murmur64(seed) & 0x000fffffffffffffL) | POSITIVE_POW1) - 1.5) * 2; + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + return (getNoiseUnmapped(seed, x, y) - 1); + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + return (getNoiseUnmapped(seed, x, y, z) - 1); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/random/WhiteNoiseSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/WhiteNoiseSampler.java similarity index 61% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/random/WhiteNoiseSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/WhiteNoiseSampler.java index 962ca2486..d8399f1af 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/random/WhiteNoiseSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/random/WhiteNoiseSampler.java @@ -1,52 +1,60 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.random; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.random; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; -import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction; /** * NoiseSampler implementation to produce random, uniformly distributed (white) noise. */ public class WhiteNoiseSampler extends NoiseFunction { - private static final long POSITIVE_POW1 = 0b01111111111L << 52; // Bits that when applied to the exponent/sign section of a double, produce a positive number with a power of 1. - - public WhiteNoiseSampler(int seed) { - super(seed); + private static final long POSITIVE_POW1 = 0b01111111111L << 52; + // Bits that when applied to the exponent/sign section of a double, produce a positive number with a power of 1. + + public WhiteNoiseSampler() { } - - public double getNoiseRaw(long seed) { - return (Double.longBitsToDouble((murmur64(seed) & 0x000fffffffffffffL) | POSITIVE_POW1) - 1.5) * 2; - } - - @Override - public double getNoiseRaw(int seed, double x, double y) { - return (getNoiseUnmapped(seed, x, y) - 1.5) * 2; - } - - @Override - public double getNoiseRaw(int seed, double x, double y, double z) { - return (getNoiseUnmapped(seed, x, y, z) - 1.5) * 2; - } - - public double getNoiseUnmapped(int seed, double x, double y, double z) { - long base = ((randomBits(seed, x, y, z)) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent - return Double.longBitsToDouble(base); - } - - public double getNoiseUnmapped(int seed, double x, double y) { - long base = (randomBits(seed, x, y) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent - return Double.longBitsToDouble(base); - } - - public long randomBits(int seed, double x, double y, double z) { + + public long randomBits(long seed, double x, double y, double z) { long hashX = Double.doubleToRawLongBits(x) ^ seed; long hashZ = Double.doubleToRawLongBits(y) ^ seed; long hash = (((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed) + Double.doubleToRawLongBits(z); return murmur64(hash); } - - public long randomBits(int seed, double x, double y) { + + public long randomBits(long seed, double x, double y) { long hashX = Double.doubleToRawLongBits(x) ^ seed; long hashZ = Double.doubleToRawLongBits(y) ^ seed; long hash = ((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed; return murmur64(hash); } + + public double getNoiseRaw(long seed) { + return (Double.longBitsToDouble((murmur64(seed) & 0x000fffffffffffffL) | POSITIVE_POW1) - 1.5) * 2; + } + + @Override + public double getNoiseRaw(long seed, double x, double y) { + return (getNoiseUnmapped(seed, x, y) - 1.5) * 2; + } + + @Override + public double getNoiseRaw(long seed, double x, double y, double z) { + return (getNoiseUnmapped(seed, x, y, z) - 1.5) * 2; + } + + public double getNoiseUnmapped(long seed, double x, double y, double z) { + long base = ((randomBits(seed, x, y, z)) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent + return Double.longBitsToDouble(base); + } + + public double getNoiseUnmapped(long seed, double x, double y) { + long base = (randomBits(seed, x, y) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent + return Double.longBitsToDouble(base); + } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/OpenSimplex2SSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java similarity index 82% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/OpenSimplex2SSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java index 2ed7fc612..90f6a713f 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/OpenSimplex2SSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java @@ -1,49 +1,53 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.simplex; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.simplex; /** * NoiseSampler implementation to provide OpenSimplex2 (Smooth Variant) noise. */ public class OpenSimplex2SSampler extends SimplexStyleSampler { - public OpenSimplex2SSampler(int seed) { - super(seed); - } - @Override @SuppressWarnings("NumericOverflow") - public double getNoiseRaw(int seed, double x, double y) { + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; // 2D OpenSimplex2S case is a modified 2D simplex noise. - + final double SQRT3 = 1.7320508075688772935274463415059; final double G2 = (3 - SQRT3) / 6; - + final double F2 = 0.5f * (SQRT3 - 1); double s = (x + y) * F2; x += s; y += s; - - + + int i = fastFloor(x); int j = fastFloor(y); double xi = x - i; double yi = y - j; - + i *= PRIME_X; j *= PRIME_Y; int i1 = i + PRIME_X; int j1 = j + PRIME_Y; - + double t = (xi + yi) * G2; double x0 = xi - t; double y0 = yi - t; - + double a0 = (2.0 / 3.0) - x0 * x0 - y0 * y0; double value = (a0 * a0) * (a0 * a0) * gradCoord(seed, i, j, x0, y0); - + double a1 = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a0); double x1 = x0 - (1 - 2 * G2); double y1 = y0 - (1 - 2 * G2); value += (a1 * a1) * (a1 * a1) * gradCoord(seed, i1, j1, x1, y1); - + // Nested conditionals were faster than compact bit logic/arithmetic. double xmyi = xi - yi; if(t > G2) { @@ -62,7 +66,7 @@ public class OpenSimplex2SSampler extends SimplexStyleSampler { value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i, j + PRIME_Y, x2, y2); } } - + if(yi - xmyi > 1) { double x3 = x0 + (3 * G2 - 1); double y3 = y0 + (3 * G2 - 2); @@ -94,7 +98,7 @@ public class OpenSimplex2SSampler extends SimplexStyleSampler { value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + PRIME_X, j, x2, y2); } } - + if(yi < xmyi) { double x2 = x0 - G2; double y2 = y0 - (G2 - 1); @@ -111,72 +115,76 @@ public class OpenSimplex2SSampler extends SimplexStyleSampler { } } } - + return value * 18.24196194486065; } - + @Override @SuppressWarnings("NumericOverflow") - public double getNoiseRaw(int seed, double x, double y, double z) { + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; // 3D OpenSimplex2S case uses two offset rotated cube grids. final double R3 = (2.0 / 3.0); double r = (x + y + z) * R3; // Rotation, not skew x = r - x; y = r - y; z = r - z; - - + + int i = fastFloor(x); int j = fastFloor(y); int k = fastFloor(z); double xi = x - i; double yi = y - j; double zi = z - k; - + i *= PRIME_X; j *= PRIME_Y; k *= PRIME_Z; int seed2 = seed + 1293373; - + int xNMask = (int) (-0.5 - xi); int yNMask = (int) (-0.5 - yi); int zNMask = (int) (-0.5 - zi); - + double x0 = xi + xNMask; double y0 = yi + yNMask; double z0 = zi + zNMask; double a0 = 0.75 - x0 * x0 - y0 * y0 - z0 * z0; - double value = (a0 * a0) * (a0 * a0) * gradCoord(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x0, y0, - z0); - + double value = (a0 * a0) * (a0 * a0) * gradCoord(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x0, + y0, + z0); + double x1 = xi - 0.5; double y1 = yi - 0.5; double z1 = zi - 0.5; double a1 = 0.75 - x1 * x1 - y1 * y1 - z1 * z1; value += (a1 * a1) * (a1 * a1) * gradCoord(seed2, i + PRIME_X, j + PRIME_Y, k + PRIME_Z, x1, y1, z1); - + double xAFlipMask0 = ((xNMask | 1) << 1) * x1; double yAFlipMask0 = ((yNMask | 1) << 1) * y1; double zAFlipMask0 = ((zNMask | 1) << 1) * z1; double xAFlipMask1 = (-2 - (xNMask << 2)) * x1 - 1.0; double yAFlipMask1 = (-2 - (yNMask << 2)) * y1 - 1.0; double zAFlipMask1 = (-2 - (zNMask << 2)) * z1 - 1.0; - + boolean skip5 = false; double a2 = xAFlipMask0 + a0; if(a2 > 0) { double x2 = x0 - (xNMask | 1); - value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x2, y0, - z0); + value += (a2 * a2) * (a2 * a2) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x2, + y0, + z0); } else { double a3 = yAFlipMask0 + zAFlipMask0 + a0; if(a3 > 0) { double y3 = y0 - (yNMask | 1); double z3 = z0 - (zNMask | 1); - value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x0, - y3, z3); + value += (a3 * a3) * (a3 * a3) * gradCoord(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), + x0, + y3, z3); } - + double a4 = xAFlipMask1 + a1; if(a4 > 0) { double x4 = (xNMask | 1) + x1; @@ -184,22 +192,24 @@ public class OpenSimplex2SSampler extends SimplexStyleSampler { skip5 = true; } } - + boolean skip9 = false; double a6 = yAFlipMask0 + a0; if(a6 > 0) { double y6 = y0 - (yNMask | 1); - value += (a6 * a6) * (a6 * a6) * gradCoord(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x0, y6, - z0); + value += (a6 * a6) * (a6 * a6) * gradCoord(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z), x0, + y6, + z0); } else { double a7 = xAFlipMask0 + zAFlipMask0 + a0; if(a7 > 0) { double x7 = x0 - (xNMask | 1); double z7 = z0 - (zNMask | 1); - value += (a7 * a7) * (a7 * a7) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x7, - y0, z7); + value += (a7 * a7) * (a7 * a7) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), + x7, + y0, z7); } - + double a8 = yAFlipMask1 + a1; if(a8 > 0) { double y8 = (yNMask | 1) + y1; @@ -207,22 +217,24 @@ public class OpenSimplex2SSampler extends SimplexStyleSampler { skip9 = true; } } - + boolean skipD = false; double aA = zAFlipMask0 + a0; if(aA > 0) { double zA = z0 - (zNMask | 1); - value += (aA * aA) * (aA * aA) * gradCoord(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x0, y0, - zA); + value += (aA * aA) * (aA * aA) * gradCoord(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z), x0, + y0, + zA); } else { double aB = xAFlipMask0 + yAFlipMask0 + a0; if(aB > 0) { double xB = x0 - (xNMask | 1); double yB = y0 - (yNMask | 1); - value += (aB * aB) * (aB * aB) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z), xB, - yB, z0); + value += (aB * aB) * (aB * aB) * gradCoord(seed, i + (~xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z), + xB, + yB, z0); } - + double aC = zAFlipMask1 + a1; if(aC > 0) { double zC = (zNMask | 1) + z1; @@ -230,37 +242,38 @@ public class OpenSimplex2SSampler extends SimplexStyleSampler { skipD = true; } } - + if(!skip5) { double a5 = yAFlipMask1 + zAFlipMask1 + a1; if(a5 > 0) { double y5 = (yNMask | 1) + y1; double z5 = (zNMask | 1) + z1; value += (a5 * a5) * (a5 * a5) * gradCoord(seed2, i + PRIME_X, j + (yNMask & (PRIME_Y << 1)), k + (zNMask & (PRIME_Z << 1)), - x1, y5, z5); + x1, y5, z5); } } - + if(!skip9) { double a9 = xAFlipMask1 + zAFlipMask1 + a1; if(a9 > 0) { double x9 = (xNMask | 1) + x1; double z9 = (zNMask | 1) + z1; - value += (a9 * a9) * (a9 * a9) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + PRIME_Y, k + (zNMask & (PRIME_Z << 1)), x9, - y1, z9); + value += (a9 * a9) * (a9 * a9) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + PRIME_Y, k + (zNMask & (PRIME_Z << 1)), + x9, + y1, z9); } } - + if(!skipD) { double aD = xAFlipMask1 + yAFlipMask1 + a1; if(aD > 0) { double xD = (xNMask | 1) + x1; double yD = (yNMask | 1) + y1; value += (aD * aD) * (aD * aD) * gradCoord(seed2, i + (xNMask & (PRIME_X << 1)), j + (yNMask & (PRIME_Y << 1)), k + PRIME_Z, - xD, yD, z1); + xD, yD, z1); } } - + return value * 9.046026385208288; } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/OpenSimplex2Sampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java similarity index 84% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/OpenSimplex2Sampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java index 767ce45cb..f4fc0018e 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/OpenSimplex2Sampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java @@ -1,46 +1,50 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.simplex; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.simplex; /** * NoiseSampler implementation to provide OpenSimplex2 noise. */ public class OpenSimplex2Sampler extends SimplexStyleSampler { private static final double SQRT3 = 1.7320508075688772935274463415059; - - public OpenSimplex2Sampler(int seed) { - super(seed); - } - + @Override - public double getNoiseRaw(int seed, double x, double y) { + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; // 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex. final double G2 = (3 - SQRT3) / 6; - + final double F2 = 0.5f * (SQRT3 - 1); double s = (x + y) * F2; x += s; y += s; - - + + int i = fastFloor(x); int j = fastFloor(y); double xi = x - i; double yi = y - j; - + double t = (xi + yi) * G2; double x0 = xi - t; double y0 = yi - t; - + i *= PRIME_X; j *= PRIME_Y; - + double n0, n1, n2; - + double a = 0.5 - x0 * x0 - y0 * y0; if(a <= 0) n0 = 0; else { n0 = (a * a) * (a * a) * gradCoord(seed, i, j, x0, y0); } - + double c = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a); if(c <= 0) n2 = 0; else { @@ -48,7 +52,7 @@ public class OpenSimplex2Sampler extends SimplexStyleSampler { double y2 = y0 + (2 * G2 - 1); n2 = (c * c) * (c * c) * gradCoord(seed, i + PRIME_X, j + PRIME_Y, x2, y2); } - + if(y0 > x0) { double x1 = x0 + G2; double y1 = y0 + (G2 - 1); @@ -66,47 +70,48 @@ public class OpenSimplex2Sampler extends SimplexStyleSampler { n1 = (b * b) * (b * b) * gradCoord(seed, i + PRIME_X, j, x1, y1); } } - + return (n0 + n1 + n2) * 99.83685446303647f; } - + @Override - public double getNoiseRaw(int seed, double x, double y, double z) { + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; // 3D OpenSimplex2Sampler case uses two offset rotated cube grids. final double R3 = (2.0 / 3.0); double r = (x + y + z) * R3; // Rotation, not skew x = r - x; y = r - y; z = r - z; - - + + int i = fastRound(x); int j = fastRound(y); int k = fastRound(z); double x0 = x - i; double y0 = y - j; double z0 = z - k; - + int xNSign = (int) (-1.0 - x0) | 1; int yNSign = (int) (-1.0 - y0) | 1; int zNSign = (int) (-1.0 - z0) | 1; - + double ax0 = xNSign * -x0; double ay0 = yNSign * -y0; double az0 = zNSign * -z0; - + i *= PRIME_X; j *= PRIME_Y; k *= PRIME_Z; - + double value = 0; double a = (0.6f - x0 * x0) - (y0 * y0 + z0 * z0); - + for(int l = 0; ; l++) { if(a > 0) { value += (a * a) * (a * a) * gradCoord(seed, i, j, k, x0, y0, z0); } - + if(ax0 >= ay0 && ax0 >= az0) { double b = a + ax0 + ax0; if(b > 1) { @@ -126,30 +131,30 @@ public class OpenSimplex2Sampler extends SimplexStyleSampler { value += (b * b) * (b * b) * gradCoord(seed, i, j, k - zNSign * PRIME_Z, x0, y0, z0 + zNSign); } } - + if(l == 1) break; - + ax0 = 0.5 - ax0; ay0 = 0.5 - ay0; az0 = 0.5 - az0; - + x0 = xNSign * ax0; y0 = yNSign * ay0; z0 = zNSign * az0; - + a += (0.75 - ax0) - (ay0 + az0); - + i += (xNSign >> 1) & PRIME_X; j += (yNSign >> 1) & PRIME_Y; k += (zNSign >> 1) & PRIME_Z; - + xNSign = -xNSign; yNSign = -yNSign; zNSign = -zNSign; - + seed = ~seed; } - + return value * 32.69428253173828125; } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/PerlinSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/PerlinSampler.java similarity index 77% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/PerlinSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/PerlinSampler.java index 86469fd18..999b73265 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/PerlinSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/PerlinSampler.java @@ -1,69 +1,74 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.simplex; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.simplex; /** * NoiseSampler implementation to provide Perlin Noise. */ public class PerlinSampler extends SimplexStyleSampler { - public PerlinSampler(int seed) { - super(seed); - } - @Override - public double getNoiseRaw(int seed, double x, double y) { + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; int x0 = fastFloor(x); int y0 = fastFloor(y); - + double xd0 = x - x0; double yd0 = y - y0; double xd1 = xd0 - 1; double yd1 = yd0 - 1; - + double xs = interpQuintic(xd0); double ys = interpQuintic(yd0); - + x0 *= PRIME_X; y0 *= PRIME_Y; int x1 = x0 + PRIME_X; int y1 = y0 + PRIME_Y; - + double xf0 = lerp(gradCoord(seed, x0, y0, xd0, yd0), gradCoord(seed, x1, y0, xd1, yd0), xs); double xf1 = lerp(gradCoord(seed, x0, y1, xd0, yd1), gradCoord(seed, x1, y1, xd1, yd1), xs); - + return lerp(xf0, xf1, ys) * 1.4247691104677813; } - + @Override - public double getNoiseRaw(int seed, double x, double y, double z) { + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; int x0 = fastFloor(x); int y0 = fastFloor(y); int z0 = fastFloor(z); - + double xd0 = x - x0; double yd0 = y - y0; double zd0 = z - z0; double xd1 = xd0 - 1; double yd1 = yd0 - 1; double zd1 = zd0 - 1; - + double xs = interpQuintic(xd0); double ys = interpQuintic(yd0); double zs = interpQuintic(zd0); - + x0 *= PRIME_X; y0 *= PRIME_Y; z0 *= PRIME_Z; int x1 = x0 + PRIME_X; int y1 = y0 + PRIME_Y; int z1 = z0 + PRIME_Z; - + double xf00 = lerp(gradCoord(seed, x0, y0, z0, xd0, yd0, zd0), gradCoord(seed, x1, y0, z0, xd1, yd0, zd0), xs); double xf10 = lerp(gradCoord(seed, x0, y1, z0, xd0, yd1, zd0), gradCoord(seed, x1, y1, z0, xd1, yd1, zd0), xs); double xf01 = lerp(gradCoord(seed, x0, y0, z1, xd0, yd0, zd1), gradCoord(seed, x1, y0, z1, xd1, yd0, zd1), xs); double xf11 = lerp(gradCoord(seed, x0, y1, z1, xd0, yd1, zd1), gradCoord(seed, x1, y1, z1, xd1, yd1, zd1), xs); - + double yf0 = lerp(xf00, xf10, ys); double yf1 = lerp(xf01, xf11, ys); - + return lerp(yf0, yf1, zs) * 0.964921414852142333984375; } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/SimplexSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexSampler.java similarity index 88% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/SimplexSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexSampler.java index b12a75d21..4cacc6fef 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/SimplexSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexSampler.java @@ -1,72 +1,76 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.simplex; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.simplex; public class SimplexSampler extends SimplexStyleSampler { private static final Double2[] GRAD_2D = { new Double2(-1, -1), new Double2(1, -1), new Double2(-1, 1), new Double2(1, 1), new Double2(0, -1), new Double2(-1, 0), new Double2(0, 1), new Double2(1, 0), - }; + }; private static final Double3[] GRAD_3D = { new Double3(1, 1, 0), new Double3(-1, 1, 0), new Double3(1, -1, 0), new Double3(-1, -1, 0), new Double3(1, 0, 1), new Double3(-1, 0, 1), new Double3(1, 0, -1), new Double3(-1, 0, -1), new Double3(0, 1, 1), new Double3(0, -1, 1), new Double3(0, 1, -1), new Double3(0, -1, -1), new Double3(1, 1, 0), new Double3(0, -1, 1), new Double3(-1, 1, 0), new Double3(0, -1, -1), - }; - + }; + private static final double F2 = 1.0 / 2.0; private static final double F3 = (1.0 / 3.0); private static final double G2 = 1.0 / 4.0; private static final double G3 = (1.0 / 6.0); private static final double G33 = G3 * 3 - 1; - + private static final int X_PRIME = 1619; private static final int Y_PRIME = 31337; private static final int Z_PRIME = 6971; - - - public SimplexSampler(int seed) { - super(seed); - } - + + private static double gradCoord3D(int seed, int x, int y, int z, double xd, double yd, double zd) { int hash = seed; hash ^= X_PRIME * x; hash ^= Y_PRIME * y; hash ^= Z_PRIME * z; - + hash = hash * hash * hash * 60493; hash = (hash >> 13) ^ hash; - + Double3 g = GRAD_3D[hash & 15]; - + return xd * g.x + yd * g.y + zd * g.z; } - + private static double gradCoord2D(int seed, int x, int y, double xd, double yd) { int hash = seed; hash ^= X_PRIME * x; hash ^= Y_PRIME * y; - + hash = hash * hash * hash * 60493; hash = (hash >> 13) ^ hash; - + Double2 g = GRAD_2D[hash & 7]; - + return xd * g.x + yd * g.y; } - + @Override - public double getNoiseRaw(int seed, double x, double y) { + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; double t = (x + y) * F2; int i = fastFloor(x + t); int j = fastFloor(y + t); - + t = (i + j) * G2; double X0 = i - t; double Y0 = j - t; - + double x0 = x - X0; double y0 = y - Y0; - + int i1, j1; if(x0 > y0) { i1 = 1; @@ -75,14 +79,14 @@ public class SimplexSampler extends SimplexStyleSampler { i1 = 0; j1 = 1; } - + double x1 = x0 - i1 + G2; double y1 = y0 - j1 + G2; double x2 = x0 - 1 + F2; double y2 = y0 - 1 + F2; - + double n0, n1, n2; - + t = 0.5 - x0 * x0 - y0 * y0; if(t < 0) { n0 = 0; @@ -90,7 +94,7 @@ public class SimplexSampler extends SimplexStyleSampler { t *= t; n0 = t * t * gradCoord2D(seed, i, j, x0, y0); } - + t = 0.5 - x1 * x1 - y1 * y1; if(t < 0) { n1 = 0; @@ -98,7 +102,7 @@ public class SimplexSampler extends SimplexStyleSampler { t *= t; n1 = t * t * gradCoord2D(seed, i + i1, j + j1, x1, y1); } - + t = 0.5 - x2 * x2 - y2 * y2; if(t < 0) { n2 = 0; @@ -106,25 +110,26 @@ public class SimplexSampler extends SimplexStyleSampler { t *= t; n2 = t * t * gradCoord2D(seed, i + 1, j + 1, x2, y2); } - + return 50 * (n0 + n1 + n2); } - + @Override - public double getNoiseRaw(int seed, double x, double y, double z) { + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; double t = (x + y + z) * F3; int i = fastFloor(x + t); int j = fastFloor(y + t); int k = fastFloor(z + t); - + t = (i + j + k) * G3; double x0 = x - (i - t); double y0 = y - (j - t); double z0 = z - (k - t); - + int i1, j1, k1; int i2, j2, k2; - + if(x0 >= y0) { if(y0 >= z0) { i1 = 1; @@ -175,7 +180,7 @@ public class SimplexSampler extends SimplexStyleSampler { k2 = 0; } } - + double x1 = x0 - i1 + G3; double y1 = y0 - j1 + G3; double z1 = z0 - k1 + G3; @@ -185,16 +190,16 @@ public class SimplexSampler extends SimplexStyleSampler { double x3 = x0 + G33; double y3 = y0 + G33; double z3 = z0 + G33; - + double n0, n1, n2, n3; - + t = 0.6 - x0 * x0 - y0 * y0 - z0 * z0; if(t < 0) n0 = 0; else { t *= t; n0 = t * t * gradCoord3D(seed, i, j, k, x0, y0, z0); } - + t = 0.6 - x1 * x1 - y1 * y1 - z1 * z1; if(t < 0) { n1 = 0; @@ -202,7 +207,7 @@ public class SimplexSampler extends SimplexStyleSampler { t *= t; n1 = t * t * gradCoord3D(seed, i + i1, j + j1, k + k1, x1, y1, z1); } - + t = 0.6 - x2 * x2 - y2 * y2 - z2 * z2; if(t < 0) { n2 = 0; @@ -210,7 +215,7 @@ public class SimplexSampler extends SimplexStyleSampler { t *= t; n2 = t * t * gradCoord3D(seed, i + i2, j + j2, k + k2, x2, y2, z2); } - + t = 0.6 - x3 * x3 - y3 * y3 - z3 * z3; if(t < 0) { n3 = 0; @@ -218,22 +223,23 @@ public class SimplexSampler extends SimplexStyleSampler { t *= t; n3 = t * t * gradCoord3D(seed, i + 1, j + 1, k + 1, x3, y3, z3); } - + return 32 * (n0 + n1 + n2 + n3); } - + private static class Double2 { public final double x, y; - + public Double2(double x, double y) { this.x = x; this.y = y; } } - + + private static class Double3 { public final double x, y, z; - + public Double3(double x, double y, double z) { this.x = x; this.y = y; diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/SimplexStyleSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java similarity index 94% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/SimplexStyleSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java index 51e4a75ab..9d6a3e083 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/simplex/SimplexStyleSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java @@ -1,6 +1,14 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.simplex; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.simplex; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; -import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction; /** * Abstract NoiseSampler implementation for simplex-style noise functions. @@ -50,8 +58,8 @@ public abstract class SimplexStyleSampler extends NoiseFunction { 0.38268343236509d, 0.923879532511287d, 0.923879532511287d, 0.38268343236509d, 0.923879532511287d, -0.38268343236509d, 0.38268343236509d, -0.923879532511287d, -0.38268343236509d, -0.923879532511287d, -0.923879532511287d, -0.38268343236509d, -0.923879532511287d, 0.38268343236509d, -0.38268343236509d, 0.923879532511287d, - }; - + }; + protected static final double[] GRADIENTS_3D = { 0, 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, @@ -70,31 +78,27 @@ public abstract class SimplexStyleSampler extends NoiseFunction { 1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, -1, 0, 0, 1, 1, 0, 0, 0, -1, 1, 0, -1, 1, 0, 0, 0, -1, -1, 0 }; - - public SimplexStyleSampler(int seed) { - super(seed); - } - + protected static double gradCoord(int seed, int xPrimed, int yPrimed, double xd, double yd) { int hash = hash(seed, xPrimed, yPrimed); hash ^= hash >> 15; hash &= 127 << 1; - + double xg = GRADIENTS_2_D[hash]; double yg = GRADIENTS_2_D[hash | 1]; - + return xd * xg + yd * yg; } - + protected static double gradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, double xd, double yd, double zd) { int hash = hash(seed, xPrimed, yPrimed, zPrimed); hash ^= hash >> 15; hash &= 63 << 2; - + double xg = GRADIENTS_3D[hash]; double yg = GRADIENTS_3D[hash | 1]; double zg = GRADIENTS_3D[hash | 2]; - + return xd * xg + yd * yg + zd * zg; } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/value/ValueCubicSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueCubicSampler.java similarity index 68% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/value/ValueCubicSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueCubicSampler.java index d0664c922..9995046e1 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/value/ValueCubicSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueCubicSampler.java @@ -1,18 +1,22 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.value; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.value; public class ValueCubicSampler extends ValueStyleNoise { - public ValueCubicSampler(int seed) { - super(seed); - } - @Override - public double getNoiseRaw(int seed, double x, double y) { + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; int x1 = fastFloor(x); int y1 = fastFloor(y); - + double xs = x - x1; double ys = y - y1; - + x1 *= PRIME_X; y1 *= PRIME_Y; int x0 = x1 - PRIME_X; @@ -21,33 +25,34 @@ public class ValueCubicSampler extends ValueStyleNoise { int y2 = y1 + PRIME_Y; int x3 = x1 + (PRIME_X << 1); int y3 = y1 + (PRIME_Y << 1); - + return cubicLerp( cubicLerp(valCoord(seed, x0, y0), valCoord(seed, x1, y0), valCoord(seed, x2, y0), valCoord(seed, x3, y0), - xs), + xs), cubicLerp(valCoord(seed, x0, y1), valCoord(seed, x1, y1), valCoord(seed, x2, y1), valCoord(seed, x3, y1), - xs), + xs), cubicLerp(valCoord(seed, x0, y2), valCoord(seed, x1, y2), valCoord(seed, x2, y2), valCoord(seed, x3, y2), - xs), + xs), cubicLerp(valCoord(seed, x0, y3), valCoord(seed, x1, y3), valCoord(seed, x2, y3), valCoord(seed, x3, y3), - xs), + xs), ys) * (1 / (1.5 * 1.5)); } - + @Override - public double getNoiseRaw(int seed, double x, double y, double z) { + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; int x1 = fastFloor(x); int y1 = fastFloor(y); int z1 = fastFloor(z); - + double xs = x - x1; double ys = y - y1; double zs = z - z1; - + x1 *= PRIME_X; y1 *= PRIME_Y; z1 *= PRIME_Z; - + int x0 = x1 - PRIME_X; int y0 = y1 - PRIME_Y; int z0 = z1 - PRIME_Z; @@ -57,47 +62,47 @@ public class ValueCubicSampler extends ValueStyleNoise { int x3 = x1 + (PRIME_X << 1); int y3 = y1 + (PRIME_Y << 1); int z3 = z1 + (PRIME_Z << 1); - + return cubicLerp( cubicLerp( cubicLerp(valCoord(seed, x0, y0, z0), valCoord(seed, x1, y0, z0), valCoord(seed, x2, y0, z0), - valCoord(seed, x3, y0, z0), xs), + valCoord(seed, x3, y0, z0), xs), cubicLerp(valCoord(seed, x0, y1, z0), valCoord(seed, x1, y1, z0), valCoord(seed, x2, y1, z0), - valCoord(seed, x3, y1, z0), xs), + valCoord(seed, x3, y1, z0), xs), cubicLerp(valCoord(seed, x0, y2, z0), valCoord(seed, x1, y2, z0), valCoord(seed, x2, y2, z0), - valCoord(seed, x3, y2, z0), xs), + valCoord(seed, x3, y2, z0), xs), cubicLerp(valCoord(seed, x0, y3, z0), valCoord(seed, x1, y3, z0), valCoord(seed, x2, y3, z0), - valCoord(seed, x3, y3, z0), xs), + valCoord(seed, x3, y3, z0), xs), ys), cubicLerp( cubicLerp(valCoord(seed, x0, y0, z1), valCoord(seed, x1, y0, z1), valCoord(seed, x2, y0, z1), - valCoord(seed, x3, y0, z1), xs), + valCoord(seed, x3, y0, z1), xs), cubicLerp(valCoord(seed, x0, y1, z1), valCoord(seed, x1, y1, z1), valCoord(seed, x2, y1, z1), - valCoord(seed, x3, y1, z1), xs), + valCoord(seed, x3, y1, z1), xs), cubicLerp(valCoord(seed, x0, y2, z1), valCoord(seed, x1, y2, z1), valCoord(seed, x2, y2, z1), - valCoord(seed, x3, y2, z1), xs), + valCoord(seed, x3, y2, z1), xs), cubicLerp(valCoord(seed, x0, y3, z1), valCoord(seed, x1, y3, z1), valCoord(seed, x2, y3, z1), - valCoord(seed, x3, y3, z1), xs), + valCoord(seed, x3, y3, z1), xs), ys), cubicLerp( cubicLerp(valCoord(seed, x0, y0, z2), valCoord(seed, x1, y0, z2), valCoord(seed, x2, y0, z2), - valCoord(seed, x3, y0, z2), xs), + valCoord(seed, x3, y0, z2), xs), cubicLerp(valCoord(seed, x0, y1, z2), valCoord(seed, x1, y1, z2), valCoord(seed, x2, y1, z2), - valCoord(seed, x3, y1, z2), xs), + valCoord(seed, x3, y1, z2), xs), cubicLerp(valCoord(seed, x0, y2, z2), valCoord(seed, x1, y2, z2), valCoord(seed, x2, y2, z2), - valCoord(seed, x3, y2, z2), xs), + valCoord(seed, x3, y2, z2), xs), cubicLerp(valCoord(seed, x0, y3, z2), valCoord(seed, x1, y3, z2), valCoord(seed, x2, y3, z2), - valCoord(seed, x3, y3, z2), xs), + valCoord(seed, x3, y3, z2), xs), ys), cubicLerp( cubicLerp(valCoord(seed, x0, y0, z3), valCoord(seed, x1, y0, z3), valCoord(seed, x2, y0, z3), - valCoord(seed, x3, y0, z3), xs), + valCoord(seed, x3, y0, z3), xs), cubicLerp(valCoord(seed, x0, y1, z3), valCoord(seed, x1, y1, z3), valCoord(seed, x2, y1, z3), - valCoord(seed, x3, y1, z3), xs), + valCoord(seed, x3, y1, z3), xs), cubicLerp(valCoord(seed, x0, y2, z3), valCoord(seed, x1, y2, z3), valCoord(seed, x2, y2, z3), - valCoord(seed, x3, y2, z3), xs), + valCoord(seed, x3, y2, z3), xs), cubicLerp(valCoord(seed, x0, y3, z3), valCoord(seed, x1, y3, z3), valCoord(seed, x2, y3, z3), - valCoord(seed, x3, y3, z3), xs), + valCoord(seed, x3, y3, z3), xs), ys), zs) * (1 / (1.5 * 1.5 * 1.5)); } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/value/ValueSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueSampler.java similarity index 71% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/value/ValueSampler.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueSampler.java index e79f5cf2b..fbab36d35 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/value/ValueSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueSampler.java @@ -1,54 +1,59 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.value; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.value; public class ValueSampler extends ValueStyleNoise { - public ValueSampler(int seed) { - super(seed); - } - @Override - public double getNoiseRaw(int seed, double x, double y) { + public double getNoiseRaw(long sl, double x, double y) { + int seed = (int) sl; int x0 = fastFloor(x); int y0 = fastFloor(y); - + double xs = interpHermite(x - x0); double ys = interpHermite(y - y0); - + x0 *= PRIME_X; y0 *= PRIME_Y; int x1 = x0 + PRIME_X; int y1 = y0 + PRIME_Y; - + double xf0 = lerp(valCoord(seed, x0, y0), valCoord(seed, x1, y0), xs); double xf1 = lerp(valCoord(seed, x0, y1), valCoord(seed, x1, y1), xs); - + return lerp(xf0, xf1, ys); } - + @Override - public double getNoiseRaw(int seed, double x, double y, double z) { + public double getNoiseRaw(long sl, double x, double y, double z) { + int seed = (int) sl; int x0 = fastFloor(x); int y0 = fastFloor(y); int z0 = fastFloor(z); - + double xs = interpHermite(x - x0); double ys = interpHermite(y - y0); double zs = interpHermite(z - z0); - + x0 *= PRIME_X; y0 *= PRIME_Y; z0 *= PRIME_Z; int x1 = x0 + PRIME_X; int y1 = y0 + PRIME_Y; int z1 = z0 + PRIME_Z; - + double xf00 = lerp(valCoord(seed, x0, y0, z0), valCoord(seed, x1, y0, z0), xs); double xf10 = lerp(valCoord(seed, x0, y1, z0), valCoord(seed, x1, y1, z0), xs); double xf01 = lerp(valCoord(seed, x0, y0, z1), valCoord(seed, x1, y0, z1), xs); double xf11 = lerp(valCoord(seed, x0, y1, z1), valCoord(seed, x1, y1, z1), xs); - + double yf0 = lerp(xf00, xf10, ys); double yf1 = lerp(xf01, xf11, ys); - + return lerp(yf0, yf1, zs); } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/value/ValueStyleNoise.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueStyleNoise.java similarity index 59% rename from common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/value/ValueStyleNoise.java rename to common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueStyleNoise.java index 246d77538..24ac89c8b 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/value/ValueStyleNoise.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/value/ValueStyleNoise.java @@ -1,23 +1,28 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.value; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.noise.samplers.noise.value; + +import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; -import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction; public abstract class ValueStyleNoise extends NoiseFunction { - public ValueStyleNoise(int seed) { - super(seed); - } - + protected static double valCoord(int seed, int xPrimed, int yPrimed) { int hash = hash(seed, xPrimed, yPrimed); - + hash *= hash; hash ^= hash << 19; return hash * (1 / 2147483648.0); } - + protected static double valCoord(int seed, int xPrimed, int yPrimed, int zPrimed) { int hash = hash(seed, xPrimed, yPrimed, zPrimed); - + hash *= hash; hash ^= hash << 19; return hash * (1 / 2147483648.0); diff --git a/common/addons/config-noise-function/src/main/resources/terra.addon.yml b/common/addons/config-noise-function/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..b22b0f781 --- /dev/null +++ b/common/addons/config-noise-function/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: config-noise-function +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.noise.NoiseAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/config-ore/LICENSE b/common/addons/config-ore/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/config-ore/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/config-ore/README.md b/common/addons/config-ore/README.md new file mode 100644 index 000000000..1b72835ea --- /dev/null +++ b/common/addons/config-ore/README.md @@ -0,0 +1,3 @@ +# config-ore + +Registers the default configuration for Terra Ores, `ORE`. \ No newline at end of file diff --git a/common/addons/config-ore/build.gradle.kts b/common/addons/config-ore/build.gradle.kts new file mode 100644 index 000000000..d575f43d3 --- /dev/null +++ b/common/addons/config-ore/build.gradle.kts @@ -0,0 +1,11 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("net.jafama", "com.dfsek.terra.addons.ore.lib.jafama") +} diff --git a/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreAddon.java b/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreAddon.java new file mode 100644 index 000000000..4e6f1751b --- /dev/null +++ b/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreAddon.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.ore; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class OreAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> event.getPack().registerConfigType(new OreConfigType(), addon.key("ORE"), 1)) + .failThrough(); + } +} diff --git a/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreConfigType.java b/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreConfigType.java new file mode 100644 index 000000000..2bdc87bdd --- /dev/null +++ b/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreConfigType.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.ore; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class OreConfigType implements ConfigType { + public static final TypeKey ORE_TYPE_TOKEN = new TypeKey<>() { + }; + private final OreFactory factory = new OreFactory(); + + @Override + public OreTemplate getTemplate(ConfigPack pack, Platform platform) { + return new OreTemplate(); + } + + @Override + public ConfigFactory getFactory() { + return factory; + } + + @Override + public TypeKey getTypeKey() { + return ORE_TYPE_TOKEN; + } +} diff --git a/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreFactory.java b/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreFactory.java new file mode 100644 index 000000000..9d8b1055a --- /dev/null +++ b/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreFactory.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.ore; + +import com.dfsek.terra.addons.ore.ores.VanillaOre; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.structure.Structure; + + +public class OreFactory implements ConfigFactory { + @Override + public VanillaOre build(OreTemplate config, Platform platform) { + BlockState m = config.getMaterial(); + return new VanillaOre(m, config.getSize(), config.getReplaceable(), config.doPhysics(), config.isExposed(), + config.getMaterialOverrides()); + } +} diff --git a/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreTemplate.java b/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreTemplate.java new file mode 100644 index 000000000..8bfbc82d3 --- /dev/null +++ b/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/OreTemplate.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.ore; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Description; +import com.dfsek.tectonic.api.config.template.annotations.Final; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.HashMap; +import java.util.Map; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.AbstractableTemplate; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.collection.MaterialSet; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class OreTemplate implements AbstractableTemplate { + @Value("id") + @Final + private String id; + + @Value("material") + private @Meta BlockState material; + + @Value("material-overrides") + @Default + private @Meta Map<@Meta BlockType, @Meta BlockState> materials = new HashMap<>(); + + @Value("replace") + private @Meta MaterialSet replaceable; + + @Value("physics") + @Default + private @Meta boolean physics = false; + + @Value("size") + private @Meta double size; + + @Value("exposed") + @Default + @Description("The chance that ore blocks bordering air will be exposed. 0 = 0%, 1 = 100%") + private @Meta double exposed = 1; + + public boolean doPhysics() { + return physics; + } + + public double getSize() { + return size; + } + + public BlockState getMaterial() { + return material; + } + + public MaterialSet getReplaceable() { + return replaceable; + } + + public String getID() { + return id; + } + + public Map getMaterialOverrides() { + return materials; + } + + public double isExposed() { + return exposed; + } +} diff --git a/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/ores/VanillaOre.java b/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/ores/VanillaOre.java new file mode 100644 index 000000000..a1046aea9 --- /dev/null +++ b/common/addons/config-ore/src/main/java/com/dfsek/terra/addons/ore/ores/VanillaOre.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.ore.ores; + +import net.jafama.FastMath; + +import java.util.Map; +import java.util.Random; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.collection.MaterialSet; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.WritableWorld; + + +public class VanillaOre implements Structure { + + private final BlockState material; + + private final double size; + private final MaterialSet replaceable; + private final boolean applyGravity; + private final double exposed; + private final Map materials; + + public VanillaOre(BlockState material, double size, MaterialSet replaceable, boolean applyGravity, + double exposed, Map materials) { + this.material = material; + this.size = size; + this.replaceable = replaceable; + this.applyGravity = applyGravity; + this.exposed = exposed; + this.materials = materials; + } + + @Override + public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { + int centerX = location.getX(); + int centerZ = location.getZ(); + int centerY = location.getY(); + + + float f = random.nextFloat() * (float) Math.PI; + + double d1 = centerX + 8 + FastMath.sin(f) * size / 8.0F; + double d2 = centerX + 8 - FastMath.sin(f) * size / 8.0F; + double d3 = centerZ + 8 + FastMath.cos(f) * size / 8.0F; + double d4 = centerZ + 8 - FastMath.cos(f) * size / 8.0F; + + double d5 = centerY + random.nextInt(3) - 2D; + double d6 = centerY + random.nextInt(3) - 2D; + + for(int i = 0; i < size; i++) { + float iFactor = (float) i / (float) size; + + double d10 = random.nextDouble() * size / 16.0D; + double d11 = (FastMath.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0; + double d12 = (FastMath.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0; + + int xStart = FastMath.roundToInt(FastMath.floor(d1 + (d2 - d1) * iFactor - d11 / 2.0D)); + int yStart = FastMath.roundToInt(FastMath.floor(d5 + (d6 - d5) * iFactor - d12 / 2.0D)); + int zStart = FastMath.roundToInt(FastMath.floor(d3 + (d4 - d3) * iFactor - d11 / 2.0D)); + + int xEnd = FastMath.roundToInt(FastMath.floor(d1 + (d2 - d1) * iFactor + d11 / 2.0D)); + int yEnd = FastMath.roundToInt(FastMath.floor(d5 + (d6 - d5) * iFactor + d12 / 2.0D)); + int zEnd = FastMath.roundToInt(FastMath.floor(d3 + (d4 - d3) * iFactor + d11 / 2.0D)); + + for(int x = xStart; x <= xEnd; x++) { + double d13 = (x + 0.5D - (d1 + (d2 - d1) * iFactor)) / (d11 / 2.0D); + + if(d13 * d13 < 1.0D) { + for(int y = yStart; y <= yEnd; y++) { + double d14 = (y + 0.5D - (d5 + (d6 - d5) * iFactor)) / (d12 / 2.0D); + if(d13 * d13 + d14 * d14 < 1.0D) { + for(int z = zStart; z <= zEnd; z++) { + double d15 = (z + 0.5D - (d3 + (d4 - d3) * iFactor)) / (d11 / 2.0D); + if(y >= world.getMaxHeight() || y < world.getMinHeight()) continue; + BlockType block = world.getBlockState(x, y, z).getBlockType(); + if((d13 * d13 + d14 * d14 + d15 * d15 < 1.0D) && getReplaceable().contains(block)) { + if(exposed > random.nextDouble() || !(world.getBlockState(x, y, z - 1).isAir() || + world.getBlockState(x, y, z + 1).isAir() || + world.getBlockState(x, y - 1, z).isAir() || + world.getBlockState(x, y + 1, z).isAir() || + world.getBlockState(x - 1, y, z).isAir() || + world.getBlockState(x + 1, y, z).isAir())) { + world.setBlockState(x, y, z, getMaterial(block), isApplyGravity()); + } + } + } + } + } + } + } + } + return true; + } + + public BlockState getMaterial(BlockType replace) { + return materials.getOrDefault(replace, material); + } + + public MaterialSet getReplaceable() { + return replaceable; + } + + public boolean isApplyGravity() { + return applyGravity; + } +} diff --git a/common/addons/config-ore/src/main/resources/terra.addon.yml b/common/addons/config-ore/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..60ea05e60 --- /dev/null +++ b/common/addons/config-ore/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: config-ore +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.ore.OreAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/config-palette/LICENSE b/common/addons/config-palette/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/config-palette/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/config-palette/README.md b/common/addons/config-palette/README.md new file mode 100644 index 000000000..7aa0bbe8f --- /dev/null +++ b/common/addons/config-palette/README.md @@ -0,0 +1,3 @@ +# config-palette + +Registers the default configuration for Terra Palettes, `PALETTE`. \ No newline at end of file diff --git a/common/addons/config-palette/build.gradle.kts b/common/addons/config-palette/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/config-palette/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteAddon.java b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteAddon.java new file mode 100644 index 000000000..78744e42d --- /dev/null +++ b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteAddon.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.palette; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.addons.palette.palette.PaletteLayerHolder; +import com.dfsek.terra.addons.palette.palette.PaletteLayerLoader; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class PaletteAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + event.getPack().registerConfigType(new PaletteConfigType(platform), addon.key("PALETTE"), 2); + event.getPack().applyLoader(PaletteLayerHolder.class, PaletteLayerLoader::new); + }) + .failThrough(); + } +} diff --git a/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteConfigType.java b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteConfigType.java new file mode 100644 index 000000000..9df70cb97 --- /dev/null +++ b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteConfigType.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.palette; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class PaletteConfigType implements ConfigType { + public static final TypeKey PALETTE_TYPE_TOKEN = new TypeKey<>() { + }; + private final PaletteFactory factory = new PaletteFactory(); + private final Platform platform; + + public PaletteConfigType(Platform platform) { + this.platform = platform; + } + + @Override + public PaletteTemplate getTemplate(ConfigPack pack, Platform platform) { + return new PaletteTemplate(); + } + + @Override + public ConfigFactory getFactory() { + return factory; + } + + @Override + public TypeKey getTypeKey() { + return PALETTE_TYPE_TOKEN; + } +} diff --git a/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteFactory.java b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteFactory.java new file mode 100644 index 000000000..efcfbd425 --- /dev/null +++ b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteFactory.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.palette; + +import com.dfsek.terra.addons.palette.palette.PaletteImpl; +import com.dfsek.terra.addons.palette.palette.PaletteLayerHolder; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class PaletteFactory implements ConfigFactory { + @Override + public Palette build(PaletteTemplate config, Platform platform) { + PaletteImpl palette = new PaletteImpl(config.getNoise()); + for(PaletteLayerHolder layer : config.getPalette()) { + palette.add(layer.getLayer(), layer.getSize(), layer.getSampler()); + } + return palette; + } +} diff --git a/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteTemplate.java b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteTemplate.java new file mode 100644 index 000000000..7147284d1 --- /dev/null +++ b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/PaletteTemplate.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.palette; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Final; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.List; + +import com.dfsek.terra.addons.palette.palette.PaletteLayerHolder; +import com.dfsek.terra.api.config.AbstractableTemplate; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.noise.NoiseSampler; + + +@SuppressWarnings({ "FieldMayBeFinal", "unused" }) +public class PaletteTemplate implements AbstractableTemplate { + @Value("sampler") + @Default + private @Meta NoiseSampler noise = NoiseSampler.zero(); + + @Value("id") + @Final + private String id; + + @Value("layers") + private @Meta List<@Meta PaletteLayerHolder> palette; + + public String getID() { + return id; + } + + public List getPalette() { + return palette; + } + + public NoiseSampler getNoise() { + return noise; + } +} diff --git a/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteImpl.java b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteImpl.java new file mode 100644 index 000000000..ede31d7ea --- /dev/null +++ b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteImpl.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.palette.palette; + +import java.util.ArrayList; +import java.util.List; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +/** + * A class representation of a "slice" of the world. + * Used to get a section of blocks, based on the depth at which they are found. + */ +public class PaletteImpl implements Palette { + private final List pallet = new ArrayList<>(); + private final NoiseSampler sampler; + + public PaletteImpl(NoiseSampler sampler) { + this.sampler = sampler; + } + + public Palette add(ProbabilityCollection m, int layers, NoiseSampler sampler) { + for(int i = 0; i < layers; i++) { + pallet.add(new PaletteLayer(m, sampler)); + } + return this; + } + + @Override + public BlockState get(int layer, double x, double y, double z, long seed) { + PaletteLayer paletteLayer; + if(layer > this.getSize()) paletteLayer = this.getLayers().get(this.getLayers().size() - 1); + else { + List pl = getLayers(); + if(layer >= pl.size()) paletteLayer = pl.get(pl.size() - 1); + else paletteLayer = pl.get(layer); + } + NoiseSampler paletteSampler = paletteLayer.getSampler(); + return paletteLayer.get(paletteSampler == null ? sampler : paletteSampler, x, y, z, seed); + } + + + public int getSize() { + return pallet.size(); + } + + public List getLayers() { + return pallet; + } + + /** + * Class representation of a layer of a BlockPalette. + */ + public static class PaletteLayer { + private final NoiseSampler sampler; + private final ProbabilityCollection collection; + + /** + * Constructs a PaletteLayerHolder with a ProbabilityCollection of materials and a number of layers. + * + * @param type The collection of materials to choose from. + * @param sampler Noise sampler to use + */ + public PaletteLayer(ProbabilityCollection type, NoiseSampler sampler) { + this.sampler = sampler; + this.collection = type; + } + + public BlockState get(NoiseSampler random, double x, double y, double z, long seed) { + return this.collection.get(random, x, y, z, seed); + } + + public NoiseSampler getSampler() { + return sampler; + } + + } +} diff --git a/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteLayerHolder.java b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteLayerHolder.java new file mode 100644 index 000000000..30ffb5e81 --- /dev/null +++ b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteLayerHolder.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.palette.palette; + +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class PaletteLayerHolder { + private final ProbabilityCollection layer; + private final NoiseSampler sampler; + private final int size; + + public PaletteLayerHolder(@NotNull ProbabilityCollection layer, NoiseSampler sampler, int size) { + this.layer = layer; + this.sampler = sampler; + this.size = size; + } + + @NotNull + public ProbabilityCollection getLayer() { + return layer; + } + + public int getSize() { + return size; + } + + public NoiseSampler getSampler() { + return sampler; + } +} diff --git a/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteLayerLoader.java b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteLayerLoader.java new file mode 100644 index 000000000..f0ad5cbd1 --- /dev/null +++ b/common/addons/config-palette/src/main/java/com/dfsek/terra/addons/palette/palette/PaletteLayerLoader.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.palette.palette; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class PaletteLayerLoader implements ObjectTemplate { + @Value("materials") + private ProbabilityCollection collection; + + @Value("sampler") + @Default + private NoiseSampler sampler = null; + + @Value("layers") + private int layers; + + @Override + public PaletteLayerHolder get() { + return new PaletteLayerHolder(collection, sampler, layers); + } +} diff --git a/common/addons/config-palette/src/main/resources/terra.addon.yml b/common/addons/config-palette/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..255a58048 --- /dev/null +++ b/common/addons/config-palette/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: config-palette +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.palette.PaletteAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/config-structure/LICENSE b/common/addons/config-structure/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/config-structure/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/config-structure/README.md b/common/addons/config-structure/README.md new file mode 100644 index 000000000..60e62972a --- /dev/null +++ b/common/addons/config-structure/README.md @@ -0,0 +1,3 @@ +# config-structure + +Registers the default configuration for Terra Structures, `STRUCTURE`. \ No newline at end of file diff --git a/common/addons/config-structure/build.gradle.kts b/common/addons/config-structure/build.gradle.kts new file mode 100644 index 000000000..dad8fff7d --- /dev/null +++ b/common/addons/config-structure/build.gradle.kts @@ -0,0 +1,13 @@ +version = version("1.0.0") + +dependencies { + api("com.googlecode.json-simple:json-simple:1.1.1") + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("net.jafama", "com.dfsek.terra.addons.structure.lib.jafama") +} diff --git a/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/BiomeStructures.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/BiomeStructures.java new file mode 100644 index 000000000..16a0e84b6 --- /dev/null +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/BiomeStructures.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure; + +import java.util.Set; + +import com.dfsek.terra.api.properties.Properties; +import com.dfsek.terra.api.structure.configured.ConfiguredStructure; + + +public class BiomeStructures implements Properties { + private final Set structures; + + public BiomeStructures(Set structures) { + this.structures = structures; + } + + public Set getStructures() { + return structures; + } +} diff --git a/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/BiomeStructuresTemplate.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/BiomeStructuresTemplate.java new file mode 100644 index 000000000..02a656695 --- /dev/null +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/BiomeStructuresTemplate.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.Collections; +import java.util.Set; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.configured.ConfiguredStructure; + + +@SuppressWarnings("FieldMayBeFinal") +public class BiomeStructuresTemplate implements ObjectTemplate { + @Value("structures") + @Default + private @Meta Set<@Meta ConfiguredStructure> structures = Collections.emptySet(); + + @Override + public BiomeStructures get() { + return new BiomeStructures(structures); + } +} diff --git a/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureAddon.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureAddon.java new file mode 100644 index 000000000..d578b7721 --- /dev/null +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureAddon.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class StructureAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> event.getPack().registerConfigType(new StructureConfigType(), addon.key("STRUCTURE"), 2)) + .failThrough(); + } +} diff --git a/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureConfigType.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureConfigType.java new file mode 100644 index 000000000..a6a4c5f7d --- /dev/null +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureConfigType.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.structure.configured.ConfiguredStructure; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class StructureConfigType implements ConfigType { + public static final TypeKey CONFIGURED_STRUCTURE_TYPE_KEY = new TypeKey<>() { + }; + private final ConfigFactory factory = new StructureFactory(); + + @Override + public StructureTemplate getTemplate(ConfigPack pack, Platform platform) { + return new StructureTemplate(); + } + + @Override + public ConfigFactory getFactory() { + return factory; + } + + @Override + public TypeKey getTypeKey() { + return CONFIGURED_STRUCTURE_TYPE_KEY; + } +} diff --git a/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureFactory.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureFactory.java new file mode 100644 index 000000000..8b0a8f05e --- /dev/null +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureFactory.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.structure.configured.ConfiguredStructure; + + +public class StructureFactory implements ConfigFactory { + @Override + public ConfiguredStructure build(StructureTemplate config, Platform platform) { + return new TerraStructure(config.getStructures(), config.getY(), config.getSpawn(), config.getID()); + } +} diff --git a/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureTemplate.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureTemplate.java new file mode 100644 index 000000000..48dd223df --- /dev/null +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/StructureTemplate.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure; + +import com.dfsek.tectonic.api.config.template.annotations.Final; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.api.config.AbstractableTemplate; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.structure.StructureSpawn; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class StructureTemplate implements AbstractableTemplate { + @Value("id") + @Final + private String id; + + @Value("scripts") + private @Meta ProbabilityCollection<@Meta Structure> structure; + + @Value("spawn.start") + private @Meta Range y; + + @Value("spawn") + private @Meta StructureSpawn spawn; + + public String getID() { + return id; + } + + public ProbabilityCollection getStructures() { + return structure; + } + + public Range getY() { + return y; + } + + public StructureSpawn getSpawn() { + return spawn; + } +} diff --git a/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/TerraStructure.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/TerraStructure.java new file mode 100644 index 000000000..cef38f2b9 --- /dev/null +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/TerraStructure.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure; + +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.structure.StructureSpawn; +import com.dfsek.terra.api.structure.configured.ConfiguredStructure; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +public class TerraStructure implements ConfiguredStructure { + private final ProbabilityCollection structure; + private final Range spawnStart; + private final StructureSpawn spawn; + + private final String id; + + public TerraStructure(ProbabilityCollection structures, Range spawnStart, StructureSpawn spawn, String id) { + this.structure = structures; + this.spawnStart = spawnStart; + this.spawn = spawn; + this.id = id; + } + + @Override + public ProbabilityCollection getStructure() { + return structure; + } + + @Override + public Range getSpawnStart() { + return spawnStart; + } + + @Override + public StructureSpawn getSpawn() { + return spawn; + } + + @Override + public String getID() { + return id; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/Entry.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/Entry.java similarity index 67% rename from common/src/main/java/com/dfsek/terra/api/structures/loot/Entry.java rename to common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/Entry.java index 81c48aab1..ab8be10e2 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/Entry.java +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/Entry.java @@ -1,50 +1,58 @@ -package com.dfsek.terra.api.structures.loot; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure.structures.loot; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.api.structures.loot.functions.AmountFunction; -import com.dfsek.terra.api.structures.loot.functions.DamageFunction; -import com.dfsek.terra.api.structures.loot.functions.EnchantFunction; -import com.dfsek.terra.api.structures.loot.functions.LootFunction; -import com.dfsek.terra.api.util.GlueList; import net.jafama.FastMath; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import java.util.ArrayList; import java.util.List; import java.util.Random; +import com.dfsek.terra.addons.structure.structures.loot.functions.AmountFunction; +import com.dfsek.terra.addons.structure.structures.loot.functions.DamageFunction; +import com.dfsek.terra.addons.structure.structures.loot.functions.EnchantFunction; +import com.dfsek.terra.addons.structure.structures.loot.functions.LootFunction; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.ItemStack; + + /** * Representation of a single item entry within a Loot Table pool. */ public class Entry { private final Item item; private final long weight; - private final List functions = new GlueList<>(); - + private final List functions = new ArrayList<>(); + /** * Instantiates an Entry from a JSON representation. * * @param entry The JSON Object to instantiate from. */ - public Entry(JSONObject entry, TerraPlugin main) { + public Entry(JSONObject entry, Platform platform) { String id = entry.get("name").toString(); - this.item = main.getItemHandle().createItem(id); - + this.item = platform.getItemHandle().createItem(id); + long weight1; try { weight1 = (long) entry.get("weight"); } catch(NullPointerException e) { weight1 = 1; } - + this.weight = weight1; if(entry.containsKey("functions")) { for(Object function : (JSONArray) entry.get("functions")) { switch(((String) ((JSONObject) function).get("function"))) { - case "minecraft:set_count": - case "set_count": + case "minecraft:set_count", "set_count" -> { Object loot = ((JSONObject) function).get("count"); long max, min; if(loot instanceof Long) { @@ -55,31 +63,31 @@ public class Entry { min = (long) ((JSONObject) loot).get("min"); } functions.add(new AmountFunction(FastMath.toIntExact(min), FastMath.toIntExact(max))); - break; - case "minecraft:set_damage": - case "set_damage": + } + case "minecraft:set_damage", "set_damage" -> { long maxDamage = (long) ((JSONObject) ((JSONObject) function).get("damage")).get("max"); long minDamage = (long) ((JSONObject) ((JSONObject) function).get("damage")).get("min"); functions.add(new DamageFunction(FastMath.toIntExact(minDamage), FastMath.toIntExact(maxDamage))); - break; - case "minecraft:enchant_with_levels": - case "enchant_with_levels": + } + case "minecraft:enchant_with_levels", "enchant_with_levels" -> { long maxEnchant = (long) ((JSONObject) ((JSONObject) function).get("levels")).get("max"); long minEnchant = (long) ((JSONObject) ((JSONObject) function).get("levels")).get("min"); JSONArray disabled = null; if(((JSONObject) function).containsKey("disabled_enchants")) disabled = (JSONArray) ((JSONObject) function).get("disabled_enchants"); - functions.add(new EnchantFunction(FastMath.toIntExact(minEnchant), FastMath.toIntExact(maxEnchant), disabled, main)); - break; + functions.add( + new EnchantFunction(FastMath.toIntExact(minEnchant), FastMath.toIntExact(maxEnchant), disabled, platform)); + } } } } } - + /** * Fetches a single ItemStack from the Entry, applying all functions to it. * * @param r The Random instance to apply functions with + * * @return ItemStack - The ItemStack with all functions applied. */ public ItemStack getItem(Random r) { @@ -89,7 +97,7 @@ public class Entry { } return item; } - + /** * Gets the weight attribute of the Entry. * diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/LootTable.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/LootTableImpl.java similarity index 70% rename from common/src/main/java/com/dfsek/terra/api/structures/loot/LootTable.java rename to common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/LootTableImpl.java index 886d72178..c817c2d2d 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/LootTable.java +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/LootTableImpl.java @@ -1,58 +1,49 @@ -package com.dfsek.terra.api.structures.loot; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure.structures.loot; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.inventory.Inventory; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.api.util.GlueList; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; +import java.util.ArrayList; import java.util.List; import java.util.Random; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.inventory.Inventory; +import com.dfsek.terra.api.inventory.ItemStack; + + /** * Class representation of a Loot Table to populate chest loot. */ -public class LootTable { - private final List pools = new GlueList<>(); - +public class LootTableImpl implements com.dfsek.terra.api.structure.LootTable { + private final List pools = new ArrayList<>(); + /** * Instantiates a LootTable from a JSON String. * * @param json The JSON String representing the loot table. + * * @throws ParseException if malformed JSON is passed. */ - public LootTable(String json, TerraPlugin main) throws ParseException { + public LootTableImpl(String json, Platform platform) throws ParseException { JSONParser jsonParser = new JSONParser(); Object tableJSON = jsonParser.parse(json); JSONArray poolArray = (JSONArray) ((JSONObject) tableJSON).get("pools"); for(Object pool : poolArray) { - pools.add(new Pool((JSONObject) pool, main)); + pools.add(new Pool((JSONObject) pool, platform)); } } - - /** - * Fetches a list of ItemStacks from the loot table using the given Random instance. - * - * @param r The Random instance to use. - * @return List<ItemStack> - The list of loot fetched. - */ - public List getLoot(Random r) { - List itemList = new GlueList<>(); - for(Pool pool : pools) { - itemList.addAll(pool.getItems(r)); - } - return itemList; - } - - /** - * Fills an Inventory with loot. - * - * @param i The Inventory to fill. - * @param r The The Random instance to use. - */ + + @Override public void fillInventory(Inventory i, Random r) { List loot = getLoot(r); for(ItemStack stack : loot) { @@ -77,4 +68,13 @@ public class LootTable { } } } + + @Override + public List getLoot(Random r) { + List itemList = new ArrayList<>(); + for(Pool pool : pools) { + itemList.addAll(pool.getItems(r)); + } + return itemList; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/Pool.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/Pool.java similarity index 69% rename from common/src/main/java/com/dfsek/terra/api/structures/loot/Pool.java rename to common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/Pool.java index e01a25bdb..a807cb4a1 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/Pool.java +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/Pool.java @@ -1,16 +1,25 @@ -package com.dfsek.terra.api.structures.loot; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure.structures.loot; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.api.util.GlueList; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; import net.jafama.FastMath; import org.json.simple.JSONArray; import org.json.simple.JSONObject; +import java.util.ArrayList; import java.util.List; import java.util.Random; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.inventory.ItemStack; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + /** * Representation of a Loot Table pool, or a set of items to be fetched independently. */ @@ -18,13 +27,13 @@ public class Pool { private final int max; private final int min; private final ProbabilityCollection entries; - + /** * Instantiates a Pool from a JSON representation. * * @param pool The JSON Object to instantiate from. */ - public Pool(JSONObject pool, TerraPlugin main) { + public Pool(JSONObject pool, Platform platform) { entries = new ProbabilityCollection<>(); Object amount = pool.get("rolls"); if(amount instanceof Long) { @@ -34,23 +43,24 @@ public class Pool { max = FastMath.toIntExact((Long) ((JSONObject) amount).get("max")); min = FastMath.toIntExact((Long) ((JSONObject) amount).get("min")); } - + for(Object entryJSON : (JSONArray) pool.get("entries")) { - Entry entry = new Entry((JSONObject) entryJSON, main); + Entry entry = new Entry((JSONObject) entryJSON, platform); entries.add(entry, FastMath.toIntExact(entry.getWeight())); } } - + /** * Fetches a list of items from the pool using the provided Random instance. * * @param r The Random instance to use. + * * @return List<ItemStack> - The list of items fetched. */ public List getItems(Random r) { - + int rolls = r.nextInt(max - min + 1) + min; - List items = new GlueList<>(); + List items = new ArrayList<>(); for(int i = 0; i < rolls; i++) { items.add(entries.get(r).getItem(r)); } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/AmountFunction.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/AmountFunction.java similarity index 70% rename from common/src/main/java/com/dfsek/terra/api/structures/loot/functions/AmountFunction.java rename to common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/AmountFunction.java index f83498fec..8fd59a5ee 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/AmountFunction.java +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/AmountFunction.java @@ -1,17 +1,25 @@ -package com.dfsek.terra.api.structures.loot.functions; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ +package com.dfsek.terra.addons.structure.structures.loot.functions; -import com.dfsek.terra.api.platform.inventory.ItemStack; import java.util.Random; +import com.dfsek.terra.api.inventory.ItemStack; + + /** * Loot LootFunction fot setting the amount of an item. */ public class AmountFunction implements LootFunction { private final int max; private final int min; - + /** * Instantiates an AmountFunction. * @@ -22,12 +30,13 @@ public class AmountFunction implements LootFunction { this.min = min; this.max = max; } - + /** * Applies the function to an ItemStack. * * @param original The ItemStack on which to apply the function. * @param r The Random instance to use. + * * @return - ItemStack - The mutated ItemStack. */ @Override diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/DamageFunction.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/DamageFunction.java similarity index 74% rename from common/src/main/java/com/dfsek/terra/api/structures/loot/functions/DamageFunction.java rename to common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/DamageFunction.java index 517777db0..09eda7417 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/DamageFunction.java +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/DamageFunction.java @@ -1,18 +1,26 @@ -package com.dfsek.terra.api.structures.loot.functions; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.api.platform.inventory.item.Damageable; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; +package com.dfsek.terra.addons.structure.structures.loot.functions; import java.util.Random; +import com.dfsek.terra.api.inventory.ItemStack; +import com.dfsek.terra.api.inventory.item.Damageable; +import com.dfsek.terra.api.inventory.item.ItemMeta; + + /** * Loot LootFunction for setting the damage on items in Loot Tables */ public class DamageFunction implements LootFunction { private final int max; private final int min; - + /** * Instantiates a DamageFunction. * @@ -23,12 +31,13 @@ public class DamageFunction implements LootFunction { this.min = min; this.max = max; } - + /** * Applies the function to an ItemStack. * * @param original The ItemStack on which to apply the function. * @param r The Random instance to use. + * * @return - ItemStack - The mutated ItemStack. */ @Override diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/EnchantFunction.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/EnchantFunction.java similarity index 60% rename from common/src/main/java/com/dfsek/terra/api/structures/loot/functions/EnchantFunction.java rename to common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/EnchantFunction.java index 50818d871..6f5b4d62d 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/EnchantFunction.java +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/EnchantFunction.java @@ -1,45 +1,58 @@ -package com.dfsek.terra.api.structures.loot.functions; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.structure.structures.loot.functions; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; -import com.dfsek.terra.api.util.GlueList; import net.jafama.FastMath; import org.json.simple.JSONArray; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.inventory.ItemStack; +import com.dfsek.terra.api.inventory.item.Enchantment; +import com.dfsek.terra.api.inventory.item.ItemMeta; + + public class EnchantFunction implements LootFunction { + private static final Logger LOGGER = LoggerFactory.getLogger(EnchantFunction.class); private final int min; private final int max; private final JSONArray disabled; - private final TerraPlugin main; - - - public EnchantFunction(int min, int max, JSONArray disabled, TerraPlugin main) { + private final Platform platform; + + + public EnchantFunction(int min, int max, JSONArray disabled, Platform platform) { this.max = max; this.min = min; this.disabled = disabled; - this.main = main; + this.platform = platform; } - + /** * Applies the function to an ItemStack. * * @param original The ItemStack on which to apply the function. * @param r The Random instance to use. + * * @return - ItemStack - The mutated ItemStack. */ @Override public ItemStack apply(ItemStack original, Random r) { if(original.getItemMeta() == null) return original; - + double enchant = (r.nextDouble() * (max - min)) + min; - List possible = new GlueList<>(); - for(Enchantment ench : main.getItemHandle().getEnchantments()) { + List possible = new ArrayList<>(); + for(Enchantment ench : platform.getItemHandle().getEnchantments()) { if(ench.canEnchantItem(original) && (disabled == null || !this.disabled.contains(ench.getID()))) { possible.add(ench); } @@ -57,7 +70,10 @@ public class EnchantFunction implements LootFunction { try { meta.addEnchantment(chosen, FastMath.max(lvl, 1)); } catch(IllegalArgumentException e) { - main.logger().warning("Attempted to enchant " + original.getType() + " with " + chosen + " at level " + FastMath.max(lvl, 1) + ", but an unexpected exception occurred! Usually this is caused by a misbehaving enchantment plugin."); + LOGGER.warn( + "Attempted to enchant {} with {} at level {}, but an unexpected exception occurred! Usually this is caused by a " + + "misbehaving enchantment plugin.", + original.getType(), chosen, FastMath.max(lvl, 1)); } } original.setItemMeta(meta); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/LootFunction.java b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/LootFunction.java similarity index 54% rename from common/src/main/java/com/dfsek/terra/api/structures/loot/functions/LootFunction.java rename to common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/LootFunction.java index 5b882c830..ebe0fd550 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/loot/functions/LootFunction.java +++ b/common/addons/config-structure/src/main/java/com/dfsek/terra/addons/structure/structures/loot/functions/LootFunction.java @@ -1,10 +1,18 @@ -package com.dfsek.terra.api.structures.loot.functions; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ +package com.dfsek.terra.addons.structure.structures.loot.functions; -import com.dfsek.terra.api.platform.inventory.ItemStack; import java.util.Random; +import com.dfsek.terra.api.inventory.ItemStack; + + /** * Interface for mutating items in Loot Tables. */ @@ -14,6 +22,7 @@ public interface LootFunction { * * @param original The ItemStack on which to apply the function. * @param r The Random instance to use. + * * @return - ItemStack - The mutated ItemStack. */ ItemStack apply(ItemStack original, Random r); diff --git a/common/addons/config-structure/src/main/resources/terra.addon.yml b/common/addons/config-structure/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..ad31e3641 --- /dev/null +++ b/common/addons/config-structure/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: config-structure +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.structure.StructureAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/generation-stage-feature/LICENSE b/common/addons/generation-stage-feature/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/generation-stage-feature/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/generation-stage-feature/build.gradle.kts b/common/addons/generation-stage-feature/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/generation-stage-feature/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationAddon.java b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationAddon.java new file mode 100644 index 000000000..c3db72aac --- /dev/null +++ b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationAddon.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.generation.feature; + +import com.dfsek.tectonic.api.config.template.dynamic.DynamicTemplate; +import com.dfsek.tectonic.api.config.template.dynamic.DynamicValue; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +import com.dfsek.terra.addons.generation.feature.config.BiomeFeatures; +import com.dfsek.terra.addons.generation.feature.config.FeatureStageTemplate; +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.structure.feature.Feature; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; + + +public class FeatureGenerationAddon implements AddonInitializer { + public static final TypeKey>> STAGE_TYPE_KEY = new TypeKey<>() { + }; + + public static final TypeKey<@Meta List<@Meta Feature>> FEATURE_LIST_TYPE_KEY = new TypeKey<>() { + }; + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @SuppressWarnings("unchecked") + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> event.getPack() + .getOrCreateRegistry(STAGE_TYPE_KEY) + .register(addon.key("FEATURE"), () -> new FeatureStageTemplate(platform))) + .failThrough(); + + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigurationLoadEvent.class) + .then(event -> { + if(event.is(Biome.class)) { + DynamicTemplate.Builder templateBuilder = DynamicTemplate.builder(); + + List featureGenerationStages = new ArrayList<>(); + event.getPack().getStages().forEach(stage -> { + if(stage instanceof FeatureGenerationStage featureGenerationStage) { + featureGenerationStages.add(featureGenerationStage); + templateBuilder + .value(featureGenerationStage.getID(), + DynamicValue + .builder("features." + featureGenerationStage.getID(), List.class) + .annotatedType(FEATURE_LIST_TYPE_KEY.getAnnotatedType()) + .setDefault(Collections.emptyList()) + .build()); + } + }); + + DynamicTemplate template = event.load(templateBuilder.build()); + + Map> features = new HashMap<>(); + + featureGenerationStages.forEach(stage -> features.put(stage, template.get(stage.getID(), List.class))); + + event.getLoadedObject(Biome.class).getContext().put(new BiomeFeatures(features)); + } + }) + .failThrough(); + } +} diff --git a/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationStage.java b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationStage.java new file mode 100644 index 000000000..c60ecc6aa --- /dev/null +++ b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationStage.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.generation.feature; + +import java.util.Collections; +import java.util.Random; + +import com.dfsek.terra.addons.generation.feature.config.BiomeFeatures; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.registry.key.StringIdentifiable; +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.WritableWorld; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; +import com.dfsek.terra.api.world.chunk.generation.util.Column; + + +public class FeatureGenerationStage implements GenerationStage, StringIdentifiable { + private final Platform platform; + + private final String id; + + private final String profile; + + public FeatureGenerationStage(Platform platform, String id) { + this.platform = platform; + this.id = id; + this.profile = "feature_stage:" + id; + } + + @Override + @SuppressWarnings("try") + public void populate(ProtoWorld world) { + platform.getProfiler().push(profile); + int cx = world.centerChunkX() << 4; + int cz = world.centerChunkZ() << 4; + long seed = world.getSeed(); + for(int x = 0; x < 16; x++) { + for(int z = 0; z < 16; z++) { + int tx = cx + x; + int tz = cz + z; + Column column = world.column(tx, tz); + long coordinateSeed = (seed * 31 + tx) * 31 + tz; + + world.getBiomeProvider() + .getBiome(tx, 0, tz, seed) + .getContext() + .get(BiomeFeatures.class) + .getFeatures() + .getOrDefault(this, Collections.emptyList()) + .forEach(feature -> { + platform.getProfiler().push(feature.getID()); + if(feature.getDistributor().matches(tx, tz, seed)) { + feature.getLocator() + .getSuitableCoordinates(column) + .forEach(y -> + feature.getStructure(world, tx, y, tz) + .generate(Vector3Int.of(tx, y, tz), + world, + new Random(coordinateSeed * 31 + y), + Rotation.NONE) + ); + } + platform.getProfiler().pop(feature.getID()); + }); + } + } + platform.getProfiler().pop(profile); + } + + @Override + public String getID() { + return id; + } +} diff --git a/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/config/BiomeFeatures.java b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/config/BiomeFeatures.java new file mode 100644 index 000000000..473b7f782 --- /dev/null +++ b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/config/BiomeFeatures.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.generation.feature.config; + +import java.util.List; +import java.util.Map; + +import com.dfsek.terra.addons.generation.feature.FeatureGenerationStage; +import com.dfsek.terra.api.properties.Properties; +import com.dfsek.terra.api.structure.feature.Feature; + + +public class BiomeFeatures implements Properties { + private final Map> features; + + public BiomeFeatures(Map> features) { + this.features = features; + } + + public Map> getFeatures() { + return features; + } +} diff --git a/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/config/FeatureStageTemplate.java b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/config/FeatureStageTemplate.java new file mode 100644 index 000000000..1663ceed8 --- /dev/null +++ b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/config/FeatureStageTemplate.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.addons.generation.feature.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import com.dfsek.terra.addons.generation.feature.FeatureGenerationStage; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; + + +public class FeatureStageTemplate implements ObjectTemplate { + private final Platform platform; + @Value("id") + private String id; + + public FeatureStageTemplate(Platform platform) { this.platform = platform; } + + + @Override + public FeatureGenerationStage get() { + return new FeatureGenerationStage(platform, id); + } +} diff --git a/common/addons/generation-stage-feature/src/main/resources/terra.addon.yml b/common/addons/generation-stage-feature/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..640aa8aa3 --- /dev/null +++ b/common/addons/generation-stage-feature/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: generation-stage-feature +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.generation.feature.FeatureGenerationAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/generation-stage-structure/LICENSE b/common/addons/generation-stage-structure/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/generation-stage-structure/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/generation-stage-structure/build.gradle.kts b/common/addons/generation-stage-structure/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/generation-stage-structure/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/StructureGenerationAddon.java b/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/StructureGenerationAddon.java new file mode 100644 index 000000000..3bf03ec6f --- /dev/null +++ b/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/StructureGenerationAddon.java @@ -0,0 +1,43 @@ +package com.dfsek.terra.addons.generation.structure; + +import com.dfsek.terra.addons.generation.structure.config.BiomeStructuresTemplate; +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.api.world.chunk.generation.util.provider.GenerationStageProvider; + + +public class StructureGenerationAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> event.getPack() + .getOrCreateRegistry(GenerationStageProvider.class) + .register(addon.key("STRUCTURE"), pack -> new StructureGenerationStage(platform))) + .failThrough(); + + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigurationLoadEvent.class) + .then(event -> { + if(event.is(Biome.class)) { + event.getLoadedObject(Biome.class).getContext().put(event.load(new BiomeStructuresTemplate()).get()); + } + }) + .failThrough(); + + } +} diff --git a/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/StructureGenerationStage.java b/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/StructureGenerationStage.java new file mode 100644 index 000000000..07d9e7128 --- /dev/null +++ b/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/StructureGenerationStage.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.addons.generation.structure; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; + + +public class StructureGenerationStage implements GenerationStage { + private final Platform platform; + + public StructureGenerationStage(Platform platform) { this.platform = platform; } + + @Override + public void populate(ProtoWorld world) { + + } +} diff --git a/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/config/BiomeStructures.java b/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/config/BiomeStructures.java new file mode 100644 index 000000000..3a3fc4242 --- /dev/null +++ b/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/config/BiomeStructures.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.addons.generation.structure.config; + +import java.util.List; + +import com.dfsek.terra.api.properties.Properties; +import com.dfsek.terra.api.structure.configured.ConfiguredStructure; + + +public class BiomeStructures implements Properties { + private final List structures; + + public BiomeStructures(List structures) { this.structures = structures; } + + public List getStructures() { + return structures; + } +} diff --git a/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/config/BiomeStructuresTemplate.java b/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/config/BiomeStructuresTemplate.java new file mode 100644 index 000000000..64f65a018 --- /dev/null +++ b/common/addons/generation-stage-structure/src/main/java/com/dfsek/terra/addons/generation/structure/config/BiomeStructuresTemplate.java @@ -0,0 +1,23 @@ +package com.dfsek.terra.addons.generation.structure.config; + +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.util.Collections; +import java.util.List; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.structure.configured.ConfiguredStructure; + + +public class BiomeStructuresTemplate implements ObjectTemplate { + @Value("features") + @Default + private @Meta List<@Meta ConfiguredStructure> features = Collections.emptyList(); + + @Override + public BiomeStructures get() { + return new BiomeStructures(features); + } +} diff --git a/common/addons/generation-stage-structure/src/main/resources/terra.addon.yml b/common/addons/generation-stage-structure/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..2d361cf3d --- /dev/null +++ b/common/addons/generation-stage-structure/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: generation-stage-structure +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.generation.structure.StructureGenerationAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/language-yaml/LICENSE b/common/addons/language-yaml/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/language-yaml/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/language-yaml/README.md b/common/addons/language-yaml/README.md new file mode 100644 index 000000000..a8c94a331 --- /dev/null +++ b/common/addons/language-yaml/README.md @@ -0,0 +1,3 @@ +# language-yaml + +Allows `*.yml` files to be loaded as Terra configurations. \ No newline at end of file diff --git a/common/addons/language-yaml/build.gradle.kts b/common/addons/language-yaml/build.gradle.kts new file mode 100644 index 000000000..bb180dae9 --- /dev/null +++ b/common/addons/language-yaml/build.gradle.kts @@ -0,0 +1,6 @@ +version = version("1.0.0") + +dependencies { + implementation("com.dfsek.tectonic:yaml:${Versions.Libraries.tectonic}") + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/language-yaml/src/main/java/com/dfsek/terra/addons/yaml/YamlAddon.java b/common/addons/language-yaml/src/main/java/com/dfsek/terra/addons/yaml/YamlAddon.java new file mode 100644 index 000000000..dc5772dc3 --- /dev/null +++ b/common/addons/language-yaml/src/main/java/com/dfsek/terra/addons/yaml/YamlAddon.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.yaml; + +import com.dfsek.tectonic.yaml.YamlConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.ConfigurationDiscoveryEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class YamlAddon implements AddonInitializer { + + private static final Logger LOGGER = LoggerFactory.getLogger(YamlAddon.class); + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigurationDiscoveryEvent.class) + .then(event -> event.getLoader().open("", ".yml").thenEntries(entries -> entries.forEach(entry -> { + LOGGER.debug("Discovered config {}", entry.getKey()); + event.register(entry.getKey(), new YamlConfiguration(entry.getValue(), entry.getKey())); + })).close()) + .failThrough(); + } +} diff --git a/common/addons/language-yaml/src/main/resources/terra.addon.yml b/common/addons/language-yaml/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..2b3d1d50b --- /dev/null +++ b/common/addons/language-yaml/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: language-yaml +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.yaml.YamlAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/manifest-addon-loader/LICENSE b/common/addons/manifest-addon-loader/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/manifest-addon-loader/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/manifest-addon-loader/build.gradle.kts b/common/addons/manifest-addon-loader/build.gradle.kts new file mode 100644 index 000000000..6a5b6f54e --- /dev/null +++ b/common/addons/manifest-addon-loader/build.gradle.kts @@ -0,0 +1,14 @@ +version = version("1.0.0") + +dependencies { + api("commons-io:commons-io:2.7") + implementation("com.dfsek.tectonic:yaml:${Versions.Libraries.tectonic}") +} + +tasks.withType { + manifest { + attributes("Terra-Bootstrap-Addon-Entry-Point" to "com.dfsek.terra.addons.manifest.impl.ManifestAddonLoader") + } +} + +project.extra.set("bootstrap", true) \ No newline at end of file diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/api/AddonInitializer.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/api/AddonInitializer.java new file mode 100644 index 000000000..e9b596996 --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/api/AddonInitializer.java @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.api; + + +public interface AddonInitializer { + void initialize(); +} diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddon.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddon.java new file mode 100644 index 000000000..a0c23f284 --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddon.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.impl; + +import ca.solostudios.strata.version.Version; +import ca.solostudios.strata.version.VersionRange; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.addons.manifest.impl.config.AddonManifest; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.inject.Injector; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class ManifestAddon implements BaseAddon { + private static final Logger logger = LoggerFactory.getLogger(ManifestAddon.class); + private final AddonManifest manifest; + private final List initializers; + @Inject + private Platform platform; + + public ManifestAddon(AddonManifest manifest, List initializers) { + this.manifest = manifest; + this.initializers = initializers; + } + + public AddonManifest getManifest() { + return manifest; + } + + @Override + public String getID() { + return manifest.getID(); + } + + public void initialize() { + Injector addonInjector = Injector.get(this); + addonInjector.addExplicitTarget(BaseAddon.class); + + Injector platformInjector = Injector.get(platform); + platformInjector.addExplicitTarget(Platform.class); + + logger.debug("Initializing addon {}", getID()); + + initializers.forEach(initializer -> { + Injector loggerInjector = Injector.get(LoggerFactory.getLogger(initializer.getClass())); + loggerInjector.addExplicitTarget(Logger.class); + + logger.debug("Invoking entry point {}", initializer.getClass()); + addonInjector.inject(initializer); + platformInjector.inject(initializer); + loggerInjector.inject(initializer); + initializer.initialize(); + }); + } + + @Override + public Map getDependencies() { + return manifest.getDependencies(); + } + + @Override + public Version getVersion() { + return manifest.getVersion(); + } +} diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddonClassLoader.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddonClassLoader.java new file mode 100644 index 000000000..6a2923a3b --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddonClassLoader.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.impl; + +import java.net.URL; +import java.net.URLClassLoader; + + +public class ManifestAddonClassLoader extends URLClassLoader { + static { + ClassLoader.registerAsParallelCapable(); + } + + public ManifestAddonClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } +} diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddonLoader.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddonLoader.java new file mode 100644 index 000000000..00a54a226 --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/ManifestAddonLoader.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.impl; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.version.Version; +import ca.solostudios.strata.version.VersionRange; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.yaml.YamlConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.nio.file.FileVisitOption; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.addons.manifest.impl.config.AddonManifest; +import com.dfsek.terra.addons.manifest.impl.config.WebsiteConfig; +import com.dfsek.terra.addons.manifest.impl.config.loaders.VersionLoader; +import com.dfsek.terra.addons.manifest.impl.config.loaders.VersionRangeLoader; +import com.dfsek.terra.addons.manifest.impl.exception.AddonException; +import com.dfsek.terra.addons.manifest.impl.exception.ManifestException; +import com.dfsek.terra.addons.manifest.impl.exception.ManifestNotPresentException; +import com.dfsek.terra.api.addon.bootstrap.BootstrapAddonClassLoader; +import com.dfsek.terra.api.addon.bootstrap.BootstrapBaseAddon; + + +public class ManifestAddonLoader implements BootstrapBaseAddon { + private static final Logger logger = LoggerFactory.getLogger(ManifestAddonLoader.class); + private static final Version VERSION = Versions.getVersion(1, 0, 0); + + private final ConfigLoader manifestLoader = new ConfigLoader() + .registerLoader(Version.class, new VersionLoader()) + .registerLoader(VersionRange.class, new VersionRangeLoader()) + .registerLoader(WebsiteConfig.class, WebsiteConfig::new); + + public ManifestAddon loadAddon(Path addonPath, ClassLoader loader) { + try(JarFile jar = new JarFile(addonPath.toFile())) { + logger.debug("Loading addon from JAR {}", addonPath); + + JarEntry manifestEntry = jar.getJarEntry("terra.addon.yml"); + if(manifestEntry == null) { + throw new ManifestNotPresentException("Addon " + addonPath + " does not contain addon manifest."); + } + + + //noinspection NestedTryStatement + try { + AddonManifest manifest = manifestLoader.load(new AddonManifest(), + new YamlConfiguration(jar.getInputStream(manifestEntry), + "terra.addon.yml")); + + logger.debug("Loading addon {}@{}", manifest.getID(), manifest.getVersion().getFormatted()); + + if(manifest.getSchemaVersion() != 1) { + throw new AddonException("Addon " + manifest.getID() + " has unknown schema version: " + manifest.getSchemaVersion()); + } + + List initializers = manifest.getEntryPoints().stream().map(entryPoint -> { + try { + Object in = loader.loadClass(entryPoint).getConstructor().newInstance(); + if(!(in instanceof AddonInitializer)) { + throw new AddonException(in.getClass() + " does not extend " + AddonInitializer.class); + } + return (AddonInitializer) in; + } catch(InvocationTargetException e) { + throw new AddonException("Exception occurred while instantiating addon", e); + } catch(NoSuchMethodException | IllegalAccessException | InstantiationException e) { + throw new AddonException(String.format("No valid default constructor found in entry point %s", entryPoint), e); + } catch(ClassNotFoundException e) { + throw new AddonException(String.format("Entry point %s not found in JAR.", entryPoint), e); + } + }).collect(Collectors.toList()); + + return new ManifestAddon(manifest, initializers); + + } catch(LoadException e) { + throw new ManifestException("Failed to load addon manifest", e); + } + } catch(IOException e) { + throw new AddonException("Failed to load addon from JAR " + addonPath, e); + } + } + + @Override + public Iterable loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent) { + logger.debug("Loading addons..."); + + try(Stream files = Files.walk(addonsFolder, 1, FileVisitOption.FOLLOW_LINKS)) { + List addons = files + .filter(path -> path.toFile().isFile()) + .filter(path -> path.toFile().canRead()) + .filter(path -> !path.getFileName().startsWith(".")) // ignore hidden files. + .filter(path -> path.toString().endsWith(".jar")) + .toList(); + + addons.stream().map(path -> { + try { + return path.toUri().toURL(); + } catch(MalformedURLException e) { + throw new UncheckedIOException(e); + } + }).forEach(parent::addURL); + + return addons.stream() + .map(jar -> loadAddon(jar, parent)) + .collect(Collectors.toList()); + } catch(IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public String getID() { + return "MANIFEST"; + } + + @Override + public Version getVersion() { + return VERSION; + } +} diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/AddonManifest.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/AddonManifest.java new file mode 100644 index 000000000..0e225b712 --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/AddonManifest.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.impl.config; + +import ca.solostudios.strata.version.Version; +import ca.solostudios.strata.version.VersionRange; +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import com.dfsek.terra.api.registry.key.StringIdentifiable; + + +@SuppressWarnings("FieldMayBeFinal") +public class AddonManifest implements ConfigTemplate, StringIdentifiable { + @Value("schema-version") + private int schemaVersion; + + @Value("id") + private String id; + + @Value("version") + private Version version; + + @Value("license") + private String license; + + @Value("contributors") + @Default + private List contributors = Collections.emptyList(); + + @Value("entrypoints") + private List entryPoints; + + @Value("depends") + @Default + private Map dependencies = Collections.emptyMap(); + + @Value("website") + @Default + private WebsiteConfig website; + + @Override + public String getID() { + return id; + } + + public int getSchemaVersion() { + return schemaVersion; + } + + public Version getVersion() { + return version; + } + + public List getContributors() { + return contributors; + } + + public List getEntryPoints() { + return entryPoints; + } + + public String getLicense() { + return license; + } + + public WebsiteConfig getWebsite() { + return website; + } + + public Map getDependencies() { + return dependencies; + } +} diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/WebsiteConfig.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/WebsiteConfig.java new file mode 100644 index 000000000..669fc7c18 --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/WebsiteConfig.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.impl.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + + +public class WebsiteConfig implements ObjectTemplate { + @Value("issues") + private String issues; + + @Value("source") + private String source; + + @Value("docs") + private String docs; + + public String getDocs() { + return docs; + } + + public String getIssues() { + return issues; + } + + public String getSource() { + return source; + } + + @Override + public WebsiteConfig get() { + return this; + } +} diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/loaders/VersionLoader.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/loaders/VersionLoader.java new file mode 100644 index 000000000..23e6bc1ce --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/loaders/VersionLoader.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.impl.config.loaders; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.parser.tokenizer.ParseException; +import ca.solostudios.strata.version.Version; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; + + +public class VersionLoader implements TypeLoader { + @Override + public Version load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) + throws LoadException { + try { + return Versions.parseVersion((String) c); + } catch(ParseException e) { + throw new LoadException("Failed to parse version", e, depthTracker); + } + } +} diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/loaders/VersionRangeLoader.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/loaders/VersionRangeLoader.java new file mode 100644 index 000000000..5adaf3663 --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/config/loaders/VersionRangeLoader.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.impl.config.loaders; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.parser.tokenizer.ParseException; +import ca.solostudios.strata.version.VersionRange; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; + + +public class VersionRangeLoader implements TypeLoader { + @Override + public VersionRange load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) + throws LoadException { + try { + return Versions.parseVersionRange((String) c); + } catch(ParseException e) { + throw new LoadException("Failed to parse version range", e, depthTracker); + } + } +} diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/exception/AddonException.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/exception/AddonException.java new file mode 100644 index 000000000..9fa06a2e4 --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/exception/AddonException.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.impl.exception; + +import java.io.Serial; + + +public class AddonException extends RuntimeException { + @Serial + private static final long serialVersionUID = -4201912399458420090L; + + public AddonException(String message) { + super(message); + } + + public AddonException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/exception/ManifestException.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/exception/ManifestException.java new file mode 100644 index 000000000..d076c8875 --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/exception/ManifestException.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.impl.exception; + +import java.io.Serial; + + +public class ManifestException extends AddonException { + @Serial + private static final long serialVersionUID = -2458077663176544645L; + + public ManifestException(String message) { + super(message); + } + + public ManifestException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/exception/ManifestNotPresentException.java b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/exception/ManifestNotPresentException.java new file mode 100644 index 000000000..010dcb86a --- /dev/null +++ b/common/addons/manifest-addon-loader/src/main/java/com/dfsek/terra/addons/manifest/impl/exception/ManifestNotPresentException.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.manifest.impl.exception; + +import java.io.Serial; + + +public class ManifestNotPresentException extends ManifestException { + @Serial + private static final long serialVersionUID = -2116663180747013810L; + + public ManifestNotPresentException(String message) { + super(message); + } + + public ManifestNotPresentException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/addons/palette-block-shortcut/LICENSE b/common/addons/palette-block-shortcut/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/palette-block-shortcut/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/palette-block-shortcut/build.gradle.kts b/common/addons/palette-block-shortcut/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/palette-block-shortcut/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/palette-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/PaletteBlockShortcutAddon.java b/common/addons/palette-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/PaletteBlockShortcutAddon.java new file mode 100644 index 000000000..c3a2f3ea4 --- /dev/null +++ b/common/addons/palette-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/PaletteBlockShortcutAddon.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.addons.palette.shortcut.block; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class PaletteBlockShortcutAddon implements AddonInitializer { + @Inject + private BaseAddon addon; + @Inject + private Platform platform; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> event.getPack() + .registerShortcut(Palette.class, "BLOCK", + (configLoader, input, tracker) -> new SingletonPalette( + configLoader.loadType(BlockState.class, input, tracker)))) + .failThrough(); + } +} diff --git a/common/addons/palette-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/SingletonPalette.java b/common/addons/palette-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/SingletonPalette.java new file mode 100644 index 000000000..847c2c2b3 --- /dev/null +++ b/common/addons/palette-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/SingletonPalette.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.addons.palette.shortcut.block; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public class SingletonPalette implements Palette { + private final BlockState blockState; + + public SingletonPalette(BlockState blockState) { + this.blockState = blockState; + } + + @Override + public BlockState get(int layer, double x, double y, double z, long seed) { + return blockState; + } +} diff --git a/common/addons/palette-block-shortcut/src/main/resources/terra.addon.yml b/common/addons/palette-block-shortcut/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..6b643a053 --- /dev/null +++ b/common/addons/palette-block-shortcut/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: palette-block-shortcut +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.palette.shortcut.block.PaletteBlockShortcutAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/structure-block-shortcut/LICENSE b/common/addons/structure-block-shortcut/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/structure-block-shortcut/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/structure-block-shortcut/build.gradle.kts b/common/addons/structure-block-shortcut/build.gradle.kts new file mode 100644 index 000000000..9d0aac37f --- /dev/null +++ b/common/addons/structure-block-shortcut/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/structure-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/SingletonStructure.java b/common/addons/structure-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/SingletonStructure.java new file mode 100644 index 000000000..7d14c6ee7 --- /dev/null +++ b/common/addons/structure-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/SingletonStructure.java @@ -0,0 +1,24 @@ +package com.dfsek.terra.addons.palette.shortcut.block; + +import java.util.Random; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.WritableWorld; + + +public class SingletonStructure implements Structure { + private final BlockState blockState; + + public SingletonStructure(BlockState blockState) { + this.blockState = blockState; + } + + @Override + public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { + world.setBlockState(location, blockState); + return true; + } +} diff --git a/common/addons/structure-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/StructureBlockShortcutAddon.java b/common/addons/structure-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/StructureBlockShortcutAddon.java new file mode 100644 index 000000000..210ab98d1 --- /dev/null +++ b/common/addons/structure-block-shortcut/src/main/java/com/dfsek/terra/addons/palette/shortcut/block/StructureBlockShortcutAddon.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.addons.palette.shortcut.block; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.structure.Structure; + + +public class StructureBlockShortcutAddon implements AddonInitializer { + @Inject + private BaseAddon addon; + @Inject + private Platform platform; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> event.getPack() + .registerShortcut(Structure.class, "BLOCK", + (configLoader, input, tracker) -> new SingletonStructure( + configLoader.loadType(BlockState.class, input, tracker) + ))) + .failThrough(); + } +} diff --git a/common/addons/structure-block-shortcut/src/main/resources/terra.addon.yml b/common/addons/structure-block-shortcut/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..d653e2d9c --- /dev/null +++ b/common/addons/structure-block-shortcut/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: structure-block-shortcut +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.palette.shortcut.block.StructureBlockShortcutAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/structure-mutator/build.gradle.kts b/common/addons/structure-mutator/build.gradle.kts new file mode 100644 index 000000000..0440540bb --- /dev/null +++ b/common/addons/structure-mutator/build.gradle.kts @@ -0,0 +1,5 @@ +version = version("0.1.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} diff --git a/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructure.java b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructure.java new file mode 100644 index 000000000..a5aafdd1e --- /dev/null +++ b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructure.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.addons.structure.mutator; + +import java.util.Random; + +import com.dfsek.terra.api.registry.key.Keyed; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.WritableWorld; +import com.dfsek.terra.api.world.util.ReadInterceptor; +import com.dfsek.terra.api.world.util.WriteInterceptor; + + +public class MutatedStructure implements Structure, Keyed { + private final RegistryKey key; + private final Structure base; + private final ReadInterceptor readInterceptor; + private final WriteInterceptor writeInterceptor; + + public MutatedStructure(RegistryKey key, Structure base, + ReadInterceptor readInterceptor, WriteInterceptor writeInterceptor) { + this.key = key; + this.base = base; + this.readInterceptor = readInterceptor; + this.writeInterceptor = writeInterceptor; + } + + @Override + public RegistryKey getRegistryKey() { + return key; + } + + @Override + public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { + return base.generate(location, + world + .buffer() + .read(readInterceptor) + .write(writeInterceptor) + .build(), + random, rotation); + } +} diff --git a/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructureConfigType.java b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructureConfigType.java new file mode 100644 index 000000000..23eb5e802 --- /dev/null +++ b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructureConfigType.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.addons.structure.mutator; + +import com.dfsek.terra.addons.structure.mutator.config.MutatedStructureTemplate; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class MutatedStructureConfigType implements ConfigType { + private final BaseAddon addon; + + public MutatedStructureConfigType(BaseAddon addon) { + this.addon = addon; + } + + @Override + public MutatedStructureTemplate getTemplate(ConfigPack pack, Platform platform) { + return new MutatedStructureTemplate(); + } + + @Override + public ConfigFactory getFactory() { + return new MutatedStructureFactory(addon); + } + + @Override + public TypeKey getTypeKey() { + return TypeKey.of(MutatedStructure.class); + } +} diff --git a/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructureFactory.java b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructureFactory.java new file mode 100644 index 000000000..a8f953d3c --- /dev/null +++ b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructureFactory.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.addons.structure.mutator; + +import com.dfsek.tectonic.api.exception.LoadException; + +import com.dfsek.terra.addons.structure.mutator.config.MutatedStructureTemplate; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.config.ConfigFactory; + + +public class MutatedStructureFactory implements ConfigFactory { + private final BaseAddon addon; + + public MutatedStructureFactory(BaseAddon addon) { + this.addon = addon; + } + + @Override + public MutatedStructure build(MutatedStructureTemplate config, Platform platform) throws LoadException { + return new MutatedStructure(addon.key(config.getID()), + config.getDelegate(), + config.getReadInterceptor(), + config.getWriteInterceptor()); + } +} diff --git a/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/StructureMutatorAddon.java b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/StructureMutatorAddon.java new file mode 100644 index 000000000..b5a3fab7f --- /dev/null +++ b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/StructureMutatorAddon.java @@ -0,0 +1,29 @@ +package com.dfsek.terra.addons.structure.mutator; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class StructureMutatorAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + event.getPack().registerConfigType(new MutatedStructureConfigType(addon), addon.key("MUTATED_STRUCTURE"), 499); + }) + .failThrough(); + } +} diff --git a/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/config/MutatedStructureTemplate.java b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/config/MutatedStructureTemplate.java new file mode 100644 index 000000000..1b8d473d1 --- /dev/null +++ b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/config/MutatedStructureTemplate.java @@ -0,0 +1,40 @@ +package com.dfsek.terra.addons.structure.mutator.config; + +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.api.config.AbstractableTemplate; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.world.util.ReadInterceptor; +import com.dfsek.terra.api.world.util.WriteInterceptor; + + +public class MutatedStructureTemplate implements AbstractableTemplate { + @Value("id") + private String id; + + @Value("mutate.read") + private ReadInterceptor readInterceptor; + + @Value("mutate.write") + private WriteInterceptor writeInterceptor; + + @Value("structure") + private Structure delegate; + + @Override + public String getID() { + return id; + } + + public ReadInterceptor getReadInterceptor() { + return readInterceptor; + } + + public WriteInterceptor getWriteInterceptor() { + return writeInterceptor; + } + + public Structure getDelegate() { + return delegate; + } +} diff --git a/common/addons/structure-mutator/src/main/resources/terra.addon.yml b/common/addons/structure-mutator/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..29df5332d --- /dev/null +++ b/common/addons/structure-mutator/src/main/resources/terra.addon.yml @@ -0,0 +1,11 @@ +schema-version: 1 +contributors: + - Terra contributors +id: structure-mutator +version: @VERSION@ +entrypoints: [ ] +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/structure-sponge-loader/LICENSE b/common/addons/structure-sponge-loader/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/structure-sponge-loader/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/structure-sponge-loader/build.gradle.kts b/common/addons/structure-sponge-loader/build.gradle.kts new file mode 100644 index 000000000..d064e4fd5 --- /dev/null +++ b/common/addons/structure-sponge-loader/build.gradle.kts @@ -0,0 +1,17 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +version = version("1.0.0") + +repositories { + maven { url = uri("https://jitpack.io/") } +} + +dependencies { + api("commons-io:commons-io:2.7") + api("com.github.Querz:NBT:6.1") + compileOnlyApi(project(":common:addons:manifest-addon-loader")) +} + +tasks.named("shadowJar") { + relocate("org.apache.commons", "com.dfsek.terra.addons.sponge.lib.commons") +} \ No newline at end of file diff --git a/common/addons/structure-sponge-loader/src/main/java/com/dfsek/terra/addons/sponge/SpongeSchematicAddon.java b/common/addons/structure-sponge-loader/src/main/java/com/dfsek/terra/addons/sponge/SpongeSchematicAddon.java new file mode 100644 index 000000000..caf7f47b5 --- /dev/null +++ b/common/addons/structure-sponge-loader/src/main/java/com/dfsek/terra/addons/sponge/SpongeSchematicAddon.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.sponge; + +import net.querz.nbt.io.NBTDeserializer; +import net.querz.nbt.tag.ByteArrayTag; +import net.querz.nbt.tag.CompoundTag; +import net.querz.nbt.tag.IntTag; +import net.querz.nbt.tag.Tag; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PushbackInputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.StringUtil; + + +public class SpongeSchematicAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + private static InputStream detectDecompression(InputStream is) throws IOException { + PushbackInputStream pbis = new PushbackInputStream(is, 2); + int signature = (pbis.read() & 0xFF) + (pbis.read() << 8); + pbis.unread(signature >> 8); + pbis.unread(signature & 0xFF); + if(signature == GZIPInputStream.GZIP_MAGIC) { + return new GZIPInputStream(pbis); + } + return pbis; + } + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + CheckedRegistry structureRegistry = event.getPack().getOrCreateRegistry(Structure.class); + event.getPack() + .getLoader() + .open("", ".schem") + .thenEntries(entries -> entries + .stream() + .map(entry -> convert(entry.getValue(), StringUtil.fileName(entry.getKey()))) + .forEach(structureRegistry::register)).close(); + }) + .failThrough(); + } + + public SpongeStructure convert(InputStream in, String id) { + try { + CompoundTag baseTag = (CompoundTag) new NBTDeserializer(false).fromStream(detectDecompression(in)).getTag(); + int wid = baseTag.getShort("Width"); + int len = baseTag.getShort("Length"); + int hei = baseTag.getShort("Height"); + + ByteArrayTag blocks = baseTag.getByteArrayTag("BlockData"); + + CompoundTag palette = (CompoundTag) baseTag.get("Palette"); + Map data = new HashMap<>(); + + for(Map.Entry> entry : palette.entrySet()) { + data.put(((IntTag) entry.getValue()).asInt(), entry.getKey()); + } + + BlockState[][][] states = new BlockState[wid][len][hei]; + + byte[] arr = blocks.getValue(); + for(int x = 0; x < wid; x++) { + for(int z = 0; z < len; z++) { + for(int y = 0; y < hei; y++) { + String block = data.get((int) arr[x + z * wid + y * wid * len]); + if(block.startsWith("minecraft:structure_void")) continue; + states[x][z][y] = platform.getWorldHandle().createBlockState(block); + } + } + } + + return new SpongeStructure(states, addon.key(id)); + } catch(IOException e) { + throw new IllegalArgumentException("Failed to parse Sponge schematic: ", e); + } + } +} diff --git a/common/addons/structure-sponge-loader/src/main/java/com/dfsek/terra/addons/sponge/SpongeStructure.java b/common/addons/structure-sponge-loader/src/main/java/com/dfsek/terra/addons/sponge/SpongeStructure.java new file mode 100644 index 000000000..e08c51146 --- /dev/null +++ b/common/addons/structure-sponge-loader/src/main/java/com/dfsek/terra/addons/sponge/SpongeStructure.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.sponge; + +import java.util.Random; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.registry.key.Keyed; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.vector.Vector2Int; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.WritableWorld; + + +public class SpongeStructure implements Structure, Keyed { + + private final BlockState[][][] blocks; + + private final RegistryKey id; + + public SpongeStructure(BlockState[][][] blocks, RegistryKey id) { + this.blocks = blocks; + this.id = id; + } + + @Override + public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { + int bX = location.getX(); + int bY = location.getY(); + int bZ = location.getZ(); + for(int x = 0; x < blocks.length; x++) { + for(int z = 0; z < blocks[x].length; z++) { + Vector2Int r = Vector2Int.of(x, z).rotate(rotation); + int rX = r.getX(); + int rZ = r.getZ(); + for(int y = 0; y < blocks[x][z].length; y++) { + BlockState state = blocks[x][z][y]; + if(state == null) continue; + world.setBlockState(bX + rX, bY + y, bZ + rZ, state); + } + } + } + return true; + } + + @Override + public RegistryKey getRegistryKey() { + return id; + } +} diff --git a/common/addons/structure-sponge-loader/src/main/resources/terra.addon.yml b/common/addons/structure-sponge-loader/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..d5635f09b --- /dev/null +++ b/common/addons/structure-sponge-loader/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: structure-sponge-loader +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.sponge.SpongeSchematicAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/addons/structure-terrascript-loader/LICENSE b/common/addons/structure-terrascript-loader/LICENSE new file mode 100644 index 000000000..64c1cd516 --- /dev/null +++ b/common/addons/structure-terrascript-loader/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2021 Polyhedral Development + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +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. \ No newline at end of file diff --git a/common/addons/structure-terrascript-loader/README.md b/common/addons/structure-terrascript-loader/README.md new file mode 100644 index 000000000..5bf8f622a --- /dev/null +++ b/common/addons/structure-terrascript-loader/README.md @@ -0,0 +1,4 @@ +# structure-terrascript-loader + +Implements the TerraScript structure scripting language, and loads all `*.tesf` +files into the Structure registry. \ No newline at end of file diff --git a/common/addons/structure-terrascript-loader/build.gradle.kts b/common/addons/structure-terrascript-loader/build.gradle.kts new file mode 100644 index 000000000..15b7f1107 --- /dev/null +++ b/common/addons/structure-terrascript-loader/build.gradle.kts @@ -0,0 +1,15 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +version = version("1.0.0") + +dependencies { + api("commons-io:commons-io:2.7") + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("org.apache.commons", "com.dfsek.terra.addons.terrascript.lib.commons") + relocate("net.jafama", "com.dfsek.terra.addons.terrascript.lib.jafama") +} \ No newline at end of file diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java new file mode 100644 index 000000000..f2e1d0055 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.StructureScript; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.structure.LootTable; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.StringUtil; + + +public class TerraScriptAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .then(event -> { + CheckedRegistry structureRegistry = event.getPack().getOrCreateRegistry(Structure.class); + CheckedRegistry lootRegistry = event.getPack().getOrCreateRegistry(LootTable.class); + event.getPack().getLoader().open("", ".tesf").thenEntries( + entries -> + entries.stream() + .parallel() + .map(entry -> { + try { + String id = StringUtil.fileName(entry.getKey()); + return new StructureScript(entry.getValue(), + addon.key(id), + platform, + structureRegistry, + lootRegistry, + event.getPack().getOrCreateRegistry(FunctionBuilder.class)); + } catch(ParseException e) { + throw new RuntimeException("Failed to load script \"" + entry.getKey() + "\"", e); + } + }) + .toList() + .forEach(structureRegistry::register)) + .close(); + }) + .priority(100) + .failThrough(); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java similarity index 69% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java index 9f4ff96db..56aa24b87 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java @@ -1,133 +1,128 @@ -package com.dfsek.terra.api.structures.parser; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.Item; -import com.dfsek.terra.api.structures.parser.lang.Keyword; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant; -import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression; -import com.dfsek.terra.api.structures.parser.lang.constants.NumericConstant; -import com.dfsek.terra.api.structures.parser.lang.constants.StringConstant; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.parser.lang.keywords.flow.BreakKeyword; -import com.dfsek.terra.api.structures.parser.lang.keywords.flow.ContinueKeyword; -import com.dfsek.terra.api.structures.parser.lang.keywords.flow.FailKeyword; -import com.dfsek.terra.api.structures.parser.lang.keywords.flow.ReturnKeyword; -import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.ForKeyword; -import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.IfKeyword; -import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.WhileKeyword; -import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.BooleanAndOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.BooleanNotOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.BooleanOrOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.ConcatenationOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.DivisionOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.ModuloOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.MultiplicationOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.NegationOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.NumberAdditionOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.SubtractionOperation; -import com.dfsek.terra.api.structures.parser.lang.operations.statements.EqualsStatement; -import com.dfsek.terra.api.structures.parser.lang.operations.statements.GreaterOrEqualsThanStatement; -import com.dfsek.terra.api.structures.parser.lang.operations.statements.GreaterThanStatement; -import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanOrEqualsStatement; -import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanStatement; -import com.dfsek.terra.api.structures.parser.lang.operations.statements.NotEqualsStatement; -import com.dfsek.terra.api.structures.parser.lang.variables.Assignment; -import com.dfsek.terra.api.structures.parser.lang.variables.Declaration; -import com.dfsek.terra.api.structures.parser.lang.variables.Getter; -import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.api.structures.tokenizer.Token; -import com.dfsek.terra.api.structures.tokenizer.Tokenizer; -import com.dfsek.terra.api.util.GlueList; +package com.dfsek.terra.addons.terrascript.parser; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.Item; +import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.BooleanConstant; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.ConstantExpression; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.NumericConstant; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.StringConstant; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow.BreakKeyword; +import com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow.ContinueKeyword; +import com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow.FailKeyword; +import com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow.ReturnKeyword; +import com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike.ForKeyword; +import com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike.IfKeyword; +import com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike.WhileKeyword; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.BooleanAndOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.BooleanNotOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.BooleanOrOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.ConcatenationOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.DivisionOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.ModuloOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.MultiplicationOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.NegationOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.NumberAdditionOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.SubtractionOperation; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.EqualsStatement; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.GreaterOrEqualsThanStatement; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.GreaterThanStatement; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.LessThanOrEqualsStatement; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.LessThanStatement; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.NotEqualsStatement; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.VariableAssignmentNode; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.VariableDeclarationNode; +import com.dfsek.terra.addons.terrascript.parser.lang.variables.VariableReferenceNode; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.addons.terrascript.tokenizer.Token; +import com.dfsek.terra.addons.terrascript.tokenizer.Tokenizer; + + @SuppressWarnings("unchecked") public class Parser { private final String data; private final Map>> functions = new HashMap<>(); - - private String id; - + private final List ignoredFunctions = new ArrayList<>(); + public Parser(String data) { this.data = data; } - + public Parser registerFunction(String name, FunctionBuilder> functionBuilder) { functions.put(name, functionBuilder); return this; } - - public String getID() { - return id; + + public Parser ignoreFunction(String name) { + ignoredFunctions.add(name); + return this; } - + /** * Parse input * * @return executable {@link Block} + * * @throws ParseException If parsing fails. */ - public Block parse() throws ParseException { - Tokenizer tokens = new Tokenizer(data); - - // Parse ID - ParserUtil.checkType(tokens.consume(), Token.Type.ID); // First token must be ID - Token idToken = tokens.get(); - ParserUtil.checkType(tokens.consume(), Token.Type.STRING); // Second token must be string literal containing ID - ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); - this.id = idToken.getContent(); - - - return parseBlock(tokens, new HashMap<>(), false); + public Block parse() { + return parseBlock(new Tokenizer(data), new HashMap<>(), false); } - - + private Keyword parseLoopLike(Tokenizer tokens, Map variableMap, boolean loop) throws ParseException { - + Token identifier = tokens.consume(); ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP); - + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); - - switch(identifier.getType()) { - case FOR_LOOP: - return parseForLoop(tokens, variableMap, identifier.getPosition()); - case IF_STATEMENT: - return parseIfStatement(tokens, variableMap, identifier.getPosition(), loop); - case WHILE_LOOP: - return parseWhileLoop(tokens, variableMap, identifier.getPosition()); - default: - throw new UnsupportedOperationException("Unknown keyword " + identifier.getContent() + ": " + identifier.getPosition()); - } + + return switch(identifier.getType()) { + case FOR_LOOP -> parseForLoop(tokens, variableMap, identifier.getPosition()); + case IF_STATEMENT -> parseIfStatement(tokens, variableMap, identifier.getPosition(), loop); + case WHILE_LOOP -> parseWhileLoop(tokens, variableMap, identifier.getPosition()); + default -> throw new UnsupportedOperationException( + "Unknown keyword " + identifier.getContent() + ": " + identifier.getPosition()); + }; } - - private WhileKeyword parseWhileLoop(Tokenizer tokens, Map variableMap, Position start) throws ParseException { + + private WhileKeyword parseWhileLoop(Tokenizer tokens, Map variableMap, Position start) { Returnable first = parseExpression(tokens, true, variableMap); ParserUtil.checkReturnType(first, Returnable.ReturnType.BOOLEAN); - + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); - + return new WhileKeyword(parseStatementBlock(tokens, variableMap, true), (Returnable) first, start); // While loop } - - private IfKeyword parseIfStatement(Tokenizer tokens, Map variableMap, Position start, boolean loop) throws ParseException { + + private IfKeyword parseIfStatement(Tokenizer tokens, Map variableMap, Position start, boolean loop) { Returnable condition = parseExpression(tokens, true, variableMap); ParserUtil.checkReturnType(condition, Returnable.ReturnType.BOOLEAN); - + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); - + Block elseBlock = null; Block statement = parseStatementBlock(tokens, variableMap, loop); - - List, Block>> elseIf = new GlueList<>(); - + + List, Block>> elseIf = new ArrayList<>(); + while(tokens.hasNext() && tokens.get().getType().equals(Token.Type.ELSE)) { tokens.consume(); // Consume else. if(tokens.get().getType().equals(Token.Type.IF_STATEMENT)) { @@ -140,12 +135,12 @@ public class Parser { break; // Else must be last. } } - + return new IfKeyword(statement, (Returnable) condition, elseIf, elseBlock, start); // If statement } - - private Block parseStatementBlock(Tokenizer tokens, Map variableMap, boolean loop) throws ParseException { - + + private Block parseStatementBlock(Tokenizer tokens, Map variableMap, boolean loop) { + if(tokens.get().getType().equals(Token.Type.BLOCK_BEGIN)) { ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_BEGIN); Block block = parseBlock(tokens, variableMap, loop); @@ -158,14 +153,14 @@ public class Parser { return block; } } - - private ForKeyword parseForLoop(Tokenizer tokens, Map old, Position start) throws ParseException { + + private ForKeyword parseForLoop(Tokenizer tokens, Map old, Position start) { Map variableMap = new HashMap<>(old); // New scope Token f = tokens.get(); ParserUtil.checkType(f, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.IDENTIFIER); Item initializer; if(f.isVariableDeclaration()) { - Declaration forVar = parseVariableDeclaration(tokens, variableMap); + VariableDeclarationNode forVar = parseVariableDeclaration(tokens, variableMap); Token name = tokens.get(); if(functions.containsKey(name.getContent()) || variableMap.containsKey(name.getContent())) throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition()); @@ -175,19 +170,20 @@ public class Parser { Returnable conditional = parseExpression(tokens, true, variableMap); ParserUtil.checkReturnType(conditional, Returnable.ReturnType.BOOLEAN); ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); - + Item incrementer; Token token = tokens.get(); if(variableMap.containsKey(token.getContent())) { // Assume variable assignment incrementer = parseAssignment(tokens, variableMap); } else incrementer = parseFunction(tokens, true, variableMap); - + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); - - return new ForKeyword(parseStatementBlock(tokens, variableMap, true), initializer, (Returnable) conditional, incrementer, start); + + return new ForKeyword(parseStatementBlock(tokens, variableMap, true), initializer, (Returnable) conditional, incrementer, + start); } - - private Returnable parseExpression(Tokenizer tokens, boolean full, Map variableMap) throws ParseException { + + private Returnable parseExpression(Tokenizer tokens, boolean full, Map variableMap) { boolean booleanInverted = false; // Check for boolean not operator boolean negate = false; if(tokens.get().getType().equals(Token.Type.BOOLEAN_NOT)) { @@ -197,11 +193,11 @@ public class Parser { negate = true; tokens.consume(); } - + Token id = tokens.get(); - + ParserUtil.checkType(id, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.GROUP_BEGIN); - + Returnable expression; if(id.isConstant()) { expression = parseConstantExpression(tokens); @@ -212,10 +208,10 @@ public class Parser { expression = parseFunction(tokens, false, variableMap); else if(variableMap.containsKey(id.getContent())) { ParserUtil.checkType(tokens.consume(), Token.Type.IDENTIFIER); - expression = new Getter(id.getContent(), id.getPosition(), variableMap.get(id.getContent())); + expression = new VariableReferenceNode(id.getContent(), id.getPosition(), variableMap.get(id.getContent())); } else throw new ParseException("Unexpected token \" " + id.getContent() + "\"", id.getPosition()); } - + if(booleanInverted) { // Invert operation if boolean not detected ParserUtil.checkReturnType(expression, Returnable.ReturnType.BOOLEAN); expression = new BooleanNotOperation((Returnable) expression, expression.getPosition()); @@ -223,14 +219,14 @@ public class Parser { ParserUtil.checkReturnType(expression, Returnable.ReturnType.NUMBER); expression = new NegationOperation((Returnable) expression, expression.getPosition()); } - + if(full && tokens.get().isBinaryOperator()) { // Parse binary operations return parseBinaryOperation(expression, tokens, variableMap); } return expression; } - - private ConstantExpression parseConstantExpression(Tokenizer tokens) throws ParseException { + + private ConstantExpression parseConstantExpression(Tokenizer tokens) { Token constantToken = tokens.consume(); Position position = constantToken.getPosition(); switch(constantToken.getType()) { @@ -242,24 +238,25 @@ public class Parser { case BOOLEAN: return new BooleanConstant(Boolean.parseBoolean(constantToken.getContent()), position); default: - throw new UnsupportedOperationException("Unsupported constant token: " + constantToken.getType() + " at position: " + position); + throw new UnsupportedOperationException( + "Unsupported constant token: " + constantToken.getType() + " at position: " + position); } } - - private Returnable parseGroup(Tokenizer tokens, Map variableMap) throws ParseException { + + private Returnable parseGroup(Tokenizer tokens, Map variableMap) { ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); Returnable expression = parseExpression(tokens, true, variableMap); // Parse inside of group as a separate expression ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); return expression; } - - - private BinaryOperation parseBinaryOperation(Returnable left, Tokenizer tokens, Map variableMap) throws ParseException { + + private BinaryOperation parseBinaryOperation(Returnable left, Tokenizer tokens, + Map variableMap) { Token binaryOperator = tokens.consume(); ParserUtil.checkBinaryOperator(binaryOperator); - + Returnable right = parseExpression(tokens, false, variableMap); - + Token other = tokens.get(); if(ParserUtil.hasPrecedence(binaryOperator.getType(), other.getType())) { return assemble(left, parseBinaryOperation(right, tokens, variableMap), binaryOperator); @@ -268,8 +265,8 @@ public class Parser { } return assemble(left, right, binaryOperator); } - - private BinaryOperation assemble(Returnable left, Returnable right, Token binaryOperator) throws ParseException { + + private BinaryOperation assemble(Returnable left, Returnable right, Token binaryOperator) { if(binaryOperator.isStrictNumericOperator()) ParserUtil.checkArithmeticOperation(left, right, binaryOperator); // Numeric type checking if(binaryOperator.isStrictBooleanOperator()) ParserUtil.checkBooleanOperation(left, right, binaryOperator); // Boolean type checking @@ -294,7 +291,8 @@ public class Parser { case LESS_THAN_OPERATOR: return new LessThanStatement((Returnable) left, (Returnable) right, binaryOperator.getPosition()); case GREATER_THAN_OR_EQUALS_OPERATOR: - return new GreaterOrEqualsThanStatement((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + return new GreaterOrEqualsThanStatement((Returnable) left, (Returnable) right, + binaryOperator.getPosition()); case LESS_THAN_OR_EQUALS_OPERATOR: return new LessThanOrEqualsStatement((Returnable) left, (Returnable) right, binaryOperator.getPosition()); case BOOLEAN_AND: @@ -307,51 +305,57 @@ public class Parser { throw new UnsupportedOperationException("Unsupported binary operator: " + binaryOperator.getType()); } } - - private Declaration parseVariableDeclaration(Tokenizer tokens, Map variableMap) throws ParseException { + + private VariableDeclarationNode parseVariableDeclaration(Tokenizer tokens, Map variableMap) { Token type = tokens.consume(); ParserUtil.checkType(type, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE); - + Returnable.ReturnType returnType = ParserUtil.getVariableReturnType(type); - + ParserUtil.checkVarType(type, returnType); // Check for type mismatch Token identifier = tokens.consume(); ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); if(functions.containsKey(identifier.getContent()) || variableMap.containsKey(identifier.getContent())) throw new ParseException(identifier.getContent() + " is already defined in this scope", identifier.getPosition()); ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT); - + Returnable value = parseExpression(tokens, true, variableMap); ParserUtil.checkReturnType(value, returnType); - + variableMap.put(identifier.getContent(), returnType); - - return new Declaration<>(tokens.get().getPosition(), identifier.getContent(), value, returnType); + + return new VariableDeclarationNode<>(tokens.get().getPosition(), identifier.getContent(), value, returnType); } - - private Block parseBlock(Tokenizer tokens, Map superVars, boolean loop) throws ParseException { - List> parsedItems = new GlueList<>(); - - Map parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations. - + + private Block parseBlock(Tokenizer tokens, Map superVars, boolean loop) { + List> parsedItems = new ArrayList<>(); + + Map parsedVariables = new HashMap<>( + superVars); // New hashmap as to not mutate parent scope's declarations. + Token first = tokens.get(); - + while(tokens.hasNext()) { Token token = tokens.get(); if(token.getType().equals(Token.Type.BLOCK_END)) break; // Stop parsing at block end. - parsedItems.add(parseItem(tokens, parsedVariables, loop)); + Item parsedItem = parseItem(tokens, parsedVariables, loop); + if(parsedItem != Function.NULL) { + parsedItems.add(parsedItem); + } if(tokens.hasNext() && !token.isLoopLike()) ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END); } return new Block(parsedItems, first.getPosition()); } - - private Item parseItem(Tokenizer tokens, Map variableMap, boolean loop) throws ParseException { + + private Item parseItem(Tokenizer tokens, Map variableMap, boolean loop) { Token token = tokens.get(); if(loop) ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP, - Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN, Token.Type.BREAK, Token.Type.CONTINUE, Token.Type.FAIL); + Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, + Token.Type.RETURN, Token.Type.BREAK, Token.Type.CONTINUE, Token.Type.FAIL); else ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP, - Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN, Token.Type.FAIL); - + Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN, + Token.Type.FAIL); + if(token.isLoopLike()) { // Parse loop-like tokens (if, while, etc) return parseLoopLike(tokens, variableMap, loop); } else if(token.isIdentifier()) { // Parse identifiers @@ -359,67 +363,71 @@ public class Parser { return parseAssignment(tokens, variableMap); } else return parseFunction(tokens, true, variableMap); } else if(token.isVariableDeclaration()) { - + return parseVariableDeclaration(tokens, variableMap); - + } else if(token.getType().equals(Token.Type.RETURN)) return new ReturnKeyword(tokens.consume().getPosition()); else if(token.getType().equals(Token.Type.BREAK)) return new BreakKeyword(tokens.consume().getPosition()); else if(token.getType().equals(Token.Type.CONTINUE)) return new ContinueKeyword(tokens.consume().getPosition()); else if(token.getType().equals(Token.Type.FAIL)) return new FailKeyword(tokens.consume().getPosition()); else throw new UnsupportedOperationException("Unexpected token " + token.getType() + ": " + token.getPosition()); } - - private Assignment parseAssignment(Tokenizer tokens, Map variableMap) throws ParseException { + + private VariableAssignmentNode parseAssignment(Tokenizer tokens, Map variableMap) { Token identifier = tokens.consume(); - + ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); - + ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT); - + Returnable value = parseExpression(tokens, true, variableMap); - + ParserUtil.checkReturnType(value, variableMap.get(identifier.getContent())); - - return new Assignment<>(value, identifier.getContent(), identifier.getPosition()); + + return new VariableAssignmentNode<>(value, identifier.getContent(), identifier.getPosition()); } - - private Function parseFunction(Tokenizer tokens, boolean fullStatement, Map variableMap) throws ParseException { + + private Function parseFunction(Tokenizer tokens, boolean fullStatement, Map variableMap) { Token identifier = tokens.consume(); ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier - + if(!functions.containsKey(identifier.getContent())) throw new ParseException("No such function \"" + identifier.getContent() + "\"", identifier.getPosition()); - + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); // Second is body begin - - + + List> args = getArgs(tokens, variableMap); // Extract arguments, consume the rest. - + ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); // Remove body end - + if(fullStatement) ParserUtil.checkType(tokens.get(), Token.Type.STATEMENT_END); - + + if(ignoredFunctions.contains(identifier.getContent())) { + return Function.NULL; + } + if(functions.containsKey(identifier.getContent())) { FunctionBuilder builder = functions.get(identifier.getContent()); - + if(builder.argNumber() != -1 && args.size() != builder.argNumber()) throw new ParseException("Expected " + builder.argNumber() + " arguments, found " + args.size(), identifier.getPosition()); - + for(int i = 0; i < args.size(); i++) { Returnable argument = args.get(i); if(builder.getArgument(i) == null) - throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent(), identifier.getPosition()); + throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent(), + identifier.getPosition()); ParserUtil.checkReturnType(argument, builder.getArgument(i)); } return builder.build(args, identifier.getPosition()); } throw new UnsupportedOperationException("Unsupported function: " + identifier.getContent()); } - - - private List> getArgs(Tokenizer tokens, Map variableMap) throws ParseException { - List> args = new GlueList<>(); - + + private List> getArgs(Tokenizer tokens, Map variableMap) { + List> args = new ArrayList<>(); + while(!tokens.get().getType().equals(Token.Type.GROUP_END)) { args.add(parseExpression(tokens, true, variableMap)); ParserUtil.checkType(tokens.get(), Token.Type.SEPARATOR, Token.Type.GROUP_END); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/ParserUtil.java similarity index 61% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/ParserUtil.java index 724ac9099..6a7f0c7bf 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/ParserUtil.java @@ -1,96 +1,111 @@ -package com.dfsek.terra.api.structures.parser; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Token; +package com.dfsek.terra.addons.terrascript.parser; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Token; + + public class ParserUtil { - + private static final Map> PRECEDENCE = new HashMap<>(); // If second has precedence, true. - private static final List ARITHMETIC = Arrays.asList(Token.Type.ADDITION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, Token.Type.MODULO_OPERATOR); - private static final List COMPARISON = Arrays.asList(Token.Type.EQUALS_OPERATOR, Token.Type.NOT_EQUALS_OPERATOR, Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, Token.Type.GREATER_THAN_OPERATOR, Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR); - + private static final List ARITHMETIC = Arrays.asList(Token.Type.ADDITION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, + Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, + Token.Type.MODULO_OPERATOR); + private static final List COMPARISON = Arrays.asList(Token.Type.EQUALS_OPERATOR, Token.Type.NOT_EQUALS_OPERATOR, + Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, + Token.Type.GREATER_THAN_OPERATOR, + Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR); + static { // Setup precedence Map add = new HashMap<>(); // Addition/subtraction before Multiplication/division. add.put(Token.Type.MULTIPLICATION_OPERATOR, true); add.put(Token.Type.DIVISION_OPERATOR, true); - + PRECEDENCE.put(Token.Type.ADDITION_OPERATOR, add); PRECEDENCE.put(Token.Type.SUBTRACTION_OPERATOR, add); - + Map numericBoolean = new HashMap<>(); - + ARITHMETIC.forEach(op -> numericBoolean.put(op, true)); // Numbers before comparison COMPARISON.forEach(op -> PRECEDENCE.put(op, numericBoolean)); - - + + Map booleanOps = new HashMap<>(); ARITHMETIC.forEach(op -> booleanOps.put(op, true)); // Everything before boolean COMPARISON.forEach(op -> booleanOps.put(op, true)); - - + + PRECEDENCE.put(Token.Type.BOOLEAN_AND, booleanOps); PRECEDENCE.put(Token.Type.BOOLEAN_OR, booleanOps); } - - public static void checkType(Token token, Token.Type... expected) throws ParseException { + + public static void checkType(Token token, Token.Type... expected) { for(Token.Type type : expected) if(token.getType().equals(type)) return; throw new ParseException("Expected " + Arrays.toString(expected) + " but found " + token.getType(), token.getPosition()); } - - public static void checkReturnType(Returnable returnable, Returnable.ReturnType... types) throws ParseException { + + public static void checkReturnType(Returnable returnable, Returnable.ReturnType... types) { for(Returnable.ReturnType type : types) if(returnable.returnType().equals(type)) return; throw new ParseException("Expected " + Arrays.toString(types) + " but found " + returnable.returnType(), returnable.getPosition()); } - - public static void checkArithmeticOperation(Returnable left, Returnable right, Token operation) throws ParseException { + + public static void checkArithmeticOperation(Returnable left, Returnable right, Token operation) { if(!left.returnType().equals(Returnable.ReturnType.NUMBER) || !right.returnType().equals(Returnable.ReturnType.NUMBER)) { - throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(), operation.getPosition()); + throw new ParseException( + "Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(), + operation.getPosition()); } } - - public static void checkBooleanOperation(Returnable left, Returnable right, Token operation) throws ParseException { + + public static void checkBooleanOperation(Returnable left, Returnable right, Token operation) { if(!left.returnType().equals(Returnable.ReturnType.BOOLEAN) || !right.returnType().equals(Returnable.ReturnType.BOOLEAN)) { - throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(), operation.getPosition()); + throw new ParseException( + "Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(), + operation.getPosition()); } } - - public static void checkVarType(Token token, Returnable.ReturnType returnType) throws ParseException { + + public static void checkVarType(Token token, Returnable.ReturnType returnType) { if(returnType.equals(Returnable.ReturnType.STRING) && token.getType().equals(Token.Type.STRING_VARIABLE)) return; if(returnType.equals(Returnable.ReturnType.NUMBER) && token.getType().equals(Token.Type.NUMBER_VARIABLE)) return; if(returnType.equals(Returnable.ReturnType.BOOLEAN) && token.getType().equals(Token.Type.BOOLEAN_VARIABLE)) return; throw new ParseException("Type mismatch, cannot convert from " + returnType + " to " + token.getType(), token.getPosition()); } - + /** * Checks if token is a binary operator * * @param token Token to check + * * @throws ParseException If token isn't a binary operator */ - public static void checkBinaryOperator(Token token) throws ParseException { + public static void checkBinaryOperator(Token token) { if(!token.isBinaryOperator()) throw new ParseException("Expected binary operator, found " + token.getType(), token.getPosition()); } - - public static Returnable.ReturnType getVariableReturnType(Token varToken) throws ParseException { - switch(varToken.getType()) { - case NUMBER_VARIABLE: - return Returnable.ReturnType.NUMBER; - case STRING_VARIABLE: - return Returnable.ReturnType.STRING; - case BOOLEAN_VARIABLE: - return Returnable.ReturnType.BOOLEAN; - default: - throw new ParseException("Unexpected token " + varToken.getType() + "; expected variable declaration", varToken.getPosition()); - } + + public static Returnable.ReturnType getVariableReturnType(Token varToken) { + return switch(varToken.getType()) { + case NUMBER_VARIABLE -> Returnable.ReturnType.NUMBER; + case STRING_VARIABLE -> Returnable.ReturnType.STRING; + case BOOLEAN_VARIABLE -> Returnable.ReturnType.BOOLEAN; + default -> throw new ParseException("Unexpected token " + varToken.getType() + "; expected variable declaration", + varToken.getPosition()); + }; } - + public static boolean hasPrecedence(Token.Type first, Token.Type second) { if(!PRECEDENCE.containsKey(first)) return false; Map pre = PRECEDENCE.get(first); diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/exceptions/ParseException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/exceptions/ParseException.java similarity index 55% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/exceptions/ParseException.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/exceptions/ParseException.java index 03bd8d5e4..59fdb01ae 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/exceptions/ParseException.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/exceptions/ParseException.java @@ -1,26 +1,37 @@ -package com.dfsek.terra.api.structures.parser.exceptions; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.structures.tokenizer.Position; +package com.dfsek.terra.addons.terrascript.parser.exceptions; -public class ParseException extends Exception { +import java.io.Serial; + +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class ParseException extends RuntimeException { + @Serial private static final long serialVersionUID = 6744390543046766386L; private final Position position; - + public ParseException(String message, Position position) { super(message); this.position = position; } - + public ParseException(String message, Position position, Throwable cause) { super(message, cause); this.position = position; } - + @Override public String getMessage() { return super.getMessage() + ": " + position; } - + public Position getPosition() { return position; } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Block.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Block.java similarity index 56% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Block.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Block.java index b3d47b2fb..473d033ef 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Block.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Block.java @@ -1,76 +1,95 @@ -package com.dfsek.terra.api.structures.parser.lang; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; +package com.dfsek.terra.addons.terrascript.parser.lang; -import java.util.HashMap; import java.util.List; -import java.util.Map; + +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + public class Block implements Item> { private final List> items; private final Position position; - + public Block(List> items, Position position) { this.items = items; this.position = position; } - - public List> getItems() { - return items; - } - + public ReturnInfo apply(ImplementationArguments implementationArguments) { - return apply(implementationArguments, new HashMap<>()); + return apply(implementationArguments, new Scope()); } - + @Override - public ReturnInfo apply(ImplementationArguments implementationArguments, Map> variableMap) { - Map> scope = new HashMap<>(variableMap); + public ReturnInfo apply(ImplementationArguments implementationArguments, Scope scope) { + Scope sub = scope.sub(); for(Item item : items) { - Object result = item.apply(implementationArguments, scope); - if(result instanceof ReturnInfo) { - ReturnInfo level = (ReturnInfo) result; + Object result = item.apply(implementationArguments, sub); + if(result instanceof ReturnInfo level) { if(!level.getLevel().equals(ReturnLevel.NONE)) return level; } } return new ReturnInfo<>(ReturnLevel.NONE, null); } - + + public ReturnInfo applyNoNewScope(ImplementationArguments implementationArguments, Scope scope) { + for(Item item : items) { + Object result = item.apply(implementationArguments, scope); + if(result instanceof ReturnInfo level) { + if(!level.getLevel().equals(ReturnLevel.NONE)) return level; + } + } + return new ReturnInfo<>(ReturnLevel.NONE, null); + } + @Override public Position getPosition() { return position; } - - public static class ReturnInfo { - private final ReturnLevel level; - private final T data; - - public ReturnInfo(ReturnLevel level, T data) { - this.level = level; - this.data = data; - } - - public ReturnLevel getLevel() { - return level; - } - - public T getData() { - return data; - } + + public List> getItems() { + return items; } - + public enum ReturnLevel { - NONE(false), BREAK(false), CONTINUE(false), RETURN(true), FAIL(true); - + NONE(false), + BREAK(false), + CONTINUE(false), + RETURN(true), + FAIL(true); + private final boolean returnFast; - + ReturnLevel(boolean returnFast) { this.returnFast = returnFast; } - + public boolean isReturnFast() { return returnFast; } } + + + public static class ReturnInfo { + private final ReturnLevel level; + private final T data; + + public ReturnInfo(ReturnLevel level, T data) { + this.level = level; + this.data = data; + } + + public ReturnLevel getLevel() { + return level; + } + + public T getData() { + return data; + } + } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/ImplementationArguments.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/ImplementationArguments.java new file mode 100644 index 000000000..a0f78aefb --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/ImplementationArguments.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang; + +/** + * Arguments passed to {@link Item}s by the implementation + */ +public interface ImplementationArguments { +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Item.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Item.java new file mode 100644 index 000000000..10065bfc9 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Item.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang; + +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public interface Item { + T apply(ImplementationArguments implementationArguments, Scope scope); + + Position getPosition(); +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Keyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Keyword.java new file mode 100644 index 000000000..56bb8bfd8 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Keyword.java @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang; + +public interface Keyword extends Returnable { +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Returnable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Returnable.java new file mode 100644 index 000000000..ac6578f4c --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Returnable.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang; + +public interface Returnable extends Item { + ReturnType returnType(); + + enum ReturnType { + NUMBER(true), + STRING(true), + BOOLEAN(false), + VOID(false), + OBJECT(false); + + private final boolean comparable; + + ReturnType(boolean comparable) { + this.comparable = comparable; + } + + public boolean isComparable() { + return comparable; + } + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java new file mode 100644 index 000000000..a511e2db4 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java @@ -0,0 +1,46 @@ +package com.dfsek.terra.addons.terrascript.parser.lang; + +import java.util.HashMap; +import java.util.Map; + +import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable; + + +public class Scope { + private static final Scope NULL = new Scope() { + @Override + public Variable get(String id) { + throw new IllegalStateException("Cannot get variable from null scope: " + id); + } + + @Override + public void put(String id, Variable variable) { + throw new IllegalStateException("Cannot set variable in null scope: " + id); + } + }; + + private final Scope parent; + private final Map> variableMap = new HashMap<>(); + + public Scope(Scope parent) { + this.parent = parent; + } + + public Scope() { + this.parent = NULL; + } + + public Variable get(String id) { + Variable var = variableMap.get(id); + return var == null ? parent.get(id) : var; + } + + public void put(String id, Variable variable) { + variableMap.put(id, variable); + } + + + public Scope sub() { + return new Scope(this); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Statement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Statement.java new file mode 100644 index 000000000..14300e5fa --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Statement.java @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang; + +public interface Statement extends Item { +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java new file mode 100644 index 000000000..b61e05364 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.constants; + +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class BooleanConstant extends ConstantExpression { + public BooleanConstant(Boolean constant, Position position) { + super(constant, position); + } + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/ConstantExpression.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/ConstantExpression.java new file mode 100644 index 000000000..dc783a628 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/ConstantExpression.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.constants; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public abstract class ConstantExpression implements Returnable { + private final T constant; + private final Position position; + + public ConstantExpression(T constant, Position position) { + this.constant = constant; + this.position = position; + } + + @Override + public T apply(ImplementationArguments implementationArguments, Scope scope) { + return constant; + } + + @Override + public Position getPosition() { + return position; + } + + public T getConstant() { + return constant; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java new file mode 100644 index 000000000..911f601f2 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.constants; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class NumericConstant extends ConstantExpression { + public NumericConstant(Number constant, Position position) { + super(constant, position); + } + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.NUMBER; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/StringConstant.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/StringConstant.java new file mode 100644 index 000000000..3e44bea10 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/StringConstant.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.constants; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class StringConstant extends ConstantExpression { + public StringConstant(String constant, Position position) { + super(constant, position); + } + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.STRING; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java new file mode 100644 index 000000000..da27138b6 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.functions; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public interface Function extends Returnable { + Function NULL = new Function<>() { + @Override + public ReturnType returnType() { + return null; + } + + @Override + public Object apply(ImplementationArguments implementationArguments, Scope scope) { + return null; + } + + @Override + public Position getPosition() { + return null; + } + }; +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/FunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/FunctionBuilder.java new file mode 100644 index 000000000..d43121c6f --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/FunctionBuilder.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.functions; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public interface FunctionBuilder> { + T build(List> argumentList, Position position); + + int argNumber(); + + Returnable.ReturnType getArgument(int position); +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/BreakKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/BreakKeyword.java new file mode 100644 index 000000000..b70b656ee --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/BreakKeyword.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow; + +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class BreakKeyword implements Keyword> { + private final Position position; + + public BreakKeyword(Position position) { + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Scope scope) { + return new Block.ReturnInfo<>(Block.ReturnLevel.BREAK, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ContinueKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ContinueKeyword.java new file mode 100644 index 000000000..f7b03d3b4 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ContinueKeyword.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow; + +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class ContinueKeyword implements Keyword> { + private final Position position; + + public ContinueKeyword(Position position) { + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Scope scope) { + return new Block.ReturnInfo<>(Block.ReturnLevel.CONTINUE, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/FailKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/FailKeyword.java new file mode 100644 index 000000000..4f6a82f50 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/FailKeyword.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow; + +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class FailKeyword implements Keyword> { + private final Position position; + + public FailKeyword(Position position) { + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Scope scope) { + return new Block.ReturnInfo<>(Block.ReturnLevel.FAIL, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ReturnKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ReturnKeyword.java new file mode 100644 index 000000000..997098af1 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ReturnKeyword.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow; + +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class ReturnKeyword implements Keyword> { + private final Position position; + + public ReturnKeyword(Position position) { + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Scope scope) { + return new Block.ReturnInfo<>(Block.ReturnLevel.RETURN, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/ForKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/ForKeyword.java new file mode 100644 index 000000000..eebd67183 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/ForKeyword.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike; + +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Item; +import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class ForKeyword implements Keyword> { + private final Block conditional; + private final Item initializer; + private final Returnable statement; + private final Item incrementer; + private final Position position; + + public ForKeyword(Block conditional, Item initializer, Returnable statement, Item incrementer, Position position) { + this.conditional = conditional; + this.initializer = initializer; + this.statement = statement; + this.incrementer = incrementer; + this.position = position; + } + + @Override + public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Scope scope) { + Scope sub = scope.sub(); + for(initializer.apply(implementationArguments, sub); + statement.apply(implementationArguments, sub); + incrementer.apply(implementationArguments, sub)) { + Block.ReturnInfo level = conditional.applyNoNewScope(implementationArguments, sub); + if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break; + if(level.getLevel().isReturnFast()) return level; + } + return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/IfKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java similarity index 59% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/IfKeyword.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java index 1e639acfa..c3737433e 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/IfKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java @@ -1,15 +1,23 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords.looplike; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike; -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Keyword; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; import org.jetbrains.annotations.Nullable; import java.util.List; -import java.util.Map; + +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + public class IfKeyword implements Keyword> { private final Block conditional; @@ -17,53 +25,54 @@ public class IfKeyword implements Keyword> { private final Position position; private final List, Block>> elseIf; private final Block elseBlock; - - public IfKeyword(Block conditional, Returnable statement, List, Block>> elseIf, @Nullable Block elseBlock, Position position) { + + public IfKeyword(Block conditional, Returnable statement, List, Block>> elseIf, + @Nullable Block elseBlock, Position position) { this.conditional = conditional; this.statement = statement; this.position = position; this.elseIf = elseIf; this.elseBlock = elseBlock; } - + @Override - public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Map> variableMap) { - if(statement.apply(implementationArguments, variableMap)) return conditional.apply(implementationArguments, variableMap); + public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Scope scope) { + if(statement.apply(implementationArguments, scope)) return conditional.apply(implementationArguments, scope); else { for(Pair, Block> pair : elseIf) { - if(pair.getLeft().apply(implementationArguments, variableMap)) { - return pair.getRight().apply(implementationArguments, variableMap); + if(pair.getLeft().apply(implementationArguments, scope)) { + return pair.getRight().apply(implementationArguments, scope); } } - if(elseBlock != null) return elseBlock.apply(implementationArguments, variableMap); + if(elseBlock != null) return elseBlock.apply(implementationArguments, scope); } return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null); } - - + @Override public Position getPosition() { return position; } - + @Override public ReturnType returnType() { return ReturnType.VOID; } - + + public static class Pair { private final L left; private final R right; - + public Pair(L left, R right) { this.left = left; this.right = right; } - + public L getLeft() { return left; } - + public R getRight() { return right; } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/WhileKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/WhileKeyword.java similarity index 53% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/WhileKeyword.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/WhileKeyword.java index 4eeb18107..d5126e7db 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/WhileKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/WhileKeyword.java @@ -1,40 +1,46 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords.looplike; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Keyword; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; +package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike; + +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; -import java.util.Map; public class WhileKeyword implements Keyword> { private final Block conditional; private final Returnable statement; private final Position position; - + public WhileKeyword(Block conditional, Returnable statement, Position position) { this.conditional = conditional; this.statement = statement; this.position = position; } - + @Override - public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Map> variableMap) { - while(statement.apply(implementationArguments, variableMap)) { - Block.ReturnInfo level = conditional.apply(implementationArguments, variableMap); + public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Scope scope) { + while(statement.apply(implementationArguments, scope)) { + Block.ReturnInfo level = conditional.apply(implementationArguments, scope); if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break; if(level.getLevel().isReturnFast()) return level; } return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null); } - + @Override public Position getPosition() { return position; } - + @Override public ReturnType returnType() { return ReturnType.VOID; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java new file mode 100644 index 000000000..11a4d74e8 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public abstract class BinaryOperation implements Returnable { + private final Returnable left; + private final Returnable right; + private final Position start; + + public BinaryOperation(Returnable left, Returnable right, Position start) { + this.left = left; + this.right = right; + this.start = start; + } + + public abstract O apply(Supplier left, Supplier right); + + @Override + public O apply(ImplementationArguments implementationArguments, Scope scope) { + return apply(() -> left.apply(implementationArguments, scope), () -> right.apply(implementationArguments, scope)); + } + + @Override + public Position getPosition() { + return start; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java new file mode 100644 index 000000000..6018b21d0 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class BooleanAndOperation extends BinaryOperation { + public BooleanAndOperation(Returnable left, Returnable right, Position start) { + super(left, right, start); + } + + @Override + public Boolean apply(Supplier left, Supplier right) { + return left.get() && right.get(); + } + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanNotOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanNotOperation.java new file mode 100644 index 000000000..e1b4d2fed --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanNotOperation.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class BooleanNotOperation extends UnaryOperation { + public BooleanNotOperation(Returnable input, Position position) { + super(input, position); + } + + @Override + public Boolean apply(Boolean input) { + return !input; + } + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java new file mode 100644 index 000000000..90b11cf86 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class BooleanOrOperation extends BinaryOperation { + public BooleanOrOperation(Returnable left, Returnable right, Position start) { + super(left, right, start); + } + + @Override + public Boolean apply(Supplier left, Supplier right) { + return left.get() || right.get(); + } + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java new file mode 100644 index 000000000..79fd3d103 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class ConcatenationOperation extends BinaryOperation { + public ConcatenationOperation(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public String apply(Supplier left, Supplier right) { + return left.get().toString() + right.get().toString(); + } + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.STRING; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java new file mode 100644 index 000000000..b6d76c451 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class DivisionOperation extends BinaryOperation { + public DivisionOperation(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Number apply(Supplier left, Supplier right) { + return left.get().doubleValue() / right.get().doubleValue(); + } + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.NUMBER; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java new file mode 100644 index 000000000..a22439b6d --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class ModuloOperation extends BinaryOperation { + public ModuloOperation(Returnable left, Returnable right, Position start) { + super(left, right, start); + } + + @Override + public Number apply(Supplier left, Supplier right) { + return left.get().doubleValue() % right.get().doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java new file mode 100644 index 000000000..232d8ee52 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class MultiplicationOperation extends BinaryOperation { + public MultiplicationOperation(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Number apply(Supplier left, Supplier right) { + return left.get().doubleValue() * right.get().doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NegationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NegationOperation.java new file mode 100644 index 000000000..2f9ee5161 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NegationOperation.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class NegationOperation extends UnaryOperation { + public NegationOperation(Returnable input, Position position) { + super(input, position); + } + + @Override + public Number apply(Number input) { + return -input.doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java new file mode 100644 index 000000000..7baa56df3 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class NumberAdditionOperation extends BinaryOperation { + public NumberAdditionOperation(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Number apply(Supplier left, Supplier right) { + return left.get().doubleValue() + right.get().doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java new file mode 100644 index 000000000..70e6709b7 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class SubtractionOperation extends BinaryOperation { + public SubtractionOperation(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Number apply(Supplier left, Supplier right) { + return left.get().doubleValue() - right.get().doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java new file mode 100644 index 000000000..b8e9c1770 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public abstract class UnaryOperation implements Returnable { + private final Returnable input; + private final Position position; + + public UnaryOperation(Returnable input, Position position) { + this.input = input; + this.position = position; + } + + public abstract T apply(T input); + + @Override + public T apply(ImplementationArguments implementationArguments, Scope scope) { + return apply(input.apply(implementationArguments, scope)); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java new file mode 100644 index 000000000..6552a8cc8 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; + +import net.jafama.FastMath; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + +import static com.dfsek.terra.api.util.MathUtil.EPSILON; + + +public class EqualsStatement extends BinaryOperation { + + public EqualsStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Supplier left, Supplier right) { + Object leftUnwrapped = left.get(); + Object rightUnwrapped = right.get(); + if(leftUnwrapped instanceof Number l && rightUnwrapped instanceof Number r) { + return FastMath.abs(l.doubleValue() - r.doubleValue()) <= EPSILON; + } + + return left.equals(rightUnwrapped); + } + + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.BOOLEAN; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java new file mode 100644 index 000000000..2c795b1c9 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class GreaterOrEqualsThanStatement extends BinaryOperation { + public GreaterOrEqualsThanStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Supplier left, Supplier right) { + return left.get().doubleValue() >= right.get().doubleValue(); + } + + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.BOOLEAN; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java new file mode 100644 index 000000000..a6c7d8e52 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterThanStatement.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class GreaterThanStatement extends BinaryOperation { + public GreaterThanStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Supplier left, Supplier right) { + return left.get().doubleValue() > right.get().doubleValue(); + } + + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.BOOLEAN; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java new file mode 100644 index 000000000..d798a6590 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class LessThanOrEqualsStatement extends BinaryOperation { + public LessThanOrEqualsStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Supplier left, Supplier right) { + return left.get().doubleValue() <= right.get().doubleValue(); + } + + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.BOOLEAN; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java new file mode 100644 index 000000000..04bca475c --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class LessThanStatement extends BinaryOperation { + public LessThanStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Supplier left, Supplier right) { + return left.get().doubleValue() < right.get().doubleValue(); + } + + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.BOOLEAN; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java new file mode 100644 index 000000000..20fb34fe3 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; + +import net.jafama.FastMath; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + +import static com.dfsek.terra.api.util.MathUtil.EPSILON; + + +public class NotEqualsStatement extends BinaryOperation { + public NotEqualsStatement(Returnable left, Returnable right, Position position) { + super(left, right, position); + } + + @Override + public Boolean apply(Supplier left, Supplier right) { + Object leftUnwrapped = left.get(); + Object rightUnwrapped = right.get(); + if(leftUnwrapped instanceof Number l && rightUnwrapped instanceof Number r) { + return FastMath.abs(l.doubleValue() - r.doubleValue()) > EPSILON; + } + + return !leftUnwrapped.equals(rightUnwrapped); + } + + + @Override + public Returnable.ReturnType returnType() { + return Returnable.ReturnType.BOOLEAN; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/BooleanVariable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/BooleanVariable.java similarity index 58% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/BooleanVariable.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/BooleanVariable.java index ad0ed5400..205c99e6f 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/BooleanVariable.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/BooleanVariable.java @@ -1,32 +1,40 @@ -package com.dfsek.terra.api.structures.parser.lang.variables; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.variables; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; public class BooleanVariable implements Variable { private final Position position; private Boolean value; - + public BooleanVariable(Boolean value, Position position) { this.value = value; this.position = position; } - + @Override public Boolean getValue() { return value; } - + @Override public void setValue(Boolean value) { this.value = value; } - + @Override public Returnable.ReturnType getType() { return Returnable.ReturnType.BOOLEAN; } - + @Override public Position getPosition() { return position; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/NumberVariable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/NumberVariable.java similarity index 58% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/NumberVariable.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/NumberVariable.java index 6f7355cb4..698afdd4d 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/NumberVariable.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/NumberVariable.java @@ -1,32 +1,40 @@ -package com.dfsek.terra.api.structures.parser.lang.variables; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.variables; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; public class NumberVariable implements Variable { private final Position position; private Number value; - + public NumberVariable(Number value, Position position) { this.value = value; this.position = position; } - + @Override public Number getValue() { return value; } - + @Override public void setValue(Number value) { this.value = value; } - + @Override public Returnable.ReturnType getType() { return Returnable.ReturnType.NUMBER; } - + @Override public Position getPosition() { return position; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/StringVariable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/StringVariable.java similarity index 58% rename from common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/StringVariable.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/StringVariable.java index a2b48e73e..3ed471cd6 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/StringVariable.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/StringVariable.java @@ -1,32 +1,40 @@ -package com.dfsek.terra.api.structures.parser.lang.variables; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.variables; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; public class StringVariable implements Variable { private final Position position; private String value; - + public StringVariable(String value, Position position) { this.value = value; this.position = position; } - + @Override public String getValue() { return value; } - + @Override public void setValue(String value) { this.value = value; } - + @Override public Returnable.ReturnType getType() { return Returnable.ReturnType.STRING; } - + @Override public Position getPosition() { return position; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/Variable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/Variable.java new file mode 100644 index 000000000..4bf0d6752 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/Variable.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.variables; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public interface Variable { + T getValue(); + + void setValue(T value); + + Returnable.ReturnType getType(); + + Position getPosition(); +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableAssignmentNode.java new file mode 100644 index 000000000..af833d570 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableAssignmentNode.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.variables; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Item; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class VariableAssignmentNode implements Item { + private final Returnable value; + private final Position position; + private final String identifier; + + public VariableAssignmentNode(Returnable value, String identifier, Position position) { + this.value = value; + this.identifier = identifier; + this.position = position; + } + + @SuppressWarnings("unchecked") + @Override + public synchronized T apply(ImplementationArguments implementationArguments, Scope scope) { + T val = value.apply(implementationArguments, scope); + ((Variable) scope.get(identifier)).setValue(val); + return val; + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableDeclarationNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableDeclarationNode.java new file mode 100644 index 000000000..ceae122a3 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableDeclarationNode.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.variables; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Item; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class VariableDeclarationNode implements Item { + private final Position position; + private final String identifier; + private final Returnable value; + private final Returnable.ReturnType type; + + public VariableDeclarationNode(Position position, String identifier, Returnable value, Returnable.ReturnType type) { + switch(type) { + case STRING: + case BOOLEAN: + case NUMBER: + break; + default: + throw new IllegalArgumentException("Invalid variable type: " + type); + } + this.position = position; + this.identifier = identifier; + this.value = value; + this.type = type; + } + + @Override + public T apply(ImplementationArguments implementationArguments, Scope scope) { + T result = value.apply(implementationArguments, scope); + scope.put(identifier, switch(type) { + case NUMBER -> new NumberVariable((Number) result, position); + case BOOLEAN -> new BooleanVariable((Boolean) result, position); + case STRING -> new StringVariable((String) result, position); + default -> throw new IllegalStateException("Unexpected value: " + type); + }); + return result; + } + + @Override + public Position getPosition() { + return position; + } + + public Returnable.ReturnType getType() { + return type; + } + + public String getIdentifier() { + return identifier; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableReferenceNode.java new file mode 100644 index 000000000..3d017b364 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/VariableReferenceNode.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.parser.lang.variables; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class VariableReferenceNode implements Returnable { + private final String identifier; + private final Position position; + private final ReturnType type; + + public VariableReferenceNode(String identifier, Position position, ReturnType type) { + this.identifier = identifier; + this.position = position; + this.type = type; + } + + @Override + public ReturnType returnType() { + return type; + } + + @Override + public synchronized Object apply(ImplementationArguments implementationArguments, Scope scope) { + return scope.get(identifier).getValue(); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java new file mode 100644 index 000000000..363fc47ca --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script; + +import net.jafama.FastMath; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Random; + +import com.dfsek.terra.addons.terrascript.parser.Parser; +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.BinaryNumberFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.BiomeFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.BlockFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.CheckBlockFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.EntityFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.GetMarkFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.LootFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.PullFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.RandomFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.RecursionsFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.SetMarkFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.StateFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.StructureFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.UnaryBooleanFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.UnaryNumberFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.UnaryStringFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.ZeroArgFunctionBuilder; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.registry.key.Keyed; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.structure.LootTable; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.WritableWorld; + + +public class StructureScript implements Structure, Keyed { + private static final Logger LOGGER = LoggerFactory.getLogger(StructureScript.class); + private final Block block; + private final RegistryKey id; + + private final String profile; + private final Platform platform; + + @SuppressWarnings("rawtypes") + public StructureScript(InputStream inputStream, RegistryKey id, Platform platform, Registry registry, + Registry lootRegistry, + Registry functionRegistry) { + Parser parser; + try { + parser = new Parser(IOUtils.toString(inputStream, Charset.defaultCharset())); + } catch(IOException e) { + throw new RuntimeException(e); + } + this.id = id; + this.profile = "terrascript_direct:" + id; + + //noinspection unchecked + functionRegistry.forEach((key, function) -> parser.registerFunction(key.getID(), function)); // Register registry functions. + + parser + .registerFunction("block", new BlockFunctionBuilder(platform)) + .registerFunction("debugBlock", new BlockFunctionBuilder(platform)) + .registerFunction("structure", new StructureFunctionBuilder(registry, platform)) + .registerFunction("randomInt", new RandomFunctionBuilder()) + .registerFunction("recursions", new RecursionsFunctionBuilder()) + .registerFunction("setMark", new SetMarkFunctionBuilder()) + .registerFunction("getMark", new GetMarkFunctionBuilder()) + .registerFunction("pull", new PullFunctionBuilder(platform)) + .registerFunction("loot", new LootFunctionBuilder(platform, lootRegistry, this)) + .registerFunction("entity", new EntityFunctionBuilder(platform)) + .registerFunction("getBiome", new BiomeFunctionBuilder(platform)) + .registerFunction("getBlock", new CheckBlockFunctionBuilder()) + .registerFunction("state", new StateFunctionBuilder(platform)) + .registerFunction("setWaterlog", new UnaryBooleanFunctionBuilder((waterlog, args) -> args.setWaterlog(waterlog))) + .registerFunction("originX", new ZeroArgFunctionBuilder(arguments -> arguments.getOrigin().getX(), + Returnable.ReturnType.NUMBER)) + .registerFunction("originY", new ZeroArgFunctionBuilder(arguments -> arguments.getOrigin().getY(), + Returnable.ReturnType.NUMBER)) + .registerFunction("originZ", new ZeroArgFunctionBuilder(arguments -> arguments.getOrigin().getZ(), + Returnable.ReturnType.NUMBER)) + .registerFunction("rotation", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().toString(), + Returnable.ReturnType.STRING)) + .registerFunction("rotationDegrees", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().getDegrees(), + Returnable.ReturnType.NUMBER)) + .registerFunction("print", + new UnaryStringFunctionBuilder(string -> LOGGER.debug("[TerraScript:{}] {}", id, string))) + .registerFunction("abs", new UnaryNumberFunctionBuilder(number -> FastMath.abs(number.doubleValue()))) + .registerFunction("pow2", new UnaryNumberFunctionBuilder(number -> FastMath.pow2(number.doubleValue()))) + .registerFunction("pow", new BinaryNumberFunctionBuilder( + (number, number2) -> FastMath.pow(number.doubleValue(), number2.doubleValue()))) + .registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> FastMath.sqrt(number.doubleValue()))) + .registerFunction("floor", new UnaryNumberFunctionBuilder(number -> FastMath.floor(number.doubleValue()))) + .registerFunction("ceil", new UnaryNumberFunctionBuilder(number -> FastMath.ceil(number.doubleValue()))) + .registerFunction("log", new UnaryNumberFunctionBuilder(number -> FastMath.log(number.doubleValue()))) + .registerFunction("round", new UnaryNumberFunctionBuilder(number -> FastMath.round(number.doubleValue()))) + .registerFunction("sin", new UnaryNumberFunctionBuilder(number -> FastMath.sin(number.doubleValue()))) + .registerFunction("cos", new UnaryNumberFunctionBuilder(number -> FastMath.cos(number.doubleValue()))) + .registerFunction("tan", new UnaryNumberFunctionBuilder(number -> FastMath.tan(number.doubleValue()))) + .registerFunction("asin", new UnaryNumberFunctionBuilder(number -> FastMath.asin(number.doubleValue()))) + .registerFunction("acos", new UnaryNumberFunctionBuilder(number -> FastMath.acos(number.doubleValue()))) + .registerFunction("atan", new UnaryNumberFunctionBuilder(number -> FastMath.atan(number.doubleValue()))) + .registerFunction("max", new BinaryNumberFunctionBuilder( + (number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue()))) + .registerFunction("min", new BinaryNumberFunctionBuilder( + (number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue()))); + + if(!platform.getTerraConfig().isDebugScript()) { + parser.ignoreFunction("debugBlock"); + } + + block = parser.parse(); + this.platform = platform; + } + + @Override + @SuppressWarnings("try") + public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { + platform.getProfiler().push(profile); + boolean result = applyBlock(new TerraImplementationArguments(location, rotation, random, world, 0)); + platform.getProfiler().pop(profile); + return result; + } + + public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation, int recursions) { + platform.getProfiler().push(profile); + boolean result = applyBlock(new TerraImplementationArguments(location, rotation, random, world, recursions)); + platform.getProfiler().pop(profile); + return result; + } + + private boolean applyBlock(TerraImplementationArguments arguments) { + try { + return block.apply(arguments).getLevel() != Block.ReturnLevel.FAIL; + } catch(RuntimeException e) { + LOGGER.error("Failed to generate structure at {}", arguments.getOrigin(), e); + return false; + } + } + + @Override + public RegistryKey getRegistryKey() { + return id; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/TerraImplementationArguments.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/TerraImplementationArguments.java new file mode 100644 index 000000000..b9b9af058 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/TerraImplementationArguments.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.WritableWorld; + + +public class TerraImplementationArguments implements ImplementationArguments { + private final Rotation rotation; + private final Random random; + private final WritableWorld world; + private final Map marks = new HashMap<>(); + private final int recursions; + private final Vector3Int origin; + private boolean waterlog = false; + + public TerraImplementationArguments(Vector3Int origin, Rotation rotation, Random random, WritableWorld world, int recursions) { + this.rotation = rotation; + this.random = random; + this.world = world; + this.recursions = recursions; + this.origin = origin; + } + + public int getRecursions() { + return recursions; + } + + public Random getRandom() { + return random; + } + + public Rotation getRotation() { + return rotation; + } + + public boolean isWaterlog() { + return waterlog; + } + + public void setWaterlog(boolean waterlog) { + this.waterlog = waterlog; + } + + public WritableWorld getWorld() { + return world; + } + + public Vector3Int getOrigin() { + return origin; + } + + public void setMark(Vector3 pos, String mark) { + marks.put(pos, mark); + } + + public String getMark(Vector3 pos) { + return marks.get(pos); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BinaryNumberFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BinaryNumberFunctionBuilder.java similarity index 53% rename from common/src/main/java/com/dfsek/terra/api/structures/script/builders/BinaryNumberFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BinaryNumberFunctionBuilder.java index 780527ab8..0e55e4d3d 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BinaryNumberFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BinaryNumberFunctionBuilder.java @@ -1,50 +1,58 @@ -package com.dfsek.terra.api.structures.script.builders; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; +package com.dfsek.terra.addons.terrascript.script.builders; import java.util.List; -import java.util.Map; import java.util.function.BiFunction; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + public class BinaryNumberFunctionBuilder implements FunctionBuilder> { - + private final BiFunction function; - + public BinaryNumberFunctionBuilder(BiFunction function) { this.function = function; } - + @Override public Function build(List> argumentList, Position position) { - return new Function() { + return new Function<>() { @Override public ReturnType returnType() { return ReturnType.NUMBER; } - + @SuppressWarnings("unchecked") @Override - public Number apply(ImplementationArguments implementationArguments, Map> variableMap) { - return function.apply(((Returnable) argumentList.get(0)).apply(implementationArguments, variableMap), ((Returnable) argumentList.get(1)).apply(implementationArguments, variableMap)); + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return function.apply(((Returnable) argumentList.get(0)).apply(implementationArguments, scope), + ((Returnable) argumentList.get(1)).apply(implementationArguments, scope)); } - + @Override public Position getPosition() { return position; } }; } - + @Override public int argNumber() { return 2; } - + @Override public Returnable.ReturnType getArgument(int position) { if(position == 0 || position == 1) return Returnable.ReturnType.NUMBER; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BiomeFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BiomeFunctionBuilder.java new file mode 100644 index 000000000..98d5e951b --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BiomeFunctionBuilder.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.BiomeFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; + + +public class BiomeFunctionBuilder implements FunctionBuilder { + private final Platform platform; + + public BiomeFunctionBuilder(Platform platform) { + this.platform = platform; + } + + @SuppressWarnings("unchecked") + @Override + public BiomeFunction build(List> argumentList, Position position) { + return new BiomeFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), position); + } + + @Override + public int argNumber() { + return 3; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + default -> null; + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BlockFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BlockFunctionBuilder.java new file mode 100644 index 000000000..daa001ca9 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BlockFunctionBuilder.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.BooleanConstant; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.StringConstant; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.BlockFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; + + +public class BlockFunctionBuilder implements FunctionBuilder { + private final Platform platform; + + public BlockFunctionBuilder(Platform platform) { + this.platform = platform; + } + + @SuppressWarnings("unchecked") + @Override + public BlockFunction build(List> argumentList, Position position) { + if(argumentList.size() < 4) throw new ParseException("Expected data", position); + Returnable booleanReturnable = new BooleanConstant(true, position); + if(argumentList.size() == 5) booleanReturnable = (Returnable) argumentList.get(4); + if(argumentList.get(3) instanceof StringConstant) { + return new BlockFunction.Constant((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), (StringConstant) argumentList.get(3), + booleanReturnable, platform, position); + } + return new BlockFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), booleanReturnable, + platform, position); + } + + @Override + public int argNumber() { + return -1; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + case 3 -> Returnable.ReturnType.STRING; + case 4 -> Returnable.ReturnType.BOOLEAN; + default -> null; + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/CheckBlockFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/CheckBlockFunctionBuilder.java new file mode 100644 index 000000000..2e32cf363 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/CheckBlockFunctionBuilder.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.CheckBlockFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class CheckBlockFunctionBuilder implements FunctionBuilder { + @SuppressWarnings("unchecked") + @Override + public CheckBlockFunction build(List> argumentList, Position position) { + return new CheckBlockFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), position); + } + + @Override + public int argNumber() { + return 3; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + default -> null; + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/EntityFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/EntityFunctionBuilder.java new file mode 100644 index 000000000..305105180 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/EntityFunctionBuilder.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.EntityFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; + + +public class EntityFunctionBuilder implements FunctionBuilder { + private final Platform platform; + + public EntityFunctionBuilder(Platform platform) { + this.platform = platform; + } + + @SuppressWarnings("unchecked") + @Override + public EntityFunction build(List> argumentList, Position position) { + return new EntityFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), platform, position); + } + + @Override + public int argNumber() { + return 4; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + case 3 -> Returnable.ReturnType.STRING; + default -> null; + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/GetMarkFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/GetMarkFunctionBuilder.java new file mode 100644 index 000000000..c38c406d4 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/GetMarkFunctionBuilder.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.GetMarkFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class GetMarkFunctionBuilder implements FunctionBuilder { + + public GetMarkFunctionBuilder() { + } + + @SuppressWarnings("unchecked") + @Override + public GetMarkFunction build(List> argumentList, Position position) { + return new GetMarkFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), position); + } + + @Override + public int argNumber() { + return 3; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + default -> null; + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/LootFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/LootFunctionBuilder.java new file mode 100644 index 000000000..293b5278c --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/LootFunctionBuilder.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.StructureScript; +import com.dfsek.terra.addons.terrascript.script.functions.LootFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.structure.LootTable; + + +public class LootFunctionBuilder implements FunctionBuilder { + private final Platform platform; + private final Registry registry; + private final StructureScript script; + + public LootFunctionBuilder(Platform platform, Registry registry, StructureScript script) { + this.platform = platform; + this.registry = registry; + this.script = script; + } + + @SuppressWarnings("unchecked") + @Override + public LootFunction build(List> argumentList, Position position) { + return new LootFunction(registry, (Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), platform, position, + script); + } + + @Override + public int argNumber() { + return 4; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + case 3 -> Returnable.ReturnType.STRING; + default -> null; + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/PullFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/PullFunctionBuilder.java new file mode 100644 index 000000000..ff970735d --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/PullFunctionBuilder.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.PullFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; + + +public class PullFunctionBuilder implements FunctionBuilder { + private final Platform platform; + + public PullFunctionBuilder(Platform platform) { + this.platform = platform; + } + + @SuppressWarnings("unchecked") + @Override + public PullFunction build(List> argumentList, Position position) { + return new PullFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), platform, position); + } + + @Override + public int argNumber() { + return 4; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + case 3 -> Returnable.ReturnType.STRING; + default -> null; + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RandomFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RandomFunctionBuilder.java new file mode 100644 index 000000000..6cfeaa52d --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RandomFunctionBuilder.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.RandomFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class RandomFunctionBuilder implements FunctionBuilder { + @SuppressWarnings("unchecked") + @Override + public RandomFunction build(List> argumentList, Position position) { + return new RandomFunction((Returnable) argumentList.get(0), position); + } + + @Override + public int argNumber() { + return 1; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + if(position == 0) return Returnable.ReturnType.NUMBER; + return null; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RecursionsFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RecursionsFunctionBuilder.java new file mode 100644 index 000000000..f4b34673e --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RecursionsFunctionBuilder.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.RecursionsFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class RecursionsFunctionBuilder implements FunctionBuilder { + @Override + public RecursionsFunction build(List> argumentList, Position position) { + return new RecursionsFunction(position); + } + + @Override + public int argNumber() { + return 0; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return null; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/SetMarkFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/SetMarkFunctionBuilder.java new file mode 100644 index 000000000..52babac7f --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/SetMarkFunctionBuilder.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.SetMarkFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class SetMarkFunctionBuilder implements FunctionBuilder { + + public SetMarkFunctionBuilder() { + } + + @SuppressWarnings("unchecked") + @Override + public SetMarkFunction build(List> argumentList, Position position) { + return new SetMarkFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), position); + } + + @Override + public int argNumber() { + return 4; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + case 3 -> Returnable.ReturnType.STRING; + default -> null; + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StateFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StateFunctionBuilder.java new file mode 100644 index 000000000..cecd17112 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StateFunctionBuilder.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.StateFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; + + +public class StateFunctionBuilder implements FunctionBuilder { + private final Platform platform; + + public StateFunctionBuilder(Platform platform) { + this.platform = platform; + } + + @SuppressWarnings("unchecked") + @Override + public StateFunction build(List> argumentList, Position position) { + if(argumentList.size() < 4) throw new ParseException("Expected data", position); + return new StateFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), position); + } + + @Override + public int argNumber() { + return 4; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + case 3 -> Returnable.ReturnType.STRING; + default -> null; + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StructureFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StructureFunctionBuilder.java new file mode 100644 index 000000000..69b05554d --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StructureFunctionBuilder.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.builders; + +import java.util.List; +import java.util.stream.Collectors; + +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.functions.StructureFunction; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.structure.Structure; + + +public class StructureFunctionBuilder implements FunctionBuilder { + private final Registry registry; + private final Platform platform; + + public StructureFunctionBuilder(Registry registry, Platform platform) { + this.registry = registry; + this.platform = platform; + } + + @SuppressWarnings("unchecked") + @Override + public StructureFunction build(List> argumentList, Position position) { + if(argumentList.size() < 5) throw new ParseException("Expected rotations", position); + + return new StructureFunction((Returnable) argumentList.remove(0), (Returnable) argumentList.remove(0), + (Returnable) argumentList.remove(0), (Returnable) argumentList.remove(0), + argumentList.stream().map(item -> ((Returnable) item)).collect(Collectors.toList()), registry, + position, platform); + } + + @Override + public int argNumber() { + return -1; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + default -> Returnable.ReturnType.STRING; + }; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryBooleanFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryBooleanFunctionBuilder.java similarity index 53% rename from common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryBooleanFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryBooleanFunctionBuilder.java index add26248e..922f4842f 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryBooleanFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryBooleanFunctionBuilder.java @@ -1,52 +1,60 @@ -package com.dfsek.terra.api.structures.script.builders; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.tokenizer.Position; +package com.dfsek.terra.addons.terrascript.script.builders; import java.util.List; -import java.util.Map; import java.util.function.BiConsumer; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + public class UnaryBooleanFunctionBuilder implements FunctionBuilder> { - + private final BiConsumer function; - + public UnaryBooleanFunctionBuilder(BiConsumer function) { this.function = function; } - + @Override public Function build(List> argumentList, Position position) { - return new Function() { + return new Function<>() { @Override public ReturnType returnType() { return ReturnType.VOID; } - + @SuppressWarnings("unchecked") @Override - public Void apply(ImplementationArguments implementationArguments, Map> variableMap) { - function.accept(((Returnable) argumentList.get(0)).apply(implementationArguments, variableMap), (TerraImplementationArguments) implementationArguments); + public Void apply(ImplementationArguments implementationArguments, Scope scope) { + function.accept(((Returnable) argumentList.get(0)).apply(implementationArguments, scope), + (TerraImplementationArguments) implementationArguments); return null; } - + @Override public Position getPosition() { return position; } }; } - + @Override public int argNumber() { return 1; } - + @Override public Returnable.ReturnType getArgument(int position) { if(position == 0) return Returnable.ReturnType.BOOLEAN; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryNumberFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryNumberFunctionBuilder.java similarity index 56% rename from common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryNumberFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryNumberFunctionBuilder.java index 80b705498..c20bf2479 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryNumberFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryNumberFunctionBuilder.java @@ -1,49 +1,56 @@ -package com.dfsek.terra.api.structures.script.builders; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; +package com.dfsek.terra.addons.terrascript.script.builders; import java.util.List; -import java.util.Map; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + public class UnaryNumberFunctionBuilder implements FunctionBuilder> { - + private final java.util.function.Function function; - + public UnaryNumberFunctionBuilder(java.util.function.Function function) { this.function = function; } - + @Override public Function build(List> argumentList, Position position) { - return new Function() { + return new Function<>() { @Override public ReturnType returnType() { return ReturnType.NUMBER; } - + @SuppressWarnings("unchecked") @Override - public Number apply(ImplementationArguments implementationArguments, Map> variableMap) { - return function.apply(((Returnable) argumentList.get(0)).apply(implementationArguments, variableMap)); + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return function.apply(((Returnable) argumentList.get(0)).apply(implementationArguments, scope)); } - + @Override public Position getPosition() { return position; } }; } - + @Override public int argNumber() { return 1; } - + @Override public Returnable.ReturnType getArgument(int position) { if(position == 0) return Returnable.ReturnType.NUMBER; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryStringFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryStringFunctionBuilder.java similarity index 56% rename from common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryStringFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryStringFunctionBuilder.java index 30932b352..8bc6d7fd1 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/UnaryStringFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryStringFunctionBuilder.java @@ -1,50 +1,57 @@ -package com.dfsek.terra.api.structures.script.builders; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; +package com.dfsek.terra.addons.terrascript.script.builders; import java.util.List; -import java.util.Map; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + public class UnaryStringFunctionBuilder implements FunctionBuilder> { - + private final java.util.function.Consumer function; - + public UnaryStringFunctionBuilder(java.util.function.Consumer function) { this.function = function; } - + @Override public Function build(List> argumentList, Position position) { - return new Function() { + return new Function<>() { @Override public ReturnType returnType() { return ReturnType.VOID; } - + @SuppressWarnings("unchecked") @Override - public Void apply(ImplementationArguments implementationArguments, Map> variableMap) { - function.accept(((Returnable) argumentList.get(0)).apply(implementationArguments, variableMap)); + public Void apply(ImplementationArguments implementationArguments, Scope scope) { + function.accept(((Returnable) argumentList.get(0)).apply(implementationArguments, scope)); return null; } - + @Override public Position getPosition() { return position; } }; } - + @Override public int argNumber() { return 1; } - + @Override public Returnable.ReturnType getArgument(int position) { if(position == 0) return Returnable.ReturnType.STRING; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/ZeroArgFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/ZeroArgFunctionBuilder.java similarity index 57% rename from common/src/main/java/com/dfsek/terra/api/structures/script/builders/ZeroArgFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/ZeroArgFunctionBuilder.java index 0bc7beff1..da7806051 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/ZeroArgFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/ZeroArgFunctionBuilder.java @@ -1,50 +1,57 @@ -package com.dfsek.terra.api.structures.script.builders; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.tokenizer.Position; +package com.dfsek.terra.addons.terrascript.script.builders; import java.util.List; -import java.util.Map; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + public class ZeroArgFunctionBuilder implements FunctionBuilder> { private final java.util.function.Function function; private final Returnable.ReturnType type; - + public ZeroArgFunctionBuilder(java.util.function.Function function, Returnable.ReturnType type) { this.function = function; this.type = type; } - + @Override public Function build(List> argumentList, Position position) { - return new Function() { + return new Function<>() { @Override public ReturnType returnType() { return type; } - + @Override - public T apply(ImplementationArguments implementationArguments, Map> variableMap) { + public T apply(ImplementationArguments implementationArguments, Scope scope) { return function.apply((TerraImplementationArguments) implementationArguments); } - + @Override public Position getPosition() { return position; } }; } - + @Override public int argNumber() { return 0; } - + @Override public Returnable.ReturnType getArgument(int position) { if(position == 0) return type; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BiomeFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BiomeFunction.java new file mode 100644 index 000000000..452b9f43b --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BiomeFunction.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class BiomeFunction implements Function { + private final Returnable x, y, z; + private final Position position; + + + public BiomeFunction(Returnable x, Returnable y, Returnable z, Position position) { + this.x = x; + this.y = y; + this.z = z; + this.position = position; + } + + + @Override + public String apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + + Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()), + arguments.getRotation()); + + + BiomeProvider grid = arguments.getWorld().getBiomeProvider(); + + return grid.getBiome(arguments.getOrigin() + .toVector3() + .mutable() + .add(Vector3.of(FastMath.roundToInt(xz.getX()), + y.apply(implementationArguments, scope).intValue(), + FastMath.roundToInt(xz.getZ()))).immutable(), arguments.getWorld().getSeed()).getID(); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BlockFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BlockFunction.java new file mode 100644 index 000000000..63d754975 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BlockFunction.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import net.jafama.FastMath; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.StringConstant; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; + + +public class BlockFunction implements Function { + private static final Logger logger = LoggerFactory.getLogger(BlockFunction.class); + protected final Returnable x, y, z; + protected final Returnable blockData; + protected final Platform platform; + private final Map data = new HashMap<>(); + private final Returnable overwrite; + private final Position position; + + public BlockFunction(Returnable x, Returnable y, Returnable z, Returnable blockData, + Returnable overwrite, Platform platform, Position position) { + this.x = x; + this.y = y; + this.z = z; + this.blockData = blockData; + this.overwrite = overwrite; + this.platform = platform; + this.position = position; + } + + @Override + public Void apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + BlockState rot = getBlockState(implementationArguments, scope); + setBlock(implementationArguments, scope, arguments, rot); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } + + void setBlock(ImplementationArguments implementationArguments, Scope scope, + TerraImplementationArguments arguments, BlockState rot) { + Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation()); + try { + Vector3.Mutable set = Vector3.of(FastMath.roundToInt(xz.getX()), + y.apply(implementationArguments, scope).doubleValue(), + FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin()); + BlockState current = arguments.getWorld().getBlockState(set); + if(overwrite.apply(implementationArguments, scope) || current.isAir()) { + arguments.getWorld().setBlockState(set, rot); + } + } catch(RuntimeException e) { + logger.error("Failed to place block at location {}", arguments.getOrigin(), e); + } + } + + protected BlockState getBlockState(ImplementationArguments arguments, Scope scope) { + return data.computeIfAbsent(blockData.apply(arguments, scope), platform.getWorldHandle()::createBlockState); + } + + + public static class Constant extends BlockFunction { + private final BlockState state; + + public Constant(Returnable x, Returnable y, Returnable z, StringConstant blockData, + Returnable overwrite, Platform platform, Position position) { + super(x, y, z, blockData, overwrite, platform, position); + this.state = platform.getWorldHandle().createBlockState(blockData.getConstant()); + } + + @Override + protected BlockState getBlockState(ImplementationArguments arguments, Scope scope) { + return state; + } + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/CheckBlockFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/CheckBlockFunction.java new file mode 100644 index 000000000..d2fddf169 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/CheckBlockFunction.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; + + +public class CheckBlockFunction implements Function { + private final Returnable x, y, z; + private final Position position; + + public CheckBlockFunction(Returnable x, Returnable y, Returnable z, Position position) { + this.x = x; + this.y = y; + this.z = z; + this.position = position; + } + + + @Override + public String apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + + Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()), + arguments.getRotation()); + + + String data = arguments.getWorld() + .getBlockState(arguments.getOrigin() + .toVector3() + .mutable() + .add(Vector3.of(FastMath.roundToInt(xz.getX()), + y.apply(implementationArguments, scope) + .doubleValue(), FastMath.roundToInt(xz.getZ())))) + .getAsString(); + if(data.contains("[")) return data.substring(0, data.indexOf('[')); // Strip properties + else return data; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/EntityFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/EntityFunction.java new file mode 100644 index 000000000..9fd51ceac --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/EntityFunction.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.ConstantExpression; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.event.events.world.generation.EntitySpawnEvent; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; + + +public class EntityFunction implements Function { + private final EntityType data; + private final Returnable x, y, z; + private final Position position; + private final Platform platform; + + public EntityFunction(Returnable x, Returnable y, Returnable z, Returnable data, Platform platform, + Position position) { + this.position = position; + this.platform = platform; + if(!(data instanceof ConstantExpression)) throw new ParseException("Entity data must be constant", data.getPosition()); + + this.data = platform.getWorldHandle().getEntity(((ConstantExpression) data).getConstant()); + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Void apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation()); + + Entity entity = arguments.getWorld().spawnEntity(Vector3.of(xz.getX(), y.apply(implementationArguments, scope).doubleValue(), + xz.getZ()) + .mutable() + .add(arguments.getOrigin()) + .add(0.5, 0, 0.5) + .immutable(), data); + platform.getEventManager().callEvent(new EntitySpawnEvent(entity.world().getPack(), entity)); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/GetMarkFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/GetMarkFunction.java new file mode 100644 index 000000000..09e735665 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/GetMarkFunction.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; + + +public class GetMarkFunction implements Function { + private final Returnable x, y, z; + private final Position position; + + public GetMarkFunction(Returnable x, Returnable y, Returnable z, Position position) { + this.position = position; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public String apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation()); + + String mark = arguments.getMark(Vector3.of(FastMath.floorToInt(xz.getX()), FastMath.floorToInt( + y.apply(implementationArguments, scope).doubleValue()), + FastMath.floorToInt(xz.getZ())) + .mutable() + .add(arguments.getOrigin()) + .immutable()); + return mark == null ? "" : mark; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/LootFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/LootFunction.java new file mode 100644 index 000000000..ebadb9288 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/LootFunction.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import net.jafama.FastMath; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Random; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.StructureScript; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.entity.Container; +import com.dfsek.terra.api.event.events.world.generation.LootPopulateEvent; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.structure.LootTable; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; + + +public class LootFunction implements Function { + private static final Logger LOGGER = LoggerFactory.getLogger(LootFunction.class); + private final Registry registry; + private final Returnable data; + private final Returnable x, y, z; + private final Position position; + private final Platform platform; + private final StructureScript script; + + public LootFunction(Registry registry, Returnable x, Returnable y, Returnable z, + Returnable data, Platform platform, Position position, StructureScript script) { + this.registry = registry; + this.position = position; + this.data = data; + this.x = x; + this.y = y; + this.z = z; + this.platform = platform; + this.script = script; + } + + @Override + public Void apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()), + arguments.getRotation()); + + + String id = data.apply(implementationArguments, scope); + + + registry.get(RegistryKey.parse(id)) + .ifPresentOrElse(table -> { + Vector3 apply = Vector3.of(FastMath.roundToInt(xz.getX()), + y.apply(implementationArguments, scope) + .intValue(), + FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin()).immutable(); + + try { + BlockEntity data = arguments.getWorld().getBlockEntity(apply); + if(!(data instanceof Container container)) { + LOGGER.error("Failed to place loot at {}; block {} is not a container", + apply, data); + return; + } + + LootPopulateEvent event = new LootPopulateEvent(container, table, + arguments.getWorld().getPack(), script); + platform.getEventManager().callEvent(event); + if(event.isCancelled()) return; + + event.getTable().fillInventory(container.getInventory(), + new Random(apply.hashCode())); + data.update(false); + } catch(Exception e) { + LOGGER.error("Could not apply loot at {}", apply, e); + e.printStackTrace(); + } + }, + () -> LOGGER.error("No such loot table {}", id)); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/PullFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/PullFunction.java new file mode 100644 index 000000000..70fbbafc5 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/PullFunction.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.ConstantExpression; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; + + +public class PullFunction implements Function { + private final BlockState data; + private final Returnable x, y, z; + private final Position position; + + public PullFunction(Returnable x, Returnable y, Returnable z, Returnable data, Platform platform, + Position position) { + this.position = position; + if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition()); + + this.data = platform.getWorldHandle().createBlockState(((ConstantExpression) data).getConstant()); + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Void apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation()); + + Vector3.Mutable mutable = Vector3.of(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, scope).intValue(), + FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin()); + while(mutable.getY() > arguments.getWorld().getMinHeight()) { + if(!arguments.getWorld().getBlockState(mutable).isAir()) { + arguments.getWorld().setBlockState(mutable, data); + break; + } + mutable.subtract(0, 1, 0); + } + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RandomFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RandomFunction.java new file mode 100644 index 000000000..3170d2645 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RandomFunction.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class RandomFunction implements Function { + private final Returnable numberReturnable; + private final Position position; + + public RandomFunction(Returnable numberReturnable, Position position) { + this.numberReturnable = numberReturnable; + this.position = position; + } + + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } + + @Override + public Integer apply(ImplementationArguments implementationArguments, Scope scope) { + return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt( + numberReturnable.apply(implementationArguments, scope).intValue()); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RecursionsFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RecursionsFunction.java new file mode 100644 index 000000000..6343c1002 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RecursionsFunction.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class RecursionsFunction implements Function { + private final Position position; + + public RecursionsFunction(Position position) { + this.position = position; + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } + + @Override + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + return ((TerraImplementationArguments) implementationArguments).getRecursions(); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/SetMarkFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/SetMarkFunction.java new file mode 100644 index 000000000..43a7436b9 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/SetMarkFunction.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; + + +public class SetMarkFunction implements Function { + private final Returnable x, y, z; + private final Position position; + private final Returnable mark; + + public SetMarkFunction(Returnable x, Returnable y, Returnable z, Returnable mark, Position position) { + this.position = position; + this.mark = mark; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Void apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation()); + + + arguments.setMark(Vector3.of(FastMath.floorToInt(xz.getX()), + FastMath.floorToInt( + y.apply(implementationArguments, scope).doubleValue()), + FastMath.floorToInt(xz.getZ())).mutable().add(arguments.getOrigin()).immutable(), + mark.apply(implementationArguments, scope)); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StateFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StateFunction.java new file mode 100644 index 000000000..6ccbe1a80 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StateFunction.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import net.jafama.FastMath; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; + + +public class StateFunction implements Function { + private static final Logger LOGGER = LoggerFactory.getLogger(StateFunction.class); + private final Returnable data; + private final Returnable x, y, z; + private final Position position; + + public StateFunction(Returnable x, Returnable y, Returnable z, Returnable data, + Position position) { + this.position = position; + this.data = data; + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public Void apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation()); + + + Vector3 origin = Vector3.of(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, scope).intValue(), + FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin()).immutable(); + try { + BlockEntity state = arguments.getWorld().getBlockEntity(origin); + state.applyState(data.apply(implementationArguments, scope)); + state.update(false); + } catch(Exception e) { + LOGGER.warn("Could not apply BlockState at {}", origin, e); + e.printStackTrace(); + } + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StructureFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StructureFunction.java new file mode 100644 index 000000000..51fb47054 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StructureFunction.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.script.functions; + +import net.jafama.FastMath; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.StructureScript; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; + + +public class StructureFunction implements Function { + private static final Logger LOGGER = LoggerFactory.getLogger(StructureFunction.class); + private final Registry registry; + private final Returnable id; + private final Returnable x, y, z; + private final Position position; + private final Platform platform; + private final List> rotations; + + public StructureFunction(Returnable x, Returnable y, Returnable z, Returnable id, + List> rotations, Registry registry, Position position, Platform platform) { + this.registry = registry; + this.id = id; + this.position = position; + this.x = x; + this.y = y; + this.z = z; + this.platform = platform; + this.rotations = rotations; + } + + @Override + public ReturnType returnType() { + return ReturnType.BOOLEAN; + } + + @Override + public Boolean apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + + if(arguments.getRecursions() > platform.getTerraConfig().getMaxRecursion()) + throw new RuntimeException("Structure recursion too deep: " + arguments.getRecursions()); + + Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation()); + + + String app = id.apply(implementationArguments, scope); + return registry.getByID(app).map(script -> { + Rotation rotation1; + String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).apply(implementationArguments, scope); + try { + rotation1 = Rotation.valueOf(rotString); + } catch(IllegalArgumentException e) { + LOGGER.warn("Invalid rotation {}", rotString); + return false; + } + + if(script instanceof StructureScript structureScript) { + return structureScript.generate(arguments.getOrigin(), + arguments.getWorld() + .buffer(FastMath.roundToInt(xz.getX()), + y.apply(implementationArguments, scope).intValue(), + FastMath.roundToInt(xz.getZ())), + arguments.getRandom(), + arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1); + } + return script.generate(arguments.getOrigin(), + arguments.getWorld() + .buffer(FastMath.roundToInt(xz.getX()), + y.apply(implementationArguments, scope).intValue(), + FastMath.roundToInt(xz.getZ())), + arguments.getRandom(), + arguments.getRotation().rotate(rotation1)); + }).orElseGet(() -> { + LOGGER.error("No such structure {}", app); + return false; + }); + } + + @Override + public Position getPosition() { + return position; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Char.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Char.java similarity index 76% rename from common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Char.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Char.java index 5b655cd31..c9a361492 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Char.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Char.java @@ -1,41 +1,24 @@ -package com.dfsek.terra.api.structures.tokenizer; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.tokenizer; public class Char { private final char character; private final int index; private final int line; - - + + public Char(char character, int index, int line) { this.character = character; this.index = index; this.line = line; } - - public char getCharacter() { - return character; - } - - public int getIndex() { - return index; - } - - public int getLine() { - return line; - } - - public boolean isWhitespace() { - return Character.isWhitespace(character); - } - - public boolean isNewLine() { - return character == '\n'; - } - - public boolean isDigit() { - return Character.isDigit(character); - } - + public boolean is(char... tests) { for(char test : tests) { if(test == character && test != '\0') { @@ -44,13 +27,37 @@ public class Char { } return false; } - - public boolean isEOF() { - return character == '\0'; - } - + @Override public String toString() { return Character.toString(character); } + + public char getCharacter() { + return character; + } + + public int getIndex() { + return index; + } + + public int getLine() { + return line; + } + + public boolean isWhitespace() { + return Character.isWhitespace(character); + } + + public boolean isNewLine() { + return character == '\n'; + } + + public boolean isDigit() { + return Character.isDigit(character); + } + + public boolean isEOF() { + return character == '\0'; + } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Lookahead.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Lookahead.java similarity index 85% rename from common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Lookahead.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Lookahead.java index cfbec6d6b..4778b70af 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Lookahead.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Lookahead.java @@ -1,25 +1,33 @@ -package com.dfsek.terra.api.structures.tokenizer; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.tokenizer; -import com.dfsek.terra.api.util.GlueList; import java.io.IOException; import java.io.Reader; +import java.util.ArrayList; import java.util.List; + /** * Stream-like data structure that allows viewing future elements without consuming current. */ public class Lookahead { - private final List buffer = new GlueList<>(); + private final List buffer = new ArrayList<>(); private final Reader input; private int index = 0; private int line = 0; private boolean end = false; - + public Lookahead(Reader r) { this.input = r; } - + /** * Get the current character without consuming it. * @@ -28,8 +36,8 @@ public class Lookahead { public Char current() { return next(0); } - - + + /** * Consume and return one character. * @@ -40,7 +48,57 @@ public class Lookahead { consume(1); return consumed; } - + + /** + * Fetch a future character without consuming it. + * + * @param ahead Distance ahead to peek + * + * @return Character + */ + public Char next(int ahead) { + if(ahead < 0) throw new IllegalArgumentException(); + + while(buffer.size() <= ahead && !end) { + Char item = fetch(); + if(item != null) { + buffer.add(item); + } else end = true; + } + + if(ahead >= buffer.size()) { + return null; + } else return buffer.get(ahead); + } + + /** + * Consume an amount of characters + * + * @param amount Number of characters to consume + */ + public void consume(int amount) { + if(amount < 0) throw new IllegalArgumentException(); + while(amount-- > 0) { + if(!buffer.isEmpty()) buffer.remove(0); // Remove top item from buffer. + else { + if(end) return; + Char item = fetch(); + if(item == null) end = true; + } + } + } + + public boolean matches(String check, boolean consume) { + if(check == null) return false; + + for(int i = 0; i < check.length(); i++) { + if(!next(i).is(check.charAt(i))) return false; + } + + if(consume) consume(check.length()); // Consume string + return true; + } + /** * Fetch the next character. * @@ -61,61 +119,12 @@ public class Lookahead { return null; } } - - /** - * Fetch a future character without consuming it. - * - * @param ahead Distance ahead to peek - * @return Character - */ - public Char next(int ahead) { - if(ahead < 0) throw new IllegalArgumentException(); - - while(buffer.size() <= ahead && !end) { - Char item = fetch(); - if(item != null) { - buffer.add(item); - } else end = true; - } - - if(ahead >= buffer.size()) { - return null; - } else return buffer.get(ahead); - } - + public int getLine() { return line; } - + public int getIndex() { return index; } - - /** - * Consume an amount of characters - * - * @param amount Number of characters to consume - */ - public void consume(int amount) { - if(amount < 0) throw new IllegalArgumentException(); - while(amount-- > 0) { - if(!buffer.isEmpty()) buffer.remove(0); // Remove top item from buffer. - else { - if(end) return; - Char item = fetch(); - if(item == null) end = true; - } - } - } - - public boolean matches(String check, boolean consume) { - if(check == null) return false; - - for(int i = 0; i < check.length(); i++) { - if(!next(i).is(check.charAt(i))) return false; - } - - if(consume) consume(check.length()); // Consume string - return true; - } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Position.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Position.java similarity index 50% rename from common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Position.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Position.java index 17d319edb..9e5c7c675 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Position.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Position.java @@ -1,14 +1,21 @@ -package com.dfsek.terra.api.structures.tokenizer; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.tokenizer; public class Position { private final int line; private final int index; - + public Position(int line, int index) { this.line = line; this.index = index; } - + @Override public String toString() { return (line + 1) + ":" + index; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Token.java similarity index 71% rename from common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Token.java index b74a206f7..6ab278807 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Token.java @@ -1,91 +1,98 @@ -package com.dfsek.terra.api.structures.tokenizer; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.tokenizer; public class Token { private final String content; private final Type type; private final Position start; - + public Token(String content, Type type, Position start) { this.content = content; this.type = type; this.start = start; } - - public Type getType() { - return type; - } - - public String getContent() { - return content; - } - - public Position getPosition() { - return start; - } - + @Override public String toString() { return type + ": '" + content + "'"; } - + + public Type getType() { + return type; + } + + public String getContent() { + return content; + } + + public Position getPosition() { + return start; + } + public boolean isConstant() { return this.type.equals(Type.NUMBER) || this.type.equals(Type.STRING) || this.type.equals(Type.BOOLEAN); } - + public boolean isBinaryOperator() { return type.equals(Type.ADDITION_OPERATOR) - || type.equals(Type.SUBTRACTION_OPERATOR) - || type.equals(Type.MULTIPLICATION_OPERATOR) - || type.equals(Type.DIVISION_OPERATOR) - || type.equals(Type.EQUALS_OPERATOR) - || type.equals(Type.NOT_EQUALS_OPERATOR) - || type.equals(Type.LESS_THAN_OPERATOR) - || type.equals(Type.GREATER_THAN_OPERATOR) - || type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR) - || type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR) - || type.equals(Type.BOOLEAN_OR) - || type.equals(Type.BOOLEAN_AND) - || type.equals(Type.MODULO_OPERATOR); + || type.equals(Type.SUBTRACTION_OPERATOR) + || type.equals(Type.MULTIPLICATION_OPERATOR) + || type.equals(Type.DIVISION_OPERATOR) + || type.equals(Type.EQUALS_OPERATOR) + || type.equals(Type.NOT_EQUALS_OPERATOR) + || type.equals(Type.LESS_THAN_OPERATOR) + || type.equals(Type.GREATER_THAN_OPERATOR) + || type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR) + || type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR) + || type.equals(Type.BOOLEAN_OR) + || type.equals(Type.BOOLEAN_AND) + || type.equals(Type.MODULO_OPERATOR); } - + public boolean isStrictNumericOperator() { return type.equals(Type.SUBTRACTION_OPERATOR) - || type.equals(Type.MULTIPLICATION_OPERATOR) - || type.equals(Type.DIVISION_OPERATOR) - || type.equals(Type.GREATER_THAN_OPERATOR) - || type.equals(Type.LESS_THAN_OPERATOR) - || type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR) - || type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR) - || type.equals(Type.MODULO_OPERATOR); + || type.equals(Type.MULTIPLICATION_OPERATOR) + || type.equals(Type.DIVISION_OPERATOR) + || type.equals(Type.GREATER_THAN_OPERATOR) + || type.equals(Type.LESS_THAN_OPERATOR) + || type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR) + || type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR) + || type.equals(Type.MODULO_OPERATOR); } - + public boolean isStrictBooleanOperator() { return type.equals(Type.BOOLEAN_AND) - || type.equals(Type.BOOLEAN_OR); + || type.equals(Type.BOOLEAN_OR); } - + public boolean isVariableDeclaration() { return type.equals(Type.STRING_VARIABLE) - || type.equals(Type.BOOLEAN_VARIABLE) - || type.equals(Type.NUMBER_VARIABLE); + || type.equals(Type.BOOLEAN_VARIABLE) + || type.equals(Type.NUMBER_VARIABLE); } - + public boolean isLoopLike() { return type.equals(Type.IF_STATEMENT) - || type.equals(Type.WHILE_LOOP) - || type.equals(Type.FOR_LOOP); + || type.equals(Type.WHILE_LOOP) + || type.equals(Type.FOR_LOOP); } - + public boolean isIdentifier() { return type.equals(Type.IDENTIFIER); } - + public enum Type { /** * Function identifier or language keyword */ IDENTIFIER, - + /** * Numeric literal */ @@ -218,10 +225,6 @@ public class Token { * Fail statement. Like return keyword, but specifies that generation has failed. */ FAIL, - /** - * ID declaration - */ - ID, /** * For loop initializer token */ diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Tokenizer.java similarity index 85% rename from common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Tokenizer.java index 2fb3e4e1f..16ede7b3a 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/Tokenizer.java @@ -1,64 +1,69 @@ -package com.dfsek.terra.api.structures.tokenizer; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.tokenizer; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.tokenizer.exceptions.EOFException; -import com.dfsek.terra.api.structures.tokenizer.exceptions.FormatException; -import com.dfsek.terra.api.structures.tokenizer.exceptions.TokenizerException; import com.google.common.collect.Sets; import java.io.StringReader; import java.util.Set; import java.util.Stack; +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.tokenizer.exceptions.EOFException; +import com.dfsek.terra.addons.terrascript.tokenizer.exceptions.FormatException; +import com.dfsek.terra.addons.terrascript.tokenizer.exceptions.TokenizerException; + + public class Tokenizer { - public static final Set syntaxSignificant = Sets.newHashSet(';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', '/', '>', '<', '!'); // Reserved chars + public static final Set syntaxSignificant = Sets.newHashSet(';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', '/', + '>', '<', '!'); // Reserved chars private final Lookahead reader; private final Stack brackets = new Stack<>(); private Token current; - - public Tokenizer(String data) throws ParseException { + private Token last; + + public Tokenizer(String data) { reader = new Lookahead(new StringReader(data + '\0')); current = fetchCheck(); } - + /** * Get the first token. * * @return First token + * * @throws ParseException If token does not exist */ - public Token get() throws ParseException { - if(!hasNext()) throw new ParseException("Unexpected end of input", current.getPosition()); + public Token get() { + if(!hasNext()) throw new ParseException("Unexpected end of input", last.getPosition()); return current; } - + /** * Consume (get and remove) the first token. * * @return First token + * * @throws ParseException If token does not exist */ - public Token consume() throws ParseException { - if(!hasNext()) throw new ParseException("Unexpected end of input", current.getPosition()); + public Token consume() { + if(!hasNext()) throw new ParseException("Unexpected end of input", last.getPosition()); Token temp = current; current = fetchCheck(); return temp; } - - /** - * Whether this {@code Tokenizer} contains additional tokens. - * - * @return {@code true} if more tokens are present, otherwise {@code false} - */ - public boolean hasNext() { - return !(current == null); - } - - private Token fetchCheck() throws ParseException { + + private Token fetchCheck() { Token fetch = fetch(); if(fetch != null) { - if(fetch.getType().equals(Token.Type.BLOCK_BEGIN)) brackets.push(fetch); // Opening bracket - else if(fetch.getType().equals(Token.Type.BLOCK_END)) { + last = fetch; + if(fetch.getType() == Token.Type.BLOCK_BEGIN) brackets.push(fetch); // Opening bracket + else if(fetch.getType() == Token.Type.BLOCK_END) { if(!brackets.isEmpty()) brackets.pop(); else throw new ParseException("Dangling opening brace", new Position(0, 0)); } @@ -67,16 +72,16 @@ public class Tokenizer { } return fetch; } - + private Token fetch() throws TokenizerException { while(!reader.current().isEOF() && reader.current().isWhitespace()) reader.consume(); - + while(reader.matches("//", true)) skipLine(); // Skip line if comment - + if(reader.matches("/*", true)) skipTo("*/"); // Skip multi line comment - + if(reader.current().isEOF()) return null; // EOF - + if(reader.matches("==", true)) return new Token("==", Token.Type.EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex())); if(reader.matches("!=", true)) @@ -89,14 +94,14 @@ public class Tokenizer { return new Token(">", Token.Type.GREATER_THAN_OPERATOR, new Position(reader.getLine(), reader.getIndex())); if(reader.matches("<", true)) return new Token("<", Token.Type.LESS_THAN_OPERATOR, new Position(reader.getLine(), reader.getIndex())); - - + + if(reader.matches("||", true)) return new Token("||", Token.Type.BOOLEAN_OR, new Position(reader.getLine(), reader.getIndex())); if(reader.matches("&&", true)) return new Token("&&", Token.Type.BOOLEAN_AND, new Position(reader.getLine(), reader.getIndex())); - - + + if(isNumberStart()) { StringBuilder num = new StringBuilder(); while(!reader.current().isEOF() && isNumberLike()) { @@ -104,7 +109,7 @@ public class Tokenizer { } return new Token(num.toString(), Token.Type.NUMBER, new Position(reader.getLine(), reader.getIndex())); } - + if(reader.current().is('"')) { reader.consume(); // Consume first quote StringBuilder string = new StringBuilder(); @@ -120,10 +125,10 @@ public class Tokenizer { string.append(reader.consume()); } reader.consume(); // Consume last quote - + return new Token(string.toString(), Token.Type.STRING, new Position(reader.getLine(), reader.getIndex())); } - + if(reader.current().is('(')) return new Token(reader.consume().toString(), Token.Type.GROUP_BEGIN, new Position(reader.getLine(), reader.getIndex())); if(reader.current().is(')')) @@ -141,37 +146,39 @@ public class Tokenizer { if(reader.current().is('+')) return new Token(reader.consume().toString(), Token.Type.ADDITION_OPERATOR, new Position(reader.getLine(), reader.getIndex())); if(reader.current().is('-')) - return new Token(reader.consume().toString(), Token.Type.SUBTRACTION_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + return new Token(reader.consume().toString(), Token.Type.SUBTRACTION_OPERATOR, + new Position(reader.getLine(), reader.getIndex())); if(reader.current().is('*')) - return new Token(reader.consume().toString(), Token.Type.MULTIPLICATION_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + return new Token(reader.consume().toString(), Token.Type.MULTIPLICATION_OPERATOR, + new Position(reader.getLine(), reader.getIndex())); if(reader.current().is('/')) return new Token(reader.consume().toString(), Token.Type.DIVISION_OPERATOR, new Position(reader.getLine(), reader.getIndex())); if(reader.current().is('%')) return new Token(reader.consume().toString(), Token.Type.MODULO_OPERATOR, new Position(reader.getLine(), reader.getIndex())); if(reader.current().is('!')) return new Token(reader.consume().toString(), Token.Type.BOOLEAN_NOT, new Position(reader.getLine(), reader.getIndex())); - + StringBuilder token = new StringBuilder(); while(!reader.current().isEOF() && !isSyntaxSignificant(reader.current().getCharacter())) { Char c = reader.consume(); if(c.isWhitespace()) break; token.append(c); } - + String tokenString = token.toString(); - + if(tokenString.equals("true")) return new Token(tokenString, Token.Type.BOOLEAN, new Position(reader.getLine(), reader.getIndex())); if(tokenString.equals("false")) return new Token(tokenString, Token.Type.BOOLEAN, new Position(reader.getLine(), reader.getIndex())); - + if(tokenString.equals("num")) return new Token(tokenString, Token.Type.NUMBER_VARIABLE, new Position(reader.getLine(), reader.getIndex())); if(tokenString.equals("str")) return new Token(tokenString, Token.Type.STRING_VARIABLE, new Position(reader.getLine(), reader.getIndex())); if(tokenString.equals("bool")) return new Token(tokenString, Token.Type.BOOLEAN_VARIABLE, new Position(reader.getLine(), reader.getIndex())); - + if(tokenString.equals("if")) return new Token(tokenString, Token.Type.IF_STATEMENT, new Position(reader.getLine(), reader.getIndex())); if(tokenString.equals("else")) @@ -180,7 +187,7 @@ public class Tokenizer { return new Token(tokenString, Token.Type.WHILE_LOOP, new Position(reader.getLine(), reader.getIndex())); if(tokenString.equals("for")) return new Token(tokenString, Token.Type.FOR_LOOP, new Position(reader.getLine(), reader.getIndex())); - + if(tokenString.equals("return")) return new Token(tokenString, Token.Type.RETURN, new Position(reader.getLine(), reader.getIndex())); if(tokenString.equals("continue")) @@ -189,32 +196,19 @@ public class Tokenizer { return new Token(tokenString, Token.Type.BREAK, new Position(reader.getLine(), reader.getIndex())); if(tokenString.equals("fail")) return new Token(tokenString, Token.Type.FAIL, new Position(reader.getLine(), reader.getIndex())); - - if(tokenString.equals("id")) - return new Token(tokenString, Token.Type.ID, new Position(reader.getLine(), reader.getIndex())); - + return new Token(tokenString, Token.Type.IDENTIFIER, new Position(reader.getLine(), reader.getIndex())); } - - private boolean isNumberLike() { - return reader.current().isDigit() - || reader.current().is('_', '.', 'E'); - } - - private boolean isNumberStart() { - return reader.current().isDigit() - || reader.current().is('.') && reader.next(1).isDigit(); - } - + private void skipLine() { while(!reader.current().isEOF() && !reader.current().isNewLine()) reader.consume(); consumeWhitespace(); } - + private void consumeWhitespace() { while(!reader.current().isEOF() && reader.current().isWhitespace()) reader.consume(); // Consume whitespace. } - + private void skipTo(String s) throws EOFException { Position begin = new Position(reader.getLine(), reader.getIndex()); while(!reader.current().isEOF()) { @@ -226,9 +220,28 @@ public class Tokenizer { } throw new EOFException("No end of expression found.", begin); } - + + /** + * Whether this {@code Tokenizer} contains additional tokens. + * + * @return {@code true} if more tokens are present, otherwise {@code false} + */ + public boolean hasNext() { + return !(current == null); + } + + private boolean isNumberLike() { + return reader.current().isDigit() + || reader.current().is('_', '.', 'E'); + } + + private boolean isNumberStart() { + return reader.current().isDigit() + || reader.current().is('.') && reader.next(1).isDigit(); + } + public boolean isSyntaxSignificant(char c) { return syntaxSignificant.contains(c); } - + } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/exceptions/EOFException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/exceptions/EOFException.java new file mode 100644 index 000000000..bd9097946 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/exceptions/EOFException.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.tokenizer.exceptions; + +import java.io.Serial; + +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class EOFException extends TokenizerException { + + @Serial + private static final long serialVersionUID = 3980047409902809440L; + + public EOFException(String message, Position position) { + super(message, position); + } + + public EOFException(String message, Position position, Throwable cause) { + super(message, position, cause); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/exceptions/FormatException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/exceptions/FormatException.java new file mode 100644 index 000000000..067b49b70 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/exceptions/FormatException.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.tokenizer.exceptions; + +import java.io.Serial; + +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class FormatException extends TokenizerException { + + @Serial + private static final long serialVersionUID = -791308012940744455L; + + public FormatException(String message, Position position) { + super(message, position); + } + + public FormatException(String message, Position position, Throwable cause) { + super(message, position, cause); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/exceptions/TokenizerException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/exceptions/TokenizerException.java new file mode 100644 index 000000000..079f17226 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/tokenizer/exceptions/TokenizerException.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.tokenizer.exceptions; + +import java.io.Serial; + +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public abstract class TokenizerException extends ParseException { + + @Serial + private static final long serialVersionUID = 2792384010083575420L; + + public TokenizerException(String message, Position position) { + super(message, position); + } + + public TokenizerException(String message, Position position, Throwable cause) { + super(message, position, cause); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/resources/terra.addon.yml b/common/addons/structure-terrascript-loader/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..0850687c9 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/resources/terra.addon.yml @@ -0,0 +1,12 @@ +schema-version: 1 +contributors: + - Terra contributors +id: structure-terrascript-loader +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.terrascript.TerraScriptAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License \ No newline at end of file diff --git a/common/src/test/java/structure/LookaheadTest.java b/common/addons/structure-terrascript-loader/src/test/java/structure/LookaheadTest.java similarity index 63% rename from common/src/test/java/structure/LookaheadTest.java rename to common/addons/structure-terrascript-loader/src/test/java/structure/LookaheadTest.java index fd1e10724..e428f67cf 100644 --- a/common/src/test/java/structure/LookaheadTest.java +++ b/common/addons/structure-terrascript-loader/src/test/java/structure/LookaheadTest.java @@ -1,15 +1,24 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + package structure; -import com.dfsek.terra.api.structures.tokenizer.Lookahead; import org.junit.jupiter.api.Test; import java.io.StringReader; +import com.dfsek.terra.addons.terrascript.tokenizer.Lookahead; + + public class LookaheadTest { @Test public void lookahead() { Lookahead lookahead = new Lookahead(new StringReader("Test string...")); - + for(int i = 0; lookahead.next(i) != null; i++) { System.out.print(lookahead.next(i).getCharacter()); } diff --git a/common/src/test/java/structure/ParserTest.java b/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java similarity index 56% rename from common/src/test/java/structure/ParserTest.java rename to common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java index fd1ff30c1..b502a3563 100644 --- a/common/src/test/java/structure/ParserTest.java +++ b/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java @@ -1,85 +1,91 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + package structure; -import com.dfsek.terra.api.structures.parser.Parser; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; + import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.charset.Charset; -import java.util.HashMap; import java.util.List; -import java.util.Map; + +import com.dfsek.terra.addons.terrascript.parser.Parser; +import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + public class ParserTest { @Test public void parse() throws IOException, ParseException { Parser parser = new Parser(IOUtils.toString(getClass().getResourceAsStream("/test.tesf"), Charset.defaultCharset())); - + parser.registerFunction("test", new FunctionBuilder() { @Override public Test1 build(List> argumentList, Position position) { return new Test1(argumentList.get(0), argumentList.get(1), position); } - + @Override public int argNumber() { return 2; } - + @Override public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - return Returnable.ReturnType.STRING; - case 1: - return Returnable.ReturnType.NUMBER; - default: - return null; - } + return switch(position) { + case 0 -> Returnable.ReturnType.STRING; + case 1 -> Returnable.ReturnType.NUMBER; + default -> null; + }; } - + }); - + long l = System.nanoTime(); Block block = parser.parse(); long t = System.nanoTime() - l; System.out.println("Took " + (double) t / 1000000); - - block.apply(null, new HashMap<>()); - - block.apply(null, new HashMap<>()); + + block.apply(null, new Scope()); + + block.apply(null, new Scope()); } - + private static class Test1 implements Function { private final Returnable a; private final Returnable b; private final Position position; - + public Test1(Returnable a, Returnable b, Position position) { this.a = a; this.b = b; this.position = position; } - + @Override - public Void apply(ImplementationArguments implementationArguments, Map> variableMap) { - System.out.println("string: " + a.apply(implementationArguments, variableMap) + ", double: " + b.apply(implementationArguments, variableMap)); + public Void apply(ImplementationArguments implementationArguments, Scope scope) { + System.out.println("string: " + a.apply(implementationArguments, scope) + ", double: " + + b.apply(implementationArguments, scope)); return null; } - + @Override public Position getPosition() { return position; } - + @Override public ReturnType returnType() { return ReturnType.VOID; diff --git a/common/addons/structure-terrascript-loader/src/test/java/structure/PerformanceTest.java b/common/addons/structure-terrascript-loader/src/test/java/structure/PerformanceTest.java new file mode 100644 index 000000000..cc2ed4372 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/test/java/structure/PerformanceTest.java @@ -0,0 +1,90 @@ +package structure; + +import net.jafama.FastMath; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.Parser; +import com.dfsek.terra.addons.terrascript.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable.ReturnType; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.UnaryNumberFunctionBuilder; +import com.dfsek.terra.addons.terrascript.script.builders.UnaryStringFunctionBuilder; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class PerformanceTest { + public static void main(String... args) throws IOException { + Parser parser = new Parser( + IOUtils.toString(PerformanceTest.class.getResourceAsStream("/performance.tesf"), Charset.defaultCharset())); + + parser.registerFunction("assert", new FunctionBuilder() { + @Override + public AssertFunction build(List> argumentList, Position position) { + return new AssertFunction(position, (Returnable) argumentList.get(0)); + } + + @Override + public int argNumber() { + return 1; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0 -> ReturnType.BOOLEAN; + default -> null; + }; + } + + }).registerFunction("print", + new UnaryStringFunctionBuilder(System.out::println)) + .registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> FastMath.sqrt(number.doubleValue()))); + + Block block = parser.parse(); + + for(int i = 0; i < 20; i++) { + long s = System.nanoTime(); + + block.apply(null, new Scope()); + + long e = System.nanoTime(); + long d = e - s; + + System.out.println("Took " + ((double) d) / 1000000 + "ms"); + } + } + + public static final class AssertFunction implements Function { + private final Position position; + private final Returnable arg; + + public AssertFunction(Position position, Returnable arg) { + this.position = position; + this.arg = arg; + } + + @Override + public Void apply(ImplementationArguments implementationArguments, Scope scope) { + if(!arg.apply(implementationArguments, scope)) throw new IllegalStateException(); + return null; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.VOID; + } + } +} diff --git a/common/addons/structure-terrascript-loader/src/test/resources/performance.tesf b/common/addons/structure-terrascript-loader/src/test/resources/performance.tesf new file mode 100644 index 000000000..45527678c --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/test/resources/performance.tesf @@ -0,0 +1,25 @@ +num epsilon = 0.001; + +for(num n = 1; n < 1000000; n = n + 1) { + + num x = n; + + num root = 0; + + while(true) { + root = 0.5 * (x + (n / x)); + + num diff = root - x; + if(diff < 0) diff = -diff; + + if(diff < epsilon) break; + + x = root; + } + + num diff = root - sqrt(n); + + if(diff < 0) diff = -diff; + + assert(diff <= epsilon); +} \ No newline at end of file diff --git a/common/src/test/resources/test.tesf b/common/addons/structure-terrascript-loader/src/test/resources/test.tesf similarity index 99% rename from common/src/test/resources/test.tesf rename to common/addons/structure-terrascript-loader/src/test/resources/test.tesf index 93fe11eda..8bcce7177 100644 --- a/common/src/test/resources/test.tesf +++ b/common/addons/structure-terrascript-loader/src/test/resources/test.tesf @@ -1,5 +1,3 @@ -id "testScript"; - bool thing1 = 2 > (2+2) || false; if(2 > 2 || 3 + 4 <= 2 && 4 + 5 > 2 / 3) { diff --git a/common/addons/terrascript-function-check-noise-3d/build.gradle.kts b/common/addons/terrascript-function-check-noise-3d/build.gradle.kts new file mode 100644 index 000000000..51bb33cf6 --- /dev/null +++ b/common/addons/terrascript-function-check-noise-3d/build.gradle.kts @@ -0,0 +1,14 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + compileOnlyApi(project(":common:addons:chunk-generator-noise-3d")) + compileOnlyApi(project(":common:addons:structure-terrascript-loader")) + + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.named("shadowJar") { + relocate("net.jafama", "com.dfsek.terra.addon.terrascript.check.lib.jafama") +} diff --git a/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunction.java b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunction.java new file mode 100644 index 000000000..1dfb1d293 --- /dev/null +++ b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunction.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addon.terrascript.check; + +import net.jafama.FastMath; + +import com.dfsek.terra.addons.chunkgenerator.generation.NoiseChunkGenerator3D; +import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider; +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.util.RotationUtil; +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.World; +import com.dfsek.terra.api.world.WritableWorld; + + +public class CheckFunction implements Function { + private final Returnable x, y, z; + private final Position position; + + public CheckFunction(Returnable x, Returnable y, Returnable z, Position position) { + this.x = x; + this.y = y; + this.z = z; + this.position = position; + } + + + @Override + public String apply(ImplementationArguments implementationArguments, Scope scope) { + + + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + + + Vector2 xz = Vector2.of(x.apply(implementationArguments, scope).doubleValue(), + z.apply(implementationArguments, scope).doubleValue()); + + RotationUtil.rotateVector(xz, arguments.getRotation()); + + Vector3 location = arguments.getOrigin().toVector3Mutable().add( + Vector3.of(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, scope).doubleValue(), + FastMath.roundToInt(xz.getZ()))).immutable(); + + return apply(location, arguments.getWorld()); + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.STRING; + } + + private String apply(Vector3 vector, WritableWorld world) { + int y = vector.getBlockY(); + if(y >= world.getMaxHeight() || y < 0) return "AIR"; + SamplerProvider cache = ((NoiseChunkGenerator3D) world.getGenerator()).samplerProvider(); + double comp = sample(vector.getX(), vector.getY(), vector.getZ(), cache, world); + + if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land. + + //BiomeProvider provider = tw.getBiomeProvider(); + //TerraBiome b = provider.getBiome(vector.getBlockX(), vector.getBlockZ()); + + /*if(vector.getY() > c.getSeaLevel())*/ + return "AIR"; // Above sea level + //return "OCEAN"; // Below sea level + } + + private double sample(double x, double y, double z, SamplerProvider cache, World world) { + int cx = FastMath.floorDiv((int) x, 16); + int cz = FastMath.floorDiv((int) z, 16); + return cache.getChunk(cx, cz, world, world.getBiomeProvider()).sample(x - (cx << 4), y, z - (cz << 4)); + } +} diff --git a/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunctionBuilder.java b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunctionBuilder.java new file mode 100644 index 000000000..dc0a0b1da --- /dev/null +++ b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunctionBuilder.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addon.terrascript.check; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.Platform; + + +public class CheckFunctionBuilder implements FunctionBuilder { + private final Platform platform; + + public CheckFunctionBuilder(Platform platform) { + this.platform = platform; + } + + @SuppressWarnings("unchecked") + @Override + public CheckFunction build(List> argumentList, Position position) { + return new CheckFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), position); + } + + @Override + public int argNumber() { + return 3; + } + + @Override + public Returnable.ReturnType getArgument(int position) { + return switch(position) { + case 0, 1, 2 -> Returnable.ReturnType.NUMBER; + default -> null; + }; + } +} diff --git a/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/TerraScriptCheckFunctionAddon.java b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/TerraScriptCheckFunctionAddon.java new file mode 100644 index 000000000..26a1ca358 --- /dev/null +++ b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/TerraScriptCheckFunctionAddon.java @@ -0,0 +1,31 @@ +package com.dfsek.terra.addon.terrascript.check; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class TerraScriptCheckFunctionAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .priority(1) + .then(event -> { + event.getPack().getOrCreateRegistry(FunctionBuilder.class).register(addon.key("check"), + new CheckFunctionBuilder(platform)); + }) + .failThrough(); + } +} diff --git a/common/addons/terrascript-function-check-noise-3d/src/main/resources/terra.addon.yml b/common/addons/terrascript-function-check-noise-3d/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..028db2274 --- /dev/null +++ b/common/addons/terrascript-function-check-noise-3d/src/main/resources/terra.addon.yml @@ -0,0 +1,15 @@ +schema-version: 1 +contributors: + - Terra contributors +id: structure-function-check-noise-3d +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addon.terrascript.check.TerraScriptCheckFunctionAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License +depends: + structure-terrascript-loader: "1.+" + chunk-generator-noise-3d: "1.+" \ No newline at end of file diff --git a/common/addons/terrascript-function-sampler/build.gradle.kts b/common/addons/terrascript-function-sampler/build.gradle.kts new file mode 100644 index 000000000..dd3249444 --- /dev/null +++ b/common/addons/terrascript-function-sampler/build.gradle.kts @@ -0,0 +1,7 @@ +version = version("1.0.0") + +dependencies { + compileOnlyApi(project(":common:addons:manifest-addon-loader")) + compileOnlyApi(project(":common:addons:config-noise-function")) + compileOnlyApi(project(":common:addons:structure-terrascript-loader")) +} diff --git a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/ConstantSamplerFunction.java b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/ConstantSamplerFunction.java new file mode 100644 index 000000000..83cf2563b --- /dev/null +++ b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/ConstantSamplerFunction.java @@ -0,0 +1,58 @@ +package com.dfsek.terra.addons.terrascript.sampler; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class ConstantSamplerFunction implements Function { + private final Returnable x, y, z; + private final NoiseSampler sampler; + + + private final boolean twoD; + private final Position position; + + public ConstantSamplerFunction(NoiseSampler sampler, + Returnable x, + Returnable y, + Returnable z, + boolean twoD, + Position position) { + this.x = x; + this.y = y; + this.z = z; + this.sampler = sampler; + this.twoD = twoD; + this.position = position; + } + + @Override + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + double x = this.x.apply(implementationArguments, scope).doubleValue(); + + double z = this.z.apply(implementationArguments, scope).doubleValue(); + + if(twoD) { + return sampler.noise(arguments.getWorld().getSeed(), x, z); + } else { + double y = this.y.apply(implementationArguments, scope).doubleValue(); + return sampler.noise(arguments.getWorld().getSeed(), x, y, z); + } + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunction.java b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunction.java new file mode 100644 index 000000000..abaafecab --- /dev/null +++ b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunction.java @@ -0,0 +1,64 @@ +package com.dfsek.terra.addons.terrascript.sampler; + +import java.util.function.Supplier; + +import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import com.dfsek.terra.api.noise.NoiseSampler; + + +public class SamplerFunction implements Function { + private final Returnable x, y, z; + private final Returnable function; + + private final java.util.function.Function, NoiseSampler> samplerFunction; + + private final boolean twoD; + private final Position position; + + public SamplerFunction(Returnable function, + Returnable x, + Returnable y, + Returnable z, + java.util.function.Function, NoiseSampler> samplerFunction, + boolean twoD, + Position position) { + this.x = x; + this.y = y; + this.z = z; + this.function = function; + this.samplerFunction = samplerFunction; + this.twoD = twoD; + this.position = position; + } + + @Override + public Number apply(ImplementationArguments implementationArguments, Scope scope) { + TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; + double x = this.x.apply(implementationArguments, scope).doubleValue(); + + double z = this.z.apply(implementationArguments, scope).doubleValue(); + + NoiseSampler sampler = samplerFunction.apply(() -> function.apply(implementationArguments, scope)); + if(twoD) { + return sampler.noise(arguments.getWorld().getSeed(), x, z); + } else { + double y = this.y.apply(implementationArguments, scope).doubleValue(); + return sampler.noise(arguments.getWorld().getSeed(), x, y, z); + } + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java new file mode 100644 index 000000000..98ac7fca3 --- /dev/null +++ b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java @@ -0,0 +1,97 @@ +package com.dfsek.terra.addons.terrascript.sampler; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; +import com.dfsek.terra.addons.terrascript.parser.lang.Returnable.ReturnType; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.NumericConstant; +import com.dfsek.terra.addons.terrascript.parser.lang.constants.StringConstant; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.tokenizer.Position; + + +public class SamplerFunctionBuilder implements FunctionBuilder> { + private final Map samplers2d; + private final Map samplers3d; + + public SamplerFunctionBuilder(Map samplers) { + this.samplers2d = new HashMap<>(); + this.samplers3d = new HashMap<>(); + + samplers.forEach((id, sampler) -> { + if(sampler.getDimensions() == 2) { + samplers2d.put(id, sampler); + } else if(sampler.getDimensions() == 3) { + samplers3d.put(id, sampler); + } + }); + } + + @SuppressWarnings("unchecked") + @Override + public com.dfsek.terra.addons.terrascript.parser.lang.functions.Function build(List> argumentList, + Position position) { + Returnable arg = (Returnable) argumentList.get(0); + + if(argumentList.size() == 3) { // 2D + if(arg instanceof StringConstant constant) { + return new ConstantSamplerFunction(Objects.requireNonNull(samplers2d.get(constant.getConstant()), + "No such 2D noise function " + constant.getConstant()) + .getSampler(), + (Returnable) argumentList.get(1), + new NumericConstant(0, position), + (Returnable) argumentList.get(2), + true, + position); + } else { + return new SamplerFunction((Returnable) argumentList.get(0), + (Returnable) argumentList.get(1), + new NumericConstant(0, position), + (Returnable) argumentList.get(2), + s -> Objects.requireNonNull(samplers2d.get(s.get()), "No such 2D noise function " + s.get()) + .getSampler(), + true, + position); + } + + } else { // 3D + if(arg instanceof StringConstant constant) { + return new ConstantSamplerFunction(Objects.requireNonNull(samplers3d.get(constant.getConstant()), + "No such 2D noise function " + constant.getConstant()) + .getSampler(), + (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), + (Returnable) argumentList.get(3), + true, + position); + } else { + return new SamplerFunction((Returnable) argumentList.get(0), + (Returnable) argumentList.get(1), + (Returnable) argumentList.get(2), + (Returnable) argumentList.get(3), + s -> Objects.requireNonNull(samplers2d.get(s.get()), "No such 2D noise function " + s.get()) + .getSampler(), + true, + position); + } + } + } + + @Override + public int argNumber() { + return -1; + } + + @Override + public ReturnType getArgument(int position) { + return switch(position) { + case 0 -> ReturnType.STRING; + case 1, 2, 3 -> ReturnType.NUMBER; + default -> null; + }; + } +} diff --git a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/TerraScriptSamplerFunctionAddon.java b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/TerraScriptSamplerFunctionAddon.java new file mode 100644 index 000000000..cdb4b92bd --- /dev/null +++ b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/TerraScriptSamplerFunctionAddon.java @@ -0,0 +1,34 @@ +package com.dfsek.terra.addons.terrascript.sampler; + +import com.dfsek.terra.addons.manifest.api.AddonInitializer; +import com.dfsek.terra.addons.noise.NoiseConfigPackTemplate; +import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.annotations.Inject; + + +public class TerraScriptSamplerFunctionAddon implements AddonInitializer { + @Inject + private Platform platform; + + @Inject + private BaseAddon addon; + + + @Override + public void initialize() { + platform.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(addon, ConfigPackPreLoadEvent.class) + .priority(51) + .then(event -> event + .getPack() + .getOrCreateRegistry(FunctionBuilder.class) + .register(addon.key("sampler"), new SamplerFunctionBuilder(event.getPack().getContext().get( + NoiseConfigPackTemplate.class).getSamplers()))) + .failThrough(); + } +} diff --git a/common/addons/terrascript-function-sampler/src/main/resources/terra.addon.yml b/common/addons/terrascript-function-sampler/src/main/resources/terra.addon.yml new file mode 100644 index 000000000..635814c2c --- /dev/null +++ b/common/addons/terrascript-function-sampler/src/main/resources/terra.addon.yml @@ -0,0 +1,15 @@ +schema-version: 1 +contributors: + - Terra contributors +id: terrascript-function-sampler +version: @VERSION@ +entrypoints: + - "com.dfsek.terra.addons.terrascript.sampler.TerraScriptSamplerFunctionAddon" +website: + issues: https://github.com/PolyhedralDev/Terra/issues + source: https://github.com/PolyhedralDev/Terra + docs: https://terra.polydev.org +license: MIT License +depends: + structure-terrascript-loader: "1.+" + config-noise-function: "1.+" \ No newline at end of file diff --git a/common/api/build.gradle.kts b/common/api/build.gradle.kts new file mode 100644 index 000000000..b31c8b89e --- /dev/null +++ b/common/api/build.gradle.kts @@ -0,0 +1,10 @@ +dependencies { + api("ca.solo-studios", "strata", Versions.Libraries.strata) + api("org.slf4j", "slf4j-api", Versions.Libraries.slf4j) + api("cloud.commandframework", "cloud-core", Versions.Libraries.cloud) + + api("com.dfsek.tectonic", "common", Versions.Libraries.tectonic) + + + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} \ No newline at end of file diff --git a/common/api/src/main/java/com/dfsek/terra/api/Handle.java b/common/api/src/main/java/com/dfsek/terra/api/Handle.java new file mode 100644 index 000000000..293e53ce7 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/Handle.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api; + +/** + * An interface that contains a platform delegate. + */ +public interface Handle { + /** + * Gets the delegate object. + * + * @return Delegate + */ + Object getHandle(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/Platform.java b/common/api/src/main/java/com/dfsek/terra/api/Platform.java new file mode 100644 index 000000000..080998b31 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/Platform.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.PluginConfig; +import com.dfsek.terra.api.event.EventManager; +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.api.profiler.Profiler; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.tectonic.LoaderRegistrar; + + +/** + * Represents a Terra mod/plugin instance. + */ +public interface Platform extends LoaderRegistrar { + boolean reload(); + + @NotNull + @Contract(pure = true) + String platformName(); + + /** + * Runs a task that may or may not be thread safe, depending on platform. + *

+ * Allows platforms to define what code is safe to be run asynchronously. + * + * @param task Task to be run. + */ + default void runPossiblyUnsafeTask(@NotNull Runnable task) { + task.run(); + } + + @NotNull + @Contract(pure = true) + WorldHandle getWorldHandle(); + + @NotNull + @Contract(pure = true) + PluginConfig getTerraConfig(); + + @NotNull + @Contract(pure = true) + File getDataFolder(); + + @NotNull + @Contract(pure = true) + CheckedRegistry getConfigRegistry(); + + @NotNull + @Contract(pure = true) + Registry getAddons(); + + @NotNull + @Contract(pure = true) + ItemHandle getItemHandle(); + + @NotNull + @Contract(pure = true) + EventManager getEventManager(); + + @Contract(pure = true) + default @NotNull String getVersion() { + return "@VERSION@"; + } + + @NotNull + @Contract(pure = true) + Profiler getProfiler(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/addon/BaseAddon.java b/common/api/src/main/java/com/dfsek/terra/api/addon/BaseAddon.java new file mode 100644 index 000000000..0672261ca --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/addon/BaseAddon.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.addon; + +import ca.solostudios.strata.version.Version; +import ca.solostudios.strata.version.VersionRange; + +import java.util.Collections; +import java.util.Map; + +import com.dfsek.terra.api.registry.key.Namespaced; +import com.dfsek.terra.api.registry.key.StringIdentifiable; + + +/** + * Base interface which all Terra addons extend + */ +public interface BaseAddon extends StringIdentifiable, Namespaced { + /** + * Initializes the addon. To be implemented by addons, but never manually invoked. + */ + default void initialize() { } + + /** + * Gets the dependencies of this addon. + * + * @return Map of dependency ID to {@link VersionRange} of dependency + */ + default Map getDependencies() { + return Collections.emptyMap(); + } + + /** + * Get the version of the addon + * + * @return Version of addon + */ + Version getVersion(); + + default String getNamespace() { + return getID(); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapAddonClassLoader.java b/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapAddonClassLoader.java new file mode 100644 index 000000000..b6b3a67ae --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapAddonClassLoader.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.api.addon.bootstrap; + +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLStreamHandlerFactory; + + +public class BootstrapAddonClassLoader extends URLClassLoader { + public BootstrapAddonClassLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } + + public BootstrapAddonClassLoader(URL[] urls) { + super(urls); + } + + public BootstrapAddonClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) { + super(urls, parent, factory); + } + + public BootstrapAddonClassLoader(String name, URL[] urls, ClassLoader parent) { + super(name, urls, parent); + } + + public BootstrapAddonClassLoader(String name, URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) { + super(name, urls, parent, factory); + } + + @Override + public void addURL(URL url) { + super.addURL(url); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapBaseAddon.java b/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapBaseAddon.java new file mode 100644 index 000000000..f8f58c3f3 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/addon/bootstrap/BootstrapBaseAddon.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.addon.bootstrap; + +import java.nio.file.Path; + +import com.dfsek.terra.api.addon.BaseAddon; + + +/** + * Interface representing a bootstrap addon. + *

+ * A bootstrap addon is the only type of addon Terra implements a loader for. + * It is a minimal base for addon loaders to be implemented on top of. + *

+ * Unless you are writing your own addon loader, you will want to depend on the + * {@code manifest-addon-loader} addon, and implement its AddonInitializer. + * + * @param Type of addon this bootstrap addon loads + */ +public interface BootstrapBaseAddon extends BaseAddon { + /** + * Load all the relevant addons in the specified path. + * + * @param addonsFolder Path containing addons. + * @param parent parent class loader + * + * @return Loaded addons + */ + Iterable loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java b/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java new file mode 100644 index 000000000..78c20cd5e --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/BlockType.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.block.state.BlockState; + + +/** + * Represents a type of block + */ +public interface BlockType extends Handle { + /** + * Get the default {@link BlockState} of this block + * + * @return Default block state + */ + BlockState getDefaultState(); + + /** + * Get whether this block is solid. + * + * @return Whether this block is solid. + */ + boolean isSolid(); + + /** + * Get whether this block is water. + * + * @return Whether this block is water. + */ + boolean isWater(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/entity/BlockEntity.java b/common/api/src/main/java/com/dfsek/terra/api/block/entity/BlockEntity.java new file mode 100644 index 000000000..313e0f888 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/entity/BlockEntity.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.entity; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.vector.Vector3; + + +public interface BlockEntity extends Handle { + boolean update(boolean applyPhysics); + + default void applyState(String state) { + // Do nothing by default. + } + + Vector3 getPosition(); + + int getX(); + + int getY(); + + int getZ(); + + BlockState getBlockState(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/entity/Container.java b/common/api/src/main/java/com/dfsek/terra/api/block/entity/Container.java new file mode 100644 index 000000000..3b2a8588a --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/entity/Container.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.entity; + +import com.dfsek.terra.api.inventory.BlockInventoryHolder; + + +public interface Container extends BlockEntity, BlockInventoryHolder { +} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/state/MobSpawner.java b/common/api/src/main/java/com/dfsek/terra/api/block/entity/MobSpawner.java similarity index 60% rename from common/src/main/java/com/dfsek/terra/api/platform/block/state/MobSpawner.java rename to common/api/src/main/java/com/dfsek/terra/api/block/entity/MobSpawner.java index ef1b2d606..b64e7ed5c 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/state/MobSpawner.java +++ b/common/api/src/main/java/com/dfsek/terra/api/block/entity/MobSpawner.java @@ -1,38 +1,47 @@ -package com.dfsek.terra.api.platform.block.state; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.entity; -import com.dfsek.terra.api.platform.entity.EntityType; import org.jetbrains.annotations.NotNull; -public interface MobSpawner extends BlockState { +import com.dfsek.terra.api.entity.EntityType; + + +public interface MobSpawner extends BlockEntity { EntityType getSpawnedType(); - + void setSpawnedType(@NotNull EntityType creatureType); - + int getDelay(); - + void setDelay(int delay); - + int getMinSpawnDelay(); - + void setMinSpawnDelay(int delay); - + int getMaxSpawnDelay(); - + void setMaxSpawnDelay(int delay); - + int getSpawnCount(); - + void setSpawnCount(int spawnCount); - + int getMaxNearbyEntities(); - + void setMaxNearbyEntities(int maxNearbyEntities); - + int getRequiredPlayerRange(); - + void setRequiredPlayerRange(int requiredPlayerRange); - + int getSpawnRange(); - + void setSpawnRange(int spawnRange); } diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/state/SerialState.java b/common/api/src/main/java/com/dfsek/terra/api/block/entity/SerialState.java similarity index 88% rename from common/src/main/java/com/dfsek/terra/api/platform/block/state/SerialState.java rename to common/api/src/main/java/com/dfsek/terra/api/block/entity/SerialState.java index 7c05c1253..17af01361 100644 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/state/SerialState.java +++ b/common/api/src/main/java/com/dfsek/terra/api/block/entity/SerialState.java @@ -1,14 +1,22 @@ -package com.dfsek.terra.api.platform.block.state; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.entity; import java.util.HashMap; import java.util.Map; + public class SerialState { protected final Map> properties = new HashMap<>(); - + public SerialState() { } - + public static Map parse(String props) { String[] sep = props.split(","); Map map = new HashMap<>(); @@ -17,51 +25,7 @@ public class SerialState { } return map; } - - private void checkExists(String prop) { - if(!properties.containsKey(prop)) throw new IllegalArgumentException("No such property \"" + prop + "\""); - } - - private void checkType(Class clazz, Object o, String id) { - if(!clazz.isInstance(o)) - throw new IllegalArgumentException("Invalid data for property " + id + ": " + o); - } - - public void setProperty(String id, Object value) { - checkExists(id); - Property prop = properties.get(id); - checkType(prop.getValueClass(), value, id); - prop.setValue(value); - } - - public int getInteger(String id) { - checkExists(id); - Property prop = properties.get(id); - checkType(Integer.class, prop.getValue(), id); - return (Integer) prop.getValue(); - } - - public String getString(String id) { - checkExists(id); - Property prop = properties.get(id); - checkType(String.class, prop.getValue(), id); - return (String) prop.getValue(); - } - - public long getLong(String id) { - checkExists(id); - Property prop = properties.get(id); - checkType(Long.class, prop.getValue(), id); - return (Long) prop.getValue(); - } - - public boolean getBoolean(String id) { - checkExists(id); - Property prop = properties.get(id); - checkType(Boolean.class, prop.getValue(), id); - return (Boolean) prop.getValue(); - } - + @SuppressWarnings("unchecked") public T get(String id, Class clazz) { checkExists(id); @@ -69,24 +33,69 @@ public class SerialState { checkType(clazz, prop.getValue(), id); return (T) prop.getValue(); } - + + private void checkExists(String prop) { + if(!properties.containsKey(prop)) throw new IllegalArgumentException("No such property \"" + prop + "\""); + } + + private void checkType(Class clazz, Object o, String id) { + if(!clazz.isInstance(o)) + throw new IllegalArgumentException("Invalid data for property " + id + ": " + o); + } + + public void setProperty(String id, Object value) { + checkExists(id); + Property prop = properties.get(id); + checkType(prop.getValueClass(), value, id); + prop.setValue(value); + } + + public int getInteger(String id) { + checkExists(id); + Property prop = properties.get(id); + checkType(Integer.class, prop.getValue(), id); + return (Integer) prop.getValue(); + } + + public String getString(String id) { + checkExists(id); + Property prop = properties.get(id); + checkType(String.class, prop.getValue(), id); + return (String) prop.getValue(); + } + + public long getLong(String id) { + checkExists(id); + Property prop = properties.get(id); + checkType(Long.class, prop.getValue(), id); + return (Long) prop.getValue(); + } + + public boolean getBoolean(String id) { + checkExists(id); + Property prop = properties.get(id); + checkType(Boolean.class, prop.getValue(), id); + return (Boolean) prop.getValue(); + } + + protected static class Property { private final Class clazz; private Object value; - + public Property(Class clazz) { this.clazz = clazz; } - + public Class getValueClass() { return clazz; } - + @SuppressWarnings("unchecked") public T getValue() { return (T) value; } - + public void setValue(Object value) { this.value = value; } diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/entity/Sign.java b/common/api/src/main/java/com/dfsek/terra/api/block/entity/Sign.java new file mode 100644 index 000000000..4f48c2b99 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/entity/Sign.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.entity; + +import org.jetbrains.annotations.NotNull; + + +public interface Sign extends BlockEntity { + void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException; + + @NotNull String[] getLines(); + + @NotNull String getLine(int index) throws IndexOutOfBoundsException; +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockState.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockState.java new file mode 100644 index 000000000..039f078d0 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/BlockState.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state; + +import java.util.function.Consumer; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.properties.Property; + + +/** + * Contains basic data about a {@link BlockType} in the world + */ +public interface BlockState extends Handle { + + /** + * Whether this {@link BlockState} matches another. + *

+ * "matches" is defined as this {@link BlockState} holding a matching {@link #getBlockType()}. + * + * @param other Other {@link BlockState} + * + * @return Whether this state matches the other + */ + boolean matches(BlockState other); + + /** + * Check whether this {@link BlockState} has a {@link Property}. + * + * @param property Property to check for + * + * @return Whether this state has the property. + */ + > boolean has(Property property); + + /** + * Get the value of a {@link Property} on this state. + * + * @param property Property to get + * + * @return Value of the property + */ + > T get(Property property); + + /** + * Return a new {@link BlockState} with a {@link Property} set to a value. + * + * @param property Property to set + * @param value Value of property + * + * @return New {@link BlockState} with property set. + */ + > BlockState set(Property property, T value); + + /** + * Perform an action on this {@link BlockState} if it contains a {@link Property} + * + * @param property Property to check for + * @param action Action to perform if property is present + * + * @return This {@link BlockState} + */ + default > BlockState ifProperty(Property property, Consumer action) { + if(has(property)) action.accept(this); + return this; + } + + /** + * Set the value of a {@link Property} on this {@link BlockState} if it is present. + * + * @param property Property to check for/set. + * @param value Value to set if property is present. + * + * @return Thie {@link BlockState} + */ + default > BlockState setIfPresent(Property property, T value) { + if(has(property)) set(property, value); + return this; + } + + /** + * Get the {@link BlockType} this state applies to. + * + * @return Block type. + */ + BlockType getBlockType(); + + /** + * Get this state and its properties as a String + * + * @return String representation of this state + */ + default String getAsString() { + return getAsString(true); + } + + /** + * Get this state and its properties as a String + * + * @param properties Whether to include properties + * + * @return String representation of this state + */ + String getAsString(boolean properties); + + /** + * Get whether this BlockState is air + * + * @return Whether this state is air + */ + boolean isAir(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/Property.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/Property.java new file mode 100644 index 000000000..3bebb4771 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/Property.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state.properties; + +import java.util.Collection; + +import com.dfsek.terra.api.registry.key.StringIdentifiable; + + +/** + * Represents a property a state holds + */ +public interface Property extends StringIdentifiable { + /** + * Get all possible values of this property + * + * @return All values of this property + */ + Collection values(); + + /** + * Get the type of this property. + * + * @return {@link Class} instance representing the type of this property + */ + Class getType(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/base/BooleanProperty.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/base/BooleanProperty.java new file mode 100644 index 000000000..e005145e0 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/base/BooleanProperty.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state.properties.base; + +import java.util.Arrays; +import java.util.Collection; + +import com.dfsek.terra.api.block.state.properties.Property; + + +public interface BooleanProperty extends Property { + static BooleanProperty of(String name) { + return new BooleanProperty() { + private static final Collection BOOLEANS = Arrays.asList(true, false); + + @Override + public Collection values() { + return BOOLEANS; + } + + @Override + public String getID() { + return name; + } + }; + } + + @Override + default Class getType() { + return Boolean.class; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/base/EnumProperty.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/base/EnumProperty.java new file mode 100644 index 000000000..df0f3b52c --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/base/EnumProperty.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state.properties.base; + +import java.util.Arrays; +import java.util.Collection; + +import com.dfsek.terra.api.block.state.properties.Property; +import com.dfsek.terra.api.util.generic.Lazy; + + +public interface EnumProperty> extends Property { + static > EnumProperty of(String name, Class clazz) { + return new EnumProperty<>() { + private final Lazy> constants = Lazy.lazy(() -> Arrays.asList(clazz.getEnumConstants())); + + @Override + public Collection values() { + return constants.value(); + } + + @Override + public Class getType() { + return clazz; + } + + @Override + public String getID() { + return name; + } + }; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/base/IntProperty.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/base/IntProperty.java new file mode 100644 index 000000000..b671e4689 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/base/IntProperty.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state.properties.base; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.dfsek.terra.api.block.state.properties.Property; +import com.dfsek.terra.api.util.generic.Construct; + + +public interface IntProperty extends Property { + static IntProperty of(String name, int min, int max) { + return new IntProperty() { + private final Collection collection = Construct.construct(() -> { + List ints = new ArrayList<>(); + for(int i = min; i <= max; i++) { + ints.add(i); + } + return ints; + }); + + @Override + public Collection values() { + return collection; + } + + @Override + public String getID() { + return name; + } + }; + } + + @Override + default Class getType() { + return Integer.class; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/Axis.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/Axis.java new file mode 100644 index 000000000..f57362ef1 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/Axis.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state.properties.enums; + +public enum Axis { + X, + Y, + Z +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/Direction.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/Direction.java new file mode 100644 index 000000000..5cdacf976 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/Direction.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state.properties.enums; + +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.generic.Construct; + + +public enum Direction { + NORTH(0, 0, 0, -1), + EAST(1, 1, 0, 0), + SOUTH(2, 0, 0, 1), + WEST(3, -1, 0, 0), + UP(-1, 0, 1, 0), + DOWN(-1, 0, -1, 0); + + private static final Direction[] rotations = Construct.construct(() -> new Direction[]{ NORTH, SOUTH, EAST, WEST }); + + private final int rotation; + + private final int modX; + private final int modY; + private final int modZ; + + Direction(int rotation, int modX, int modY, int modZ) { + this.rotation = rotation; + this.modX = modX; + this.modY = modY; + this.modZ = modZ; + } + + public Direction rotate(Rotation rotation) { + return switch(this) { + case UP, DOWN -> this; + default -> rotations[(this.rotation + rotation.getDegrees() / 90) % 4]; + }; + } + + public Direction opposite() { + return switch(this) { + case DOWN -> UP; + case UP -> DOWN; + case EAST -> WEST; + case WEST -> EAST; + case NORTH -> SOUTH; + case SOUTH -> NORTH; + }; + } + + public int getModX() { + return modX; + } + + public int getModY() { + return modY; + } + + public int getModZ() { + return modZ; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/Half.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/Half.java new file mode 100644 index 000000000..160710629 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/Half.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state.properties.enums; + +public enum Half { + /** + * The top half of the block, normally with the higher y coordinate. + */ + TOP, + /** + * The bottom half of the block, normally with the lower y coordinate. + */ + BOTTOM, + + /** + * Some blocks, e.g. slabs, can occupy both halves. + */ + DOUBLE +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/RailShape.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/RailShape.java new file mode 100644 index 000000000..6030b699c --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/RailShape.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state.properties.enums; + +public enum RailShape { + ASCENDING_EAST, + ASCENDING_NORTH, + ASCENDING_SOUTH, + ASCENDING_WEST, + EAST_WEST, + NORTH_EAST, + NORTH_SOUTH, + NORTH_WEST, + SOUTH_EAST, + SOUTH_WEST +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/RedstoneConnection.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/RedstoneConnection.java new file mode 100644 index 000000000..12b5899c8 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/RedstoneConnection.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state.properties.enums; + +public enum RedstoneConnection { + NONE, + SIDE, + UP +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/WallHeight.java b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/WallHeight.java new file mode 100644 index 000000000..e9940eace --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/block/state/properties/enums/WallHeight.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.block.state.properties.enums; + +public enum WallHeight { + LOW, + NONE, + TALL +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/command/CommandSender.java b/common/api/src/main/java/com/dfsek/terra/api/command/CommandSender.java new file mode 100644 index 000000000..8d0ff260a --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/command/CommandSender.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.command; + +import java.util.Optional; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.Player; + + +public interface CommandSender extends Handle { + void sendMessage(String message); + + Optional getEntity(); + + Optional getPlayer(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/command/arguments/RegistryArgument.java b/common/api/src/main/java/com/dfsek/terra/api/command/arguments/RegistryArgument.java new file mode 100644 index 000000000..7cb8f731f --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/command/arguments/RegistryArgument.java @@ -0,0 +1,153 @@ +package com.dfsek.terra.api.command.arguments; + +import cloud.commandframework.ArgumentDescription; +import cloud.commandframework.arguments.CommandArgument; +import cloud.commandframework.arguments.parser.ArgumentParseResult; +import cloud.commandframework.arguments.parser.ArgumentParser; +import cloud.commandframework.context.CommandContext; +import io.leangen.geantyref.TypeToken; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.util.List; +import java.util.Optional; +import java.util.Queue; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.stream.Collectors; + +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.registry.exception.NoSuchEntryException; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class RegistryArgument extends CommandArgument { + private RegistryArgument( + boolean required, + @NonNull String name, + Function, Registry> registryFunction, + TypeToken typeToken, + @NonNull String defaultValue, + @Nullable BiFunction, String, List> suggestionsProvider, + @NonNull ArgumentDescription description + ) { + super(required, + name, + new RegistryArgumentParser<>(registryFunction), + defaultValue, + typeToken, + suggestionsProvider, + description); + } + + public static Builder builder(String name, Registry registry) { + return new Builder<>(name, registry); + } + + public static CommandArgument of(String name, Registry registry) { + return RegistryArgument.builder(name, registry).build(); + } + + public static CommandArgument optional(String name, Registry registry) { + return RegistryArgument.builder(name, registry).asOptional().build(); + } + + public static CommandArgument optional(String name, Registry registry, String defaultKey) { + return RegistryArgument.builder(name, registry).asOptionalWithDefault(defaultKey).build(); + } + + @SuppressWarnings("unchecked") + public static Builder builder(String name, Function, Registry> registryFunction, + TypeKey registryType) { + return new Builder<>(name, registryFunction, (TypeToken) TypeToken.get(registryType.getType())); + } + + public static CommandArgument of(String name, Function, Registry> registryFunction, + TypeKey registryType) { + return RegistryArgument.builder(name, registryFunction, registryType).build(); + } + + public static CommandArgument optional(String name, Function, Registry> registryFunction, + TypeKey registryType) { + return RegistryArgument.builder(name, registryFunction, registryType).asOptional().build(); + } + + public static CommandArgument optional(String name, Function, Registry> registryFunction, + TypeKey registryType, String defaultKey) { + return RegistryArgument.builder(name, registryFunction, registryType).asOptionalWithDefault(defaultKey).build(); + } + + public static final class Builder extends CommandArgument.Builder { + private final Function, Registry> registryFunction; + private final TypeToken typeToken; + + @SuppressWarnings("unchecked") + private Builder(@NonNull String name, Registry registry) { + super((TypeToken) TypeToken.get(registry.getType().getType()), name); + this.registryFunction = commandContext -> registry; + this.typeToken = (TypeToken) TypeToken.get(registry.getType().getType()); + } + + private Builder(@NonNull String name, Function, Registry> registryFunction, TypeToken typeToken) { + super(typeToken, name); + this.typeToken = typeToken; + this.registryFunction = registryFunction; + } + + @Override + public @NonNull RegistryArgument build() { + return new RegistryArgument<>( + isRequired(), + getName(), + registryFunction, + typeToken, + getDefaultValue(), + getSuggestionsProvider(), + getDefaultDescription() + ); + } + } + + + private static final class RegistryArgumentParser implements ArgumentParser { + private final Function, Registry> registryFunction; + + private RegistryArgumentParser(Function, Registry> registryFunction) { + this.registryFunction = registryFunction; + } + + @Override + public @NonNull ArgumentParseResult<@NonNull R> parse(@NonNull CommandContext<@NonNull T> commandContext, + @NonNull Queue<@NonNull String> inputQueue) { + String input = inputQueue.remove(); + String next = inputQueue.peek(); + if(next != null && next.equals(":")) { + input += inputQueue.remove(); + input += inputQueue.remove(); + } + + Registry registry = registryFunction.apply(commandContext); + + Optional result; + try { + result = registry.get(RegistryKey.parse(input)); + } catch(IllegalArgumentException e) { + try { + result = registry.getByID(input); + } catch(IllegalArgumentException e1) { + return ArgumentParseResult.failure(e1); + } + } + + return result + .map(ArgumentParseResult::success) + .orElse(ArgumentParseResult.failure(new NoSuchEntryException("No such entry: " + input))); + } + + @Override + public @NonNull List<@NonNull String> suggestions(@NonNull CommandContext commandContext, @NonNull String input) { + return registryFunction.apply(commandContext).keys().stream().map(RegistryKey::toString).sorted().collect(Collectors.toList()); + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/config/AbstractableTemplate.java b/common/api/src/main/java/com/dfsek/terra/api/config/AbstractableTemplate.java new file mode 100644 index 000000000..144183a6f --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/config/AbstractableTemplate.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.config; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; + +import com.dfsek.terra.api.registry.key.StringIdentifiable; + + +/** + * An abstractable config template + */ +public interface AbstractableTemplate extends ConfigTemplate, StringIdentifiable { +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/config/ConfigFactory.java b/common/api/src/main/java/com/dfsek/terra/api/config/ConfigFactory.java new file mode 100644 index 000000000..abbffc7d9 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/config/ConfigFactory.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.config; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.exception.LoadException; + +import com.dfsek.terra.api.Platform; + + +public interface ConfigFactory { + O build(C config, Platform platform) throws LoadException; +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/config/ConfigPack.java b/common/api/src/main/java/com/dfsek/terra/api/config/ConfigPack.java new file mode 100644 index 000000000..860a742be --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/config/ConfigPack.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.config; + +import ca.solostudios.strata.version.Version; +import ca.solostudios.strata.version.VersionRange; + +import java.util.List; +import java.util.Map; + +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.properties.PropertyHolder; +import com.dfsek.terra.api.registry.key.Keyed; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.registry.meta.CheckedRegistryHolder; +import com.dfsek.terra.api.registry.meta.RegistryProvider; +import com.dfsek.terra.api.tectonic.ConfigLoadingDelegate; +import com.dfsek.terra.api.tectonic.LoaderRegistrar; +import com.dfsek.terra.api.tectonic.ShortcutLoader; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; +import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider; + + +public interface ConfigPack extends LoaderRegistrar, + ConfigLoadingDelegate, + CheckedRegistryHolder, + RegistryProvider, + Keyed, + PropertyHolder { + + ConfigPack registerConfigType(ConfigType type, RegistryKey id, int priority); + + Map addons(); + + BiomeProvider getBiomeProvider(); + + List getStages(); + + Loader getLoader(); + + String getAuthor(); + + Version getVersion(); + + ConfigPack registerShortcut(TypeKey clazz, String shortcut, ShortcutLoader loader); + + default ConfigPack registerShortcut(Class clazz, String shortcut, ShortcutLoader loader) { + return registerShortcut(TypeKey.of(clazz), shortcut, loader); + } + + ChunkGeneratorProvider getGeneratorProvider(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/config/ConfigType.java b/common/api/src/main/java/com/dfsek/terra/api/config/ConfigType.java new file mode 100644 index 000000000..7c3e604c1 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/config/ConfigType.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.config; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public interface ConfigType { + T getTemplate(ConfigPack pack, Platform platform); + + ConfigFactory getFactory(); + + TypeKey getTypeKey(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/config/Loader.java b/common/api/src/main/java/com/dfsek/terra/api/config/Loader.java new file mode 100644 index 000000000..1d540c3fc --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/config/Loader.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.config; + +import com.dfsek.tectonic.api.exception.ConfigException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; + + +public interface Loader { + + Loader thenNames(Consumer> consumer) throws ConfigException; + + Loader thenEntries(Consumer>> consumer) throws ConfigException; + + /** + * Get a single file from this Loader. + * + * @param singleFile File to get + * + * @return InputStream from file. + */ + InputStream get(String singleFile) throws IOException; + + /** + * Open a subdirectory. + * + * @param directory Directory to open + * @param extension File extension + */ + Loader open(String directory, String extension); + + /** + * Close all InputStreams opened. + */ + Loader close(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/config/PluginConfig.java b/common/api/src/main/java/com/dfsek/terra/api/config/PluginConfig.java new file mode 100644 index 000000000..2d540e483 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/config/PluginConfig.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.config; + +import com.dfsek.terra.api.Platform; + + +public interface PluginConfig { + void load(Platform platform); + + boolean dumpDefaultConfig(); + + boolean isDebugCommands(); + + boolean isDebugProfiler(); + + boolean isDebugScript(); + + int getBiomeSearchResolution(); + + int getStructureCache(); + + int getSamplerCache(); + + int getMaxRecursion(); + + int getProviderCache(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/config/meta/Meta.java b/common/api/src/main/java/com/dfsek/terra/api/config/meta/Meta.java new file mode 100644 index 000000000..874b9900a --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/config/meta/Meta.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.config.meta; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE_USE) +public @interface Meta { +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/entity/Entity.java b/common/api/src/main/java/com/dfsek/terra/api/entity/Entity.java new file mode 100644 index 000000000..0f11b746e --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/entity/Entity.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.entity; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; + + +public interface Entity extends Handle { + Vector3 position(); + + void position(Vector3 position); + + void world(ServerWorld world); + + ServerWorld world(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/entity/EntityType.java b/common/api/src/main/java/com/dfsek/terra/api/entity/EntityType.java new file mode 100644 index 000000000..b873e69f4 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/entity/EntityType.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.entity; + +import com.dfsek.terra.api.Handle; + + +public interface EntityType extends Handle { +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/entity/Player.java b/common/api/src/main/java/com/dfsek/terra/api/entity/Player.java new file mode 100644 index 000000000..972d7e265 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/entity/Player.java @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.entity; + +public interface Player extends Entity { +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/EventHandler.java b/common/api/src/main/java/com/dfsek/terra/api/event/EventHandler.java new file mode 100644 index 000000000..6c9c71fd6 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/EventHandler.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event; + +import com.dfsek.terra.api.event.events.Event; + + +public interface EventHandler { + void handle(Event event); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/EventManager.java b/common/api/src/main/java/com/dfsek/terra/api/event/EventManager.java new file mode 100644 index 000000000..b602f3911 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/EventManager.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event; + +import com.dfsek.terra.api.event.events.Event; + + +/** + * Manages event registration and triggering. + */ +public interface EventManager { + /** + * Call an event, and return the execution status. + * + * @param event Event to pass to all registered EventListeners. + */ + T callEvent(T event); + + void registerHandler(Class clazz, T handler); + + T getHandler(Class clazz); +} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/AbstractCancellable.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/AbstractCancellable.java similarity index 70% rename from common/src/main/java/com/dfsek/terra/api/event/events/AbstractCancellable.java rename to common/api/src/main/java/com/dfsek/terra/api/event/events/AbstractCancellable.java index e6fdd5319..188f078c9 100644 --- a/common/src/main/java/com/dfsek/terra/api/event/events/AbstractCancellable.java +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/AbstractCancellable.java @@ -1,18 +1,26 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + package com.dfsek.terra.api.event.events; import com.dfsek.terra.api.util.mutable.MutableBoolean; + /** * Abstract class containing basic {@link Cancellable} implementation. */ public abstract class AbstractCancellable implements Cancellable { private final MutableBoolean cancelled = new MutableBoolean(false); - + @Override public boolean isCancelled() { return cancelled.get(); } - + @Override public void setCancelled(boolean cancelled) { this.cancelled.set(cancelled); diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/Cancellable.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/Cancellable.java similarity index 73% rename from common/src/main/java/com/dfsek/terra/api/event/events/Cancellable.java rename to common/api/src/main/java/com/dfsek/terra/api/event/events/Cancellable.java index ca7bccdf7..4a832b817 100644 --- a/common/src/main/java/com/dfsek/terra/api/event/events/Cancellable.java +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/Cancellable.java @@ -1,3 +1,10 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + package com.dfsek.terra.api.event.events; /** @@ -12,7 +19,7 @@ public interface Cancellable extends Event { * @return Whether event is cancelled. */ boolean isCancelled(); - + /** * Set the cancellation status of the event. * diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/Event.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/Event.java new file mode 100644 index 000000000..3051c744f --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/Event.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events; + +/** + * An event that addons may listen to. + */ +public interface Event { +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/FailThroughEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/FailThroughEvent.java new file mode 100644 index 000000000..0c1f35382 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/FailThroughEvent.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events; + +/** + * An event which (optionally) passes exceptions thrown by listeners to + * the event caller. + */ +public interface FailThroughEvent extends Event { +} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/PackEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/PackEvent.java similarity index 60% rename from common/src/main/java/com/dfsek/terra/api/event/events/PackEvent.java rename to common/api/src/main/java/com/dfsek/terra/api/event/events/PackEvent.java index 66f7b7d6c..cb7ebe079 100644 --- a/common/src/main/java/com/dfsek/terra/api/event/events/PackEvent.java +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/PackEvent.java @@ -1,13 +1,20 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + package com.dfsek.terra.api.event.events; -import com.dfsek.terra.api.event.annotations.Global; -import com.dfsek.terra.config.pack.ConfigPack; +import com.dfsek.terra.api.config.ConfigPack; + /** * An event with functionality directly linked to a {@link ConfigPack}. *

* PackEvents are only invoked when the pack specifies the addon in its - * {@code addon} key (or when the listener is annotated {@link Global}). + * {@code addon} key (or when the listener is global). */ @SuppressWarnings("InterfaceMayBeAnnotatedFunctional") public interface PackEvent extends Event { diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/config/ConfigurationDiscoveryEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/ConfigurationDiscoveryEvent.java new file mode 100644 index 000000000..74be475a0 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/ConfigurationDiscoveryEvent.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events.config; + +import com.dfsek.tectonic.api.config.Configuration; + +import java.util.function.BiConsumer; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.Loader; +import com.dfsek.terra.api.event.events.FailThroughEvent; +import com.dfsek.terra.api.event.events.PackEvent; + + +/** + * Fired when a pack is searched for {@link Configuration}s. + *

+ * Addons should listen to this event if they wish to add + * another configuration format. + */ +public class ConfigurationDiscoveryEvent implements PackEvent, FailThroughEvent { + private final ConfigPack pack; + private final Loader loader; + + private final BiConsumer consumer; + + public ConfigurationDiscoveryEvent(ConfigPack pack, Loader loader, BiConsumer consumer) { + this.pack = pack; + this.loader = loader; + this.consumer = consumer; + } + + public void register(String identifier, Configuration config) { + consumer.accept(identifier, config); + } + + @Override + public ConfigPack getPack() { + return pack; + } + + public Loader getLoader() { + return loader; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/config/ConfigurationLoadEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/ConfigurationLoadEvent.java new file mode 100644 index 000000000..55f5f969f --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/ConfigurationLoadEvent.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events.config; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.impl.abstraction.AbstractConfiguration; + +import java.util.function.Consumer; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.event.events.FailThroughEvent; +import com.dfsek.terra.api.event.events.PackEvent; +import com.dfsek.terra.api.util.reflection.ReflectionUtil; + + +/** + * Fired when each individual configuration is loaded. + *

+ * Addons should listen to this event if they wish to add + * config values to existing {@link ConfigType}s. + */ +public class ConfigurationLoadEvent implements PackEvent, FailThroughEvent { + private final ConfigPack pack; + private final AbstractConfiguration configuration; + private final Consumer loader; + private final ConfigType type; + + private final Object loaded; + + public ConfigurationLoadEvent(ConfigPack pack, AbstractConfiguration configuration, Consumer loader, + ConfigType type, Object loaded) { + this.pack = pack; + this.configuration = configuration; + this.loader = loader; + this.type = type; + this.loaded = loaded; + } + + public T load(T template) { + loader.accept(template); + return template; + } + + public boolean is(Class clazz) { + return clazz.isAssignableFrom(type.getTypeKey().getRawType()); + } + + @Override + public ConfigPack getPack() { + return pack; + } + + public AbstractConfiguration getConfiguration() { + return configuration; + } + + public ConfigType getType() { + return type; + } + + @SuppressWarnings("unchecked") + public T getLoadedObject(Class clazz) { + if(!clazz.isAssignableFrom(type.getTypeKey().getRawType())) + throw new ClassCastException( + "Cannot assign object from loader of type " + ReflectionUtil.typeToString(type.getTypeKey().getType()) + " to class " + + clazz.getCanonicalName()); + return (T) loaded; + } + + @SuppressWarnings("unchecked") + public T getLoadedObject() { + return (T) loaded; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackLoadEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/pack/ConfigPackLoadEvent.java similarity index 53% rename from common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackLoadEvent.java rename to common/api/src/main/java/com/dfsek/terra/api/event/events/config/pack/ConfigPackLoadEvent.java index e995c8897..47664bbfe 100644 --- a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackLoadEvent.java +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/pack/ConfigPackLoadEvent.java @@ -1,36 +1,47 @@ -package com.dfsek.terra.api.event.events.config; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.tectonic.exception.ConfigException; +package com.dfsek.terra.api.event.events.config.pack; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.exception.ConfigException; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.event.events.FailThroughEvent; import com.dfsek.terra.api.event.events.PackEvent; -import com.dfsek.terra.config.pack.ConfigPack; + /** * An event related to the loading process of config packs. */ -public abstract class ConfigPackLoadEvent implements PackEvent { +public abstract class ConfigPackLoadEvent implements PackEvent, FailThroughEvent { private final ConfigPack pack; private final ExceptionalConsumer configLoader; - + public ConfigPackLoadEvent(ConfigPack pack, ExceptionalConsumer configLoader) { this.pack = pack; this.configLoader = configLoader; } - - @Override - public ConfigPack getPack() { - return pack; - } - + /** * Load a custom {@link ConfigTemplate} using the pack manifest. * * @param template Template to register. */ - public void loadTemplate(ConfigTemplate template) throws ConfigException { + public T loadTemplate(T template) throws ConfigException { configLoader.accept(template); + return template; } - + + @Override + public ConfigPack getPack() { + return pack; + } + public interface ExceptionalConsumer { void accept(T value) throws ConfigException; } diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/config/pack/ConfigPackPostLoadEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/pack/ConfigPackPostLoadEvent.java new file mode 100644 index 000000000..95a504798 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/pack/ConfigPackPostLoadEvent.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events.config.pack; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; + +import com.dfsek.terra.api.config.ConfigPack; + + +/** + * Called when a config pack has finished loading. + */ +public class ConfigPackPostLoadEvent extends ConfigPackLoadEvent { + public ConfigPackPostLoadEvent(ConfigPack pack, ExceptionalConsumer loader) { + super(pack, loader); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/config/pack/ConfigPackPreLoadEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/pack/ConfigPackPreLoadEvent.java new file mode 100644 index 000000000..8e09c3fe1 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/pack/ConfigPackPreLoadEvent.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events.config.pack; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; + +import com.dfsek.terra.api.config.ConfigPack; + + +/** + * Called before a config pack's registries are filled. + */ +public class ConfigPackPreLoadEvent extends ConfigPackLoadEvent { + public ConfigPackPreLoadEvent(ConfigPack pack, ExceptionalConsumer configLoader) { + super(pack, configLoader); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/config/type/ConfigTypeLoadEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/type/ConfigTypeLoadEvent.java new file mode 100644 index 000000000..8dd7db191 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/type/ConfigTypeLoadEvent.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events.config.type; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.event.events.FailThroughEvent; +import com.dfsek.terra.api.event.events.PackEvent; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.util.reflection.ReflectionUtil; + + +public abstract class ConfigTypeLoadEvent implements PackEvent, FailThroughEvent { + private final ConfigType type; + private final CheckedRegistry registry; + + private final ConfigPack pack; + + public ConfigTypeLoadEvent(ConfigType type, CheckedRegistry registry, ConfigPack pack) { + this.type = type; + this.registry = registry; + this.pack = pack; + } + + public boolean is(Class clazz) { + return clazz.isAssignableFrom(type.getTypeKey().getRawType()); + } + + @Override + public ConfigPack getPack() { + return pack; + } + + @SuppressWarnings("unchecked") + public CheckedRegistry getRegistry(Class clazz) { + if(!clazz.isAssignableFrom(type.getTypeKey().getRawType())) + throw new ClassCastException( + "Cannot assign object from loader of type " + ReflectionUtil.typeToString(type.getTypeKey().getType()) + " to class " + + clazz.getCanonicalName()); + return (CheckedRegistry) registry; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/config/type/ConfigTypePostLoadEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/type/ConfigTypePostLoadEvent.java new file mode 100644 index 000000000..f3b72ccd2 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/type/ConfigTypePostLoadEvent.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events.config.type; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.registry.CheckedRegistry; + + +public class ConfigTypePostLoadEvent extends ConfigTypeLoadEvent { + public ConfigTypePostLoadEvent(ConfigType type, CheckedRegistry registry, ConfigPack pack) { + super(type, registry, pack); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/config/type/ConfigTypePreLoadEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/type/ConfigTypePreLoadEvent.java new file mode 100644 index 000000000..084d68a0a --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/config/type/ConfigTypePreLoadEvent.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events.config.type; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.registry.CheckedRegistry; + + +public class ConfigTypePreLoadEvent extends ConfigTypeLoadEvent { + public ConfigTypePreLoadEvent(ConfigType type, CheckedRegistry registry, ConfigPack pack) { + super(type, registry, pack); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/platform/CommandRegistrationEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/platform/CommandRegistrationEvent.java new file mode 100644 index 000000000..40d113079 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/platform/CommandRegistrationEvent.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.api.event.events.platform; + +import cloud.commandframework.CommandManager; + +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.event.events.Event; + + +public class CommandRegistrationEvent implements Event { + private final CommandManager commandManager; + + public CommandRegistrationEvent(CommandManager commandManager) { + this.commandManager = commandManager; + } + + public CommandManager getCommandManager() { + return commandManager; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/platform/PlatformInitializationEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/platform/PlatformInitializationEvent.java new file mode 100644 index 000000000..d94ee750c --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/platform/PlatformInitializationEvent.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events.platform; + +import com.dfsek.terra.api.event.events.Event; + + +/** + * Called when the platform is initialized. + */ +public class PlatformInitializationEvent implements Event { +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/world/generation/EntitySpawnEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/world/generation/EntitySpawnEvent.java new file mode 100644 index 000000000..2efc4ac24 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/world/generation/EntitySpawnEvent.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.events.world.generation; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.event.events.PackEvent; + + +/** + * Called when an entity is spawned. + */ +public class EntitySpawnEvent implements PackEvent { + private final ConfigPack pack; + private final Entity entity; + + public EntitySpawnEvent(ConfigPack pack, Entity entity) { + this.pack = pack; + this.entity = entity; + } + + @Override + public ConfigPack getPack() { + return pack; + } + + /** + * Get the entity that triggered the event. + * + * @return The entity. + */ + public Entity getEntity() { + return entity; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/world/generation/LootPopulateEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/world/generation/LootPopulateEvent.java similarity index 54% rename from common/src/main/java/com/dfsek/terra/api/event/events/world/generation/LootPopulateEvent.java rename to common/api/src/main/java/com/dfsek/terra/api/event/events/world/generation/LootPopulateEvent.java index cb3735017..e956c5067 100644 --- a/common/src/main/java/com/dfsek/terra/api/event/events/world/generation/LootPopulateEvent.java +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/world/generation/LootPopulateEvent.java @@ -1,48 +1,48 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + package com.dfsek.terra.api.event.events.world.generation; -import com.dfsek.terra.api.event.events.AbstractCancellable; -import com.dfsek.terra.api.event.events.Cancellable; -import com.dfsek.terra.api.event.events.PackEvent; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.state.Container; -import com.dfsek.terra.api.structures.loot.LootTable; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication; -import com.dfsek.terra.config.pack.ConfigPack; import org.jetbrains.annotations.NotNull; -/** - * Called when loot is populated via {@link BufferedLootApplication}. - */ -public class LootPopulateEvent extends AbstractCancellable implements PackEvent, Cancellable { - private final Block block; - private final Container container; - private LootTable table; - private final ConfigPack pack; - private final StructureScript script; +import com.dfsek.terra.api.block.entity.Container; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.event.events.AbstractCancellable; +import com.dfsek.terra.api.event.events.PackEvent; +import com.dfsek.terra.api.structure.LootTable; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.util.vector.Vector3; - public LootPopulateEvent(Block block, Container container, LootTable table, ConfigPack pack, StructureScript script) { - this.block = block; + +/** + * Called when loot is populated. + */ +public class LootPopulateEvent extends AbstractCancellable implements PackEvent { + private final Container container; + private final ConfigPack pack; + private final Structure structure; + private LootTable table; + + public LootPopulateEvent(Container container, LootTable table, ConfigPack pack, Structure structure) { this.container = container; this.table = table; this.pack = pack; - this.script = script; + this.structure = structure; } - + @Override public ConfigPack getPack() { return pack; } - - /** - * Get the block containing the tile entity loot is applied to. - * - * @return Block at which loot is applied. - */ - public Block getBlock() { - return block; + + public Vector3 getPosition() { + return container.getPosition(); } - + /** * Get the {@link Container} representing the inventory. * @@ -51,15 +51,16 @@ public class LootPopulateEvent extends AbstractCancellable implements PackEvent, public Container getContainer() { return container; } - + /** * Get the loot table to be populated. + * * @return Loot table. */ public LootTable getTable() { return table; } - + /** * Set the loot table to be populated. * @@ -68,13 +69,13 @@ public class LootPopulateEvent extends AbstractCancellable implements PackEvent, public void setTable(@NotNull LootTable table) { this.table = table; } - + /** * Get the script used to generate the structure. * * @return Structure script. */ - public StructureScript getStructureScript() { - return script; + public Structure getStructure() { + return structure; } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/functional/EventContext.java b/common/api/src/main/java/com/dfsek/terra/api/event/functional/EventContext.java new file mode 100644 index 000000000..54750cc8b --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/functional/EventContext.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.functional; + +import java.util.function.Consumer; + +import com.dfsek.terra.api.event.events.Event; + + +public interface EventContext { + EventContext then(Consumer action); + + EventContext priority(int priority); + + EventContext failThrough(); + + EventContext global(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/functional/FunctionalEventHandler.java b/common/api/src/main/java/com/dfsek/terra/api/event/functional/FunctionalEventHandler.java new file mode 100644 index 000000000..9ec9c62c9 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/event/functional/FunctionalEventHandler.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.event.functional; + +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.EventHandler; +import com.dfsek.terra.api.event.events.Event; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public interface FunctionalEventHandler extends EventHandler { + EventContext register(BaseAddon addon, Class clazz); + + EventContext register(BaseAddon addon, TypeKey clazz); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/handle/ItemHandle.java b/common/api/src/main/java/com/dfsek/terra/api/handle/ItemHandle.java new file mode 100644 index 000000000..2cc69db77 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/handle/ItemHandle.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.handle; + +import java.util.Set; + +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.item.Enchantment; + + +public interface ItemHandle { + + Item createItem(String data); + + Enchantment getEnchantment(String id); + + Set getEnchantments(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/handle/WorldHandle.java b/common/api/src/main/java/com/dfsek/terra/api/handle/WorldHandle.java new file mode 100644 index 000000000..4f28b254e --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/handle/WorldHandle.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.handle; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.entity.EntityType; + + +/** + * Interface to be implemented for world manipulation. + */ +public interface WorldHandle { + @NotNull + @Contract("_ -> new") + BlockState createBlockState(@NotNull String data); + + @NotNull + @Contract(pure = true) + BlockState air(); + + @NotNull + EntityType getEntity(@NotNull String id); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/inject/Injector.java b/common/api/src/main/java/com/dfsek/terra/api/inject/Injector.java new file mode 100644 index 000000000..50caaf420 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/inject/Injector.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inject; + +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.inject.exception.InjectionException; +import com.dfsek.terra.api.inject.impl.InjectorImpl; + + +/** + * Dynamic dependency injector. + *

+ * Stores an object to inject, and injects it into objects passed to {@link #inject(Object)}. + * + * @param Type of object to inject. + */ +public interface Injector { + static Injector get(T1 value) { + return new InjectorImpl<>(value); + } + + /** + * Add an explicit class as a target. Useful for applications where subclasses may cause issues with DI. + * + * @param target Target class type. + */ + void addExplicitTarget(Class target); + + /** + * Inject the stored object into an object. + *

+ * Injects the stored object into any non-static, non-final fields + * annotated with {@link Inject}, + * with type matching the stored object or any explicit targets + * ({@link #addExplicitTarget(Class)}. + * + * @param object Object to inject into + * + * @throws InjectionException If: + *

    + *
  • Matching field annotated with {@link Inject} is final
  • + *
  • Matching field annotated with {@link Inject} is static
  • + *
  • A reflective access exception occurs
  • + *
+ */ + void inject(Object object) throws InjectionException; +} diff --git a/common/src/main/java/com/dfsek/terra/api/injection/annotations/Inject.java b/common/api/src/main/java/com/dfsek/terra/api/inject/annotations/Inject.java similarity index 56% rename from common/src/main/java/com/dfsek/terra/api/injection/annotations/Inject.java rename to common/api/src/main/java/com/dfsek/terra/api/inject/annotations/Inject.java index b73f05d42..28936aef2 100644 --- a/common/src/main/java/com/dfsek/terra/api/injection/annotations/Inject.java +++ b/common/api/src/main/java/com/dfsek/terra/api/inject/annotations/Inject.java @@ -1,10 +1,18 @@ -package com.dfsek.terra.api.injection.annotations; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inject.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; + /** * Specifies that a field is a target for dependency injection. */ diff --git a/common/api/src/main/java/com/dfsek/terra/api/inject/exception/InjectionException.java b/common/api/src/main/java/com/dfsek/terra/api/inject/exception/InjectionException.java new file mode 100644 index 000000000..4275d7a5a --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/inject/exception/InjectionException.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inject.exception; + +import java.io.Serial; + +import com.dfsek.terra.api.inject.Injector; + + +/** + * Thrown when dynamic dependency injection cannot be completed by an {@link Injector}. + */ +public class InjectionException extends RuntimeException { + @Serial + private static final long serialVersionUID = -6929631447064215387L; + + public InjectionException(String message) { + super(message); + } + + public InjectionException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/injection/Injector.java b/common/api/src/main/java/com/dfsek/terra/api/inject/impl/InjectorImpl.java similarity index 51% rename from common/src/main/java/com/dfsek/terra/api/injection/Injector.java rename to common/api/src/main/java/com/dfsek/terra/api/inject/impl/InjectorImpl.java index c19a680fa..9c17501a5 100644 --- a/common/src/main/java/com/dfsek/terra/api/injection/Injector.java +++ b/common/api/src/main/java/com/dfsek/terra/api/inject/impl/InjectorImpl.java @@ -1,59 +1,44 @@ -package com.dfsek.terra.api.injection; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.injection.exception.InjectionException; -import com.dfsek.terra.api.util.ReflectionUtil; +package com.dfsek.terra.api.inject.impl; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashSet; import java.util.Set; -/** - * Dynamic dependency injector. - *

- * Stores an object to inject, and injects it into objects passed to {@link #inject(Object)}. - * - * @param Type of object to inject. - */ -public class Injector { +import com.dfsek.terra.api.inject.Injector; +import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.inject.exception.InjectionException; +import com.dfsek.terra.api.util.reflection.ReflectionUtil; + + +public class InjectorImpl implements Injector { private final T value; private final Set> targets = new HashSet<>(); - + /** * Instantiate an Injector with a value to inject * * @param value Value to inject */ - public Injector(T value) { + public InjectorImpl(T value) { this.value = value; } - - /** - * Add an explicit class as a target. Useful for applications where subclasses may cause issues with DI. - * - * @param target Target class type. - */ + + + @Override public void addExplicitTarget(Class target) { targets.add(target); } - - /** - * Inject the stored object into an object. - *

- * Injects the stored object into any non-static, non-final fields - * annotated with {@link Inject}, - * with type matching the stored object or any explicit targets - * ({@link #addExplicitTarget(Class)}. - * - * @param object Object to inject into - * @throws InjectionException If: - *

    - *
  • Matching field annotated with {@link Inject} is final
  • - *
  • Matching field annotated with {@link Inject} is static
  • - *
  • A reflective access exception occurs
  • - *
- */ + + + @Override public void inject(Object object) throws InjectionException { for(Field field : ReflectionUtil.getFields(object.getClass())) { Inject inject = field.getAnnotation(Inject.class); diff --git a/common/api/src/main/java/com/dfsek/terra/api/inventory/BlockInventoryHolder.java b/common/api/src/main/java/com/dfsek/terra/api/inventory/BlockInventoryHolder.java new file mode 100644 index 000000000..267a1ffec --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/inventory/BlockInventoryHolder.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inventory; + +import com.dfsek.terra.api.util.vector.Vector3; + + +public interface BlockInventoryHolder extends InventoryHolder { + Vector3 getPosition(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/inventory/Inventory.java b/common/api/src/main/java/com/dfsek/terra/api/inventory/Inventory.java new file mode 100644 index 000000000..8f0888ac7 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/inventory/Inventory.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inventory; + +import com.dfsek.terra.api.Handle; + + +public interface Inventory extends Handle { + void setItem(int slot, ItemStack newStack); + + int getSize(); + + ItemStack getItem(int slot); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/inventory/InventoryHolder.java b/common/api/src/main/java/com/dfsek/terra/api/inventory/InventoryHolder.java new file mode 100644 index 000000000..bf62a1c79 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/inventory/InventoryHolder.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inventory; + +import com.dfsek.terra.api.Handle; + + +public interface InventoryHolder extends Handle { + Inventory getInventory(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/inventory/Item.java b/common/api/src/main/java/com/dfsek/terra/api/inventory/Item.java new file mode 100644 index 000000000..36d27c08d --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/inventory/Item.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inventory; + +import com.dfsek.terra.api.Handle; + + +/** + * An inventory item. + */ +public interface Item extends Handle { + ItemStack newItemStack(int amount); + + double getMaxDurability(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/inventory/ItemStack.java b/common/api/src/main/java/com/dfsek/terra/api/inventory/ItemStack.java new file mode 100644 index 000000000..0edc53c6e --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/inventory/ItemStack.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inventory; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.inventory.item.Damageable; +import com.dfsek.terra.api.inventory.item.ItemMeta; + + +public interface ItemStack extends Handle { + int getAmount(); + + void setAmount(int i); + + Item getType(); + + ItemMeta getItemMeta(); + + void setItemMeta(ItemMeta meta); + + default boolean isDamageable() { + return getItemMeta() instanceof Damageable; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/inventory/item/Damageable.java b/common/api/src/main/java/com/dfsek/terra/api/inventory/item/Damageable.java new file mode 100644 index 000000000..9f950a3c9 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/inventory/item/Damageable.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inventory.item; + +import com.dfsek.terra.api.Handle; + + +public interface Damageable extends Handle { + int getDamage(); + + void setDamage(int damage); + + boolean hasDamage(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/inventory/item/Enchantment.java b/common/api/src/main/java/com/dfsek/terra/api/inventory/item/Enchantment.java new file mode 100644 index 000000000..a836bc22b --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/inventory/item/Enchantment.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inventory.item; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.inventory.ItemStack; + + +public interface Enchantment extends Handle { + boolean canEnchantItem(ItemStack itemStack); + + boolean conflictsWith(Enchantment other); + + String getID(); + + int getMaxLevel(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/inventory/item/ItemMeta.java b/common/api/src/main/java/com/dfsek/terra/api/inventory/item/ItemMeta.java new file mode 100644 index 000000000..6094ce389 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/inventory/item/ItemMeta.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.inventory.item; + +import java.util.Map; + +import com.dfsek.terra.api.Handle; + + +public interface ItemMeta extends Handle { + void addEnchantment(Enchantment enchantment, int level); + + Map getEnchantments(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/noise/NoiseSampler.java b/common/api/src/main/java/com/dfsek/terra/api/noise/NoiseSampler.java new file mode 100644 index 000000000..5e6a5df0b --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/noise/NoiseSampler.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.noise; + + +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector2Int; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.util.vector.Vector3Int; + + +public interface NoiseSampler { + static NoiseSampler zero() { + return new NoiseSampler() { + @Override + public double noise(long seed, double x, double y) { + return 0; + } + + @Override + public double noise(long seed, double x, double y, double z) { + return 0; + } + }; + } + + default double noise(Vector3 vector3, long seed) { + return noise(seed, vector3.getX(), vector3.getY(), vector3.getZ()); + } + + default double noise(Vector3Int vector3, long seed) { + return noise(seed, vector3.getX(), vector3.getY(), vector3.getZ()); + } + + + default double noise(Vector2 vector2, long seed) { + return noise(seed, vector2.getX(), vector2.getZ()); + } + + default double noise(Vector2Int vector2, long seed) { + return noise(seed, vector2.getX(), vector2.getZ()); + } + + double noise(long seed, double x, double y); + + default double noise(long seed, int x, int y) { + return noise(seed, (double) x, y); + } + + double noise(long seed, double x, double y, double z); + + default double noise(long seed, int x, int y, int z) { + return noise(seed, (double) x, y, z); + } +} diff --git a/common/src/main/java/com/dfsek/terra/profiler/Profiler.java b/common/api/src/main/java/com/dfsek/terra/api/profiler/Profiler.java similarity index 58% rename from common/src/main/java/com/dfsek/terra/profiler/Profiler.java rename to common/api/src/main/java/com/dfsek/terra/api/profiler/Profiler.java index 65560ad56..15d610a63 100644 --- a/common/src/main/java/com/dfsek/terra/profiler/Profiler.java +++ b/common/api/src/main/java/com/dfsek/terra/api/profiler/Profiler.java @@ -1,7 +1,15 @@ -package com.dfsek.terra.profiler; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.profiler; import java.util.Map; + public interface Profiler { /** * Push a frame to this profiler. @@ -9,7 +17,7 @@ public interface Profiler { * @param frame ID of frame. */ void push(String frame); - + /** * Pop a frame from this profiler. * @@ -17,40 +25,26 @@ public interface Profiler { * at the top of the profiler stack. */ void pop(String frame); - + /** * Start profiling. */ void start(); - + /** * Stop profiling. */ void stop(); - + + /** + * Clear the profiler data. + */ + void reset(); + /** * Get the profiler data. * * @return Profiler data. */ Map getTimings(); - - /** - * Return a {@link AutoCloseable} implementation that - * may be used in a try-with-resources statement for - * more intuitive profiling, with auto-push/pop. - * - * @param frame ID of frame. - * @return {@link AutoCloseable} implementation for use - * in try-with-resources. - */ - default ProfileFrame profile(String frame) { - push(frame); - return new ProfileFrame(() -> pop(frame)); - } - - /** - * Clear the profiler data. - */ - void reset(); } diff --git a/common/src/main/java/com/dfsek/terra/profiler/Timings.java b/common/api/src/main/java/com/dfsek/terra/api/profiler/Timings.java similarity index 77% rename from common/src/main/java/com/dfsek/terra/profiler/Timings.java rename to common/api/src/main/java/com/dfsek/terra/api/profiler/Timings.java index 3875285b3..199d4943f 100644 --- a/common/src/main/java/com/dfsek/terra/profiler/Timings.java +++ b/common/api/src/main/java/com/dfsek/terra/api/profiler/Timings.java @@ -1,4 +1,11 @@ -package com.dfsek.terra.profiler; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.profiler; import java.util.ArrayList; import java.util.Collections; @@ -8,51 +15,49 @@ import java.util.List; import java.util.Map; import java.util.Set; + public class Timings { private final Map subItems = new HashMap<>(); - + private final List timings = new ArrayList<>(); - + public void addTime(long time) { timings.add(time); } - - public List getTimings() { - return timings; - } - + public double average() { return (double) timings.stream().reduce(0L, Long::sum) / timings.size(); } - + public long max() { return timings.stream().mapToLong(Long::longValue).max().orElse(0L); } - + public long min() { return timings.stream().mapToLong(Long::longValue).min().orElse(0L); } - + public double sum() { return timings.stream().mapToDouble(Long::doubleValue).sum(); } - - public Timings getSubItem(String id) { - return subItems.computeIfAbsent(id, s -> new Timings()); + + @Override + public String toString() { + return toString(1, this, Collections.emptySet()); } - - public String toString(int indent, Timings parent, Set branches) { + + private String toString(int indent, Timings parent, Set branches) { StringBuilder builder = new StringBuilder(); - + builder.append((double) min() / 1000000).append("ms min / ").append(average() / 1000000).append("ms avg / ") - .append((double) max() / 1000000).append("ms max (").append(timings.size()).append(" samples, ") - .append((sum() / parent.sum()) * 100).append("% of parent)"); - + .append((double) max() / 1000000).append("ms max (").append(timings.size()).append(" samples, ") + .append((sum() / parent.sum()) * 100).append("% of parent)"); + List frames = new ArrayList<>(); Set newBranches = new HashSet<>(branches); newBranches.add(indent); subItems.forEach((id, timings) -> frames.add(id + ": " + timings.toString(indent + 1, this, newBranches))); - + for(int i = 0; i < frames.size(); i++) { builder.append('\n'); for(int j = 0; j < indent; j++) { @@ -65,9 +70,12 @@ public class Timings { } return builder.toString(); } - - @Override - public String toString() { - return toString(1, this, Collections.emptySet()); + + public List getTimings() { + return timings; + } + + public Timings getSubItem(String id) { + return subItems.computeIfAbsent(id, s -> new Timings()); } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java b/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java new file mode 100644 index 000000000..3b7f1fa40 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/properties/Context.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.properties; + +import java.util.HashMap; +import java.util.Map; + + +public class Context { + private final Map, Properties> map = new HashMap<>(); + + @SuppressWarnings("unchecked") + public T get(Class clazz) { + return (T) map.computeIfAbsent(clazz, k -> { + throw new IllegalArgumentException("No properties registered for class " + clazz.getCanonicalName()); + }); + } + + public Context put(Properties properties) { + if(map.containsKey(properties.getClass())) throw new IllegalArgumentException( + "Property for class " + properties.getClass().getCanonicalName() + " already registered."); + map.put(properties.getClass(), properties); + return this; + } + + public boolean has(Class test) { + return map.containsKey(test); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/properties/Properties.java b/common/api/src/main/java/com/dfsek/terra/api/properties/Properties.java new file mode 100644 index 000000000..162828357 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/properties/Properties.java @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.properties; + +public interface Properties { +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/properties/PropertyHolder.java b/common/api/src/main/java/com/dfsek/terra/api/properties/PropertyHolder.java new file mode 100644 index 000000000..e48d50bed --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/properties/PropertyHolder.java @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.properties; + +public interface PropertyHolder { + Context getContext(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/properties/annotations/Linked.java b/common/api/src/main/java/com/dfsek/terra/api/properties/annotations/Linked.java new file mode 100644 index 000000000..230ab1841 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/properties/annotations/Linked.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.properties.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.dfsek.terra.api.properties.PropertyHolder; + + +/** + * Specifies that this property holder shares properties + * with the {@link #value()} holder. + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.CLASS) +public @interface Linked { + Class value(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/CheckedRegistry.java b/common/api/src/main/java/com/dfsek/terra/api/registry/CheckedRegistry.java new file mode 100644 index 000000000..dd79c7c4a --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/CheckedRegistry.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.registry; + +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.registry.exception.DuplicateEntryException; +import com.dfsek.terra.api.registry.key.Keyed; +import com.dfsek.terra.api.registry.key.RegistryKey; + + +public interface CheckedRegistry extends Registry { + /** + * Add a value to this registry, checking whether it is present first. + * + * @param identifier Identifier to assign value. + * @param value Value to register. + * + * @throws DuplicateEntryException If an entry with the same identifier is already present. + */ + void register(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException; + + @SuppressWarnings("unchecked") + default void register(@NotNull Keyed value) throws DuplicateEntryException { + register(value.getRegistryKey(), (T) value); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/OpenRegistry.java b/common/api/src/main/java/com/dfsek/terra/api/registry/OpenRegistry.java new file mode 100644 index 000000000..dcedae900 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/OpenRegistry.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.registry; + +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.registry.exception.DuplicateEntryException; +import com.dfsek.terra.api.registry.key.Keyed; +import com.dfsek.terra.api.registry.key.RegistryKey; + + +public interface OpenRegistry extends Registry { + /** + * Add a value to this registry. + * + * @param identifier Identifier to assign value. + * @param value Value to register. + */ + boolean register(@NotNull RegistryKey identifier, @NotNull T value); + + @SuppressWarnings("unchecked") + default boolean register(@NotNull Keyed value) { + return register(value.getRegistryKey(), (T) value); + } + + /** + * Add a value to this registry, checking whether it is present first. + * + * @param identifier Identifier to assign value. + * @param value Value to register. + * + * @throws DuplicateEntryException If an entry with the same identifier is already present. + */ + void registerChecked(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException; + + @SuppressWarnings("unchecked") + default void registerChecked(@NotNull Keyed value) { + registerChecked(value.getRegistryKey(), (T) value); + } + + /** + * Clears all entries from the registry. + */ + void clear(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/Registry.java b/common/api/src/main/java/com/dfsek/terra/api/registry/Registry.java new file mode 100644 index 000000000..7ebde15d2 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/Registry.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.registry; + +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; + +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public interface Registry extends TypeLoader { + /** + * Get a value from the registry. + * + * @param key Identifier of value. + * + * @return Value matching the identifier, {@code null} if no value is present. + */ + @Contract(pure = true) + Optional get(@NotNull RegistryKey key); + + /** + * Check if the registry contains a value. + * + * @param key Identifier of value. + * + * @return Whether the registry contains the value. + */ + @Contract(pure = true) + boolean contains(@NotNull RegistryKey key); + + /** + * Perform the given action for every value in the registry. + * + * @param consumer Action to perform on value. + */ + void forEach(@NotNull Consumer consumer); + + /** + * Perform an action for every key-value pair in the registry. + * + * @param consumer Action to perform on pair. + */ + void forEach(@NotNull BiConsumer consumer); + + /** + * Get the entries of this registry as a {@link Set}. + * + * @return Set containing all entries. + */ + @NotNull + @Contract(pure = true) + Collection entries(); + + /** + * Get all the keys in this registry. + * + * @return Keys in registry + */ + @NotNull + @Contract(pure = true) + Set keys(); + + TypeKey getType(); + + default Class getRawType() { + return getType().getRawType(); + } + + default Optional getByID(String id) { + return getByID(id, map -> { + if(map.isEmpty()) return Optional.empty(); + if(map.size() == 1) { + return map.values().stream().findFirst(); // only one value. + } + throw new IllegalArgumentException("ID \"" + id + "\" is ambiguous; matches: " + map + .keySet() + .stream() + .map(RegistryKey::toString) + .reduce("", (a, b) -> a + "\n - " + b)); + }); + } + + default Collection getAllWithID(String id) { + return getMatches(id).values(); + } + + Map getMatches(String id); + + default Optional getByID(String attempt, Function, Optional> reduction) { + if(attempt.contains(":")) { + return get(RegistryKey.parse(attempt)); + } + return reduction.apply(getMatches(attempt)); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/exception/DuplicateEntryException.java b/common/api/src/main/java/com/dfsek/terra/api/registry/exception/DuplicateEntryException.java new file mode 100644 index 000000000..123ec2da3 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/exception/DuplicateEntryException.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.registry.exception; + +import java.io.Serial; + + +/** + * Thrown when a duplicate entry is found in a registry. + */ +public class DuplicateEntryException extends RuntimeException { + @Serial + private static final long serialVersionUID = -7199021672428288780L; + + public DuplicateEntryException(String message) { + super(message); + } + + public DuplicateEntryException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/exception/NoSuchEntryException.java b/common/api/src/main/java/com/dfsek/terra/api/registry/exception/NoSuchEntryException.java new file mode 100644 index 000000000..ce39576c3 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/exception/NoSuchEntryException.java @@ -0,0 +1,8 @@ +package com.dfsek.terra.api.registry.exception; + +public class NoSuchEntryException extends RuntimeException { + public NoSuchEntryException(String message) { + super(message); + } + +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/key/Keyed.java b/common/api/src/main/java/com/dfsek/terra/api/registry/key/Keyed.java new file mode 100644 index 000000000..957226f52 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/key/Keyed.java @@ -0,0 +1,16 @@ +package com.dfsek.terra.api.registry.key; + +@SuppressWarnings("unused") +public interface Keyed> extends Namespaced, StringIdentifiable { + RegistryKey getRegistryKey(); + + @Override + default String getNamespace() { + return getRegistryKey().getNamespace(); + } + + @Override + default String getID() { + return getRegistryKey().getID(); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/key/Namespaced.java b/common/api/src/main/java/com/dfsek/terra/api/registry/key/Namespaced.java new file mode 100644 index 000000000..0c4e33c22 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/key/Namespaced.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.api.registry.key; + +public interface Namespaced { + String getNamespace(); + + default RegistryKey key(String id) { + return RegistryKey.of(getNamespace(), id); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/key/RegistryKey.java b/common/api/src/main/java/com/dfsek/terra/api/registry/key/RegistryKey.java new file mode 100644 index 000000000..40398b81a --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/key/RegistryKey.java @@ -0,0 +1,70 @@ +package com.dfsek.terra.api.registry.key; + +import java.util.Objects; +import java.util.regex.Pattern; + + +public final class RegistryKey implements StringIdentifiable, Namespaced { + private static final Pattern ID_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]*$"); + private final String namespace; + private final String id; + + private RegistryKey(String namespace, String id) { + if(!ID_PATTERN.matcher(namespace).matches()) { + throw new IllegalArgumentException( + "Namespace must only contain alphanumeric characters, hyphens, and underscores. \"" + namespace + + "\" is not a valid namespace."); + } + + if(!ID_PATTERN.matcher(id).matches()) { + throw new IllegalArgumentException( + "ID must only contain alphanumeric characters, hyphens, and underscores. \"" + id + + "\" is not a valid ID."); + } + + this.namespace = namespace; + this.id = id; + } + + public static RegistryKey parse(String key) { + if(key.chars().filter(c -> c == ':').count() != 1) { + throw new IllegalArgumentException("Malformed RegistryKey: " + key); + } + String namespace = key.substring(0, key.indexOf(":")); + String id = key.substring(key.indexOf(":") + 1); + + return new RegistryKey(namespace, id); + } + + public static RegistryKey of(String namespace, String id) { + return new RegistryKey(namespace, id); + } + + @Override + public String getNamespace() { + return namespace; + } + + @Override + public String getID() { + return id; + } + + @Override + public int hashCode() { + return Objects.hash(namespace, id); + } + + @Override + public boolean equals(Object obj) { + if(obj instanceof RegistryKey that) { + return this.id.equals(that.id) && this.namespace.equals(that.namespace); + } + return false; + } + + @Override + public String toString() { + return namespace + ":" + id; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/key/StringIdentifiable.java b/common/api/src/main/java/com/dfsek/terra/api/registry/key/StringIdentifiable.java new file mode 100644 index 000000000..fe2a5b6db --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/key/StringIdentifiable.java @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.registry.key; + +public interface StringIdentifiable { + String getID(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/meta/CheckedRegistryHolder.java b/common/api/src/main/java/com/dfsek/terra/api/registry/meta/CheckedRegistryHolder.java new file mode 100644 index 000000000..57d35e043 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/meta/CheckedRegistryHolder.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.api.registry.meta; + +import java.lang.reflect.Type; + +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public interface CheckedRegistryHolder extends RegistryHolder { + default CheckedRegistry getCheckedRegistry(Class clazz) throws IllegalStateException { + return getCheckedRegistry((Type) clazz); + } + + default CheckedRegistry getCheckedRegistry(TypeKey type) throws IllegalStateException { + return getCheckedRegistry(type.getType()); + } + + CheckedRegistry getCheckedRegistry(Type type); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/meta/RegistryHolder.java b/common/api/src/main/java/com/dfsek/terra/api/registry/meta/RegistryHolder.java new file mode 100644 index 000000000..a42054538 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/meta/RegistryHolder.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.registry.meta; + +import java.lang.reflect.Type; + +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public interface RegistryHolder { + default Registry getRegistry(Class clazz) { + return getRegistry((Type) clazz); + } + + default Registry getRegistry(TypeKey type) { + return getRegistry(type.getType()); + } + + Registry getRegistry(Type type); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/meta/RegistryProvider.java b/common/api/src/main/java/com/dfsek/terra/api/registry/meta/RegistryProvider.java new file mode 100644 index 000000000..b3acdfd20 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/meta/RegistryProvider.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.api.registry.meta; + +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public interface RegistryProvider { + default CheckedRegistry getOrCreateRegistry(Class clazz) { + return getOrCreateRegistry(TypeKey.of(clazz)); + } + + CheckedRegistry getOrCreateRegistry(TypeKey type); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/structure/LootTable.java b/common/api/src/main/java/com/dfsek/terra/api/structure/LootTable.java new file mode 100644 index 000000000..162247c82 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/structure/LootTable.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.structure; + +import org.jetbrains.annotations.ApiStatus.Experimental; + +import java.util.List; +import java.util.Random; + +import com.dfsek.terra.api.inventory.Inventory; +import com.dfsek.terra.api.inventory.ItemStack; + + +@Experimental +public interface LootTable { + /** + * Fills an Inventory with loot. + * + * @param i The Inventory to fill. + * @param r The The Random instance to use. + */ + void fillInventory(Inventory i, Random r); + + /** + * Fetches a list of ItemStacks from the loot table using the given Random instance. + * + * @param r The Random instance to use. + * + * @return List<ItemStack> - The list of loot fetched. + */ + List getLoot(Random r); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/structure/Structure.java b/common/api/src/main/java/com/dfsek/terra/api/structure/Structure.java new file mode 100644 index 000000000..479c77e38 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/structure/Structure.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.structure; + +import java.util.Random; + +import com.dfsek.terra.api.util.Rotation; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.WritableWorld; + + +public interface Structure { + boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/structure/StructureSpawn.java b/common/api/src/main/java/com/dfsek/terra/api/structure/StructureSpawn.java new file mode 100644 index 000000000..a06496817 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/structure/StructureSpawn.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.structure; + +import org.jetbrains.annotations.ApiStatus.Experimental; + +import com.dfsek.terra.api.util.vector.Vector3; + + +@Experimental +public interface StructureSpawn { + /** + * Get nearest spawn point + * + * @param x X coordinate + * @param z Z coordinate + * @param seed Seed for RNG + * + * @return Vector representing nearest spawnpoint + */ + Vector3 getNearestSpawn(int x, int z, long seed); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/structure/configured/ConfiguredStructure.java b/common/api/src/main/java/com/dfsek/terra/api/structure/configured/ConfiguredStructure.java new file mode 100644 index 000000000..452d0a902 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/structure/configured/ConfiguredStructure.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.structure.configured; + +import org.jetbrains.annotations.ApiStatus.Experimental; + +import com.dfsek.terra.api.registry.key.StringIdentifiable; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.structure.StructureSpawn; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +@Experimental +public interface ConfiguredStructure extends StringIdentifiable { + ProbabilityCollection getStructure(); + + Range getSpawnStart(); + + StructureSpawn getSpawn(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/structure/feature/BinaryColumn.java b/common/api/src/main/java/com/dfsek/terra/api/structure/feature/BinaryColumn.java new file mode 100644 index 000000000..bb985e83a --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/structure/feature/BinaryColumn.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.structure.feature; + +import java.util.function.BooleanSupplier; +import java.util.function.IntConsumer; + +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.util.function.IntToBooleanFunction; +import com.dfsek.terra.api.util.generic.Lazy; + + +/** + * A column of binary data + */ +public class BinaryColumn { + private static final BinaryColumn NULL = new BinaryColumn(0, 1, y -> false); + private final IntToBooleanFunction data; + private final int minY; + private final int maxY; + private final Lazy results; + + /** + * Constructs a new {@link BinaryColumn} with all values initiated to {@code false} + * + * @param minY Minimum Y value + * @param maxY Maximum Y value + */ + public BinaryColumn(int minY, int maxY, IntToBooleanFunction data) { + this.minY = minY; + this.maxY = maxY; + this.results = Lazy.lazy(() -> { + boolean[] res = new boolean[maxY - minY]; + for(int y = minY; y < maxY; y++) { + res[y - minY] = get(y); + } + return res; + }); + if(maxY <= minY) throw new IllegalArgumentException("Max y must be greater than min y"); + this.data = data; + } + + public BinaryColumn(int minY, int maxY, boolean[] data) { + this.minY = minY; + this.maxY = maxY; + this.results = Lazy.lazy(() -> data); + if(maxY <= minY) throw new IllegalArgumentException("Max y must be greater than min y"); + this.data = y -> data[y - minY]; + } + + public BinaryColumn(Range y, IntToBooleanFunction data) { + this(y.getMin(), y.getMax(), data); + } + + public static BinaryColumn getNull() { + return NULL; + } + + /** + * Get the value at a height. + * + * @param y Height of entry to get. + * + * @return Whether height has been set. + */ + public boolean get(int y) { + return data.apply(y); + } + + + public boolean contains(int y) { + return y >= minY && y < maxY; + } + + /** + * Perform an action for all heights which have been set. + * + * @param consumer Action to perform + */ + public void forEach(IntConsumer consumer) { + boolean[] results = this.results.value(); + for(int y = minY; y < maxY; y++) { + if(results[y - minY]) { + consumer.accept(y); + } + } + } + + /** + * Return a {@link BinaryColumn} of equal height with a boolean AND operation applied to each height. + * + * @param that Other binary column, must match this column's height. + * + * @return Merged column. + * + * @throws IllegalArgumentException if column heights do not match + */ + public BinaryColumn and(BinaryColumn that) { + int bigMinY = Math.max(this.minY, that.minY); // narrow new column, as areas outside will always be false. + int smallMaxY = Math.min(this.maxY, that.maxY); + + if(bigMinY >= smallMaxY) return getNull(); + + return new BinaryColumn(bigMinY, smallMaxY, y -> this.get(y) && that.get(y)); + } + + /** + * Return a {@link BinaryColumn} of equal height with a boolean OR operation applied to each height. + * + * @param that Other binary column, must match this column's height. + * + * @return Merged column. + * + * @throws IllegalArgumentException if column heights do not match + */ + public BinaryColumn or(BinaryColumn that) { + return or(that, (a, b) -> a.getAsBoolean() || b.getAsBoolean()); + } + + public BinaryColumn xor(BinaryColumn that) { + return or(that, (a, b) -> a.getAsBoolean() ^ b.getAsBoolean()); + } + + private BinaryColumn or(BinaryColumn that, BooleanBinaryOperator operator) { + int smallMinY = Math.min(this.minY, that.minY); + int bigMaxY = Math.max(this.maxY, that.maxY); + + return new BinaryColumn(smallMinY, bigMaxY, y -> operator.apply(() -> this.get(y), () -> that.get(y))); + } + + private interface BooleanBinaryOperator { + boolean apply(BooleanSupplier a, BooleanSupplier b); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/structure/feature/Distributor.java b/common/api/src/main/java/com/dfsek/terra/api/structure/feature/Distributor.java new file mode 100644 index 000000000..f037ed489 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/structure/feature/Distributor.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.structure.feature; + +public interface Distributor { + static Distributor yes() { + return (x, z, seed) -> true; + } + + static Distributor no() { + return (x, z, seed) -> false; + } + + boolean matches(int x, int z, long seed); + + default Distributor and(Distributor other) { + return (x, z, seed) -> this.matches(x, z, seed) && other.matches(x, z, seed); + } + + default Distributor or(Distributor other) { + return (x, z, seed) -> this.matches(x, z, seed) || other.matches(x, z, seed); + } + + default Distributor xor(Distributor other) { + return (x, z, seed) -> this.matches(x, z, seed) ^ other.matches(x, z, seed); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/structure/feature/Feature.java b/common/api/src/main/java/com/dfsek/terra/api/structure/feature/Feature.java new file mode 100644 index 000000000..1cbc6f8ad --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/structure/feature/Feature.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.structure.feature; + +import com.dfsek.terra.api.registry.key.StringIdentifiable; +import com.dfsek.terra.api.structure.Structure; +import com.dfsek.terra.api.world.WritableWorld; + + +public interface Feature extends StringIdentifiable { + Structure getStructure(WritableWorld world, int x, int y, int z); + + Distributor getDistributor(); + + Locator getLocator(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/structure/feature/Locator.java b/common/api/src/main/java/com/dfsek/terra/api/structure/feature/Locator.java new file mode 100644 index 000000000..a5d4e6ca1 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/structure/feature/Locator.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.structure.feature; + +import com.dfsek.terra.api.world.chunk.generation.util.Column; + + +public interface Locator { + default Locator and(Locator that) { + return column -> this.getSuitableCoordinates(column).and(that.getSuitableCoordinates(column)); + } + + default Locator or(Locator that) { + return column -> this.getSuitableCoordinates(column).or(that.getSuitableCoordinates(column)); + } + + default Locator xor(Locator that) { + return column -> this.getSuitableCoordinates(column).xor(that.getSuitableCoordinates(column)); + } + + BinaryColumn getSuitableCoordinates(Column column); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/tectonic/ConfigLoadingDelegate.java b/common/api/src/main/java/com/dfsek/terra/api/tectonic/ConfigLoadingDelegate.java new file mode 100644 index 000000000..e0969eba3 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/tectonic/ConfigLoadingDelegate.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.tectonic; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.loader.type.TypeLoader; + +import java.lang.reflect.Type; +import java.util.function.Supplier; + + +public interface ConfigLoadingDelegate { + ConfigLoadingDelegate applyLoader(Type type, TypeLoader loader); + + default ConfigLoadingDelegate applyLoader(Class type, TypeLoader loader) { + return applyLoader((Type) type, loader); + } + + ConfigLoadingDelegate applyLoader(Type type, Supplier> loader); + + default ConfigLoadingDelegate applyLoader(Class type, Supplier> loader) { + return applyLoader((Type) type, loader); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/tectonic/LoaderRegistrar.java b/common/api/src/main/java/com/dfsek/terra/api/tectonic/LoaderRegistrar.java new file mode 100644 index 000000000..b63c4f101 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/tectonic/LoaderRegistrar.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.tectonic; + +import com.dfsek.tectonic.api.TypeRegistry; + + +public interface LoaderRegistrar { + void register(TypeRegistry registry); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/tectonic/ShortcutLoader.java b/common/api/src/main/java/com/dfsek/terra/api/tectonic/ShortcutLoader.java new file mode 100644 index 000000000..e61585f2a --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/tectonic/ShortcutLoader.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.api.tectonic; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.loader.ConfigLoader; + + +public interface ShortcutLoader { + T load(ConfigLoader configLoader, String input, DepthTracker tracker); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/transform/Transform.java b/common/api/src/main/java/com/dfsek/terra/api/transform/Transform.java new file mode 100644 index 000000000..014747f0f --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/transform/Transform.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.transform; + +import com.dfsek.terra.api.transform.exception.TransformException; + + +/** + * Interface to transform data from one type to another. + */ +@FunctionalInterface +public interface Transform { + T transform(F input) throws TransformException; +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/transform/Transformer.java b/common/api/src/main/java/com/dfsek/terra/api/transform/Transformer.java new file mode 100644 index 000000000..8ca8a904a --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/transform/Transformer.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.transform; + +public interface Transformer { + /** + * Translate data from {@code from} type to {@code to} type. + * + * @param from Data to translate + * + * @return Result + */ + T translate(F from); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/transform/Validator.java b/common/api/src/main/java/com/dfsek/terra/api/transform/Validator.java new file mode 100644 index 000000000..9a9aecbdd --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/transform/Validator.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.transform; + + +import java.util.Objects; + +import com.dfsek.terra.api.transform.exception.TransformException; + + +public interface Validator { + static Validator notNull() { + return Objects::nonNull; + } + + boolean validate(T value) throws TransformException; +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/transform/exception/AttemptsFailedException.java b/common/api/src/main/java/com/dfsek/terra/api/transform/exception/AttemptsFailedException.java new file mode 100644 index 000000000..8cc6bab87 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/transform/exception/AttemptsFailedException.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.transform.exception; + + +import java.io.Serial; +import java.util.ArrayList; +import java.util.List; + + +/** + * Thrown when all transformation attempts fail + */ +public class AttemptsFailedException extends RuntimeException { + @Serial + private static final long serialVersionUID = -1160459550006067137L; + private final List causes; + + public AttemptsFailedException(String message, List causes) { + super(message); + this.causes = causes; + } + + public List getCauses() { + return new ArrayList<>(causes); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/TransformException.java b/common/api/src/main/java/com/dfsek/terra/api/transform/exception/TransformException.java similarity index 59% rename from common/src/main/java/com/dfsek/terra/api/transform/TransformException.java rename to common/api/src/main/java/com/dfsek/terra/api/transform/exception/TransformException.java index 048c7d4da..ff80b6642 100644 --- a/common/src/main/java/com/dfsek/terra/api/transform/TransformException.java +++ b/common/api/src/main/java/com/dfsek/terra/api/transform/exception/TransformException.java @@ -1,20 +1,31 @@ -package com.dfsek.terra.api.transform; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.transform.exception; + +import java.io.Serial; + public class TransformException extends Exception { + @Serial private static final long serialVersionUID = -6661338369581162084L; - + public TransformException() { super(); } - + public TransformException(String message) { super(message); } - + public TransformException(String message, Throwable cause) { super(message, cause); } - + public TransformException(Throwable cause) { super(cause); } diff --git a/common/src/main/java/com/dfsek/terra/api/math/Range.java b/common/api/src/main/java/com/dfsek/terra/api/util/ConstantRange.java similarity index 64% rename from common/src/main/java/com/dfsek/terra/api/math/Range.java rename to common/api/src/main/java/com/dfsek/terra/api/util/ConstantRange.java index ce8ae477d..5849d09a6 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/Range.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/ConstantRange.java @@ -1,4 +1,11 @@ -package com.dfsek.terra.api.math; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util; import net.jafama.FastMath; import org.jetbrains.annotations.NotNull; @@ -6,113 +13,127 @@ import org.jetbrains.annotations.NotNull; import java.util.Iterator; import java.util.Random; -public class Range implements Iterable { + +public class ConstantRange implements Range { private int min; private int max; - - public Range(int min, int max) { - if(min > max) throw new IllegalArgumentException("Minimum must not be grater than maximum!"); + + public ConstantRange(int min, int max) { + if(min >= max) throw new IllegalArgumentException("Minimum must not be greater than or equal to maximum!"); this.max = max; this.min = min; } - - public boolean isInRange(int test) { - return test >= min && test < max; - } - - public int getMax() { - return max; - } - - public Range setMax(int max) { - this.max = max; - return this; - } - - public int getMin() { - return min; - } - - public Range setMin(int min) { - this.min = min; - return this; - } - - public int getRange() { - return max - min; - } - + + @Override public Range multiply(int mult) { min *= mult; max *= mult; return this; } - + + @Override public Range reflect(int pt) { - return new Range(2 * pt - this.getMax(), 2 * pt - this.getMin()); + return new ConstantRange(2 * pt - this.getMax(), 2 * pt - this.getMin()); } - + + @Override public int get(Random r) { - return r.nextInt((max - min) + 1) + min; + return r.nextInt(min, max); } - - public Range intersects(com.dfsek.terra.api.math.Range other) { + + @Override + public Range intersects(Range other) { try { - return new Range(FastMath.max(this.getMin(), other.getMin()), FastMath.min(this.getMax(), other.getMax())); + return new ConstantRange(FastMath.max(this.getMin(), other.getMin()), FastMath.min(this.getMax(), other.getMax())); } catch(IllegalArgumentException e) { return null; } } - + + @Override public Range add(int add) { this.min += add; this.max += add; return this; } - + + @Override public Range sub(int sub) { this.min -= sub; this.max -= sub; return this; } - - @Override - public String toString() { - return "Min: " + getMin() + ", Max:" + getMax(); - } - - @Override - public int hashCode() { - return min * 31 + max; - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof com.dfsek.terra.api.math.Range)) return false; - Range other = (com.dfsek.terra.api.math.Range) obj; - return other.getMin() == this.getMin() && other.getMax() == this.getMax(); - } - + @NotNull @Override public Iterator iterator() { return new RangeIterator(this); } - + + @Override + public boolean isInRange(int test) { + return test >= min && test < max; + } + + @Override + public int getMax() { + return max; + } + + @Override + public Range setMax(int max) { + this.max = max; + return this; + } + + @Override + public int getMin() { + return min; + } + + @Override + public Range setMin(int min) { + this.min = min; + return this; + } + + @Override + public int getRange() { + return max - min; + } + + @Override + public int hashCode() { + return min * 31 + max; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof ConstantRange)) return false; + Range other = (Range) obj; + return other.getMin() == this.getMin() && other.getMax() == this.getMax(); + } + + @Override + public String toString() { + return "Min: " + getMin() + ", Max:" + getMax(); + } + + private static class RangeIterator implements Iterator { private final Range m; private Integer current; - + public RangeIterator(Range m) { this.m = m; current = m.getMin(); } - + @Override public boolean hasNext() { return current < m.getMax(); } - + @Override public Integer next() { current++; diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/GeometryUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/GeometryUtil.java new file mode 100644 index 000000000..6bb21b3df --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/GeometryUtil.java @@ -0,0 +1,34 @@ +package com.dfsek.terra.api.util; + +import java.util.function.Consumer; + +import com.dfsek.terra.api.util.vector.Vector3Int; + + +public final class GeometryUtil { + private GeometryUtil() { + + } + + public static void sphere(Vector3Int origin, int radius, Consumer action) { + for(int x = -radius; x <= radius; x++) { + for(int y = -radius; y <= radius; y++) { + for(int z = -radius; z <= radius; z++) { + if(x * x + y * y + z * z <= radius * radius) { + action.accept(Vector3Int.of(origin, x, y, z)); + } + } + } + } + } + + public static void cube(Vector3Int origin, int radius, Consumer action) { + for(int x = -radius; x <= radius; x++) { + for(int y = -radius; y <= radius; y++) { + for(int z = -radius; z <= radius; z++) { + action.accept(Vector3Int.of(origin, x, y, z)); + } + } + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java new file mode 100644 index 000000000..e24de0e03 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/MathUtil.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util; + +import net.jafama.FastMath; + +import java.util.List; + + +/** + * Utility class for mathematical functions. + */ +public final class MathUtil { + /** + * Epsilon for fuzzy floating point comparisons. + */ + public static final double EPSILON = 1.0E-5; + + /** + * Gets the standard deviation of an array of doubles. + * + * @param numArray The array of numbers to calculate the standard deviation of. + * + * @return double - The standard deviation. + */ + public static double standardDeviation(List numArray) { + double sum = 0.0, standardDeviation = 0.0; + int length = numArray.size(); + + for(Number num : numArray) { + sum += num.doubleValue(); + } + + double mean = sum / length; + + for(Number num : numArray) { + standardDeviation += FastMath.pow2(num.doubleValue() - mean); + } + + return FastMath.sqrt(standardDeviation / length); + } + + public static long hashToLong(String s) { + if(s == null) { + return 0; + } + long hash = 0; + for(char c : s.toCharArray()) { + hash = 31L * hash + c; + } + return hash; + } + + /** + * Compare 2 floating-point values with epsilon to account for rounding errors + * + * @param a Value 1 + * @param b Value 2 + * + * @return Whether these values are equal + */ + public static boolean equals(double a, double b) { + return a == b || FastMath.abs(a - b) < EPSILON; + } + + public static int normalizeIndex(double val, int size) { + return FastMath.max(FastMath.min(FastMath.floorToInt(((val + 1D) / 2D) * size), size - 1), 0); + } + + public static long squash(int first, int last) { + return (((long) first) << 32) | (last & 0xffffffffL); + } + + /** + * Clamp value to range of [-1, 1] + * + * @param in Value to clamp + * + * @return Clamped value + */ + public static double clamp(double in) { + return FastMath.min(FastMath.max(in, -1), 1); + } + + /** + * Compute the value in a normally distributed data set that has probability p. + * + * @param p Probability of value + * @param mu Mean of data + * @param sigma Standard deviation of data + * + * @return Value corresponding to input probability + */ + public static double normalInverse(double p, double mu, double sigma) { + if(p < 0 || p > 1) + throw new IllegalArgumentException("Probability must be in range [0, 1]"); + if(sigma < 0) + throw new IllegalArgumentException("Standard deviation must be positive."); + if(p == 0) + return Double.NEGATIVE_INFINITY; + if(p == 1) + return Double.POSITIVE_INFINITY; + if(sigma == 0) + return mu; + double q, r, val; + + q = p - 0.5; + + if(FastMath.abs(q) <= .425) { + r = .180625 - q * q; + val = + q * (((((((r * 2509.0809287301226727 + + 33430.575583588128105) * r + 67265.770927008700853) * r + + 45921.953931549871457) * r + 13731.693765509461125) * r + + 1971.5909503065514427) * r + 133.14166789178437745) * r + + 3.387132872796366608) + / (((((((r * 5226.495278852854561 + + 28729.085735721942674) * r + 39307.89580009271061) * r + + 21213.794301586595867) * r + 5394.1960214247511077) * r + + 687.1870074920579083) * r + 42.313330701600911252) * r + 1); + } else { + if(q > 0) { + r = 1 - p; + } else { + r = p; + } + + r = FastMath.sqrt(-FastMath.log(r)); + + if(r <= 5) { + r -= 1.6; + val = (((((((r * 7.7454501427834140764e-4 + + .0227238449892691845833) * r + .24178072517745061177) * + r + 1.27045825245236838258) * r + + 3.64784832476320460504) * r + 5.7694972214606914055) * + r + 4.6303378461565452959) * r + + 1.42343711074968357734) + / (((((((r * + 1.05075007164441684324e-9 + 5.475938084995344946e-4) * + r + .0151986665636164571966) * r + + .14810397642748007459) * r + .68976733498510000455) * + r + 1.6763848301838038494) * r + + 2.05319162663775882187) * r + 1); + } else { + r -= 5; + val = (((((((r * 2.01033439929228813265e-7 + + 2.71155556874348757815e-5) * r + + .0012426609473880784386) * r + .026532189526576123093) * + r + .29656057182850489123) * r + + 1.7848265399172913358) * r + 5.4637849111641143699) * + r + 6.6579046435011037772) + / (((((((r * + 2.04426310338993978564e-15 + 1.4215117583164458887e-7) * + r + 1.8463183175100546818e-5) * r + + 7.868691311456132591e-4) * r + .0148753612908506148525) + * r + .13692988092273580531) * r + + .59983220655588793769) * r + 1); + } + + if(q < 0.0) { + val = -val; + } + } + + return mu + sigma * val; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/PopulationUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/PopulationUtil.java new file mode 100644 index 000000000..d8949a0c2 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/PopulationUtil.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util; + +import java.util.Random; + +import com.dfsek.terra.api.world.chunk.Chunk; + + +public final class PopulationUtil { + public static Random getRandom(Chunk c) { + return getRandom(c, 0); + } + + public static Random getRandom(Chunk c, long salt) { + return new Random(getCarverChunkSeed(c.getX(), c.getZ(), c.getWorld().getSeed() + salt)); + } + + /** + * Gets the carver seed for a chunk. + * + * @param chunkX Chunk's X coordinate + * @param chunkZ Chunk's Z coordinate + * @param seed World seed + * + * @return long - The carver seed. + */ + public static long getCarverChunkSeed(int chunkX, int chunkZ, long seed) { + Random r = new Random(seed); + return chunkX * r.nextLong() ^ chunkZ * r.nextLong() ^ seed; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Range.java b/common/api/src/main/java/com/dfsek/terra/api/util/Range.java new file mode 100644 index 000000000..9aa57fde3 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Range.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util; + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.Random; + + +public interface Range extends Iterable { + Range multiply(int mult); + + Range reflect(int pt); + + int get(Random r); + + Range intersects(Range other); + + Range add(int add); + + Range sub(int sub); + + @NotNull + @Override + Iterator iterator(); + + boolean isInRange(int test); + + int getMax(); + + Range setMax(int max); + + int getMin(); + + Range setMin(int min); + + int getRange(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/Rotation.java b/common/api/src/main/java/com/dfsek/terra/api/util/Rotation.java new file mode 100644 index 000000000..4d43b1732 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/Rotation.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util; + +import net.jafama.FastMath; + + +public enum Rotation { + + CW_90(90), + CW_180(180), + CCW_90(270), + NONE(0); + private final int degrees; + + Rotation(int degrees) { + this.degrees = degrees; + } + + public static Rotation fromDegrees(int deg) { + return switch(FastMath.floorMod(deg, 360)) { + case 0 -> Rotation.NONE; + case 90 -> Rotation.CW_90; + case 180 -> Rotation.CW_180; + case 270 -> Rotation.CCW_90; + default -> throw new IllegalArgumentException(); + }; + } + + public Rotation inverse() { + return switch(this) { + case NONE -> NONE; + case CCW_90 -> CW_90; + case CW_90 -> CCW_90; + case CW_180 -> CW_180; + }; + } + + public Rotation rotate(Rotation rotation) { + return fromDegrees(this.getDegrees() + rotation.getDegrees()); + } + + public int getDegrees() { + return degrees; + } + + public enum Axis { + X, + Y, + Z + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/RotationUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/RotationUtil.java new file mode 100644 index 000000000..6f9fb8048 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/RotationUtil.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util; + +import com.dfsek.terra.api.util.vector.Vector2; +import com.dfsek.terra.api.util.vector.Vector2.Mutable; + + +public final class RotationUtil { + /** + * Rotate and mirror a coordinate pair. + * + * @param orig Vector to rotate. + * @param r Rotation + * + * @return Rotated vector + */ + public static Vector2 rotateVector(Vector2 orig, Rotation r) { + Mutable copy = orig.mutable(); + switch(r) { + case CW_90 -> copy.setX(orig.getZ()).setZ(-orig.getX()); + case CCW_90 -> copy.setX(-orig.getZ()).setZ(orig.getX()); + case CW_180 -> copy.multiply(-1); + } + return copy.immutable(); + } + + +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/StringUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/StringUtil.java new file mode 100644 index 000000000..ae9bd3ff0 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/StringUtil.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util; + +import java.io.File; + + +public class StringUtil { + public static String fileName(String path) { + if(path.contains(File.separator)) { + return path.substring(path.lastIndexOf(File.separatorChar) + 1, path.lastIndexOf('.')); + } else if(path.contains("/")) { + return path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf('.')); + } else if(path.contains(".")) { + return path.substring(0, path.lastIndexOf('.')); + } else { + return path; + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/collection/MaterialSet.java b/common/api/src/main/java/com/dfsek/terra/api/util/collection/MaterialSet.java new file mode 100644 index 000000000..25cf98eb1 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/collection/MaterialSet.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util.collection; + +import java.io.Serial; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; + + +public class MaterialSet extends HashSet { + @Serial + private static final long serialVersionUID = 3056512763631017301L; + + public static MaterialSet singleton(BlockType material) { + return new Singleton(material); + } + + public static MaterialSet get(BlockType... materials) { + MaterialSet set = new MaterialSet(); + set.addAll(Arrays.asList(materials)); + return set; + } + + public static MaterialSet get(BlockState... materials) { + MaterialSet set = new MaterialSet(); + Arrays.stream(materials).forEach(set::add); + return set; + } + + public static MaterialSet empty() { + return new MaterialSet(); + } + + private void add(BlockState data) { + add(data.getBlockType()); + } + + private static final class Singleton extends MaterialSet { + private final BlockType element; + + Singleton(BlockType e) { + element = e; + } + + public Iterator iterator() { + return new Iterator<>() { + private boolean hasNext = true; + + public boolean hasNext() { + return hasNext; + } + + public BlockType next() { + if(hasNext) { + hasNext = false; + return element; + } + throw new NoSuchElementException(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public void forEachRemaining(Consumer action) { + Objects.requireNonNull(action); + if(hasNext) { + hasNext = false; + action.accept(element); + } + } + }; + } + + public int size() { + return 1; + } + + public boolean contains(Object o) { + return Objects.equals(o, element); + } + + // Override default methods for Collection + @Override + public void forEach(Consumer action) { + action.accept(element); + } + + @Override + public Spliterator spliterator() { + return new Spliterator<>() { + long est = 1; + + @Override + public Spliterator trySplit() { + return null; + } + + @Override + public boolean tryAdvance(Consumer consumer) { + Objects.requireNonNull(consumer); + if(est > 0) { + est--; + consumer.accept(element); + return true; + } + return false; + } + + @Override + public void forEachRemaining(Consumer consumer) { + tryAdvance(consumer); + } + + @Override + public long estimateSize() { + return est; + } + + @Override + public int characteristics() { + int value = (element != null) ? Spliterator.NONNULL : 0; + + return value | Spliterator.SIZED | Spliterator.SUBSIZED | Spliterator.IMMUTABLE | + Spliterator.DISTINCT | Spliterator.ORDERED; + } + }; + } + + @Override + public boolean removeIf(Predicate filter) { + throw new UnsupportedOperationException(); + } + + @Override + public int hashCode() { + return Objects.hashCode(element); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/collections/ProbabilityCollection.java b/common/api/src/main/java/com/dfsek/terra/api/util/collection/ProbabilityCollection.java similarity index 73% rename from common/src/main/java/com/dfsek/terra/api/util/collections/ProbabilityCollection.java rename to common/api/src/main/java/com/dfsek/terra/api/util/collection/ProbabilityCollection.java index f9ec64992..f5d5863c6 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/collections/ProbabilityCollection.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/collection/ProbabilityCollection.java @@ -1,8 +1,12 @@ -package com.dfsek.terra.api.util.collections; +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util.collection; -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.mutable.MutableInteger; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -15,12 +19,18 @@ import java.util.Random; import java.util.Set; import java.util.function.Function; -@SuppressWarnings("unchecked") +import com.dfsek.terra.api.noise.NoiseSampler; +import com.dfsek.terra.api.util.MathUtil; +import com.dfsek.terra.api.util.mutable.MutableInteger; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.util.vector.Vector3Int; + + public class ProbabilityCollection implements Collection { protected final Map cont = new HashMap<>(); private Object[] array = new Object[0]; private int size; - + public ProbabilityCollection add(E item, int probability) { if(!cont.containsKey(item)) size++; cont.computeIfAbsent(item, i -> new MutableInteger(0)).increment(); @@ -31,85 +41,92 @@ public class ProbabilityCollection implements Collection { for(int i = oldLength; i < array.length; i++) array[i] = item; return this; } - + + @SuppressWarnings("unchecked") public E get(Random r) { if(array.length == 0) return null; return (E) array[r.nextInt(array.length)]; } - - public E get(NoiseSampler n, double x, double y, double z) { + + @SuppressWarnings("unchecked") + public E get(NoiseSampler n, double x, double y, double z, long seed) { if(array.length == 0) return null; - return (E) array[MathUtil.normalizeIndex(n.getNoise(x, y, z), array.length)]; + return (E) array[MathUtil.normalizeIndex(n.noise(seed, x, y, z), array.length)]; } - - public E get(NoiseSampler n, double x, double z) { + + @SuppressWarnings("unchecked") + public E get(NoiseSampler n, Vector3Int vector3Int, long seed) { if(array.length == 0) return null; - return (E) array[MathUtil.normalizeIndex(n.getNoise(x, z), array.length)]; + return (E) array[MathUtil.normalizeIndex(n.noise(seed, vector3Int.getX(), vector3Int.getY(), vector3Int.getZ()), array.length)]; } - + + @SuppressWarnings("unchecked") + public E get(NoiseSampler n, Vector3 vector3Int, long seed) { + if(array.length == 0) return null; + return (E) array[MathUtil.normalizeIndex(n.noise(seed, vector3Int.getX(), vector3Int.getY(), vector3Int.getZ()), array.length)]; + } + + @SuppressWarnings("unchecked") + public E get(NoiseSampler n, double x, double z, long seed) { + if(array.length == 0) return null; + return (E) array[MathUtil.normalizeIndex(n.noise(seed, x, z), array.length)]; + } + + @SuppressWarnings("unchecked") public ProbabilityCollection map(Function mapper, boolean carryNull) { ProbabilityCollection newCollection = new ProbabilityCollection<>(); newCollection.array = new Object[array.length]; - + for(int i = 0; i < array.length; i++) { if(carryNull && array[i] == null) continue; newCollection.array[i] = mapper.apply((E) array[i]); } return newCollection; } - - public int getTotalProbability() { - return array.length; - } - - public int getProbability(E item) { - MutableInteger integer = cont.get(item); - return integer == null ? 0 : integer.get(); - } - + @Override public String toString() { StringBuilder builder = new StringBuilder("["); - + cont.forEach((item, prob) -> builder.append(item).append(": ").append(prob).append(", ")); - + return builder.append("]").toString(); } - + @Override public int size() { return size; } - + @Override public boolean isEmpty() { return array.length == 0; } - + @Override public boolean contains(Object o) { return cont.containsKey(o); } - + @NotNull @Override public Iterator iterator() { return cont.keySet().iterator(); } - + @NotNull @Override - public Object[] toArray() { + public Object @NotNull [] toArray() { return cont.keySet().toArray(); } - + @SuppressWarnings("SuspiciousToArrayCall") @NotNull @Override - public T[] toArray(@NotNull T[] a) { + public T @NotNull [] toArray(@NotNull T @NotNull [] a) { return cont.keySet().toArray(a); } - + /** * Adds an item with probability of 1. */ @@ -118,87 +135,96 @@ public class ProbabilityCollection implements Collection { add(e, 1); return true; // Since this adds the item with a probability, the collection will always have changed. } - + @Override public boolean remove(Object o) { throw new UnsupportedOperationException("Cannot remove item from ProbabilityCollection!"); } - + @Override public boolean containsAll(@NotNull Collection c) { return cont.keySet().containsAll(c); } - + @Override public boolean addAll(@NotNull Collection c) { c.forEach(this::add); return true; } - + @Override public boolean removeAll(@NotNull Collection c) { throw new UnsupportedOperationException("Cannot remove item from ProbabilityCollection!"); } - + @Override public boolean retainAll(@NotNull Collection c) { throw new UnsupportedOperationException("Cannot remove item from ProbabilityCollection!"); } - + @Override public void clear() { cont.clear(); array = new Object[0]; } - + + public int getTotalProbability() { + return array.length; + } + + public int getProbability(E item) { + MutableInteger integer = cont.get(item); + return integer == null ? 0 : integer.get(); + } + public Set getContents() { return new HashSet<>(cont.keySet()); } - + public static final class Singleton extends ProbabilityCollection { private final T single; - + public Singleton(T single) { this.single = single; cont.put(single, new MutableInteger(1)); } - + @Override public ProbabilityCollection add(T item, int probability) { throw new UnsupportedOperationException(); } - + + @Override + public T get(Random r) { + return single; + } + + @Override + public T get(NoiseSampler n, double x, double y, double z, long seed) { + return single; + } + + @Override + public T get(NoiseSampler n, double x, double z, long seed) { + return single; + } + @Override public ProbabilityCollection map(Function mapper, boolean carryNull) { if(carryNull && single == null) return new Singleton<>(null); return new Singleton<>(mapper.apply(single)); } - - @Override - public T get(Random r) { - return single; - } - - @Override - public T get(NoiseSampler n, double x, double y, double z) { - return single; - } - - @Override - public T get(NoiseSampler n, double x, double z) { - return single; - } - - @Override - public int getTotalProbability() { - return 1; - } - + @Override public int size() { return 1; } - + + @Override + public int getTotalProbability() { + return 1; + } + @Override public Set getContents() { return Collections.singleton(single); diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/function/IntToBooleanFunction.java b/common/api/src/main/java/com/dfsek/terra/api/util/function/IntToBooleanFunction.java new file mode 100644 index 000000000..eb02bb73b --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/function/IntToBooleanFunction.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.util.function; + +@FunctionalInterface +public interface IntToBooleanFunction { + boolean apply(int value); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/Construct.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/Construct.java new file mode 100644 index 000000000..678a98b2d --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/Construct.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util.generic; + +import java.util.function.Supplier; + + +public final class Construct { + public static T construct(Supplier in) { + return in.get(); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/Lazy.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/Lazy.java new file mode 100644 index 000000000..ca9735d03 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/Lazy.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util.generic; + +import java.util.function.Supplier; + + +public final class Lazy { + private final Supplier valueSupplier; + private T value; + private boolean got = false; + + private Lazy(Supplier valueSupplier) { + this.valueSupplier = valueSupplier; + } + + public static Lazy lazy(Supplier valueSupplier) { + return new Lazy<>(valueSupplier); + } + + public T value() { + if(!got && value == null) { + got = true; + value = valueSupplier.get(); + } + return value; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/generic/either/Either.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/either/Either.java similarity index 51% rename from common/src/main/java/com/dfsek/terra/api/util/generic/either/Either.java rename to common/api/src/main/java/com/dfsek/terra/api/util/generic/either/Either.java index cad5d93bf..047fb8426 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/generic/either/Either.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/either/Either.java @@ -1,52 +1,87 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + package com.dfsek.terra.api.util.generic.either; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; + public final class Either { private final L left; private final R right; private final boolean leftPresent; - + private Either(L left, R right, boolean leftPresent) { this.left = left; this.right = right; this.leftPresent = leftPresent; } - + + @NotNull + @Contract("_ -> new") public static Either left(L1 left) { - return new Either<>(left, null, true); + return new Either<>(Objects.requireNonNull(left), null, true); } - + + @NotNull + @Contract("_ -> new") public static Either right(R1 right) { - return new Either<>(null, right, false); + return new Either<>(null, Objects.requireNonNull(right), false); } - - public Optional getLeft() { - if(leftPresent) return Optional.of(left); - return Optional.empty(); - } - - public Optional getRight() { - if(!leftPresent) return Optional.of(right); - return Optional.empty(); - } - + + @NotNull + @Contract("_ -> this") public Either ifLeft(Consumer action) { if(leftPresent) action.accept(left); return this; } - + + @NotNull + @Contract("_ -> this") public Either ifRight(Consumer action) { if(!leftPresent) action.accept(right); return this; } - + + @NotNull + public Optional getLeft() { + if(leftPresent) return Optional.of(left); + return Optional.empty(); + } + + @NotNull + public Optional getRight() { + if(!leftPresent) return Optional.of(right); + return Optional.empty(); + } + public boolean hasLeft() { return leftPresent; } - + public boolean hasRight() { return !leftPresent; } + + @Override + public int hashCode() { + return Objects.hash(left, right); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Either that)) return false; + + return (this.leftPresent && that.leftPresent && Objects.equals(this.left, that.left)) + || (!this.leftPresent && !that.leftPresent && Objects.equals(this.right, that.right)); + } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java new file mode 100644 index 000000000..58d1e7353 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util.generic.pair; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + + +public final class Pair { + private static final Pair NULL = new Pair<>(null, null); + private final L left; + private final R right; + + private Pair(L left, R right) { + this.left = left; + this.right = right; + } + + @Contract("_, _ -> new") + public static Pair of(L1 left, R1 right) { + return new Pair<>(left, right); + } + + @Contract("-> new") + @SuppressWarnings("unchecked") + public static Pair ofNull() { + return (Pair) NULL; + } + + @NotNull + @Contract("-> new") + public Pair.Mutable mutable() { + return Mutable.of(left, right); + } + + public R getRight() { + return right; + } + + public L getLeft() { + return left; + } + + @Override + public int hashCode() { + return Objects.hash(left, right); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Pair that)) return false; + + return Objects.equals(this.left, that.left) && Objects.equals(this.right, that.right); + } + + public static class Mutable { + private L left; + private R right; + + private Mutable(L left, R right) { + this.left = left; + this.right = right; + } + + @NotNull + @Contract("_, _ -> new") + public static Pair.Mutable of(L1 left, R1 right) { + return new Mutable<>(left, right); + } + + @Contract("-> new") + public Pair immutable() { + return Pair.of(left, right); + } + + public L getLeft() { + return left; + } + + public void setLeft(L left) { + this.left = left; + } + + public R getRight() { + return right; + } + + public void setRight(R right) { + this.right = right; + } + + @Override + public int hashCode() { + return Objects.hash(left, right); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Mutable that)) return false; + + return Objects.equals(this.left, that.left) && Objects.equals(this.right, that.right); + } + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableBoolean.java b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableBoolean.java similarity index 74% rename from common/src/main/java/com/dfsek/terra/api/util/mutable/MutableBoolean.java rename to common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableBoolean.java index a71fdb9be..eb6b07948 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableBoolean.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableBoolean.java @@ -1,33 +1,41 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + package com.dfsek.terra.api.util.mutable; import org.jetbrains.annotations.NotNull; + public class MutableBoolean implements MutablePrimitive { private boolean value; - + public MutableBoolean() { this.value = false; } - + public MutableBoolean(boolean value) { this.value = value; } - + @Override public Boolean get() { return value; } - + @Override public void set(Boolean value) { this.value = value; } - + public boolean invert() { value = !value; return value; } - + @Override public int compareTo(@NotNull Boolean o) { return Boolean.compare(value, o); diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableDouble.java b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableDouble.java similarity index 75% rename from common/src/main/java/com/dfsek/terra/api/util/mutable/MutableDouble.java rename to common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableDouble.java index be86110b3..c3edfdd20 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableDouble.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableDouble.java @@ -1,44 +1,55 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + package com.dfsek.terra.api.util.mutable; import org.jetbrains.annotations.NotNull; -public class MutableDouble extends MutableNumber { - private static final long serialVersionUID = -2218110876763640053L; +import java.io.Serial; + +public class MutableDouble extends MutableNumber { + @Serial + private static final long serialVersionUID = -2218110876763640053L; + public MutableDouble(Double value) { super(value); } - + @Override public void increment() { add(1d); } - + @Override public void decrement() { subtract(1d); } - + @Override public void add(Double add) { value += add; } - + @Override public void multiply(Double mul) { value *= mul; } - + @Override public void subtract(Double sub) { value -= sub; } - + @Override public void divide(Double divide) { value /= divide; } - + @Override public int compareTo(@NotNull Double o) { return Double.compare(value, o); diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableInteger.java b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableInteger.java similarity index 76% rename from common/src/main/java/com/dfsek/terra/api/util/mutable/MutableInteger.java rename to common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableInteger.java index a2d949d87..ed1abadd9 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableInteger.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableInteger.java @@ -1,46 +1,57 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + package com.dfsek.terra.api.util.mutable; import org.jetbrains.annotations.NotNull; -public class MutableInteger extends MutableNumber { - private static final long serialVersionUID = -4427935901819632745L; +import java.io.Serial; + +public class MutableInteger extends MutableNumber { + @Serial + private static final long serialVersionUID = -4427935901819632745L; + public MutableInteger(Integer value) { super(value); } - + public void increment() { add(1); } - + public void decrement() { subtract(1); } - + @Override public void add(Integer add) { value += add; } - + @Override public void multiply(Integer mul) { value *= mul; } - + @Override public void subtract(Integer sub) { value -= sub; } - + @Override public void divide(Integer divide) { value /= divide; } - + public void add(int add) { value += add; } - + @Override public int compareTo(@NotNull Integer o) { return Integer.compare(value, o); diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableNumber.java b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableNumber.java similarity index 77% rename from common/src/main/java/com/dfsek/terra/api/util/mutable/MutableNumber.java rename to common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableNumber.java index 8b682eea0..ce9fe2874 100644 --- a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutableNumber.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutableNumber.java @@ -1,51 +1,62 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + package com.dfsek.terra.api.util.mutable; -public abstract class MutableNumber extends Number implements MutablePrimitive { +import java.io.Serial; + +public abstract class MutableNumber extends Number implements MutablePrimitive { + + @Serial private static final long serialVersionUID = 8619508342781664393L; protected T value; - + public MutableNumber(T value) { this.value = value; } - + public abstract void increment(); - + public abstract void decrement(); - + public abstract void add(T add); - + public abstract void multiply(T mul); - + public abstract void subtract(T sub); - + public abstract void divide(T divide); - + @Override public T get() { return value; } - + @Override public void set(T value) { this.value = value; } - + @Override public int intValue() { return value.intValue(); } - + @Override public long longValue() { return value.longValue(); } - + @Override public float floatValue() { return value.floatValue(); } - + @Override public double doubleValue() { return value.doubleValue(); diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutablePrimitive.java b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutablePrimitive.java new file mode 100644 index 000000000..5718aba48 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/MutablePrimitive.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util.mutable; + +public interface MutablePrimitive extends Comparable { + T get(); + + void set(T value); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/mutable/package-info.java b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/package-info.java new file mode 100644 index 000000000..c45a11ed4 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/mutable/package-info.java @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +/** + * Mutable objects containing primitive types. + */ + +package com.dfsek.terra.api.util.mutable; \ No newline at end of file diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/reflection/ReflectionUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/reflection/ReflectionUtil.java new file mode 100644 index 000000000..11bbd8802 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/reflection/ReflectionUtil.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util.reflection; + +import org.jetbrains.annotations.NotNull; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.Arrays; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.stream.Stream; + + +public final class ReflectionUtil { + public static Field[] getFields(@NotNull Class type) { + Field[] result = type.getDeclaredFields(); + Class parentClass = type.getSuperclass(); + if(parentClass != null) { + result = Stream.concat(Arrays.stream(result), Arrays.stream(getFields(parentClass))).toArray(Field[]::new); + } + return result; + } + + public static Method[] getMethods(@NotNull Class type) { + Method[] result = type.getDeclaredMethods(); + Class parentClass = type.getSuperclass(); + if(parentClass != null) { + result = Stream.concat(Arrays.stream(result), Arrays.stream(getMethods(parentClass))).toArray(Method[]::new); + } + return result; + } + + public static void ifAnnotationPresent(AnnotatedElement element, Class annotation, + Consumer operation) { + T a = element.getAnnotation(annotation); + if(a != null) operation.accept(a); + } + + public static Class getRawType(Type type) { + if(type instanceof Class) { + return (Class) type; + } else if(type instanceof ParameterizedType parameterizedType) { + Type rawType = parameterizedType.getRawType(); + return (Class) rawType; + } else if(type instanceof GenericArrayType) { + Type componentType = ((GenericArrayType) type).getGenericComponentType(); + return Array.newInstance(getRawType(componentType), 0).getClass(); + } else if(type instanceof TypeVariable) { + return Object.class; + } else if(type instanceof WildcardType) { + return getRawType(((WildcardType) type).getUpperBounds()[0]); + } else { + String className = type == null ? "null" : type.getClass().getName(); + throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + + "GenericArrayType, but <" + type + "> is of type " + className); + } + } + + public static String typeToString(Type type) { + return type instanceof Class ? ((Class) type).getName() : type.toString(); + } + + public static boolean equals(Type a, Type b) { + if(a == b) { + return true; + } else if(a instanceof Class) { + return a.equals(b); + } else if(a instanceof ParameterizedType pa) { + if(!(b instanceof ParameterizedType pb)) { + return false; + } + + return Objects.equals(pa.getOwnerType(), pb.getOwnerType()) + && pa.getRawType().equals(pb.getRawType()) + && Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments()); + } else if(a instanceof GenericArrayType ga) { + if(!(b instanceof GenericArrayType gb)) { + return false; + } + + return equals(ga.getGenericComponentType(), gb.getGenericComponentType()); + } else if(a instanceof WildcardType wa) { + if(!(b instanceof WildcardType wb)) { + return false; + } + + return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds()) + && Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds()); + } else if(a instanceof TypeVariable va) { + if(!(b instanceof TypeVariable vb)) { + return false; + } + return va.getGenericDeclaration() == vb.getGenericDeclaration() + && va.getName().equals(vb.getName()); + } else { + return false; + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/reflection/TypeKey.java b/common/api/src/main/java/com/dfsek/terra/api/util/reflection/TypeKey.java new file mode 100644 index 000000000..a3518c512 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/reflection/TypeKey.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util.reflection; + +import com.dfsek.tectonic.util.ClassAnnotatedTypeImpl; + +import java.lang.reflect.AnnotatedParameterizedType; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + + +public class TypeKey { + final Class rawType; + final Type type; + + final AnnotatedType annotatedType; + final int hashCode; + + @SuppressWarnings("unchecked") + protected TypeKey() { + this.type = getSuperclassTypeParameter(getClass()); + this.annotatedType = getAnnotatedSuperclassTypeParameter(getClass()); + this.rawType = (Class) ReflectionUtil.getRawType(type); + this.hashCode = type.hashCode(); + } + + protected TypeKey(Class clazz) { + this.type = clazz; + this.rawType = clazz; + this.annotatedType = new ClassAnnotatedTypeImpl(clazz); + this.hashCode = type.hashCode(); + } + + public static TypeKey of(Class clazz) { + return new TypeKey<>(clazz); + } + + private static Type getSuperclassTypeParameter(Class subclass) { + Type superclass = subclass.getGenericSuperclass(); + if(superclass instanceof Class) { + throw new RuntimeException("Missing type parameter."); + } + ParameterizedType parameterized = (ParameterizedType) superclass; + return parameterized.getActualTypeArguments()[0]; + } + + private static AnnotatedType getAnnotatedSuperclassTypeParameter(Class subclass) { + AnnotatedType superclass = subclass.getAnnotatedSuperclass(); + if(superclass.getType() instanceof Class) { + throw new RuntimeException("Missing type parameter."); + } + AnnotatedParameterizedType parameterized = (AnnotatedParameterizedType) superclass; + return parameterized.getAnnotatedActualTypeArguments()[0]; + } + + /** + * Returns the raw (non-generic) type for this type. + */ + public final Class getRawType() { + return rawType; + } + + /** + * Gets underlying {@code Type} instance. + */ + public final Type getType() { + return type; + } + + public final AnnotatedType getAnnotatedType() { + return annotatedType; + } + + @Override + public final int hashCode() { + return this.hashCode; + } + + @Override + public final boolean equals(Object o) { + return o instanceof TypeKey + && ReflectionUtil.equals(type, ((TypeKey) o).type); + } + + @Override + public final String toString() { + return ReflectionUtil.typeToString(type); + } +} + diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector2.java b/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector2.java new file mode 100644 index 000000000..5dc1e8f1c --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector2.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util.vector; + +import net.jafama.FastMath; + +import com.dfsek.terra.api.util.MathUtil; + + +/** + * oh yeah + */ +public class Vector2 { + protected double x; + protected double z; + + /** + * Create a vector with a given X and Z component + * + * @param x X component + * @param z Z component + */ + private Vector2(double x, double z) { + this.x = x; + this.z = z; + } + + public static Vector2 of(double x, double z) { + return new Vector2(x, z); + } + + + /** + * Get the length of this Vector + * + * @return length + */ + public double length() { + return FastMath.sqrt(lengthSquared()); + } + + /** + * Get the squared length of this Vector + * + * @return squared length + */ + public double lengthSquared() { + return x * x + z * z; + } + + /** + * Get the distance from this vector to another. + * + * @param other Another vector + * + * @return Distance between vectors + */ + public double distance(Vector2 other) { + return FastMath.sqrt(distanceSquared(other)); + } + + /** + * Get the squared distance between 2 vectors. + * + * @param other Another vector + * + * @return Squared distance + */ + public double distanceSquared(Vector2 other) { + double dx = other.getX() - x; + double dz = other.getZ() - z; + return dx * dx + dz * dz; + } + + public Vector3 extrude(double y) { + return Vector3.of(this.x, y, this.z); + } + + /** + * Get X component + * + * @return X component + */ + public double getX() { + return x; + } + + + /** + * Get Z component + * + * @return Z component + */ + public double getZ() { + return z; + } + + + public int getBlockX() { + return FastMath.floorToInt(x); + } + + public int getBlockZ() { + return FastMath.floorToInt(z); + } + + @Override + public int hashCode() { + int hash = 17; + hash = 31 * hash + Double.hashCode(x); + hash = 31 * hash + Double.hashCode(z); + return hash; + } + + public boolean equals(Object obj) { + if(!(obj instanceof Vector2 other)) return false; + return MathUtil.equals(this.x, other.x) && MathUtil.equals(this.z, other.z); + } + + public Mutable mutable() { + return new Mutable(x, z); + } + + @Override + public String toString() { + return "(" + x + ", " + z + ")"; + } + + + public static class Mutable extends Vector2 { + + private Mutable(double x, double z) { + super(x, z); + } + + public double getX() { + return x; + } + + public Mutable setX(double x) { + this.x = x; + return this; + } + + public double getZ() { + return z; + } + + public Mutable setZ(double z) { + this.z = z; + return this; + } + + public Vector2 immutable() { + return Vector2.of(x, z); + } + + /** + * Get the length of this Vector + * + * @return length + */ + public double length() { + return FastMath.sqrt(lengthSquared()); + } + + /** + * Get the squared length of this Vector + * + * @return squared length + */ + public double lengthSquared() { + return x * x + z * z; + } + + public Mutable add(double x, double z) { + this.x += x; + this.z += z; + return this; + } + + /** + * Multiply X and Z components by a value. + * + * @param m Value to multiply + * + * @return Mutated vector, for chaining. + */ + public Mutable multiply(double m) { + x *= m; + z *= m; + return this; + } + + /** + * Add this vector to another. + * + * @param other Vector to add + * + * @return Mutated vector, for chaining. + */ + public Mutable add(Vector2 other) { + x += other.getX(); + z += other.getZ(); + return this; + } + + /** + * Subtract a vector from this vector, + * + * @param other Vector to subtract + * + * @return Mutated vector, for chaining. + */ + public Mutable subtract(Vector2 other) { + x -= other.getX(); + z -= other.getZ(); + return this; + } + + /** + * Normalize this vector to length 1 + * + * @return Mutated vector, for chaining. + */ + public Mutable normalize() { + divide(length()); + return this; + } + + /** + * Divide X and Z components by a value. + * + * @param d Divisor + * + * @return Mutated vector, for chaining. + */ + public Mutable divide(double d) { + x /= d; + z /= d; + return this; + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector2Int.java b/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector2Int.java new file mode 100644 index 000000000..09ce8715d --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector2Int.java @@ -0,0 +1,97 @@ +package com.dfsek.terra.api.util.vector; + +import com.dfsek.terra.api.util.Rotation; + + +/** + * oh yeah + */ +public class Vector2Int { + private static final Vector2Int ZERO = new Vector2Int(0, 0); + private static final Vector2Int UNIT = new Vector2Int(0, 1); + protected int x; + protected int z; + + protected Vector2Int(int x, int z) { + this.x = x; + this.z = z; + } + + public static Vector2Int zero() { + return ZERO; + } + + public static Vector2Int unit() { + return UNIT; + } + + public static Vector2Int of(int x, int z) { + return new Vector2Int(x, z); + } + + public int getX() { + return x; + } + + public int getZ() { + return z; + } + + public Vector3Int toVector3(int y) { + return new Vector3Int(x, y, z); + } + + public Mutable mutable() { + return new Mutable(x, z); + } + + public Vector2Int rotate(Rotation rotation) { + return switch(rotation) { + case CW_90 -> of(z, -x); + case CCW_90 -> of(-z, x); + case CW_180 -> of(-x, -z); + default -> this; + }; + } + + @Override + public int hashCode() { + return (31 * x) + z; + } + + @Override + public boolean equals(Object obj) { + if(obj instanceof Vector2Int that) { + return this.x == that.x && this.z == that.z; + } + return false; + } + + + public static class Mutable extends Vector2Int { + + protected Mutable(int x, int z) { + super(x, z); + } + + public int getZ() { + return z; + } + + public void setZ(int z) { + this.z = z; + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public Vector2Int immutable() { + return new Vector2Int(x, z); + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector3.java b/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector3.java new file mode 100644 index 000000000..b5c45ca61 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector3.java @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.util.vector; + +import net.jafama.FastMath; +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.util.MathUtil; + + +public class Vector3 { + protected double x; + protected double y; + protected double z; + + private Vector3(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public static Vector3 of(double x, double y, double z) { + return new Vector3(x, y, z); + } + + public double lengthSquared() { + return x * x + y * y + z * z; + } + + public double length() { + return FastMath.sqrt(lengthSquared()); + } + + public double inverseLength() { + return FastMath.invSqrtQuick(lengthSquared()); + } + + /** + * Get the distance between this vector and another. The value of this + * method is not cached and uses a costly square-root function, so do not + * repeatedly call this method to get the vector's magnitude. NaN will be + * returned if the inner result of the sqrt() function overflows, which + * will be caused if the distance is too long. + * + * @param o The other vector + * + * @return the distance + */ + public double distance(@NotNull Vector3 o) { + return FastMath.sqrt(FastMath.pow2(x - o.getX()) + FastMath.pow2(y - o.getY()) + FastMath.pow2(z - o.getZ())); + } + + /** + * Get the squared distance between this vector and another. + * + * @param o The other vector + * + * @return the distance + */ + public double distanceSquared(@NotNull Vector3 o) { + return FastMath.pow2(x - o.getX()) + FastMath.pow2(y - o.getY()) + FastMath.pow2(z - o.getZ()); + } + + /** + * Calculates the dot product of this vector with another. The dot product + * is defined as x1*x2+y1*y2+z1*z2. The returned value is a scalar. + * + * @param other The other vector + * + * @return dot product + */ + public double dot(@NotNull Vector3 other) { + return x * other.getX() + y * other.getY() + z * other.getZ(); + } + + public double getZ() { + return z; + } + + + public double getX() { + return x; + } + + + public double getY() { + return y; + } + + + public int getBlockX() { + return FastMath.floorToInt(x); + } + + public int getBlockY() { + return FastMath.floorToInt(y); + } + + public int getBlockZ() { + return FastMath.floorToInt(z); + } + + /** + * Returns if a vector is normalized + * + * @return whether the vector is normalised + */ + public boolean isNormalized() { + return MathUtil.equals(this.lengthSquared(), 1); + } + + /** + * Returns a hash code for this vector + * + * @return hash code + */ + @Override + public int hashCode() { + int hash = 7; + + hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); + hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); + hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); + return hash; + } + + /** + * Checks to see if two objects are equal. + *

+ * Only two Vectors can ever return true. This method uses a fuzzy match + * to account for floating point errors. The epsilon can be retrieved + * with epsilon. + */ + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Vector3 other)) return false; + return MathUtil.equals(x, other.getX()) && MathUtil.equals(y, other.getY()) && MathUtil.equals(z, other.getZ()); + } + + public Vector3Int toInt() { + return Vector3Int.of(getBlockX(), getBlockY(), getBlockZ()); + } + + public Mutable mutable() { + return new Mutable(x, y, z); + } + + @Override + public String toString() { + return "(" + getX() + ", " + getY() + ", " + getZ() + ")"; + } + + + public static class Mutable extends Vector3 { + private Mutable(double x, double y, double z) { + super(x, y, z); + } + + public static Mutable of(double x, double y, double z) { + return new Mutable(x, y, z); + } + + public Vector3 immutable() { + return Vector3.of(x, y, z); + } + + public double getZ() { + return z; + } + + public Mutable setZ(double z) { + this.z = z; + return this; + } + + public double getX() { + return x; + } + + public Mutable setX(double x) { + this.x = x; + return this; + } + + public double getY() { + return y; + } + + public Mutable setY(double y) { + this.y = y; + return this; + } + + public double lengthSquared() { + return x * x + y * y + z * z; + } + + public double length() { + return FastMath.sqrt(lengthSquared()); + } + + public double inverseLength() { + return FastMath.invSqrtQuick(lengthSquared()); + } + + public Mutable normalize() { + return this.multiply(this.inverseLength()); + } + + public Mutable subtract(int x, int y, int z) { + this.x -= x; + this.y -= y; + this.z -= z; + return this; + } + + /** + * Calculates the dot product of this vector with another. The dot product + * is defined as x1*x2+y1*y2+z1*z2. The returned value is a scalar. + * + * @param other The other vector + * + * @return dot product + */ + public double dot(@NotNull Vector3 other) { + return x * other.getX() + y * other.getY() + z * other.getZ(); + } + + public Mutable subtract(Vector3 end) { + x -= end.getX(); + y -= end.getY(); + z -= end.getZ(); + return this; + } + + public Mutable multiply(double m) { + x *= m; + y *= m; + z *= m; + return this; + } + + public Mutable add(double x, double y, double z) { + this.x += x; + this.y += y; + this.z += z; + return this; + } + + public Mutable add(Vector3 other) { + this.x += other.getX(); + this.y += other.getY(); + this.z += other.getZ(); + return this; + } + + public Mutable add(Vector3Int other) { + this.x += other.getX(); + this.y += other.getY(); + this.z += other.getZ(); + return this; + } + + public Mutable add(Vector2 other) { + this.x += other.getX(); + this.z += other.getZ(); + return this; + } + + /** + * Rotates the vector around a given arbitrary axis in 3 dimensional space. + * + *

+ * Rotation will follow the general Right-Hand-Rule, which means rotation + * will be counterclockwise when the axis is pointing towards the observer. + *

+ * This method will always make sure the provided axis is a unit vector, to + * not modify the length of the vector when rotating. + * + * @param axis the axis to rotate the vector around. If the passed vector is + * not of length 1, it gets copied and normalized before using it for the + * rotation. Please use {@link Mutable#normalize()} on the instance before + * passing it to this method + * @param angle the angle to rotate the vector around the axis + * + * @return the same vector + * + * @throws IllegalArgumentException if the provided axis vector instance is + * null + */ + @NotNull + public Mutable rotateAroundAxis(@NotNull Vector3 axis, double angle) throws IllegalArgumentException { + return rotateAroundNonUnitAxis(axis.isNormalized() ? axis : axis.mutable().normalize().immutable(), angle); + } + + /** + * Rotates the vector around a given arbitrary axis in 3 dimensional space. + * + *

+ * Rotation will follow the general Right-Hand-Rule, which means rotation + * will be counterclockwise when the axis is pointing towards the observer. + *

+ * Note that the vector length will change accordingly to the axis vector + * length. If the provided axis is not a unit vector, the rotated vector + * will not have its previous length. The scaled length of the resulting + * vector will be related to the axis vector. + * + * @param axis the axis to rotate the vector around. + * @param angle the angle to rotate the vector around the axis + * + * @return the same vector + * + * @throws IllegalArgumentException if the provided axis vector instance is + * null + */ + @NotNull + public Mutable rotateAroundNonUnitAxis(@NotNull Vector3 axis, double angle) throws IllegalArgumentException { + double x = getX(), y = getY(), z = getZ(); + double x2 = axis.getX(), y2 = axis.getY(), z2 = axis.getZ(); + + double cosTheta = Math.cos(angle); + double sinTheta = Math.sin(angle); + double dotProduct = this.dot(axis); + + double xPrime = x2 * dotProduct * (1d - cosTheta) + + x * cosTheta + + (-z2 * y + y2 * z) * sinTheta; + double yPrime = y2 * dotProduct * (1d - cosTheta) + + y * cosTheta + + (z2 * x - x2 * z) * sinTheta; + double zPrime = z2 * dotProduct * (1d - cosTheta) + + z * cosTheta + + (-y2 * x + x2 * y) * sinTheta; + + return setX(xPrime).setY(yPrime).setZ(zPrime); + } + + /** + * Rotates the vector around the x axis. + *

+ * This piece of math is based on the standard rotation matrix for vectors + * in three dimensional space. This matrix can be found here: + * Rotation + * Matrix. + * + * @param angle the angle to rotate the vector about. This angle is passed + * in radians + * + * @return the same vector + */ + @NotNull + public Mutable rotateAroundX(double angle) { + double angleCos = Math.cos(angle); + double angleSin = Math.sin(angle); + + double y = angleCos * getY() - angleSin * getZ(); + double z = angleSin * getY() + angleCos * getZ(); + return setY(y).setZ(z); + } + + /** + * Rotates the vector around the y axis. + *

+ * This piece of math is based on the standard rotation matrix for vectors + * in three dimensional space. This matrix can be found here: + * Rotation + * Matrix. + * + * @param angle the angle to rotate the vector about. This angle is passed + * in radians + * + * @return the same vector + */ + @NotNull + public Mutable rotateAroundY(double angle) { + double angleCos = Math.cos(angle); + double angleSin = Math.sin(angle); + + double x = angleCos * getX() + angleSin * getZ(); + double z = -angleSin * getX() + angleCos * getZ(); + return setX(x).setZ(z); + } + + /** + * Rotates the vector around the z axis + *

+ * This piece of math is based on the standard rotation matrix for vectors + * in three dimensional space. This matrix can be found here: + * Rotation + * Matrix. + * + * @param angle the angle to rotate the vector about. This angle is passed + * in radians + * + * @return the same vector + */ + @NotNull + public Mutable rotateAroundZ(double angle) { + double angleCos = Math.cos(angle); + double angleSin = Math.sin(angle); + + double x = angleCos * getX() - angleSin * getY(); + double y = angleSin * getX() + angleCos * getY(); + return setX(x).setY(y); + } + + @Override + public int hashCode() { + int hash = 13; + + hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); + hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); + hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); + return hash; + } + + public int getBlockX() { + return FastMath.floorToInt(x); + } + + public int getBlockY() { + return FastMath.floorToInt(y); + } + + public int getBlockZ() { + return FastMath.floorToInt(z); + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector3Int.java b/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector3Int.java new file mode 100644 index 000000000..ad79cec14 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/util/vector/Vector3Int.java @@ -0,0 +1,99 @@ +package com.dfsek.terra.api.util.vector; + + +public class Vector3Int { + private static final Vector3Int ZERO = new Vector3Int(0, 0, 0); + private static final Vector3Int UNIT = new Vector3Int(0, 1, 0); + protected int x, y, z; + + protected Vector3Int(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + public static Vector3Int unit() { + return UNIT; + } + + public static Vector3Int zero() { + return ZERO; + } + + public static Vector3Int of(int x, int y, int z) { + return new Vector3Int(x, y, z); + } + + public static Vector3Int of(Vector3Int origin, int x, int y, int z) { + return new Vector3Int(origin.x + x, origin.y + y, origin.z + z); + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getZ() { + return z; + } + + public Mutable mutable() { + return new Mutable(x, y, z); + } + + public Vector3 toVector3() { + return Vector3.of(x, y, z); + } + + public Vector3.Mutable toVector3Mutable() { + return Vector3.Mutable.of(x, y, z); + } + + public static class Mutable extends Vector3Int { + protected Mutable(int x, int y, int z) { + super(x, y, z); + } + + public int getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public int getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + public int getZ() { + return z; + } + + public void setZ(int z) { + this.z = z; + } + + public Vector3Int immutable() { + return Vector3Int.of(x, y, z); + } + + public Mutable add(int x, int y, int z) { + this.x += x; + this.y += y; + this.z += z; + return this; + } + + public Vector3 toVector3() { + return Vector3.of(x, y, z); + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/BufferedWorld.java b/common/api/src/main/java/com/dfsek/terra/api/world/BufferedWorld.java new file mode 100644 index 000000000..aba5d9cfa --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/BufferedWorld.java @@ -0,0 +1,163 @@ +package com.dfsek.terra.api.world; + +import java.util.Objects; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.util.Interceptors; +import com.dfsek.terra.api.world.util.ReadInterceptor; +import com.dfsek.terra.api.world.util.WriteInterceptor; + + +/** + * A {@link WritableWorld} implementation which delegates read/write operations to + * another {@link WritableWorld}, at an offset. + */ +public class BufferedWorld implements WritableWorld { + private final WritableWorld delegate; + private final int offsetX, offsetY, offsetZ; + + private final ReadInterceptor readInterceptor; + private final WriteInterceptor writeInterceptor; + + protected BufferedWorld(WritableWorld delegate, int offsetX, int offsetY, int offsetZ, + ReadInterceptor readInterceptor, WriteInterceptor writeInterceptor) { + this.delegate = delegate; + this.offsetX = offsetX; + + this.offsetY = offsetY; + this.offsetZ = offsetZ; + this.readInterceptor = readInterceptor; + this.writeInterceptor = writeInterceptor; + } + + protected static Builder builder(WritableWorld world) { + return new Builder(world); + } + + @Override + public Object getHandle() { + return delegate.getHandle(); + } + + @Override + public BlockState getBlockState(int x, int y, int z) { + return readInterceptor.read(x + offsetX, y + offsetY, z + offsetZ, delegate); + } + + @Override + public BlockEntity getBlockEntity(int x, int y, int z) { + return delegate.getBlockEntity(x + offsetX, y + offsetY, z + offsetZ); + } + + @Override + public long getSeed() { + return delegate.getSeed(); + } + + @Override + public int getMaxHeight() { + return delegate.getMaxHeight(); + } + + @Override + public int getMinHeight() { + return delegate.getMinHeight(); + } + + @Override + public ChunkGenerator getGenerator() { + return delegate.getGenerator(); + } + + @Override + public BiomeProvider getBiomeProvider() { + return delegate.getBiomeProvider(); + } + + @Override + public ConfigPack getPack() { + return delegate.getPack(); + } + + @Override + public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { + writeInterceptor.write(x + offsetX, y + offsetY, z + offsetZ, data, delegate, physics); + } + + @Override + public Entity spawnEntity(double x, double y, double z, EntityType entityType) { + return delegate.spawnEntity(x + offsetX, y + offsetY, z + offsetZ, entityType); + } + + /** + * Get the world this {@link BufferedWorld} delegates to. + * + * @return Delegate world. + */ + public WritableWorld getDelegate() { + return delegate; + } + + + public static final class Builder { + private final WritableWorld delegate; + private ReadInterceptor readInterceptor; + private WriteInterceptor writeInterceptor; + + private int x = 0; + private int y = 0; + private int z = 0; + + private Builder(WritableWorld delegate) { + this.delegate = delegate; + } + + public Builder read(ReadInterceptor interceptor) { + this.readInterceptor = interceptor; + return this; + } + + public Builder write(WriteInterceptor interceptor) { + this.writeInterceptor = interceptor; + return this; + } + + public Builder offsetX(int x) { + this.x = x; + return this; + } + + public Builder offsetY(int y) { + this.y = y; + return this; + } + + public Builder offsetZ(int z) { + this.z = z; + return this; + } + + public Builder offset(Vector3Int vector) { + this.x = vector.getX(); + this.y = vector.getY(); + this.z = vector.getZ(); + return this; + } + + public BufferedWorld build() { + return new BufferedWorld(delegate, + this.x, + this.y, + this.z, + Objects.requireNonNullElse(readInterceptor, Interceptors.readThrough()), + Objects.requireNonNullElse(writeInterceptor, Interceptors.writeThrough())); + } + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/ReadableWorld.java b/common/api/src/main/java/com/dfsek/terra/api/world/ReadableWorld.java new file mode 100644 index 000000000..931f599d2 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/ReadableWorld.java @@ -0,0 +1,55 @@ +package com.dfsek.terra.api.world; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.util.vector.Vector3Int; + + +/** + * A {@link World} with read access. + */ +public interface ReadableWorld extends World { + /** + * Get the {@link BlockState} at a location. + * + * @param x X coordinate + * @param y Y coordinate + * @param z Z coordinate + * + * @return {@link BlockState} at coordinates. + */ + BlockState getBlockState(int x, int y, int z); + + /** + * Get the {@link BlockState} at a location. + * + * @param position Location to get block. + * + * @return {@link BlockState} at coordinates. + */ + default BlockState getBlockState(Vector3 position) { + return getBlockState(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + } + + /** + * Get the {@link BlockState} at a location. + * + * @param position Location to get block. + * + * @return {@link BlockState} at coordinates. + */ + default BlockState getBlockState(Vector3Int position) { + return getBlockState(position.getX(), position.getY(), position.getZ()); + } + + BlockEntity getBlockEntity(int x, int y, int z); + + default BlockEntity getBlockEntity(Vector3 position) { + return getBlockEntity(position.getBlockX(), position.getBlockY(), position.getBlockZ()); + } + + default BlockEntity getBlockEntity(Vector3Int position) { + return getBlockEntity(position.getX(), position.getY(), position.getZ()); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/ServerWorld.java b/common/api/src/main/java/com/dfsek/terra/api/world/ServerWorld.java new file mode 100644 index 000000000..4fbda89b0 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/ServerWorld.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world; + +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.chunk.Chunk; + + +public interface ServerWorld extends WritableWorld { + Chunk getChunkAt(int x, int z); + + default Chunk getChunkAt(Vector3 location) { + return getChunkAt(location.getBlockX() >> 4, location.getBlockZ() >> 4); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/World.java b/common/api/src/main/java/com/dfsek/terra/api/world/World.java new file mode 100644 index 000000000..938f7ed58 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/World.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.api.world; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.info.WorldProperties; + + +/** + * Represents a world. + */ +public interface World extends WorldProperties { + /** + * Get the {@link ChunkGenerator} this world uses. + * + * @return Chunk generator. + */ + ChunkGenerator getGenerator(); + + /** + * Get the {@link BiomeProvider} this world uses. + * + * @return Biome provider. + */ + BiomeProvider getBiomeProvider(); + + /** + * Get the {@link ConfigPack} this world uses. + * + * @return Config pack. + */ + ConfigPack getPack(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/WritableWorld.java b/common/api/src/main/java/com/dfsek/terra/api/world/WritableWorld.java new file mode 100644 index 000000000..ef4ca89bb --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/WritableWorld.java @@ -0,0 +1,73 @@ +package com.dfsek.terra.api.world; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.chunk.generation.util.Column; + + +public interface WritableWorld extends ReadableWorld { + default void setBlockState(Vector3 position, BlockState data, boolean physics) { + setBlockState(position.getBlockX(), position.getBlockY(), position.getBlockZ(), data, physics); + } + + default void setBlockState(Vector3.Mutable position, BlockState data, boolean physics) { + setBlockState(position.getBlockX(), position.getBlockY(), position.getBlockZ(), data, physics); + } + + default void setBlockState(Vector3Int position, BlockState data, boolean physics) { + setBlockState(position.getX(), position.getY(), position.getZ(), data, physics); + } + + default void setBlockState(Vector3Int.Mutable position, BlockState data, boolean physics) { + setBlockState(position.getX(), position.getY(), position.getZ(), data, physics); + } + + default void setBlockState(Vector3 position, BlockState data) { + setBlockState(position, data, false); + } + + default void setBlockState(Vector3.Mutable position, BlockState data) { + setBlockState(position, data, false); + } + + default void setBlockState(Vector3Int position, BlockState data) { + setBlockState(position, data, false); + } + + default void setBlockState(Vector3Int.Mutable position, BlockState data) { + setBlockState(position, data, false); + } + + default void setBlockState(int x, int y, int z, BlockState data) { + setBlockState(x, y, z, data, false); + } + + void setBlockState(int x, int y, int z, BlockState data, boolean physics); + + + default Entity spawnEntity(Vector3 location, EntityType entityType) { + return spawnEntity(location.getX(), location.getY(), location.getZ(), entityType); + } + + Entity spawnEntity(double x, double y, double z, EntityType entityType); + + default BufferedWorld buffer(int offsetX, int offsetY, int offsetZ) { + return BufferedWorld + .builder(this) + .offsetX(offsetX) + .offsetY(offsetY) + .offsetZ(offsetZ) + .build(); + } + + default BufferedWorld.Builder buffer() { + return BufferedWorld.builder(this); + } + + default Column column(int x, int z) { + return new Column<>(x, z, this); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/Biome.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/Biome.java new file mode 100644 index 000000000..7d2ec6189 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/Biome.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.biome; + + +import java.util.Set; + +import com.dfsek.terra.api.properties.PropertyHolder; +import com.dfsek.terra.api.registry.key.StringIdentifiable; + + +/** + * Represents a Terra biome + */ +public interface Biome extends PropertyHolder, StringIdentifiable { + + /** + * Gets the platform biome this custom biome delegates to. + * + * @return The platform biome. + */ + PlatformBiome getPlatformBiome(); + + /** + * Get the color of this biome. + * + * @return ARGB color of this biome + */ + int getColor(); + + /** + * Get the tags this biome holds + * + * @return A {@link Set} of String tags this biome holds. + */ + Set getTags(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/PaletteSettings.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/PaletteSettings.java new file mode 100644 index 000000000..5bd49361e --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/PaletteSettings.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.biome; + +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + + +public interface PaletteSettings { + Palette getPalette(int y); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/PlatformBiome.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/PlatformBiome.java new file mode 100644 index 000000000..5eeff8306 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/PlatformBiome.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.biome; + +import com.dfsek.terra.api.Handle; + + +public interface PlatformBiome extends Handle { +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java new file mode 100644 index 000000000..282541720 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/BiomeProvider.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.biome.generation; + +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.biome.Biome; + +import com.dfsek.terra.api.world.info.WorldProperties; + +import org.jetbrains.annotations.Contract; + +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + + +/** + * Provides locations of biomes in a world. + */ +public interface BiomeProvider { + /** + * Get the biome at a location. + * + * @param x X coordinate + * @param y + * @param z Z coordinate + * @param seed World seed + * + * @return Biome at the location + */ + @Contract(pure = true) + Biome getBiome(int x, int y, int z, long seed); + + /** + * Get the biome at a location. + * + * @param vector3 Location + * @param seed World seed + * + * @return Biome at the location + */ + @Contract(pure = true) + default Biome getBiome(Vector3 vector3, long seed) { + return getBiome(vector3.getBlockX(), vector3.getBlockY(), vector3.getBlockZ(), seed); + } + + /** + * Get the biome at a location. + * + * @param vector3 Location + * @param seed World seed + * + * @return Biome at the location + */ + @Contract(pure = true) + default Biome getBiome(Vector3Int vector3, long seed) { + return getBiome(vector3.getX(), vector3.getY(), vector3.getZ(), seed); + } + + /** + * Get all biomes this {@link BiomeProvider} is capable of generating in the world. + *

+ * Must contain all biomes that could possibly generate. + * + * @return {@link Iterable} of all biomes this provider can generate. + */ + @Contract(pure = true) + Iterable getBiomes(); + + @Contract(pure = true) + default Stream stream() { + return StreamSupport.stream(getBiomes().spliterator(), false); + } + + default BiomeProvider caching(int minY, int maxY) { + return new CachingBiomeProvider(this, minY, maxY); + } + + default BiomeProvider caching(WorldProperties worldProperties) { + return caching(worldProperties.getMinHeight(), worldProperties.getMaxHeight()); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java new file mode 100644 index 000000000..ee2b41dbc --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/biome/generation/CachingBiomeProvider.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.api.world.biome.generation; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.util.MathUtil; +import com.dfsek.terra.api.world.biome.Biome; + +import java.util.HashMap; +import java.util.Map; + + +/** + * A biome provider implementation that lazily evaluates biomes, and caches them. + *

+ * This is for use in chunk generators, it makes the assumption that the seed remains the same for the duration of its use! + */ +public class CachingBiomeProvider implements BiomeProvider, Handle { + private final BiomeProvider delegate; + private final int minY; + private final int maxY; + private final Map cache = new HashMap<>(); + + protected CachingBiomeProvider(BiomeProvider delegate, int minY, int maxY) { + this.delegate = delegate; + this.minY = minY; + this.maxY = maxY; + } + + @Override + public BiomeProvider getHandle() { + return delegate; + } + + @Override + public Biome getBiome(int x, int y, int z, long seed) { + if(y >= maxY || y < minY) throw new IllegalArgumentException("Y out of range: " + y + " (min: " + minY + ", max: " + maxY + ")"); + Biome[] biomes = cache.computeIfAbsent(MathUtil.squash(x, z), key -> new Biome[maxY - minY]); + int yi = y - minY; + if(biomes[yi] == null) { + biomes[yi] = delegate.getBiome(x, y, z, seed); + } + return biomes[yi]; + } + + @Override + public Iterable getBiomes() { + return delegate.getBiomes(); + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/Chunk.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/Chunk.java new file mode 100644 index 000000000..303ad1e2e --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/Chunk.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk; + +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.ServerWorld; + + +public interface Chunk extends ChunkAccess { + void setBlock(int x, int y, int z, BlockState data, boolean physics); + + default void setBlock(int x, int y, int z, @NotNull BlockState data) { + setBlock(x, y, z, data, false); + } + + @NotNull BlockState getBlock(int x, int y, int z); + + int getX(); + + int getZ(); + + ServerWorld getWorld(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/ChunkAccess.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/ChunkAccess.java new file mode 100644 index 000000000..ca10c9d04 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/ChunkAccess.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk; + +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.block.state.BlockState; + + +public interface ChunkAccess extends Handle { + /** + * Set the block at x,y,z in the chunk data to material. + *

+ * Setting blocks outside the chunk's bounds does nothing. + * + * @param x the x location in the chunk from 0-15 inclusive + * @param y the y location in the chunk from 0 (inclusive) - maxHeight (exclusive) + * @param z the z location in the chunk from 0-15 inclusive + * @param blockState the type to set the block to + */ + void setBlock(int x, int y, int z, @NotNull BlockState blockState); + + /** + * Get the type and data of the block at x, y, z. + *

+ * Getting blocks outside the chunk's bounds returns air. + * + * @param x the x location in the chunk from 0-15 inclusive + * @param y the y location in the chunk from 0 (inclusive) - maxHeight (exclusive) + * @param z the z location in the chunk from 0-15 inclusive + * + * @return the data of the block or the BlockData for air if x, y or z are outside the chunk's bounds + */ + @NotNull BlockState getBlock(int x, int y, int z); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/ChunkGenerator.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/ChunkGenerator.java new file mode 100644 index 000000000..b88c8bc85 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/ChunkGenerator.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk.generation; + +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.util.vector.Vector3Int; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; +import com.dfsek.terra.api.world.info.WorldProperties; + + +public interface ChunkGenerator { + void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldProperties world, @NotNull BiomeProvider biomeProvider, + int chunkX, int chunkZ); + + BlockState getBlock(WorldProperties world, int x, int y, int z, BiomeProvider biomeProvider); + + default BlockState getBlock(WorldProperties world, Vector3 vector3, BiomeProvider biomeProvider) { + return getBlock(world, vector3.getBlockX(), vector3.getBlockY(), vector3.getBlockZ(), biomeProvider); + } + + default BlockState getBlock(WorldProperties world, Vector3Int vector3, BiomeProvider biomeProvider) { + return getBlock(world, vector3.getX(), vector3.getY(), vector3.getZ(), biomeProvider); + } + + Palette getPalette(int x, int y, int z, WorldProperties world, BiomeProvider biomeProvider); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/ProtoChunk.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/ProtoChunk.java new file mode 100644 index 000000000..2de97241c --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/ProtoChunk.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk.generation; + + +import com.dfsek.terra.api.world.chunk.ChunkAccess; + + +public interface ProtoChunk extends ChunkAccess { + /** + * Get the maximum height for the chunk. + *

+ * Setting blocks at or above this height will do nothing. + * + * @return the maximum height + */ + int getMaxHeight(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/ProtoWorld.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/ProtoWorld.java new file mode 100644 index 000000000..dd484d6fc --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/ProtoWorld.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.world.chunk.generation; + +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.WritableWorld; + + +public interface ProtoWorld extends WritableWorld { + int centerChunkX(); + + int centerChunkZ(); + + /** + * Get the world object this ProtoWorld represents + * + * Do not read from/write to this world! + * + * @return The world + */ + ServerWorld getWorld(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/stage/Chunkified.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/stage/Chunkified.java new file mode 100644 index 000000000..6d5679951 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/stage/Chunkified.java @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk.generation.stage; + +/** + * Marker interface that marks a feature as "chunkified" (only modifying one chunk at a time) + */ +public interface Chunkified { +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/stage/GenerationStage.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/stage/GenerationStage.java new file mode 100644 index 000000000..a80789926 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/stage/GenerationStage.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk.generation.stage; + +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; + + +public interface GenerationStage { + void populate(ProtoWorld world); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java new file mode 100644 index 000000000..6defa986b --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Column.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk.generation.util; + +import java.util.function.IntConsumer; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.structure.feature.BinaryColumn; +import com.dfsek.terra.api.util.function.IntToBooleanFunction; +import com.dfsek.terra.api.world.WritableWorld; + + +/** + * A single vertical column of a world. + */ +public class Column { + private final int x; + private final int z; + private final T world; + + public Column(int x, int z, T world) { + this.x = x; + this.z = z; + this.world = world; + } + + public int getX() { + return x; + } + + public int getZ() { + return z; + } + + public BlockState getBlock(int y) { + return world.getBlockState(x, y, z); + } + + public T getWorld() { + return world; + } + + public int getMinY() { + return world.getMinHeight(); + } + + public int getMaxY() { + return world.getMaxHeight(); + } + + public void forEach(IntConsumer function) { + for(int y = world.getMinHeight(); y < world.getMaxHeight(); y++) { + function.accept(y); + } + } + + public BinaryColumn newBinaryColumn(IntToBooleanFunction function) { + return new BinaryColumn(getMinY(), getMaxY(), function); + } + + public BinaryColumnBuilder newBinaryColumn() { + return new BinaryColumnBuilder(this); + } + + @SuppressWarnings("unchecked") + public Column adjacent(int offsetX, int offsetZ) { + return (Column) world.column(x + offsetX, z + offsetZ); + } + + + public static class BinaryColumnBuilder { + private final boolean[] arr; + private final Column column; + + public BinaryColumnBuilder(Column column) { + this.column = column; + arr = new boolean[column.getMaxY() - column.getMinY()]; + } + + public BinaryColumn build() { + return new BinaryColumn(column.getMinY(), column.getMaxY(), arr); + } + + public BinaryColumnBuilder set(int y) { + arr[y - column.getMinY()] = true; + return this; + } + } +} \ No newline at end of file diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/GeneratorWrapper.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/GeneratorWrapper.java new file mode 100644 index 000000000..27cda9f01 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/GeneratorWrapper.java @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk.generation.util; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; + + +public interface GeneratorWrapper extends Handle { + @Override + ChunkGenerator getHandle(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Palette.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Palette.java new file mode 100644 index 000000000..0a15b7be2 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/Palette.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk.generation.util; + +import com.dfsek.terra.api.block.state.BlockState; + + +public interface Palette { + /** + * Fetches a material from the palette, at a given layer. + * + * @param layer - The layer at which to fetch the material. + * + * @return BlockData - The material fetched. + */ + BlockState get(int layer, double x, double y, double z, long seed); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/provider/ChunkGeneratorProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/provider/ChunkGeneratorProvider.java new file mode 100644 index 000000000..32bcab044 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/provider/ChunkGeneratorProvider.java @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk.generation.util.provider; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; + + +public interface ChunkGeneratorProvider { + ChunkGenerator newInstance(ConfigPack pack); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/provider/GenerationStageProvider.java b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/provider/GenerationStageProvider.java new file mode 100644 index 000000000..eeb711f0e --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/chunk/generation/util/provider/GenerationStageProvider.java @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra API is licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in the common/api directory. + */ + +package com.dfsek.terra.api.world.chunk.generation.util.provider; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; + + +public interface GenerationStageProvider { + GenerationStage newInstance(ConfigPack pack); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/info/WorldProperties.java b/common/api/src/main/java/com/dfsek/terra/api/world/info/WorldProperties.java new file mode 100644 index 000000000..d9db43ef6 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/info/WorldProperties.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.api.world.info; + +import com.dfsek.terra.api.Handle; + + +public interface WorldProperties extends Handle { + long getSeed(); + + int getMaxHeight(); + + int getMinHeight(); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/util/Interceptors.java b/common/api/src/main/java/com/dfsek/terra/api/world/util/Interceptors.java new file mode 100644 index 000000000..c608ea4d9 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/util/Interceptors.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.api.world.util; + +public final class Interceptors { + private static final ReadInterceptor READ_THROUGH = ((x, y, z, world) -> world.getBlockState(x, y, z)); + private static final WriteInterceptor WRITE_THROUGH = ((x, y, z, block, world, physics) -> world.setBlockState(x, y, z, block, + physics)); + + private Interceptors() { + + } + + public static ReadInterceptor readThrough() { + return READ_THROUGH; + } + + public static WriteInterceptor writeThrough() { + return WRITE_THROUGH; + } +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/util/ReadInterceptor.java b/common/api/src/main/java/com/dfsek/terra/api/world/util/ReadInterceptor.java new file mode 100644 index 000000000..583cb9d8b --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/util/ReadInterceptor.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.api.world.util; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.ReadableWorld; + + +public interface ReadInterceptor { + BlockState read(int x, int y, int z, ReadableWorld world); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/world/util/WriteInterceptor.java b/common/api/src/main/java/com/dfsek/terra/api/world/util/WriteInterceptor.java new file mode 100644 index 000000000..27f4bcbe1 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/world/util/WriteInterceptor.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.api.world.util; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.WritableWorld; + + +public interface WriteInterceptor { + default void write(int x, int y, int z, BlockState block, WritableWorld world) { + write(x, y, z, block, world, false); + } + + void write(int x, int y, int z, BlockState block, WritableWorld world, boolean physics); +} diff --git a/common/build.gradle.kts b/common/build.gradle.kts deleted file mode 100644 index ca834dd81..000000000 --- a/common/build.gradle.kts +++ /dev/null @@ -1,57 +0,0 @@ -import com.dfsek.terra.configureCompilation -import com.dfsek.terra.configureDependencies - -plugins { - `java-library` - `maven-publish` - idea -} - -configureCompilation() -configureDependencies() - -group = "com.dfsek.terra.common" - -dependencies { - "shadedApi"("org.apache.commons:commons-rng-core:1.3") - "shadedApi"("commons-io:commons-io:2.4") - - "shadedApi"("com.dfsek:Paralithic:0.3.2") - "shadedApi"("com.dfsek:Tectonic:1.4.0") - "shadedApi"("net.jafama:jafama:2.3.2") - "shadedApi"("org.yaml:snakeyaml:1.27") - "shadedApi"("org.ow2.asm:asm:9.0") - "shadedApi"("commons-io:commons-io:2.6") - - "shadedApi"("com.googlecode.json-simple:json-simple:1.1.1") - "shadedApi"("org.yaml:snakeyaml:1.27") - - "compileOnly"("com.google.guava:guava:30.0-jre") - - "testImplementation"("com.google.guava:guava:30.0-jre") -} - -publishing { - publications { - create("mavenJava") { - artifact(tasks["sourcesJar"]) - artifact(tasks["jar"]) - } - } - - repositories { - val mavenUrl = "https://repo.codemc.io/repository/maven-releases/" - val mavenSnapshotUrl = "https://repo.codemc.io/repository/maven-snapshots/" - - maven(mavenUrl) { - val mavenUsername: String? by project - val mavenPassword: String? by project - if (mavenUsername != null && mavenPassword != null) { - credentials { - username = mavenUsername - password = mavenPassword - } - } - } - } -} \ No newline at end of file diff --git a/common/implementation/LICENSE b/common/implementation/LICENSE new file mode 100644 index 000000000..f288702d2 --- /dev/null +++ b/common/implementation/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/common/implementation/base/build.gradle.kts b/common/implementation/base/build.gradle.kts new file mode 100644 index 000000000..64c176c77 --- /dev/null +++ b/common/implementation/base/build.gradle.kts @@ -0,0 +1,13 @@ +dependencies { + api(project(":common:api")) + api(project(":common:implementation:bootstrap-addon-loader")) + + implementation("commons-io", "commons-io", Versions.Libraries.Internal.apacheIO) + + implementation("org.apache.commons", "commons-text", Versions.Libraries.Internal.apacheText) + implementation("com.dfsek.tectonic", "yaml", Versions.Libraries.tectonic) + + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) + + implementation("com.dfsek", "paralithic", Versions.Libraries.paralithic) +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java new file mode 100644 index 000000000..9509f38b9 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java @@ -0,0 +1,271 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra; + +import com.dfsek.tectonic.api.TypeRegistry; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.Yaml; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +import com.dfsek.terra.addon.BootstrapAddonLoader; +import com.dfsek.terra.addon.DependencySorter; +import com.dfsek.terra.addon.EphemeralAddon; +import com.dfsek.terra.addon.InternalAddon; +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.addon.bootstrap.BootstrapAddonClassLoader; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.PluginConfig; +import com.dfsek.terra.api.event.EventManager; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.inject.Injector; +import com.dfsek.terra.api.inject.impl.InjectorImpl; +import com.dfsek.terra.api.profiler.Profiler; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.registry.key.StringIdentifiable; +import com.dfsek.terra.api.util.mutable.MutableBoolean; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.config.GenericLoaders; +import com.dfsek.terra.config.PluginConfigImpl; +import com.dfsek.terra.event.EventManagerImpl; +import com.dfsek.terra.profiler.ProfilerImpl; +import com.dfsek.terra.registry.CheckedRegistryImpl; +import com.dfsek.terra.registry.LockedRegistryImpl; +import com.dfsek.terra.registry.OpenRegistryImpl; +import com.dfsek.terra.registry.master.ConfigRegistry; + + +/** + * Skeleton implementation of {@link Platform} + *

+ * Implementations must invoke {@link #load()} in their constructors. + */ +public abstract class AbstractPlatform implements Platform { + private static final Logger logger = LoggerFactory.getLogger(AbstractPlatform.class); + + private static final MutableBoolean LOADED = new MutableBoolean(false); + private final EventManager eventManager = new EventManagerImpl(); + private final ConfigRegistry configRegistry = new ConfigRegistry(); + + private final CheckedRegistry checkedConfigRegistry = new CheckedRegistryImpl<>(configRegistry); + + private final Profiler profiler = new ProfilerImpl(); + + private final GenericLoaders loaders = new GenericLoaders(this); + + private final PluginConfigImpl config = new PluginConfigImpl(); + + private final CheckedRegistry addonRegistry = new CheckedRegistryImpl<>(new OpenRegistryImpl<>(TypeKey.of(BaseAddon.class))); + + private final Registry lockedAddonRegistry = new LockedRegistryImpl<>(addonRegistry); + + public ConfigRegistry getRawConfigRegistry() { + return configRegistry; + } + + protected Iterable platformAddon() { + return Collections.emptySet(); + } + + protected void load() { + if(LOADED.get()) { + throw new IllegalStateException( + "Someone tried to initialize Terra, but Terra has already initialized. This is most likely due to a broken platform " + + "implementation, or a misbehaving mod."); + } + LOADED.set(true); + + logger.info("Initializing Terra..."); + + try(InputStream stream = getClass().getResourceAsStream("/config.yml")) { + File configFile = new File(getDataFolder(), "config.yml"); + if(!configFile.exists()) { + FileUtils.copyInputStreamToFile(stream, configFile); + } + } catch(IOException e) { + logger.error("Error loading config.yml resource from jar", e); + } + + config.load(this); // load config.yml + + if(config.dumpDefaultConfig()) { + dumpResources(); + } else { + logger.info("Skipping resource dumping."); + } + + if(config.isDebugProfiler()) { // if debug.profiler is enabled, start profiling + profiler.start(); + } + + InternalAddon internalAddon = loadAddons(); + + eventManager.getHandler(FunctionalEventHandler.class) + .register(internalAddon, PlatformInitializationEvent.class) + .then(event -> { + logger.info("Loading config packs..."); + configRegistry.loadAll(this); + logger.info("Loaded packs."); + }) + .global(); + + + logger.info("Terra addons successfully loaded."); + logger.info("Finished initialization."); + } + + protected InternalAddon loadAddons() { + List addonList = new ArrayList<>(); + + InternalAddon internalAddon = new InternalAddon(); + + addonList.add(internalAddon); + + platformAddon().forEach(addonList::add); + + BootstrapAddonLoader bootstrapAddonLoader = new BootstrapAddonLoader(); + + Path addonsFolder = getDataFolder().toPath().resolve("addons"); + + Injector platformInjector = new InjectorImpl<>(this); + platformInjector.addExplicitTarget(Platform.class); + + BootstrapAddonClassLoader bootstrapAddonClassLoader = new BootstrapAddonClassLoader(new URL[]{ }, getClass().getClassLoader()); + + bootstrapAddonLoader.loadAddons(addonsFolder, bootstrapAddonClassLoader) + .forEach(bootstrapAddon -> { + platformInjector.inject(bootstrapAddon); + + bootstrapAddon.loadAddons(addonsFolder, bootstrapAddonClassLoader) + .forEach(addonList::add); + }); + + addonList.sort(Comparator.comparing(StringIdentifiable::getID)); + if(logger.isInfoEnabled()) { + StringBuilder builder = new StringBuilder(); + builder.append("Loading ") + .append(addonList.size()) + .append(" Terra addons:"); + + for(BaseAddon addon : addonList) { + builder.append("\n ") + .append("- ") + .append(addon.getID()) + .append("@") + .append(addon.getVersion().getFormatted()); + } + + logger.info(builder.toString()); + } + + DependencySorter sorter = new DependencySorter(); + addonList.forEach(sorter::add); + sorter.sort().forEach(addon -> { + platformInjector.inject(addon); + addon.initialize(); + if(!(addon instanceof EphemeralAddon)) { // ephemeral addons exist only for version checking + addonRegistry.register(addon.key(addon.getID()), addon); + } + }); + + return internalAddon; + } + + protected void dumpResources() { + try(InputStream resourcesConfig = getClass().getResourceAsStream("/resources.yml")) { + if(resourcesConfig == null) { + logger.info("No resources config found. Skipping resource dumping."); + return; + } + String resourceYaml = IOUtils.toString(resourcesConfig, StandardCharsets.UTF_8); + Map> resources = new Yaml().load(resourceYaml); + resources.forEach((dir, entries) -> entries.forEach(entry -> { + String resourcePath = String.format("%s/%s", dir, entry); + File resource = new File(getDataFolder(), resourcePath); + if(resource.exists()) + return; // dont overwrite + logger.info("Dumping resource {}...", resource.getAbsolutePath()); + try { + resource.getParentFile().mkdirs(); + resource.createNewFile(); + } catch(IOException e) { + throw new UncheckedIOException(e); + } + logger.debug("Copying resource {}", resourcePath); + try(InputStream is = getClass().getResourceAsStream("/" + resourcePath); + OutputStream os = new FileOutputStream(resource)) { + IOUtils.copy(is, os); + } catch(IOException e) { + throw new UncheckedIOException(e); + } + })); + } catch(IOException e) { + logger.error("Error while dumping resources...", e); + } + } + + @Override + public void register(TypeRegistry registry) { + loaders.register(registry); + } + + @Override + public @NotNull PluginConfig getTerraConfig() { + return config; + } + + @Override + public @NotNull CheckedRegistry getConfigRegistry() { + return checkedConfigRegistry; + } + + @Override + public @NotNull Registry getAddons() { + return lockedAddonRegistry; + } + + @Override + public @NotNull EventManager getEventManager() { + return eventManager; + } + + @Override + public @NotNull Profiler getProfiler() { + return profiler; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/addon/DependencySorter.java b/common/implementation/base/src/main/java/com/dfsek/terra/addon/DependencySorter.java new file mode 100644 index 000000000..5b1402c44 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/addon/DependencySorter.java @@ -0,0 +1,105 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.addon; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.dfsek.terra.addon.dependency.CircularDependencyException; +import com.dfsek.terra.addon.dependency.DependencyException; +import com.dfsek.terra.addon.dependency.DependencyVersionException; +import com.dfsek.terra.api.addon.BaseAddon; + + +public class DependencySorter { + private final Map addons = new HashMap<>(); + private final Map visited = new HashMap<>(); + + private final List addonList = new ArrayList<>(); + + public void add(BaseAddon addon) { + addons.put(addon.getID(), addon); + visited.put(addon.getID(), false); + addonList.add(addon); + } + + private void sortDependencies(BaseAddon addon, List sort) { + addon.getDependencies().forEach((id, range) -> { + BaseAddon dependency = get(id, addon); + + if(!range.isSatisfiedBy(dependency.getVersion())) { + throw new DependencyVersionException( + "Addon " + addon.getID() + " specifies dependency on " + id + ", versions " + range.getFormatted() + + ", but non-matching version " + dependency.getVersion().getFormatted() + " is installed."); + } + + if(!visited.get(dependency.getID())) { // if we've not visited it yet + visited.put(dependency.getID(), true); // we've visited it now + + sortDependencies(dependency, sort); + + sort.add(dependency); // add it to the list. + } + }); + } + + private BaseAddon get(String id, BaseAddon addon) { + if(!addons.containsKey(id)) { + throw new DependencyException("Addon " + addon.getID() + " specifies dependency on " + id + ", versions " + + addon.getDependencies().get(id).getFormatted() + + ", but no such addon is installed."); + } + return addons.get(id); + } + + private void checkDependencies(BaseAddon base, BaseAddon current) { + current.getDependencies().forEach((id, range) -> { + BaseAddon dependency = get(id, current); + if(dependency.getID().equals(base.getID())) { + throw new CircularDependencyException( + "Addon " + base.getID() + " has circular dependency beginning with " + dependency.getID()); + } + checkDependencies(base, dependency); + }); + } + + public List sort() { + List sorted = new ArrayList<>(); + + for(int i = addonList.size() - 1; i >= 0; i--) { + BaseAddon addon = addonList.get(i); + + checkDependencies(addon, addon); + + addonList.remove(i); + + if(!visited.get(addon.getID())) { + sortDependencies(addon, sorted); + } + + if(!visited.get(addon.getID())) { + sorted.add(addon); + visited.put(addon.getID(), true); + } + } + + return sorted; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/addon/EphemeralAddon.java b/common/implementation/base/src/main/java/com/dfsek/terra/addon/EphemeralAddon.java new file mode 100644 index 000000000..8d269241d --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/addon/EphemeralAddon.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.addon; + +import ca.solostudios.strata.version.Version; + +import com.dfsek.terra.api.addon.BaseAddon; + + +public class EphemeralAddon implements BaseAddon { + private final Version version; + private final String id; + + public EphemeralAddon(Version version, String id) { + this.version = version; + this.id = id; + } + + @Override + public Version getVersion() { + return version; + } + + @Override + public String getID() { + return id; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/addon/InternalAddon.java b/common/implementation/base/src/main/java/com/dfsek/terra/addon/InternalAddon.java new file mode 100644 index 000000000..cdd9ac5f2 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/addon/InternalAddon.java @@ -0,0 +1,42 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.addon; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.version.Version; + +import com.dfsek.terra.api.addon.BaseAddon; + + +public class InternalAddon implements BaseAddon { + private static final Version VERSION = Versions.getVersion(1, 0, 0); + + public InternalAddon() { + + } + + @Override + public String getID() { + return "terra"; + } + + @Override + public Version getVersion() { + return VERSION; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/addon/dependency/CircularDependencyException.java b/common/implementation/base/src/main/java/com/dfsek/terra/addon/dependency/CircularDependencyException.java new file mode 100644 index 000000000..0c646d94f --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/addon/dependency/CircularDependencyException.java @@ -0,0 +1,34 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.addon.dependency; + +import java.io.Serial; + + +public class CircularDependencyException extends DependencyException { + @Serial + private static final long serialVersionUID = -6098780459461482651L; + + public CircularDependencyException(String message) { + super(message); + } + + public CircularDependencyException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/addon/dependency/DependencyException.java b/common/implementation/base/src/main/java/com/dfsek/terra/addon/dependency/DependencyException.java new file mode 100644 index 000000000..1b6ded135 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/addon/dependency/DependencyException.java @@ -0,0 +1,35 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.addon.dependency; + + +import java.io.Serial; + + +public class DependencyException extends RuntimeException { + @Serial + private static final long serialVersionUID = 4864727433635612759L; + + public DependencyException(String message) { + super(message); + } + + public DependencyException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/addon/dependency/DependencyVersionException.java b/common/implementation/base/src/main/java/com/dfsek/terra/addon/dependency/DependencyVersionException.java new file mode 100644 index 000000000..007968451 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/addon/dependency/DependencyVersionException.java @@ -0,0 +1,34 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.addon.dependency; + +import java.io.Serial; + + +public class DependencyVersionException extends DependencyException { + @Serial + private static final long serialVersionUID = 3564288935278878135L; + + public DependencyVersionException(String message) { + super(message); + } + + public DependencyVersionException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/GenericLoaders.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/GenericLoaders.java new file mode 100644 index 000000000..f4f5c6cfd --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/GenericLoaders.java @@ -0,0 +1,66 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config; + +import ca.solostudios.strata.version.Version; +import ca.solostudios.strata.version.VersionRange; +import com.dfsek.tectonic.api.TypeRegistry; + +import java.util.LinkedHashMap; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.tectonic.LoaderRegistrar; +import com.dfsek.terra.api.util.Range; +import com.dfsek.terra.api.util.collection.MaterialSet; +import com.dfsek.terra.api.util.collection.ProbabilityCollection; +import com.dfsek.terra.config.loaders.LinkedHashMapLoader; +import com.dfsek.terra.config.loaders.MaterialSetLoader; +import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader; +import com.dfsek.terra.config.loaders.RangeLoader; +import com.dfsek.terra.config.loaders.VersionLoader; +import com.dfsek.terra.config.loaders.VersionRangeLoader; + + +public class GenericLoaders implements LoaderRegistrar { + private final Platform platform; + + public GenericLoaders(Platform platform) { + this.platform = platform; + } + + @Override + public void register(TypeRegistry registry) { + registry.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader()) + .registerLoader(Range.class, new RangeLoader()) + .registerLoader(Version.class, new VersionLoader()) + .registerLoader(MaterialSet.class, new MaterialSetLoader()) + .registerLoader(VersionRange.class, new VersionRangeLoader()) + .registerLoader(LinkedHashMap.class, new LinkedHashMapLoader()); + + if(platform != null) { + registry.registerLoader(BaseAddon.class, platform.getAddons()) + .registerLoader(BlockType.class, (type, object, configLoader, depthTracker) -> platform + .getWorldHandle().createBlockState((String) object).getBlockType()) + .registerLoader(BlockState.class, (type, object, configLoader, depthTracker) -> platform + .getWorldHandle().createBlockState((String) object)); + } + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/PluginConfigImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/PluginConfigImpl.java new file mode 100644 index 000000000..ee40850d6 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/PluginConfigImpl.java @@ -0,0 +1,140 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.exception.ConfigException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.yaml.YamlConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.UncheckedIOException; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.PluginConfig; + + +@SuppressWarnings("FieldMayBeFinal") +public class PluginConfigImpl implements ConfigTemplate, PluginConfig { + private static final Logger logger = LoggerFactory.getLogger(PluginConfigImpl.class); + + @Value("debug.commands") + @Default + private boolean debugCommands = false; + + @Value("debug.profiler") + @Default + private boolean debugProfiler = false; + + @Value("debug.script") + @Default + private boolean debugScript = false; + + @Value("biome-search-resolution") + @Default + private int biomeSearch = 4; + + @Value("cache.structure") + @Default + private int structureCache = 32; + + @Value("cache.sampler") + @Default + private int samplerCache = 1024; + + @Value("cache.biome-provider") + @Default + private int providerCache = 32; + + @Value("dump-default") + @Default + private boolean dumpDefaultData = true; + + @Value("script.max-recursion") + @Default + private int maxRecursion = 1000; + + @Override + public void load(Platform platform) { + logger.info("Loading config values from config.yml"); + try(FileInputStream file = new FileInputStream(new File(platform.getDataFolder(), "config.yml"))) { + ConfigLoader loader = new ConfigLoader(); + loader.load(this, new YamlConfiguration(file, "config.yml")); + } catch(ConfigException | IOException | UncheckedIOException e) { + logger.error("Failed to load config", e); + } + + if(debugCommands) + logger.info("Debug commands enabled."); + if(debugProfiler) + logger.info("Debug profiler enabled."); + if(debugScript) + logger.info("Script debug blocks enabled."); + } + + @Override + public boolean dumpDefaultConfig() { + return dumpDefaultData; + } + + @Override + public boolean isDebugCommands() { + return debugCommands; + } + + @Override + public boolean isDebugProfiler() { + return debugProfiler; + } + + @Override + public boolean isDebugScript() { + return debugScript; + } + + @Override + public int getBiomeSearchResolution() { + return biomeSearch; + } + + @Override + public int getStructureCache() { + return structureCache; + } + + @Override + public int getSamplerCache() { + return samplerCache; + } + + @Override + public int getMaxRecursion() { + return maxRecursion; + } + + @Override + public int getProviderCache() { + return providerCache; + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/fileloaders/FolderLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/FolderLoader.java similarity index 55% rename from common/src/main/java/com/dfsek/terra/config/fileloaders/FolderLoader.java rename to common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/FolderLoader.java index f54708bff..e9e44c412 100644 --- a/common/src/main/java/com/dfsek/terra/config/fileloaders/FolderLoader.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/FolderLoader.java @@ -1,5 +1,25 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.config.fileloaders; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -9,22 +29,24 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.stream.Stream; + /** * Load all {@code *.yml} files from a {@link java.nio.file.Path}. */ -public class FolderLoader extends Loader { +public class FolderLoader extends LoaderImpl { + private static final Logger logger = LoggerFactory.getLogger(FolderLoader.class); + private final Path path; - + public FolderLoader(Path path) { this.path = path; } - + @Override public InputStream get(String singleFile) throws IOException { return new FileInputStream(new File(path.toFile(), singleFile)); } - - @Override + protected void load(String directory, String extension) { File newPath = new File(path.toFile(), directory); newPath.mkdirs(); @@ -34,11 +56,11 @@ public class FolderLoader extends Loader { String rel = newPath.toPath().relativize(file).toString(); streams.put(rel, new FileInputStream(file.toFile())); } catch(FileNotFoundException e) { - e.printStackTrace(); + logger.error("Could not find file to load", e); } }); } catch(IOException e) { - e.printStackTrace(); + logger.error("Error while loading files", e); } } } diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/LoaderImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/LoaderImpl.java new file mode 100644 index 000000000..00637240b --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/LoaderImpl.java @@ -0,0 +1,83 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.fileloaders; + +import com.dfsek.tectonic.api.exception.ConfigException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; + +import com.dfsek.terra.api.config.Loader; + + +public abstract class LoaderImpl implements Loader { + private static final Logger logger = LoggerFactory.getLogger(LoaderImpl.class); + + protected final Map streams = new HashMap<>(); + + @Override + public Loader thenNames(Consumer> consumer) throws ConfigException { + consumer.accept(new ArrayList<>(streams.keySet())); + return this; + } + + @Override + public Loader thenEntries(Consumer>> consumer) throws ConfigException { + consumer.accept(streams.entrySet()); + return this; + } + + /** + * Open a subdirectory. + * + * @param directory Directory to open + * @param extension File extension + */ + @Override + public LoaderImpl open(String directory, String extension) { + if(!streams.isEmpty()) throw new IllegalStateException("Attempted to load new directory before closing existing InputStreams"); + load(directory, extension); + return this; + } + + /** + * Close all InputStreams opened. + */ + @Override + public Loader close() { + streams.forEach((name, input) -> { + try { + input.close(); + } catch(IOException e) { + logger.error("Error occurred while loading", e); + } + }); + streams.clear(); + return this; + } + + protected abstract void load(String directory, String extension); +} diff --git a/common/src/main/java/com/dfsek/terra/config/fileloaders/ZIPLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/ZIPLoader.java similarity index 57% rename from common/src/main/java/com/dfsek/terra/config/fileloaders/ZIPLoader.java rename to common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/ZIPLoader.java index d10449a37..2b68580d9 100644 --- a/common/src/main/java/com/dfsek/terra/config/fileloaders/ZIPLoader.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/fileloaders/ZIPLoader.java @@ -1,18 +1,41 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.config.fileloaders; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -public class ZIPLoader extends Loader { - private final ZipFile file; +public class ZIPLoader extends LoaderImpl { + private static final Logger logger = LoggerFactory.getLogger(ZIPLoader.class); + + private final ZipFile file; + public ZIPLoader(ZipFile file) { this.file = file; } - + @Override public InputStream get(String singleFile) throws IOException { Enumeration entries = file.entries(); @@ -22,18 +45,17 @@ public class ZIPLoader extends Loader { } throw new IllegalArgumentException("No such file: " + singleFile); } - - @Override + protected void load(String directory, String extension) { Enumeration entries = file.entries(); while(entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); if(!entry.isDirectory() && entry.getName().startsWith(directory) && entry.getName().endsWith(extension)) { try { - String rel = entry.getName().substring(directory.length() + 1); + String rel = entry.getName().substring(directory.length()); streams.put(rel, file.getInputStream(entry)); } catch(IOException e) { - e.printStackTrace(); + logger.error("Error while loading file from zip", e); } } } diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/GenericTemplateSupplierLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/GenericTemplateSupplierLoader.java new file mode 100644 index 000000000..0c24524fb --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/GenericTemplateSupplierLoader.java @@ -0,0 +1,53 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.loaders; + +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import com.dfsek.tectonic.impl.MapConfiguration; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.Map; +import java.util.function.Supplier; + +import com.dfsek.terra.api.registry.Registry; + + +public class GenericTemplateSupplierLoader implements TypeLoader { + private final Registry>> registry; + + public GenericTemplateSupplierLoader(Registry>> registry) { + this.registry = registry; + } + + @SuppressWarnings("unchecked") + @Override + public T load(@NotNull AnnotatedType t, @NotNull Object c, ConfigLoader loader, DepthTracker depthTracker) throws LoadException { + Map map = (Map) c; + String type = (String) map.get("type"); + return loader + .load(registry.getByID(type) + .orElseThrow(() -> new LoadException("No such entry: " + map.get("type"), depthTracker)) + .get(), new MapConfiguration(map), depthTracker.intrinsic("With type \"" + type + "\"")).get(); + + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/LinkedHashMapLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/LinkedHashMapLoader.java new file mode 100644 index 000000000..a79d6418b --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/LinkedHashMapLoader.java @@ -0,0 +1,50 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.loaders; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedParameterizedType; +import java.lang.reflect.AnnotatedType; +import java.util.LinkedHashMap; +import java.util.Map; + + +@SuppressWarnings("unchecked") +public class LinkedHashMapLoader implements TypeLoader> { + @Override + public LinkedHashMap load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, + DepthTracker depthTracker) throws LoadException { + Map config = (Map) c; + LinkedHashMap map = new LinkedHashMap<>(); + if(t instanceof AnnotatedParameterizedType pType) { + AnnotatedType key = pType.getAnnotatedActualTypeArguments()[0]; + AnnotatedType value = pType.getAnnotatedActualTypeArguments()[1]; + for(Map.Entry entry : config.entrySet()) { + map.put(loader.loadType(key, entry.getKey(), depthTracker.entry(entry.getKey())), + loader.loadType(value, entry.getValue(), depthTracker.entry(entry.getKey()))); + } + } else throw new LoadException("Unable to load config", depthTracker); + + return map; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java new file mode 100644 index 000000000..1debeb906 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java @@ -0,0 +1,56 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.loaders; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.List; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.util.collection.MaterialSet; + + +@SuppressWarnings("unchecked") +public class MaterialSetLoader implements TypeLoader { + @Override + public MaterialSet load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader, DepthTracker depthTracker) + throws LoadException { + List stringData = (List) o; + + if(stringData.size() == 1) { + return MaterialSet.singleton(configLoader.loadType(BlockType.class, stringData.get(0), depthTracker)); + } + + MaterialSet set = new MaterialSet(); + + for(String string : stringData) { + try { + set.add(configLoader.loadType(BlockType.class, string, depthTracker)); + } catch(NullPointerException e) { + throw new LoadException("Invalid data identifier \"" + string + "\"", e, depthTracker); + } + } + + return set; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java new file mode 100644 index 000000000..01cda5c4b --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java @@ -0,0 +1,73 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.loaders; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedParameterizedType; +import java.lang.reflect.AnnotatedType; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import com.dfsek.terra.api.util.collection.ProbabilityCollection; + + +@SuppressWarnings("unchecked") +public class ProbabilityCollectionLoader implements TypeLoader> { + @Override + public ProbabilityCollection load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader, + DepthTracker depthTracker) throws LoadException { + ProbabilityCollection collection = new ProbabilityCollection<>(); + + if(type instanceof AnnotatedParameterizedType pType) { + AnnotatedType generic = pType.getAnnotatedActualTypeArguments()[0]; + if(o instanceof Map) { + Map map = (Map) o; + for(Map.Entry entry : map.entrySet()) { + collection.add(configLoader.loadType(generic, entry.getKey(), depthTracker.entry((String) entry.getKey())), + configLoader.loadType(Integer.class, entry.getValue(), depthTracker.entry((String) entry.getKey()))); + } + } else if(o instanceof List) { + List> map = (List>) o; + for(int i = 0; i < map.size(); i++) { + Map l = map.get(i); + for(Entry entry : l.entrySet()) { + if(entry.getValue() == null) throw new LoadException("No probability defined for entry \"" + entry.getKey() + "\"", + depthTracker); + Object val = configLoader.loadType(generic, entry.getKey(), depthTracker.index(i).entry((String) entry.getKey())); + collection.add(val, + configLoader.loadType(Integer.class, entry.getValue(), depthTracker.entry((String) entry.getKey()))); + } + } + } else if(o instanceof String) { + return new ProbabilityCollection.Singleton<>(configLoader.loadType(generic, o, depthTracker)); + } else { + throw new LoadException("Malformed Probability Collection: " + o, depthTracker); + } + } else throw new LoadException("Unable to load config! Could not retrieve parameterized type: " + type, depthTracker); + + + return collection; + } + +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java new file mode 100644 index 000000000..b4e55f935 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java @@ -0,0 +1,46 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.loaders; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.Map; + +import com.dfsek.terra.api.util.ConstantRange; +import com.dfsek.terra.api.util.Range; + + +@SuppressWarnings("unchecked") +public class RangeLoader implements TypeLoader { + @Override + public Range load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader, DepthTracker depthTracker) + throws LoadException { + if(o instanceof Map) { + Map map = (Map) o; + return new ConstantRange(map.get("min"), map.get("max")); + } else { + int h = configLoader.loadType(Integer.class, o, depthTracker); + return new ConstantRange(h, h + 1); + } + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/VersionLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/VersionLoader.java new file mode 100644 index 000000000..66a066224 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/VersionLoader.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.config.loaders; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.parser.tokenizer.ParseException; +import ca.solostudios.strata.version.Version; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; + + +public class VersionLoader implements TypeLoader { + @Override + public Version load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) + throws LoadException { + try { + return Versions.parseVersion((String) c); + } catch(ParseException e) { + throw new LoadException("Failed to parse version", e, depthTracker); + } + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/VersionRangeLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/VersionRangeLoader.java new file mode 100644 index 000000000..c4df1682c --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/VersionRangeLoader.java @@ -0,0 +1,42 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.loaders; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.parser.tokenizer.ParseException; +import ca.solostudios.strata.version.VersionRange; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; + + +public class VersionRangeLoader implements TypeLoader { + @Override + public VersionRange load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) + throws LoadException { + try { + return Versions.parseVersionRange((String) c); + } catch(ParseException e) { + throw new LoadException("Failed to parse version range: ", e, depthTracker); + } + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java new file mode 100644 index 000000000..98f24842c --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java @@ -0,0 +1,50 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.loaders.config; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.lang.reflect.AnnotatedType; + +import com.dfsek.terra.api.config.Loader; + + +public class BufferedImageLoader implements TypeLoader { + private final Loader files; + + public BufferedImageLoader(Loader files) { + this.files = files; + } + + @Override + public BufferedImage load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) + throws LoadException { + try { + return ImageIO.read(files.get((String) c)); + } catch(IOException e) { + throw new LoadException("Unable to load image", e, depthTracker); + } + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackAddonsTemplate.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackAddonsTemplate.java new file mode 100644 index 000000000..004a961c9 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackAddonsTemplate.java @@ -0,0 +1,41 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.pack; + +import ca.solostudios.strata.version.VersionRange; +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.HashMap; +import java.util.Map; + +import com.dfsek.terra.api.addon.BaseAddon; + + +@SuppressWarnings("FieldMayBeFinal") +public class ConfigPackAddonsTemplate implements ConfigTemplate { + @Value("addons") + @Default + private Map addons = new HashMap<>(); + + + public Map getAddons() { + return addons; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java new file mode 100644 index 000000000..887e697ae --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackImpl.java @@ -0,0 +1,428 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.pack; + +import ca.solostudios.strata.version.Version; +import ca.solostudios.strata.version.VersionRange; +import com.dfsek.tectonic.api.TypeRegistry; +import com.dfsek.tectonic.api.config.Configuration; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; +import com.dfsek.tectonic.api.loader.AbstractConfigLoader; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import com.dfsek.tectonic.yaml.YamlConfiguration; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Multimaps; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.config.ConfigFactory; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.ConfigType; +import com.dfsek.terra.api.config.Loader; +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.event.events.config.ConfigurationDiscoveryEvent; +import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.events.config.type.ConfigTypePostLoadEvent; +import com.dfsek.terra.api.properties.Context; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.OpenRegistry; +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.tectonic.ShortcutLoader; +import com.dfsek.terra.api.util.generic.Construct; +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.api.util.reflection.ReflectionUtil; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; +import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider; +import com.dfsek.terra.config.fileloaders.FolderLoader; +import com.dfsek.terra.config.fileloaders.ZIPLoader; +import com.dfsek.terra.config.loaders.GenericTemplateSupplierLoader; +import com.dfsek.terra.config.loaders.config.BufferedImageLoader; +import com.dfsek.terra.config.preprocessor.MetaListLikePreprocessor; +import com.dfsek.terra.config.preprocessor.MetaMapPreprocessor; +import com.dfsek.terra.config.preprocessor.MetaNumberPreprocessor; +import com.dfsek.terra.config.preprocessor.MetaStringPreprocessor; +import com.dfsek.terra.config.preprocessor.MetaValuePreprocessor; +import com.dfsek.terra.config.prototype.ProtoConfig; +import com.dfsek.terra.registry.CheckedRegistryImpl; +import com.dfsek.terra.registry.OpenRegistryImpl; +import com.dfsek.terra.registry.ShortcutHolder; + + +/** + * Represents a Terra configuration pack. + */ +public class ConfigPackImpl implements ConfigPack { + public static final TypeKey> CONFIG_TYPE_TYPE_KEY = new TypeKey<>() { + }; + private static final Logger logger = LoggerFactory.getLogger(ConfigPackImpl.class); + private final Context context = new Context(); + private final ConfigPackTemplate template = new ConfigPackTemplate(); + + private final AbstractConfigLoader abstractConfigLoader = new AbstractConfigLoader(); + private final ConfigLoader selfLoader = new ConfigLoader(); + private final Platform platform; + private final Loader loader; + + private final Map addons; + + private final BiomeProvider seededBiomeProvider; + + private final Map> registryMap = new HashMap<>(); + private final Map> shortcuts = new HashMap<>(); + + private final OpenRegistry> configTypeRegistry; + private final TreeMap>>> configTypes = new TreeMap<>(); + + private final RegistryKey key; + + public ConfigPackImpl(File folder, Platform platform) { + this(new FolderLoader(folder.toPath()), Construct.construct(() -> { + try { + return new YamlConfiguration(new FileInputStream(new File(folder, "pack.yml")), "pack.yml"); + } catch(FileNotFoundException e) { + throw new UncheckedIOException("No pack.yml file found in " + folder.getAbsolutePath(), e); + } + }), platform); + } + + public ConfigPackImpl(ZipFile file, Platform platform) { + this(new ZIPLoader(file), Construct.construct(() -> { + ZipEntry pack = null; + Enumeration entries = file.entries(); + while(entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if(entry.getName().equals("pack.yml")) pack = entry; + } + + if(pack == null) throw new IllegalArgumentException("No pack.yml file found in " + file.getName()); + + try { + return new YamlConfiguration(file.getInputStream(pack), "pack.yml"); + } catch(IOException e) { + throw new UncheckedIOException("Unable to load pack.yml from ZIP file", e); + } + }), platform); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private ConfigPackImpl(Loader loader, Configuration packManifest, Platform platform) { + long start = System.nanoTime(); + + this.loader = loader; + this.platform = platform; + this.configTypeRegistry = createConfigRegistry(); + + register(selfLoader); + platform.register(selfLoader); + + register(abstractConfigLoader); + platform.register(abstractConfigLoader); + + ConfigPackAddonsTemplate addonsTemplate = new ConfigPackAddonsTemplate(); + selfLoader.load(addonsTemplate, packManifest); + this.addons = addonsTemplate.getAddons(); + + Map configurations = discoverConfigurations(); + registerMeta(configurations); + + platform.getEventManager().callEvent( + new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, packManifest))); + + selfLoader.load(template, packManifest); + + String namespace; + String id; + if(template.getID().contains(":")) { + namespace = template.getID().substring(0, template.getID().indexOf(":")); + id = template.getID().substring(template.getID().indexOf(":") + 1); + } else { + id = template.getID(); + namespace = template.getID(); + } + + this.key = RegistryKey.of(namespace, id); + + logger.info("Loading config pack \"{}:{}\"", id, namespace); + + configTypes.values().forEach(list -> list.forEach(pair -> configTypeRegistry.register(pair.getLeft(), pair.getRight()))); + + ListMultimap, Configuration> multimap = configurations.values().parallelStream().collect( + () -> Multimaps.newListMultimap(new ConcurrentHashMap<>(), ArrayList::new), (configs, configuration) -> { + if(configuration.contains("type")) { // Only sort configs with type key + ProtoConfig config = new ProtoConfig(); + selfLoader.load(config, configuration); + configs.put(config.getType(), configuration); + } + }, ListMultimap::putAll); + + configTypeRegistry.forEach(configType -> { + CheckedRegistry registry = getCheckedRegistry(configType.getTypeKey()); + abstractConfigLoader + .loadConfigs(multimap.get(configType)) + .stream() + .parallel() + .map(configuration -> { + logger.debug("Loading abstract config {}", configuration.getID()); + Object loaded = ((ConfigFactory) configType.getFactory()).build( + selfLoader.load(configType.getTemplate(this, platform), configuration), platform); + platform.getEventManager().callEvent(new ConfigurationLoadEvent(this, + configuration, + template -> selfLoader.load(template, + configuration), + configType, + loaded)); + return Pair.of(configuration.getID(), loaded); + }) + .toList() + .forEach(pair -> registry.register(key(pair.getLeft()), pair.getRight())); + platform.getEventManager().callEvent(new ConfigTypePostLoadEvent(configType, registry, this)); + }); + + platform.getEventManager().callEvent(new ConfigPackPostLoadEvent(this, template -> selfLoader.load(template, packManifest))); + logger.info("Loaded config pack \"{}:{}\" v{} by {} in {}ms.", + namespace, id, getVersion().getFormatted(), template.getAuthor(), (System.nanoTime() - start) / 1000000.0D); + + + ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate(); + selfLoader.load(packPostTemplate, packManifest); + seededBiomeProvider = packPostTemplate.getProviderBuilder(); + checkDeadEntries(); + } + + private Map discoverConfigurations() { + Map configurations = new HashMap<>(); + platform.getEventManager().callEvent(new ConfigurationDiscoveryEvent(this, loader, + (s, c) -> configurations.put(s.replace("\\", "/"), + c))); // Create all the configs. + return configurations; + } + + private void registerMeta(Map configurations) { + MetaStringPreprocessor stringPreprocessor = new MetaStringPreprocessor(configurations); + selfLoader.registerPreprocessor(Meta.class, stringPreprocessor); + abstractConfigLoader.registerPreprocessor(Meta.class, stringPreprocessor); + + MetaListLikePreprocessor listPreprocessor = new MetaListLikePreprocessor(configurations); + selfLoader.registerPreprocessor(Meta.class, listPreprocessor); + abstractConfigLoader.registerPreprocessor(Meta.class, listPreprocessor); + + MetaMapPreprocessor mapPreprocessor = new MetaMapPreprocessor(configurations); + selfLoader.registerPreprocessor(Meta.class, mapPreprocessor); + abstractConfigLoader.registerPreprocessor(Meta.class, mapPreprocessor); + + MetaValuePreprocessor valuePreprocessor = new MetaValuePreprocessor(configurations); + selfLoader.registerPreprocessor(Meta.class, valuePreprocessor); + abstractConfigLoader.registerPreprocessor(Meta.class, valuePreprocessor); + + MetaNumberPreprocessor numberPreprocessor = new MetaNumberPreprocessor(configurations); + selfLoader.registerPreprocessor(Meta.class, numberPreprocessor); + abstractConfigLoader.registerPreprocessor(Meta.class, numberPreprocessor); + } + + @Override + public ConfigPackImpl applyLoader(Type type, TypeLoader loader) { + abstractConfigLoader.registerLoader(type, loader); + selfLoader.registerLoader(type, loader); + return this; + } + + @Override + public ConfigPackImpl applyLoader(Type type, Supplier> loader) { + abstractConfigLoader.registerLoader(type, loader); + selfLoader.registerLoader(type, loader); + return this; + } + + @Override + public void register(TypeRegistry registry) { + registry.registerLoader(ConfigType.class, configTypeRegistry) + .registerLoader(BufferedImage.class, new BufferedImageLoader(loader)); + registryMap.forEach(registry::registerLoader); + shortcuts.forEach(registry::registerLoader); // overwrite with delegated shortcuts if present + } + + @Override + public ConfigPack registerConfigType(ConfigType type, RegistryKey key, int priority) { + Set contained = new HashSet<>(); + configTypes.forEach((p, configs) -> configs.forEach(pair -> { + if(contained.contains(pair.getLeft())) throw new IllegalArgumentException("Duplicate config key: " + key); + contained.add(key); + })); + configTypes.computeIfAbsent(priority, p -> new ArrayList<>()).add(Pair.of(key, type)); + return this; + } + + @Override + public Map addons() { + return addons; + } + + @Override + public BiomeProvider getBiomeProvider() { + return seededBiomeProvider; + } + + @SuppressWarnings("unchecked") + @Override + public CheckedRegistry getOrCreateRegistry(TypeKey typeKey) { + return (CheckedRegistry) registryMap.computeIfAbsent(typeKey.getType(), c -> { + OpenRegistry registry = new OpenRegistryImpl<>(typeKey); + selfLoader.registerLoader(c, registry); + abstractConfigLoader.registerLoader(c, registry); + logger.debug("Registered loader for registry of class {}", ReflectionUtil.typeToString(c)); + + if(typeKey.getType() instanceof ParameterizedType param) { + Type base = param.getRawType(); + if(base instanceof Class // should always be true but we'll check anyways + && Supplier.class.isAssignableFrom((Class) base)) { // If it's a supplier + Type supplied = param.getActualTypeArguments()[0]; // Grab the supplied type + if(supplied instanceof ParameterizedType suppliedParam) { + Type suppliedBase = suppliedParam.getRawType(); + if(suppliedBase instanceof Class // should always be true but we'll check anyways + && ObjectTemplate.class.isAssignableFrom((Class) suppliedBase)) { + Type templateType = suppliedParam.getActualTypeArguments()[0]; + GenericTemplateSupplierLoader loader = new GenericTemplateSupplierLoader<>( + (Registry>>>>) registry); + selfLoader.registerLoader(templateType, loader); + abstractConfigLoader.registerLoader(templateType, loader); + logger.debug("Registered template loader for registry of class {}", ReflectionUtil.typeToString(templateType)); + } + } + } + } + + return new CheckedRegistryImpl<>(registry); + }); + } + + @Override + public List getStages() { + return template.getStages(); + } + + @Override + public Loader getLoader() { + return loader; + } + + @Override + public String getAuthor() { + return template.getAuthor(); + } + + @Override + public Version getVersion() { + return template.getVersion(); + } + + @SuppressWarnings("unchecked,rawtypes") + @Override + public ConfigPack registerShortcut(TypeKey clazz, String shortcut, ShortcutLoader loader) { + ShortcutHolder holder = shortcuts + .computeIfAbsent(clazz.getType(), c -> new ShortcutHolder<>(getOrCreateRegistry(clazz))) + .register(shortcut, (ShortcutLoader) loader); + selfLoader.registerLoader(clazz.getType(), holder); + abstractConfigLoader.registerLoader(clazz.getType(), holder); + return this; + } + + @Override + public ChunkGeneratorProvider getGeneratorProvider() { + return template.getGeneratorProvider(); + } + + private OpenRegistry> createConfigRegistry() { + return new OpenRegistryImpl<>(new LinkedHashMap<>(), CONFIG_TYPE_TYPE_KEY) { + @Override + public boolean register(@NotNull RegistryKey key, @NotNull ConfigType value) { + if(!registryMap + .containsKey(value.getTypeKey() + .getType())) { + OpenRegistry openRegistry = new OpenRegistryImpl<>(value.getTypeKey()); + selfLoader.registerLoader(value.getTypeKey().getType(), openRegistry); + abstractConfigLoader.registerLoader(value.getTypeKey().getType(), openRegistry); + registryMap.put(value.getTypeKey().getType(), new CheckedRegistryImpl<>(openRegistry)); + } + return super.register(key, value); + } + }; + } + + private void checkDeadEntries() { + registryMap.forEach((clazz, pair) -> ((OpenRegistryImpl) pair.getRegistry()) + .getDeadEntries() + .forEach((id, value) -> logger.debug("Dead entry in '{}' registry: '{}'", ReflectionUtil.typeToString(clazz), id))); + } + + public ConfigPackTemplate getTemplate() { + return template; + } + + @Override + @SuppressWarnings("unchecked") + public CheckedRegistry getRegistry(Type type) { + return (CheckedRegistry) registryMap.get(type); + } + + @SuppressWarnings("unchecked") + @Override + public CheckedRegistry getCheckedRegistry(Type type) throws IllegalStateException { + return (CheckedRegistry) registryMap.get(type); + } + + @Override + public RegistryKey getRegistryKey() { + return key; + } + + @Override + public Context getContext() { + return context; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java new file mode 100644 index 000000000..cfa166a40 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java @@ -0,0 +1,34 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.pack; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; + + +public class ConfigPackPostTemplate implements ConfigTemplate { + @Value("biomes") + private @Meta BiomeProvider providerBuilder; + + public BiomeProvider getProviderBuilder() { + return providerBuilder; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java new file mode 100644 index 000000000..b41005a25 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java @@ -0,0 +1,185 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.pack; + +import ca.solostudios.strata.version.Version; +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; +import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider; + + +@SuppressWarnings({ "unused", "FieldMayBeFinal" }) +public class ConfigPackTemplate implements ConfigTemplate { + @Value("id") + private String id; + + @Value("variables") + @Default + private @Meta Map variables = new HashMap<>(); + + @Value("beta.carving") + @Default + private @Meta boolean betaCarvers = false; + + @Value("structures.locatable") + @Default + private @Meta Map<@Meta String, @Meta String> locatable = new HashMap<>(); + + @Value("blend.terrain.elevation") + @Default + private @Meta int elevationBlend = 4; + + @Value("vanilla.mobs") + @Default + private @Meta boolean vanillaMobs = true; + + @Value("vanilla.caves") + @Default + private @Meta boolean vanillaCaves = false; + + @Value("vanilla.decorations") + @Default + private @Meta boolean vanillaDecorations = false; + + @Value("vanilla.structures") + @Default + private @Meta boolean vanillaStructures = false; + + @Value("author") + @Default + private String author = "Anon Y. Mous"; + + @Value("disable.sapling") + @Default + private @Meta boolean disableSaplings = false; + + @Value("stages") + @Default + private @Meta List<@Meta GenerationStage> stages = Collections.emptyList(); + + @Value("version") + private Version version; + + @Value("disable.carvers") + @Default + private @Meta boolean disableCarvers = false; + + @Value("disable.structures") + @Default + private @Meta boolean disableStructures = false; + + @Value("disable.ores") + @Default + private @Meta boolean disableOres = false; + + @Value("disable.trees") + @Default + private @Meta boolean disableTrees = false; + + @Value("disable.flora") + @Default + private @Meta boolean disableFlora = false; + + @Value("generator") + private @Meta ChunkGeneratorProvider generatorProvider; + + public boolean disableCarvers() { + return disableCarvers; + } + + public boolean disableFlora() { + return disableFlora; + } + + public boolean disableOres() { + return disableOres; + } + + public boolean disableStructures() { + return disableStructures; + } + + public boolean disableTrees() { + return disableTrees; + } + + public boolean vanillaMobs() { + return vanillaMobs; + } + + public boolean vanillaCaves() { + return vanillaCaves; + } + + public boolean vanillaDecorations() { + return vanillaDecorations; + } + + public boolean vanillaStructures() { + return vanillaStructures; + } + + public boolean doBetaCarvers() { + return betaCarvers; + } + + public ChunkGeneratorProvider getGeneratorProvider() { + return generatorProvider; + } + + public List getStages() { + return stages; + } + + public Version getVersion() { + return version; + } + + public boolean isDisableSaplings() { + return disableSaplings; + } + + public String getID() { + return id; + } + + public String getAuthor() { + return author; + } + + public Map getVariables() { + return variables; + } + + public int getElevationBlend() { + return elevationBlend; + } + + public Map getLocatable() { + return locatable; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaListLikePreprocessor.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaListLikePreprocessor.java new file mode 100644 index 000000000..38f754cf7 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaListLikePreprocessor.java @@ -0,0 +1,106 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.preprocessor; + +import com.dfsek.tectonic.api.config.Configuration; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.depth.IndexLevel; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.preprocessor.Result; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.generic.pair.Pair; + + +public class MetaListLikePreprocessor extends MetaPreprocessor { + public MetaListLikePreprocessor(Map configs) { + super(configs); + } + + @SuppressWarnings("unchecked") + @Override + public @NotNull Result process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation, DepthTracker depthTracker) { + if(t.getType() instanceof ParameterizedType parameterizedType) { + if(parameterizedType.getRawType() instanceof Class baseClass) { // Should always be true but we check anyways + + if((List.class.isAssignableFrom(baseClass) || Set.class.isAssignableFrom(baseClass)) && + c instanceof List) { // List or set metaconfig + List list = (List) c; + + int offset = 0; + List newList = new ArrayList<>((List) c); + + for(int i = 0; i < list.size(); i++) { + Object o = list.get(i); + if(!(o instanceof String)) continue; + String s = ((String) o).trim(); + if(!s.startsWith("<< ")) continue; + String meta = s.substring(3); + + + Pair pair = getMetaValue(meta, depthTracker); + Object metaValue = pair.getRight(); + + if(!(metaValue instanceof List)) { + throw new LoadException( + "MetaList/Set injection candidate must be list, is type " + metaValue.getClass().getCanonicalName(), + depthTracker); + } + + List metaList = (List) metaValue; + + newList.remove(i + offset); // Remove placeholder + newList.addAll(i + offset, metaList); // Add metalist values where placeholder was + + int begin = i + offset; + offset += metaList.size() - 1; // add metalist size to offset, subtract one to account for placeholder. + int end = i + offset; + depthTracker.addIntrinsicLevel(level -> { + if(level instanceof IndexLevel indexLevel && + indexLevel.getIndex() >= begin && + indexLevel.getIndex() <= end) { + String configName; + if(pair.getLeft().getName() == null) { + configName = "Anonymous Configuration"; + } else { + configName = pair.getLeft().getName(); + } + return Optional.of("From configuration \"" + configName + "\""); + } + return Optional.empty(); + }); + } + + return (Result) Result.overwrite(newList, depthTracker); + } + } + } + + return Result.noOp(); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaMapPreprocessor.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaMapPreprocessor.java new file mode 100644 index 000000000..f4953ca6e --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaMapPreprocessor.java @@ -0,0 +1,95 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.preprocessor; + +import com.dfsek.tectonic.api.config.Configuration; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.depth.EntryLevel; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.preprocessor.Result; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.ParameterizedType; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class MetaMapPreprocessor extends MetaPreprocessor { + private static final TypeKey> STRING_LIST = new TypeKey<>() { + }; + + public MetaMapPreprocessor(Map configs) { + super(configs); + } + + @SuppressWarnings("unchecked") + @Override + public @NotNull Result process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation, DepthTracker depthTracker) { + if(t.getType() instanceof ParameterizedType parameterizedType) { + if(parameterizedType.getRawType() instanceof Class baseClass) { // Should always be true but we check anyways + + if(Map.class.isAssignableFrom(baseClass) && c instanceof Map) { // Map metaconfig + Map map = (Map) c; + + if(map.containsKey("<<")) { + Map newMap = new HashMap<>(map); + + List keys = (List) loader.loadType(STRING_LIST.getAnnotatedType(), map.get("<<"), depthTracker); + keys.forEach(key -> { + Pair pair = getMetaValue(key, depthTracker); + Object meta = pair.getRight(); + if(!(meta instanceof Map)) { + throw new LoadException( + "MetaMap injection candidate must be list, is type " + meta.getClass().getCanonicalName(), + depthTracker); + } + newMap.putAll((Map) meta); + + String configName; + if(pair.getLeft().getName() == null) { + configName = "Anonymous Configuration"; + } else { + configName = pair.getLeft().getName(); + } + + depthTracker.addIntrinsicLevel(level -> { + if(level instanceof EntryLevel entryLevel && ((Map) meta).containsKey(entryLevel.getName())) { + return Optional.of("From configuration \"" + configName + "\""); + } + return Optional.empty(); + }); + }); + newMap.putAll(map); + newMap.remove("<<"); // Remove placeholder + return (Result) Result.overwrite(newMap, depthTracker); + } + } + } + } + + return Result.noOp(); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaNumberPreprocessor.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaNumberPreprocessor.java new file mode 100644 index 000000000..543e2b862 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaNumberPreprocessor.java @@ -0,0 +1,66 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.preprocessor; + +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.tokenizer.ParseException; +import com.dfsek.tectonic.api.config.Configuration; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.preprocessor.Result; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.Map; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class MetaNumberPreprocessor extends MetaPreprocessor { + public static final TypeKey META_STRING_KEY = new TypeKey<@Meta String>() { + }; + + public MetaNumberPreprocessor(Map configs) { + super(configs); + } + + private static boolean isNumber(Class clazz) { + return Number.class.isAssignableFrom(clazz) + || byte.class.equals(clazz) + || int.class.equals(clazz) + || long.class.equals(clazz) + || float.class.equals(clazz) + || double.class.equals(clazz); + } + + @SuppressWarnings("unchecked") + @Override + public @NotNull Result process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation, DepthTracker depthTracker) { + if(t.getType() instanceof Class && isNumber((Class) t.getType()) && c instanceof String) { + String expression = (String) loader.loadType(META_STRING_KEY.getAnnotatedType(), c, depthTracker); + try { + return (Result) Result.overwrite(new Parser().eval(expression), depthTracker); + } catch(ParseException e) { + throw new LoadException("Invalid expression: ", e, depthTracker); + } + } + return Result.noOp(); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaPreprocessor.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaPreprocessor.java new file mode 100644 index 000000000..5ed605845 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaPreprocessor.java @@ -0,0 +1,53 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.preprocessor; + +import com.dfsek.tectonic.api.config.Configuration; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.preprocessor.ValuePreprocessor; + +import java.lang.annotation.Annotation; +import java.util.Map; + +import com.dfsek.terra.api.util.generic.pair.Pair; + + +public abstract class MetaPreprocessor implements ValuePreprocessor { + private final Map configs; + + public MetaPreprocessor(Map configs) { + this.configs = configs; + } + + protected Pair getMetaValue(String meta, DepthTracker depthTracker) { + int sep = meta.indexOf(':'); + String file = meta.substring(0, sep); + String key = meta.substring(sep + 1); + + if(!configs.containsKey(file)) throw new LoadException("Cannot fetch metavalue: No such config: " + file, depthTracker); + + Configuration config = configs.get(file); + + if(!config.contains(key)) { + throw new LoadException("Cannot fetch metavalue: No such key " + key + " in configuration " + config.getName(), depthTracker); + } + + return Pair.of(config, config.get(key)); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaStringPreprocessor.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaStringPreprocessor.java new file mode 100644 index 000000000..c23bbb287 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaStringPreprocessor.java @@ -0,0 +1,57 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.preprocessor; + +import com.dfsek.tectonic.api.config.Configuration; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.preprocessor.Result; +import org.apache.commons.text.StringSubstitutor; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.Map; + +import com.dfsek.terra.api.config.meta.Meta; + + +public class MetaStringPreprocessor extends MetaPreprocessor { + public MetaStringPreprocessor(Map configs) { + super(configs); + } + + @SuppressWarnings("unchecked") + @Override + public @NotNull Result process(AnnotatedType t, T c, ConfigLoader loader, Meta annotation, DepthTracker depthTracker) { + if(String.class.equals(t.getType()) && c instanceof String candidate) { // String is final so we use #equals + StringSubstitutor substitutor = new StringSubstitutor(key -> { + Object meta = getMetaValue(key, depthTracker).getRight(); + if(!(meta instanceof String) && !(meta instanceof Number) && !(meta instanceof Character) && !(meta instanceof Boolean)) { + throw new LoadException("MetaString template injection candidate must be string or primitive, is type " + + meta.getClass().getCanonicalName(), depthTracker); + } + return meta.toString(); + }); + return (Result) Result.overwrite(substitutor.replace(candidate), depthTracker); + } + return Result.noOp(); + } + + +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaValuePreprocessor.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaValuePreprocessor.java new file mode 100644 index 000000000..94997ca5b --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaValuePreprocessor.java @@ -0,0 +1,60 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.preprocessor; + +import com.dfsek.tectonic.api.config.Configuration; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.preprocessor.Result; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.Map; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.generic.pair.Pair; + + +public class MetaValuePreprocessor extends MetaPreprocessor { + + public MetaValuePreprocessor(Map configs) { + super(configs); + } + + @SuppressWarnings("unchecked") + @Override + public @NotNull Result process(AnnotatedType t, T c, ConfigLoader configLoader, Meta annotation, DepthTracker depthTracker) { + if(c instanceof String) { // Can we do standard metaconfig? + String value = ((String) c).trim(); + if(value.startsWith("$") // it's a meta value. + && !value.startsWith("${")) { // it's not a meta string template. + Pair pair = getMetaValue(value.substring(1), depthTracker); + + String configName; + if(pair.getLeft().getName() == null) { + configName = "Anonymous Configuration"; + } else { + configName = pair.getLeft().getName(); + } + + return (Result) Result.overwrite(pair.getRight(), depthTracker.intrinsic("From configuration \"" + configName + "\"")); + } + } + return Result.noOp(); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/prototype/ProtoConfig.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/prototype/ProtoConfig.java new file mode 100644 index 000000000..928aaaf72 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/prototype/ProtoConfig.java @@ -0,0 +1,41 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.config.prototype; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.api.config.ConfigType; + + +public class ProtoConfig implements ConfigTemplate { + @Value("id") + private String id; + + @Value("type") + private ConfigType type; + + + public String getId() { + return id; + } + + public ConfigType getType() { + return type; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/event/EventContextImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/event/EventContextImpl.java new file mode 100644 index 000000000..891102e2b --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/event/EventContextImpl.java @@ -0,0 +1,102 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.event; + +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.Event; +import com.dfsek.terra.api.event.events.FailThroughEvent; +import com.dfsek.terra.api.event.functional.EventContext; +import com.dfsek.terra.api.util.reflection.ReflectionUtil; + + +public class EventContextImpl implements EventContext, Comparable> { + private final List> actions = new ArrayList<>(); + private final BaseAddon addon; + private final Type eventType; + private final FunctionalEventHandlerImpl parent; + private int priority; + private boolean failThrough = false; + private boolean global = false; + + public EventContextImpl(BaseAddon addon, Type eventType, FunctionalEventHandlerImpl parent) { + this.addon = addon; + this.eventType = eventType; + this.parent = parent; + } + + public void handle(T event) { + actions.forEach(action -> action.accept(event)); + } + + @Override + public EventContext then(Consumer action) { + actions.add(action); + return this; + } + + @Override + public EventContext priority(int priority) { + this.priority = priority; + parent.recomputePriorities(eventType); + return this; + } + + @Override + public EventContext failThrough() { + if(!FailThroughEvent.class.isAssignableFrom(ReflectionUtil.getRawType(eventType))) { + throw new IllegalStateException( + "Cannot fail-through on event which does not implement FailThroughEvent: " + ReflectionUtil.typeToString(eventType)); + } + this.failThrough = true; + return this; + } + + @Override + public EventContext global() { + this.global = true; + return this; + } + + @Override + public int compareTo(@NotNull EventContextImpl o) { + return this.priority - o.priority; + } + + public boolean isGlobal() { + return global; + } + + public int getPriority() { + return priority; + } + + public BaseAddon getAddon() { + return addon; + } + + public boolean isFailThrough() { + return failThrough; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/event/EventManagerImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/event/EventManagerImpl.java new file mode 100644 index 000000000..80a50785f --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/event/EventManagerImpl.java @@ -0,0 +1,54 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.event; + +import java.util.HashMap; +import java.util.Map; + +import com.dfsek.terra.api.event.EventHandler; +import com.dfsek.terra.api.event.EventManager; +import com.dfsek.terra.api.event.events.Event; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; + + +public class EventManagerImpl implements EventManager { + private final Map, EventHandler> handlers = new HashMap<>(); + + public EventManagerImpl() { + registerHandler(FunctionalEventHandler.class, new FunctionalEventHandlerImpl()); // default handler + } + + @Override + public T callEvent(T event) { + handlers.values().forEach(handler -> handler.handle(event)); + return event; + } + + @Override + public void registerHandler(Class clazz, T handler) { + handlers.put(clazz, handler); + } + + @SuppressWarnings("unchecked") + @Override + public T getHandler(Class clazz) { + return (T) handlers.computeIfAbsent(clazz, c -> { + throw new IllegalArgumentException("No event handler registered for class " + clazz.getCanonicalName()); + }); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/event/FunctionalEventHandlerImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/event/FunctionalEventHandlerImpl.java new file mode 100644 index 000000000..3ba854a3e --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/event/FunctionalEventHandlerImpl.java @@ -0,0 +1,84 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.event; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.Event; +import com.dfsek.terra.api.event.events.FailThroughEvent; +import com.dfsek.terra.api.event.events.PackEvent; +import com.dfsek.terra.api.event.functional.EventContext; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +public class FunctionalEventHandlerImpl implements FunctionalEventHandler { + private static final Logger logger = LoggerFactory.getLogger(FunctionalEventHandlerImpl.class); + + private final Map>> contextMap = new HashMap<>(); + + @SuppressWarnings("unchecked") + @Override + public void handle(Event event) { + contextMap.getOrDefault(event.getClass(), Collections.emptyList()).forEach(context -> { + try { + if(event instanceof PackEvent) { + if((context.isGlobal() || ((PackEvent) event).getPack().addons().containsKey(context.getAddon()))) { + ((EventContextImpl) context).handle(event); + } + } else { + ((EventContextImpl) context).handle(event); + } + } catch(Exception e) { + if(context.isFailThrough() && event instanceof FailThroughEvent) + throw e; // Rethrow if it's fail-through. + // else warn + logger.warn("Exception occurred during event handling. Report this to the maintainers of {}@{}", + context.getAddon().getID(), context.getAddon().getVersion().getFormatted(), e); + } + }); + } + + @Override + public EventContext register(BaseAddon addon, Class clazz) { + EventContextImpl eventContext = new EventContextImpl<>(addon, clazz, this); + contextMap.computeIfAbsent(clazz, c -> new ArrayList<>()).add(eventContext); + return eventContext; + } + + @Override + public EventContext register(BaseAddon addon, TypeKey clazz) { + EventContextImpl eventContext = new EventContextImpl<>(addon, clazz.getType(), this); + contextMap.computeIfAbsent(clazz.getType(), c -> new ArrayList<>()).add(eventContext); + return eventContext; + } + + public void recomputePriorities(Type target) { + contextMap.get(target).sort(Comparator.naturalOrder()); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/profiler/Frame.java b/common/implementation/base/src/main/java/com/dfsek/terra/profiler/Frame.java new file mode 100644 index 000000000..0b4d2dae5 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/profiler/Frame.java @@ -0,0 +1,41 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.profiler; + +public class Frame { + private final String id; + private final long start; + + public Frame(String id) { + this.id = id; + this.start = System.nanoTime(); + } + + @Override + public String toString() { + return id; + } + + public String getId() { + return id; + } + + public long getStart() { + return start; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java new file mode 100644 index 000000000..7da799e68 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java @@ -0,0 +1,125 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.profiler; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Stack; + +import com.dfsek.terra.api.profiler.Profiler; +import com.dfsek.terra.api.profiler.Timings; +import com.dfsek.terra.api.util.mutable.MutableInteger; +import com.dfsek.terra.profiler.exception.MalformedStackException; + + +public class ProfilerImpl implements Profiler { + private static final Logger logger = LoggerFactory.getLogger(ProfilerImpl.class); + + private static final ThreadLocal> THREAD_STACK = ThreadLocal.withInitial(Stack::new); + private static final ThreadLocal>> TIMINGS = ThreadLocal.withInitial(HashMap::new); + private static final ThreadLocal SAFE = ThreadLocal.withInitial(() -> false); + private static final ThreadLocal STACK_SIZE = ThreadLocal.withInitial(() -> new MutableInteger(0)); + private static boolean instantiated = false; + private final List>> accessibleThreadMaps = new ArrayList<>(); + private volatile boolean running = false; + + public ProfilerImpl() { + if(instantiated) + throw new IllegalStateException("Only one instance of Profiler may exist!"); + instantiated = true; + } + + @Override + public void push(String frame) { + if(running) { + STACK_SIZE.get().increment(); + if(SAFE.get()) { + Stack stack = THREAD_STACK.get(); + stack.push(new Frame(stack.isEmpty() ? frame : stack.peek().getId() + "." + frame)); + } else SAFE.set(false); + } else SAFE.set(false); + } + + @Override + public void pop(String frame) { + if(running) { + MutableInteger size = STACK_SIZE.get(); + size.decrement(); + if(SAFE.get()) { + long time = System.nanoTime(); + Stack stack = THREAD_STACK.get(); + + Map> timingsMap = TIMINGS.get(); + + if(timingsMap.isEmpty()) { + synchronized(accessibleThreadMaps) { + accessibleThreadMaps.add(timingsMap); + } + } + + Frame top = stack.pop(); + if(!stack.isEmpty() ? !top.getId().endsWith("." + frame) : !top.getId().equals(frame)) + throw new MalformedStackException("Expected " + frame + ", found " + top); + + List timings = timingsMap.computeIfAbsent(top.getId(), id -> new ArrayList<>()); + + timings.add(time - top.getStart()); + } + if(size.get() == 0) SAFE.set(true); + } + } + + @Override + public void start() { + logger.info("Starting Terra profiler"); + running = true; + } + + @Override + public void stop() { + logger.info("Stopping Terra profiler"); + running = false; + } + + @Override + public void reset() { + logger.info("Resetting Terra profiler"); + accessibleThreadMaps.forEach(Map::clear); + } + + @Override + public Map getTimings() { + Map map = new HashMap<>(); + synchronized(accessibleThreadMaps) { + accessibleThreadMaps.forEach(smap -> smap.forEach((key, list) -> { + String[] keys = key.split("\\."); + Timings timings = map.computeIfAbsent(keys[0], id -> new Timings()); + for(int i = 1; i < keys.length; i++) { + timings = timings.getSubItem(keys[i]); + } + new ArrayList<>(list).forEach(timings::addTime); + })); + } + return map; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/profiler/exception/MalformedStackException.java b/common/implementation/base/src/main/java/com/dfsek/terra/profiler/exception/MalformedStackException.java new file mode 100644 index 000000000..3578d80e0 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/profiler/exception/MalformedStackException.java @@ -0,0 +1,38 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.profiler.exception; + +import java.io.Serial; + + +public class MalformedStackException extends ProfilerException { + @Serial + private static final long serialVersionUID = -3009539681021691054L; + + public MalformedStackException(String message) { + super(message); + } + + public MalformedStackException(String message, Throwable cause) { + super(message, cause); + } + + public MalformedStackException(Throwable cause) { + super(cause); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/profiler/exception/ProfilerException.java b/common/implementation/base/src/main/java/com/dfsek/terra/profiler/exception/ProfilerException.java new file mode 100644 index 000000000..8a839249f --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/profiler/exception/ProfilerException.java @@ -0,0 +1,38 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.profiler.exception; + +import java.io.Serial; + + +public class ProfilerException extends RuntimeException { + @Serial + private static final long serialVersionUID = 8206737998791649002L; + + public ProfilerException(String message) { + super(message); + } + + public ProfilerException(String message, Throwable cause) { + super(message, cause); + } + + public ProfilerException(Throwable cause) { + super(cause); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/registry/CheckedRegistryImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/registry/CheckedRegistryImpl.java new file mode 100644 index 000000000..13e849675 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/registry/CheckedRegistryImpl.java @@ -0,0 +1,108 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.registry; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import org.jetbrains.annotations.ApiStatus.Internal; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.OpenRegistry; +import com.dfsek.terra.api.registry.exception.DuplicateEntryException; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +/** + * Wrapper for a registry that ensures checked additions. + * + * @param Type in registry + */ +public class CheckedRegistryImpl implements CheckedRegistry { + private final OpenRegistry registry; + + public CheckedRegistryImpl(OpenRegistry registry) { + this.registry = registry; + } + + @Internal + public OpenRegistry getRegistry() { + return registry; + } + + @Override + public void register(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException { + registry.registerChecked(identifier, value); + } + + @Override + public Optional get(@NotNull RegistryKey key) { + return registry.get(key); + } + + @Override + public boolean contains(@NotNull RegistryKey key) { + return registry.contains(key); + } + + @Override + public void forEach(@NotNull Consumer consumer) { + registry.forEach(consumer); + } + + @Override + public void forEach(@NotNull BiConsumer consumer) { + registry.forEach(consumer); + } + + @Override + public @NotNull Collection entries() { + return registry.entries(); + } + + @Override + public @NotNull Set keys() { + return registry.keys(); + } + + @Override + public TypeKey getType() { + return registry.getType(); + } + + @Override + public Map getMatches(String id) { + return registry.getMatches(id); + } + + @Override + public T load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) + throws LoadException { + return registry.load(t, c, loader, depthTracker); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/registry/LockedRegistryImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/registry/LockedRegistryImpl.java new file mode 100644 index 000000000..977979148 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/registry/LockedRegistryImpl.java @@ -0,0 +1,95 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.registry; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +/** + * Wrapper for a registry that forbids all write access. + * + * @param Type in registry + */ +public class LockedRegistryImpl implements Registry { + private final Registry registry; + + public LockedRegistryImpl(Registry registry) { + this.registry = registry; + } + + @Override + public Optional get(@NotNull RegistryKey key) { + return registry.get(key); + } + + @Override + public boolean contains(@NotNull RegistryKey key) { + return registry.contains(key); + } + + @Override + public void forEach(@NotNull Consumer consumer) { + registry.forEach(consumer); + } + + @Override + public void forEach(@NotNull BiConsumer consumer) { + registry.forEach(consumer); + } + + @Override + public @NotNull Collection entries() { + return registry.entries(); + } + + @Override + public @NotNull Set keys() { + return registry.keys(); + } + + @Override + public TypeKey getType() { + return registry.getType(); + } + + @Override + public Map getMatches(String id) { + return registry.getMatches(id); + } + + @Override + public T load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) + throws LoadException { + return registry.load(t, c, loader, depthTracker); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/registry/OpenRegistryImpl.java b/common/implementation/base/src/main/java/com/dfsek/terra/registry/OpenRegistryImpl.java new file mode 100644 index 000000000..d02ba1172 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/registry/OpenRegistryImpl.java @@ -0,0 +1,185 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.registry; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Multimaps; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import com.dfsek.terra.api.registry.OpenRegistry; +import com.dfsek.terra.api.registry.exception.DuplicateEntryException; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.api.util.reflection.TypeKey; + + +/** + * Registry implementation with read/write access. For internal use only. + * + * @param + */ +public class OpenRegistryImpl implements OpenRegistry { + private static final Entry NULL = new Entry<>(null); + private final Map> objects; + private final ListMultimap>> objectIDs = Multimaps.newListMultimap(new HashMap<>(), ArrayList::new); + private final TypeKey typeKey; + + public OpenRegistryImpl(TypeKey typeKey) { + this(new HashMap<>(), typeKey); + } + + protected OpenRegistryImpl(Map> init, TypeKey typeKey) { + this.objects = init; + this.typeKey = typeKey; + } + + @Override + public T load(@NotNull AnnotatedType type, @NotNull Object o, @NotNull ConfigLoader configLoader, DepthTracker depthTracker) + throws LoadException { + return getByID((String) o).orElseThrow(() -> new LoadException("No such " + type.getType().getTypeName() + " matching \"" + o + + "\" was found in this registry. Registry contains items: " + + getItemsFormatted(), depthTracker)); + } + + private String getItemsFormatted() { + if(objects.isEmpty()) { + return "[ ]"; + } + return objects + .keySet() + .stream() + .map(RegistryKey::toString) + .sorted() + .reduce("", (a, b) -> a + "\n - " + b); + } + + @Override + public boolean register(@NotNull RegistryKey identifier, @NotNull T value) { + return register(identifier, new Entry<>(value)); + } + + @Override + public void registerChecked(@NotNull RegistryKey identifier, @NotNull T value) throws DuplicateEntryException { + if(objects.containsKey(identifier)) + throw new DuplicateEntryException("Value with identifier \"" + identifier + "\" is already defined in registry."); + register(identifier, value); + } + + @Override + public void clear() { + objects.clear(); + objectIDs.clear(); + } + + private boolean register(RegistryKey identifier, Entry value) { + boolean exists = objects.containsKey(identifier); + objects.put(identifier, value); + objectIDs.put(identifier.getID(), Pair.of(identifier, value)); + return exists; + } + + @SuppressWarnings("unchecked") + @Override + public Optional get(@NotNull RegistryKey key) { + return Optional.ofNullable(objects.getOrDefault(key, (Entry) NULL).getValue()); + } + + @Override + public boolean contains(@NotNull RegistryKey key) { + return objects.containsKey(key); + } + + @Override + public void forEach(@NotNull Consumer consumer) { + objects.forEach((id, obj) -> consumer.accept(obj.getRaw())); + } + + @Override + public void forEach(@NotNull BiConsumer consumer) { + objects.forEach((id, entry) -> consumer.accept(id, entry.getRaw())); + } + + @Override + public @NotNull Collection entries() { + return objects.values().stream().map(Entry::getRaw).collect(Collectors.toList()); + } + + @Override + public @NotNull Set keys() { + return objects.keySet(); + } + + @Override + public TypeKey getType() { + return typeKey; + } + + @Override + public Map getMatches(String id) { + return objectIDs + .get(id) + .stream() + .collect(HashMap::new, (map, pair) -> map.put(pair.getLeft(), pair.getRight().getValue()), Map::putAll); + } + + public Map getDeadEntries() { + Map dead = new HashMap<>(); + objects.forEach((id, entry) -> { + if(entry.dead()) dead.put(id, entry.value); // dont increment value here. + }); + return dead; + } + + + private static final class Entry { + private final T value; + private final AtomicInteger access = new AtomicInteger(0); + + public Entry(T value) { + this.value = value; + } + + public boolean dead() { + return access.get() == 0; + } + + public T getValue() { + access.incrementAndGet(); + return value; + } + + private T getRaw() { + return value; + } + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/registry/ShortcutHolder.java b/common/implementation/base/src/main/java/com/dfsek/terra/registry/ShortcutHolder.java new file mode 100644 index 000000000..8330a959b --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/registry/ShortcutHolder.java @@ -0,0 +1,50 @@ +package com.dfsek.terra.registry; + +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.AnnotatedType; +import java.util.HashMap; +import java.util.Map; + +import com.dfsek.terra.api.registry.Registry; +import com.dfsek.terra.api.tectonic.ShortcutLoader; + + +public class ShortcutHolder implements TypeLoader { + private final Map> shortcuts = new HashMap<>(); + private final Registry back; + + public ShortcutHolder(Registry back) { + this.back = back; + } + + public ShortcutHolder register(String id, ShortcutLoader loader) { + if(shortcuts.containsKey(id)) { + throw new IllegalArgumentException( + "Attempted to register duplicate shortcut " + id + ", previously registered to " + shortcuts.get(id) + .getClass() + .getCanonicalName()); + } + shortcuts.put(id, loader); + return this; + } + + @Override + public T load(@NotNull AnnotatedType annotatedType, @NotNull Object o, @NotNull ConfigLoader configLoader, DepthTracker depthTracker) + throws LoadException { + String id = (String) o; + if(id.contains(":")) { + String shortcut = id.substring(0, id.indexOf(":")); + if(shortcuts.containsKey(shortcut)) { + return shortcuts.get(shortcut).load(configLoader, id.substring(id.indexOf(":") + 1), + depthTracker.intrinsic("Using shortcut \"" + shortcut + "\"")); + } + throw new LoadException("Shortcut \"" + shortcut + "\" is not defined.", depthTracker); + } + return back.load(annotatedType, o, configLoader, depthTracker); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java b/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java new file mode 100644 index 000000000..98ab127e1 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java @@ -0,0 +1,80 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.registry.master; + +import com.dfsek.tectonic.api.exception.ConfigException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.util.Objects; +import java.util.zip.ZipFile; + +import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.config.pack.ConfigPackImpl; +import com.dfsek.terra.registry.OpenRegistryImpl; + + +/** + * Class to hold config packs + */ +public class ConfigRegistry extends OpenRegistryImpl { + private static final Logger logger = LoggerFactory.getLogger(ConfigRegistry.class); + + public ConfigRegistry() { + super(TypeKey.of(ConfigPack.class)); + } + + public void load(File folder, Platform platform) throws ConfigException { + ConfigPack pack = new ConfigPackImpl(folder, platform); + register(pack.getRegistryKey(), pack); + } + + public boolean loadAll(Platform platform) { + boolean valid = true; + File packsFolder = new File(platform.getDataFolder(), "packs"); + packsFolder.mkdirs(); + for(File dir : Objects.requireNonNull(packsFolder.listFiles(File::isDirectory))) { + try { + load(dir, platform); + } catch(ConfigException e) { + logger.error("Error loading config pack {}", dir.getName(), e); + valid = false; + } + } + for(File zip : Objects.requireNonNull( + packsFolder.listFiles(file -> file.getName().endsWith(".zip") || file.getName().endsWith(".terra")))) { + try { + logger.info("Loading ZIP archive: {}", zip.getName()); + load(new ZipFile(zip), platform); + } catch(IOException | ConfigException e) { + logger.error("Error loading config pack {}", zip.getName(), e); + valid = false; + } + } + return valid; + } + + public void load(ZipFile file, Platform platform) throws ConfigException { + ConfigPackImpl pack = new ConfigPackImpl(file, platform); + register(pack.getRegistryKey(), pack); + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/transform/MapTransform.java b/common/implementation/base/src/main/java/com/dfsek/terra/transform/MapTransform.java new file mode 100644 index 000000000..7bc2ab6d9 --- /dev/null +++ b/common/implementation/base/src/main/java/com/dfsek/terra/transform/MapTransform.java @@ -0,0 +1,53 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.transform; + +import java.util.HashMap; +import java.util.Map; + +import com.dfsek.terra.api.transform.Transform; +import com.dfsek.terra.api.transform.exception.TransformException; + + +public class MapTransform implements Transform { + private final Map map; + + public MapTransform(Map map) { + this.map = map; + } + + public MapTransform() { + this.map = new HashMap<>(); + } + + public MapTransform add(F from, T to) { + map.put(from, to); + return this; + } + + public MapTransform remove(F from) { + map.remove(from); + return this; + } + + @Override + public T transform(F input) throws TransformException { + if(!map.containsKey(input)) throw new TransformException("No key matching " + input.toString() + " found in map."); + return map.get(input); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/Transformer.java b/common/implementation/base/src/main/java/com/dfsek/terra/transform/TransformerImpl.java similarity index 58% rename from common/src/main/java/com/dfsek/terra/api/transform/Transformer.java rename to common/implementation/base/src/main/java/com/dfsek/terra/transform/TransformerImpl.java index efd801dd8..9875a5e65 100644 --- a/common/src/main/java/com/dfsek/terra/api/transform/Transformer.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/transform/TransformerImpl.java @@ -1,4 +1,21 @@ -package com.dfsek.terra.api.transform; +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.transform; import java.util.ArrayList; import java.util.Arrays; @@ -6,25 +23,27 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import com.dfsek.terra.api.transform.Transform; +import com.dfsek.terra.api.transform.Transformer; +import com.dfsek.terra.api.transform.Validator; +import com.dfsek.terra.api.transform.exception.AttemptsFailedException; +import com.dfsek.terra.api.transform.exception.TransformException; + + /** * Class to translate types from one style/platform to another. * * @param Data type to transform from. * @param Data type to transform to. */ -public class Transformer { +public class TransformerImpl implements Transformer { private final LinkedHashMap, List>> transformers; - - private Transformer(LinkedHashMap, List>> transformer) { + + private TransformerImpl(LinkedHashMap, List>> transformer) { this.transformers = transformer; } - - /** - * Translate data from {@code from} type to {@code to} type. - * - * @param from Data to translate - * @return Result - */ + + @Override public T translate(F from) { List exceptions = new ArrayList<>(); for(Map.Entry, List>> transform : transformers.entrySet()) { @@ -42,7 +61,7 @@ public class Transformer { } throw new AttemptsFailedException("Could not transform input; all attempts failed: " + from.toString() + "\n", exceptions); } - + /** * Builder pattern for building Transformers * @@ -51,16 +70,16 @@ public class Transformer { */ public static final class Builder { private final LinkedHashMap, List>> transforms = new LinkedHashMap<>(); - + @SafeVarargs @SuppressWarnings("varargs") public final Builder addTransform(Transform transform, Validator... validators) { transforms.put(transform, Arrays.asList(validators)); return this; } - - public Transformer build() { - return new Transformer<>(transforms); + + public TransformerImpl build() { + return new TransformerImpl<>(transforms); } } } diff --git a/common/implementation/base/src/main/resources/config.yml b/common/implementation/base/src/main/resources/config.yml new file mode 100644 index 000000000..72dd67061 --- /dev/null +++ b/common/implementation/base/src/main/resources/config.yml @@ -0,0 +1,20 @@ +# This file contains core configuration options for Terra +# +# As you can see, there is not that much to configure here. +# For advanced configuration, use config packs. Config +# packs are loaded from the packs directory. Check the +# wiki for information regarding config pack development. + +debug: + commands: false + log: false + profiler: false + script: false +dump-default: true +biome-search-resolution: 4 +cache: + structure: 32 + sampler: 128 + biome-provider: 32 +script: + max-recursion: 1000 \ No newline at end of file diff --git a/common/implementation/base/src/test/java/MetaTest.java b/common/implementation/base/src/test/java/MetaTest.java new file mode 100644 index 000000000..81a90544b --- /dev/null +++ b/common/implementation/base/src/test/java/MetaTest.java @@ -0,0 +1,133 @@ +import com.dfsek.tectonic.api.config.Configuration; +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.loader.ConfigLoader; +import com.dfsek.tectonic.yaml.YamlConfiguration; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.config.preprocessor.MetaListLikePreprocessor; +import com.dfsek.terra.config.preprocessor.MetaMapPreprocessor; +import com.dfsek.terra.config.preprocessor.MetaNumberPreprocessor; +import com.dfsek.terra.config.preprocessor.MetaStringPreprocessor; +import com.dfsek.terra.config.preprocessor.MetaValuePreprocessor; + + +public class MetaTest { + @Test + public void testMetaList() { + Configuration meta = new YamlConfiguration(MetaTest.class.getResourceAsStream("/meta.yml"), "meta.yml"); + Configuration metaTarget = new YamlConfiguration(MetaTest.class.getResourceAsStream("/metaTarget.yml"), "metaTarget.yml"); + + Map configurationMap = new HashMap<>(); + + configurationMap.put(meta.getName(), meta); + configurationMap.put(metaTarget.getName(), metaTarget); + + ConfigLoader loader = new ConfigLoader(); + loader.registerPreprocessor(Meta.class, new MetaStringPreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaListLikePreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaMapPreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaNumberPreprocessor(configurationMap)); + + loader.registerPreprocessor(Meta.class, new MetaValuePreprocessor(configurationMap)); + + loader.load(new MetaListConfig(), meta).list.forEach(System.out::println); + } + + @Test + public void testMetaMap() { + Configuration meta = new YamlConfiguration(MetaTest.class.getResourceAsStream("/meta.yml"), "meta.yml"); + Configuration metaTarget = new YamlConfiguration(MetaTest.class.getResourceAsStream("/metaTarget.yml"), "metaTarget.yml"); + + Map configurationMap = new HashMap<>(); + + configurationMap.put(meta.getName(), meta); + configurationMap.put(metaTarget.getName(), metaTarget); + + ConfigLoader loader = new ConfigLoader(); + loader.registerPreprocessor(Meta.class, new MetaStringPreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaListLikePreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaMapPreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaNumberPreprocessor(configurationMap)); + + loader.registerPreprocessor(Meta.class, new MetaValuePreprocessor(configurationMap)); + + loader.load(new MetaMapConfig(), meta).map.forEach((k, v) -> System.out.println(k + ": " + v)); + } + + @Test + public void testMetaString() { + Configuration meta = new YamlConfiguration(MetaTest.class.getResourceAsStream("/meta.yml"), "meta.yml"); + Configuration metaTarget = new YamlConfiguration(MetaTest.class.getResourceAsStream("/metaTarget.yml"), "metaTarget.yml"); + + Map configurationMap = new HashMap<>(); + + configurationMap.put(meta.getName(), meta); + configurationMap.put(metaTarget.getName(), metaTarget); + + ConfigLoader loader = new ConfigLoader(); + + loader.registerPreprocessor(Meta.class, new MetaStringPreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaListLikePreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaMapPreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaNumberPreprocessor(configurationMap)); + + loader.registerPreprocessor(Meta.class, new MetaValuePreprocessor(configurationMap)); + + System.out.println(loader.load(new MetaStringConfig(), meta).string); + } + + @Test + public void testMetaNumber() { + Configuration meta = new YamlConfiguration(MetaTest.class.getResourceAsStream("/meta.yml"), "meta.yml"); + Configuration metaTarget = new YamlConfiguration(MetaTest.class.getResourceAsStream("/metaTarget.yml"), "metaTarget.yml"); + + Map configurationMap = new HashMap<>(); + + configurationMap.put(meta.getName(), meta); + configurationMap.put(metaTarget.getName(), metaTarget); + + ConfigLoader loader = new ConfigLoader(); + loader.registerPreprocessor(Meta.class, new MetaStringPreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaListLikePreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaMapPreprocessor(configurationMap)); + loader.registerPreprocessor(Meta.class, new MetaNumberPreprocessor(configurationMap)); + + loader.registerPreprocessor(Meta.class, new MetaValuePreprocessor(configurationMap)); + + System.out.println("int: " + loader.load(new MetaNumberConfig(), meta).integer); + System.out.println("double: " + loader.load(new MetaNumberConfig(), meta).aDouble); + } + + + private static final class MetaListConfig implements ConfigTemplate { + @Value("list") + private @Meta List<@Meta String> list; + } + + + private static final class MetaMapConfig implements ConfigTemplate { + @Value("map") + private @Meta Map<@Meta String, @Meta String> map; + } + + + private static final class MetaStringConfig implements ConfigTemplate { + @Value("string") + private @Meta String string; + } + + + private static final class MetaNumberConfig implements ConfigTemplate { + @Value("int") + private @Meta int integer; + + @Value("double") + private @Meta double aDouble; + } +} diff --git a/common/src/test/java/profiler/ProfilerTest.java b/common/implementation/base/src/test/java/profiler/ProfilerTest.java similarity index 57% rename from common/src/test/java/profiler/ProfilerTest.java rename to common/implementation/base/src/test/java/profiler/ProfilerTest.java index b4d97856d..1986f4633 100644 --- a/common/src/test/java/profiler/ProfilerTest.java +++ b/common/implementation/base/src/test/java/profiler/ProfilerTest.java @@ -1,21 +1,70 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package profiler; -import com.dfsek.terra.profiler.Profiler; +import org.junit.jupiter.api.Test; + +import com.dfsek.terra.api.profiler.Profiler; import com.dfsek.terra.profiler.ProfilerImpl; + public class ProfilerTest { private static final Profiler PROFILER = new ProfilerImpl(); - //@Test - public static void main(String... a) throws InterruptedException { + + private static void doThing() throws InterruptedException { + PROFILER.push("thing"); + Thread.sleep(1); + doOtherThing(); + thing4(); + PROFILER.pop("thing"); + } + + private static void doOtherThing() throws InterruptedException { + PROFILER.push("thing2"); + Thread.sleep(2); + doThirdOtherThing(); + thing4(); + PROFILER.pop("thing2"); + } + + private static void doThirdOtherThing() throws InterruptedException { + PROFILER.push("thing3"); + Thread.sleep(2); + PROFILER.pop("thing3"); + } + + private static void thing4() throws InterruptedException { + PROFILER.push("thing4"); + Thread.sleep(2); + PROFILER.pop("thing4"); + } + + @Test + public void testProfiler() throws InterruptedException { //PROFILER.start(); - for(int i = 0; i < 1000; i++) { + for(int i = 0; i < 100; i++) { doThing(); } - + for(int i = 0; i < 100; i++) { doThirdOtherThing(); } - + for(int i = 0; i < 100; i++) { doOtherThing(); } @@ -27,37 +76,7 @@ public class ProfilerTest { PROFILER.pop("thing"); PROFILER.push("thing4"); PROFILER.pop("thing4"); - - PROFILER.getTimings().forEach((id, timings) -> { - System.out.println(id + ": " + timings.toString()); - }); - } - - private static void doThing() throws InterruptedException { - PROFILER.push("thing"); - Thread.sleep(1); - doOtherThing(); - thing4(); - PROFILER.pop("thing"); - } - - private static void doOtherThing() throws InterruptedException { - PROFILER.push("thing2"); - Thread.sleep(2); - doThirdOtherThing(); - thing4(); - PROFILER.pop("thing2"); - } - - private static void doThirdOtherThing() throws InterruptedException { - PROFILER.push("thing3"); - Thread.sleep(2); - PROFILER.pop("thing3"); - } - - private static void thing4() throws InterruptedException { - PROFILER.push("thing4"); - Thread.sleep(2); - PROFILER.pop("thing4"); + + PROFILER.getTimings().forEach((id, timings) -> System.out.println(id + ": " + timings.toString())); } } diff --git a/common/implementation/base/src/test/java/registry/RegistryTest.java b/common/implementation/base/src/test/java/registry/RegistryTest.java new file mode 100644 index 000000000..b11e123b6 --- /dev/null +++ b/common/implementation/base/src/test/java/registry/RegistryTest.java @@ -0,0 +1,96 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package registry; + +import org.junit.jupiter.api.Test; + +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.api.registry.OpenRegistry; +import com.dfsek.terra.api.registry.exception.DuplicateEntryException; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.api.util.reflection.TypeKey; +import com.dfsek.terra.registry.CheckedRegistryImpl; +import com.dfsek.terra.registry.OpenRegistryImpl; + +import static org.junit.jupiter.api.Assertions.*; + + +public class RegistryTest { + @Test + public void openRegistry() { + OpenRegistry test = new OpenRegistryImpl<>(TypeKey.of(String.class)); + + test.register(RegistryKey.parse("test:test"), "bazinga"); + + assertEquals(test.get(RegistryKey.parse("test:test")).orElseThrow(), "bazinga"); + } + + @Test + public void openRegistryChecked() { + OpenRegistry test = new OpenRegistryImpl<>(TypeKey.of(String.class)); + + test.registerChecked(RegistryKey.parse("test:test"), "bazinga"); + + try { + test.registerChecked(RegistryKey.parse("test:test"), "bazinga2"); + fail("Shouldn't be able to re-register with #registerChecked!"); + } catch(DuplicateEntryException ignore) { + + } + } + + @Test + public void checkedRegistry() { + CheckedRegistry test = new CheckedRegistryImpl<>(new OpenRegistryImpl<>(TypeKey.of(String.class))); + + test.register(RegistryKey.parse("test:test"), "bazinga"); + + assertEquals(test.get(RegistryKey.parse("test:test")).orElseThrow(), "bazinga"); + + try { + test.register(RegistryKey.parse("test:test"), "bazinga2"); + fail("Shouldn't be able to re-register in CheckedRegistry!"); + } catch(DuplicateEntryException ignore) { + + } + } + + @Test + public void getID() { + OpenRegistry test = new OpenRegistryImpl<>(TypeKey.of(String.class)); + + test.register(RegistryKey.parse("test:test"), "bazinga"); + + assertEquals(test.getByID("test").orElseThrow(), "bazinga"); + } + + @Test + public void getIDAmbiguous() { + OpenRegistry test = new OpenRegistryImpl<>(TypeKey.of(String.class)); + + test.registerChecked(RegistryKey.parse("test:test"), "bazinga"); + test.registerChecked(RegistryKey.parse("test2:test"), "bazinga"); + + try { + test.getByID("test"); + fail("Shouldn't be able to get with ambiguous ID!"); + } catch(IllegalArgumentException ignore) { + + } + } +} diff --git a/common/src/test/resources/config.yml b/common/implementation/base/src/test/resources/config.yml similarity index 100% rename from common/src/test/resources/config.yml rename to common/implementation/base/src/test/resources/config.yml diff --git a/common/src/test/resources/map.jpg b/common/implementation/base/src/test/resources/map.jpg similarity index 100% rename from common/src/test/resources/map.jpg rename to common/implementation/base/src/test/resources/map.jpg diff --git a/common/implementation/base/src/test/resources/meta.yml b/common/implementation/base/src/test/resources/meta.yml new file mode 100644 index 000000000..116b32b89 --- /dev/null +++ b/common/implementation/base/src/test/resources/meta.yml @@ -0,0 +1,18 @@ +list: + - ONE + - "<< metaTarget.yml:list" + - FOUR + - FIVE + - SIX + - "<< metaTarget.yml:list2" + - NINE + - TEN +map: + "<<": + - metaTarget.yml:map1 + - metaTarget.yml:map2 + one: ONE + two: TWO +string: "one-${metaTarget.yml:string.two}-${metaTarget.yml:string.three}-four-five-${metaTarget.yml:string.six}" +int: 2 + 4 +double: ${metaTarget.yml:double} + 5.6 \ No newline at end of file diff --git a/common/implementation/base/src/test/resources/metaTarget.yml b/common/implementation/base/src/test/resources/metaTarget.yml new file mode 100644 index 000000000..338930b52 --- /dev/null +++ b/common/implementation/base/src/test/resources/metaTarget.yml @@ -0,0 +1,17 @@ +list: + - TWO + - THREE +list2: + - SEVEN + - EIGHT +map1: + three: THREE + four: FOUR + five: FIVE +map2: + six: SIX +string: + two: two + three: three + six: six +double: 1 \ No newline at end of file diff --git a/common/implementation/bootstrap-addon-loader/build.gradle.kts b/common/implementation/bootstrap-addon-loader/build.gradle.kts new file mode 100644 index 000000000..4369042f3 --- /dev/null +++ b/common/implementation/bootstrap-addon-loader/build.gradle.kts @@ -0,0 +1,3 @@ +dependencies { + compileOnlyApi(project(":common:api")) +} diff --git a/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java b/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java new file mode 100644 index 000000000..f3b56cde7 --- /dev/null +++ b/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/BootstrapAddonLoader.java @@ -0,0 +1,106 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.addon; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.version.Version; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.reflect.InvocationTargetException; +import java.nio.file.FileVisitOption; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.jar.JarFile; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.dfsek.terra.addon.exception.AddonLoadException; +import com.dfsek.terra.api.addon.bootstrap.BootstrapAddonClassLoader; +import com.dfsek.terra.api.addon.bootstrap.BootstrapBaseAddon; + + +public class BootstrapAddonLoader implements BootstrapBaseAddon> { + private static final Logger logger = LoggerFactory.getLogger(BootstrapAddonLoader.class); + private static final Version VERSION = Versions.getVersion(1, 0, 0); + + public BootstrapAddonLoader() { } + + private BootstrapBaseAddon loadAddon(Path addonPath, BootstrapAddonClassLoader parent) { + logger.debug("Loading bootstrap addon from JAR {}", addonPath); + try(JarFile jar = new JarFile(addonPath.toFile())) { + String entry = jar.getManifest().getMainAttributes().getValue("Terra-Bootstrap-Addon-Entry-Point"); + + if(entry == null) { + throw new AddonLoadException("No Terra-Bootstrap-Addon-Entry-Point attribute defined in addon's MANIFEST.MF."); + } + + //noinspection NestedTryStatement + try { + parent.addURL(addonPath.toUri().toURL()); + Object addonObject = parent.loadClass(entry).getConstructor().newInstance(); + + if(!(addonObject instanceof BootstrapBaseAddon addon)) { + throw new AddonLoadException( + addonObject.getClass() + " does not extend " + BootstrapBaseAddon.class); + } + + logger.debug("Loaded bootstrap addon {}@{} with entry point {}", + addon.getID(), addon.getVersion().getFormatted(), addonObject.getClass()); + return addon; + } catch(InvocationTargetException e) { + throw new AddonLoadException("Exception occurred while instantiating addon", e); + } catch(NoSuchMethodException | IllegalAccessException | InstantiationException e) { + throw new AddonLoadException(String.format("No valid default constructor found in entry point %s", entry), e); + } catch(ClassNotFoundException | NoClassDefFoundError e) { + throw new AddonLoadException(String.format("Entry point %s not found in JAR.", entry), e); + } + + } catch(IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public Iterable> loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent) { + Path bootstrapFolder = addonsFolder.resolve("bootstrap"); + logger.debug("Loading bootstrap addons from {}", bootstrapFolder); + + try(Stream bootstrapAddons = Files.walk(bootstrapFolder, 1, FileVisitOption.FOLLOW_LINKS)) { + return bootstrapAddons.filter(path -> path.toFile().isFile()) + .filter(path -> path.toFile().canRead()) + .filter(path -> path.toString().endsWith(".jar")) + .map(path -> loadAddon(path, parent)) + .collect(Collectors.toList()); + } catch(IOException e) { + throw new UncheckedIOException(e); + } + } + + @Override + public String getID() { + return "BOOTSTRAP"; + } + + @Override + public Version getVersion() { + return VERSION; + } +} diff --git a/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java b/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java new file mode 100644 index 000000000..8f4eac420 --- /dev/null +++ b/common/implementation/bootstrap-addon-loader/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java @@ -0,0 +1,34 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.addon.exception; + +import java.io.Serial; + + +public class AddonLoadException extends RuntimeException { + @Serial + private static final long serialVersionUID = -4949084729296580176L; + + public AddonLoadException(String message) { + super(message); + } + + public AddonLoadException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/common/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java b/common/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java deleted file mode 100644 index 6f09a5307..000000000 --- a/common/src/main/java/com/dfsek/terra/addon/AddonClassLoader.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.dfsek.terra.addon; - -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.addons.annotations.Addon; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Set; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -public class AddonClassLoader extends URLClassLoader { - static { - ClassLoader.registerAsParallelCapable(); - } - - public AddonClassLoader(URL[] urls, ClassLoader parent) { - super(urls, parent); - } - - public AddonClassLoader(URL[] urls) { - super(urls); - } - - @SuppressWarnings("unchecked") - public static Set> fetchAddonClasses(File file) throws IOException { - JarFile jarFile = new JarFile(file); - Enumeration entries = jarFile.entries(); - - AddonClassLoader loader = new AddonClassLoader(new URL[] {file.toURI().toURL()}, AddonClassLoader.class.getClassLoader()); - - Set> set = new HashSet<>(); - while(entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); - - if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue; - String className = entry.getName().substring(0, entry.getName().length() - 6).replace('/', '.'); - - try { - Class clazz = loader.loadClass(className); - - Addon addon = clazz.getAnnotation(Addon.class); - - if(addon == null) continue; - - if(!TerraAddon.class.isAssignableFrom(clazz)) - throw new IllegalArgumentException("Addon class \"" + clazz + "\" must extend TerraAddon."); - - set.add((Class) clazz); - } catch(ClassNotFoundException e) { - throw new IllegalStateException(e); // this should literally never happen, if it does something is very wrong - } - } - - return set; - } -} diff --git a/common/src/main/java/com/dfsek/terra/addon/AddonPool.java b/common/src/main/java/com/dfsek/terra/addon/AddonPool.java deleted file mode 100644 index 5636aa06b..000000000 --- a/common/src/main/java/com/dfsek/terra/addon/AddonPool.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dfsek.terra.addon; - -import com.dfsek.terra.addon.exception.AddonLoadException; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -public class AddonPool { - private final Map pool = new HashMap<>(); - - public void add(PreLoadAddon addon) throws AddonLoadException { - if(pool.containsKey(addon.getId())) { - String message = "Duplicate addon ID: " + - addon.getId() + "; original ID from file: " + - pool.get(addon.getId()).getFile().getAbsolutePath() + - ", class: " + - pool.get(addon.getId()).getAddonClass().getCanonicalName() + - "Duplicate ID from file: " + - addon.getFile().getAbsolutePath() + - ", class: " + - addon.getAddonClass().getCanonicalName(); - throw new AddonLoadException(message); - } - pool.put(addon.getId(), addon); - } - - public PreLoadAddon get(String id) { - return pool.get(id); - } - - public void buildAll() throws AddonLoadException { - for(PreLoadAddon value : pool.values()) { - value.rebuildDependencies(this, value, true); - } - } - - public Set getAddons() { - return new HashSet<>(pool.values()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java b/common/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java deleted file mode 100644 index 7b21ecb40..000000000 --- a/common/src/main/java/com/dfsek/terra/addon/PreLoadAddon.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.dfsek.terra.addon; - -import com.dfsek.terra.addon.exception.AddonLoadException; -import com.dfsek.terra.addon.exception.CircularDependencyException; -import com.dfsek.terra.addon.exception.DependencyMissingException; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.addons.annotations.Addon; -import com.dfsek.terra.api.addons.annotations.Depends; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class PreLoadAddon { - private final List depends = new ArrayList<>(); - private final Class addonClass; - private final String id; - private final String[] dependencies; - private final File file; - - public PreLoadAddon(Class addonClass, File file) { - this.addonClass = addonClass; - this.id = addonClass.getAnnotation(Addon.class).value(); - this.file = file; - Depends depends = addonClass.getAnnotation(Depends.class); - this.dependencies = depends == null ? new String[] {} : depends.value(); - } - - public List getDepends() { - return depends; - } - - public void rebuildDependencies(AddonPool pool, PreLoadAddon origin, boolean levelG1) throws AddonLoadException { - if(this.equals(origin) && !levelG1) - throw new CircularDependencyException("Detected circular dependency in addon \"" + id + "\", dependencies: " + Arrays.toString(dependencies)); - - for(String dependency : dependencies) { - PreLoadAddon preLoadAddon = pool.get(dependency); - if(preLoadAddon == null) - throw new DependencyMissingException("Dependency " + dependency + " was not found. Please install " + dependency + " to use " + id + "."); - depends.add(preLoadAddon); - preLoadAddon.rebuildDependencies(pool, origin, false); - } - } - - public String getId() { - return id; - } - - public Class getAddonClass() { - return addonClass; - } - - public File getFile() { - return file; - } -} diff --git a/common/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java b/common/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java deleted file mode 100644 index e0ff046d5..000000000 --- a/common/src/main/java/com/dfsek/terra/addon/exception/AddonLoadException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.addon.exception; - -public class AddonLoadException extends Exception { - private static final long serialVersionUID = -4949084729296580176L; - - public AddonLoadException(String message) { - super(message); - } - - public AddonLoadException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/addon/exception/CircularDependencyException.java b/common/src/main/java/com/dfsek/terra/addon/exception/CircularDependencyException.java deleted file mode 100644 index 88513f6b1..000000000 --- a/common/src/main/java/com/dfsek/terra/addon/exception/CircularDependencyException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.addon.exception; - -public class CircularDependencyException extends AddonLoadException { - private static final long serialVersionUID = 7398510879124125121L; - - public CircularDependencyException(String message) { - super(message); - } - - public CircularDependencyException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/addon/exception/DependencyMissingException.java b/common/src/main/java/com/dfsek/terra/addon/exception/DependencyMissingException.java deleted file mode 100644 index fec11d10f..000000000 --- a/common/src/main/java/com/dfsek/terra/addon/exception/DependencyMissingException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.addon.exception; - -public class DependencyMissingException extends AddonLoadException { - private static final long serialVersionUID = -8419489102208521583L; - - public DependencyMissingException(String message) { - super(message); - } - - public DependencyMissingException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/LoaderRegistrar.java b/common/src/main/java/com/dfsek/terra/api/LoaderRegistrar.java deleted file mode 100644 index 96308deb0..000000000 --- a/common/src/main/java/com/dfsek/terra/api/LoaderRegistrar.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api; - -import com.dfsek.tectonic.loading.TypeRegistry; - -public interface LoaderRegistrar { - void register(TypeRegistry registry); -} diff --git a/common/src/main/java/com/dfsek/terra/api/TerraPlugin.java b/common/src/main/java/com/dfsek/terra/api/TerraPlugin.java deleted file mode 100644 index 2982da04f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/TerraPlugin.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.dfsek.terra.api; - -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.event.EventManager; -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.registry.CheckedRegistry; -import com.dfsek.terra.api.registry.LockedRegistry; -import com.dfsek.terra.api.util.JarUtil; -import com.dfsek.terra.api.util.logging.DebugLogger; -import com.dfsek.terra.api.util.logging.Logger; -import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.lang.Language; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.profiler.Profiler; -import com.dfsek.terra.world.TerraWorld; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.jar.JarFile; - -/** - * Represents a Terra mod/plugin instance. - */ -public interface TerraPlugin extends LoaderRegistrar { - WorldHandle getWorldHandle(); - - TerraWorld getWorld(World world); - - Logger logger(); - - PluginConfig getTerraConfig(); - - File getDataFolder(); - - boolean isDebug(); - - Language getLanguage(); - - CheckedRegistry getConfigRegistry(); - - LockedRegistry getAddons(); - - boolean reload(); - - ItemHandle getItemHandle(); - - void saveDefaultConfig(); - - String platformName(); - - DebugLogger getDebugLogger(); - - EventManager getEventManager(); - - default String getVersion() { - return "@VERSION@"; - } - - /** - * Runs a task that may or may not be thread safe, depending on platform. - *

- * Allows platforms to define what code is safe to be run asynchronously. - * - * @param task Task to be run. - */ - default void runPossiblyUnsafeTask(Runnable task) { - task.run(); - } - - Profiler getProfiler(); - - default JarFile getModJar() throws URISyntaxException, IOException { - return JarUtil.getJarFile(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/addons/TerraAddon.java b/common/src/main/java/com/dfsek/terra/api/addons/TerraAddon.java deleted file mode 100644 index c202f9e39..000000000 --- a/common/src/main/java/com/dfsek/terra/api/addons/TerraAddon.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dfsek.terra.api.addons; - - -import com.dfsek.terra.api.addons.annotations.Addon; -import com.dfsek.terra.api.addons.annotations.Author; -import com.dfsek.terra.api.addons.annotations.Version; -import org.jetbrains.annotations.NotNull; - -/** - * Represents an entry point for an addon. Implementations must be annotated with {@link Addon}. - */ -public abstract class TerraAddon { - /** - * Gets the version of this addon. - * - * @return Addon version. - */ - public final @NotNull String getVersion() { - Version version = getClass().getAnnotation(Version.class); - return version == null ? "0.1.0" : version.value(); - } - - /** - * Gets the author of this addon. - * - * @return Addon author. - */ - public final @NotNull String getAuthor() { - Author author = getClass().getAnnotation(Author.class); - return author == null ? "Anon Y. Mous" : author.value(); - } - - /** - * Gets the name (ID) of this addon. - * - * @return Addon ID. - */ - public final @NotNull String getName() { - Addon addon = getClass().getAnnotation(Addon.class); - if(addon == null) - throw new IllegalStateException("Addon annotation not present"); // This should never happen; the presence of this annotation is checked by the addon loader. - return addon.value(); - } - - /** - * Invoked immediately after an addon is loaded. - */ - public abstract void initialize(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Addon.java b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Addon.java deleted file mode 100644 index cf36cf6cf..000000000 --- a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Addon.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.addons.annotations; - -import org.jetbrains.annotations.NotNull; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Specifies that the annotated class is an entry point for a Terra addon. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface Addon { - /** - * @return The ID of the addon. - */ - @NotNull String value(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Author.java b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Author.java deleted file mode 100644 index 7a7c70873..000000000 --- a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Author.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.addons.annotations; - -import org.jetbrains.annotations.NotNull; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Optional annotation that specifies the author of an addon. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface Author { - /** - * @return Name of the addon author. - */ - @NotNull String value(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Depends.java b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Depends.java deleted file mode 100644 index 8634335be..000000000 --- a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Depends.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.addons.annotations; - -import org.jetbrains.annotations.NotNull; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Optional annotation that specifies dependencies of an addon. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface Depends { - /** - * @return All addons this addon is dependent upon. - */ - @NotNull String[] value(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Version.java b/common/src/main/java/com/dfsek/terra/api/addons/annotations/Version.java deleted file mode 100644 index a2f8c2743..000000000 --- a/common/src/main/java/com/dfsek/terra/api/addons/annotations/Version.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.addons.annotations; - -import org.jetbrains.annotations.NotNull; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Optional annotation that specifies the version of an addon. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface Version { - /** - * @return Version of the addon. - */ - @NotNull String value(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/CommandManager.java b/common/src/main/java/com/dfsek/terra/api/command/CommandManager.java deleted file mode 100644 index a33d70921..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/CommandManager.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.api.command; - -import com.dfsek.terra.api.command.exception.CommandException; -import com.dfsek.terra.api.command.exception.MalformedCommandException; -import com.dfsek.terra.api.platform.CommandSender; - -import java.util.List; - -public interface CommandManager { - void execute(String command, CommandSender sender, List args) throws CommandException; - - void register(String name, Class clazz) throws MalformedCommandException; - - List tabComplete(String command, CommandSender sender, List args) throws CommandException; - - int getMaxArgumentDepth(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/CommandTemplate.java b/common/src/main/java/com/dfsek/terra/api/command/CommandTemplate.java deleted file mode 100644 index 836192b6b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/CommandTemplate.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.command; - -import com.dfsek.terra.api.platform.CommandSender; - -public interface CommandTemplate { - void execute(CommandSender sender); -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/ExecutionState.java b/common/src/main/java/com/dfsek/terra/api/command/ExecutionState.java deleted file mode 100644 index 89216bd89..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/ExecutionState.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.api.command; - -import com.dfsek.terra.api.platform.CommandSender; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -public final class ExecutionState { - private final Set switches = new HashSet<>(); - private final Map args = new HashMap<>(); - private final CommandSender sender; - - protected ExecutionState(CommandSender sender) { - this.sender = sender; - } - - protected void addSwitch(String flag) { - switches.add(flag); - } - - protected void addArgument(String arg, String value) { - args.put(arg, value); - } - - public String getArgument(String argument) { - return args.get(argument); - } - - public boolean hasSwitch(String flag) { - return switches.contains(flag); - } - - public CommandSender getSender() { - return sender; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java b/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java deleted file mode 100644 index e58dbbf30..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/TerraCommandManager.java +++ /dev/null @@ -1,283 +0,0 @@ -package com.dfsek.terra.api.command; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Subcommand; -import com.dfsek.terra.api.command.annotation.Switch; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.command.arg.ArgumentParser; -import com.dfsek.terra.api.command.exception.CommandException; -import com.dfsek.terra.api.command.exception.ExecutionException; -import com.dfsek.terra.api.command.exception.InvalidArgumentsException; -import com.dfsek.terra.api.command.exception.MalformedCommandException; -import com.dfsek.terra.api.command.exception.SwitchFormatException; -import com.dfsek.terra.api.command.tab.TabCompleter; -import com.dfsek.terra.api.injection.Injector; -import com.dfsek.terra.api.injection.exception.InjectionException; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.util.ReflectionUtil; -import com.dfsek.terra.world.TerraWorld; -import net.jafama.FastMath; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class TerraCommandManager implements CommandManager { - private final Map commands = new HashMap<>(); - private final Injector pluginInjector; - private final TerraPlugin main; - - public TerraCommandManager(TerraPlugin main) { - this.main = main; - this.pluginInjector = new Injector<>(main); - pluginInjector.addExplicitTarget(TerraPlugin.class); - } - - @Override - public void execute(String commandName, CommandSender sender, List argsIn) throws CommandException { - if(!commands.containsKey(commandName)) throw new InvalidArgumentsException("No such command \"" + commandName + "\""); - execute(commands.get(commandName), sender, new ArrayList<>(argsIn)); - } - - private void execute(CommandHolder commandHolder, CommandSender sender, List args) throws CommandException { - Class commandClass = commandHolder.clazz; - - if(commandClass.isAnnotationPresent(DebugCommand.class) && !main.isDebug()) { - sender.sendMessage("Command must be executed with debug mode enabled."); - return; - } - - if(commandClass.isAnnotationPresent(PlayerCommand.class) && !(sender instanceof Player)) { - sender.sendMessage("Command must be executed by player."); - return; - } - - if(commandClass.isAnnotationPresent(WorldCommand.class) && (!(sender instanceof Player) || !(((Player) sender).getWorld()).isTerraWorld())) { - sender.sendMessage("Command must be executed in a Terra world."); - return; - } - - List ogArgs = new ArrayList<>(args); - - ExecutionState state = new ExecutionState(sender); - - if(!commandClass.isAnnotationPresent(Command.class)) { - invoke(commandClass, state, commandHolder); - return; - } - - Command command = commandClass.getAnnotation(Command.class); - - if(command.arguments().length == 0 && command.subcommands().length == 0) { - if(args.isEmpty()) { - invoke(commandClass, state, commandHolder); - return; - } else throw new InvalidArgumentsException("Expected 0 arguments, found " + args.size()); - } - - if(!args.isEmpty() && commandHolder.subcommands.containsKey(args.get(0))) { - String c = args.get(0); - args.remove(0); - execute(commandHolder.subcommands.get(c), sender, args); - return; - } - - boolean req = true; - for(Argument argument : command.arguments()) { - if(!req && argument.required()) { - throw new MalformedCommandException("Required arguments must come first! Arguments: " + Arrays.toString(command.arguments())); - } - req = argument.required(); - - if(args.isEmpty()) { - if(req) throw new InvalidArgumentsException("Invalid arguments: " + ogArgs + ", usage: " + command.usage()); - break; - } - - String arg = args.get(0); - - if(arg.startsWith("-")) { // switches have started. - if(req) throw new InvalidArgumentsException("Switches must come after arguments."); - break; - } - - state.addArgument(argument.value(), args.remove(0)); - } - - while(!args.isEmpty()) { - String aSwitch = args.remove(0); - if(!aSwitch.startsWith("-")) throw new SwitchFormatException("Invalid switch \"" + aSwitch + "\""); - - String val = aSwitch.substring(1); // remove dash - - if(!commandHolder.switches.containsKey(val)) throw new SwitchFormatException("No such switch \"" + aSwitch + "\""); - - state.addSwitch(commandHolder.switches.get(val)); - } - - invoke(commandClass, state, commandHolder); - } - - private void invoke(Class clazz, ExecutionState state, CommandHolder holder) throws CommandException { - try { - CommandTemplate template = clazz.getConstructor().newInstance(); - - pluginInjector.inject(template); - - for(Field field : ReflectionUtil.getFields(clazz)) { - if(field.isAnnotationPresent(ArgumentTarget.class)) { - ArgumentTarget argumentTarget = field.getAnnotation(ArgumentTarget.class); - if(!holder.argumentMap.containsKey(argumentTarget.value())) { - throw new MalformedCommandException("Argument Target specifies nonexistent argument \"" + argumentTarget.value() + "\""); - } - - String argument = argumentTarget.value(); - - ArgumentParser argumentParser = holder.argumentMap.get(argumentTarget.value()).argumentParser().getConstructor().newInstance(); - - pluginInjector.inject(argumentParser); - - field.setAccessible(true); - String value = state.getArgument(argument); - - if(value == null) value = holder.argumentMap.get(argumentTarget.value()).defaultValue(); - - field.set(template, argumentParser.parse(state.getSender(), value)); - } - if(field.isAnnotationPresent(SwitchTarget.class)) { - SwitchTarget switchTarget = field.getAnnotation(SwitchTarget.class); - if(!holder.switches.containsValue(switchTarget.value())) { - throw new MalformedCommandException("Switch Target specifies nonexistent switch \"" + switchTarget.value() + "\""); - } - - if(!(field.getType() == boolean.class)) { - throw new MalformedCommandException("Switch Target must be of type boolean."); - } - - field.setAccessible(true); - field.setBoolean(template, state.hasSwitch(switchTarget.value())); - } - } - - try { - template.execute(state.getSender()); - } catch(Throwable e) { - throw new ExecutionException("Failed to execute command: " + e.getMessage(), e); - } - } catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) { - throw new MalformedCommandException("Unable to reflectively instantiate command: ", e); - } - } - - @Override - public void register(String name, Class clazz) throws MalformedCommandException { - commands.put(name, new CommandHolder(clazz)); - } - - @Override - public List tabComplete(String command, CommandSender sender, List args) throws CommandException { - if(args.isEmpty()) return new ArrayList<>(commands.keySet()).stream().sorted(String::compareTo).collect(Collectors.toList()); - if(!commands.containsKey(command)) return Collections.emptyList(); - return tabComplete(commands.get(command), sender, new ArrayList<>(args)).stream().filter(s -> s.toLowerCase().startsWith(args.get(args.size() - 1).toLowerCase())).sorted(String::compareTo).collect(Collectors.toList()); - } - - @Override - public int getMaxArgumentDepth() { - int max = 0; - for(CommandHolder value : commands.values()) { - max = FastMath.max(getMaxArgumentDepth(value), max); - } - return max; - } - - private int getMaxArgumentDepth(CommandHolder holder) { - int max = 0; - max = FastMath.max(holder.arguments.size() + holder.switchList.size(), max); - for(CommandHolder value : holder.subcommands.values()) { - max = FastMath.max(max, getMaxArgumentDepth(value) + 1); - } - return max; - } - - private List tabComplete(CommandHolder holder, CommandSender sender, List args) throws CommandException { - if(args.isEmpty()) return Collections.emptyList(); - List completions = new ArrayList<>(); - - if(args.size() == 1) { - completions.addAll(holder.subcommands.keySet()); - } - - if(holder.subcommands.containsKey(args.get(0))) { - List newArgs = new ArrayList<>(args); - newArgs.remove(0); - completions.addAll(tabComplete(holder.subcommands.get(args.get(0)), sender, newArgs)); - } - try { - if(args.size() <= holder.arguments.size()) { - TabCompleter completer = holder.arguments.get(args.size() - 1).tabCompleter().getConstructor().newInstance(); - pluginInjector.inject(completer); - completions.addAll(completer.complete(sender)); - } - } catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | InjectionException e) { - throw new MalformedCommandException("Unable to reflectively instantiate tab-completer: ", e); - } - return completions; - } - - /** - * Pre-processes command metadata. - */ - private static final class CommandHolder { - private final Class clazz; - private final Map subcommands = new HashMap<>(); - private final Map switches = new HashMap<>(); - private final List arguments; - private final List switchList; - private final Map argumentMap = new HashMap<>(); - - private CommandHolder(Class clazz) throws MalformedCommandException { - this.clazz = clazz; - if(clazz.isAnnotationPresent(Command.class)) { - Command command = clazz.getAnnotation(Command.class); - for(Subcommand subcommand : command.subcommands()) { - if(subcommands.containsKey(subcommand.value())) - throw new MalformedCommandException("Duplicate subcommand: " + subcommand); - CommandHolder holder = new CommandHolder(subcommand.clazz()); - subcommands.put(subcommand.value(), holder); - for(String alias : subcommand.aliases()) { - subcommands.put(alias, holder); - } - } - for(Switch aSwitch : command.switches()) { - if(switches.containsKey(aSwitch.value())) throw new MalformedCommandException("Duplicate switch: " + aSwitch); - switches.put(aSwitch.value(), aSwitch.value()); - for(String alias : aSwitch.aliases()) { - switches.put(alias, aSwitch.value()); - } - } - for(Argument argument : command.arguments()) { - if(argumentMap.containsKey(argument.value())) throw new MalformedCommandException("Duplicate argument: " + argument); - argumentMap.put(argument.value(), argument); - } - arguments = Arrays.asList(command.arguments()); - switchList = Arrays.asList(command.switches()); - } else { - arguments = Collections.emptyList(); - switchList = Collections.emptyList(); - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/Argument.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/Argument.java deleted file mode 100644 index d0c91a965..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/annotation/Argument.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.api.command.annotation; - -import com.dfsek.terra.api.command.arg.ArgumentParser; -import com.dfsek.terra.api.command.arg.StringArgumentParser; -import com.dfsek.terra.api.command.tab.NothingCompleter; -import com.dfsek.terra.api.command.tab.TabCompleter; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.ANNOTATION_TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface Argument { - String value(); - - boolean required() default true; - - Class tabCompleter() default NothingCompleter.class; - - Class> argumentParser() default StringArgumentParser.class; - - String defaultValue() default ""; -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/Command.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/Command.java deleted file mode 100644 index fb5fd81ea..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/annotation/Command.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.api.command.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface Command { - Argument[] arguments() default {}; - - Switch[] switches() default {}; - - Subcommand[] subcommands() default {}; - - String usage() default ""; -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/Subcommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/Subcommand.java deleted file mode 100644 index 7f729ba0a..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/annotation/Subcommand.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.api.command.annotation; - -import com.dfsek.terra.api.command.CommandTemplate; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.ANNOTATION_TYPE) -public @interface Subcommand { - String value(); - - String[] aliases() default {}; - - Class clazz(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/Switch.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/Switch.java deleted file mode 100644 index 16ea3e21a..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/annotation/Switch.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.command.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.ANNOTATION_TYPE) -public @interface Switch { - String value(); - - String[] aliases() default {}; -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/ArgumentTarget.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/ArgumentTarget.java deleted file mode 100644 index 89dbc5245..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/ArgumentTarget.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.api.command.annotation.inject; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface ArgumentTarget { - String value(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/SwitchTarget.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/SwitchTarget.java deleted file mode 100644 index 67478373a..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/annotation/inject/SwitchTarget.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.api.command.annotation.inject; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface SwitchTarget { - String value(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/DebugCommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/DebugCommand.java deleted file mode 100644 index 174710401..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/DebugCommand.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.command.annotation.type; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Command may only be executed with debug mode enabled. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface DebugCommand { -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/PlayerCommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/PlayerCommand.java deleted file mode 100644 index fd7b1e320..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/PlayerCommand.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.command.annotation.type; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Marks command as player-only - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface PlayerCommand { -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/WorldCommand.java b/common/src/main/java/com/dfsek/terra/api/command/annotation/type/WorldCommand.java deleted file mode 100644 index c51ee570b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/annotation/type/WorldCommand.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.command.annotation.type; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Command may only be executed in a Terra world. - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface WorldCommand { -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/arg/ArgumentParser.java b/common/src/main/java/com/dfsek/terra/api/command/arg/ArgumentParser.java deleted file mode 100644 index 3fcc5aeef..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/arg/ArgumentParser.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.command.arg; - -import com.dfsek.terra.api.platform.CommandSender; - -public interface ArgumentParser { - T parse(CommandSender sender, String arg); -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/arg/DoubleArgumentParser.java b/common/src/main/java/com/dfsek/terra/api/command/arg/DoubleArgumentParser.java deleted file mode 100644 index 3f229b444..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/arg/DoubleArgumentParser.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.api.command.arg; - -import com.dfsek.terra.api.platform.CommandSender; - -public class DoubleArgumentParser implements ArgumentParser { - @Override - public Double parse(CommandSender sender, String arg) { - return arg == null ? null : Double.parseDouble(arg); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/arg/IntegerArgumentParser.java b/common/src/main/java/com/dfsek/terra/api/command/arg/IntegerArgumentParser.java deleted file mode 100644 index 24e3186ca..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/arg/IntegerArgumentParser.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.api.command.arg; - -import com.dfsek.terra.api.platform.CommandSender; - -public class IntegerArgumentParser implements ArgumentParser { - @Override - public Integer parse(CommandSender sender, String arg) { - return arg == null ? null : Integer.parseInt(arg); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/arg/StringArgumentParser.java b/common/src/main/java/com/dfsek/terra/api/command/arg/StringArgumentParser.java deleted file mode 100644 index 736b335d0..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/arg/StringArgumentParser.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.api.command.arg; - -import com.dfsek.terra.api.platform.CommandSender; - -public class StringArgumentParser implements ArgumentParser { - @Override - public String parse(CommandSender sender, String arg) { - return arg; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/exception/CommandException.java b/common/src/main/java/com/dfsek/terra/api/command/exception/CommandException.java deleted file mode 100644 index 3fd6537ef..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/exception/CommandException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.api.command.exception; - -public abstract class CommandException extends Exception { - private static final long serialVersionUID = -2955328495045879822L; - - public CommandException(String message) { - super(message); - } - - public CommandException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/exception/ExecutionException.java b/common/src/main/java/com/dfsek/terra/api/command/exception/ExecutionException.java deleted file mode 100644 index 061bfc64b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/exception/ExecutionException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.api.command.exception; - -public class ExecutionException extends CommandException { - private static final long serialVersionUID = -6345523475880607959L; - - public ExecutionException(String message) { - super(message); - } - - public ExecutionException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/exception/InvalidArgumentsException.java b/common/src/main/java/com/dfsek/terra/api/command/exception/InvalidArgumentsException.java deleted file mode 100644 index 5ad88d0b3..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/exception/InvalidArgumentsException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.api.command.exception; - -public class InvalidArgumentsException extends CommandException { - private static final long serialVersionUID = 7563619667472569824L; - - public InvalidArgumentsException(String message) { - super(message); - } - - public InvalidArgumentsException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/exception/MalformedCommandException.java b/common/src/main/java/com/dfsek/terra/api/command/exception/MalformedCommandException.java deleted file mode 100644 index c124a8b85..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/exception/MalformedCommandException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.api.command.exception; - -/** - * Thrown when command is incorrectly defined. - */ -public class MalformedCommandException extends CommandException { - private static final long serialVersionUID = -5417760860407895496L; - - public MalformedCommandException(String message) { - super(message); - } - - public MalformedCommandException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/exception/SwitchFormatException.java b/common/src/main/java/com/dfsek/terra/api/command/exception/SwitchFormatException.java deleted file mode 100644 index c7e545ae7..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/exception/SwitchFormatException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.api.command.exception; - -public class SwitchFormatException extends CommandException { - private static final long serialVersionUID = -965858989317844628L; - - public SwitchFormatException(String message) { - super(message); - } - - public SwitchFormatException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/tab/NothingCompleter.java b/common/src/main/java/com/dfsek/terra/api/command/tab/NothingCompleter.java deleted file mode 100644 index 111125505..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/tab/NothingCompleter.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.api.command.tab; - -import com.dfsek.terra.api.platform.CommandSender; - -import java.util.Collections; -import java.util.List; - -public class NothingCompleter implements TabCompleter { - @Override - public List complete(CommandSender sender) { - return Collections.emptyList(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/command/tab/TabCompleter.java b/common/src/main/java/com/dfsek/terra/api/command/tab/TabCompleter.java deleted file mode 100644 index 33f875234..000000000 --- a/common/src/main/java/com/dfsek/terra/api/command/tab/TabCompleter.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dfsek.terra.api.command.tab; - -import com.dfsek.terra.api.platform.CommandSender; - -import java.util.List; - -public interface TabCompleter { - List complete(CommandSender sender); -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/EventListener.java b/common/src/main/java/com/dfsek/terra/api/event/EventListener.java deleted file mode 100644 index cde546369..000000000 --- a/common/src/main/java/com/dfsek/terra/api/event/EventListener.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.api.event; - -import com.dfsek.terra.api.event.events.Event; - -/** - * Marker interface for a class that contains event listener methods. - * - * @see Event - * @see EventManager - */ -public interface EventListener { -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/EventManager.java b/common/src/main/java/com/dfsek/terra/api/event/EventManager.java deleted file mode 100644 index de6ba0e19..000000000 --- a/common/src/main/java/com/dfsek/terra/api/event/EventManager.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.api.event; - -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.event.events.Event; - -/** - * Manages event registration and triggering. - */ -public interface EventManager { - /** - * Call an event, and return the execution status. - * - * @param event Event to pass to all registered EventListeners. - * @return False if the event is cancellable and has been cancelled, otherwise true. - */ - boolean callEvent(Event event); - - /** - * Register an {@link EventListener} under an {@link TerraAddon}. - * - * @param addon Addon to register listener for. - * @param listener Listener to register. - */ - void registerListener(TerraAddon addon, EventListener listener); -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/TerraEventManager.java b/common/src/main/java/com/dfsek/terra/api/event/TerraEventManager.java deleted file mode 100644 index 493efa364..000000000 --- a/common/src/main/java/com/dfsek/terra/api/event/TerraEventManager.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.dfsek.terra.api.event; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.event.annotations.Global; -import com.dfsek.terra.api.event.annotations.Priority; -import com.dfsek.terra.api.event.events.Cancellable; -import com.dfsek.terra.api.event.events.Event; -import com.dfsek.terra.api.event.events.PackEvent; -import com.dfsek.terra.api.util.ReflectionUtil; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class TerraEventManager implements EventManager { - private final Map, List> listeners = new HashMap<>(); - private final TerraPlugin main; - - public TerraEventManager(TerraPlugin main) { - this.main = main; - } - - @Override - public boolean callEvent(Event event) { - listeners.getOrDefault(event.getClass(), Collections.emptyList()).forEach(listenerHolder -> { - try { - if(event instanceof PackEvent && !listenerHolder.global) { - PackEvent packEvent = (PackEvent) event; - if(packEvent - .getPack() - .getTemplate() - .getAddons() - .contains(listenerHolder.addon)) { - listenerHolder.method.invoke(listenerHolder.listener, event); - } - } else { - listenerHolder.method.invoke(listenerHolder.listener, event); - } - } catch(InvocationTargetException e) { - StringWriter writer = new StringWriter(); - e.getTargetException().printStackTrace(new PrintWriter(writer)); - main.logger().warning("Exception occurred during event handling:"); - main.logger().warning(writer.toString()); - main.logger().warning("Report this to the maintainers of " + listenerHolder.method.getName()); - } catch(Exception e) { - StringWriter writer = new StringWriter(); - e.printStackTrace(new PrintWriter(writer)); - main.logger().warning("Exception occurred during event handling:"); - main.logger().warning(writer.toString()); - main.logger().warning("Report this to the maintainers of " + listenerHolder.method.getName()); - } - } - ); - if(event instanceof Cancellable) return !((Cancellable) event).isCancelled(); - return true; - } - - @SuppressWarnings("unchecked") - @Override - public void registerListener(TerraAddon addon, EventListener listener) { - Class listenerClass = listener.getClass(); - Method[] methods = ReflectionUtil.getMethods(listenerClass); - - for(Method method : methods) { - if(method.getParameterCount() != 1) continue; // Check that parameter count is only 1. - Class eventParam = method.getParameterTypes()[0]; - if(!Event.class.isAssignableFrom(eventParam)) continue; // Check that parameter is an Event. - - Priority p = method.getAnnotation(Priority.class); - - int priority = p == null ? 0 : p.value(); - - method.setAccessible(true); - - List holders = listeners.computeIfAbsent((Class) eventParam, e -> new ArrayList<>()); - - holders.add(new ListenerHolder(method, listener, priority, addon, method.getAnnotation(Global.class) != null)); - - holders.sort(Comparator.comparingInt(ListenerHolder::getPriority)); // Sort priorities. - } - } - - private static final class ListenerHolder { - private final Method method; - private final EventListener listener; - private final int priority; - private final TerraAddon addon; - private final boolean global; - - private ListenerHolder(Method method, EventListener listener, int priority, TerraAddon addon, boolean global) { - this.method = method; - this.listener = listener; - this.priority = priority; - this.addon = addon; - this.global = global; - } - - public int getPriority() { - return priority; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/annotations/Global.java b/common/src/main/java/com/dfsek/terra/api/event/annotations/Global.java deleted file mode 100644 index d162c00d9..000000000 --- a/common/src/main/java/com/dfsek/terra/api/event/annotations/Global.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.api.event.annotations; - -import com.dfsek.terra.api.event.events.PackEvent; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Specifies that an event handler is to handle all {@link PackEvent}s, regardless of whether the pack - * depends on the addon's listener. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface Global { -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/annotations/Priority.java b/common/src/main/java/com/dfsek/terra/api/event/annotations/Priority.java deleted file mode 100644 index 2d5b7c11f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/event/annotations/Priority.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.api.event.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotated listener methods will have a specific priority set. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface Priority { - /** - * Highest possible priority. Listeners with this priority will always be invoked last. - */ - int HIGHEST = Integer.MAX_VALUE; - /** - * Lowest possible priority. Listeners with this priority will always be invoked first. - */ - int LOWEST = Integer.MIN_VALUE; - /** - * Default priority. - */ - int NORMAL = 0; - /** - * High priority. - */ - int HIGH = 1; - /** - * Low Priority. - */ - int LOW = -1; - /** - * @return Priority of this event. Events are executed from lowest to highest priorities. - */ - int value(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/Event.java b/common/src/main/java/com/dfsek/terra/api/event/events/Event.java deleted file mode 100644 index 67d12a029..000000000 --- a/common/src/main/java/com/dfsek/terra/api/event/events/Event.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.event.events; - -/** - * An event that addons may listen to. - */ -public interface Event { -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPostLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPostLoadEvent.java deleted file mode 100644 index 1398ec219..000000000 --- a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPostLoadEvent.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.api.event.events.config; - -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.terra.config.pack.ConfigPack; - -/** - * Called when a config pack has finished loading. - */ -public class ConfigPackPostLoadEvent extends ConfigPackLoadEvent { - public ConfigPackPostLoadEvent(ConfigPack pack, ExceptionalConsumer loader) { - super(pack, loader); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPreLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPreLoadEvent.java deleted file mode 100644 index 1ac2de54d..000000000 --- a/common/src/main/java/com/dfsek/terra/api/event/events/config/ConfigPackPreLoadEvent.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.event.events.config; - -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.terra.config.pack.ConfigPack; - -/** - * Called before a config pack's registries are filled. At this point, the pack manifest has been loaded, and all registries are empty. - */ -public class ConfigPackPreLoadEvent extends ConfigPackLoadEvent { - public ConfigPackPreLoadEvent(ConfigPack pack, ExceptionalConsumer configLoader) { - super(pack, configLoader); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/world/TerraWorldLoadEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/world/TerraWorldLoadEvent.java deleted file mode 100644 index 52e5bf956..000000000 --- a/common/src/main/java/com/dfsek/terra/api/event/events/world/TerraWorldLoadEvent.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.api.event.events.world; - -import com.dfsek.terra.api.event.events.PackEvent; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.pack.WorldConfig; -import com.dfsek.terra.world.TerraWorld; - -/** - * Called upon initialization of a TerraWorld. - */ -public class TerraWorldLoadEvent implements PackEvent { - private final TerraWorld world; - private final ConfigPack pack; - - public TerraWorldLoadEvent(TerraWorld world, ConfigPack pack) { - this.world = world; - this.pack = pack; - } - - public TerraWorld getWorld() { - return world; - } - - public ConfigPack getPack() { - return pack; - } - - public WorldConfig getWorldConfig() { - return world.getConfig(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/event/events/world/generation/EntitySpawnEvent.java b/common/src/main/java/com/dfsek/terra/api/event/events/world/generation/EntitySpawnEvent.java deleted file mode 100644 index 2f4b25bbe..000000000 --- a/common/src/main/java/com/dfsek/terra/api/event/events/world/generation/EntitySpawnEvent.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.dfsek.terra.api.event.events.world.generation; - -import com.dfsek.terra.api.event.events.PackEvent; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedEntity; -import com.dfsek.terra.config.pack.ConfigPack; - -/** - * Called when an entity is spawned via {@link BufferedEntity}. - */ -public class EntitySpawnEvent implements PackEvent { - private final ConfigPack pack; - private final Entity entity; - private final Location location; - - public EntitySpawnEvent(ConfigPack pack, Entity entity, Location location) { - this.pack = pack; - this.entity = entity; - this.location = location; - } - - @Override - public ConfigPack getPack() { - return pack; - } - - /** - * Get the entity that triggered the event. - * - * @return The entity. - */ - public Entity getEntity() { - return entity; - } - - /** - * Get the location of the entity. - * - * @return Location of the entity. - */ - public Location getLocation() { - return location; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/injection/exception/InjectionException.java b/common/src/main/java/com/dfsek/terra/api/injection/exception/InjectionException.java deleted file mode 100644 index 314dd5e93..000000000 --- a/common/src/main/java/com/dfsek/terra/api/injection/exception/InjectionException.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.api.injection.exception; - -import com.dfsek.terra.api.injection.Injector; - -/** - * Thrown when dynamic dependency injection cannot be completed by an {@link Injector}. - */ -public class InjectionException extends Exception { - private static final long serialVersionUID = -6929631447064215387L; - - public InjectionException(String message) { - super(message); - } - - public InjectionException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/GridSpawn.java b/common/src/main/java/com/dfsek/terra/api/math/GridSpawn.java deleted file mode 100644 index f25832de1..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/GridSpawn.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.dfsek.terra.api.math; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.util.GlueList; - -import java.util.List; -import java.util.Random; - -/** - * Class to procedurally determine the spawn point of an object based on a grid with padding between cells. - */ -public class GridSpawn { - private final int separation; - private final int width; - private final int salt; - - public GridSpawn(int width, int separation, int salt) { - this.separation = separation; - this.width = width; - this.salt = salt; - } - - /** - * Get nearest spawn point - * - * @param x X coordinate - * @param z Z coordinate - * @param seed Seed for RNG - * @return Vector representing nearest spawnpoint - */ - public Vector3 getNearestSpawn(int x, int z, long seed) { - int structureChunkX = x / (width + 2 * separation); - int structureChunkZ = z / (width + 2 * separation); - List zones = new GlueList<>(); - for(int xi = structureChunkX - 1; xi <= structureChunkX + 1; xi++) { - for(int zi = structureChunkZ - 1; zi <= structureChunkZ + 1; zi++) { - zones.add(getChunkSpawn(xi, zi, seed)); - } - } - Vector3 shortest = zones.get(0); - Vector3 compare = new Vector3(x, 0, z); - for(Vector3 v : zones) { - if(compare.distanceSquared(shortest) > compare.distanceSquared(v)) shortest = v.clone(); - } - return shortest; - } - - /** - * Get the X/Z coordinates of the spawn point in the nearest Chunk (not Minecraft chunk) - * - * @param structureChunkX Chunk X coordinate - * @param structureChunkZ Chunk Z coordinate - * @param seed Seed for RNG - * @return Vector representing spawnpoint - */ - public Vector3 getChunkSpawn(int structureChunkX, int structureChunkZ, long seed) { - Random r = new FastRandom(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed + salt)); - int offsetX = r.nextInt(width); - int offsetZ = r.nextInt(width); - int sx = structureChunkX * (width + 2 * separation) + offsetX; - int sz = structureChunkZ * (width + 2 * separation) + offsetZ; - return new Vector3(sx, 0, sz); - } - - public int getWidth() { - return width; - } - - public int getSeparation() { - return separation; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/MathUtil.java b/common/src/main/java/com/dfsek/terra/api/math/MathUtil.java deleted file mode 100644 index 77c1a43cf..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/MathUtil.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.dfsek.terra.api.math; - -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.world.generation.math.samplers.Sampler; -import net.jafama.FastMath; - -import java.util.List; -import java.util.Random; - -/** - * Utility class for mathematical functions. - */ -public final class MathUtil { - /** - * Epsilon for fuzzy floating point comparisons. - */ - public static final double EPSILON = 1.0E-5; - /** - * Derivative constant. - */ - private static final double DERIVATIVE_DIST = 0.55; - - /** - * Gets the standard deviation of an array of doubles. - * - * @param numArray The array of numbers to calculate the standard deviation of. - * @return double - The standard deviation. - */ - public static double standardDeviation(List numArray) { - double sum = 0.0, standardDeviation = 0.0; - int length = numArray.size(); - - for(Number num : numArray) { - sum += num.doubleValue(); - } - - double mean = sum / length; - - for(Number num : numArray) { - standardDeviation += FastMath.pow2(num.doubleValue() - mean); - } - - return FastMath.sqrt(standardDeviation / length); - } - - /** - * Gets the carver seed for a chunk. - * - * @param chunkX Chunk's X coordinate - * @param chunkZ Chunk's Z coordinate - * @param seed World seed - * @return long - The carver seed. - */ - public static long getCarverChunkSeed(int chunkX, int chunkZ, long seed) { - Random r = new FastRandom(seed); - return chunkX * r.nextLong() ^ chunkZ * r.nextLong() ^ seed; - } - - public static long hashToLong(String s) { - if(s == null) { - return 0; - } - long hash = 0; - for(char c : s.toCharArray()) { - hash = 31L * hash + c; - } - return hash; - } - - /** - * Compare 2 floating-point values with epsilon to account for rounding errors - * - * @param a Value 1 - * @param b Value 2 - * @return Whether these values are equal - */ - public static boolean equals(double a, double b) { - return a == b || FastMath.abs(a - b) < EPSILON; - } - - public static double derivative(Sampler sampler, double x, double y, double z) { - double baseSample = sampler.sample(x, y, z); - - double xVal1 = (sampler.sample(x + DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST; - double xVal2 = (sampler.sample(x - DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST; - double zVal1 = (sampler.sample(x, y, z + DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST; - double zVal2 = (sampler.sample(x, y, z - DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST; - double yVal1 = (sampler.sample(x, y + DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST; - double yVal2 = (sampler.sample(x, y - DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST; - - return Math.sqrt(((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1))); - } - - public static int normalizeIndex(double val, int size) { - return FastMath.max(FastMath.min(FastMath.floorToInt(((val + 1D) / 2D) * size), size - 1), 0); - } - - public static long squash(int first, int last) { - return (((long) first) << 32) | (last & 0xffffffffL); - } - - /** - * Clamp value to range of [-1, 1] - * - * @param in Value to clamp - * @return Clamped value - */ - public static double clamp(double in) { - return FastMath.min(FastMath.max(in, -1), 1); - } - - /** - * Compute the value in a normally distributed data set that has probability p. - * - * @param p Probability of value - * @param mu Mean of data - * @param sigma Standard deviation of data - * @return Value corresponding to input probability - */ - public static double normalInverse(double p, double mu, double sigma) { - if(p < 0 || p > 1) - throw new IllegalArgumentException("Probability must be in range [0, 1]"); - if(sigma < 0) - throw new IllegalArgumentException("Standard deviation must be positive."); - if(p == 0) - return Double.NEGATIVE_INFINITY; - if(p == 1) - return Double.POSITIVE_INFINITY; - if(sigma == 0) - return mu; - double q, r, val; - - q = p - 0.5; - - if(FastMath.abs(q) <= .425) { - r = .180625 - q * q; - val = - q * (((((((r * 2509.0809287301226727 + - 33430.575583588128105) * r + 67265.770927008700853) * r + - 45921.953931549871457) * r + 13731.693765509461125) * r + - 1971.5909503065514427) * r + 133.14166789178437745) * r + - 3.387132872796366608) - / (((((((r * 5226.495278852854561 + - 28729.085735721942674) * r + 39307.89580009271061) * r + - 21213.794301586595867) * r + 5394.1960214247511077) * r + - 687.1870074920579083) * r + 42.313330701600911252) * r + 1); - } else { - if(q > 0) { - r = 1 - p; - } else { - r = p; - } - - r = FastMath.sqrt(-FastMath.log(r)); - - if(r <= 5) { - r += -1.6; - val = (((((((r * 7.7454501427834140764e-4 + - .0227238449892691845833) * r + .24178072517745061177) * - r + 1.27045825245236838258) * r + - 3.64784832476320460504) * r + 5.7694972214606914055) * - r + 4.6303378461565452959) * r + - 1.42343711074968357734) - / (((((((r * - 1.05075007164441684324e-9 + 5.475938084995344946e-4) * - r + .0151986665636164571966) * r + - .14810397642748007459) * r + .68976733498510000455) * - r + 1.6763848301838038494) * r + - 2.05319162663775882187) * r + 1); - } else { - r += -5; - val = (((((((r * 2.01033439929228813265e-7 + - 2.71155556874348757815e-5) * r + - .0012426609473880784386) * r + .026532189526576123093) * - r + .29656057182850489123) * r + - 1.7848265399172913358) * r + 5.4637849111641143699) * - r + 6.6579046435011037772) - / (((((((r * - 2.04426310338993978564e-15 + 1.4215117583164458887e-7) * - r + 1.8463183175100546818e-5) * r + - 7.868691311456132591e-4) * r + .0148753612908506148525) - * r + .13692988092273580531) * r + - .59983220655588793769) * r + 1); - } - - if(q < 0.0) { - val = -val; - } - } - - return mu + sigma * val; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/NoiseSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/NoiseSampler.java deleted file mode 100644 index 34fc3704e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/NoiseSampler.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.api.math.noise; - -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; - -public interface NoiseSampler { - /** - * 2D noise at given position using current settings - *

- * Noise output bounded between -1...1 - */ - double getNoise(double x, double y); - - /** - * 3D noise at given position using current settings - *

- * Noise output bounded between -1...1 - */ - double getNoise(double x, double y, double z); - - default double getNoise(Vector3 vector3) { - return getNoise(vector3.getX(), vector3.getY(), vector3.getZ()); - } - - default double getNoise(Vector2 vector2) { - return getNoise(vector2.getX(), vector2.getZ()); - } - - double getNoiseSeeded(int seed, double x, double y); - - double getNoiseSeeded(int seed, double x, double y, double z); -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/Normalizer.java b/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/Normalizer.java deleted file mode 100644 index 19967130c..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/Normalizer.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dfsek.terra.api.math.noise.normalizer; - -import com.dfsek.terra.api.math.noise.NoiseSampler; - -public abstract class Normalizer implements NoiseSampler { - private final NoiseSampler sampler; - - public Normalizer(NoiseSampler sampler) { - this.sampler = sampler; - } - - public abstract double normalize(double in); - - @Override - public double getNoise(double x, double y) { - return normalize(sampler.getNoise(x, y)); - } - - @Override - public double getNoise(double x, double y, double z) { - return normalize(sampler.getNoise(x, y, z)); - } - - @Override - public double getNoiseSeeded(int seed, double x, double y) { - return normalize(sampler.getNoiseSeeded(seed, x, y)); - } - - @Override - public double getNoiseSeeded(int seed, double x, double y, double z) { - return normalize(sampler.getNoiseSeeded(seed, x, y, z)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/DomainWarpedSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/DomainWarpedSampler.java deleted file mode 100644 index cbaf053c7..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/DomainWarpedSampler.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dfsek.terra.api.math.noise.samplers; - -import com.dfsek.terra.api.math.noise.NoiseSampler; - -public class DomainWarpedSampler implements NoiseSampler { - private final NoiseSampler function; - private final NoiseSampler warp; - private final int seed; - private final double amplitude; - - public DomainWarpedSampler(NoiseSampler function, NoiseSampler warp, int seed, double amplitude) { - this.function = function; - this.warp = warp; - this.seed = seed; - this.amplitude = amplitude; - } - - @Override - public double getNoise(double x, double y) { - return getNoiseSeeded(seed, x, y); - } - - @Override - public double getNoise(double x, double y, double z) { - return getNoiseSeeded(seed, x, y, z); - } - - @Override - public double getNoiseSeeded(int seed, double x, double y) { - return function.getNoise( - x + warp.getNoiseSeeded(seed, x, y) * amplitude, - y + warp.getNoiseSeeded(seed + 1, x, y) * amplitude - ); - } - - @Override - public double getNoiseSeeded(int seed, double x, double y, double z) { - return function.getNoise( - x + warp.getNoiseSeeded(seed, x, y, z) * amplitude, - y + warp.getNoiseSeeded(seed + 1, x, y, z) * amplitude, - z + warp.getNoiseSeeded(seed + 2, x, y, z) * amplitude - ); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java deleted file mode 100644 index 8ca8f2333..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.dfsek.terra.api.math.noise.samplers; - -import com.dfsek.paralithic.Expression; -import com.dfsek.paralithic.eval.parser.Parser; -import com.dfsek.paralithic.eval.parser.Scope; -import com.dfsek.paralithic.eval.tokenizer.ParseException; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction; -import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction2; -import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction3; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; - -import java.util.Map; - -/** - * Sampler3D implementation using Paralithic expression - */ -public class ExpressionSampler implements NoiseSampler { - private final Expression expression; - - public ExpressionSampler(String equation, Scope parent, long seed, Map functions, Map definedFunctions) throws ParseException { - Parser parser = new Parser(); - Scope scope = new Scope().withParent(parent); - - scope.addInvocationVariable("x"); - scope.addInvocationVariable("y"); - scope.addInvocationVariable("z"); - - functions.forEach((id, noise) -> { - switch(noise.getDimensions()) { - case 2: - parser.registerFunction(id, new NoiseFunction2(noise.apply(seed))); - break; - case 3: - parser.registerFunction(id, new NoiseFunction3(noise.apply(seed))); - break; - } - }); - - for(Map.Entry entry : definedFunctions.entrySet()) { - parser.registerFunction(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), parser, parent)); - } - - this.expression = parser.parse(equation, scope); - } - - @Override - public double getNoise(double x, double y) { - return getNoise(x, 0, y); - } - - @Override - public double getNoise(double x, double y, double z) { - return expression.evaluate(x, y, z); - } - - @Override - public double getNoiseSeeded(int seed, double x, double y) { - return getNoise(x, y); - } - - @Override - public double getNoiseSeeded(int seed, double x, double y, double z) { - return getNoise(x, y, z); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/ConstantSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/ConstantSampler.java deleted file mode 100644 index 203a1a85f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/ConstantSampler.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dfsek.terra.api.math.noise.samplers.noise; - -/** - * Sampler3D implementation that returns a constant. - */ -public class ConstantSampler extends NoiseFunction { - private final double constant; - - public ConstantSampler(double constant) { - super(0); - this.constant = constant; - } - - @Override - public double getNoiseRaw(int seed, double x, double y) { - return constant; - } - - @Override - public double getNoiseRaw(int seed, double x, double y, double z) { - return constant; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/random/GaussianNoiseSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/random/GaussianNoiseSampler.java deleted file mode 100644 index 9843df3e4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/noise/random/GaussianNoiseSampler.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.dfsek.terra.api.math.noise.samplers.noise.random; - -import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction; - -/** - * NoiseSampler implementation to provide random, normally distributed (Gaussian) noise. - */ -public class GaussianNoiseSampler extends NoiseFunction { - private final WhiteNoiseSampler whiteNoiseSampler; // Back with a white noise sampler. - - public GaussianNoiseSampler(int seed) { - super(seed); - whiteNoiseSampler = new WhiteNoiseSampler(seed); - } - - @Override - public double getNoiseRaw(int seed, double x, double y) { - double v1, v2, s; - do { - v1 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y); - v2 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y); - s = v1 * v1 + v2 * v2; - } while(s >= 1 || s == 0); - double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s); - return v1 * multiplier; - } - - @Override - public double getNoiseRaw(int seed, double x, double y, double z) { - double v1, v2, s; - do { - v1 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y, z); - v2 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y, z); - s = v1 * v1 + v2 * v2; - } while(s >= 1 || s == 0); - double multiplier = StrictMath.sqrt(-2 * StrictMath.log(s) / s); - return v1 * multiplier; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/paralithic/BlankFunction.java b/common/src/main/java/com/dfsek/terra/api/math/paralithic/BlankFunction.java deleted file mode 100644 index 12cd1872a..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/paralithic/BlankFunction.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.api.math.paralithic; - - -import com.dfsek.paralithic.functions.dynamic.DynamicFunction; - -public class BlankFunction implements DynamicFunction { - private final int args; - - public BlankFunction(int args) { - this.args = args; - } - - @Override - public int getArgNumber() { - return args; - } - - @Override - public double eval(double... d) { - return 0; - } - - @Override - public boolean isStateless() { - return true; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/paralithic/defined/UserDefinedFunction.java b/common/src/main/java/com/dfsek/terra/api/math/paralithic/defined/UserDefinedFunction.java deleted file mode 100644 index 7058d8085..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/paralithic/defined/UserDefinedFunction.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dfsek.terra.api.math.paralithic.defined; - -import com.dfsek.paralithic.Expression; -import com.dfsek.paralithic.eval.parser.Parser; -import com.dfsek.paralithic.eval.parser.Scope; -import com.dfsek.paralithic.eval.tokenizer.ParseException; -import com.dfsek.paralithic.functions.dynamic.DynamicFunction; -import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; - - -public class UserDefinedFunction implements DynamicFunction { - private final Expression expression; - private final int args; - - protected UserDefinedFunction(Expression expression, int args) { - this.expression = expression; - this.args = args; - } - - - @Override - public double eval(double... args) { - return expression.evaluate(args); - } - - @Override - public boolean isStateless() { - return true; - } - - @Override - public int getArgNumber() { - return args; - } - - public static UserDefinedFunction newInstance(FunctionTemplate template, Parser parser, Scope parent) throws ParseException { - - Scope functionScope = new Scope().withParent(parent); - - template.getArgs().forEach(functionScope::addInvocationVariable); - - return new UserDefinedFunction(parser.parse(template.getFunction(), functionScope), template.getArgs().size()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction.java b/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction.java deleted file mode 100644 index 76b2bf39e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.math.paralithic.noise; - - -import com.dfsek.paralithic.functions.dynamic.DynamicFunction; - -public interface NoiseFunction extends DynamicFunction { -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction2.java b/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction2.java deleted file mode 100644 index f4a516375..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction2.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.dfsek.terra.api.math.paralithic.noise; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.hash.HashMapDoubleDouble; - - - -public class NoiseFunction2 implements NoiseFunction { - private final NoiseSampler gen; - private final Cache cache = new Cache(); - - public NoiseFunction2(NoiseSampler gen) { - this.gen = gen; - } - - @Override - public int getArgNumber() { - return 2; - } - - @Override - public double eval(double... args) { - return cache.get(gen, args[0], args[1]); - } - - @Override - public boolean isStateless() { - return true; - } - - private static class Cache extends HashMapDoubleDouble { - private static final long serialVersionUID = 8915092734723467010L; - private static final int cacheSize = 384; - - public Cache() { - super(cacheSize); - } - - public double get(NoiseSampler noise, double x, double z) { - double xx = x >= 0 ? x * 2 : x * -2 - 1; - double zz = z >= 0 ? z * 2 : z * -2 - 1; - double key = (xx >= zz) ? (xx * xx + xx + zz) : (zz * zz + xx); - double value = this.get(key); - if(this.size() > cacheSize) { - this.clear(); - } - return (value == 4.9E-324D ? addAndReturn(noise.getNoise(x, z), key) : value); - } - - private synchronized double addAndReturn(double value, double key) { - this.put(key, value); - return value; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction3.java b/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction3.java deleted file mode 100644 index 297a0d2cb..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/paralithic/noise/NoiseFunction3.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dfsek.terra.api.math.paralithic.noise; - -import com.dfsek.terra.api.math.noise.NoiseSampler; - -public class NoiseFunction3 implements NoiseFunction { - private final NoiseSampler gen; - - public NoiseFunction3(NoiseSampler gen) { - this.gen = gen; - } - - @Override - public int getArgNumber() { - return 3; - } - - @Override - public double eval(double... args) { - return gen.getNoise(args[0], args[1], args[2]); - } - - @Override - public boolean isStateless() { - return true; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/pixel/Distribution.java b/common/src/main/java/com/dfsek/terra/api/math/pixel/Distribution.java deleted file mode 100644 index a91f07028..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/pixel/Distribution.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.math.pixel; - -public class Distribution { - public Distribution(Rectangle bound, int numPoints, double minRad) { - - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/pixel/Polygon.java b/common/src/main/java/com/dfsek/terra/api/math/pixel/Polygon.java deleted file mode 100644 index 00f996fd7..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/pixel/Polygon.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.api.math.pixel; - -import com.dfsek.terra.api.math.vector.Vector2; - -import java.util.Set; - -@SuppressWarnings("unused") -public abstract class Polygon { - public abstract Set getContainedPixels(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/pixel/Rectangle.java b/common/src/main/java/com/dfsek/terra/api/math/pixel/Rectangle.java deleted file mode 100644 index 0eecb2f40..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/pixel/Rectangle.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.api.math.pixel; - -import com.dfsek.terra.api.math.vector.Vector2; -import net.jafama.FastMath; - -import java.util.HashSet; -import java.util.Set; - -@SuppressWarnings("unused") -public class Rectangle extends Polygon { - private final Vector2 min; - private final Vector2 max; - - public Rectangle(Vector2 min, Vector2 max) { - this.max = new Vector2(FastMath.min(min.getX(), max.getX()), FastMath.min(min.getZ(), max.getZ())); - this.min = new Vector2(FastMath.max(min.getX(), max.getX()), FastMath.max(min.getZ(), max.getZ())); - } - - public Rectangle(Vector2 center, double xRadius, double zRadius) { - Vector2 rad = new Vector2(xRadius, zRadius); - this.min = center.clone().subtract(rad); - this.max = center.clone().add(rad); - } - - @Override - public Set getContainedPixels() { - Set pixels = new HashSet<>(); - for(int x = (int) min.getX(); x <= max.getX(); x++) { - for(int z = (int) min.getZ(); z <= max.getZ(); z++) { - pixels.add(new Vector2(x, z)); - } - } - return pixels; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/vector/Location.java b/common/src/main/java/com/dfsek/terra/api/math/vector/Location.java deleted file mode 100644 index de01cce98..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/vector/Location.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.dfsek.terra.api.math.vector; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.world.World; - -import java.util.Objects; - -public class Location implements Cloneable { - private World world; - private Vector3 vector; - private double pitch; - private double yaw; - - public Location(World w, double x, double y, double z) { - this.world = w; - this.vector = new Vector3(x, y, z); - } - - public Location(World w, Vector3 vector) { - this.world = w; - this.vector = vector; - } - - public void setWorld(World world) { - this.world = world; - } - - public Vector3 getVector() { - return vector; - } - - public void setVector(Vector3 vector) { - this.vector = vector; - } - - @Override - public Location clone() { - try { - Location other = (Location) super.clone(); - other.setVector(other.getVector().clone()); - return other; - } catch(CloneNotSupportedException e) { - throw new Error(e); - } - } - - public int getBlockX() { - return vector.getBlockX(); - } - - public int getBlockY() { - return vector.getBlockY(); - } - - public int getBlockZ() { - return vector.getBlockZ(); - } - - public double getY() { - return vector.getY(); - } - - public Location setY(double y) { - vector.setY(y); - return this; - } - - public double getX() { - return vector.getX(); - } - - public Location setX(double x) { - vector.setX(x); - return this; - } - - public double getZ() { - return vector.getZ(); - } - - public Location setZ(double z) { - vector.setZ(z); - return this; - } - - public World getWorld() { - return world; - } - - public Location add(double x, double y, double z) { - vector.add(x, y, z); - return this; - } - - public Block getBlock() { - return world.getBlockAt(this); - } - - public Location subtract(int x, int y, int z) { - vector.subtract(x, y, z); - return this; - } - - public Location add(Vector3 add) { - vector.add(add); - return this; - } - - public Location add(Location add) { - vector.add(add.toVector()); - return this; - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof Location)) { - return false; - } - final Location other = (Location) obj; - - World world = this.world; - World otherWorld = other.world; - if(!Objects.equals(world, otherWorld)) { - return false; - } - if(Double.doubleToLongBits(this.vector.getX()) != Double.doubleToLongBits(other.vector.getX())) { - return false; - } - if(Double.doubleToLongBits(this.vector.getY()) != Double.doubleToLongBits(other.vector.getY())) { - return false; - } - return Double.doubleToLongBits(this.vector.getZ()) == Double.doubleToLongBits(other.vector.getZ()); - } - - public double getPitch() { - return pitch; - } - - public void setPitch(double pitch) { - this.pitch = pitch; - } - - public double getYaw() { - return yaw; - } - - public void setYaw(double yaw) { - this.yaw = yaw; - } - - @Override - public int hashCode() { - int hash = 3; - - World world = (this.world == null) ? null : this.world; - hash = 19 * hash + (world != null ? world.hashCode() : 0); - hash = 19 * hash + (int) (Double.doubleToLongBits(this.vector.getX()) ^ (Double.doubleToLongBits(this.vector.getX()) >>> 32)); - hash = 19 * hash + (int) (Double.doubleToLongBits(this.vector.getY()) ^ (Double.doubleToLongBits(this.vector.getY()) >>> 32)); - hash = 19 * hash + (int) (Double.doubleToLongBits(this.vector.getZ()) ^ (Double.doubleToLongBits(this.vector.getZ()) >>> 32)); - hash = 19 * hash + (int) (Double.doubleToLongBits(this.pitch) ^ Double.doubleToLongBits(this.pitch) >>> 32); - hash = 19 * hash + (int) (Double.doubleToLongBits(this.yaw) ^ Double.doubleToLongBits(this.yaw) >>> 32); - return hash; - } - - public Vector3 toVector() { - return vector.clone(); - } - - @Override - public String toString() { - return "[" + world + ": (" + getX() + ", " + getY() + ", " + getZ() + ")]"; - } - - public Location multiply(double v) { - vector.multiply(v); - return this; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/vector/Vector2.java b/common/src/main/java/com/dfsek/terra/api/math/vector/Vector2.java deleted file mode 100644 index 8513e56d2..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/vector/Vector2.java +++ /dev/null @@ -1,192 +0,0 @@ -package com.dfsek.terra.api.math.vector; - -import com.dfsek.terra.api.math.MathUtil; -import net.jafama.FastMath; - -/** - * oh yeah - */ -public class Vector2 implements Cloneable { - private double x; - private double z; - - /** - * Create a vector with a given X and Z component - * - * @param x X component - * @param z Z component - */ - public Vector2(double x, double z) { - this.x = x; - this.z = z; - } - - /** - * Get X component - * - * @return X component - */ - public double getX() { - return x; - } - - public Vector2 setX(double x) { - this.x = x; - return this; - } - - /** - * Get Z component - * - * @return Z component - */ - public double getZ() { - return z; - } - - public Vector2 setZ(double z) { - this.z = z; - return this; - } - - /** - * Multiply X and Z components by a value. - * - * @param m Value to multiply - * @return Mutated vector, for chaining. - */ - public Vector2 multiply(double m) { - x *= m; - z *= m; - return this; - } - - /** - * Add this vector to another. - * - * @param other Vector to add - * @return Mutated vector, for chaining. - */ - public Vector2 add(Vector2 other) { - x += other.x; - z += other.z; - return this; - } - - /** - * Subtract a vector from this vector, - * - * @param other Vector to subtract - * @return Mutated vector, for chaining. - */ - public Vector2 subtract(Vector2 other) { - x -= other.x; - z -= other.z; - return this; - } - - /** - * Normalize this vector to length 1 - * - * @return Mutated vector, for chaining. - */ - public Vector2 normalize() { - divide(length()); - return this; - } - - /** - * Divide X and Z components by a value. - * - * @param d Divisor - * @return Mutated vector, for chaining. - */ - public Vector2 divide(double d) { - x /= d; - z /= d; - return this; - } - - /** - * Get the length of this Vector - * - * @return length - */ - public double length() { - return FastMath.sqrt(lengthSquared()); - } - - /** - * Get the squared length of this Vector - * - * @return squared length - */ - public double lengthSquared() { - return x * x + z * z; - } - - /** - * Get the distance from this vector to another. - * - * @param other Another vector - * @return Distance between vectors - */ - public double distance(Vector2 other) { - return FastMath.sqrt(distanceSquared(other)); - } - - /** - * Get the squared distance between 2 vectors. - * - * @param other Another vector - * @return Squared distance - */ - public double distanceSquared(Vector2 other) { - double dx = other.x - x; - double dz = other.z - z; - return dx * dx + dz * dz; - } - - @Override - public int hashCode() { - int hash = 17; - hash = 31 * hash + Double.hashCode(x); - hash = 31 * hash + Double.hashCode(z); - return hash; - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof Vector2)) return false; - Vector2 other = (Vector2) obj; - return MathUtil.equals(this.x, other.x) && MathUtil.equals(this.z, other.z); - } - - @Override - public Vector2 clone() { - try { - return (Vector2) super.clone(); - } catch(CloneNotSupportedException e) { - throw new Error(e); - } - } - - public Vector2 add(double x, double z) { - this.x += x; - this.z += z; - return this; - } - - public int getBlockX() { - return FastMath.floorToInt(x); - } - - public int getBlockZ() { - return FastMath.floorToInt(z); - } - - @Override - public String toString() { - return "(" + x + ", " + z + ")"; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/vector/Vector3.java b/common/src/main/java/com/dfsek/terra/api/math/vector/Vector3.java deleted file mode 100644 index b422a1019..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/vector/Vector3.java +++ /dev/null @@ -1,341 +0,0 @@ -package com.dfsek.terra.api.math.vector; - -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.platform.world.World; -import net.jafama.FastMath; -import org.jetbrains.annotations.NotNull; - -/** - * 3D Mutable Vector - */ -public class Vector3 implements Cloneable { - - - private double x; - private double y; - private double z; - - public Vector3(double x, double y, double z) { - this.x = x; - this.y = y; - this.z = z; - } - - public double getZ() { - return z; - } - - public Vector3 setZ(double z) { - this.z = z; - return this; - } - - public double getX() { - return x; - } - - public Vector3 setX(double x) { - this.x = x; - return this; - } - - public double getY() { - return y; - } - - public Vector3 setY(double y) { - this.y = y; - return this; - } - - public int getBlockX() { - return FastMath.floorToInt(x); - } - - public int getBlockY() { - return FastMath.floorToInt(y); - } - - public int getBlockZ() { - return FastMath.floorToInt(z); - } - - public Vector3 multiply(double m) { - x *= m; - y *= m; - z *= m; - return this; - } - - public Vector3 add(double x, double y, double z) { - this.x += x; - this.y += y; - this.z += z; - return this; - } - - public Vector3 add(Vector3 other) { - this.x += other.getX(); - this.y += other.getY(); - this.z += other.getZ(); - return this; - } - - public Vector3 add(Vector2 other) { - this.x += other.getX(); - this.z += other.getZ(); - return this; - } - - public double lengthSquared() { - return x * x + y * y + z * z; - } - - @Override - public Vector3 clone() { - try { - return (Vector3) super.clone(); - } catch(CloneNotSupportedException e) { - throw new Error(e); - } - } - - public double length() { - return FastMath.sqrt(lengthSquared()); - } - - public double inverseLength() { - return FastMath.invSqrtQuick(lengthSquared()); - } - - /** - * Returns if a vector is normalized - * - * @return whether the vector is normalised - */ - public boolean isNormalized() { - return MathUtil.equals(this.lengthSquared(), 1); - } - - /** - * Rotates the vector around the x axis. - *

- * This piece of math is based on the standard rotation matrix for vectors - * in three dimensional space. This matrix can be found here: - * Rotation - * Matrix. - * - * @param angle the angle to rotate the vector about. This angle is passed - * in radians - * @return the same vector - */ - @NotNull - public Vector3 rotateAroundX(double angle) { - double angleCos = Math.cos(angle); - double angleSin = Math.sin(angle); - - double y = angleCos * getY() - angleSin * getZ(); - double z = angleSin * getY() + angleCos * getZ(); - return setY(y).setZ(z); - } - - /** - * Rotates the vector around the y axis. - *

- * This piece of math is based on the standard rotation matrix for vectors - * in three dimensional space. This matrix can be found here: - * Rotation - * Matrix. - * - * @param angle the angle to rotate the vector about. This angle is passed - * in radians - * @return the same vector - */ - @NotNull - public Vector3 rotateAroundY(double angle) { - double angleCos = Math.cos(angle); - double angleSin = Math.sin(angle); - - double x = angleCos * getX() + angleSin * getZ(); - double z = -angleSin * getX() + angleCos * getZ(); - return setX(x).setZ(z); - } - - /** - * Rotates the vector around the z axis - *

- * This piece of math is based on the standard rotation matrix for vectors - * in three dimensional space. This matrix can be found here: - * Rotation - * Matrix. - * - * @param angle the angle to rotate the vector about. This angle is passed - * in radians - * @return the same vector - */ - @NotNull - public Vector3 rotateAroundZ(double angle) { - double angleCos = Math.cos(angle); - double angleSin = Math.sin(angle); - - double x = angleCos * getX() - angleSin * getY(); - double y = angleSin * getX() + angleCos * getY(); - return setX(x).setY(y); - } - - /** - * Get the distance between this vector and another. The value of this - * method is not cached and uses a costly square-root function, so do not - * repeatedly call this method to get the vector's magnitude. NaN will be - * returned if the inner result of the sqrt() function overflows, which - * will be caused if the distance is too long. - * - * @param o The other vector - * @return the distance - */ - public double distance(@NotNull Vector3 o) { - return FastMath.sqrt(FastMath.pow2(x - o.x) + FastMath.pow2(y - o.y) + FastMath.pow2(z - o.z)); - } - - /** - * Get the squared distance between this vector and another. - * - * @param o The other vector - * @return the distance - */ - public double distanceSquared(@NotNull Vector3 o) { - return FastMath.pow2(x - o.x) + FastMath.pow2(y - o.y) + FastMath.pow2(z - o.z); - } - - /** - * Rotates the vector around a given arbitrary axis in 3 dimensional space. - * - *

- * Rotation will follow the general Right-Hand-Rule, which means rotation - * will be counterclockwise when the axis is pointing towards the observer. - *

- * This method will always make sure the provided axis is a unit vector, to - * not modify the length of the vector when rotating. - * - * @param axis the axis to rotate the vector around. If the passed vector is - * not of length 1, it gets copied and normalized before using it for the - * rotation. Please use {@link Vector3#normalize()} on the instance before - * passing it to this method - * @param angle the angle to rotate the vector around the axis - * @return the same vector - * @throws IllegalArgumentException if the provided axis vector instance is - * null - */ - @NotNull - public Vector3 rotateAroundAxis(@NotNull Vector3 axis, double angle) throws IllegalArgumentException { - return rotateAroundNonUnitAxis(axis.isNormalized() ? axis : axis.clone().normalize(), angle); - } - - /** - * Rotates the vector around a given arbitrary axis in 3 dimensional space. - * - *

- * Rotation will follow the general Right-Hand-Rule, which means rotation - * will be counterclockwise when the axis is pointing towards the observer. - *

- * Note that the vector length will change accordingly to the axis vector - * length. If the provided axis is not a unit vector, the rotated vector - * will not have its previous length. The scaled length of the resulting - * vector will be related to the axis vector. - * - * @param axis the axis to rotate the vector around. - * @param angle the angle to rotate the vector around the axis - * @return the same vector - * @throws IllegalArgumentException if the provided axis vector instance is - * null - */ - @NotNull - public Vector3 rotateAroundNonUnitAxis(@NotNull Vector3 axis, double angle) throws IllegalArgumentException { - double x = getX(), y = getY(), z = getZ(); - double x2 = axis.getX(), y2 = axis.getY(), z2 = axis.getZ(); - - double cosTheta = Math.cos(angle); - double sinTheta = Math.sin(angle); - double dotProduct = this.dot(axis); - - double xPrime = x2 * dotProduct * (1d - cosTheta) - + x * cosTheta - + (-z2 * y + y2 * z) * sinTheta; - double yPrime = y2 * dotProduct * (1d - cosTheta) - + y * cosTheta - + (z2 * x - x2 * z) * sinTheta; - double zPrime = z2 * dotProduct * (1d - cosTheta) - + z * cosTheta - + (-y2 * x + x2 * y) * sinTheta; - - return setX(xPrime).setY(yPrime).setZ(zPrime); - } - - /** - * Calculates the dot product of this vector with another. The dot product - * is defined as x1*x2+y1*y2+z1*z2. The returned value is a scalar. - * - * @param other The other vector - * @return dot product - */ - public double dot(@NotNull Vector3 other) { - return x * other.x + y * other.y + z * other.z; - } - - public Location toLocation(World world) { - return new Location(world, this.clone()); - } - - public Vector3 normalize() { - return this.multiply(this.inverseLength()); - } - - public Vector3 subtract(int x, int y, int z) { - this.x -= x; - this.y -= y; - this.z -= z; - return this; - } - - public Vector3 subtract(Vector3 end) { - x -= end.x; - y -= end.y; - z -= end.z; - return this; - } - - /** - * Returns a hash code for this vector - * - * @return hash code - */ - @Override - public int hashCode() { - int hash = 7; - - hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); - hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); - hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); - return hash; - } - - /** - * Checks to see if two objects are equal. - *

- * Only two Vectors can ever return true. This method uses a fuzzy match - * to account for floating point errors. The epsilon can be retrieved - * with epsilon. - */ - @Override - public boolean equals(Object obj) { - if(!(obj instanceof Vector3)) return false; - Vector3 other = (Vector3) obj; - return MathUtil.equals(x, other.x) && MathUtil.equals(y, other.y) && MathUtil.equals(x, other.z); - } - - @Override - public String toString() { - return "(" + getX() + ", " + getY() + ", " + getZ() + ")"; - } - -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/voxel/Cylinder.java b/common/src/main/java/com/dfsek/terra/api/math/voxel/Cylinder.java deleted file mode 100644 index 44d5558c3..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/voxel/Cylinder.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.api.math.voxel; - - -import com.dfsek.terra.api.math.vector.Vector3; - -public class Cylinder extends VoxelGeometry { - public Cylinder(Vector3 start, int rad, int height) { - - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/voxel/DeformedSphere.java b/common/src/main/java/com/dfsek/terra/api/math/voxel/DeformedSphere.java deleted file mode 100644 index 668a0ccdc..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/voxel/DeformedSphere.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.api.math.voxel; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.vector.Vector3; - -public class DeformedSphere extends VoxelGeometry { - public DeformedSphere(Vector3 start, int rad, double deform, NoiseSampler noise) { - for(int x = -rad; x <= rad; x++) { - for(int y = -rad; y <= rad; y++) { - for(int z = -rad; z <= rad; z++) { - Vector3 c = new Vector3(x, y, z); - if(c.length() < (rad + 0.5) * ((noise.getNoise(x, y, z) + 1) * deform)) { - addVector(c.add(start)); - } - } - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/voxel/Sphere.java b/common/src/main/java/com/dfsek/terra/api/math/voxel/Sphere.java deleted file mode 100644 index ced0cb3cd..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/voxel/Sphere.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.api.math.voxel; - -import com.dfsek.terra.api.math.vector.Vector3; - -public class Sphere extends VoxelGeometry { - public Sphere(Vector3 start, int rad) { - for(int x = -rad; x <= rad; x++) { - for(int y = -rad; y <= rad; y++) { - for(int z = -rad; z <= rad; z++) { - Vector3 c = new Vector3(x, y, z); - if(c.length() < rad + 0.5) { - addVector(c.add(start)); - } - } - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/voxel/Tube.java b/common/src/main/java/com/dfsek/terra/api/math/voxel/Tube.java deleted file mode 100644 index 7e0af69fc..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/voxel/Tube.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.api.math.voxel; - -import com.dfsek.terra.api.math.vector.Vector3; - -public class Tube extends VoxelGeometry { - public Tube(Vector3 start, Vector3 end, int radius) { - Vector3 step = start.clone().subtract(end).normalize(); - Vector3 run = start.clone(); - int steps = (int) start.distance(end); - for(int i = 0; i < steps; i++) { - merge(new Sphere(run, radius)); - run.add(step); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/math/voxel/VoxelGeometry.java b/common/src/main/java/com/dfsek/terra/api/math/voxel/VoxelGeometry.java deleted file mode 100644 index dccbe3f1c..000000000 --- a/common/src/main/java/com/dfsek/terra/api/math/voxel/VoxelGeometry.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.api.math.voxel; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.util.GlueList; - -import java.util.List; - -public abstract class VoxelGeometry { - private final List geometry = new GlueList<>(); - - public static VoxelGeometry getBlank() { - return new VoxelGeometry() { - }; - } - - public List getGeometry() { - return geometry; - } - - protected void addVector(Vector3 v) { - geometry.add(v); - } - - public void merge(VoxelGeometry other) { - geometry.addAll(other.geometry); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/CommandSender.java b/common/src/main/java/com/dfsek/terra/api/platform/CommandSender.java deleted file mode 100644 index 5fd7d60a7..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/CommandSender.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.dfsek.terra.api.platform; - -public interface CommandSender extends Handle { - void sendMessage(String message); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/Handle.java b/common/src/main/java/com/dfsek/terra/api/platform/Handle.java deleted file mode 100644 index 4f27ad55b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/Handle.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.api.platform; - -/** - * An interface that contains a platform delegate. - */ -public interface Handle { - /** - * Gets the delegate object. - * - * @return Delegate - */ - Object getHandle(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/Axis.java b/common/src/main/java/com/dfsek/terra/api/platform/block/Axis.java deleted file mode 100644 index 38236b3b1..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/Axis.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.dfsek.terra.api.platform.block; - -public enum Axis { - X, Y, Z -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/Block.java b/common/src/main/java/com/dfsek/terra/api/platform/block/Block.java deleted file mode 100644 index b6132ef0a..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/Block.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.api.platform.block; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.platform.block.state.BlockState; - -public interface Block extends Handle { - void setBlockData(BlockData data, boolean physics); - - BlockData getBlockData(); - - BlockState getState(); - - default Block getRelative(BlockFace face) { - return getRelative(face, 1); - } - - Block getRelative(BlockFace face, int len); - - boolean isEmpty(); - - Location getLocation(); - - default BlockType getType() { - return getBlockData().getBlockType(); - } - - int getX(); - - int getZ(); - - int getY(); - - boolean isPassable(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockData.java b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockData.java deleted file mode 100644 index 3082a2184..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockData.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.api.platform.block; - -import com.dfsek.terra.api.platform.Handle; - -public interface BlockData extends Cloneable, Handle { - - BlockType getBlockType(); - - boolean matches(BlockData other); - - BlockData clone(); - - String getAsString(); - - boolean isAir(); - - boolean isStructureVoid(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockFace.java b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockFace.java deleted file mode 100644 index 4f9bcb904..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockFace.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.dfsek.terra.api.platform.block; - -import com.dfsek.terra.api.math.vector.Vector3; -import org.jetbrains.annotations.NotNull; - -public enum BlockFace { - NORTH(0, 0, -1), - EAST(1, 0, 0), - SOUTH(0, 0, 1), - WEST(-1, 0, 0), - UP(0, 1, 0), - DOWN(0, -1, 0), - NORTH_EAST(NORTH, EAST), - NORTH_WEST(NORTH, WEST), - SOUTH_EAST(SOUTH, EAST), - SOUTH_WEST(SOUTH, WEST), - WEST_NORTH_WEST(WEST, NORTH_WEST), - NORTH_NORTH_WEST(NORTH, NORTH_WEST), - NORTH_NORTH_EAST(NORTH, NORTH_EAST), - EAST_NORTH_EAST(EAST, NORTH_EAST), - EAST_SOUTH_EAST(EAST, SOUTH_EAST), - SOUTH_SOUTH_EAST(SOUTH, SOUTH_EAST), - SOUTH_SOUTH_WEST(SOUTH, SOUTH_WEST), - WEST_SOUTH_WEST(WEST, SOUTH_WEST), - SELF(0, 0, 0); - - private final int modX; - private final int modY; - private final int modZ; - - BlockFace(final int modX, final int modY, final int modZ) { - this.modX = modX; - this.modY = modY; - this.modZ = modZ; - } - - BlockFace(final BlockFace face1, final BlockFace face2) { - this.modX = face1.getModX() + face2.getModX(); - this.modY = face1.getModY() + face2.getModY(); - this.modZ = face1.getModZ() + face2.getModZ(); - } - - /** - * Get the amount of X-coordinates to modify to get the represented block - * - * @return Amount of X-coordinates to modify - */ - public int getModX() { - return modX; - } - - /** - * Get the amount of Y-coordinates to modify to get the represented block - * - * @return Amount of Y-coordinates to modify - */ - public int getModY() { - return modY; - } - - /** - * Get the amount of Z-coordinates to modify to get the represented block - * - * @return Amount of Z-coordinates to modify - */ - public int getModZ() { - return modZ; - } - - /** - * Gets the normal vector corresponding to this block face. - * - * @return the normal vector - */ - @NotNull - public Vector3 getDirection() { - Vector3 direction = new Vector3(modX, modY, modZ); - if(modX != 0 || modY != 0 || modZ != 0) { - direction.normalize(); - } - return direction; - } - - @NotNull - public BlockFace getOppositeFace() { - switch(this) { - case NORTH: - return BlockFace.SOUTH; - - case SOUTH: - return BlockFace.NORTH; - - case EAST: - return BlockFace.WEST; - - case WEST: - return BlockFace.EAST; - - case UP: - return BlockFace.DOWN; - - case DOWN: - return BlockFace.UP; - - case NORTH_EAST: - return BlockFace.SOUTH_WEST; - - case NORTH_WEST: - return BlockFace.SOUTH_EAST; - - case SOUTH_EAST: - return BlockFace.NORTH_WEST; - - case SOUTH_WEST: - return BlockFace.NORTH_EAST; - - case WEST_NORTH_WEST: - return BlockFace.EAST_SOUTH_EAST; - - case NORTH_NORTH_WEST: - return BlockFace.SOUTH_SOUTH_EAST; - - case NORTH_NORTH_EAST: - return BlockFace.SOUTH_SOUTH_WEST; - - case EAST_NORTH_EAST: - return BlockFace.WEST_SOUTH_WEST; - - case EAST_SOUTH_EAST: - return BlockFace.WEST_NORTH_WEST; - - case SOUTH_SOUTH_EAST: - return BlockFace.NORTH_NORTH_WEST; - - case SOUTH_SOUTH_WEST: - return BlockFace.NORTH_NORTH_EAST; - - case WEST_SOUTH_WEST: - return BlockFace.EAST_NORTH_EAST; - - case SELF: - return BlockFace.SELF; - } - - return BlockFace.SELF; - } -} - diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockType.java b/common/src/main/java/com/dfsek/terra/api/platform/block/BlockType.java deleted file mode 100644 index 0703f02f1..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/BlockType.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.api.platform.block; - -import com.dfsek.terra.api.platform.Handle; - -public interface BlockType extends Handle { - BlockData getDefaultData(); - - boolean isSolid(); - - boolean isWater(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/AnaloguePowerable.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/AnaloguePowerable.java deleted file mode 100644 index 7c9ea0a7e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/AnaloguePowerable.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; - -public interface AnaloguePowerable extends BlockData { - int getMaximumPower(); - int getPower(); - void setPower(int power); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Bisected.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Bisected.java deleted file mode 100644 index a1061e33b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Bisected.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; - -public interface Bisected extends BlockData { - Half getHalf(); - - void setHalf(Half half); - - enum Half { - /** - * The top half of the block, normally with the higher y coordinate. - */ - TOP, - /** - * The bottom half of the block, normally with the lower y coordinate. - */ - BOTTOM - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Directional.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Directional.java deleted file mode 100644 index 6857121e3..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Directional.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; - -public interface Directional extends BlockData { - BlockFace getFacing(); - - void setFacing(BlockFace facing); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/MultipleFacing.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/MultipleFacing.java deleted file mode 100644 index bf57c54d4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/MultipleFacing.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; - -import java.util.Set; - -public interface MultipleFacing extends BlockData { - Set getFaces(); - - void setFace(BlockFace face, boolean facing); - - Set getAllowedFaces(); - - boolean hasFace(BlockFace f); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Orientable.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Orientable.java deleted file mode 100644 index ff3cf79e3..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Orientable.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -import com.dfsek.terra.api.platform.block.Axis; -import com.dfsek.terra.api.platform.block.BlockData; - -import java.util.Set; - -public interface Orientable extends BlockData { - Set getAxes(); - - Axis getAxis(); - - void setAxis(Axis axis); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rail.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rail.java deleted file mode 100644 index 4436d11fb..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rail.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; - -public interface Rail extends BlockData { - Shape getShape(); - - void setShape(Shape newShape); - - enum Shape { - ASCENDING_EAST, - ASCENDING_NORTH, - ASCENDING_SOUTH, - ASCENDING_WEST, - EAST_WEST, - NORTH_EAST, - NORTH_SOUTH, - NORTH_WEST, - SOUTH_EAST, - SOUTH_WEST - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/RedstoneWire.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/RedstoneWire.java deleted file mode 100644 index 6f9602de8..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/RedstoneWire.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; - -import java.util.Set; - -public interface RedstoneWire extends BlockData, AnaloguePowerable { - Set getAllowedFaces(); - Connection getFace(BlockFace face); - void setFace(BlockFace face, Connection connection); - enum Connection { - NONE, SIDE, UP - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rotatable.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rotatable.java deleted file mode 100644 index 58f23989e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Rotatable.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; - -public interface Rotatable extends BlockData { - BlockFace getRotation(); - - void setRotation(BlockFace face); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Slab.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Slab.java deleted file mode 100644 index d813c8938..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Slab.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -public interface Slab extends Waterlogged { - Type getType(); - - void setType(Type type); - - enum Type { - TOP, BOTTOM, DOUBLE - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Stairs.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Stairs.java deleted file mode 100644 index 9ed5382aa..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Stairs.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -public interface Stairs extends Waterlogged, Directional, Bisected { - Shape getShape(); - - void setShape(Shape shape); - - enum Shape { - /** - * Regular stair block. - */ - STRAIGHT, - /** - * Inner corner stair block with higher left side. - */ - INNER_LEFT, - /** - * Inner corner stair block with higher right side. - */ - INNER_RIGHT, - /** - * Outer corner stair block with higher left side. - */ - OUTER_LEFT, - /** - * Outer corner stair block with higher right side. - */ - OUTER_RIGHT - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Wall.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Wall.java deleted file mode 100644 index 5d891a0da..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Wall.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; - -public interface Wall extends BlockData, Waterlogged { - boolean isUp(); - void setHeight(BlockFace face, Height height); - Height getHeight(BlockFace face); - void setUp(boolean up); - - enum Height { - LOW, NONE, TALL - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Waterlogged.java b/common/src/main/java/com/dfsek/terra/api/platform/block/data/Waterlogged.java deleted file mode 100644 index 3d5d3fed8..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/data/Waterlogged.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dfsek.terra.api.platform.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; - -public interface Waterlogged extends BlockData { - boolean isWaterlogged(); - - void setWaterlogged(boolean waterlogged); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/state/BlockState.java b/common/src/main/java/com/dfsek/terra/api/platform/block/state/BlockState.java deleted file mode 100644 index 47f5f51b7..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/state/BlockState.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dfsek.terra.api.platform.block.state; - -import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; - -public interface BlockState extends Handle { - Block getBlock(); - - int getX(); - - int getY(); - - int getZ(); - - BlockData getBlockData(); - - boolean update(boolean applyPhysics); - - default void applyState(String state) { - // Do nothing by default. - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/state/Container.java b/common/src/main/java/com/dfsek/terra/api/platform/block/state/Container.java deleted file mode 100644 index 450b8d09a..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/state/Container.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.dfsek.terra.api.platform.block.state; - -import com.dfsek.terra.api.platform.inventory.BlockInventoryHolder; - -public interface Container extends BlockState, BlockInventoryHolder { -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/block/state/Sign.java b/common/src/main/java/com/dfsek/terra/api/platform/block/state/Sign.java deleted file mode 100644 index 0cc901816..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/block/state/Sign.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.api.platform.block.state; - -import org.jetbrains.annotations.NotNull; - -public interface Sign extends BlockState { - @NotNull String[] getLines(); - - @NotNull String getLine(int index) throws IndexOutOfBoundsException; - - void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException; -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java b/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java deleted file mode 100644 index 51c9be6e5..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/entity/Entity.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.platform.entity; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.platform.world.World; - -public interface Entity extends Handle, CommandSender { - Location getLocation(); - - void setLocation(Location location); - - World getWorld(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/entity/EntityType.java b/common/src/main/java/com/dfsek/terra/api/platform/entity/EntityType.java deleted file mode 100644 index d893b967b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/entity/EntityType.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.dfsek.terra.api.platform.entity; - -import com.dfsek.terra.api.platform.Handle; - -public interface EntityType extends Handle { -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/entity/Player.java b/common/src/main/java/com/dfsek/terra/api/platform/entity/Player.java deleted file mode 100644 index 43a002089..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/entity/Player.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.dfsek.terra.api.platform.entity; - -public interface Player extends Entity { -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/handle/ItemHandle.java b/common/src/main/java/com/dfsek/terra/api/platform/handle/ItemHandle.java deleted file mode 100644 index 1c76e225d..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/handle/ItemHandle.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.api.platform.handle; - -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; - -import java.util.Set; - -public interface ItemHandle { - - Item createItem(String data); - - Enchantment getEnchantment(String id); - - Set getEnchantments(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/handle/WorldHandle.java b/common/src/main/java/com/dfsek/terra/api/platform/handle/WorldHandle.java deleted file mode 100644 index 776b695a5..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/handle/WorldHandle.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dfsek.terra.api.platform.handle; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.util.generic.pair.Pair; - -/** - * Interface to be implemented for world manipulation. - */ -public interface WorldHandle { - BlockData createBlockData(String data); - - EntityType getEntity(String id); - - /** - * Get the locations selected by a player. (Usually via WorldEdit) - * - * @param player Player to get locations for - * @return Pair of locations. - */ - default Pair getSelectedLocation(Player player) { - throw new UnsupportedOperationException("Cannot get selection on this platform."); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/BlockInventoryHolder.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/BlockInventoryHolder.java deleted file mode 100644 index 157d8837e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/inventory/BlockInventoryHolder.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.platform.inventory; - -import com.dfsek.terra.api.platform.block.Block; - -public interface BlockInventoryHolder extends InventoryHolder { - Block getBlock(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/Inventory.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/Inventory.java deleted file mode 100644 index 776a23614..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/inventory/Inventory.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.api.platform.inventory; - -import com.dfsek.terra.api.platform.Handle; - -public interface Inventory extends Handle { - int getSize(); - - ItemStack getItem(int slot); - - void setItem(int slot, ItemStack newStack); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/InventoryHolder.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/InventoryHolder.java deleted file mode 100644 index c8550a121..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/inventory/InventoryHolder.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.platform.inventory; - -import com.dfsek.terra.api.platform.Handle; - -public interface InventoryHolder extends Handle { - Inventory getInventory(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/Item.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/Item.java deleted file mode 100644 index 4fa70ede3..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/inventory/Item.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.api.platform.inventory; - -import com.dfsek.terra.api.platform.Handle; - -/** - * An inventory item. - */ -public interface Item extends Handle { - ItemStack newItemStack(int amount); - - double getMaxDurability(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/ItemStack.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/ItemStack.java deleted file mode 100644 index 5b7ac6906..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/inventory/ItemStack.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.api.platform.inventory; - -import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.platform.inventory.item.Damageable; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; - -public interface ItemStack extends Handle { - int getAmount(); - - void setAmount(int i); - - Item getType(); - - ItemMeta getItemMeta(); - - void setItemMeta(ItemMeta meta); - - default boolean isDamageable() { - return getItemMeta() instanceof Damageable; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Damageable.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Damageable.java deleted file mode 100644 index 160388c94..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Damageable.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.api.platform.inventory.item; - -import com.dfsek.terra.api.platform.Handle; - -public interface Damageable extends Handle { - int getDamage(); - - void setDamage(int damage); - - boolean hasDamage(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Enchantment.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Enchantment.java deleted file mode 100644 index e8f404f34..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/Enchantment.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.platform.inventory.item; - -import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.platform.inventory.ItemStack; - -public interface Enchantment extends Handle { - boolean canEnchantItem(ItemStack itemStack); - - String getID(); - - boolean conflictsWith(Enchantment other); - - int getMaxLevel(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/ItemMeta.java b/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/ItemMeta.java deleted file mode 100644 index 0189c5755..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/inventory/item/ItemMeta.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.api.platform.inventory.item; - -import com.dfsek.terra.api.platform.Handle; - -import java.util.Map; - -public interface ItemMeta extends Handle { - Map getEnchantments(); - - void addEnchantment(Enchantment enchantment, int level); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/package-info.java b/common/src/main/java/com/dfsek/terra/api/platform/package-info.java deleted file mode 100644 index 44377a381..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * API for platform implementations. Mostly interfaces to be implemented by platform delegates. - *

- * Interfaces in this package generally should not be implemented by addons. - */ -package com.dfsek.terra.api.platform; diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/Biome.java b/common/src/main/java/com/dfsek/terra/api/platform/world/Biome.java deleted file mode 100644 index ec1b2060d..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/Biome.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.dfsek.terra.api.platform.world; - -import com.dfsek.terra.api.platform.Handle; - -public interface Biome extends Handle { -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/BiomeGrid.java b/common/src/main/java/com/dfsek/terra/api/platform/world/BiomeGrid.java deleted file mode 100644 index 0fe72dd42..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/BiomeGrid.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.api.platform.world; - -import com.dfsek.terra.api.platform.Handle; -import org.jetbrains.annotations.NotNull; - -public interface BiomeGrid extends Handle { - /** - * Get biome at x, z within chunk being generated - * - * @param x - 0-15 - * @param z - 0-15 - * @return Biome value - */ - @NotNull - Biome getBiome(int x, int z); - - /** - * Get biome at x, z within chunk being generated - * - * @param x - 0-15 - * @param y - 0-255 - * @param z - 0-15 - * @return Biome value - */ - @NotNull - Biome getBiome(int x, int y, int z); - - /** - * Set biome at x, z within chunk being generated - * - * @param x - 0-15 - * @param z - 0-15 - * @param bio - Biome value - */ - void setBiome(int x, int z, @NotNull Biome bio); - - /** - * Set biome at x, z within chunk being generated - * - * @param x - 0-15 - * @param y - 0-255 - * @param z - 0-15 - * @param bio - Biome value - */ - void setBiome(int x, int y, int z, @NotNull Biome bio); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/Chunk.java b/common/src/main/java/com/dfsek/terra/api/platform/world/Chunk.java deleted file mode 100644 index 0ba30f288..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/Chunk.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.api.platform.world; - -import com.dfsek.terra.api.platform.block.Block; - -public interface Chunk extends ChunkAccess { - int getX(); - - int getZ(); - - World getWorld(); - - Block getBlock(int x, int y, int z); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/ChunkAccess.java b/common/src/main/java/com/dfsek/terra/api/platform/world/ChunkAccess.java deleted file mode 100644 index b6da6e9a8..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/ChunkAccess.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.api.platform.world; - -import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.platform.block.BlockData; -import org.jetbrains.annotations.NotNull; - -public interface ChunkAccess extends Handle { - /** - * Set the block at x,y,z in the chunk data to material. - *

- * Setting blocks outside the chunk's bounds does nothing. - * - * @param x the x location in the chunk from 0-15 inclusive - * @param y the y location in the chunk from 0 (inclusive) - maxHeight (exclusive) - * @param z the z location in the chunk from 0-15 inclusive - * @param blockData the type to set the block to - */ - void setBlock(int x, int y, int z, @NotNull BlockData blockData); - - /** - * Get the type and data of the block at x, y, z. - *

- * Getting blocks outside the chunk's bounds returns air. - * - * @param x the x location in the chunk from 0-15 inclusive - * @param y the y location in the chunk from 0 (inclusive) - maxHeight (exclusive) - * @param z the z location in the chunk from 0-15 inclusive - * @return the data of the block or the BlockData for air if x, y or z are outside the chunk's bounds - */ - @NotNull BlockData getBlockData(int x, int y, int z); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/Tree.java b/common/src/main/java/com/dfsek/terra/api/platform/world/Tree.java deleted file mode 100644 index 34225e7eb..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/Tree.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.api.platform.world; - - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.util.collections.MaterialSet; - -import java.util.Random; - -public interface Tree { - boolean plant(Location l, Random r); - - MaterialSet getSpawnable(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/World.java b/common/src/main/java/com/dfsek/terra/api/platform/world/World.java deleted file mode 100644 index 45d13ab4d..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/World.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.dfsek.terra.api.platform.world; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; - -import java.io.File; -import java.util.UUID; - -public interface World extends Handle { - long getSeed(); - - int getMaxHeight(); - - ChunkGenerator getGenerator(); - - Chunk getChunkAt(int x, int z); - - default Chunk getChunkAt(Location location) { - return getChunkAt(location.getBlockX() >> 4, location.getBlockZ() >> 4); - } - - Block getBlockAt(int x, int y, int z); - - default Block getBlockAt(Location l) { - return getBlockAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()); - } - - Entity spawnEntity(Location location, EntityType entityType); - - int getMinHeight(); - - default boolean isTerraWorld() { - return getGenerator().getHandle() instanceof GeneratorWrapper; - } - - default TerraChunkGenerator getTerraGenerator() { - return ((GeneratorWrapper) getGenerator().getHandle()).getHandle(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/BlockPopulator.java b/common/src/main/java/com/dfsek/terra/api/platform/world/generator/BlockPopulator.java deleted file mode 100644 index 1ed9a3a33..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/BlockPopulator.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.api.platform.world.generator; - -import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; - -import java.util.Random; - -public interface BlockPopulator extends Handle { - void populate(World world, Random random, Chunk chunk); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkData.java b/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkData.java deleted file mode 100644 index bb7f164a4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkData.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.platform.world.generator; - -import com.dfsek.terra.api.platform.world.ChunkAccess; - -public interface ChunkData extends ChunkAccess { - /** - * Get the maximum height for the chunk. - *

- * Setting blocks at or above this height will do nothing. - * - * @return the maximum height - */ - int getMaxHeight(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkGenerator.java b/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkGenerator.java deleted file mode 100644 index da3594011..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/ChunkGenerator.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.platform.world.generator; - -import com.dfsek.terra.api.platform.Handle; - -public interface ChunkGenerator extends Handle { - -} diff --git a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/GeneratorWrapper.java b/common/src/main/java/com/dfsek/terra/api/platform/world/generator/GeneratorWrapper.java deleted file mode 100644 index 127f9e5bf..000000000 --- a/common/src/main/java/com/dfsek/terra/api/platform/world/generator/GeneratorWrapper.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dfsek.terra.api.platform.world.generator; - -import com.dfsek.terra.api.platform.Handle; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; - -public interface GeneratorWrapper extends Handle { - @Override - TerraChunkGenerator getHandle(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/registry/CheckedRegistry.java b/common/src/main/java/com/dfsek/terra/api/registry/CheckedRegistry.java deleted file mode 100644 index 9934c767b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/registry/CheckedRegistry.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.dfsek.terra.api.registry; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.terra.registry.OpenRegistry; -import com.dfsek.terra.registry.exception.DuplicateEntryException; - -import java.lang.reflect.Type; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -/** - * Wrapper for a registry that ensures checked additions. - * - * @param Type in registry - */ -public class CheckedRegistry implements Registry { - private final OpenRegistry registry; - - public CheckedRegistry(OpenRegistry registry) { - this.registry = registry; - } - - /** - * Add a value to this registry, checking whether it is present first. - * - * @param identifier Identifier to assign value. - * @param value Value to add. - * @throws DuplicateEntryException If an entry with the same identifier is already present. - */ - public void add(String identifier, T value) throws DuplicateEntryException { - registry.addChecked(identifier, value); - } - - /** - * Add a value to the registry, without checking presence beforehand. - *

- * Use of this method is generally discouraged, as it is bad practice to overwrite registry values. - * - * @param identifier Identifier to assign value. - * @param value Value to add. - * @deprecated Use of {@link #add(String, Object)} is encouraged. - */ - @Deprecated - public void addUnchecked(String identifier, T value) { - registry.add(identifier, value); - } - - @Override - public T get(String identifier) { - return registry.get(identifier); - } - - @Override - public boolean contains(String identifier) { - return registry.contains(identifier); - } - - @Override - public void forEach(Consumer consumer) { - registry.forEach(consumer); - } - - @Override - public void forEach(BiConsumer consumer) { - registry.forEach(consumer); - } - - @Override - public Set entries() { - return registry.entries(); - } - - @Override - public Set keys() { - return registry.keys(); - } - - @Override - public T load(Type t, Object c, ConfigLoader loader) throws LoadException { - return registry.load(t, c, loader); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/registry/LockedRegistry.java b/common/src/main/java/com/dfsek/terra/api/registry/LockedRegistry.java deleted file mode 100644 index 227656c4d..000000000 --- a/common/src/main/java/com/dfsek/terra/api/registry/LockedRegistry.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.dfsek.terra.api.registry; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; - -import java.lang.reflect.Type; -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -/** - * Wrapper for a registry that forbids all write access. - * - * @param Type in registry - */ -public class LockedRegistry implements Registry { - private final Registry registry; - - public LockedRegistry(Registry registry) { - this.registry = registry; - } - - @Override - public T get(String identifier) { - return registry.get(identifier); - } - - @Override - public boolean contains(String identifier) { - return registry.contains(identifier); - } - - @Override - public void forEach(Consumer consumer) { - registry.forEach(consumer); - } - - @Override - public void forEach(BiConsumer consumer) { - registry.forEach(consumer); - } - - @Override - public Set entries() { - return registry.entries(); - } - - @Override - public Set keys() { - return registry.keys(); - } - - @Override - public T load(Type t, Object c, ConfigLoader loader) throws LoadException { - return registry.load(t, c, loader); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/registry/Registry.java b/common/src/main/java/com/dfsek/terra/api/registry/Registry.java deleted file mode 100644 index 773d784ca..000000000 --- a/common/src/main/java/com/dfsek/terra/api/registry/Registry.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.dfsek.terra.api.registry; - -import com.dfsek.tectonic.loading.TypeLoader; - -import java.util.Set; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -public interface Registry extends TypeLoader { - /** - * Get a value from the registry. - * - * @param identifier Identifier of value. - * @return Value matching the identifier, {@code null} if no value is present. - */ - T get(String identifier); - - /** - * Check if the registry contains a value. - * - * @param identifier Identifier of value. - * @return Whether the registry contains the value. - */ - boolean contains(String identifier); - - /** - * Perform the given action for every value in the registry. - * - * @param consumer Action to perform on value. - */ - void forEach(Consumer consumer); - - /** - * Perform an action for every key-value pair in the registry. - * - * @param consumer Action to perform on pair. - */ - void forEach(BiConsumer consumer); - - /** - * Get the entries of this registry as a {@link Set}. - * - * @return Set containing all entries. - */ - Set entries(); - - /** - * Get all the keys in this registry. - * - * @return Keys in registry - */ - Set keys(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/ImplementationArguments.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/ImplementationArguments.java deleted file mode 100644 index cd71207a2..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/ImplementationArguments.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang; - -/** - * Arguments passed to {@link Item}s by the implementation - */ -public interface ImplementationArguments { -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Item.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Item.java deleted file mode 100644 index bd45e904e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Item.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang; - -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public interface Item { - T apply(ImplementationArguments implementationArguments, Map> variableMap); - - Position getPosition(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Keyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Keyword.java deleted file mode 100644 index be0a9f085..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Keyword.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang; - -public interface Keyword extends Returnable { -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Returnable.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Returnable.java deleted file mode 100644 index 3d02ae4cb..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Returnable.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang; - -public interface Returnable extends Item { - ReturnType returnType(); - - enum ReturnType { - NUMBER(true), STRING(true), BOOLEAN(false), VOID(false), OBJECT(false); - - private final boolean comparable; - - ReturnType(boolean comparable) { - this.comparable = comparable; - } - - public boolean isComparable() { - return comparable; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Statement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Statement.java deleted file mode 100644 index f268f4592..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/Statement.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang; - -public interface Statement extends Item { -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/BooleanConstant.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/BooleanConstant.java deleted file mode 100644 index 7d57f561f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/BooleanConstant.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.constants; - -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class BooleanConstant extends ConstantExpression { - public BooleanConstant(Boolean constant, Position position) { - super(constant, position); - } - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/ConstantExpression.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/ConstantExpression.java deleted file mode 100644 index b1439fdf2..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/ConstantExpression.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.constants; - -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public abstract class ConstantExpression implements Returnable { - private final T constant; - private final Position position; - - public ConstantExpression(T constant, Position position) { - this.constant = constant; - this.position = position; - } - - @Override - public T apply(ImplementationArguments implementationArguments, Map> variableMap) { - return constant; - } - - @Override - public Position getPosition() { - return position; - } - - public T getConstant() { - return constant; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/NumericConstant.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/NumericConstant.java deleted file mode 100644 index caf68836e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/NumericConstant.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.constants; - -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class NumericConstant extends ConstantExpression { - public NumericConstant(Number constant, Position position) { - super(constant, position); - } - - @Override - public ReturnType returnType() { - return ReturnType.NUMBER; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/StringConstant.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/StringConstant.java deleted file mode 100644 index 19a93353f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/constants/StringConstant.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.constants; - -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class StringConstant extends ConstantExpression { - public StringConstant(String constant, Position position) { - super(constant, position); - } - - @Override - public ReturnType returnType() { - return ReturnType.STRING; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/Function.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/Function.java deleted file mode 100644 index aaa826d12..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/Function.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.functions; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; - -public interface Function extends Returnable { -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/FunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/FunctionBuilder.java deleted file mode 100644 index 7d1cbe4ba..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/FunctionBuilder.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.functions; - -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public interface FunctionBuilder> { - T build(List> argumentList, Position position) throws ParseException; - - int argNumber(); - - Returnable.ReturnType getArgument(int position); -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/FunctionBlock.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/FunctionBlock.java deleted file mode 100644 index 26e5fa4f5..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/functions/def/FunctionBlock.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.functions.def; - -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Item; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class FunctionBlock implements Item { - private final List> items; - private final Position position; - private final T defaultVal; - - public FunctionBlock(List> items, T defaultVal, Position position) { - this.items = items; - this.position = position; - this.defaultVal = defaultVal; - } - - public List> getItems() { - return items; - } - - @SuppressWarnings("unchecked") - @Override - public synchronized T apply(ImplementationArguments implementationArguments, Map> variableMap) { - Map> scope = new HashMap<>(variableMap); - for(Item item : items) { - Object result = item.apply(implementationArguments, variableMap); - if(result instanceof Block.ReturnInfo) { - Block.ReturnInfo level = (Block.ReturnInfo) result; - if(level.getLevel().equals(Block.ReturnLevel.RETURN)) return level.getData(); - } - } - return defaultVal; - } - - @Override - public Position getPosition() { - return position; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/BreakKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/BreakKeyword.java deleted file mode 100644 index aa2cc751e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/BreakKeyword.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords.flow; - -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Keyword; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class BreakKeyword implements Keyword> { - private final Position position; - - public BreakKeyword(Position position) { - this.position = position; - } - - @Override - public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Map> variableMap) { - return new Block.ReturnInfo<>(Block.ReturnLevel.BREAK, null); - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ContinueKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ContinueKeyword.java deleted file mode 100644 index b994c477f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ContinueKeyword.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords.flow; - -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Keyword; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class ContinueKeyword implements Keyword> { - private final Position position; - - public ContinueKeyword(Position position) { - this.position = position; - } - - @Override - public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Map> variableMap) { - return new Block.ReturnInfo<>(Block.ReturnLevel.CONTINUE, null); - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/FailKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/FailKeyword.java deleted file mode 100644 index 1340e21ef..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/FailKeyword.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords.flow; - -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Keyword; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class FailKeyword implements Keyword> { - private final Position position; - - public FailKeyword(Position position) { - this.position = position; - } - - @Override - public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Map> variableMap) { - return new Block.ReturnInfo<>(Block.ReturnLevel.FAIL, null); - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ReturnKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ReturnKeyword.java deleted file mode 100644 index 20fc0b211..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/flow/ReturnKeyword.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords.flow; - -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Keyword; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class ReturnKeyword implements Keyword> { - private final Position position; - - public ReturnKeyword(Position position) { - this.position = position; - } - - @Override - public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Map> variableMap) { - return new Block.ReturnInfo<>(Block.ReturnLevel.RETURN, null); - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/ForKeyword.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/ForKeyword.java deleted file mode 100644 index 8416eb3fc..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/keywords/looplike/ForKeyword.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.keywords.looplike; - -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Item; -import com.dfsek.terra.api.structures.parser.lang.Keyword; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class ForKeyword implements Keyword> { - private final Block conditional; - private final Item initializer; - private final Returnable statement; - private final Item incrementer; - private final Position position; - - public ForKeyword(Block conditional, Item initializer, Returnable statement, Item incrementer, Position position) { - this.conditional = conditional; - this.initializer = initializer; - this.statement = statement; - this.incrementer = incrementer; - this.position = position; - } - - @Override - public Block.ReturnInfo apply(ImplementationArguments implementationArguments, Map> variableMap) { - for(initializer.apply(implementationArguments, variableMap); statement.apply(implementationArguments, variableMap); incrementer.apply(implementationArguments, variableMap)) { - Block.ReturnInfo level = conditional.apply(implementationArguments, variableMap); - if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break; - if(level.getLevel().isReturnFast()) return level; - } - return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null); - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BinaryOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BinaryOperation.java deleted file mode 100644 index 684ff8ec4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BinaryOperation.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public abstract class BinaryOperation implements Returnable { - private final Returnable left; - private final Returnable right; - private final Position start; - - public BinaryOperation(Returnable left, Returnable right, Position start) { - this.left = left; - this.right = right; - this.start = start; - } - - public abstract O apply(I left, I right); - - @Override - public Position getPosition() { - return start; - } - - @Override - public O apply(ImplementationArguments implementationArguments, Map> variableMap) { - return apply(left.apply(implementationArguments, variableMap), right.apply(implementationArguments, variableMap)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanAndOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanAndOperation.java deleted file mode 100644 index 3bca80717..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanAndOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class BooleanAndOperation extends BinaryOperation { - public BooleanAndOperation(Returnable left, Returnable right, Position start) { - super(left, right, start); - } - - @Override - public Boolean apply(Boolean left, Boolean right) { - return left && right; - } - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanNotOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanNotOperation.java deleted file mode 100644 index ebf59abd2..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanNotOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class BooleanNotOperation extends UnaryOperation { - public BooleanNotOperation(Returnable input, Position position) { - super(input, position); - } - - @Override - public Boolean apply(Boolean input) { - return !input; - } - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanOrOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanOrOperation.java deleted file mode 100644 index 513c35be5..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/BooleanOrOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class BooleanOrOperation extends BinaryOperation { - public BooleanOrOperation(Returnable left, Returnable right, Position start) { - super(left, right, start); - } - - @Override - public Boolean apply(Boolean left, Boolean right) { - return left || right; - } - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ConcatenationOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ConcatenationOperation.java deleted file mode 100644 index b0eea6f50..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ConcatenationOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class ConcatenationOperation extends BinaryOperation { - public ConcatenationOperation(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public String apply(Object left, Object right) { - return left.toString() + right.toString(); - } - - @Override - public ReturnType returnType() { - return ReturnType.STRING; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/DivisionOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/DivisionOperation.java deleted file mode 100644 index 3054f8981..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/DivisionOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class DivisionOperation extends BinaryOperation { - public DivisionOperation(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public Number apply(Number left, Number right) { - return left.doubleValue() / right.doubleValue(); - } - - @Override - public ReturnType returnType() { - return ReturnType.NUMBER; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ModuloOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ModuloOperation.java deleted file mode 100644 index 44ef9a7d1..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ModuloOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class ModuloOperation extends BinaryOperation { - public ModuloOperation(Returnable left, Returnable right, Position start) { - super(left, right, start); - } - - @Override - public Number apply(Number left, Number right) { - return left.doubleValue() % right.doubleValue(); - } - - @Override - public ReturnType returnType() { - return ReturnType.NUMBER; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/MultiplicationOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/MultiplicationOperation.java deleted file mode 100644 index b6269a6c7..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/MultiplicationOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class MultiplicationOperation extends BinaryOperation { - public MultiplicationOperation(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public Number apply(Number left, Number right) { - return left.doubleValue() * right.doubleValue(); - } - - @Override - public ReturnType returnType() { - return ReturnType.NUMBER; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NegationOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NegationOperation.java deleted file mode 100644 index cf4b01de7..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NegationOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class NegationOperation extends UnaryOperation { - public NegationOperation(Returnable input, Position position) { - super(input, position); - } - - @Override - public Number apply(Number input) { - return -input.doubleValue(); - } - - @Override - public ReturnType returnType() { - return ReturnType.NUMBER; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NumberAdditionOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NumberAdditionOperation.java deleted file mode 100644 index 969d13b5e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/NumberAdditionOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class NumberAdditionOperation extends BinaryOperation { - public NumberAdditionOperation(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public Number apply(Number left, Number right) { - return left.doubleValue() + right.doubleValue(); - } - - @Override - public ReturnType returnType() { - return ReturnType.NUMBER; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/SubtractionOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/SubtractionOperation.java deleted file mode 100644 index d2bc82203..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/SubtractionOperation.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class SubtractionOperation extends BinaryOperation { - public SubtractionOperation(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public Number apply(Number left, Number right) { - return left.doubleValue() - right.doubleValue(); - } - - @Override - public ReturnType returnType() { - return ReturnType.NUMBER; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/UnaryOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/UnaryOperation.java deleted file mode 100644 index d561527e0..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/UnaryOperation.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations; - -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public abstract class UnaryOperation implements Returnable { - private final Returnable input; - private final Position position; - - public UnaryOperation(Returnable input, Position position) { - this.input = input; - this.position = position; - } - - public abstract T apply(T input); - - @Override - public T apply(ImplementationArguments implementationArguments, Map> variableMap) { - return apply(input.apply(implementationArguments, variableMap)); - } - - @Override - public Position getPosition() { - return position; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/EqualsStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/EqualsStatement.java deleted file mode 100644 index b7dface16..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/EqualsStatement.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations.statements; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; -import com.dfsek.terra.api.structures.tokenizer.Position; -import net.jafama.FastMath; - -public class EqualsStatement extends BinaryOperation { - private static final double EPSILON = 0.000000001D; - - public EqualsStatement(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public Boolean apply(Object left, Object right) { - if(left instanceof Number && right instanceof Number) { - return FastMath.abs(((Number) left).doubleValue() - ((Number) right).doubleValue()) <= EPSILON; - } - - return left.equals(right); - } - - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java deleted file mode 100644 index 36b1ab446..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations.statements; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class GreaterOrEqualsThanStatement extends BinaryOperation { - public GreaterOrEqualsThanStatement(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public Boolean apply(Number left, Number right) { - return left.doubleValue() >= right.doubleValue(); - } - - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterThanStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterThanStatement.java deleted file mode 100644 index c9a12357b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/GreaterThanStatement.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations.statements; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class GreaterThanStatement extends BinaryOperation { - public GreaterThanStatement(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public Boolean apply(Number left, Number right) { - return left.doubleValue() > right.doubleValue(); - } - - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanOrEqualsStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanOrEqualsStatement.java deleted file mode 100644 index 6904acb62..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanOrEqualsStatement.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations.statements; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class LessThanOrEqualsStatement extends BinaryOperation { - public LessThanOrEqualsStatement(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public Boolean apply(Number left, Number right) { - return left.doubleValue() <= right.doubleValue(); - } - - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanStatement.java deleted file mode 100644 index 03fff20c1..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/LessThanStatement.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations.statements; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class LessThanStatement extends BinaryOperation { - public LessThanStatement(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public Boolean apply(Number left, Number right) { - return left.doubleValue() < right.doubleValue(); - } - - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/NotEqualsStatement.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/NotEqualsStatement.java deleted file mode 100644 index e0e57783c..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/statements/NotEqualsStatement.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.operations.statements; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class NotEqualsStatement extends BinaryOperation { - public NotEqualsStatement(Returnable left, Returnable right, Position position) { - super(left, right, position); - } - - @Override - public Boolean apply(Object left, Object right) { - return !left.equals(right); - } - - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Assignment.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Assignment.java deleted file mode 100644 index 91fc43c86..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Assignment.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.variables; - -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Item; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class Assignment implements Item { - private final Returnable value; - private final Position position; - private final String identifier; - - public Assignment(Returnable value, String identifier, Position position) { - this.value = value; - this.identifier = identifier; - this.position = position; - } - - @SuppressWarnings("unchecked") - @Override - public synchronized T apply(ImplementationArguments implementationArguments, Map> variableMap) { - T val = value.apply(implementationArguments, variableMap); - ((Variable) variableMap.get(identifier)).setValue(val); - return val; - } - - @Override - public Position getPosition() { - return position; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Declaration.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Declaration.java deleted file mode 100644 index f919f13bb..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Declaration.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.variables; - -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Item; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class Declaration implements Item { - private final Position position; - private final String identifier; - private final Returnable value; - private final Returnable.ReturnType type; - - public Declaration(Position position, String identifier, Returnable value, Returnable.ReturnType type) { - switch(type) { - case STRING: - case BOOLEAN: - case NUMBER: - break; - default: - throw new IllegalArgumentException("Invalid variable type: " + type); - } - this.position = position; - this.identifier = identifier; - this.value = value; - this.type = type; - } - - @Override - public T apply(ImplementationArguments implementationArguments, Map> variableMap) { - T result = value.apply(implementationArguments, variableMap); - switch(type) { - case NUMBER: - variableMap.put(identifier, new NumberVariable((Number) result, position)); - break; - case BOOLEAN: - variableMap.put(identifier, new BooleanVariable((Boolean) result, position)); - break; - case STRING: - variableMap.put(identifier, new StringVariable((String) result, position)); - break; - } - return result; - } - - @Override - public Position getPosition() { - return position; - } - - public Returnable.ReturnType getType() { - return type; - } - - public String getIdentifier() { - return identifier; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Getter.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Getter.java deleted file mode 100644 index 19f07ed73..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Getter.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.variables; - -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class Getter implements Returnable { - private final String identifier; - private final Position position; - private final ReturnType type; - - public Getter(String identifier, Position position, ReturnType type) { - this.identifier = identifier; - this.position = position; - this.type = type; - } - - @Override - public ReturnType returnType() { - return type; - } - - @Override - public synchronized Object apply(ImplementationArguments implementationArguments, Map> variableMap) { - return variableMap.get(identifier).getValue(); - } - - @Override - public Position getPosition() { - return position; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Variable.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Variable.java deleted file mode 100644 index 4db60a3bf..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/variables/Variable.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.structures.parser.lang.variables; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public interface Variable { - T getValue(); - - void setValue(T value); - - Returnable.ReturnType getType(); - - Position getPosition(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java deleted file mode 100644 index 673381d13..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.dfsek.terra.api.structures.script; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.structures.parser.Parser; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Block; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.script.builders.BinaryNumberFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.BiomeFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.BlockFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.CheckBlockFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.CheckFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.EntityFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.GetMarkFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.LootFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.PullFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.RandomFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.RecursionsFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.SetMarkFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.StateFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.StructureFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.UnaryBooleanFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.UnaryNumberFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.UnaryStringFunctionBuilder; -import com.dfsek.terra.api.structures.script.builders.ZeroArgFunctionBuilder; -import com.dfsek.terra.api.structures.structure.Rotation; -import com.dfsek.terra.api.structures.structure.buffer.Buffer; -import com.dfsek.terra.api.structures.structure.buffer.DirectBuffer; -import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer; -import com.dfsek.terra.profiler.ProfileFrame; -import com.dfsek.terra.registry.config.FunctionRegistry; -import com.dfsek.terra.registry.config.LootRegistry; -import com.dfsek.terra.registry.config.ScriptRegistry; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import net.jafama.FastMath; -import org.apache.commons.io.IOUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; -import java.util.Random; -import java.util.concurrent.ExecutionException; - -public class StructureScript { - private final Block block; - private final String id; - private final Cache cache; - private final TerraPlugin main; - private String tempID; - - public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, FunctionRegistry functionRegistry) throws ParseException { - Parser parser; - try { - parser = new Parser(IOUtils.toString(inputStream, Charset.defaultCharset())); - } catch(IOException e) { - throw new RuntimeException(e); - } - - functionRegistry.forEach(parser::registerFunction); // Register registry functions. - - parser.registerFunction("block", new BlockFunctionBuilder(main, false)) - .registerFunction("dynamicBlock", new BlockFunctionBuilder(main, true)) - .registerFunction("check", new CheckFunctionBuilder(main)) - .registerFunction("structure", new StructureFunctionBuilder(registry, main)) - .registerFunction("randomInt", new RandomFunctionBuilder()) - .registerFunction("recursions", new RecursionsFunctionBuilder()) - .registerFunction("setMark", new SetMarkFunctionBuilder()) - .registerFunction("getMark", new GetMarkFunctionBuilder()) - .registerFunction("pull", new PullFunctionBuilder(main)) - .registerFunction("loot", new LootFunctionBuilder(main, lootRegistry, this)) - .registerFunction("entity", new EntityFunctionBuilder(main)) - .registerFunction("getBiome", new BiomeFunctionBuilder(main)) - .registerFunction("getBlock", new CheckBlockFunctionBuilder()) - .registerFunction("state", new StateFunctionBuilder(main)) - .registerFunction("setWaterlog", new UnaryBooleanFunctionBuilder((waterlog, args) -> args.setWaterlog(waterlog))) - .registerFunction("originX", new ZeroArgFunctionBuilder(arguments -> arguments.getBuffer().getOrigin().getX(), Returnable.ReturnType.NUMBER)) - .registerFunction("originY", new ZeroArgFunctionBuilder(arguments -> arguments.getBuffer().getOrigin().getY(), Returnable.ReturnType.NUMBER)) - .registerFunction("originZ", new ZeroArgFunctionBuilder(arguments -> arguments.getBuffer().getOrigin().getZ(), Returnable.ReturnType.NUMBER)) - .registerFunction("rotation", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().toString(), Returnable.ReturnType.STRING)) - .registerFunction("rotationDegrees", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().getDegrees(), Returnable.ReturnType.NUMBER)) - .registerFunction("print", new UnaryStringFunctionBuilder(string -> main.getDebugLogger().info("[" + tempID + "] " + string))) - .registerFunction("abs", new UnaryNumberFunctionBuilder(number -> FastMath.abs(number.doubleValue()))) - .registerFunction("pow", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.pow(number.doubleValue(), number2.doubleValue()))) - .registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> FastMath.sqrt(number.doubleValue()))) - .registerFunction("floor", new UnaryNumberFunctionBuilder(number -> FastMath.floor(number.doubleValue()))) - .registerFunction("ceil", new UnaryNumberFunctionBuilder(number -> FastMath.ceil(number.doubleValue()))) - .registerFunction("log", new UnaryNumberFunctionBuilder(number -> FastMath.log(number.doubleValue()))) - .registerFunction("round", new UnaryNumberFunctionBuilder(number -> FastMath.round(number.doubleValue()))) - .registerFunction("sin", new UnaryNumberFunctionBuilder(number -> FastMath.sin(number.doubleValue()))) - .registerFunction("cos", new UnaryNumberFunctionBuilder(number -> FastMath.cos(number.doubleValue()))) - .registerFunction("tan", new UnaryNumberFunctionBuilder(number -> FastMath.tan(number.doubleValue()))) - .registerFunction("asin", new UnaryNumberFunctionBuilder(number -> FastMath.asin(number.doubleValue()))) - .registerFunction("acos", new UnaryNumberFunctionBuilder(number -> FastMath.acos(number.doubleValue()))) - .registerFunction("atan", new UnaryNumberFunctionBuilder(number -> FastMath.atan(number.doubleValue()))) - .registerFunction("max", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue()))) - .registerFunction("min", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue()))); - - block = parser.parse(); - this.id = parser.getID(); - tempID = id; - this.main = main; - this.cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getStructureCache()).build(); - } - - /** - * Paste the structure at a location - * - * @param location Location to paste structure - * @param rotation Rotation of structure - * @return Whether generation was successful - */ - @SuppressWarnings("try") - public boolean execute(Location location, Random random, Rotation rotation) { - try(ProfileFrame ignore = main.getProfiler().profile("terrascript:" + id)) { - StructureBuffer buffer = new StructureBuffer(location); - boolean level = applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0)); - buffer.paste(); - return level; - } - } - - @SuppressWarnings("try") - public boolean execute(Location location, Chunk chunk, Random random, Rotation rotation) { - try(ProfileFrame ignore = main.getProfiler().profile("terrascript_chunk:" + id)) { - StructureBuffer buffer = computeBuffer(location, random, rotation); - buffer.paste(chunk); - return buffer.succeeded(); - } - } - - @SuppressWarnings("try") - public boolean test(Location location, Random random, Rotation rotation) { - try(ProfileFrame ignore = main.getProfiler().profile("terrascript_test:" + id)) { - StructureBuffer buffer = computeBuffer(location, random, rotation); - return buffer.succeeded(); - } - } - - private StructureBuffer computeBuffer(Location location, Random random, Rotation rotation) { - try { - return cache.get(location, () -> { - StructureBuffer buf = new StructureBuffer(location); - buf.setSucceeded(applyBlock(new TerraImplementationArguments(buf, rotation, random, 0))); - return buf; - }); - } catch(ExecutionException e) { - throw new RuntimeException(e); - } - } - - @SuppressWarnings("try") - public boolean executeInBuffer(Buffer buffer, Random random, Rotation rotation, int recursions) { - try(ProfileFrame ignore = main.getProfiler().profile("terrascript_recursive:" + id)) { - return applyBlock(new TerraImplementationArguments(buffer, rotation, random, recursions)); - } - } - - @SuppressWarnings("try") - public boolean executeDirect(Location location, Random random, Rotation rotation) { - try(ProfileFrame ignore = main.getProfiler().profile("terrascript_direct:" + id)) { - DirectBuffer buffer = new DirectBuffer(location); - return applyBlock(new TerraImplementationArguments(buffer, rotation, random, 0)); - } - } - - public String getId() { - return id; - } - - private boolean applyBlock(TerraImplementationArguments arguments) { - try { - return block.apply(arguments).getLevel() != Block.ReturnLevel.FAIL; - } catch(RuntimeException e) { - main.logger().severe("Failed to generate structure at " + arguments.getBuffer().getOrigin() + ": " + e.getMessage()); - main.getDebugLogger().stack(e); - return false; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/TerraImplementationArguments.java b/common/src/main/java/com/dfsek/terra/api/structures/script/TerraImplementationArguments.java deleted file mode 100644 index 6d80871ea..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/TerraImplementationArguments.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.api.structures.script; - -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.structure.Rotation; -import com.dfsek.terra.api.structures.structure.buffer.Buffer; - -import java.util.Random; - -public class TerraImplementationArguments implements ImplementationArguments { - private final Buffer buffer; - private final Rotation rotation; - private final Random random; - private final int recursions; - private boolean waterlog = false; - - public TerraImplementationArguments(Buffer buffer, Rotation rotation, Random random, int recursions) { - this.buffer = buffer; - this.rotation = rotation; - this.random = random; - this.recursions = recursions; - } - - public Buffer getBuffer() { - return buffer; - } - - public int getRecursions() { - return recursions; - } - - public Random getRandom() { - return random; - } - - public Rotation getRotation() { - return rotation; - } - - public boolean isWaterlog() { - return waterlog; - } - - public void setWaterlog(boolean waterlog) { - this.waterlog = waterlog; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BiomeFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BiomeFunctionBuilder.java deleted file mode 100644 index 7c15c70b4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BiomeFunctionBuilder.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.BiomeFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public class BiomeFunctionBuilder implements FunctionBuilder { - private final TerraPlugin main; - - public BiomeFunctionBuilder(TerraPlugin main) { - this.main = main; - } - - @SuppressWarnings("unchecked") - @Override - public BiomeFunction build(List> argumentList, Position position) { - return new BiomeFunction(main, (Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), position); - } - - @Override - public int argNumber() { - return 3; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - default: - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java deleted file mode 100644 index 0f05d2636..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.AbstractBlockFunction; -import com.dfsek.terra.api.structures.script.functions.BlockFunction; -import com.dfsek.terra.api.structures.script.functions.DynamicBlockFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public class BlockFunctionBuilder implements FunctionBuilder { - private final TerraPlugin main; - private final boolean dynamic; - - public BlockFunctionBuilder(TerraPlugin main, boolean dynamic) { - this.main = main; - this.dynamic = dynamic; - } - - @SuppressWarnings("unchecked") - @Override - public AbstractBlockFunction build(List> argumentList, Position position) throws ParseException { - if(argumentList.size() < 4) throw new ParseException("Expected data", position); - Returnable booleanReturnable = new BooleanConstant(true, position); - if(argumentList.size() == 5) booleanReturnable = (Returnable) argumentList.get(4); - if(dynamic) - return new DynamicBlockFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), booleanReturnable, main, position); - return new BlockFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), booleanReturnable, main, position); - } - - @Override - public int argNumber() { - return -1; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - case 3: - return Returnable.ReturnType.STRING; - case 4: - return Returnable.ReturnType.BOOLEAN; - default: - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckBlockFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckBlockFunctionBuilder.java deleted file mode 100644 index 98eeb2665..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckBlockFunctionBuilder.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.CheckBlockFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public class CheckBlockFunctionBuilder implements FunctionBuilder { - @SuppressWarnings("unchecked") - @Override - public CheckBlockFunction build(List> argumentList, Position position) { - return new CheckBlockFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), position); - } - - @Override - public int argNumber() { - return 3; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - default: - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckFunctionBuilder.java deleted file mode 100644 index 4ac870f49..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/CheckFunctionBuilder.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.CheckFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.world.generation.math.SamplerCache; - -import java.util.List; - -public class CheckFunctionBuilder implements FunctionBuilder { - private final TerraPlugin main; - - public CheckFunctionBuilder(TerraPlugin main) { - this.main = main; - } - - @SuppressWarnings("unchecked") - @Override - public CheckFunction build(List> argumentList, Position position) throws ParseException { - return new CheckFunction(main, (Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), position); - } - - @Override - public int argNumber() { - return 3; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - default: - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/EntityFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/EntityFunctionBuilder.java deleted file mode 100644 index dd66a3d84..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/EntityFunctionBuilder.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.EntityFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public class EntityFunctionBuilder implements FunctionBuilder { - private final TerraPlugin main; - - public EntityFunctionBuilder(TerraPlugin main) { - this.main = main; - } - - @SuppressWarnings("unchecked") - @Override - public EntityFunction build(List> argumentList, Position position) throws ParseException { - return new EntityFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), main, position); - } - - @Override - public int argNumber() { - return 4; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - case 3: - return Returnable.ReturnType.STRING; - default: - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/GetMarkFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/GetMarkFunctionBuilder.java deleted file mode 100644 index e93fbdc2b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/GetMarkFunctionBuilder.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.GetMarkFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public class GetMarkFunctionBuilder implements FunctionBuilder { - - public GetMarkFunctionBuilder() { - } - - @SuppressWarnings("unchecked") - @Override - public GetMarkFunction build(List> argumentList, Position position) { - return new GetMarkFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), position); - } - - @Override - public int argNumber() { - return 3; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - default: - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java deleted file mode 100644 index d5e46d9d3..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.structures.script.functions.LootFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.registry.config.LootRegistry; - -import java.util.List; - -public class LootFunctionBuilder implements FunctionBuilder { - private final TerraPlugin main; - private final LootRegistry registry; - private final StructureScript script; - - public LootFunctionBuilder(TerraPlugin main, LootRegistry registry, StructureScript script) { - this.main = main; - this.registry = registry; - this.script = script; - } - - @SuppressWarnings("unchecked") - @Override - public LootFunction build(List> argumentList, Position position) { - return new LootFunction(registry, (Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), main, position, script); - } - - @Override - public int argNumber() { - return 4; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - case 3: - return Returnable.ReturnType.STRING; - default: - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/PullFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/PullFunctionBuilder.java deleted file mode 100644 index 9b55da244..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/PullFunctionBuilder.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.PullFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public class PullFunctionBuilder implements FunctionBuilder { - private final TerraPlugin main; - - public PullFunctionBuilder(TerraPlugin main) { - this.main = main; - } - - @SuppressWarnings("unchecked") - @Override - public PullFunction build(List> argumentList, Position position) throws ParseException { - return new PullFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), main, position); - } - - @Override - public int argNumber() { - return 4; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - case 3: - return Returnable.ReturnType.STRING; - default: - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RandomFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RandomFunctionBuilder.java deleted file mode 100644 index ec84d5c36..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RandomFunctionBuilder.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.RandomFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public class RandomFunctionBuilder implements FunctionBuilder { - @SuppressWarnings("unchecked") - @Override - public RandomFunction build(List> argumentList, Position position) throws ParseException { - return new RandomFunction((Returnable) argumentList.get(0), position); - } - - @Override - public int argNumber() { - return 1; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - if(position == 0) return Returnable.ReturnType.NUMBER; - return null; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RecursionsFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RecursionsFunctionBuilder.java deleted file mode 100644 index 5fc66977d..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/RecursionsFunctionBuilder.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.RecursionsFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public class RecursionsFunctionBuilder implements FunctionBuilder { - @Override - public RecursionsFunction build(List> argumentList, Position position) throws ParseException { - return new RecursionsFunction(position); - } - - @Override - public int argNumber() { - return 0; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - return null; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/SetMarkFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/SetMarkFunctionBuilder.java deleted file mode 100644 index 76fc5ec39..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/SetMarkFunctionBuilder.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.SetMarkFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public class SetMarkFunctionBuilder implements FunctionBuilder { - - public SetMarkFunctionBuilder() { - } - - @SuppressWarnings("unchecked") - @Override - public SetMarkFunction build(List> argumentList, Position position) throws ParseException { - return new SetMarkFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), position); - } - - @Override - public int argNumber() { - return 4; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - case 3: - return Returnable.ReturnType.STRING; - default: - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StateFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StateFunctionBuilder.java deleted file mode 100644 index 56c9ab2e3..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StateFunctionBuilder.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.StateFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.List; - -public class StateFunctionBuilder implements FunctionBuilder { - private final TerraPlugin main; - - public StateFunctionBuilder(TerraPlugin main) { - this.main = main; - } - - @SuppressWarnings("unchecked") - @Override - public StateFunction build(List> argumentList, Position position) throws ParseException { - if(argumentList.size() < 4) throw new ParseException("Expected data", position); - return new StateFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), main, position); - } - - @Override - public int argNumber() { - return 4; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - case 3: - return Returnable.ReturnType.STRING; - default: - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java deleted file mode 100644 index 2b0be8468..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dfsek.terra.api.structures.script.builders; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.functions.StructureFunction; -import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.registry.config.ScriptRegistry; - -import java.util.List; -import java.util.stream.Collectors; - -public class StructureFunctionBuilder implements FunctionBuilder { - private final ScriptRegistry registry; - private final TerraPlugin main; - - public StructureFunctionBuilder(ScriptRegistry registry, TerraPlugin main) { - this.registry = registry; - this.main = main; - } - - @SuppressWarnings("unchecked") - @Override - public StructureFunction build(List> argumentList, Position position) throws ParseException { - if(argumentList.size() < 5) throw new ParseException("Expected rotations", position); - - return new StructureFunction((Returnable) argumentList.remove(0), (Returnable) argumentList.remove(0), (Returnable) argumentList.remove(0), (Returnable) argumentList.remove(0), - argumentList.stream().map(item -> ((Returnable) item)).collect(Collectors.toList()), registry, position, main); - } - - @Override - public int argNumber() { - return -1; - } - - @Override - public Returnable.ReturnType getArgument(int position) { - switch(position) { - case 0: - case 1: - case 2: - return Returnable.ReturnType.NUMBER; - default: - return Returnable.ReturnType.STRING; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/AbstractBlockFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/AbstractBlockFunction.java deleted file mode 100644 index b3ff81c62..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/AbstractBlockFunction.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedBlock; -import com.dfsek.terra.api.structures.tokenizer.Position; -import net.jafama.FastMath; - -import java.util.Map; - -public abstract class AbstractBlockFunction implements Function { - protected final Returnable x, y, z; - protected final Returnable blockData; - protected final TerraPlugin main; - private final Returnable overwrite; - private final Position position; - - protected AbstractBlockFunction(Returnable x, Returnable y, Returnable z, Returnable blockData, Returnable overwrite, TerraPlugin main, Position position) { - this.x = x; - this.y = y; - this.z = z; - this.blockData = blockData; - this.overwrite = overwrite; - this.main = main; - this.position = position; - } - - void setBlock(ImplementationArguments implementationArguments, Map> variableMap, TerraImplementationArguments arguments, BlockData rot) { - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - - RotationUtil.rotateVector(xz, arguments.getRotation()); - - RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse()); - arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments, variableMap), main, arguments.isWaterlog()), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BiomeFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BiomeFunction.java deleted file mode 100644 index 54eb7e280..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BiomeFunction.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import net.jafama.FastMath; - -import java.util.Map; - -public class BiomeFunction implements Function { - private final TerraPlugin main; - private final Returnable x, y, z; - private final Position position; - - - public BiomeFunction(TerraPlugin main, Returnable x, Returnable y, Returnable z, Position position) { - this.main = main; - this.x = x; - this.y = y; - this.z = z; - this.position = position; - } - - - @Override - public String apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - - RotationUtil.rotateVector(xz, arguments.getRotation()); - - BiomeProvider grid = main.getWorld(arguments.getBuffer().getOrigin().getWorld()).getBiomeProvider(); - - return ((UserDefinedBiome) grid.getBiome(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ()))))).getID(); - } - - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.STRING; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java deleted file mode 100644 index 22f82b720..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class BlockFunction extends AbstractBlockFunction { - private final BlockData data; - - public BlockFunction(Returnable x, Returnable y, Returnable z, Returnable data, Returnable overwrite, TerraPlugin main, Position position) throws ParseException { - super(x, y, z, data, overwrite, main, position); - - if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition()); - try { - this.data = main.getWorldHandle().createBlockData(((ConstantExpression) data).getConstant()); - } catch(IllegalArgumentException e) { - throw new ParseException("Could not parse block data", data.getPosition(), e); - } - } - - @Override - public Void apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - BlockData rot = data.clone(); - setBlock(implementationArguments, variableMap, arguments, rot); - return null; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckBlockFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckBlockFunction.java deleted file mode 100644 index 546ac15f0..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckBlockFunction.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.tokenizer.Position; -import net.jafama.FastMath; - -import java.util.Map; - -public class CheckBlockFunction implements Function { - private final Returnable x, y, z; - private final Position position; - - public CheckBlockFunction(Returnable x, Returnable y, Returnable z, Position position) { - this.x = x; - this.y = y; - this.z = z; - this.position = position; - } - - - @Override - public String apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - - RotationUtil.rotateVector(xz, arguments.getRotation()); - - String data = arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ()))).getBlock().getBlockData().getAsString(); - if(data.contains("[")) return data.substring(0, data.indexOf('[')); // Strip properties - else return data; - } - - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.STRING; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java deleted file mode 100644 index fee00e6c6..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/CheckFunction.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.generation.math.SamplerCache; -import net.jafama.FastMath; - -import java.util.Map; - -public class CheckFunction implements Function { - private final TerraPlugin main; - private final Returnable x, y, z; - private final Position position; - - public CheckFunction(TerraPlugin main, Returnable x, Returnable y, Returnable z, Position position) { - this.main = main; - this.x = x; - this.y = y; - this.z = z; - this.position = position; - } - - - @Override - public String apply(ImplementationArguments implementationArguments, Map> variableMap) { - - - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - - - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - - RotationUtil.rotateVector(xz, arguments.getRotation()); - - Location location = arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ()))); - - return apply(location, arguments.getBuffer().getOrigin().getWorld()); - } - - private String apply(Location vector, World world) { - TerraWorld tw = main.getWorld(world); - SamplerCache cache = tw.getConfig().getSamplerCache(); - double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), cache); - - if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land. - - BiomeProvider provider = tw.getBiomeProvider(); - UserDefinedBiome b = (UserDefinedBiome) provider.getBiome(vector.getBlockX(), vector.getBlockZ()); - BiomeTemplate c = b.getConfig(); - - if(vector.getY() > c.getSeaLevel()) return "AIR"; // Above sea level - return "OCEAN"; // Below sea level - } - - private double sample(int x, int y, int z, SamplerCache cache) { - int cx = FastMath.floorDiv(x, 16); - int cz = FastMath.floorDiv(z, 16); - return cache.get(x, z).sample(x - (cx << 4), y, z - (cz << 4)); - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.STRING; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/DynamicBlockFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/DynamicBlockFunction.java deleted file mode 100644 index 080848345..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/DynamicBlockFunction.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.HashMap; -import java.util.Map; - -public class DynamicBlockFunction extends AbstractBlockFunction { - private final Map data = new HashMap<>(); - private final Position position; - - - public DynamicBlockFunction(Returnable x, Returnable y, Returnable z, Returnable data, Returnable overwrite, TerraPlugin main, Position position) { - super(x, y, z, data, overwrite, main, position); - this.position = position; - } - - @Override - public Void apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - BlockData rot = data.computeIfAbsent(blockData.apply(implementationArguments, variableMap), main.getWorldHandle()::createBlockData).clone(); - setBlock(implementationArguments, variableMap, arguments, rot); - return null; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/EntityFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/EntityFunction.java deleted file mode 100644 index b8b9f8d1b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/EntityFunction.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedEntity; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class EntityFunction implements Function { - private final EntityType data; - private final Returnable x, y, z; - private final Position position; - private final TerraPlugin main; - - public EntityFunction(Returnable x, Returnable y, Returnable z, Returnable data, TerraPlugin main, Position position) throws ParseException { - this.position = position; - this.main = main; - if(!(data instanceof ConstantExpression)) throw new ParseException("Entity data must be constant", data.getPosition()); - - this.data = main.getWorldHandle().getEntity(((ConstantExpression) data).getConstant()); - this.x = x; - this.y = y; - this.z = z; - } - - @Override - public Void apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - - RotationUtil.rotateVector(xz, arguments.getRotation()); - - arguments.getBuffer().addItem(new BufferedEntity(data, main), new Vector3(xz.getX(), y.apply(implementationArguments, variableMap).doubleValue(), xz.getZ()).toLocation(arguments.getBuffer().getOrigin().getWorld())); - return null; - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/GetMarkFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/GetMarkFunction.java deleted file mode 100644 index df67e3e2c..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/GetMarkFunction.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.tokenizer.Position; -import net.jafama.FastMath; - -import java.util.Map; - -public class GetMarkFunction implements Function { - private final Returnable x, y, z; - private final Position position; - - public GetMarkFunction(Returnable x, Returnable y, Returnable z, Position position) { - this.position = position; - this.x = x; - this.y = y; - this.z = z; - } - - @Override - public String apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - - RotationUtil.rotateVector(xz, arguments.getRotation()); - String mark = arguments.getBuffer().getMark(new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments, variableMap).doubleValue()), FastMath.floorToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); - return mark == null ? "" : mark; - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.STRING; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java deleted file mode 100644 index 42add8070..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.structures.loot.LootTable; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication; -import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.registry.config.LootRegistry; -import net.jafama.FastMath; - -import java.util.Map; - -public class LootFunction implements Function { - private final LootRegistry registry; - private final Returnable data; - private final Returnable x, y, z; - private final Position position; - private final TerraPlugin main; - private final StructureScript script; - - public LootFunction(LootRegistry registry, Returnable x, Returnable y, Returnable z, Returnable data, TerraPlugin main, Position position, StructureScript script) { - this.registry = registry; - this.position = position; - this.data = data; - this.x = x; - this.y = y; - this.z = z; - this.main = main; - this.script = script; - } - - @Override - public Void apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - - RotationUtil.rotateVector(xz, arguments.getRotation()); - - String id = data.apply(implementationArguments, variableMap); - LootTable table = registry.get(id); - - if(table == null) { - main.logger().severe("No such loot table " + id); - return null; - } - - arguments.getBuffer().addItem(new BufferedLootApplication(table, main, script), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); - return null; - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/PullFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/PullFunction.java deleted file mode 100644 index 059aca0fa..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/PullFunction.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedPulledBlock; -import com.dfsek.terra.api.structures.tokenizer.Position; -import net.jafama.FastMath; - -import java.util.Map; - -public class PullFunction implements Function { - private final BlockData data; - private final Returnable x, y, z; - private final Position position; - - public PullFunction(Returnable x, Returnable y, Returnable z, Returnable data, TerraPlugin main, Position position) throws ParseException { - this.position = position; - if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition()); - - this.data = main.getWorldHandle().createBlockData(((ConstantExpression) data).getConstant()); - this.x = x; - this.y = y; - this.z = z; - } - - @Override - public Void apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - - RotationUtil.rotateVector(xz, arguments.getRotation()); - BlockData rot = data.clone(); - RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse()); - arguments.getBuffer().addItem(new BufferedPulledBlock(rot), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); - return null; - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RandomFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RandomFunction.java deleted file mode 100644 index a3ae8c46c..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RandomFunction.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class RandomFunction implements Function { - private final Returnable numberReturnable; - private final Position position; - - public RandomFunction(Returnable numberReturnable, Position position) { - this.numberReturnable = numberReturnable; - this.position = position; - } - - - @Override - public ReturnType returnType() { - return ReturnType.NUMBER; - } - - @Override - public Integer apply(ImplementationArguments implementationArguments, Map> variableMap) { - return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(numberReturnable.apply(implementationArguments, variableMap).intValue()); - } - - @Override - public Position getPosition() { - return position; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RecursionsFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RecursionsFunction.java deleted file mode 100644 index e06684671..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/RecursionsFunction.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.tokenizer.Position; - -import java.util.Map; - -public class RecursionsFunction implements Function { - private final Position position; - - public RecursionsFunction(Position position) { - this.position = position; - } - - @Override - public ReturnType returnType() { - return ReturnType.NUMBER; - } - - @Override - public Number apply(ImplementationArguments implementationArguments, Map> variableMap) { - return ((TerraImplementationArguments) implementationArguments).getRecursions(); - } - - @Override - public Position getPosition() { - return position; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/SetMarkFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/SetMarkFunction.java deleted file mode 100644 index 75beae39b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/SetMarkFunction.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.tokenizer.Position; -import net.jafama.FastMath; - -import java.util.Map; - -public class SetMarkFunction implements Function { - private final Returnable x, y, z; - private final Position position; - private final Returnable mark; - - public SetMarkFunction(Returnable x, Returnable y, Returnable z, Returnable mark, Position position) { - this.position = position; - this.mark = mark; - this.x = x; - this.y = y; - this.z = z; - } - - @Override - public Void apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - - RotationUtil.rotateVector(xz, arguments.getRotation()); - - arguments.getBuffer().setMark(mark.apply(implementationArguments, variableMap), new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments, variableMap).doubleValue()), FastMath.floorToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); - return null; - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StateFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StateFunction.java deleted file mode 100644 index 4e2e2c276..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StateFunction.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedStateManipulator; -import com.dfsek.terra.api.structures.tokenizer.Position; -import net.jafama.FastMath; - -import java.util.Map; - -public class StateFunction implements Function { - private final Returnable data; - private final Returnable x, y, z; - private final Position position; - private final TerraPlugin main; - - public StateFunction(Returnable x, Returnable y, Returnable z, Returnable data, TerraPlugin main, Position position) { - this.position = position; - this.main = main; - this.data = data; - this.x = x; - this.y = y; - this.z = z; - } - - @Override - public Void apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - RotationUtil.rotateVector(xz, arguments.getRotation()); - - arguments.getBuffer().addItem(new BufferedStateManipulator(main, data.apply(implementationArguments, variableMap)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())).toLocation(arguments.getBuffer().getOrigin().getWorld())); - return null; - } - - @Override - public Position getPosition() { - return position; - } - - @Override - public ReturnType returnType() { - return ReturnType.VOID; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java deleted file mode 100644 index 7b9b38830..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.dfsek.terra.api.structures.script.functions; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments; -import com.dfsek.terra.api.structures.parser.lang.Returnable; -import com.dfsek.terra.api.structures.parser.lang.functions.Function; -import com.dfsek.terra.api.structures.parser.lang.variables.Variable; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.structure.Rotation; -import com.dfsek.terra.api.structures.structure.RotationUtil; -import com.dfsek.terra.api.structures.structure.buffer.IntermediateBuffer; -import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.registry.config.ScriptRegistry; -import net.jafama.FastMath; - -import java.util.List; -import java.util.Map; - -public class StructureFunction implements Function { - private final ScriptRegistry registry; - private final Returnable id; - private final Returnable x, y, z; - private final Position position; - private final TerraPlugin main; - private final List> rotations; - - public StructureFunction(Returnable x, Returnable y, Returnable z, Returnable id, List> rotations, ScriptRegistry registry, Position position, TerraPlugin main) { - this.registry = registry; - this.id = id; - this.position = position; - this.x = x; - this.y = y; - this.z = z; - this.main = main; - this.rotations = rotations; - } - - @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; - } - - @Override - public Boolean apply(ImplementationArguments implementationArguments, Map> variableMap) { - TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments; - - if(arguments.getRecursions() > main.getTerraConfig().getMaxRecursion()) - throw new RuntimeException("Structure recursion too deep: " + arguments.getRecursions()); - - Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue()); - - RotationUtil.rotateVector(xz, arguments.getRotation()); - - String app = id.apply(implementationArguments, variableMap); - StructureScript script = registry.get(app); - if(script == null) { - main.logger().severe("No such structure " + app); - return null; - } - - Rotation rotation1; - String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).apply(implementationArguments, variableMap); - try { - rotation1 = Rotation.valueOf(rotString); - } catch(IllegalArgumentException e) { - main.logger().severe("Invalid rotation " + rotString); - return null; - } - - Vector3 offset = new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())); - - return script.executeInBuffer(new IntermediateBuffer(arguments.getBuffer(), offset), arguments.getRandom(), arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1); - } - - @Override - public Position getPosition() { - return position; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/Rotation.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/Rotation.java deleted file mode 100644 index f81c8f63e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/Rotation.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.dfsek.terra.api.structures.structure; - -import net.jafama.FastMath; - -public enum Rotation { - - CW_90(90), CW_180(180), CCW_90(270), NONE(0); - private final int degrees; - - Rotation(int degrees) { - this.degrees = degrees; - } - - public static Rotation fromDegrees(int deg) { - switch(FastMath.floorMod(deg, 360)) { - case 0: - return Rotation.NONE; - case 90: - return Rotation.CW_90; - case 180: - return Rotation.CW_180; - case 270: - return Rotation.CCW_90; - default: - throw new IllegalArgumentException(); - } - } - - public int getDegrees() { - return degrees; - } - - public Rotation inverse() { - switch(this) { - case NONE: - return NONE; - case CCW_90: - return CW_90; - case CW_90: - return CCW_90; - case CW_180: - return CW_180; - default: - throw new IllegalArgumentException(); - } - } - - public Rotation rotate(Rotation rotation) { - return fromDegrees(this.getDegrees() + rotation.getDegrees()); - } - - public enum Axis { - X, Y, Z - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/RotationUtil.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/RotationUtil.java deleted file mode 100644 index 1d77977d3..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/RotationUtil.java +++ /dev/null @@ -1,291 +0,0 @@ -package com.dfsek.terra.api.structures.structure; - -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.platform.block.Axis; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Directional; -import com.dfsek.terra.api.platform.block.data.MultipleFacing; -import com.dfsek.terra.api.platform.block.data.Orientable; -import com.dfsek.terra.api.platform.block.data.Rail; -import com.dfsek.terra.api.platform.block.data.RedstoneWire; -import com.dfsek.terra.api.platform.block.data.Rotatable; -import com.dfsek.terra.api.platform.block.data.Wall; -import com.google.common.collect.Sets; -import net.jafama.FastMath; - -import java.util.EnumMap; -import java.util.Map; -import java.util.Set; - -public class RotationUtil { - private static final Set CARDINALS = Sets.newHashSet(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST); - - /** - * Rotate and mirror a coordinate pair. - * - * @param orig Vector to rotate. - * @param r Rotation - */ - public static void rotateVector(Vector2 orig, Rotation r) { - Vector2 copy = orig.clone(); - switch(r) { - case CW_90: - copy.setX(orig.getZ()).setZ(-orig.getX()); - break; - case CCW_90: - copy.setX(-orig.getZ()).setZ(orig.getX()); - break; - case CW_180: - copy.multiply(-1); - break; - } - orig.setX(copy.getX()); - orig.setZ(copy.getZ()); - } - - /** - * Get the BlockFace with rotation and mirrors applied to it - * - * @param f BlockFace to apply rotation to - * @param r Rotation - * @return Rotated BlockFace - */ - public static BlockFace getRotatedFace(BlockFace f, Rotation r) { - BlockFace n = f; - int rotateNum = r.getDegrees() / 90; - int rn = faceRotation(f); - if(rn >= 0) { - n = fromRotation(faceRotation(n) + 4 * rotateNum); - } - return n; - } - - /** - * Get an integer representation of a BlockFace, to perform math on. - * - * @param f BlockFace to get integer for - * @return integer representation of BlockFace - */ - public static int faceRotation(BlockFace f) { - switch(f) { - case NORTH: - return 0; - case NORTH_NORTH_EAST: - return 1; - case NORTH_EAST: - return 2; - case EAST_NORTH_EAST: - return 3; - case EAST: - return 4; - case EAST_SOUTH_EAST: - return 5; - case SOUTH_EAST: - return 6; - case SOUTH_SOUTH_EAST: - return 7; - case SOUTH: - return 8; - case SOUTH_SOUTH_WEST: - return 9; - case SOUTH_WEST: - return 10; - case WEST_SOUTH_WEST: - return 11; - case WEST: - return 12; - case WEST_NORTH_WEST: - return 13; - case NORTH_WEST: - return 14; - case NORTH_NORTH_WEST: - return 15; - default: - return -1; - } - } - - /** - * Convert integer to BlockFace representation - * - * @param r integer to get BlockFace for - * @return BlockFace represented by integer. - */ - public static BlockFace fromRotation(int r) { - switch(FastMath.floorMod(r, 16)) { - case 0: - return BlockFace.NORTH; - case 1: - return BlockFace.NORTH_NORTH_EAST; - case 2: - return BlockFace.NORTH_EAST; - case 3: - return BlockFace.EAST_NORTH_EAST; - case 4: - return BlockFace.EAST; - case 5: - return BlockFace.EAST_SOUTH_EAST; - case 6: - return BlockFace.SOUTH_EAST; - case 7: - return BlockFace.SOUTH_SOUTH_EAST; - case 8: - return BlockFace.SOUTH; - case 9: - return BlockFace.SOUTH_SOUTH_WEST; - case 10: - return BlockFace.SOUTH_WEST; - case 11: - return BlockFace.WEST_SOUTH_WEST; - case 12: - return BlockFace.WEST; - case 13: - return BlockFace.WEST_NORTH_WEST; - case 14: - return BlockFace.NORTH_WEST; - case 15: - return BlockFace.NORTH_NORTH_WEST; - default: - throw new IllegalArgumentException(); - } - } - - public static Axis getRotatedAxis(Axis orig, Rotation r) { - Axis other = orig; - final boolean shouldSwitch = r.equals(Rotation.CW_90) || r.equals(Rotation.CCW_90); - switch(orig) { - case X: - if(shouldSwitch) other = Axis.Z; - break; - case Z: - if(shouldSwitch) other = Axis.X; - break; - } - return other; - } - - /** - * Method to rotate the incredibly obnoxious Rail.Shape enum - * - * @param orig Original shape - * @param r Rotate - * @return Rotated/mirrored shape - */ - @SuppressWarnings("fallthrough") - public static Rail.Shape getRotatedRail(Rail.Shape orig, Rotation r) { - switch(r) { - case CCW_90: - switch(orig) { - case NORTH_WEST: - return Rail.Shape.SOUTH_WEST; - case NORTH_SOUTH: - return Rail.Shape.EAST_WEST; - case SOUTH_WEST: - return Rail.Shape.SOUTH_EAST; - case SOUTH_EAST: - return Rail.Shape.NORTH_EAST; - case EAST_WEST: - return Rail.Shape.NORTH_SOUTH; - case NORTH_EAST: - return Rail.Shape.NORTH_WEST; - case ASCENDING_EAST: - return Rail.Shape.ASCENDING_NORTH; - case ASCENDING_WEST: - return Rail.Shape.ASCENDING_SOUTH; - case ASCENDING_NORTH: - return Rail.Shape.ASCENDING_WEST; - case ASCENDING_SOUTH: - return Rail.Shape.ASCENDING_EAST; - } - case CW_90: - switch(orig) { - case NORTH_WEST: - return Rail.Shape.NORTH_EAST; - case NORTH_SOUTH: - return Rail.Shape.EAST_WEST; - case SOUTH_WEST: - return Rail.Shape.NORTH_WEST; - case SOUTH_EAST: - return Rail.Shape.SOUTH_WEST; - case EAST_WEST: - return Rail.Shape.NORTH_SOUTH; - case NORTH_EAST: - return Rail.Shape.SOUTH_EAST; - case ASCENDING_EAST: - return Rail.Shape.ASCENDING_SOUTH; - case ASCENDING_WEST: - return Rail.Shape.ASCENDING_NORTH; - case ASCENDING_NORTH: - return Rail.Shape.ASCENDING_EAST; - case ASCENDING_SOUTH: - return Rail.Shape.ASCENDING_WEST; - } - case CW_180: - switch(orig) { - case NORTH_WEST: - return Rail.Shape.SOUTH_EAST; - case NORTH_SOUTH: - return Rail.Shape.NORTH_SOUTH; - case SOUTH_WEST: - return Rail.Shape.NORTH_EAST; - case SOUTH_EAST: - return Rail.Shape.NORTH_WEST; - case EAST_WEST: - return Rail.Shape.EAST_WEST; - case NORTH_EAST: - return Rail.Shape.SOUTH_WEST; - case ASCENDING_EAST: - return Rail.Shape.ASCENDING_WEST; - case ASCENDING_WEST: - return Rail.Shape.ASCENDING_EAST; - case ASCENDING_NORTH: - return Rail.Shape.ASCENDING_SOUTH; - case ASCENDING_SOUTH: - return Rail.Shape.ASCENDING_NORTH; - } - } - return orig; - } - - public static void rotateBlockData(BlockData data, Rotation r) { - if(data instanceof Rotatable) { - BlockFace rt = getRotatedFace(((Rotatable) data).getRotation(), r); - ((Rotatable) data).setRotation(rt); - } else if(data instanceof Directional) { - BlockFace rt = getRotatedFace(((Directional) data).getFacing(), r); - ((Directional) data).setFacing(rt); - } else if(data instanceof MultipleFacing) { - MultipleFacing mfData = (MultipleFacing) data; - Map faces = new EnumMap<>(BlockFace.class); - for(BlockFace f : mfData.getAllowedFaces()) { - faces.put(f, mfData.hasFace(f)); - } - for(Map.Entry face : faces.entrySet()) { - mfData.setFace(getRotatedFace(face.getKey(), r), face.getValue()); - } - } else if(data instanceof Rail) { - Rail.Shape newShape = getRotatedRail(((Rail) data).getShape(), r); - ((Rail) data).setShape(newShape); - } else if(data instanceof Orientable) { - Axis newAxis = getRotatedAxis(((Orientable) data).getAxis(), r); - ((Orientable) data).setAxis(newAxis); - } else if(data instanceof RedstoneWire) { - Map connections = new EnumMap<>(BlockFace.class); - RedstoneWire rData = (RedstoneWire) data; - for(BlockFace f : rData.getAllowedFaces()) { - connections.put(f, rData.getFace(f)); - } - for(Map.Entry e : connections.entrySet()) { - rData.setFace(getRotatedFace(e.getKey(), r), e.getValue()); - } - } else if(data instanceof Wall) { - Wall wallData = (Wall) data; - Map faces = new EnumMap<>(BlockFace.class); - for(BlockFace b : CARDINALS) faces.put(b, wallData.getHeight(b)); - for(Map.Entry face : faces.entrySet()) { - wallData.setHeight(getRotatedFace(face.getKey(), r), face.getValue()); - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Buffer.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Buffer.java deleted file mode 100644 index 319534b78..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Buffer.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; - -public interface Buffer { - Buffer addItem(BufferedItem item, Location location); - - Location getOrigin(); - - String getMark(Location location); - - Buffer setMark(String mark, Location location); -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Cell.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Cell.java deleted file mode 100644 index faf4860ab..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/Cell.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; -import com.dfsek.terra.api.util.GlueList; - -import java.util.List; - -public class Cell implements BufferedItem { - private final List items = new GlueList<>(); - private String mark = null; - - - @Override - public void paste(Location origin) { - items.forEach(item -> item.paste(origin)); - } - - public void add(BufferedItem item) { - items.add(item); - } - - public String getMark() { - return mark; - } - - public void setMark(String mark) { - this.mark = mark; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/DirectBuffer.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/DirectBuffer.java deleted file mode 100644 index 40881ec0c..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/DirectBuffer.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Buffer implementation that directly pastes to the world. - */ -public class DirectBuffer implements Buffer { - private final Location origin; - private final Map marks = new LinkedHashMap<>(); - - public DirectBuffer(Location origin) { - this.origin = origin; - } - - @Override - public Buffer addItem(BufferedItem item, Location location) { - item.paste(origin.clone().add(location)); - return this; - } - - @Override - public Location getOrigin() { - return origin; - } - - @Override - public String getMark(Location location) { - return marks.get(location); - } - - @Override - public Buffer setMark(String mark, Location location) { - marks.put(location, mark); - return this; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/IntermediateBuffer.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/IntermediateBuffer.java deleted file mode 100644 index 34250571f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/IntermediateBuffer.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; - -public class IntermediateBuffer implements Buffer { - private final Buffer original; - private final Vector3 offset; - - public IntermediateBuffer(Buffer original, Vector3 offset) { - this.original = original; - this.offset = offset.clone(); - } - - @Override - public Buffer addItem(BufferedItem item, Location location) { - return original.addItem(item, location.add(offset)); - } - - @Override - public Location getOrigin() { - return original.getOrigin().clone().add(offset); - } - - @Override - public String getMark(Location location) { - return original.getMark(location.add(offset)); - } - - @Override - public Buffer setMark(String mark, Location location) { - original.setMark(mark, location.add(offset)); - return this; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java deleted file mode 100644 index 7b4e49a2e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/StructureBuffer.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.structures.structure.buffer.items.BufferedItem; -import net.jafama.FastMath; - -import java.util.LinkedHashMap; -import java.util.Map; - -public class StructureBuffer implements Buffer { - private final Map bufferedItemMap = new LinkedHashMap<>(); - private final Location origin; - private boolean succeeded; - - public StructureBuffer(Location origin) { - this.origin = origin; - } - - public void paste() { - bufferedItemMap.forEach(((vector3, item) -> item.paste(origin.clone().add(vector3)))); - } - - public void paste(Chunk chunk) { - bufferedItemMap.forEach(((location, item) -> { - Location current = origin.clone().add(location); - if(FastMath.floorDiv(current.getBlockX(), 16) != chunk.getX() || FastMath.floorDiv(current.getBlockZ(), 16) != chunk.getZ()) - return; - item.paste(chunk, current); - })); - } - - @Override - public Buffer addItem(BufferedItem item, Location location) { - bufferedItemMap.computeIfAbsent(location, l -> new Cell()).add(item); - return this; - } - - @Override - public String getMark(Location location) { - Cell cell = bufferedItemMap.get(location); - if(cell != null) { - return cell.getMark(); - } - return null; - } - - @Override - public Buffer setMark(String mark, Location location) { - bufferedItemMap.computeIfAbsent(location, l -> new Cell()).setMark(mark); - return this; - } - - public void setSucceeded(boolean succeeded) { - this.succeeded = succeeded; - } - - public boolean succeeded() { - return succeeded; - } - - @Override - public Location getOrigin() { - return origin.clone(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java deleted file mode 100644 index 9507edd15..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer.items; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.data.Waterlogged; - -public class BufferedBlock implements BufferedItem { - private final BlockData data; - private final boolean overwrite; - private final TerraPlugin main; - private final boolean waterlog; - - public BufferedBlock(BlockData data, boolean overwrite, TerraPlugin main, boolean waterlog) { - this.data = data; - this.overwrite = overwrite; - this.main = main; - this.waterlog = waterlog; - } - - @Override - public void paste(Location origin) { - Block block = origin.getBlock(); - try { - if(overwrite || block.isEmpty()) { - if(waterlog && data instanceof Waterlogged && block.getBlockData().getBlockType().isWater()) - ((Waterlogged) data).setWaterlogged(true); - block.setBlockData(data, false); - } - } catch(RuntimeException e) { - main.logger().severe("Failed to place block at location " + origin + ": " + e.getMessage()); - main.getDebugLogger().stack(e); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedEntity.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedEntity.java deleted file mode 100644 index fc90123ce..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedEntity.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer.items; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.event.events.world.generation.EntitySpawnEvent; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.entity.EntityType; - -public class BufferedEntity implements BufferedItem { - - private final EntityType type; - private final TerraPlugin main; - - public BufferedEntity(EntityType type, TerraPlugin main) { - this.type = type; - this.main = main; - } - - @Override - public void paste(Location origin) { - Entity entity = origin.clone().add(0.5, 0, 0.5).getWorld().spawnEntity(origin, type); - main.getEventManager().callEvent(new EntitySpawnEvent(entity.getWorld().getTerraGenerator().getConfigPack(), entity, entity.getLocation())); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedItem.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedItem.java deleted file mode 100644 index 7d6ddef2c..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedItem.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer.items; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Chunk; - -public interface BufferedItem { - void paste(Location origin); - - default void paste(Chunk chunk, Location origin) { - origin.setWorld(chunk.getWorld()); // Fabric weirdness - paste(origin); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java deleted file mode 100644 index 89e534449..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedLootApplication.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer.items; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.event.events.world.generation.LootPopulateEvent; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.api.platform.block.state.Container; -import com.dfsek.terra.api.structures.loot.LootTable; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.util.FastRandom; - -public class BufferedLootApplication implements BufferedItem { - private final LootTable table; - private final TerraPlugin main; - private final StructureScript structure; - - public BufferedLootApplication(LootTable table, TerraPlugin main, StructureScript structure) { - this.table = table; - this.main = main; - this.structure = structure; - } - - @Override - public void paste(Location origin) { - try { - Block block = origin.getBlock(); - BlockState data = block.getState(); - if(!(data instanceof Container)) { - main.logger().severe("Failed to place loot at " + origin + "; block " + data + " is not container."); - return; - } - Container container = (Container) data; - - LootPopulateEvent event = new LootPopulateEvent(block, container, table, block.getLocation().getWorld().getTerraGenerator().getConfigPack(), structure); - main.getEventManager().callEvent(event); - if(event.isCancelled()) return; - - event.getTable().fillInventory(container.getInventory(), new FastRandom(origin.hashCode())); - data.update(false); - } catch(Exception e) { - main.logger().warning("Could not apply loot at " + origin + ": " + e.getMessage()); - e.printStackTrace(); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedPulledBlock.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedPulledBlock.java deleted file mode 100644 index e82a061d8..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedPulledBlock.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer.items; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; - -public class BufferedPulledBlock implements BufferedItem { - private final BlockData data; - - public BufferedPulledBlock(BlockData data) { - this.data = data; - } - - @Override - public void paste(Location origin) { - Block pos = origin.getBlock(); - while(pos.getY() > origin.getWorld().getMinHeight()) { - if(!pos.isEmpty()) { - pos.setBlockData(data, false); - break; - } - pos = pos.getRelative(BlockFace.DOWN); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedStateManipulator.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedStateManipulator.java deleted file mode 100644 index 158f1a951..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedStateManipulator.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.api.structures.structure.buffer.items; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.state.BlockState; - -public class BufferedStateManipulator implements BufferedItem { - private final TerraPlugin main; - private final String data; - - public BufferedStateManipulator(TerraPlugin main, String state) { - this.main = main; - this.data = state; - } - - @Override - public void paste(Location origin) { - try { - BlockState state = origin.getBlock().getState(); - state.applyState(data); - state.update(false); - } catch(Exception e) { - main.logger().warning("Could not apply BlockState at " + origin + ": " + e.getMessage()); - e.printStackTrace(); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/EOFException.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/EOFException.java deleted file mode 100644 index 1d615f601..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/EOFException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.api.structures.tokenizer.exceptions; - -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class EOFException extends TokenizerException { - - private static final long serialVersionUID = 3980047409902809440L; - - public EOFException(String message, Position position) { - super(message, position); - } - - public EOFException(String message, Position position, Throwable cause) { - super(message, position, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/FormatException.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/FormatException.java deleted file mode 100644 index 3ca38e126..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/FormatException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.api.structures.tokenizer.exceptions; - -import com.dfsek.terra.api.structures.tokenizer.Position; - -public class FormatException extends TokenizerException { - - private static final long serialVersionUID = -791308012940744455L; - - public FormatException(String message, Position position) { - super(message, position); - } - - public FormatException(String message, Position position, Throwable cause) { - super(message, position, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/TokenizerException.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/TokenizerException.java deleted file mode 100644 index 15990bdfa..000000000 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/exceptions/TokenizerException.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.api.structures.tokenizer.exceptions; - -import com.dfsek.terra.api.structures.parser.exceptions.ParseException; -import com.dfsek.terra.api.structures.tokenizer.Position; - -public abstract class TokenizerException extends ParseException { - - private static final long serialVersionUID = 2792384010083575420L; - - public TokenizerException(String message, Position position) { - super(message, position); - } - - public TokenizerException(String message, Position position, Throwable cause) { - super(message, position, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/AttemptsFailedException.java b/common/src/main/java/com/dfsek/terra/api/transform/AttemptsFailedException.java deleted file mode 100644 index 904758a6c..000000000 --- a/common/src/main/java/com/dfsek/terra/api/transform/AttemptsFailedException.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.api.transform; - -import com.dfsek.terra.api.util.GlueList; - -import java.util.List; - -public class AttemptsFailedException extends RuntimeException { - private static final long serialVersionUID = -1160459550006067137L; - private final List causes; - - public AttemptsFailedException(String message, List causes) { - super(message); - this.causes = causes; - } - - public List getCauses() { - return new GlueList<>(causes); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/MapTransform.java b/common/src/main/java/com/dfsek/terra/api/transform/MapTransform.java deleted file mode 100644 index efd409194..000000000 --- a/common/src/main/java/com/dfsek/terra/api/transform/MapTransform.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.api.transform; - -import java.util.HashMap; -import java.util.Map; - -public class MapTransform implements Transform { - private final Map map; - - public MapTransform(Map map) { - this.map = map; - } - - public MapTransform() { - this.map = new HashMap<>(); - } - - public MapTransform add(F from, T to) { - map.put(from, to); - return this; - } - - public MapTransform remove(F from) { - map.remove(from); - return this; - } - - @Override - public T transform(F input) throws TransformException { - if(!map.containsKey(input)) throw new TransformException("No key matching " + input.toString() + " found in map."); - return map.get(input); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/Transform.java b/common/src/main/java/com/dfsek/terra/api/transform/Transform.java deleted file mode 100644 index 2732b1da7..000000000 --- a/common/src/main/java/com/dfsek/terra/api/transform/Transform.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dfsek.terra.api.transform; - -/** - * Interface to transform data from one type to another. - */ -@FunctionalInterface -public interface Transform { - T transform(F input) throws TransformException; -} diff --git a/common/src/main/java/com/dfsek/terra/api/transform/Validator.java b/common/src/main/java/com/dfsek/terra/api/transform/Validator.java deleted file mode 100644 index b22b7c08b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/transform/Validator.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.api.transform; - - -import java.util.Objects; - -public interface Validator { - boolean validate(T value) throws TransformException; - - static Validator notNull() { - return Objects::nonNull; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/FastRandom.java b/common/src/main/java/com/dfsek/terra/api/util/FastRandom.java deleted file mode 100644 index fc530944a..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/FastRandom.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.dfsek.terra.api.util; - - -import org.apache.commons.rng.core.source64.XoRoShiRo128PlusPlus; - -import java.util.Random; -import java.util.SplittableRandom; - -public class FastRandom extends Random { - - private static final long serialVersionUID = 4571946470190183260L; - private XoRoShiRo128PlusPlus random; - - public FastRandom() { - super(); - SplittableRandom randomseed = new SplittableRandom(); - this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong()); - } - - public FastRandom(long seed) { - super(seed); - SplittableRandom randomseed = new SplittableRandom(seed); - this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong()); - } - - @Override - public boolean nextBoolean() { - return random.nextBoolean(); - } - - @Override - public int nextInt() { - return random.nextInt(); - } - - @Override - public float nextFloat() { - return (float) random.nextDouble(); - } - - @Override - public double nextDouble() { - return random.nextDouble(); - } - - @Override - public synchronized void setSeed(long seed) { - SplittableRandom randomseed = new SplittableRandom(seed); - this.random = new XoRoShiRo128PlusPlus(randomseed.nextLong(), randomseed.nextLong()); - } - - @Override - public void nextBytes(byte[] bytes) { - random.nextBytes(bytes); - } - - @Override - public int nextInt(int bound) { - return random.nextInt(bound); - } - - @Override - public long nextLong() { - return random.nextLong(); - } -} \ No newline at end of file diff --git a/common/src/main/java/com/dfsek/terra/api/util/GlueList.java b/common/src/main/java/com/dfsek/terra/api/util/GlueList.java deleted file mode 100644 index 144738f56..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/GlueList.java +++ /dev/null @@ -1,1051 +0,0 @@ -/* - * Copyright 2015 Ertuğrul Çetin - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dfsek.terra.api.util; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.ConcurrentModificationException; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.NoSuchElementException; -import java.util.Objects; - -import static net.jafama.FastMath.*; - - -/** - * GlueList is a brand new List implementation which is way faster than ArrayList and LinkedList. - * This implementation inspired from ArrayList and LinkedList working mechanism. - *
- * Nodes holding data in arrays, in the beginning the world just like ArrayList ,inserts data into array one by one when there is no space for insertion to array - * new Node will be created and linked with the last Node. - *
- * The array which belongs to newly created node has half of the size of list , just like ArrayList. - * In ArrayList when there is no space for it it creates new array with double of old size and inserts old data into new one. - * Unlike ArrayList GlueList does it dynamically way with creating new node so old data does NOT have to be moved to another array. - * You can think that GlueList is dynamic version of ArrayList. - *
- * Adding and removing operations much faster than ArrayList and LinkedList. - * Searching operations nearly same with ArrayList and way better than LinkedList. - *

- * Best Case
- * Add O(1)
- * Remove O(1)
- * Search O(1)
- * Access O(1) - *

- * "m" number of created nodes.
- * "n" size of node array.
- * If you insert 10_000_000 record into List there will be just 36 nodes.

- * Worst Case
- * Add O(n*m)
- * Remove O(n*m)
- * Search O(m)
- * Access O(m) - * - * version v1.0 - * - * Date: 03.11.2015 - * - * - * @author Ertuğrul Çetin ~ ertu.ctn@gmail.com - * @see Collection - * @see List - * @see LinkedList - * @see ArrayList - * @param the type of elements held in this collection - */ -@SuppressWarnings({"ManualMinMaxCalculation", "ConstantConditions", "ManualArrayToCollectionCopy"}) -public class GlueList extends AbstractList implements List, Cloneable, Serializable { - - private static final long serialVersionUID = -4339173882660322249L; - private transient Node first; - private transient Node last; - - private int size; - - private int initialCapacity; - - private static final int DEFAULT_CAPACITY = 10; - - private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; - - public GlueList() { - - Node initNode = new Node<>(null, null, 0, DEFAULT_CAPACITY); - - first = initNode; - last = initNode; - } - - public GlueList(int initialCapacity) { - - this.initialCapacity = (initialCapacity > MAX_ARRAY_SIZE) ? MAX_ARRAY_SIZE : initialCapacity; - - Node initNode = new Node<>(null, null, 0, initialCapacity); - - first = initNode; - last = initNode; - } - - public GlueList(Collection c) { - - Objects.requireNonNull(c); - - Object[] arr = c.toArray(); - - int len = arr.length; - - if (len != 0) { - - Node initNode = new Node<>(null, null, 0, len); - - first = initNode; - last = initNode; - - System.arraycopy(arr, 0, last.elementData, 0, len); - - last.elementDataPointer += len; - } else { - - Node initNode = new Node<>(null, null, 0, DEFAULT_CAPACITY); - - first = initNode; - last = initNode; - } - - modCount++; - size += len; - } - - @Override - public boolean add(T element) { - - Node l = last; - - if (l.isAddable()) { - l.add(element); - } else { - Node newNode = new Node<>(l, null, size); - newNode.add(element); - last = newNode; - l.next = last; - } - - modCount++; - size++; - - return true; - } - - @SuppressWarnings("unchecked") - @Override - public void add(int index, T element) { - - rangeCheckForAdd(index); - - Node node = getNodeForAdd(index); - - if (node == null) { - - Node l = last; - - Node newNode = new Node<>(l, null, size); - - last = newNode; - - l.next = last; - - node = newNode; - } - - //if it is last and has extra space for element... - if (node == last && node.elementData.length - node.elementDataPointer > 0) { - - int nodeArrIndex = index - node.startingIndex; - - System.arraycopy(node.elementData, nodeArrIndex, node.elementData, nodeArrIndex + 1, node.elementDataPointer - nodeArrIndex); - - node.elementData[nodeArrIndex] = element; - - if (nodeArrIndex > 0) { - System.arraycopy(node.elementData, 0, node.elementData, 0, nodeArrIndex); - } - - node.elementDataPointer++; - } else { - - int newLen = node.elementData.length + 1; - T[] newElementData = (T[]) new Object[newLen]; - - int nodeArrIndex = index - node.startingIndex; - - System.arraycopy(node.elementData, nodeArrIndex, newElementData, nodeArrIndex + 1, node.elementDataPointer - nodeArrIndex); - - newElementData[nodeArrIndex] = element; - - if (nodeArrIndex > 0) { - System.arraycopy(node.elementData, 0, newElementData, 0, nodeArrIndex); - } - - node.elementData = newElementData; - node.endingIndex++; - node.elementDataPointer++; - } - - updateNodesAfterAdd(node); - - modCount++; - size++; - } - - private void rangeCheckForAdd(int index) { - - if (index > size || index < 0) { - throw new ArrayIndexOutOfBoundsException(index); - } - } - - private void updateNodesAfterAdd(Node nodeFrom) { - - for (Node node = nodeFrom.next; node != null; node = node.next) { - - node.startingIndex++; - node.endingIndex++; - } - } - - @SuppressWarnings("unchecked") - @Override - public boolean addAll(@NotNull Collection c) { - - Objects.requireNonNull(c); - - Object[] collection = c.toArray(); - - int len = collection.length; - - if(len == 0) { - return false; - } - - if (size == 0) { - - if (initialCapacity >= len) { - System.arraycopy(collection, 0, last.elementData, 0, len); - } else { - last.elementData = Arrays.copyOf((T[]) collection, len); - last.endingIndex = len - 1; - } - - last.elementDataPointer += len; - - modCount++; - size += len; - - return true; - } - - int elementDataLen = last.elementData.length; - int elementSize = last.elementDataPointer; - - int remainedStorage = elementDataLen - elementSize; - - if (remainedStorage == 0) { - - Node l = last; - - int newLen = (size >>> 1); - int initialLen = (len > newLen) ? len : newLen; - - Node newNode = new Node<>(l, null, size, initialLen); - - System.arraycopy(collection, 0, newNode.elementData, 0, len); - - newNode.elementDataPointer += len; - - last = newNode; - l.next = last; - - modCount++; - size += len; - - return true; - } - - if (len <= remainedStorage) { - - System.arraycopy(collection, 0, last.elementData, elementSize, len); - - last.elementDataPointer += len; - - modCount++; - size += len; - - return true; - } - - if (len > remainedStorage) { - - System.arraycopy(collection, 0, last.elementData, elementSize, remainedStorage); - - last.elementDataPointer += remainedStorage; - size += remainedStorage; - - int newLen = (size >>> 1); - int remainedDataLen = len - remainedStorage; - - int initialLen = (newLen > remainedDataLen) ? newLen : remainedDataLen; - - Node l = last; - - Node newNode = new Node<>(l, null, size, initialLen); - - System.arraycopy(collection, remainedStorage, newNode.elementData, 0, remainedDataLen); - - newNode.elementDataPointer += remainedDataLen; - - last = newNode; - l.next = last; - - modCount++; - size += remainedDataLen; - - return true; - } - - return false; - } - - @Override - public T set(int index, T element) { - - rangeCheck(index); - - Node node = getNode(index); - - int nodeArrIndex = index - node.startingIndex; - - T oldValue = node.elementData[nodeArrIndex]; - - node.elementData[nodeArrIndex] = element; - - return oldValue; - } - - @Override - public T get(int index) { - - rangeCheck(index); - - Node node = getNode(index); - - return node.elementData[index - node.startingIndex]; - } - - @Override - public int indexOf(Object o) { - - int index = 0; - - if (o == null) { - - for (Node node = first; node != null; node = node.next) { - for (int i = 0; i < node.elementDataPointer; i++) { - if (node.elementData[i] == null) { - return index; - } - index++; - } - } - } else { - - for (Node node = first; node != null; node = node.next) { - for (int i = 0; i < node.elementDataPointer; i++) { - if (o.equals(node.elementData[i])) { - return index; - } - index++; - } - } - } - - return -1; - } - - @Override - public int lastIndexOf(Object o) { - - int index = size - 1; - - if (o == null) { - for (Node node = last; node != null; node = node.pre) { - for (int i = node.elementDataPointer - 1; i >= 0; i--) { - if (node.elementData[i] == null) { - return index; - } - index--; - } - } - } else { - - for (Node node = last; node != null; node = node.pre) { - for (int i = node.elementDataPointer - 1; i >= 0; i--) { - if (o.equals(node.elementData[i])) { - return index; - } - index--; - } - } - } - - return -1; - } - - @Override - public boolean contains(Object o) { - return indexOf(o) != -1; - } - - @Override - public T remove(int index) { - - rangeCheck(index); - - Node node; - - if (size == 2 && first != last) { - - Node newNode = new Node<>(null, null, 0, 2); - newNode.add(first.elementData[0]); - newNode.add(last.elementData[0]); - - node = first = last = newNode; - } else { - node = getNode(index); - } - - T[] elementData = node.elementData; - - int elementSize = node.elementDataPointer; - - int nodeArrIndex = index - node.startingIndex; - - T oldValue = elementData[nodeArrIndex]; - - int numMoved = elementSize - nodeArrIndex - 1; - - if (numMoved > 0) { - System.arraycopy(node.elementData, nodeArrIndex + 1, node.elementData, nodeArrIndex, numMoved); - } - - if (first == last || node == last) { - node.elementData[elementSize - 1] = null; - } else { - node.elementData = Arrays.copyOf(node.elementData, elementSize - 1); - node.endingIndex = (--node.endingIndex < 0) ? 0 : node.endingIndex; - } - - node.elementDataPointer--; - - updateNodesAfterRemove(node); - - if (node.elementDataPointer == 0 && first != last) { - - Node next = node.next; - Node prev = node.pre; - - if (prev == null) { - first = next; - } else { - prev.next = next; - node.pre = null; - } - - if (next == null) { - last = prev; - } else { - next.pre = prev; - node.next = null; - } - - node.elementData = null; - } - - size--; - modCount++; - - return oldValue; - } - - @Override - public boolean removeAll(@NotNull Collection c) { - - Objects.requireNonNull(c); - - Object[] arr = c.toArray(); - if(arr.length == 0) { - return false; - } - - boolean isModified = false; - - for (Object o : arr) { - isModified |= remove(o); - } - - return isModified; - } - - @Override - public boolean retainAll(@NotNull Collection c) { - - Objects.requireNonNull(c); - - Object[] arr = c.toArray(); - if(arr.length == 0) { - return false; - } - - boolean isModified = false; - - Object[] elements = toArray(); - - for (Object element : elements) { - - if (!c.contains(element)) { - isModified |= remove(element); - } - } - - return isModified; - } - - @Override - public boolean remove(Object o) { - - int index = indexOf(o); - - if (index != -1) { - remove(index); - return true; - } else { - return false; - } - } - - private void updateNodesAfterRemove(Node fromNode) { - - for (Node node = fromNode.next; node != null; node = node.next) { - - node.startingIndex = (--node.startingIndex < 0) ? 0 : node.startingIndex; - node.endingIndex = (--node.endingIndex < 0) ? 0 : node.endingIndex; - } - } - - private Node getNode(int index) { - - int firstStartingIndex = first.startingIndex; - int firstEndingIndex = first.endingIndex; - - int firstMinDistance = min(abs(index - firstStartingIndex), abs(index - firstEndingIndex)); - - int lastStartingIndex = last.startingIndex; - int lastEndingIndex = last.endingIndex; - - int lastMinDistance = min(abs(index - lastStartingIndex), abs(index - lastEndingIndex)); - - if (firstMinDistance <= lastMinDistance) { - - Node node = first; - do { - - if (node.startingIndex <= index && index <= node.endingIndex) { - return node; - } - - node = node.next; - } while (true); - } else { - - Node node = last; - do { - - if (node.startingIndex <= index && index <= node.endingIndex) { - return node; - } - - node = node.pre; - } while (true); - } - } - - private Node getNodeForAdd(int index) { - - if (index == size && !(last.startingIndex <= index && index <= last.endingIndex)) { - return null; - } - - return getNode(index); - } - - private void rangeCheck(int index) { - - if (index >= size || index < 0) { - throw new ArrayIndexOutOfBoundsException(index); - } - } - - @Override - public void clear() { - - for (Node node = first; node != null; ) { - - Node next = node.next; - - node.next = null; - node.pre = null; - node.elementData = null; - - node = next; - } - - first = last = null; - - int capacity = min(MAX_ARRAY_SIZE, max(size, max(initialCapacity, DEFAULT_CAPACITY))); - - Node initNode = new Node<>(null, null, 0, capacity); - - initialCapacity = capacity; - - first = initNode; - last = initNode; - - modCount++; - size = 0; - } - - public void trimToSize() { - - int pointer = last.elementDataPointer; - int arrLen = last.elementData.length; - - if (pointer < arrLen && arrLen > 2) { - - if (pointer < 2) { - last.elementData = Arrays.copyOf(last.elementData, 2); - last.endingIndex -= arrLen - 2; - } else { - last.elementData = Arrays.copyOf(last.elementData, pointer); - last.endingIndex -= arrLen - pointer; - } - } - } - - @Override - public @NotNull List subList(int fromIndex, int toIndex) { - return super.subList(fromIndex, toIndex); - } - - @Override - public Object[] toArray() { - - Object[] objects = new Object[size]; - - int i = 0; - for (Node node = first; node != null; node = node.next) { - - int len = node.elementDataPointer; - - if (len > 0) { - System.arraycopy(node.elementData, 0, objects, i, len); - } - - i += len; - } - - return objects; - } - - @SuppressWarnings("unchecked") - @Override - public E[] toArray(E[] a) { - return (E[]) Arrays.copyOf(toArray(), size, a.getClass()); - } - - public boolean isEmpty() { - return size == 0; - } - - @Override - public @NotNull Iterator iterator() { - return new Itr(); - } - - @SuppressWarnings("unchecked") - @Override - public Object clone() { - - try { - com.dfsek.terra.api.util.GlueList clone = (com.dfsek.terra.api.util.GlueList) super.clone(); - - clone.first = clone.last = null; - - int capacity = min(MAX_ARRAY_SIZE, max(clone.size, max(clone.initialCapacity, DEFAULT_CAPACITY))); - - Node initNode = new Node<>(null, null, 0, capacity); - - clone.initialCapacity = capacity; - - clone.first = clone.last = initNode; - - clone.modCount = 0; - clone.size = 0; - - for(Node node = first; node != null; node = node.next) { - - for(int i = 0; i < node.elementDataPointer; i++) { - clone.add(node.elementData[i]); - } - } - - return clone; - } catch(CloneNotSupportedException e) { - throw new InternalError(); - } - } - - @Override - public @NotNull ListIterator listIterator(int index) { - - checkPositionIndex(index); - - return new ListItr(index); - } - - private void checkPositionIndex(int index) { - - if(!(index >= 0 && index <= size)) { - throw new ArrayIndexOutOfBoundsException(index); - } - } - - @Override - public @NotNull ListIterator listIterator() { - return new ListItr(0); - } - - protected static class Node { - - protected Node pre; - protected Node next; - - protected int listSize; - - protected int startingIndex; - protected int endingIndex; - - protected T[] elementData; - protected int elementDataPointer; - - @SuppressWarnings("unchecked") - Node(Node pre, Node next, int listSize) { - this.pre = pre; - this.next = next; - this.listSize = listSize; - this.elementData = (T[]) new Object[listSize >>> 1]; - this.startingIndex = listSize; - this.endingIndex = listSize + elementData.length - 1; - } - - Node(Node pre, Node next, int listSize, int initialCapacity) { - this.pre = pre; - this.next = next; - this.listSize = listSize; - this.elementData = createElementData(initialCapacity); - this.startingIndex = listSize; - this.endingIndex = listSize + elementData.length - 1; - } - - @SuppressWarnings("unchecked") - T[] createElementData(int capacity) { - - if(capacity == 0 || capacity == 1) { - return (T[]) new Object[DEFAULT_CAPACITY]; - } else if(capacity > 1) { - return (T[]) new Object[capacity]; - } else { - throw new IllegalArgumentException("Illegal Capacity: " + capacity); - } - } - - boolean isAddable() { - return elementDataPointer < elementData.length; - } - - void add(T element) { - elementData[elementDataPointer++] = element; - } - - @Override - public String toString() { - return String.format("[sIndex: %d - eIndex: %d | elementDataPointer: %d | elementDataLength: %d]", startingIndex, endingIndex, elementDataPointer, elementData.length); - } - } - - @Override - public int size() { - return size; - } - - private class ListItr extends Itr implements ListIterator { - - public ListItr(int index) { - node = (index == size) ? last : getNode(index); - j = index; - i = index - node.startingIndex; - elementDataPointer = node.elementDataPointer; - } - - @Override - public boolean hasPrevious() { - return j != 0; - } - - @Override - public T previous() { - - checkForComodification(); - - int temp = j - 1; - - if (temp < 0) { - throw new NoSuchElementException(); - } - - if (temp >= last.endingIndex + 1) { - throw new ConcurrentModificationException(); - } - - if (j == size) { - - node = last; - - elementDataPointer = node.elementDataPointer; - - i = elementDataPointer; - } - - int index = j - node.startingIndex; - if (index == 0) { - - node = node.pre; - - elementDataPointer = node.elementDataPointer; - - i = elementDataPointer; - } - - T val = node.elementData[--i]; - - if (i < 0) { - node = node.pre; - i = (node != null) ? node.elementDataPointer : 0; - } - - j = temp; - - lastReturn = j; - - return val; - } - - @Override - public int nextIndex() { - return j; - } - - @Override - public int previousIndex() { - return j - 1; - } - - @Override - public void set(T t) { - - if (lastReturn < 0) { - throw new IllegalStateException(); - } - - checkForComodification(); - - try { - com.dfsek.terra.api.util.GlueList.this.set(lastReturn, t); - } catch (IndexOutOfBoundsException e) { - throw new ConcurrentModificationException(); - } - } - - @Override - public void add(T t) { - - checkForComodification(); - - try { - int temp = j; - - com.dfsek.terra.api.util.GlueList.this.add(temp, t); - - j = temp + 1; - - lastReturn = -1; - - i++; - elementDataPointer = (node != null) ? node.elementDataPointer : 0; - - expectedModCount = modCount; - } catch (IndexOutOfBoundsException e) { - throw new ConcurrentModificationException(); - } - } - } - - private void writeObject(ObjectOutputStream s) throws IOException { - - int expectedModCount = modCount; - - s.defaultWriteObject(); - - s.writeInt(size); - - for (Node node = first; node != null; node = node.next) { - for (int i = 0; i < node.elementDataPointer; i++) { - s.writeObject(node.elementData[i]); - } - } - - if (modCount != expectedModCount) { - throw new ConcurrentModificationException(); - } - } - - - @SuppressWarnings("unchecked") - private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { - - clear(); - - s.defaultReadObject(); - - int size = s.readInt(); - - for (int i = 0; i < size; i++) { - last.add((T) s.readObject()); - } - } - - private class Itr implements Iterator { - - protected Node node = first; - - protected int i = 0;//inner-array index - protected int j = 0;//total index -> cursor - - protected int lastReturn = -1; - - protected int expectedModCount = modCount; - protected int elementDataPointer = node.elementDataPointer; - - @Override - public boolean hasNext() { - return j != size; - } - - @Override - public T next() { - - checkForComodification(); - - if(j >= size) { - throw new NoSuchElementException(); - } - - if(j >= last.endingIndex + 1) { - throw new ConcurrentModificationException(); - } - - if(j == 0) {// it's for listIterator.when node becomes null. - node = first; - elementDataPointer = node.elementDataPointer; - i = 0; - } - - T val = node.elementData[i++]; - - if(i >= elementDataPointer) { - node = node.next; - i = 0; - elementDataPointer = (node != null) ? node.elementDataPointer : 0; - } - - lastReturn = j++; - - return val; - } - - @Override - public void remove() { - - if(lastReturn < 0) { - throw new IllegalStateException(); - } - - checkForComodification(); - - try { - com.dfsek.terra.api.util.GlueList.this.remove(lastReturn); - - j = lastReturn; - - lastReturn = -1; - - i = (--i < 0) ? 0 : i; - - elementDataPointer = (node != null) ? node.elementDataPointer : 0; - - expectedModCount = modCount; - } catch(IndexOutOfBoundsException e) { - throw new ConcurrentModificationException(); - } - } - - void checkForComodification() { - if(modCount != expectedModCount) { - throw new ConcurrentModificationException(); - } - } - } -} \ No newline at end of file diff --git a/common/src/main/java/com/dfsek/terra/api/util/JarUtil.java b/common/src/main/java/com/dfsek/terra/api/util/JarUtil.java deleted file mode 100644 index 981dfdb7f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/JarUtil.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.dfsek.terra.api.util; - -import com.dfsek.terra.api.TerraPlugin; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Enumeration; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -public class JarUtil { - public static void copyResourcesToDirectory(JarFile fromJar, String sourceDir, String destDir) throws IOException { - for(Enumeration entries = fromJar.entries(); entries.hasMoreElements(); ) { - JarEntry entry = entries.nextElement(); - if(entry.getName().startsWith(sourceDir + "/") && ! entry.isDirectory()) { - File dest = new File(destDir + File.separator + entry.getName().substring(sourceDir.length() + 1)); - if(dest.exists()) continue; - File parent = dest.getParentFile(); - if(parent != null) { - parent.mkdirs(); - } - try(FileOutputStream out = new FileOutputStream(dest); InputStream in = fromJar.getInputStream(entry)) { - byte[] buffer = new byte[(8192)]; - - int s; - while((s = in.read(buffer)) > 0) { - out.write(buffer, 0, s); - } - } catch(IOException e) { - throw new IOException("Could not copy asset from jar file", e); - } - } - } - } - - public static JarFile getJarFile() throws URISyntaxException, IOException { - return new JarFile(new File(getJarURL().toURI())); - } - - public static URL getJarURL() { - return TerraPlugin.class.getProtectionDomain().getCodeSource().getLocation(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/ReflectionUtil.java b/common/src/main/java/com/dfsek/terra/api/util/ReflectionUtil.java deleted file mode 100644 index 34c70dae9..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/ReflectionUtil.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.api.util; - -import org.jetbrains.annotations.NotNull; - -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.function.Consumer; -import java.util.stream.Stream; - -public class ReflectionUtil { - public static Field[] getFields(@NotNull Class type) { - Field[] result = type.getDeclaredFields(); - Class parentClass = type.getSuperclass(); - if(parentClass != null) { - result = Stream.concat(Arrays.stream(result), Arrays.stream(getFields(parentClass))).toArray(Field[]::new); - } - return result; - } - - public static Method[] getMethods(@NotNull Class type) { - Method[] result = type.getDeclaredMethods(); - Class parentClass = type.getSuperclass(); - if(parentClass != null) { - result = Stream.concat(Arrays.stream(result), Arrays.stream(getMethods(parentClass))).toArray(Method[]::new); - } - return result; - } - - public static void ifAnnotationPresent(AnnotatedElement element, Class annotation, Consumer operation) { - T a = element.getAnnotation(annotation); - if(a != null) operation.accept(a); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/collections/MaterialSet.java b/common/src/main/java/com/dfsek/terra/api/util/collections/MaterialSet.java deleted file mode 100644 index 77099137e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/collections/MaterialSet.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.dfsek.terra.api.util.collections; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; - -import java.util.Arrays; -import java.util.HashSet; - -public class MaterialSet extends HashSet { - private static final long serialVersionUID = 3056512763631017301L; - - public static MaterialSet singleton(BlockType material) { - MaterialSet set = new MaterialSet(); - set.add(material); - return set; - } - - public static MaterialSet get(BlockType... materials) { - MaterialSet set = new MaterialSet(); - set.addAll(Arrays.asList(materials)); - return set; - } - - public static MaterialSet get(BlockData... materials) { - MaterialSet set = new MaterialSet(); - Arrays.stream(materials).forEach(set::add); - return set; - } - - public static MaterialSet empty() { - return new MaterialSet(); - } - - private void add(BlockData data) { - add(data.getBlockType()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/generic/pair/ImmutablePair.java b/common/src/main/java/com/dfsek/terra/api/util/generic/pair/ImmutablePair.java deleted file mode 100644 index f58cbb52b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/generic/pair/ImmutablePair.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.api.util.generic.pair; - -public class ImmutablePair { - private final L left; - private final R right; - - public ImmutablePair(L left, R right) { - this.left = left; - this.right = right; - } - - public static ImmutablePair of(L1 left, R1 right) { - return new ImmutablePair<>(left, right); - } - - public R getRight() { - return right; - } - - public L getLeft() { - return left; - } - - public Pair mutable() { - return new Pair<>(left, right); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java b/common/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java deleted file mode 100644 index dcb0be070..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.api.util.generic.pair; - -public class Pair { - private L left; - private R right; - - public Pair(L left, R right) { - this.left = left; - this.right = right; - } - - public static Pair of(L1 left, R1 right) { - return new Pair<>(left, right); - } - - public L getLeft() { - return left; - } - - public void setLeft(L left) { - this.left = left; - } - - public R getRight() { - return right; - } - - public void setRight(R right) { - this.right = right; - } - - public ImmutablePair immutable() { - return new ImmutablePair<>(left, right); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/hash/HashIntrinsic.java b/common/src/main/java/com/dfsek/terra/api/util/hash/HashIntrinsic.java deleted file mode 100644 index 638d8a66c..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/hash/HashIntrinsic.java +++ /dev/null @@ -1,118 +0,0 @@ -/* -Copyright 2009 Sandia Corporation. Under the terms of Contract -DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government -retains certain rights in this software. - -BSD Open Source License. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Sandia National Laboratories nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - */ - -package com.dfsek.terra.api.util.hash; - -import java.io.Serializable; - -public abstract class HashIntrinsic implements Serializable { - public static final int FLOAT_EXP_BIT_MASK = 2139095040; - public static final int FLOAT_SIGNIF_BIT_MASK = 8388607; - public static final long DOUBLE_EXP_BIT_MASK = 9218868437227405312L; - public static final long DOUBLE_SIGNIF_BIT_MASK = 4503599627370495L; - protected static final int DEFAULT_INITIAL_CAPACITY = 16; - protected static final int MAXIMUM_CAPACITY = 1073741824; - protected static final float DEFAULT_LOAD_FACTOR = 0.75F; - private static final long serialVersionUID = 8058099372006904458L; - protected int size; - protected int threshold; - protected float loadFactor; - protected int capMinus1; - - protected HashIntrinsic(int initialCapacity, float loadFactor) { - if(initialCapacity <= 0) { - throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); - } else if(!(loadFactor <= 0.0F) && !Float.isNaN(loadFactor)) { - if(initialCapacity > 1073741824) { - initialCapacity = 1073741824; - } - - int capacity; - for(capacity = 1; capacity < initialCapacity; capacity <<= 1) { - } - - this.capMinus1 = capacity - 1; - this.loadFactor = loadFactor; - this.threshold = (int) ((float) capacity * loadFactor); - } else { - throw new IllegalArgumentException("Illegal load factor: " + loadFactor); - } - } - - protected static int hashCodeLong(long value) { - return (int) (value ^ value >>> 32); - } - - protected static int hashCodeFloat(float value) { - return floatToIntBits(value); - } - - protected static int hashCodeDouble(double value) { - long bits = doubleToLongBits(value); - return (int) (bits ^ bits >>> 32); - } - - public static int floatToIntBits(float value) { - int result = Float.floatToRawIntBits(value); - if((result & 2139095040) == 2139095040 && (result & 8388607) != 0) { - result = 2143289344; - } - - return result; - } - - public static long doubleToLongBits(double value) { - long result = Double.doubleToRawLongBits(value); - if((result & 9218868437227405312L) == 9218868437227405312L && (result & 4503599627370495L) != 0L) { - result = 9221120237041090560L; - } - - return result; - } - - protected static int tableIndex(int hc, int lm1) { - hc ^= hc >>> 20 ^ hc >>> 12; - hc ^= hc >>> 7 ^ hc >>> 4; - return hc & lm1; - } - - public int size() { - return this.size; - } - - public boolean isEmpty() { - return this.size == 0; - } - - public abstract void clear(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/hash/HashMapDoubleDouble.java b/common/src/main/java/com/dfsek/terra/api/util/hash/HashMapDoubleDouble.java deleted file mode 100644 index edad7aa32..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/hash/HashMapDoubleDouble.java +++ /dev/null @@ -1,291 +0,0 @@ -/* -Copyright 2009 Sandia Corporation. Under the terms of Contract -DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government -retains certain rights in this software. - -BSD Open Source License. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Sandia National Laboratories nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - */ - -package com.dfsek.terra.api.util.hash; - -import java.io.Serializable; -import java.util.NoSuchElementException; - -public class HashMapDoubleDouble extends HashIntrinsic { - private static final long serialVersionUID = 2109458761298324234L; - private HashMapDoubleDouble.Entry[] table; - - public HashMapDoubleDouble(int initialCapacity, float loadFactor) { - super(initialCapacity, loadFactor); - this.table = this.createTable(this.capMinus1 + 1); - } - - public HashMapDoubleDouble(int initialCapacity) { - this(initialCapacity, 0.75F); - } - - public HashMapDoubleDouble() { - this(16, 0.75F); - } - - public final boolean contains(double key) { - int i = tableIndex(hashCodeDouble(key), this.capMinus1); - - for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) { - if(e.key == key) { - return true; - } - } - - return false; - } - - public boolean containsValue(double value) { - for(int i = 0; i < this.table.length; ++i) { - for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) { - if(value == e.value) { - return true; - } - } - } - - return false; - } - - public double get(double key) { - int i = tableIndex(hashCodeDouble(key), this.capMinus1); - - for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) { - if(key == e.key) { - return e.value; - } - } - - return 4.9E-324D; - } - - public HashMapDoubleDouble.Entry getEntry(double key) { - int i = tableIndex(hashCodeDouble(key), this.capMinus1); - - for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) { - if(key == e.key) { - return e; - } - } - - return null; - } - - public double put(double key, double value) { - int i = tableIndex(hashCodeDouble(key), this.capMinus1); - - for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) { - if(key == e.key) { - double oldValue = e.value; - e.value = value; - return oldValue; - } - } - - this.addEntry(key, value, i); - return 4.9E-324D; - } - - private void addEntry(double key, double value, int index) { - HashMapDoubleDouble.Entry e = this.table[index]; - this.table[index] = new HashMapDoubleDouble.Entry(key, value, e); - if(this.size++ >= this.threshold) { - this.resize(2 * this.table.length); - } - - } - - public void resize(int newCapacity) { - int oldCapacity = this.table.length; - if(oldCapacity == 1073741824) { - this.threshold = 2147483647; - } else { - HashMapDoubleDouble.Entry[] newTable = this.createTable(newCapacity); - this.capMinus1 = newCapacity - 1; - this.transfer(newTable); - this.table = newTable; - this.threshold = (int) ((float) newCapacity * this.loadFactor); - } - } - - private void transfer(HashMapDoubleDouble.Entry[] newTable) { - for(int j = 0; j < this.table.length; ++j) { - HashMapDoubleDouble.Entry e = this.table[j]; - if(e != null) { - this.table[j] = null; - - HashMapDoubleDouble.Entry next; - do { - next = e.next; - int i = tableIndex(hashCodeDouble(e.key), this.capMinus1); - e.next = newTable[i]; - newTable[i] = e; - e = next; - } while(next != null); - } - } - - } - - public final HashMapDoubleDouble.Entry remove(double key) { - int i = tableIndex(hashCodeDouble(key), this.capMinus1); - HashMapDoubleDouble.Entry prev = this.table[i]; - - HashMapDoubleDouble.Entry e; - HashMapDoubleDouble.Entry next; - for(e = prev; e != null; e = next) { - next = e.next; - if(key == e.key) { - --this.size; - if(prev == e) { - this.table[i] = next; - } else { - prev.next = next; - } - - return e; - } - - prev = e; - } - - return e; - } - - public void clear() { - for(int i = 0; i < this.table.length; ++i) { - this.table[i] = null; - } - - this.size = 0; - } - - private HashMapDoubleDouble.Entry[] createTable(int capacity) { - return new HashMapDoubleDouble.Entry[capacity]; - } - - public long memoryEstimate(int ptrsize) { - return (long) ptrsize * (long) (this.capMinus1 + this.size + 1) + (long) (this.size * 64 / 4); - } - - public HashMapDoubleDouble.Iterator iterator() { - return new HashMapDoubleDouble.Iterator(); - } - - public static class Entry implements Serializable { - private static final long serialVersionUID = 7972173983741231238L; - private final double key; - private double value; - private HashMapDoubleDouble.Entry next; - - public Entry(double key, double val, HashMapDoubleDouble.Entry n) { - this.key = key; - this.value = val; - this.next = n; - } - - public final double getKey() { - return this.key; - } - - public final double getValue() { - return this.value; - } - - public final double setValue(double newValue) { - double oldValue = this.value; - this.value = newValue; - return oldValue; - } - - public final boolean equals(Object o) { - HashMapDoubleDouble.Entry e = (HashMapDoubleDouble.Entry) o; - return this.key == e.key && this.value == e.value; - } - - public final String toString() { - return this.key + " = " + this.value; - } - - public final int hashCode() { - return hashCodeDouble(key) + hashCodeDouble(value); - } - } - - public class Iterator { - HashMapDoubleDouble.Entry next; - int index; - HashMapDoubleDouble.Entry current; - - Iterator() { - if(HashMapDoubleDouble.this.size > 0) { - while(this.index < HashMapDoubleDouble.this.table.length && (this.next = HashMapDoubleDouble.this.table[this.index++]) == null) { - } - } - - } - - public final boolean hasNext() { - return this.next != null; - } - - public HashMapDoubleDouble.Entry nextEntry() { - HashMapDoubleDouble.Entry e = this.next; - if(e == null) { - throw new NoSuchElementException(); - } else { - if((this.next = e.next) == null) { - while(this.index < HashMapDoubleDouble.this.table.length && (this.next = HashMapDoubleDouble.this.table[this.index++]) == null) { - } - } - - this.current = e; - return e; - } - } - - public double next() { - return this.nextEntry().value; - } - - public void remove() { - if(this.current == null) { - throw new IllegalStateException(); - } else { - double k = this.current.key; - this.current = null; - HashMapDoubleDouble.this.remove(k); - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/logging/DebugLogger.java b/common/src/main/java/com/dfsek/terra/api/util/logging/DebugLogger.java deleted file mode 100644 index 5236401f9..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/logging/DebugLogger.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dfsek.terra.api.util.logging; - -public class DebugLogger { - private final Logger logger; - private boolean debug = false; - - public DebugLogger(Logger logger) { - this.logger = logger; - } - - public boolean isDebug() { - return debug; - } - - public void setDebug(boolean debug) { - this.debug = debug; - } - - public void info(String message) { - if(debug) logger.info(message); - } - - public void warn(String message) { - if(debug) logger.warning(message); - } - - public void error(String message) { - if(debug) logger.severe(message); - } - - public void stack(Exception e) { - if(debug) e.printStackTrace(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/logging/JavaLogger.java b/common/src/main/java/com/dfsek/terra/api/util/logging/JavaLogger.java deleted file mode 100644 index 8a8a62e56..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/logging/JavaLogger.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.dfsek.terra.api.util.logging; - -public class JavaLogger implements Logger { - private final java.util.logging.Logger logger; - - public JavaLogger(java.util.logging.Logger logger) { - this.logger = logger; - } - - @Override - public void info(String message) { - logger.info(message); - } - - @Override - public void warning(String message) { - logger.warning(message); - } - - @Override - public void severe(String message) { - logger.severe(message); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/logging/Logger.java b/common/src/main/java/com/dfsek/terra/api/util/logging/Logger.java deleted file mode 100644 index df812533f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/logging/Logger.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dfsek.terra.api.util.logging; - -public interface Logger { - void info(String message); - - void warning(String message); - - void severe(String message); -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutablePrimitive.java b/common/src/main/java/com/dfsek/terra/api/util/mutable/MutablePrimitive.java deleted file mode 100644 index ab3e17f70..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/mutable/MutablePrimitive.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.util.mutable; - -public interface MutablePrimitive extends Comparable{ - T get(); - - void set(T value); -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/mutable/package-info.java b/common/src/main/java/com/dfsek/terra/api/util/mutable/package-info.java deleted file mode 100644 index 02bf8235e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/mutable/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Mutable objects containing primitive types. - */ -package com.dfsek.terra.api.util.mutable; \ No newline at end of file diff --git a/common/src/main/java/com/dfsek/terra/api/util/seeded/NoiseSeeded.java b/common/src/main/java/com/dfsek/terra/api/util/seeded/NoiseSeeded.java deleted file mode 100644 index 4668c38a4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/seeded/NoiseSeeded.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.api.util.seeded; - -import com.dfsek.terra.api.math.noise.NoiseSampler; - -public interface NoiseSeeded extends SeededBuilder { - @Override - NoiseSampler apply(Long seed); - - int getDimensions(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/seeded/SeededBuilder.java b/common/src/main/java/com/dfsek/terra/api/util/seeded/SeededBuilder.java deleted file mode 100644 index 1a7d15d39..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/seeded/SeededBuilder.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.api.util.seeded; - -import java.util.function.Function; - -@FunctionalInterface -public interface SeededBuilder extends Function { - -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/seeded/SourceSeeded.java b/common/src/main/java/com/dfsek/terra/api/util/seeded/SourceSeeded.java deleted file mode 100644 index 5ec6f4511..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/seeded/SourceSeeded.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.util.seeded; - -import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; - -@FunctionalInterface -public interface SourceSeeded extends SeededBuilder { -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/seeded/StageSeeded.java b/common/src/main/java/com/dfsek/terra/api/util/seeded/StageSeeded.java deleted file mode 100644 index 02ebbe181..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/seeded/StageSeeded.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.util.seeded; - -import com.dfsek.terra.api.world.biome.pipeline.stages.Stage; - -@FunctionalInterface -public interface StageSeeded extends SeededBuilder { -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/world/PaletteUtil.java b/common/src/main/java/com/dfsek/terra/api/util/world/PaletteUtil.java deleted file mode 100644 index 69edf202e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/world/PaletteUtil.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.api.util.world; - -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.api.world.palette.holder.PaletteHolder; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.world.generation.math.samplers.Sampler; - -public final class PaletteUtil { - public static Palette getPalette(int x, int y, int z, BiomeTemplate c, Sampler sampler) { - PaletteHolder slant = c.getSlantPalette(); - if(slant != null && MathUtil.derivative(sampler, x, y, z) > c.getSlantThreshold()) { - return slant.getPalette(y); - } - return c.getPalette().getPalette(y); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/util/world/PopulationUtil.java b/common/src/main/java/com/dfsek/terra/api/util/world/PopulationUtil.java deleted file mode 100644 index a1805d437..000000000 --- a/common/src/main/java/com/dfsek/terra/api/util/world/PopulationUtil.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.api.util.world; - -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.util.FastRandom; - -public final class PopulationUtil { - public static FastRandom getRandom(Chunk c) { - return getRandom(c, 0); - } - - public static FastRandom getRandom(Chunk c, long salt) { - return new FastRandom(MathUtil.getCarverChunkSeed(c.getX(), c.getZ(), c.getWorld().getSeed() + salt)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/Generator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/Generator.java deleted file mode 100644 index 539437a71..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/Generator.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.dfsek.terra.api.world.biome; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.world.palette.Palette; - -public interface Generator { - /** - * Gets the noise sampler instance to use for base terrain. - * - * @return NoiseSampler for terrain - */ - NoiseSampler getBaseSampler(); - - /** - * Gets the noise sampler to use for elevation - * - * @return NoiseSampler for elevation. - */ - NoiseSampler getElevationSampler(); - - /** - * Gets the noise sampler to use for carving. - * - * @return NoiseSampler for carving. - */ - NoiseSampler getCarver(); - - int getBlendDistance(); - - double getWeight(); - - /** - * Gets the BlocPalette to generate the biome with. - * - * @return BlocPalette - The biome's palette. - */ - Palette getPalette(int y); - - NoiseSampler getBiomeNoise(); - - double getElevationWeight(); - - int getBlendStep(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/TerraBiome.java b/common/src/main/java/com/dfsek/terra/api/world/biome/TerraBiome.java deleted file mode 100644 index 4aaac0e9e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/TerraBiome.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dfsek.terra.api.world.biome; - - -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; - -import java.util.Set; - -/** - * Represents a custom biome - */ -public interface TerraBiome { - - /** - * Gets the Vanilla biome to represent the custom biome. - * - * @return TerraBiome - The Vanilla biome. - */ - ProbabilityCollection getVanillaBiomes(); - - /** - * Gets the BiomeTerrain instance used to generate the biome. - * - * @return BiomeTerrain - The terrain generation instance. - */ - Generator getGenerator(World w); - - int getColor(); - - Set getTags(); - - String getID(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomeHolder.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomeHolder.java deleted file mode 100644 index 46edff4c4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomeHolder.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline; - -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.pipeline.expand.BiomeExpander; -import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; - -public interface BiomeHolder { - BiomeHolder expand(BiomeExpander expander); - - void mutate(BiomeMutator mutator); - - void fill(BiomeSource source); - - TerraBiome getBiome(int x, int z); - - TerraBiome getBiomeRaw(int x, int z); -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomePipeline.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomePipeline.java deleted file mode 100644 index ed4211892..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/BiomePipeline.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline; - -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.util.GlueList; -import com.dfsek.terra.api.util.seeded.StageSeeded; -import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; -import com.dfsek.terra.api.world.biome.pipeline.stages.Stage; - -import java.util.List; -import java.util.stream.Collectors; - -public class BiomePipeline { - private final BiomeSource source; - private final List stages; - private final int size; - private final int init; - - private BiomePipeline(BiomeSource source, List stages, int size, int init) { - this.source = source; - this.stages = stages; - this.size = size; - this.init = init; - } - - /** - * Get biomes in a chunk - * - * @param x Chunk X coord - * @param z Chunk Z coord - * @return BiomeHolder containing biomes. - */ - public BiomeHolder getBiomes(int x, int z) { - BiomeHolder holder = new TerraBiomeHolder(init, new Vector2(x * (init - 1), z * (init - 1))); - holder.fill(source); - for(Stage stage : stages) holder = stage.apply(holder); - return holder; - } - - public int getSize() { - return size; - } - - public static final class BiomePipelineBuilder { - private final int init; - List stages = new GlueList<>(); - private int expand; - - public BiomePipelineBuilder(int init) { - this.init = init; - expand = init; - } - - public BiomePipeline build(BiomeSource source, long seed) { - List stagesBuilt = stages.stream().map(stageBuilder -> stageBuilder.apply(seed)).collect(Collectors.toList()); - - for(Stage stage : stagesBuilt) { - if(stage.isExpansion()) expand = expand * 2 - 1; - } - - return new BiomePipeline(source, stagesBuilt, expand, init); - } - - public BiomePipelineBuilder addStage(StageSeeded stage) { - stages.add(stage); - return this; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/TerraBiomeHolder.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/TerraBiomeHolder.java deleted file mode 100644 index df07577c0..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/TerraBiomeHolder.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline; - -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.pipeline.expand.BiomeExpander; -import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; - -public class TerraBiomeHolder implements BiomeHolder { - private final Vector2 origin; - private final int width; - private TerraBiome[][] biomes; - private final int offset; - - public TerraBiomeHolder(int width, Vector2 origin) { - width += 4; - this.width = width; - biomes = new TerraBiome[width][width]; - this.origin = origin; - this.offset = 2; - } - - private TerraBiomeHolder(TerraBiome[][] biomes, Vector2 origin, int width, int offset) { - this.biomes = biomes; - this.origin = origin; - this.width = width; - this.offset = 2 * offset; - } - - @Override - public BiomeHolder expand(BiomeExpander expander) { - TerraBiome[][] old = biomes; - int newWidth = width * 2 - 1; - - biomes = new TerraBiome[newWidth][newWidth]; - - for(int x = 0; x < width; x++) { - for(int z = 0; z < width; z++) { - biomes[x * 2][z * 2] = old[x][z]; - if(z != width - 1) - biomes[x * 2][z * 2 + 1] = expander.getBetween(x + origin.getX(), z + 1 + origin.getZ(), old[x][z], old[x][z + 1]); - if(x != width - 1) - biomes[x * 2 + 1][z * 2] = expander.getBetween(x + 1 + origin.getX(), z + origin.getZ(), old[x][z], old[x + 1][z]); - if(x != width - 1 && z != width - 1) - biomes[x * 2 + 1][z * 2 + 1] = expander.getBetween(x + 1 + origin.getX(), z + 1 + origin.getZ(), old[x][z], old[x + 1][z + 1], old[x][z + 1], old[x + 1][z]); - } - } - return new TerraBiomeHolder(biomes, origin.setX(origin.getX() * 2 - 1).setZ(origin.getZ() * 2 - 1), newWidth, offset); - } - - @Override - public void mutate(BiomeMutator mutator) { - for(int x = 0; x < width; x++) { - for(int z = 0; z < width; z++) { - BiomeMutator.ViewPoint viewPoint = new BiomeMutator.ViewPoint(this, x, z); - biomes[x][z] = mutator.mutate(viewPoint, x + origin.getX(), z + origin.getZ()); - } - } - } - - @Override - public void fill(BiomeSource source) { - for(int x = 0; x < width; x++) { - for(int z = 0; z < width; z++) { - biomes[x][z] = source.getBiome(origin.getX() + x, origin.getZ() + z); - } - } - } - - @Override - public TerraBiome getBiome(int x, int z) { - x += offset; - z += offset; - return getBiomeRaw(x, z); - } - - @Override - public TerraBiome getBiomeRaw(int x, int z) { - if(x >= width || z >= width || x < 0 || z < 0) return null; - return biomes[x][z]; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/BiomeExpander.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/BiomeExpander.java deleted file mode 100644 index 15082a0fe..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/BiomeExpander.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.expand; - -import com.dfsek.terra.api.world.biome.TerraBiome; - -public interface BiomeExpander { - TerraBiome getBetween(double x, double z, TerraBiome... others); -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/FractalExpander.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/FractalExpander.java deleted file mode 100644 index a7d44be84..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/expand/FractalExpander.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.expand; - -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.world.biome.TerraBiome; - -public class FractalExpander implements BiomeExpander { - private final NoiseSampler sampler; - - public FractalExpander(NoiseSampler sampler) { - this.sampler = sampler; - } - - @Override - public TerraBiome getBetween(double x, double z, TerraBiome... others) { - return others[MathUtil.normalizeIndex(sampler.getNoise(x, z), others.length)]; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BiomeMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BiomeMutator.java deleted file mode 100644 index da70c3d9e..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BiomeMutator.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.mutator; - -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.pipeline.BiomeHolder; - -public interface BiomeMutator { - TerraBiome mutate(ViewPoint viewPoint, double x, double z); - - class ViewPoint { - private final BiomeHolder biomes; - private final int offX; - private final int offZ; - - public ViewPoint(BiomeHolder biomes, int offX, int offZ) { - this.biomes = biomes; - this.offX = offX; - this.offZ = offZ; - } - - - public TerraBiome getBiome(int x, int z) { - return biomes.getBiomeRaw(x + offX, z + offZ); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderListMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderListMutator.java deleted file mode 100644 index d16016d91..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderListMutator.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.mutator; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.TerraBiome; - -import java.util.Map; - -public class BorderListMutator implements BiomeMutator { - private final String border; - private final NoiseSampler noiseSampler; - private final ProbabilityCollection replaceDefault; - private final String defaultReplace; - private final Map> replace; - - public BorderListMutator(Map> replace, String border, String defaultReplace, NoiseSampler noiseSampler, ProbabilityCollection replaceDefault) { - this.border = border; - this.noiseSampler = noiseSampler; - this.replaceDefault = replaceDefault; - this.defaultReplace = defaultReplace; - this.replace = replace; - } - - @Override - public TerraBiome mutate(ViewPoint viewPoint, double x, double z) { - TerraBiome origin = viewPoint.getBiome(0, 0); - if(origin.getTags().contains(defaultReplace)) { - for(int xi = -1; xi <= 1; xi++) { - for(int zi = -1; zi <= 1; zi++) { - if(xi == 0 && zi == 0) continue; - TerraBiome current = viewPoint.getBiome(xi, zi); - if(current == null) continue; - if(current.getTags().contains(border)) { - if(replace.containsKey(origin)) { - TerraBiome biome = replace.get(origin).get(noiseSampler, x, z); - return biome == null ? origin : biome; - } - TerraBiome biome = replaceDefault.get(noiseSampler, x, z); - return biome == null ? origin : biome; - } - } - } - } - return origin; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderMutator.java deleted file mode 100644 index d6195c7a4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/BorderMutator.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.mutator; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.TerraBiome; - -public class BorderMutator implements BiomeMutator { - private final String border; - private final NoiseSampler noiseSampler; - private final ProbabilityCollection replace; - private final String replaceTag; - - public BorderMutator(String border, String replaceTag, NoiseSampler noiseSampler, ProbabilityCollection replace) { - this.border = border; - this.noiseSampler = noiseSampler; - this.replace = replace; - this.replaceTag = replaceTag; - } - - @Override - public TerraBiome mutate(ViewPoint viewPoint, double x, double z) { - TerraBiome origin = viewPoint.getBiome(0, 0); - if(origin.getTags().contains(replaceTag)) { - for(int xi = -1; xi <= 1; xi++) { - for(int zi = -1; zi <= 1; zi++) { - if(xi == 0 && zi == 0) continue; - TerraBiome current = viewPoint.getBiome(xi, zi); - if(current == null) continue; - if(current.getTags().contains(border)) { - TerraBiome biome = replace.get(noiseSampler, x, z); - return biome == null ? origin : biome; - } - } - } - } - return origin; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceListMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceListMutator.java deleted file mode 100644 index 8d701109a..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceListMutator.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.mutator; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.TerraBiome; - -import java.util.Map; - -public class ReplaceListMutator implements BiomeMutator { - private final Map> replace; - private final NoiseSampler sampler; - private final ProbabilityCollection replaceDefault; - private final String defaultTag; - - public ReplaceListMutator(Map> replace, String defaultTag, ProbabilityCollection replaceDefault, NoiseSampler sampler) { - this.replace = replace; - this.sampler = sampler; - this.defaultTag = defaultTag; - this.replaceDefault = replaceDefault; - } - - @Override - public TerraBiome mutate(ViewPoint viewPoint, double x, double z) { - TerraBiome center = viewPoint.getBiome(0, 0); - if(replace.containsKey(center)) { - TerraBiome biome = replace.get(center).get(sampler, x, z); - return biome == null ? viewPoint.getBiome(0, 0) : biome; - } - if(viewPoint.getBiome(0, 0).getTags().contains(defaultTag)) { - TerraBiome biome = replaceDefault.get(sampler, x, z); - return biome == null ? viewPoint.getBiome(0, 0) : biome; - } - return center; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceMutator.java deleted file mode 100644 index 7bc705b66..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/ReplaceMutator.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.mutator; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.TerraBiome; - -public class ReplaceMutator implements BiomeMutator { - private final String replaceableTag; - private final ProbabilityCollection replace; - private final NoiseSampler sampler; - - public ReplaceMutator(String replaceable, ProbabilityCollection replace, NoiseSampler sampler) { - this.replaceableTag = replaceable; - this.replace = replace; - this.sampler = sampler; - } - - @Override - public TerraBiome mutate(ViewPoint viewPoint, double x, double z) { - if(viewPoint.getBiome(0, 0).getTags().contains(replaceableTag)) { - TerraBiome biome = replace.get(sampler, x, z); - return biome == null ? viewPoint.getBiome(0, 0) : biome; - } - return viewPoint.getBiome(0, 0); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/SmoothMutator.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/SmoothMutator.java deleted file mode 100644 index a3c679ea1..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/mutator/SmoothMutator.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.mutator; - -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.world.biome.TerraBiome; - -import java.util.Objects; - -public class SmoothMutator implements BiomeMutator { - - private final NoiseSampler sampler; - - public SmoothMutator(NoiseSampler sampler) { - this.sampler = sampler; - } - - @Override - public TerraBiome mutate(ViewPoint viewPoint, double x, double z) { - TerraBiome top = viewPoint.getBiome(1, 0); - TerraBiome bottom = viewPoint.getBiome(-1, 0); - TerraBiome left = viewPoint.getBiome(0, 1); - TerraBiome right = viewPoint.getBiome(0, -1); - - - boolean vert = Objects.equals(top, bottom) && top != null; - boolean horiz = Objects.equals(left, right) && left != null; - - if(vert && horiz) { - return MathUtil.normalizeIndex(sampler.getNoise(x, z), 2) == 0 ? left : top; - } - - if(vert) return top; - if(horiz) return left; - - return viewPoint.getBiome(0, 0); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/BiomeSource.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/BiomeSource.java deleted file mode 100644 index b2e2e37cc..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/BiomeSource.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.source; - -import com.dfsek.terra.api.world.biome.TerraBiome; - -public interface BiomeSource { - TerraBiome getBiome(double x, double z); - - enum Type { - NOISE - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/RandomSource.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/RandomSource.java deleted file mode 100644 index fa95986b4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/source/RandomSource.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.source; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.TerraBiome; - -public class RandomSource implements BiomeSource { - private final ProbabilityCollection biomes; - private final NoiseSampler sampler; - - public RandomSource(ProbabilityCollection biomes, NoiseSampler sampler) { - this.biomes = biomes; - this.sampler = sampler; - } - - @Override - public TerraBiome getBiome(double x, double z) { - return biomes.get(sampler, x, z); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/ExpanderStage.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/ExpanderStage.java deleted file mode 100644 index fc0555e19..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/ExpanderStage.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.stages; - -import com.dfsek.terra.api.world.biome.pipeline.BiomeHolder; -import com.dfsek.terra.api.world.biome.pipeline.expand.BiomeExpander; - -public class ExpanderStage implements Stage { - private final BiomeExpander expander; - - public ExpanderStage(BiomeExpander expander) { - this.expander = expander; - } - - @Override - public boolean isExpansion() { - return true; - } - - @Override - public BiomeHolder apply(BiomeHolder in) { - return in.expand(expander); - } - - public enum Type { - FRACTAL - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/MutatorStage.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/MutatorStage.java deleted file mode 100644 index a9b060fd1..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/MutatorStage.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.stages; - -import com.dfsek.terra.api.world.biome.pipeline.BiomeHolder; -import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; - -public class MutatorStage implements Stage { - private final BiomeMutator mutator; - - public MutatorStage(BiomeMutator mutator) { - this.mutator = mutator; - } - - @Override - public boolean isExpansion() { - return false; - } - - @Override - public BiomeHolder apply(BiomeHolder in) { - in.mutate(mutator); - return in; - } - - public enum Type { - REPLACE, REPLACE_LIST, BORDER, BORDER_LIST, SMOOTH - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/Stage.java b/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/Stage.java deleted file mode 100644 index a179da2eb..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/pipeline/stages/Stage.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.api.world.biome.pipeline.stages; - -import com.dfsek.terra.api.world.biome.pipeline.BiomeHolder; - -public interface Stage { - boolean isExpansion(); - - BiomeHolder apply(BiomeHolder in); - -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/provider/BiomeProvider.java b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/BiomeProvider.java deleted file mode 100644 index c1f664314..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/provider/BiomeProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dfsek.terra.api.world.biome.provider; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.world.biome.TerraBiome; - -public interface BiomeProvider { - TerraBiome getBiome(int x, int z); - - default TerraBiome getBiome(Vector2 vector2) { - return getBiome(vector2.getBlockX(), vector2.getBlockZ()); - } - - default TerraBiome getBiome(Vector3 vector3) { - return getBiome(vector3.getBlockX(), vector3.getBlockZ()); - } - - default TerraBiome getBiome(Location location) { - return getBiome(location.getBlockX(), location.getBlockZ()); - } - - interface BiomeProviderBuilder { - BiomeProvider build(long seed); - } - - enum Type { - IMAGE, PIPELINE, SINGLE - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/provider/ImageBiomeProvider.java b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/ImageBiomeProvider.java deleted file mode 100644 index 5e210abc7..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/provider/ImageBiomeProvider.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.dfsek.terra.api.world.biome.provider; - -import com.dfsek.terra.api.registry.Registry; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.registry.OpenRegistry; -import net.jafama.FastMath; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class ImageBiomeProvider implements BiomeProvider, BiomeProvider.BiomeProviderBuilder { // This provider does not need a seed, so it is its own builder. - private final Map colorBiomeMap = new HashMap<>(); - private final BufferedImage image; - private final int resolution; - private final Align align; - - public ImageBiomeProvider(Set registry, BufferedImage image, int resolution, Align align) { - this.image = image; - this.resolution = resolution; - this.align = align; - registry.forEach(biome -> colorBiomeMap.put(new Color(biome.getColor()), biome)); - } - - private static int distance(Color a, Color b) { - return FastMath.abs(a.getRed() - b.getRed()) + FastMath.abs(a.getGreen() - b.getGreen()) + FastMath.abs(a.getBlue() - b.getBlue()); - } - - @Override - public TerraBiome getBiome(int x, int z) { - x /= resolution; - z /= resolution; - Color color = align.getColor(image, x, z); - return colorBiomeMap.get(colorBiomeMap.keySet().stream().reduce(colorBiomeMap.keySet().stream().findAny().orElseThrow(IllegalStateException::new), (running, element) -> { - int d1 = distance(color, running); - int d2 = distance(color, element); - return d1 < d2 ? running : element; - })); - } - - @Override - public BiomeProvider build(long seed) { - return this; - } - - public enum Align { - CENTER { - @Override - public Color getColor(BufferedImage image, int x, int z) { - return new Color(image.getRGB(FastMath.floorMod(x - image.getWidth() / 2, image.getWidth()), FastMath.floorMod(z - image.getHeight() / 2, image.getHeight()))); - } - }, NONE { - @Override - public Color getColor(BufferedImage image, int x, int z) { - return new Color(image.getRGB(FastMath.floorMod(x, image.getWidth()), FastMath.floorMod(z, image.getHeight()))); - } - }; - - public abstract Color getColor(BufferedImage image, int x, int z); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/provider/SingleBiomeProvider.java b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/SingleBiomeProvider.java deleted file mode 100644 index 6dc103cd6..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/provider/SingleBiomeProvider.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.api.world.biome.provider; - -import com.dfsek.terra.api.world.biome.TerraBiome; - -public class SingleBiomeProvider implements BiomeProvider, BiomeProvider.BiomeProviderBuilder { - private final TerraBiome biome; - - public SingleBiomeProvider(TerraBiome biome) { - this.biome = biome; - } - - @Override - public TerraBiome getBiome(int x, int z) { - return biome; - } - - @Override - public BiomeProvider build(long seed) { - return this; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/biome/provider/StandardBiomeProvider.java b/common/src/main/java/com/dfsek/terra/api/world/biome/provider/StandardBiomeProvider.java deleted file mode 100644 index 397cbe7a4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/biome/provider/StandardBiomeProvider.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.dfsek.terra.api.world.biome.provider; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.pipeline.BiomeHolder; -import com.dfsek.terra.api.world.biome.pipeline.BiomePipeline; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import net.jafama.FastMath; -import org.jetbrains.annotations.NotNull; - -public class StandardBiomeProvider implements BiomeProvider { - private final LoadingCache holderCache; - private final BiomePipeline pipeline; - private final int resolution; - private final NoiseSampler mutator; - private final double noiseAmp; - private final int seed; - - public StandardBiomeProvider(BiomePipeline pipeline, TerraPlugin main, int resolution, NoiseSampler mutator, double noiseAmp, int seed) { - this.resolution = resolution; - this.mutator = mutator; - this.noiseAmp = noiseAmp; - this.seed = seed; - holderCache = CacheBuilder.newBuilder() - .maximumSize(main == null ? 32 : main.getTerraConfig().getProviderCache()) - .build( - new CacheLoader() { - @Override - public BiomeHolder load(@NotNull Vector2 key) { - return pipeline.getBiomes(key.getBlockX(), key.getBlockZ()); - } - } - ); - this.pipeline = pipeline; - } - - @Override - public TerraBiome getBiome(int x, int z) { - x += mutator.getNoiseSeeded(seed, x, z) * noiseAmp; - z += mutator.getNoiseSeeded(1 + seed, x, z) * noiseAmp; - - - x = FastMath.floorToInt(FastMath.floorDiv(x, resolution)); - - z = FastMath.floorToInt(FastMath.floorDiv(z, resolution)); - - int fdX = FastMath.floorDiv(x, pipeline.getSize()); - int fdZ = FastMath.floorDiv(z, pipeline.getSize()); - return holderCache.getUnchecked(new Vector2(fdX, fdZ)).getBiome(x - fdX * pipeline.getSize(), z - fdZ * pipeline.getSize()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/carving/Carver.java b/common/src/main/java/com/dfsek/terra/api/world/carving/Carver.java deleted file mode 100644 index c0b21ae26..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/carving/Carver.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.api.world.carving; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.world.World; -import net.jafama.FastMath; - -import java.util.Random; -import java.util.function.BiConsumer; - -public abstract class Carver { - private final int minY; - private final int maxY; - private final double sixtyFourSq = FastMath.pow(64, 2); - private int carvingRadius = 4; - - public Carver(int minY, int maxY) { - this.minY = minY; - this.maxY = maxY; - } - - public abstract void carve(int chunkX, int chunkZ, World w, BiConsumer consumer); - - public int getCarvingRadius() { - return carvingRadius; - } - - public void setCarvingRadius(int carvingRadius) { - this.carvingRadius = carvingRadius; - } - - public abstract Worm getWorm(long seed, Vector3 l); - - public abstract boolean isChunkCarved(World w, int chunkX, int chunkZ, Random r); - - public enum CarvingType { - CENTER, WALL, TOP, BOTTOM - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java b/common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java deleted file mode 100644 index cfeadc836..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/carving/Worm.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.dfsek.terra.api.world.carving; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.world.World; -import net.jafama.FastMath; - -import java.util.Random; -import java.util.function.BiConsumer; - -public abstract class Worm { - private final Random r; - private final Vector3 origin; - private final Vector3 running; - private final int length; - private int topCut = 0; - private int bottomCut = 0; - private int[] radius = new int[] {0, 0, 0}; - - public Worm(int length, Random r, Vector3 origin) { - this.r = r; - this.length = length; - this.origin = origin; - this.running = origin; - } - - public void setBottomCut(int bottomCut) { - this.bottomCut = bottomCut; - } - - public void setTopCut(int topCut) { - this.topCut = topCut; - } - - public Vector3 getOrigin() { - return origin; - } - - public int getLength() { - return length; - } - - public Vector3 getRunning() { - return running; - } - - public WormPoint getPoint() { - return new WormPoint(running, radius, topCut, bottomCut); - } - - public int[] getRadius() { - return radius; - } - - public void setRadius(int[] radius) { - this.radius = radius; - } - - public Random getRandom() { - return r; - } - - public abstract void step(); - - public static class WormPoint { - private final Vector3 origin; - private final int topCut; - private final int bottomCut; - private final int[] rad; - - public WormPoint(Vector3 origin, int[] rad, int topCut, int bottomCut) { - this.origin = origin; - this.rad = rad; - this.topCut = topCut; - this.bottomCut = bottomCut; - } - - private static double ellipseEquation(int x, int y, int z, double xr, double yr, double zr) { - return (FastMath.pow2(x) / FastMath.pow2(xr + 0.5D)) + (FastMath.pow2(y) / FastMath.pow2(yr + 0.5D)) + (FastMath.pow2(z) / FastMath.pow2(zr + 0.5D)); - } - - public Vector3 getOrigin() { - return origin; - } - - public int getRadius(int index) { - return rad[index]; - } - - public void carve(int chunkX, int chunkZ, BiConsumer consumer, World world) { - int xRad = getRadius(0); - int yRad = getRadius(1); - int zRad = getRadius(2); - int originX = (chunkX << 4); - int originZ = (chunkZ << 4); - for(int x = -xRad - 1; x <= xRad + 1; x++) { - if(!(FastMath.floorDiv(origin.getBlockX() + x, 16) == chunkX)) continue; - for(int z = -zRad - 1; z <= zRad + 1; z++) { - if(!(FastMath.floorDiv(origin.getBlockZ() + z, 16) == chunkZ)) continue; - for(int y = -yRad - 1; y <= yRad + 1; y++) { - Vector3 position = origin.clone().add(new Vector3(x, y, z)); - if(position.getY() < world.getMinHeight() || position.getY() > world.getMaxHeight()) continue; - double eq = ellipseEquation(x, y, z, xRad, yRad, zRad); - if(eq <= 1 && - y >= -yRad - 1 + bottomCut && y <= yRad + 1 - topCut) { - consumer.accept(new Vector3(position.getBlockX() - originX, position.getBlockY(), position.getBlockZ() - originZ), Carver.CarvingType.CENTER); - } else if(eq <= 1.5) { - Carver.CarvingType type = Carver.CarvingType.WALL; - if(y <= -yRad - 1 + bottomCut) { - type = Carver.CarvingType.BOTTOM; - } else if(y >= yRad + 1 - topCut) { - type = Carver.CarvingType.TOP; - } - consumer.accept(new Vector3(position.getBlockX() - originX, position.getBlockY(), position.getBlockZ() - originZ), type); - } - } - } - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/flora/Flora.java b/common/src/main/java/com/dfsek/terra/api/world/flora/Flora.java deleted file mode 100644 index 82d57f9b0..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/flora/Flora.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.world.flora; - -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.world.Chunk; - -import java.util.List; - -public interface Flora { - List getValidSpawnsAt(Chunk chunk, int x, int z, Range check); - - boolean plant(Location l); -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/Chunkified.java b/common/src/main/java/com/dfsek/terra/api/world/generation/Chunkified.java deleted file mode 100644 index 3b9925d46..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/generation/Chunkified.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.api.world.generation; - -/** - * Marker interface that marks a feature as "chunkified" (only modifying one chunk at a time) - */ -public interface Chunkified { -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraBlockPopulator.java b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraBlockPopulator.java deleted file mode 100644 index 1d0e47577..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraBlockPopulator.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.api.world.generation; - -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; - -public interface TerraBlockPopulator { - void populate(World world, Chunk chunk); -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java b/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java deleted file mode 100644 index 345e32c61..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/generation/TerraChunkGenerator.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.dfsek.terra.api.world.generation; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.world.BiomeGrid; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkData; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.world.generation.math.samplers.Sampler; -import org.jetbrains.annotations.NotNull; - -import java.util.List; -import java.util.Random; - -public interface TerraChunkGenerator { - ChunkData generateChunkData(@NotNull World world, Random random, int x, int z, ChunkData original); - - void generateBiomes(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome); - - boolean isParallelCapable(); - - boolean shouldGenerateCaves(); - - boolean shouldGenerateDecorations(); - - boolean shouldGenerateMobs(); - - boolean shouldGenerateStructures(); - - ConfigPack getConfigPack(); - - TerraPlugin getMain(); - - Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth); - - List getPopulators(); -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncBiomeFinder.java b/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncBiomeFinder.java deleted file mode 100644 index c41892b12..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncBiomeFinder.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.api.world.locate; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import org.jetbrains.annotations.NotNull; - -import java.util.function.Consumer; - -/** - * Runnable that locates a biome asynchronously - */ -public class AsyncBiomeFinder extends AsyncFeatureFinder { - - public AsyncBiomeFinder(BiomeProvider provider, TerraBiome target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback, TerraPlugin main) { - super(provider, target, origin, startRadius, maxRadius, callback, main); - } - - /** - * Helper method to get biome at location - * - * @param x X coordinate - * @param z Z coordinate - * @return TerraBiome at coordinates - */ - @Override - public boolean isValid(int x, int z, TerraBiome target) { - int res = main.getTerraConfig().getBiomeSearchResolution(); - return getProvider().getBiome(x * res, z * res).equals(target); - } - - @Override - public Vector3 finalizeVector(Vector3 orig) { - return orig.multiply(main.getTerraConfig().getBiomeSearchResolution()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncFeatureFinder.java b/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncFeatureFinder.java deleted file mode 100644 index 31b2dec6b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncFeatureFinder.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.dfsek.terra.api.world.locate; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import org.jetbrains.annotations.NotNull; - -import java.util.function.Consumer; - -public abstract class AsyncFeatureFinder implements Runnable { - protected final BiomeProvider provider; - protected final T target; - protected final int startRadius; - protected final int maxRadius; - protected final int centerX; - protected final int centerZ; - protected final World world; - private final Consumer callback; - protected int searchSize = 1; - protected final TerraPlugin main; - - public AsyncFeatureFinder(BiomeProvider provider, T target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback, TerraPlugin main) { - this.provider = provider; - this.target = target; - this.main = main; - this.startRadius = startRadius; - this.maxRadius = maxRadius; - this.centerX = origin.getBlockX(); - this.centerZ = origin.getBlockZ(); - this.world = origin.getWorld(); - this.callback = callback; - } - - @Override - public void run() { - int x = centerX; - int z = centerZ; - - x /= searchSize; - z /= searchSize; - - int run = 1; - boolean toggle = true; - boolean found = false; - - main: - for(int i = startRadius; i < maxRadius; i++) { - for(int j = 0; j < run; j++) { - if(isValid(x, z, target)) { - found = true; - break main; - } - if(toggle) x += 1; - else x -= 1; - } - for(int j = 0; j < run; j++) { - if(isValid(x, z, target)) { - found = true; - break main; - } - if(toggle) z += 1; - else z -= 1; - } - run++; - toggle = !toggle; - } - Vector3 finalSpawn = found ? finalizeVector(new Vector3(x, 0, z)) : null; - callback.accept(finalSpawn); - } - - - public abstract Vector3 finalizeVector(Vector3 orig); - - public abstract boolean isValid(int x, int z, T target); - - public T getTarget() { - return target; - } - - public World getWorld() { - return world; - } - - public BiomeProvider getProvider() { - return provider; - } - - public int getSearchSize() { - return searchSize; - } - - public void setSearchSize(int searchSize) { - this.searchSize = searchSize; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncStructureFinder.java b/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncStructureFinder.java deleted file mode 100644 index 2686fb2db..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/locate/AsyncStructureFinder.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.api.world.locate; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.structures.structure.Rotation; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.world.population.items.TerraStructure; -import net.jafama.FastMath; -import org.jetbrains.annotations.NotNull; - -import java.util.Random; -import java.util.function.Consumer; - -public class AsyncStructureFinder extends AsyncFeatureFinder { - public AsyncStructureFinder(BiomeProvider provider, TerraStructure target, @NotNull Location origin, int startRadius, int maxRadius, Consumer callback, TerraPlugin main) { - super(provider, target, origin, startRadius, maxRadius, callback, main); - setSearchSize(target.getSpawn().getWidth() + 2 * target.getSpawn().getSeparation()); - } - - @Override - public Vector3 finalizeVector(Vector3 orig) { - return target.getSpawn().getChunkSpawn(orig.getBlockX(), orig.getBlockZ(), world.getSeed()); - } - - @Override - public boolean isValid(int x, int z, TerraStructure target) { - Location spawn = target.getSpawn().getChunkSpawn(x, z, world.getSeed()).toLocation(world); - if(!((UserDefinedBiome) provider.getBiome(spawn)).getConfig().getStructures().contains(target)) return false; - Random random = new FastRandom(MathUtil.getCarverChunkSeed(FastMath.floorDiv(spawn.getBlockX(), 16), FastMath.floorDiv(spawn.getBlockZ(), 16), world.getSeed())); - return target.getStructure().get(random).test(spawn.setY(target.getSpawnStart().get(random)), random, Rotation.fromDegrees(90 * random.nextInt(4))); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/NoisePalette.java b/common/src/main/java/com/dfsek/terra/api/world/palette/NoisePalette.java deleted file mode 100644 index 3af3d383b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/palette/NoisePalette.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dfsek.terra.api.world.palette; - -import com.dfsek.terra.api.math.noise.NoiseSampler; - -import java.util.List; - -public class NoisePalette extends Palette { - private final NoiseSampler sampler; - private final boolean is2D; - - public NoisePalette(NoiseSampler sampler, boolean is2D) { - this.sampler = sampler; - this.is2D = is2D; - } - - @Override - public E get(int layer, double x, double y, double z) { - PaletteLayer paletteLayer; - if(layer > this.getSize()) paletteLayer = this.getLayers().get(this.getLayers().size() - 1); - else { - List> pl = getLayers(); - if(layer >= pl.size()) paletteLayer = pl.get(pl.size() - 1); - else paletteLayer = pl.get(layer); - } - NoiseSampler paletteSampler = paletteLayer.getSampler(); - return paletteLayer.get(paletteSampler == null ? sampler : paletteSampler, x, y, z, is2D); - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/Palette.java b/common/src/main/java/com/dfsek/terra/api/world/palette/Palette.java deleted file mode 100644 index 881cd406c..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/palette/Palette.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.dfsek.terra.api.world.palette; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.GlueList; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; - -import java.util.List; -import java.util.Random; - -/** - * A class representation of a "slice" of the world. - * Used to get a section of blocks, based on the depth at which they are found. - */ -public abstract class Palette { - private final List> pallet = new GlueList<>(); - - /** - * Constructs a blank palette. - */ - public Palette() { - - } - - public com.dfsek.terra.api.world.palette.Palette add(E m, int layers, NoiseSampler sampler) { - for(int i = 0; i < layers; i++) { - pallet.add(new PaletteLayer<>(m, sampler)); - } - return this; - } - - public com.dfsek.terra.api.world.palette.Palette add(ProbabilityCollection m, int layers, NoiseSampler sampler) { - for(int i = 0; i < layers; i++) { - pallet.add(new PaletteLayer<>(m, sampler)); - } - return this; - } - - /** - * Fetches a material from the palette, at a given layer. - * - * @param layer - The layer at which to fetch the material. - * @return BlockData - The material fetched. - */ - public abstract E get(int layer, double x, double y, double z); - - - public int getSize() { - return pallet.size(); - } - - public List> getLayers() { - return pallet; - } - - /** - * Class representation of a layer of a BlockPalette. - */ - public static class PaletteLayer { - private final boolean col; // Is layer using a collection? - private ProbabilityCollection collection; - private final NoiseSampler sampler; - private E m; - - /** - * Constructs a PaletteLayerHolder with a ProbabilityCollection of materials and a number of layers. - * - * @param type The collection of materials to choose from. - * @param sampler Noise sampler to use - */ - public PaletteLayer(ProbabilityCollection type, NoiseSampler sampler) { - this.sampler = sampler; - this.col = true; - this.collection = type; - } - - /** - * Constructs a PaletteLayerHolder with a single Material and a number of layers. - * - * @param type The material to use. - * @param sampler Noise sampler to use - */ - public PaletteLayer(E type, NoiseSampler sampler) { - this.sampler = sampler; - this.col = false; - this.m = type; - } - - public NoiseSampler getSampler() { - return sampler; - } - - /** - * Gets a material from the layer. - * - * @return Material - the material.. - */ - public E get(Random random) { - if(col) return this.collection.get(random); - return m; - } - - public E get(NoiseSampler random, double x, double y, double z, boolean is2D) { - if(col && is2D) return this.collection.get(random, x, z); - else if(col) return this.collection.get(random, x, y, z); - return m; - } - - public ProbabilityCollection getCollection() { - return collection; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/SinglePalette.java b/common/src/main/java/com/dfsek/terra/api/world/palette/SinglePalette.java deleted file mode 100644 index 06b075a2b..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/palette/SinglePalette.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.api.world.palette; - -public class SinglePalette extends Palette { - private final E item; - - public SinglePalette(E item) { - this.item = item; - } - - @Override - public E get(int layer, double x, double y, double z) { - return item; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolder.java b/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolder.java deleted file mode 100644 index ad357e56f..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteHolder.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dfsek.terra.api.world.palette.holder; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.world.palette.Palette; - -public class PaletteHolder { - private final Palette[] palettes; - private final int offset; - - protected PaletteHolder(Palette[] palettes, int offset) { - this.palettes = palettes; - this.offset = offset; - } - - public Palette getPalette(int y) { - int index = y + offset; - return index >= 0 - ? index < palettes.length - ? palettes[index] - : palettes[palettes.length - 1] - : palettes[0]; - } -} diff --git a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteLayerHolder.java b/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteLayerHolder.java deleted file mode 100644 index cb44e8fb4..000000000 --- a/common/src/main/java/com/dfsek/terra/api/world/palette/holder/PaletteLayerHolder.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.api.world.palette.holder; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import org.jetbrains.annotations.NotNull; - -public class PaletteLayerHolder { - private final ProbabilityCollection layer; - private final NoiseSampler sampler; - private final int size; - - public PaletteLayerHolder(@NotNull ProbabilityCollection layer, NoiseSampler sampler, int size) { - this.layer = layer; - this.sampler = sampler; - this.size = size; - } - - @NotNull - public ProbabilityCollection getLayer() { - return layer; - } - - public int getSize() { - return size; - } - - public NoiseSampler getSampler() { - return sampler; - } -} diff --git a/common/src/main/java/com/dfsek/terra/carving/CarverCache.java b/common/src/main/java/com/dfsek/terra/carving/CarverCache.java deleted file mode 100644 index 096635943..000000000 --- a/common/src/main/java/com/dfsek/terra/carving/CarverCache.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.dfsek.terra.carving; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.util.GlueList; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.carving.Worm; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; -import java.util.Random; - -public class CarverCache { - - private final LoadingCache> cache; - private final UserDefinedCarver carver; - - public CarverCache(World w, TerraPlugin main, UserDefinedCarver carver) { - this.carver = carver; - cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getCarverCacheSize()) - .build(new CacheLoader>() { - @Override - public List load(@NotNull Long key) { - int chunkX = (int) (key >> 32); - int chunkZ = (int) key.longValue(); - BiomeProvider provider = main.getWorld(w).getBiomeProvider(); - if(CarverCache.this.carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + CarverCache.this.carver.hashCode())))) { - long seed = MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed()); - Random r = new FastRandom(seed); - Worm carving = CarverCache.this.carver.getWorm(seed, new Vector3((chunkX << 4) + r.nextInt(16), CarverCache.this.carver.getConfig().getHeight().get(r), (chunkZ << 4) + r.nextInt(16))); - List points = new GlueList<>(); - for(int i = 0; i < carving.getLength(); i++) { - carving.step(); - TerraBiome biome = provider.getBiome(carving.getRunning().toLocation(w)); - if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(CarverCache.this.carver)) { // Stop if we enter a biome this carver is not present in - return Collections.emptyList(); - } - points.add(carving.getPoint()); - } - return points; - } - return Collections.emptyList(); - } - }); - } - - public List getPoints(int chunkX, int chunkZ) { - return cache.getUnchecked(MathUtil.squash(chunkX, chunkZ)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java b/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java deleted file mode 100644 index 73e302e70..000000000 --- a/common/src/main/java/com/dfsek/terra/carving/CarverPalette.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.dfsek.terra.carving; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import net.jafama.FastMath; - -import java.util.Map; -import java.util.TreeMap; - -@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"}) -public class CarverPalette { - private final boolean blacklist; - private final MaterialSet replace; - private final TreeMap> map = new TreeMap<>(); - private ProbabilityCollection[] layers; - private int offset = 0; - - public CarverPalette(MaterialSet replaceable, boolean blacklist) { - this.blacklist = blacklist; - this.replace = replaceable; - } - - public CarverPalette add(ProbabilityCollection collection, int y) { - map.put(y, collection); - return this; - } - - public ProbabilityCollection get(int y) { - int index = y + offset; - return index >= 0 - ? index < layers.length - ? layers[index] - : layers[layers.length - 1] - : layers[0]; - } - - public boolean canReplace(BlockType material) { - return blacklist != replace.contains(material); - } - - /** - * Build the palette to an array. - */ - public void build() { - int min = FastMath.min(map.keySet().stream().min(Integer::compareTo).orElse(0), 0); - int max = FastMath.max(map.keySet().stream().max(Integer::compareTo).orElse(255), 255); - - layers = new ProbabilityCollection[map.lastKey() + 1 - min]; - for(int y = min; y <= FastMath.max(map.lastKey(), max); y++) { - ProbabilityCollection d = null; - for(Map.Entry> e : map.entrySet()) { - if(e.getKey() >= y) { - d = e.getValue(); - break; - } - } - if(d == null) throw new IllegalArgumentException("No palette for Y=" + y); - layers[y - min] = d; - } - offset = -min; - } -} diff --git a/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java b/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java deleted file mode 100644 index 3da18626a..000000000 --- a/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java +++ /dev/null @@ -1,187 +0,0 @@ -package com.dfsek.terra.carving; - -import com.dfsek.paralithic.Expression; -import com.dfsek.paralithic.eval.parser.Parser; -import com.dfsek.paralithic.eval.parser.Scope; -import com.dfsek.paralithic.eval.tokenizer.ParseException; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction; -import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction2; -import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction3; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.carving.Carver; -import com.dfsek.terra.api.world.carving.Worm; -import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.config.templates.CarverTemplate; -import net.jafama.FastMath; - -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.BiConsumer; - -public class UserDefinedCarver extends Carver { - private final double[] start; // 0, 1, 2 = x, y, z. - private final double[] mutate; // 0, 1, 2 = x, y, z. 3 = radius. - private final Range length; - private final long hash; - private final int topCut; - private final int bottomCut; - private final CarverTemplate config; - private final Expression xRad; - private final Expression yRad; - private final Expression zRad; - - private final Map cacheMap = new ConcurrentHashMap<>(); - private final TerraPlugin main; - private double step = 2; - private Range recalc = new Range(8, 10); - private double recalcMagnitude = 3; - - public UserDefinedCarver(Range height, Range length, double[] start, double[] mutate, List radii, Scope parent, long hash, int topCut, int bottomCut, CarverTemplate config, TerraPlugin main, Map functions, Map definedFunctions) throws ParseException { - super(height.getMin(), height.getMax()); - this.length = length; - this.start = start; - this.mutate = mutate; - this.hash = hash; - this.topCut = topCut; - this.bottomCut = bottomCut; - this.config = config; - this.main = main; - - Parser p = new Parser(); - - functions.forEach((id, noise) -> { - switch(noise.getDimensions()) { - case 2: - p.registerFunction(id, new NoiseFunction2(noise.apply(hash))); - break; - case 3: - p.registerFunction(id, new NoiseFunction3(noise.apply(hash))); - break; - } - }); - - for(Map.Entry entry : definedFunctions.entrySet()) { - p.registerFunction(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), p, parent)); - } - - Scope s = new Scope().withParent(parent); - - - s.addInvocationVariable("x"); - s.addInvocationVariable("y"); - s.addInvocationVariable("z"); - - s.addInvocationVariable("length"); - s.addInvocationVariable("position"); - s.addInvocationVariable("seed"); - - - xRad = p.parse(radii.get(0), s); - yRad = p.parse(radii.get(1), s); - zRad = p.parse(radii.get(2), s); - - } - - @Override - public Worm getWorm(long l, Vector3 vector) { - Random r = new FastRandom(l + hash); - return new UserDefinedWorm(length.get(r) / 2, r, vector, topCut, bottomCut, l); - } - - public void setStep(double step) { - this.step = step; - } - - public void setRecalc(Range recalc) { - this.recalc = recalc; - } - - @Override - public void carve(int chunkX, int chunkZ, World w, BiConsumer consumer) { - synchronized(cacheMap) { - CarverCache cache = cacheMap.computeIfAbsent(w.getSeed(), world -> new CarverCache(w, main, this)); - int carvingRadius = getCarvingRadius(); - for(int x = chunkX - carvingRadius; x <= chunkX + carvingRadius; x++) { - for(int z = chunkZ - carvingRadius; z <= chunkZ + carvingRadius; z++) { - cache.getPoints(x, z).forEach(point -> { - Vector3 origin = point.getOrigin(); - if(FastMath.floorDiv(origin.getBlockX(), 16) != chunkX && FastMath.floorDiv(origin.getBlockZ(), 16) != chunkZ) // We only want to carve this chunk. - return; - point.carve(chunkX, chunkZ, consumer, w); - }); - } - } - } - } - - public void setRecalcMagnitude(double recalcMagnitude) { - this.recalcMagnitude = recalcMagnitude; - } - - @Override - public boolean isChunkCarved(World w, int chunkX, int chunkZ, Random random) { - BiomeTemplate conf = ((UserDefinedBiome) main.getWorld(w).getBiomeProvider().getBiome((chunkX << 4) + 8, (chunkZ << 4) + 8)).getConfig(); - if(conf.getCarvers().get(this) != null) { - return new FastRandom(random.nextLong() + hash).nextInt(100) < conf.getCarvers().get(this); - } - return false; - } - - public CarverTemplate getConfig() { - return config; - } - - private class UserDefinedWorm extends Worm { - private final Vector3 direction; - private final Vector3 origin; - private int steps; - private int nextDirection = 0; - private double[] currentRotation = new double[3]; - private final long seed; - - public UserDefinedWorm(int length, Random r, Vector3 origin, int topCut, int bottomCut, long seed) { - super(length, r, origin); - this.origin = origin; - this.seed = seed; - super.setTopCut(topCut); - super.setBottomCut(bottomCut); - direction = new Vector3((r.nextDouble() - 0.5D) * start[0], (r.nextDouble() - 0.5D) * start[1], (r.nextDouble() - 0.5D) * start[2]).normalize().multiply(step); - double[] args = {origin.getX(), origin.getY(), origin.getZ(), length, 0, seed}; - setRadius(new int[] {(int) (xRad.evaluate(args)), (int) (yRad.evaluate(args)), (int) (zRad.evaluate(args))}); - } - - @Override - public WormPoint getPoint() { - return new WormPoint(getRunning().clone(), getRadius(), config.getCutTop(), config.getCutBottom()); - } - - @Override - public void step() { - if(steps == nextDirection) { - direction.rotateAroundX(FastMath.toRadians((getRandom().nextGaussian()) * mutate[0] * recalcMagnitude)); - direction.rotateAroundY(FastMath.toRadians((getRandom().nextGaussian()) * mutate[1] * recalcMagnitude)); - direction.rotateAroundZ(FastMath.toRadians((getRandom().nextGaussian()) * mutate[2] * recalcMagnitude)); - currentRotation = new double[] {(getRandom().nextGaussian()) * mutate[0], - (getRandom().nextGaussian()) * mutate[1], - (getRandom().nextGaussian()) * mutate[2]}; - nextDirection += recalc.get(getRandom()); - } - steps++; - double[] args = {origin.getX(), origin.getY(), origin.getZ(), getLength(), steps, seed}; - setRadius(new int[] {(int) (xRad.evaluate(args)), (int) (yRad.evaluate(args)), (int) (zRad.evaluate(args))}); - direction.rotateAroundX(FastMath.toRadians(currentRotation[0] * mutate[0])); - direction.rotateAroundY(FastMath.toRadians(currentRotation[1] * mutate[1])); - direction.rotateAroundZ(FastMath.toRadians(currentRotation[2] * mutate[2])); - getRunning().add(direction); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/AddonsCommand.java b/common/src/main/java/com/dfsek/terra/commands/AddonsCommand.java deleted file mode 100644 index d775de66b..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/AddonsCommand.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.commands; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; - -@Command( - usage = "/terra addons" -) -public class AddonsCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - sender.sendMessage("Installed Addons:"); - main.getAddons().forEach(addon -> sender.sendMessage(" - " + addon.getName() + " v" + addon.getVersion() + " by " + addon.getAuthor())); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/CommandUtil.java b/common/src/main/java/com/dfsek/terra/commands/CommandUtil.java deleted file mode 100644 index a9e327d08..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/CommandUtil.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.commands; - -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.exception.MalformedCommandException; -import com.dfsek.terra.commands.biome.BiomeCommand; -import com.dfsek.terra.commands.geometry.GeometryCommand; -import com.dfsek.terra.commands.profiler.ProfileCommand; -import com.dfsek.terra.commands.structure.StructureCommand; - -public final class CommandUtil { - public static void registerAll(CommandManager manager) throws MalformedCommandException { - manager.register("structure", StructureCommand.class); - manager.register("profile", ProfileCommand.class); - manager.register("reload", ReloadCommand.class); - manager.register("addons", AddonsCommand.class); - manager.register("version", VersionCommand.class); - manager.register("getblock", GetBlockCommand.class); - manager.register("packs", PacksCommand.class); - manager.register("biome", BiomeCommand.class); - manager.register("geometry", GeometryCommand.class); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/GetBlockCommand.java b/common/src/main/java/com/dfsek/terra/commands/GetBlockCommand.java deleted file mode 100644 index a57dd75f2..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/GetBlockCommand.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dfsek.terra.commands; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; - -@WorldCommand -@DebugCommand -@PlayerCommand -@Command( - usage = "/terra getblock" -) -public class GetBlockCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - Player player = (Player) sender; - sender.sendMessage("Block: " + main.getWorld(player.getWorld()).getUngeneratedBlock(player.getLocation()).getAsString()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/PacksCommand.java b/common/src/main/java/com/dfsek/terra/commands/PacksCommand.java deleted file mode 100644 index 875ca8ea1..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/PacksCommand.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.commands; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.registry.CheckedRegistry; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.pack.ConfigPackTemplate; - -@Command( - usage = "/terra packs" -) -public class PacksCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - CheckedRegistry registry = main.getConfigRegistry(); - - if(registry.entries().size() == 0) { - LangUtil.send("command.packs.none", sender); - return; - } - - LangUtil.send("command.packs.main", sender); - registry.entries().forEach(entry -> { - ConfigPackTemplate template = entry.getTemplate(); - LangUtil.send("command.packs.pack", sender, template.getID(), template.getAuthor(), template.getVersion()); - }); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/ReloadCommand.java b/common/src/main/java/com/dfsek/terra/commands/ReloadCommand.java deleted file mode 100644 index e78909c04..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/ReloadCommand.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.commands; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.config.lang.LangUtil; - -@Command( - usage = "/terra reload" -) -public class ReloadCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - if(!main.reload()) { - LangUtil.send("command.reload-error", sender); - } else { - LangUtil.send("command.reload", sender); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/VersionCommand.java b/common/src/main/java/com/dfsek/terra/commands/VersionCommand.java deleted file mode 100644 index 7e8521b1c..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/VersionCommand.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.commands; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.config.lang.LangUtil; - -@Command( - usage = "/terra version" -) -public class VersionCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - String terraVersion = main.getVersion(); - LangUtil.send("command.version", sender, terraVersion, main.platformName()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeCommand.java b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeCommand.java deleted file mode 100644 index 8871f736c..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeCommand.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.dfsek.terra.commands.biome; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Subcommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.config.lang.LangUtil; - -@Command( - subcommands = { - @Subcommand( - value = "info", - aliases = {"i"}, - clazz = BiomeInfoCommand.class - ), - @Subcommand( - value = "locate", - aliases = {"l"}, - clazz = BiomeLocateCommand.class - ) - }, - usage = "/terra biome" -) -@WorldCommand -@PlayerCommand -public class BiomeCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - Player player = (Player) sender; - - BiomeProvider provider = main.getWorld(player.getWorld()).getBiomeProvider(); - UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(player.getLocation()); - LangUtil.send("command.biome.in", sender, biome.getID()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeInfoCommand.java b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeInfoCommand.java deleted file mode 100644 index b1d0ffe1b..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeInfoCommand.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.dfsek.terra.commands.biome; - -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.commands.biome.arg.BiomeArgumentParser; -import com.dfsek.terra.commands.biome.tab.BiomeTabCompleter; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.world.population.items.TerraStructure; - -import java.util.List; - -@Command( - arguments = { - @Argument( - value = "biome", - tabCompleter = BiomeTabCompleter.class, - argumentParser = BiomeArgumentParser.class - ) - } -) -public class BiomeInfoCommand implements CommandTemplate { - @ArgumentTarget("biome") - private TerraBiome biome; - - @Override - public void execute(CommandSender sender) { - sender.sendMessage("Biome info for \"" + biome.getID() + "\"."); - sender.sendMessage("Vanilla biome: " + biome.getVanillaBiomes()); - - if(biome instanceof UserDefinedBiome) { - BiomeTemplate bio = ((UserDefinedBiome) biome).getConfig(); - - if(bio.getExtended().size() == 0) { - sender.sendMessage("No Parent Biomes"); - } else { - sender.sendMessage("------Parent Biomes-----"); - bio.getExtended().forEach(id -> sender.sendMessage(" - " + id)); - } - - List structureConfigs = bio.getStructures(); - - if(structureConfigs.size() == 0) { - sender.sendMessage("No Structures"); - } else { - sender.sendMessage("-------Structures-------"); - for(TerraStructure c : structureConfigs) { - sender.sendMessage(" - " + c.getTemplate().getID()); - } - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeLocateCommand.java b/common/src/main/java/com/dfsek/terra/commands/biome/BiomeLocateCommand.java deleted file mode 100644 index b6ef00483..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/biome/BiomeLocateCommand.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.dfsek.terra.commands.biome; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Switch; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.command.arg.IntegerArgumentParser; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.locate.AsyncBiomeFinder; -import com.dfsek.terra.commands.biome.arg.BiomeArgumentParser; -import com.dfsek.terra.commands.biome.tab.BiomeTabCompleter; -import com.dfsek.terra.config.lang.LangUtil; - -import java.util.Locale; - -@PlayerCommand -@WorldCommand -@Command( - arguments = { - @Argument( - value = "biome", - tabCompleter = BiomeTabCompleter.class, - argumentParser = BiomeArgumentParser.class - ), - @Argument( - value = "radius", - required = false, - defaultValue = "1000", - argumentParser = IntegerArgumentParser.class - ) - }, - switches = { - @Switch( - value = "teleport", - aliases = {"t", "tp"} - ) - } -) -public class BiomeLocateCommand implements CommandTemplate { - - @ArgumentTarget("radius") - private Integer radius; - - @ArgumentTarget("biome") - private TerraBiome biome; - - @SwitchTarget("teleport") - private boolean teleport; - - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - - Player player = (Player) sender; - - new Thread(new AsyncBiomeFinder(main.getWorld(player.getWorld()).getBiomeProvider(), biome, player.getLocation().clone().multiply((1D / main.getTerraConfig().getBiomeSearchResolution())), 0, radius, location -> { - if(location != null) { - sender.sendMessage(String.format("The nearest %s is at [%d, ~, %d] (%.1f blocks away)", biome.getID().toLowerCase(Locale.ROOT), location.getBlockX(), location.getBlockZ(), location.add(new Vector3(0, player.getLocation().getY(), 0)).distance(player.getLocation().toVector()))); - if(teleport) { - main.runPossiblyUnsafeTask(() -> player.setLocation(new Location(player.getWorld(), location.getX(), player.getLocation().getY(), location.getZ()))); - } - } else LangUtil.send("command.biome.unable-to-locate", sender); - }, main), "Biome Location Thread").start(); - - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/arg/BiomeArgumentParser.java b/common/src/main/java/com/dfsek/terra/commands/biome/arg/BiomeArgumentParser.java deleted file mode 100644 index 251036d39..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/biome/arg/BiomeArgumentParser.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.commands.biome.arg; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.arg.ArgumentParser; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.world.biome.TerraBiome; - -public class BiomeArgumentParser implements ArgumentParser { - @Inject - private TerraPlugin main; - - @Override - public TerraBiome parse(CommandSender sender, String arg) { - Player player = (Player) sender; - return main.getWorld(player.getWorld()).getConfig().getBiomeRegistry().get(arg); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/biome/tab/BiomeTabCompleter.java b/common/src/main/java/com/dfsek/terra/commands/biome/tab/BiomeTabCompleter.java deleted file mode 100644 index f2461c532..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/biome/tab/BiomeTabCompleter.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.commands.biome.tab; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.tab.TabCompleter; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.world.biome.TerraBiome; - -import java.util.List; -import java.util.stream.Collectors; - -public class BiomeTabCompleter implements TabCompleter { - @Inject - private TerraPlugin main; - - @Override - public List complete(CommandSender sender) { - Player player = (Player) sender; - return main.getWorld(player.getWorld()).getConfig().getBiomeRegistry().entries().stream().map(TerraBiome::getID).collect(Collectors.toList()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/geometry/DeformedSphereCommand.java b/common/src/main/java/com/dfsek/terra/commands/geometry/DeformedSphereCommand.java deleted file mode 100644 index 46ce84559..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/geometry/DeformedSphereCommand.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.dfsek.terra.commands.geometry; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.arg.DoubleArgumentParser; -import com.dfsek.terra.api.command.arg.IntegerArgumentParser; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.math.voxel.DeformedSphere; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; - -import java.util.concurrent.ThreadLocalRandom; - -@DebugCommand -@PlayerCommand -@Command( - arguments = { - @Argument( - value = "radius", - argumentParser = IntegerArgumentParser.class - ), - @Argument( - value = "deform", - argumentParser = DoubleArgumentParser.class - ), - @Argument( - value = "frequency", - argumentParser = DoubleArgumentParser.class - ) - }, - usage = "/terra geometry deformedsphere " -) -public class DeformedSphereCommand implements CommandTemplate { - @ArgumentTarget("radius") - private Integer radius; - - @ArgumentTarget("deform") - private Double deform; - - @ArgumentTarget("frequency") - private Double frequency; - - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - Player player = (Player) sender; - - OpenSimplex2Sampler noise = new OpenSimplex2Sampler(ThreadLocalRandom.current().nextInt()); - noise.setFrequency(frequency); - - DeformedSphere sphere = new DeformedSphere(player.getLocation().toVector(), radius, deform, noise); - for(Vector3 v : sphere.getGeometry()) { - v.toLocation(player.getWorld()).getBlock().setBlockData(main.getWorldHandle().createBlockData("minecraft:stone"), false); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/geometry/GeometryCommand.java b/common/src/main/java/com/dfsek/terra/commands/geometry/GeometryCommand.java deleted file mode 100644 index d41bc8506..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/geometry/GeometryCommand.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.dfsek.terra.commands.geometry; - -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Subcommand; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.config.lang.LangUtil; - - -@DebugCommand -@PlayerCommand -@Command( - subcommands = { - @Subcommand( - value = "sphere", - clazz = SphereCommand.class, - aliases = {"s"} - ), - @Subcommand( - value = "deformedsphere", - clazz = DeformedSphereCommand.class, - aliases = {"df"} - ), - @Subcommand( - value = "tube", - clazz = TubeCommand.class, - aliases = {"t"} - ) - }, - usage = "/terra geometry" -) -public class GeometryCommand implements CommandTemplate { - @Override - public void execute(CommandSender sender) { - LangUtil.send("command.geometry.main-menu", sender); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/geometry/SphereCommand.java b/common/src/main/java/com/dfsek/terra/commands/geometry/SphereCommand.java deleted file mode 100644 index 7d8586e6a..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/geometry/SphereCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dfsek.terra.commands.geometry; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.arg.IntegerArgumentParser; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.math.voxel.Sphere; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; - -@DebugCommand -@PlayerCommand -@Command( - arguments = { - @Argument( - value = "radius", - argumentParser = IntegerArgumentParser.class - ) - }, - usage = "/terra geometry sphere " -) -public class SphereCommand implements CommandTemplate { - @ArgumentTarget("radius") - private Integer radius; - - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - Player player = (Player) sender; - - Sphere sphere = new Sphere(player.getLocation().toVector(), radius); - for(Vector3 v : sphere.getGeometry()) { - v.toLocation(player.getWorld()).getBlock().setBlockData(main.getWorldHandle().createBlockData("minecraft:stone"), false); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/geometry/TubeCommand.java b/common/src/main/java/com/dfsek/terra/commands/geometry/TubeCommand.java deleted file mode 100644 index b24694762..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/geometry/TubeCommand.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dfsek.terra.commands.geometry; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.arg.IntegerArgumentParser; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.math.voxel.Tube; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.util.generic.pair.Pair; - -@DebugCommand -@PlayerCommand -@Command( - arguments = { - @Argument( - value = "radius", - argumentParser = IntegerArgumentParser.class - ) - }, - usage = "/terra geometry tube " -) -public class TubeCommand implements CommandTemplate { - @ArgumentTarget("radius") - private Integer radius; - - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - Player player = (Player) sender; - - Pair locations = main.getWorldHandle().getSelectedLocation(player); - - Tube tube = new Tube(locations.getLeft().toVector(), locations.getRight().toVector(), radius); - - for(Vector3 v : tube.getGeometry()) { - v.toLocation(player.getWorld()).getBlock().setBlockData(main.getWorldHandle().createBlockData("minecraft:stone"), false); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileCommand.java deleted file mode 100644 index c81164363..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileCommand.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.commands.profiler; - -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Subcommand; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.config.lang.LangUtil; - -@Command( - subcommands = { - @Subcommand(value = "query", aliases = {"q"}, clazz = ProfileQueryCommand.class), - @Subcommand(value = "start", aliases = {"s"}, clazz = ProfileStartCommand.class), - @Subcommand(value = "stop", aliases = {"st"}, clazz = ProfileStopCommand.class), - @Subcommand(value = "reset", aliases = {"r"}, clazz = ProfileResetCommand.class) - }, - usage = "Commands to enable/disable/query/reset the profiler." -) -@WorldCommand -@PlayerCommand -@DebugCommand -public class ProfileCommand implements CommandTemplate { - @Override - public void execute(CommandSender sender) { - LangUtil.send("command.profile.main-menu", sender); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileQueryCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileQueryCommand.java deleted file mode 100644 index eb54976e5..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileQueryCommand.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dfsek.terra.commands.profiler; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; - -@Command -@DebugCommand -public class ProfileQueryCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - StringBuilder data = new StringBuilder("Terra Profiler data dump: \n"); - main.getProfiler().getTimings().forEach((id, timings) -> data.append(id).append(": ").append(timings.toString()).append('\n')); - main.logger().info(data.toString()); - sender.sendMessage("Profiler data dumped to console."); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileResetCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileResetCommand.java deleted file mode 100644 index 2e5a97d6d..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileResetCommand.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.commands.profiler; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; - -@Command -@DebugCommand -public class ProfileResetCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - main.getProfiler().reset(); - sender.sendMessage("Profiler reset."); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStartCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStartCommand.java deleted file mode 100644 index 63c28c472..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStartCommand.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.commands.profiler; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; - -@Command -@DebugCommand -public class ProfileStartCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - main.getProfiler().start(); - sender.sendMessage("Profiling enabled."); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStopCommand.java b/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStopCommand.java deleted file mode 100644 index baa5aeab3..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/profiler/ProfileStopCommand.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.commands.profiler; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; - -@Command -@DebugCommand -public class ProfileStopCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - main.getProfiler().stop(); - sender.sendMessage("Profiling disabled."); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/SpawnCommand.java b/common/src/main/java/com/dfsek/terra/commands/structure/SpawnCommand.java deleted file mode 100644 index 490de66b4..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/structure/SpawnCommand.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dfsek.terra.commands.structure; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.structures.parser.lang.constants.NumericConstant; -import com.dfsek.terra.api.structures.script.TerraImplementationArguments; -import com.dfsek.terra.api.structures.script.functions.CheckFunction; -import com.dfsek.terra.api.structures.structure.Rotation; -import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer; -import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.api.util.FastRandom; - -import java.util.HashMap; - -@DebugCommand -@PlayerCommand -@WorldCommand -@Command( - usage = "/terra spawn" -) -public class SpawnCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - Player player = (Player) sender; - Location p = player.getLocation(); - int x = p.getBlockX(); - int y = p.getBlockY(); - int z = p.getBlockZ(); - Position dummy = new Position(0, 0); - - String check = new CheckFunction(main, new NumericConstant(0, dummy), new NumericConstant(0, dummy), new NumericConstant(0, dummy), dummy).apply(new TerraImplementationArguments(new StructureBuffer( - new com.dfsek.terra.api.math.vector.Location(player.getWorld(), x, y, z) - ), Rotation.NONE, new FastRandom(), 0), new HashMap<>()); - - sender.sendMessage("Found: " + check); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/StructureCommand.java b/common/src/main/java/com/dfsek/terra/commands/structure/StructureCommand.java deleted file mode 100644 index ad095ac70..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/structure/StructureCommand.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.dfsek.terra.commands.structure; - -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Subcommand; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.config.lang.LangUtil; - -@Command( - subcommands = { - @Subcommand( - clazz = StructureExportCommand.class, - value = "export", - aliases = "ex" - ), - @Subcommand( - clazz = StructureLoadCommand.class, - value = "load", - aliases = "ld" - ), - @Subcommand( - clazz = SpawnCommand.class, - value = "spawn", - aliases = "s" - ), - @Subcommand( - clazz = StructureLocateCommand.class, - value = "locate", - aliases = "l" - ) - }, - usage = "/te structure" -) -public class StructureCommand implements CommandTemplate { - @Override - public void execute(CommandSender sender) { - LangUtil.send("command.structure.main-menu", sender); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/StructureExportCommand.java b/common/src/main/java/com/dfsek/terra/commands/structure/StructureExportCommand.java deleted file mode 100644 index 47dd42a25..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/structure/StructureExportCommand.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.dfsek.terra.commands.structure; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.api.platform.block.state.Sign; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.util.generic.pair.Pair; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; - -@PlayerCommand -@WorldCommand -@DebugCommand -@Command( - arguments = { - @Argument( - value = "id" - ) - }, - usage = "/terra structure export " -) -public class StructureExportCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @ArgumentTarget("id") - private String id; - - @Override - public void execute(CommandSender sender) { - Player player = (Player) sender; - - Pair l = main.getWorldHandle().getSelectedLocation(player); - - Location l1 = l.getLeft(); - Location l2 = l.getRight(); - - StringBuilder scriptBuilder = new StringBuilder("id \"" + id + "\";\nnum y = 0;\n"); - - int centerX = 0; - int centerY = 0; - int centerZ = 0; - - for(int x = l1.getBlockX(); x <= l2.getBlockX(); x++) { - for(int y = l1.getBlockY(); y <= l2.getBlockY(); y++) { - for(int z = l1.getBlockZ(); z <= l2.getBlockZ(); z++) { - Block block = new Location(l1.getWorld(), x, y, z).getBlock(); - BlockState state = block.getState(); - if(state instanceof Sign) { - Sign sign = (Sign) state; - if(sign.getLine(0).equals("[TERRA]") && sign.getLine(1).equals("[CENTER]")) { - centerX = x - l1.getBlockX(); - centerY = y - l1.getBlockY(); - centerZ = z - l1.getBlockZ(); - } - } - } - } - } - - for(int x = l1.getBlockX(); x <= l2.getBlockX(); x++) { - for(int y = l1.getBlockY(); y <= l2.getBlockY(); y++) { - for(int z = l1.getBlockZ(); z <= l2.getBlockZ(); z++) { - - Block block = new Location(l1.getWorld(), x, y, z).getBlock(); - BlockData data = block.getBlockData(); - if(block.getBlockData().isStructureVoid()) continue; - BlockState state = block.getState(); - if(state instanceof Sign) { - Sign sign = (Sign) state; - if(sign.getLine(0).equals("[TERRA]")) { - data = main.getWorldHandle().createBlockData(sign.getLine(2) + sign.getLine(3)); - } - } - if(!data.isStructureVoid()) { - scriptBuilder.append("block(").append(x - l1.getBlockX() - centerX).append(", y + ").append(y - l1.getBlockY() - centerY).append(", ").append(z - l1.getBlockZ() - centerZ).append(", ") - .append("\""); - scriptBuilder.append(data.getAsString()).append("\");\n"); - } - } - } - } - - File file = new File(main.getDataFolder() + File.separator + "export" + File.separator + "structures", id + ".tesf"); - try { - file.getParentFile().mkdirs(); - file.createNewFile(); - } catch(IOException e) { - e.printStackTrace(); - } - try(BufferedWriter writer = new BufferedWriter(new FileWriter(file))) { - writer.write(scriptBuilder.toString()); - } catch(IOException e) { - e.printStackTrace(); - } - - sender.sendMessage("Exported structure to " + file.getAbsolutePath()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/StructureLoadCommand.java b/common/src/main/java/com/dfsek/terra/commands/structure/StructureLoadCommand.java deleted file mode 100644 index dfd22addf..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/structure/StructureLoadCommand.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.dfsek.terra.commands.structure; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Switch; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; -import com.dfsek.terra.api.command.annotation.type.DebugCommand; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.command.arg.IntegerArgumentParser; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.structures.structure.Rotation; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.commands.structure.argument.ScriptArgumentParser; -import com.dfsek.terra.commands.structure.completer.RotationCompleter; -import com.dfsek.terra.commands.structure.completer.ScriptCompleter; - -import java.util.concurrent.ThreadLocalRandom; - -@PlayerCommand -@DebugCommand -@WorldCommand -@Command( - arguments = { - @Argument( - value = "structure", - tabCompleter = ScriptCompleter.class, - argumentParser = ScriptArgumentParser.class - ), - @Argument( - value = "rotation", - required = false, - tabCompleter = RotationCompleter.class, - argumentParser = IntegerArgumentParser.class, - defaultValue = "0" - ) - }, - switches = { - @Switch(value = "chunk", - aliases = "c" - ) - }, - usage = "/terra structure load [ROTATION] [-c]" -) -public class StructureLoadCommand implements CommandTemplate { - @ArgumentTarget("rotation") - private Integer rotation = 0; - - @SwitchTarget("chunk") - private boolean chunk; - - @ArgumentTarget("structure") - private StructureScript script; - - @Inject - private TerraPlugin main; - - @Override - public void execute(CommandSender sender) { - Player player = (Player) sender; - - long t = System.nanoTime(); - FastRandom random = new FastRandom(ThreadLocalRandom.current().nextLong()); - Rotation r; - try { - r = Rotation.fromDegrees(rotation); - } catch(Exception e) { - sender.sendMessage("Invalid rotation: " + rotation); - return; - } - if(script == null) { - sender.sendMessage("Invalid structure."); - return; - } - if(this.chunk) { - script.execute(player.getLocation(), player.getWorld().getChunkAt(player.getLocation()), random, r); - } else { - script.execute(player.getLocation(), random, r); - } - long l = System.nanoTime() - t; - - sender.sendMessage("Took " + ((double) l) / 1000000 + "ms"); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/StructureLocateCommand.java b/common/src/main/java/com/dfsek/terra/commands/structure/StructureLocateCommand.java deleted file mode 100644 index 0e04c3ec4..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/structure/StructureLocateCommand.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.dfsek.terra.commands.structure; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Switch; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.command.arg.IntegerArgumentParser; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.world.locate.AsyncStructureFinder; -import com.dfsek.terra.commands.structure.argument.StructureArgumentParser; -import com.dfsek.terra.commands.structure.completer.StructureCompleter; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.world.population.items.TerraStructure; - -import java.util.Locale; - -@PlayerCommand -@WorldCommand -@Command( - arguments = { - @Argument( - value = "structure", - tabCompleter = StructureCompleter.class, - argumentParser = StructureArgumentParser.class - ), - @Argument( - value = "radius", - required = false, - defaultValue = "100", - argumentParser = IntegerArgumentParser.class - ) - }, - switches = { - @Switch( - value = "teleport", - aliases = {"t", "tp"} - ) - } -) -public class StructureLocateCommand implements CommandTemplate { - @Inject - private TerraPlugin main; - - @ArgumentTarget("structure") - private TerraStructure structure; - - @ArgumentTarget("radius") - private Integer radius; - - @SwitchTarget("teleport") - private boolean teleport; - - @Override - public void execute(CommandSender sender) { - Player player = (Player) sender; - - new Thread(new AsyncStructureFinder(main.getWorld(player.getWorld()).getBiomeProvider(), structure, player.getLocation().clone().multiply((1D / main.getTerraConfig().getBiomeSearchResolution())), 0, radius, location -> { - if(location != null) { - sender.sendMessage(String.format("The nearest %s is at [%d, ~, %d] (%.1f blocks away)", structure.getTemplate().getID().toLowerCase(Locale.ROOT), location.getBlockX(), location.getBlockZ(), location.add(new Vector3(0, player.getLocation().getY(), 0)).distance(player.getLocation().toVector()))); - if(teleport) { - main.runPossiblyUnsafeTask(() -> player.setLocation(new Location(player.getWorld(), location.getX(), player.getLocation().getY(), location.getZ()))); - } - } else LangUtil.send("command.biome.unable-to-locate", sender); - }, main), "Biome Location Thread").start(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/argument/ScriptArgumentParser.java b/common/src/main/java/com/dfsek/terra/commands/structure/argument/ScriptArgumentParser.java deleted file mode 100644 index 3797c08cd..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/structure/argument/ScriptArgumentParser.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.commands.structure.argument; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.arg.ArgumentParser; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.structures.script.StructureScript; - -public class ScriptArgumentParser implements ArgumentParser { - @Inject - private TerraPlugin main; - - @Override - public StructureScript parse(CommandSender sender, String arg) { - return main.getWorld(((Player) sender).getWorld()).getConfig().getScriptRegistry().get(arg); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/argument/StructureArgumentParser.java b/common/src/main/java/com/dfsek/terra/commands/structure/argument/StructureArgumentParser.java deleted file mode 100644 index dce50ac65..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/structure/argument/StructureArgumentParser.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.commands.structure.argument; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.arg.ArgumentParser; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.world.population.items.TerraStructure; - -public class StructureArgumentParser implements ArgumentParser { - @Inject - private TerraPlugin main; - - @Override - public TerraStructure parse(CommandSender sender, String arg) { - return main.getWorld(((Player) sender).getWorld()).getConfig().getStructureRegistry().get(arg); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/completer/RotationCompleter.java b/common/src/main/java/com/dfsek/terra/commands/structure/completer/RotationCompleter.java deleted file mode 100644 index 3bfed746d..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/structure/completer/RotationCompleter.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.commands.structure.completer; - -import com.dfsek.terra.api.command.tab.TabCompleter; -import com.dfsek.terra.api.platform.CommandSender; - -import java.util.Arrays; -import java.util.List; - -public class RotationCompleter implements TabCompleter { - @Override - public List complete(CommandSender sender) { - return Arrays.asList("0", "90", "180", "270"); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/completer/ScriptCompleter.java b/common/src/main/java/com/dfsek/terra/commands/structure/completer/ScriptCompleter.java deleted file mode 100644 index 24f927baa..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/structure/completer/ScriptCompleter.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.commands.structure.completer; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.tab.TabCompleter; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.structures.script.StructureScript; - -import java.util.List; -import java.util.stream.Collectors; - -public class ScriptCompleter implements TabCompleter { - @Inject - private TerraPlugin main; - - @Override - public List complete(CommandSender sender) { - return main.getWorld(((Player) sender).getWorld()).getConfig().getScriptRegistry().entries().stream().map(StructureScript::getId).collect(Collectors.toList()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/commands/structure/completer/StructureCompleter.java b/common/src/main/java/com/dfsek/terra/commands/structure/completer/StructureCompleter.java deleted file mode 100644 index a2b5b1dad..000000000 --- a/common/src/main/java/com/dfsek/terra/commands/structure/completer/StructureCompleter.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.commands.structure.completer; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.command.tab.TabCompleter; -import com.dfsek.terra.api.injection.annotations.Inject; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; - -import java.util.ArrayList; -import java.util.List; - -public class StructureCompleter implements TabCompleter { - @Inject - private TerraPlugin main; - - @Override - public List complete(CommandSender sender) { - Player player = (Player) sender; - return new ArrayList<>(main.getWorld(player.getWorld()).getConfig().getStructureRegistry().keys()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java b/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java deleted file mode 100644 index 0726b8d97..000000000 --- a/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.dfsek.terra.config; - -import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.LoaderRegistrar; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.math.GridSpawn; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.noise.samplers.ImageSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.CellularSampler; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.seeded.SourceSeeded; -import com.dfsek.terra.api.util.seeded.StageSeeded; -import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; -import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage; -import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.biome.provider.ImageBiomeProvider; -import com.dfsek.terra.api.world.palette.holder.PaletteHolder; -import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; -import com.dfsek.terra.carving.CarverPalette; -import com.dfsek.terra.config.loaders.LinkedHashMapLoader; -import com.dfsek.terra.config.loaders.MaterialSetLoader; -import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader; -import com.dfsek.terra.config.loaders.RangeLoader; -import com.dfsek.terra.config.loaders.config.FloraLayerLoader; -import com.dfsek.terra.config.loaders.config.GridSpawnLoader; -import com.dfsek.terra.config.loaders.config.OreConfigLoader; -import com.dfsek.terra.config.loaders.config.OreHolderLoader; -import com.dfsek.terra.config.loaders.config.TreeLayerLoader; -import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader; -import com.dfsek.terra.config.loaders.config.biome.SourceBuilderLoader; -import com.dfsek.terra.config.loaders.config.biome.StageBuilderLoader; -import com.dfsek.terra.config.loaders.config.biome.templates.source.NoiseSourceTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.expander.ExpanderStageTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderListMutatorTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.ReplaceListMutatorTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.ReplaceMutatorTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.SmoothMutatorTemplate; -import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.DomainWarpTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.ClampNormalizerTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.LinearNormalizerTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.NormalNormalizerTemplate; -import com.dfsek.terra.config.loaders.palette.CarverPaletteLoader; -import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader; -import com.dfsek.terra.config.loaders.palette.PaletteLayerLoader; -import com.dfsek.terra.world.population.items.flora.FloraLayer; -import com.dfsek.terra.world.population.items.flora.TerraFlora; -import com.dfsek.terra.world.population.items.ores.Ore; -import com.dfsek.terra.world.population.items.ores.OreConfig; -import com.dfsek.terra.world.population.items.ores.OreHolder; -import com.dfsek.terra.world.population.items.tree.TreeLayer; - -import java.util.LinkedHashMap; - -public class GenericLoaders implements LoaderRegistrar { - private final TerraPlugin main; - - public GenericLoaders(TerraPlugin main) { - this.main = main; - } - - @Override - public void register(TypeRegistry registry) { - registry.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader()) - .registerLoader(Range.class, new RangeLoader()) - .registerLoader(GridSpawn.class, new GridSpawnLoader()) - .registerLoader(PaletteHolder.class, new PaletteHolderLoader()) - .registerLoader(PaletteLayerHolder.class, new PaletteLayerLoader()) - .registerLoader(FloraLayer.class, new FloraLayerLoader()) - .registerLoader(Ore.Type.class, (t, o, l) -> Ore.Type.valueOf(o.toString())) - .registerLoader(OreConfig.class, new OreConfigLoader()) - .registerLoader(TreeLayer.class, new TreeLayerLoader()) - .registerLoader(MaterialSet.class, new MaterialSetLoader()) - .registerLoader(OreHolder.class, new OreHolderLoader()) - .registerLoader(ImageSamplerTemplate.class, ImageSamplerTemplate::new) - .registerLoader(DomainWarpTemplate.class, DomainWarpTemplate::new) - .registerLoader(LinearNormalizerTemplate.class, LinearNormalizerTemplate::new) - .registerLoader(NormalNormalizerTemplate.class, NormalNormalizerTemplate::new) - .registerLoader(ClampNormalizerTemplate.class, ClampNormalizerTemplate::new) - .registerLoader(ReplaceMutatorTemplate.class, ReplaceMutatorTemplate::new) - .registerLoader(ExpanderStageTemplate.class, ExpanderStageTemplate::new) - .registerLoader(SmoothMutatorTemplate.class, SmoothMutatorTemplate::new) - .registerLoader(ReplaceListMutatorTemplate.class, ReplaceListMutatorTemplate::new) - .registerLoader(BorderMutatorTemplate.class, BorderMutatorTemplate::new) - .registerLoader(BorderListMutatorTemplate.class, BorderListMutatorTemplate::new) - .registerLoader(NoiseSourceTemplate.class, NoiseSourceTemplate::new) - .registerLoader(FunctionTemplate.class, FunctionTemplate::new) - .registerLoader(LinkedHashMap.class, new LinkedHashMapLoader()) - .registerLoader(CarverPalette.class, new CarverPaletteLoader()) - .registerLoader(SourceSeeded.class, new SourceBuilderLoader()) - .registerLoader(StageSeeded.class, new StageBuilderLoader()) - .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader()) - .registerLoader(ImageSampler.Channel.class, (t, object, cf) -> ImageSampler.Channel.valueOf((String) object)) - .registerLoader(BiomeProvider.Type.class, (t, object, cf) -> BiomeProvider.Type.valueOf((String) object)) - .registerLoader(BiomeSource.Type.class, (t, object, cf) -> BiomeSource.Type.valueOf((String) object)) - .registerLoader(ImageBiomeProvider.Align.class, (t, object, cf) -> ImageBiomeProvider.Align.valueOf((String) object)) - .registerLoader(ExpanderStage.Type.class, (t, object, cf) -> ExpanderStage.Type.valueOf((String) object)) - .registerLoader(MutatorStage.Type.class, (t, object, cf) -> MutatorStage.Type.valueOf((String) object)) - .registerLoader(CellularSampler.ReturnType.class, (t, object, cf) -> CellularSampler.ReturnType.valueOf((String) object)) - .registerLoader(CellularSampler.DistanceFunction.class, (t, object, cf) -> CellularSampler.DistanceFunction.valueOf((String) object)) - .registerLoader(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf(o.toString())); - - if(main != null) { - registry.registerLoader(TerraAddon.class, main.getAddons()) - .registerLoader(BlockType.class, (t, object, cf) -> main.getWorldHandle().createBlockData((String) object).getBlockType()); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/PluginConfig.java b/common/src/main/java/com/dfsek/terra/config/PluginConfig.java deleted file mode 100644 index d391fed8e..000000000 --- a/common/src/main/java/com/dfsek/terra/config/PluginConfig.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.dfsek.terra.config; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.util.JarUtil; -import com.dfsek.terra.api.util.logging.Logger; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.net.URISyntaxException; -import java.time.Duration; -import java.util.jar.JarFile; - -@SuppressWarnings("FieldMayBeFinal") -public class PluginConfig implements ConfigTemplate { - @Value("debug") - @Default - private boolean debug = false; - - @Value("language") - @Default - private String language = "en_us"; - - @Value("data-save") - @Default - private Duration dataSave = Duration.parse("PT6M"); - - @Value("biome-search-resolution") - @Default - private int biomeSearch = 4; - - @Value("cache.carver") - @Default - private int carverCache = 256; - - @Value("cache.structure") - @Default - private int structureCache = 32; - - @Value("cache.sampler") - @Default - private int samplerCache = 64; - - @Value("cache.biome") - @Default - private int biomeCache = 512; - - @Value("cache.biome-provider") - @Default - private int providerCache = 32; - - @Value("dump-default") - @Default - private boolean dumpDefaultConfig = true; - - @Value("script.max-recursion") - @Default - private int maxRecursion = 1000; - - public void load(TerraPlugin main) { - Logger logger = main.logger(); - logger.info("Loading config values"); - try(FileInputStream file = new FileInputStream(new File(main.getDataFolder(), "config.yml"))) { - ConfigLoader loader = new ConfigLoader(); - loader.load(this, file); - if(dumpDefaultConfig) { // Don't dump default config if already loaded. - try(JarFile jar = main.getModJar()) { - JarUtil.copyResourcesToDirectory(jar, "packs", new File(main.getDataFolder(), "packs").toString()); - } catch(IOException | URISyntaxException e) { - main.getDebugLogger().error("Failed to dump default config files!"); - e.printStackTrace(); - main.getDebugLogger().error("Either you're on Forge, or this is a bug. If it's the latter, report this to Terra!"); - } - } - } catch(ConfigException | IOException e) { - e.printStackTrace(); - } - logger.info("DebugLogger: " + isDebug()); - } - - public String getLanguage() { - return language; - } - - public boolean isDebug() { - return debug; - } - - public long getDataSaveInterval() { - return dataSave.toMillis() / 20L; - } - - public int getBiomeSearchResolution() { - return biomeSearch; - } - - public int getCarverCacheSize() { - return carverCache; - } - - public int getStructureCache() { - return structureCache; - } - - public int getSamplerCache() { - return samplerCache; - } - - public int getMaxRecursion() { - return maxRecursion; - } - - public int getBiomeCache() { - return biomeCache; - } - - public int getProviderCache() { - return providerCache; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/builder/BiomeBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/BiomeBuilder.java deleted file mode 100644 index f29a06c7c..000000000 --- a/common/src/main/java/com/dfsek/terra/config/builder/BiomeBuilder.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.config.builder; - -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.seeded.SeededBuilder; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.config.templates.BiomeTemplate; - -public interface BiomeBuilder extends SeededBuilder { - ProbabilityCollection getVanillaBiomes(); - - BiomeTemplate getTemplate(); -} diff --git a/common/src/main/java/com/dfsek/terra/config/builder/UserDefinedBiomeBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/UserDefinedBiomeBuilder.java deleted file mode 100644 index a4a39e3e3..000000000 --- a/common/src/main/java/com/dfsek/terra/config/builder/UserDefinedBiomeBuilder.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.dfsek.terra.config.builder; - -import com.dfsek.paralithic.eval.parser.Scope; -import com.dfsek.paralithic.eval.tokenizer.ParseException; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.ExpressionSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler; -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.world.generation.WorldGenerator; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class UserDefinedBiomeBuilder implements BiomeBuilder { - private final BiomeTemplate template; - private final ConfigPack pack; - - private final Map biomeMap = new ConcurrentHashMap<>(); - - public UserDefinedBiomeBuilder(BiomeTemplate template, ConfigPack pack) { - this.template = template; - this.pack = pack; - } - - @Override - public UserDefinedBiome apply(Long seed) { - synchronized(biomeMap) { - return biomeMap.computeIfAbsent(seed, - s -> { - NoiseSampler noise; - NoiseSampler elevation; - NoiseSampler carving; - Scope varScope = new Scope().withParent(pack.getVarScope()); - - template.getVariables().forEach(varScope::create); - - Map noiseBuilderMap = pack.getTemplate().getNoiseBuilderMap(); - Map functionTemplateMap = new LinkedHashMap<>(pack.getTemplate().getFunctions()); - - functionTemplateMap.putAll(template.getFunctions()); - - try { - noise = new ExpressionSampler(template.getNoiseEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap); - elevation = template.getElevationEquation() == null ? new ConstantSampler(0) : new ExpressionSampler(template.getElevationEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap); - carving = new ExpressionSampler(template.getCarvingEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap); - } catch(ParseException e) { - throw new RuntimeException(e); - } - - WorldGenerator generator = new WorldGenerator(template.getPalette(), template.getSlantPalette(), noise, elevation, carving, template.getBiomeNoise().apply(seed), template.getElevationWeight(), - template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight()); - return new UserDefinedBiome(template.getVanilla(), generator, template); - } - ); - } - } - - @Override - public ProbabilityCollection getVanillaBiomes() { - return template.getVanilla(); - } - - @Override - public BiomeTemplate getTemplate() { - return template; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/dummy/DummyWorld.java b/common/src/main/java/com/dfsek/terra/config/dummy/DummyWorld.java deleted file mode 100644 index 26082be6a..000000000 --- a/common/src/main/java/com/dfsek/terra/config/dummy/DummyWorld.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.config.dummy; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; - -public class DummyWorld implements World { - @Override - public Object getHandle() { - throw new UnsupportedOperationException("Cannot get handle of DummyWorld"); - } - - @Override - public long getSeed() { - return 2403L; - } - - @Override - public int getMaxHeight() { - return 255; - } - - @Override - public ChunkGenerator getGenerator() { - return () -> (GeneratorWrapper) () -> null; - } - - @Override - public Chunk getChunkAt(int x, int z) { - throw new UnsupportedOperationException("Cannot get chunk in DummyWorld"); - } - - @Override - public Block getBlockAt(int x, int y, int z) { - throw new UnsupportedOperationException("Cannot get block in DummyWorld"); - } - - @Override - public Entity spawnEntity(Location location, EntityType entityType) { - throw new UnsupportedOperationException("Cannot spawn entity in DummyWorld"); - } - - @Override - public int getMinHeight() { - return 0; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java deleted file mode 100644 index c19ea0988..000000000 --- a/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.config.factories; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.config.builder.BiomeBuilder; -import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.BiomeTemplate; - -public class BiomeFactory implements ConfigFactory { - private final ConfigPack pack; - - public BiomeFactory(ConfigPack pack) { - this.pack = pack; - } - - @Override - public BiomeBuilder build(BiomeTemplate template, TerraPlugin main) { - return new UserDefinedBiomeBuilder(template, pack); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java deleted file mode 100644 index e572f3e6c..000000000 --- a/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.dfsek.terra.config.factories; - -import com.dfsek.paralithic.eval.tokenizer.ParseException; -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.carving.UserDefinedCarver; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.CarverTemplate; - -import java.util.Arrays; -import java.util.List; - -public class CarverFactory implements ConfigFactory { - private final ConfigPack pack; - - public CarverFactory(ConfigPack pack) { - this.pack = pack; - } - - @Override - public UserDefinedCarver build(CarverTemplate config, TerraPlugin main) throws LoadException { - double[] start = new double[] {config.getStartX(), config.getStartY(), config.getStartZ()}; - double[] mutate = new double[] {config.getMutateX(), config.getMutateY(), config.getMutateZ()}; - List radius = Arrays.asList(config.getRadMX(), config.getRadMY(), config.getRadMZ()); - long hash = MathUtil.hashToLong(config.getID()); - UserDefinedCarver carver; - try { - carver = new UserDefinedCarver(config.getHeight(), config.getLength(), start, mutate, radius, pack.getVarScope(), hash, config.getCutTop(), config.getCutBottom(), config, main, pack.getTemplate().getNoiseBuilderMap(), pack.getTemplate().getFunctions()); - } catch(ParseException e) { - throw new LoadException("Unable to parse radius equations", e); - } - carver.setRecalc(config.getRecalc()); - carver.setRecalcMagnitude(config.getRecaclulateMagnitude()); - return carver; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/factories/ConfigFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/ConfigFactory.java deleted file mode 100644 index cf676a8d6..000000000 --- a/common/src/main/java/com/dfsek/terra/config/factories/ConfigFactory.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dfsek.terra.config.factories; - -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.terra.api.TerraPlugin; - -public interface ConfigFactory { - O build(C config, TerraPlugin main) throws LoadException; -} diff --git a/common/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java deleted file mode 100644 index 279dbf3e4..000000000 --- a/common/src/main/java/com/dfsek/terra/config/factories/FloraFactory.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.config.factories; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.world.flora.Flora; -import com.dfsek.terra.api.world.palette.NoisePalette; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; -import com.dfsek.terra.config.templates.FloraTemplate; -import com.dfsek.terra.world.population.items.flora.TerraFlora; - -public class FloraFactory implements ConfigFactory { - @Override - public TerraFlora build(FloraTemplate config, TerraPlugin main) { - Palette palette = new NoisePalette<>(new WhiteNoiseSampler(2403), false); - for(PaletteLayerHolder layer : config.getFloraPalette()) { - palette.add(layer.getLayer(), layer.getSize(), layer.getSampler()); - } - return new TerraFlora(palette, config.doPhysics(), config.isCeiling(), config.getIrrigable(), config.getSpawnable(), config.getReplaceable(), config.getRotatable(), config.getMaxPlacements(), config.getSearch(), config.isSpawnBlacklist(), config.getIrrigableOffset(), main); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java deleted file mode 100644 index be6ea19d9..000000000 --- a/common/src/main/java/com/dfsek/terra/config/factories/OreFactory.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.config.factories; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.config.templates.OreTemplate; -import com.dfsek.terra.world.population.items.ores.DeformedSphereOre; -import com.dfsek.terra.world.population.items.ores.Ore; -import com.dfsek.terra.world.population.items.ores.VanillaOre; - -public class OreFactory implements ConfigFactory { - @Override - public Ore build(OreTemplate config, TerraPlugin main) { - BlockData m = config.getMaterial(); - switch(config.getType()) { - case SPHERE: - return new DeformedSphereOre(m, config.getReplaceable(), config.doPhysics(), config.getDeform(), config.getDeformFrequency(), config.getSize(), main, config.getMaterialOverrides()); - case VANILLA: - return new VanillaOre(m, config.getReplaceable(), config.doPhysics(), config.getSize(), main, config.getMaterialOverrides()); - } - return null; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java deleted file mode 100644 index d4983c076..000000000 --- a/common/src/main/java/com/dfsek/terra/config/factories/PaletteFactory.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.config.factories; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.world.palette.NoisePalette; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; -import com.dfsek.terra.config.templates.PaletteTemplate; - -public class PaletteFactory implements ConfigFactory> { - @Override - public Palette build(PaletteTemplate config, TerraPlugin main) { - NoisePalette palette = new NoisePalette<>(config.getNoise().apply(2403L), config.getNoise().getDimensions() == 2); - for(PaletteLayerHolder layer : config.getPalette()) { - palette.add(layer.getLayer(), layer.getSize(), layer.getSampler()); - } - return palette; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java deleted file mode 100644 index 0fa25315d..000000000 --- a/common/src/main/java/com/dfsek/terra/config/factories/StructureFactory.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.config.factories; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.config.templates.StructureTemplate; -import com.dfsek.terra.world.population.items.TerraStructure; - -public class StructureFactory implements ConfigFactory { - @Override - public TerraStructure build(StructureTemplate config, TerraPlugin main) { - return new TerraStructure(config.getStructures(), config.getY(), config.getSpawn(), config); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java deleted file mode 100644 index 6e57002dc..000000000 --- a/common/src/main/java/com/dfsek/terra/config/factories/TreeFactory.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.config.factories; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.config.templates.TreeTemplate; -import com.dfsek.terra.world.population.items.tree.TerraTree; - -public class TreeFactory implements ConfigFactory { - @Override - public Tree build(TreeTemplate config, TerraPlugin main) { - return new TerraTree(config.getSpawnable(), config.getyOffset(), config.getStructures()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/fileloaders/ExceptionalConsumer.java b/common/src/main/java/com/dfsek/terra/config/fileloaders/ExceptionalConsumer.java deleted file mode 100644 index 9037f4d00..000000000 --- a/common/src/main/java/com/dfsek/terra/config/fileloaders/ExceptionalConsumer.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.config.fileloaders; - -import com.dfsek.tectonic.exception.ConfigException; - -@FunctionalInterface -public interface ExceptionalConsumer { - void accept(T t) throws ConfigException; -} diff --git a/common/src/main/java/com/dfsek/terra/config/fileloaders/Loader.java b/common/src/main/java/com/dfsek/terra/config/fileloaders/Loader.java deleted file mode 100644 index c4b0bf6c7..000000000 --- a/common/src/main/java/com/dfsek/terra/config/fileloaders/Loader.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.dfsek.terra.config.fileloaders; - -import com.dfsek.tectonic.config.Configuration; -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.terra.api.util.GlueList; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public abstract class Loader { - protected final Map streams = new HashMap<>(); - - /** - * Do something with the InputStreams. - * - * @param consumer Something to do with the streams. - */ - public Loader then(ExceptionalConsumer> consumer) throws ConfigException { - List list = new GlueList<>(); - streams.forEach((id, stream) -> { - list.add(new Configuration(stream, id)); - }); - consumer.accept(list); - return this; - } - - public Loader thenNames(ExceptionalConsumer> consumer) throws ConfigException { - consumer.accept(new GlueList<>(streams.keySet())); - return this; - } - - public Loader thenEntries(ExceptionalConsumer>> consumer) throws ConfigException { - consumer.accept(streams.entrySet()); - return this; - } - - /** - * Get a single file from this Loader. - * - * @param singleFile File to get - * @return InputStream from file. - */ - public abstract InputStream get(String singleFile) throws IOException; - - /** - * Open a subdirectory. - * - * @param directory Directory to open - * @param extension - */ - public Loader open(String directory, String extension) { - if(streams.size() != 0) throw new IllegalStateException("Attempted to load new directory before closing existing InputStreams"); - load(directory, extension); - return this; - } - - protected abstract void load(String directory, String extension); - - /** - * Close all InputStreams opened. - */ - public Loader close() { - streams.forEach((name, input) -> { - try { - input.close(); - } catch(IOException e) { - e.printStackTrace(); - } - }); - streams.clear(); - return this; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/lang/LangUtil.java b/common/src/main/java/com/dfsek/terra/config/lang/LangUtil.java deleted file mode 100644 index 87f24b13e..000000000 --- a/common/src/main/java/com/dfsek/terra/config/lang/LangUtil.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.dfsek.terra.config.lang; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.util.logging.Logger; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.jar.JarFile; - -import static com.dfsek.terra.api.util.JarUtil.copyResourcesToDirectory; - -public final class LangUtil { - private static Language language; - - public static void load(String langID, TerraPlugin main) { - Logger logger = main.logger(); - File file = new File(main.getDataFolder(), "lang"); - try(JarFile jar = main.getModJar()) { - copyResourcesToDirectory(jar, "lang", file.toString()); - } catch(IOException | URISyntaxException e) { - main.getDebugLogger().error("Failed to dump language files!"); - main.getDebugLogger().stack(e); - } - try { - File file1 = new File(file, langID + ".yml"); - logger.info(file1.getAbsolutePath()); - language = new Language(file1); - logger.info("Loaded language " + langID); - } catch(IOException e) { - logger.severe("Unable to load language: " + langID); - e.printStackTrace(); - logger.severe("Double-check your configuration before reporting this to Terra!"); - } - } - - public static Language getLanguage() { - return language; - } - - public static void send(String messageID, CommandSender sender, String... args) { - language.getMessage(messageID).send(sender, args); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/lang/Language.java b/common/src/main/java/com/dfsek/terra/config/lang/Language.java deleted file mode 100644 index 2b5836391..000000000 --- a/common/src/main/java/com/dfsek/terra/config/lang/Language.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dfsek.terra.config.lang; - - -import com.dfsek.tectonic.config.Configuration; -import com.dfsek.terra.api.platform.CommandSender; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class Language { - private final Configuration configuration; - public Language(File file) throws IOException { - configuration = new Configuration(new FileInputStream(file)); - } - @SuppressWarnings("unchecked") - public Message getMessage(String id) { - Message temp = null; - if(configuration.contains(id)) { - Object m = configuration.get(id); - - if(m instanceof List) { - temp = new MultiLineMessage((List) m); - } else if(m instanceof String) { - temp = new SingleLineMessage((String) m); - } else return new SingleLineMessage("message:" + id + ":translation_undefined"); - } - if(temp == null || temp.isEmpty()) return new SingleLineMessage("message:" + id + ":translation_undefined"); - return temp; - } - public void log(String messageID, Level level, Logger logger, String... args) { - getMessage(messageID).log(logger, level, args); - } - public void send(String messageID, CommandSender sender, String... args) { - getMessage(messageID).send(sender, args); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/lang/Message.java b/common/src/main/java/com/dfsek/terra/config/lang/Message.java deleted file mode 100644 index 20ac16c14..000000000 --- a/common/src/main/java/com/dfsek/terra/config/lang/Message.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.config.lang; - - -import com.dfsek.terra.api.platform.CommandSender; - -import java.util.logging.Level; -import java.util.logging.Logger; - -public interface Message { - void log(Logger logger, Level level, String... args); - void send(CommandSender sender, String... args); - boolean isEmpty(); -} diff --git a/common/src/main/java/com/dfsek/terra/config/lang/MultiLineMessage.java b/common/src/main/java/com/dfsek/terra/config/lang/MultiLineMessage.java deleted file mode 100644 index 2d9ef1c12..000000000 --- a/common/src/main/java/com/dfsek/terra/config/lang/MultiLineMessage.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dfsek.terra.config.lang; - -import com.dfsek.terra.api.platform.CommandSender; - -import java.util.Arrays; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class MultiLineMessage implements Message { - private final List message; - public MultiLineMessage(List message) { - this.message = message; - } - @Override - public void log(Logger logger, Level level, String... args) { - for(String line: message) { - logger.log(level, String.format(line, Arrays.asList(args).toArray())); - } - } - - @Override - public void send(CommandSender sender, String... args) { - for(String line: message) { - sender.sendMessage(String.format(line, Arrays.asList(args).toArray())); - } - } - - @Override - public boolean isEmpty() { - return message == null || message.isEmpty(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/lang/SingleLineMessage.java b/common/src/main/java/com/dfsek/terra/config/lang/SingleLineMessage.java deleted file mode 100644 index f397dae50..000000000 --- a/common/src/main/java/com/dfsek/terra/config/lang/SingleLineMessage.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.config.lang; - - -import com.dfsek.terra.api.platform.CommandSender; - -import java.util.Arrays; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class SingleLineMessage implements Message { - private final String message; - public SingleLineMessage(String message) { - this.message = message; - } - @Override - public void log(Logger logger, Level level, String... args) { - logger.log(level, String.format(message, Arrays.asList(args).toArray())); - } - - @Override - public void send(CommandSender sender, String... args) { - sender.sendMessage(String.format(message, Arrays.asList(args).toArray())); - } - - @Override - public boolean isEmpty() { - return message == null || message.equals(""); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/LinkedHashMapLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/LinkedHashMapLoader.java deleted file mode 100644 index 5de7cbe9b..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/LinkedHashMapLoader.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.config.loaders; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.LinkedHashMap; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class LinkedHashMapLoader implements TypeLoader> { - @Override - public LinkedHashMap load(Type t, Object c, ConfigLoader loader) throws LoadException { - Map config = (Map) c; - LinkedHashMap map = new LinkedHashMap<>(); - if(t instanceof ParameterizedType) { - ParameterizedType pType = (ParameterizedType) t; - Type key = pType.getActualTypeArguments()[0]; - Type value = pType.getActualTypeArguments()[1]; - for(Map.Entry entry : config.entrySet()) { - map.put(loader.loadType(key, entry.getKey()), loader.loadType(value, entry.getValue())); - } - } else throw new LoadException("Unable to load config"); - - return map; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java deleted file mode 100644 index a98ca9837..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/MaterialSetLoader.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.config.loaders; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.util.collections.MaterialSet; - -import java.lang.reflect.Type; -import java.util.List; - -@SuppressWarnings("unchecked") -public class MaterialSetLoader implements TypeLoader { - @Override - public MaterialSet load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - List stringData = (List) o; - MaterialSet set = new MaterialSet(); - - for(String string : stringData) { - try { - set.add(configLoader.loadClass(BlockType.class, string)); - } catch(NullPointerException e) { - throw new LoadException("Invalid data identifier \"" + string + "\"", e); - } - } - - return set; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java deleted file mode 100644 index 050281b4d..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/ProbabilityCollectionLoader.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.dfsek.terra.config.loaders; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.List; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class ProbabilityCollectionLoader implements TypeLoader> { - @Override - public ProbabilityCollection load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - ProbabilityCollection collection = new ProbabilityCollection<>(); - - if(type instanceof ParameterizedType) { - ParameterizedType pType = (ParameterizedType) type; - Type generic = pType.getActualTypeArguments()[0]; - if(o instanceof Map) { - Map map = (Map) o; - for(Map.Entry entry : map.entrySet()) { - collection.add(configLoader.loadType(generic, entry.getKey()), entry.getValue()); - } - } else if(o instanceof List) { - List> map = (List>) o; - for(Map l : map) { - for(Map.Entry entry : l.entrySet()) { - if(entry.getValue() == null) throw new LoadException("No probability defined for entry \"" + entry.getKey() + "\""); - Object val = configLoader.loadType(generic, entry.getKey()); - collection.add(val, entry.getValue()); - } - } - } else if(o instanceof String) { - return new ProbabilityCollection.Singleton<>(configLoader.loadType(generic, o)); - } else { - throw new LoadException("Malformed Probability Collection: " + o); - } - } else throw new LoadException("Unable to load config! Could not retrieve parameterized type: " + type); - - - return collection; - } - -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java deleted file mode 100644 index 7b0913ba7..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/RangeLoader.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.config.loaders; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.Range; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class RangeLoader implements TypeLoader { - @Override - public Range load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - Map map = (Map) o; - return new Range(map.get("min"), map.get("max")); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/Types.java b/common/src/main/java/com/dfsek/terra/config/loaders/Types.java deleted file mode 100644 index 46c4f0978..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/Types.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dfsek.terra.config.loaders; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.flora.Flora; -import com.dfsek.terra.api.world.palette.Palette; - -import java.lang.reflect.Type; -import java.util.Map; - -/** - * Class to hold Type instances for types with generics. - */ -@SuppressWarnings("unused") -public final class Types { - public static final Type BLOCK_DATA_PALETTE_TYPE; - public static final Type BLOCK_DATA_PROBABILITY_COLLECTION_TYPE; - public static final Type FLORA_PROBABILITY_COLLECTION_TYPE; - public static final Type TREE_PROBABILITY_COLLECTION_TYPE; - public static final Type TERRA_BIOME_PROBABILITY_COLLECTION_TYPE; - public static final Type TERRA_BIOME_TERRA_BIOME_PROBABILITY_COLLECTION_MAP; - - static { - BLOCK_DATA_PALETTE_TYPE = getType("blockDataPalette"); - BLOCK_DATA_PROBABILITY_COLLECTION_TYPE = getType("blockDataProbabilityCollection"); - FLORA_PROBABILITY_COLLECTION_TYPE = getType("floraProbabilityCollection"); - TREE_PROBABILITY_COLLECTION_TYPE = getType("treeProbabilityCollection"); - TERRA_BIOME_PROBABILITY_COLLECTION_TYPE = getType("terraBiomeProbabilityCollection"); - TERRA_BIOME_TERRA_BIOME_PROBABILITY_COLLECTION_MAP = getType("terraBiomeProbabilityCollectionMap"); - } - - private Palette blockDataPalette; - private ProbabilityCollection blockDataProbabilityCollection; - private ProbabilityCollection floraProbabilityCollection; - private ProbabilityCollection treeProbabilityCollection; - private ProbabilityCollection terraBiomeProbabilityCollection; - private Map> terraBiomeProbabilityCollectionMap; - - private static Type getType(String dummyFieldName) { - try { - return Types.class.getDeclaredField(dummyFieldName).getGenericType(); - } catch(NoSuchFieldException e) { - e.printStackTrace(); - return null; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java deleted file mode 100644 index 191477d4c..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/BufferedImageLoader.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dfsek.terra.config.loaders.config; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.config.fileloaders.Loader; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.lang.reflect.Type; - -public class BufferedImageLoader implements TypeLoader { - private final Loader files; - - public BufferedImageLoader(Loader files) { - this.files = files; - } - - @Override - public BufferedImage load(Type t, Object c, ConfigLoader loader) throws LoadException { - try { - return ImageIO.read(files.get((String) c)); - } catch(IOException e) { - throw new LoadException("Unable to load image", e); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java deleted file mode 100644 index 719bf9b91..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/FloraLayerLoader.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dfsek.terra.config.loaders.config; - -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.world.flora.Flora; -import com.dfsek.terra.config.loaders.Types; -import com.dfsek.terra.world.population.items.flora.FloraLayer; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class FloraLayerLoader implements TypeLoader { - @Override - public FloraLayer load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - Map map = (Map) o; - double density = ((Number) map.get("density")).doubleValue(); - Range range = configLoader.loadClass(Range.class, map.get("y")); - if(range == null) throw new LoadException("Flora range unspecified"); - ProbabilityCollection items = (ProbabilityCollection) configLoader.loadType(Types.FLORA_PROBABILITY_COLLECTION_TYPE, map.get("items")); - - NoiseSeeded sampler; - if(map.containsKey("distribution")) { - try { - sampler = configLoader.loadClass(NoiseSeeded.class, map.get("distribution")); - } catch(ConfigException e) { - throw new LoadException("Unable to load noise", e); - } - return new FloraLayer(density, range, items, sampler.apply(2403L)); - } - - return new FloraLayer(density, range, items, new WhiteNoiseSampler(2403)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/GridSpawnLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/GridSpawnLoader.java deleted file mode 100644 index 493d0b0eb..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/GridSpawnLoader.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.config.loaders.config; - -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.GridSpawn; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class GridSpawnLoader implements TypeLoader { - @Override - public GridSpawn load(Type type, Object o, ConfigLoader configLoader) { - Map map = (Map) o; - return new GridSpawn(map.get("width"), map.get("padding"), map.getOrDefault("salt", 0)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/OreConfigLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/OreConfigLoader.java deleted file mode 100644 index 548da2181..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/OreConfigLoader.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.config.loaders.config; - -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.world.population.items.ores.OreConfig; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class OreConfigLoader implements TypeLoader { - @Override - public OreConfig load(Type type, Object o, ConfigLoader configLoader) { - Map map = (Map) o; - Range amount = new Range(map.get("min"), map.get("max")); - Range height = new Range(map.get("min-height"), map.get("max-height")); - return new OreConfig(amount, height); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java deleted file mode 100644 index 08f682171..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/OreHolderLoader.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dfsek.terra.config.loaders.config; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.world.population.items.ores.Ore; -import com.dfsek.terra.world.population.items.ores.OreConfig; -import com.dfsek.terra.world.population.items.ores.OreHolder; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class OreHolderLoader implements TypeLoader { - @Override - public OreHolder load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - OreHolder holder = new OreHolder(); - Map map = (Map) o; - - for(Map.Entry entry : map.entrySet()) { - holder.add(configLoader.loadClass(Ore.class, entry.getKey()), configLoader.loadClass(OreConfig.class, entry.getValue()), entry.getKey()); - } - - return holder; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java deleted file mode 100644 index 0b52d2d19..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/TreeLayerLoader.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dfsek.terra.config.loaders.config; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.config.loaders.Types; -import com.dfsek.terra.world.population.items.tree.TreeLayer; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class TreeLayerLoader implements TypeLoader { - @Override - public TreeLayer load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - Map map = (Map) o; - double density = ((Number) map.get("density")).doubleValue(); - Range range = configLoader.loadClass(Range.class, map.get("y")); - if(range == null) throw new LoadException("Tree range unspecified"); - ProbabilityCollection items = (ProbabilityCollection) configLoader.loadType(Types.TREE_PROBABILITY_COLLECTION_TYPE, map.get("items")); - - if(map.containsKey("distribution")) { - NoiseSeeded noise = configLoader.loadClass(NoiseSeeded.class, map.get("distribution")); - return new TreeLayer(density, range, items, noise.apply(2403L)); - } - - return new TreeLayer(density, range, items, new WhiteNoiseSampler(2403)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java deleted file mode 100644 index 718d33907..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class BiomeProviderBuilderLoader implements TypeLoader { - - public BiomeProviderBuilderLoader() { - } - - @Override - public BiomeProvider.BiomeProviderBuilder load(Type t, Object c, ConfigLoader loader) throws LoadException { // TODO: clean this up - Map map = (Map) c; - - switch(loader.loadClass(BiomeProvider.Type.class, map.get("type"))) { - case IMAGE: - return loader.loadClass(ImageProviderTemplate.class, map); - case PIPELINE: - return loader.loadClass(BiomePipelineTemplate.class, map); - case SINGLE: - return loader.loadClass(SingleBiomeProviderTemplate.class, map); - } - - throw new LoadException("No such biome provider type: " + map.get("type")); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java deleted file mode 100644 index 33f1dcd42..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.util.seeded.SourceSeeded; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; -import com.dfsek.terra.api.world.biome.pipeline.source.RandomSource; -import com.dfsek.terra.config.loaders.Types; -import com.dfsek.terra.config.loaders.config.biome.templates.source.NoiseSourceTemplate; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class SourceBuilderLoader implements TypeLoader { - @Override - public SourceSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException { - Map source = (Map) c; - - BiomeSource.Type type = loader.loadClass(BiomeSource.Type.class, source.get("type")); - - if(type == BiomeSource.Type.NOISE) { - return loader.loadClass(NoiseSourceTemplate.class, source); - } - throw new LoadException("No such loader type: " + type); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java deleted file mode 100644 index 58c464fde..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.util.seeded.StageSeeded; -import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage; -import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.expander.ExpanderStageTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderListMutatorTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.ReplaceListMutatorTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.ReplaceMutatorTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.SmoothMutatorTemplate; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class StageBuilderLoader implements TypeLoader { - @Override - public StageSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException { - Map raw = (Map) c; - - if(raw.size() != 1) throw new LoadException("Illegal stage map size: " + raw.size()); - - Map.Entry entry = null; - - for(Map.Entry e : raw.entrySet()) { - entry = e; - } - - Map mutator = (Map) entry.getValue(); - - if(entry.getKey().equals("expand")) { - ExpanderStage.Type stageType = loader.loadClass(ExpanderStage.Type.class, mutator.get("type")); - if(stageType.equals(ExpanderStage.Type.FRACTAL)) { - return loader.loadClass(ExpanderStageTemplate.class, mutator); - } else throw new LoadException("No such expander \"" + stageType + "\""); - } else if(entry.getKey().equals("mutate")) { - switch(loader.loadClass(MutatorStage.Type.class, mutator.get("type"))) { - case SMOOTH: - return loader.loadClass(SmoothMutatorTemplate.class, mutator); - case REPLACE: - return loader.loadClass(ReplaceMutatorTemplate.class, mutator); - case REPLACE_LIST: - return loader.loadClass(ReplaceListMutatorTemplate.class, mutator); - case BORDER: - return loader.loadClass(BorderMutatorTemplate.class, mutator); - case BORDER_LIST: - return loader.loadClass(BorderListMutatorTemplate.class, mutator); - default: - throw new LoadException("No such mutator type \"" + mutator.get("type")); - } - } - throw new LoadException("No such mutator \"" + entry.getKey() + "\""); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomePipelineTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomePipelineTemplate.java deleted file mode 100644 index 31f448553..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomePipelineTemplate.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.provider; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.util.seeded.SourceSeeded; -import com.dfsek.terra.api.util.seeded.StageSeeded; -import com.dfsek.terra.api.world.biome.pipeline.BiomePipeline; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.biome.provider.StandardBiomeProvider; - -import java.util.List; - -@SuppressWarnings({"FieldMayBeFinal", "unused"}) -public class BiomePipelineTemplate extends BiomeProviderTemplate { - private final TerraPlugin main; - @Value("pipeline.initial-size") - @Default - private int initialSize = 2; - - @Value("pipeline.stages") - private List stages; - - @Value("pipeline.source") - private SourceSeeded source; - - public BiomePipelineTemplate(TerraPlugin main) { - this.main = main; - } - - @Override - public BiomeProvider build(long seed) { - BiomePipeline.BiomePipelineBuilder biomePipelineBuilder = new BiomePipeline.BiomePipelineBuilder(initialSize); - stages.forEach(biomePipelineBuilder::addStage); - BiomePipeline pipeline = biomePipelineBuilder.build(source.apply(seed), seed); - return new StandardBiomeProvider(pipeline, main, resolution, blend.apply(seed), blendAmp, (int) seed); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomeProviderTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomeProviderTemplate.java deleted file mode 100644 index 2b0799b87..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/BiomeProviderTemplate.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.provider; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.loading.object.ObjectTemplate; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; - -public abstract class BiomeProviderTemplate implements ObjectTemplate, BiomeProvider.BiomeProviderBuilder { - @Value("resolution") - @Default - protected int resolution = 1; - @Value("blend.noise") - @Default - protected NoiseSeeded blend = new NoiseSeeded() { - @Override - public NoiseSampler apply(Long seed) { - return new ConstantSampler(0); - } - - @Override - public int getDimensions() { - return 2; - } - }; - @Value("blend.amplitude") - @Default - protected double blendAmp = 0d; - @Value("type") - BiomeProvider.Type type; - - @Override - public BiomeProvider.BiomeProviderBuilder get() { - return this; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/ImageProviderTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/ImageProviderTemplate.java deleted file mode 100644 index b66e25cba..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/ImageProviderTemplate.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.provider; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.registry.Registry; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.biome.provider.ImageBiomeProvider; -import com.dfsek.terra.config.builder.BiomeBuilder; - -import java.awt.image.BufferedImage; -import java.util.stream.Collectors; - -public class ImageProviderTemplate extends BiomeProviderTemplate { - private final Registry biomes; - @Value("image.name") - private BufferedImage image; - - @Value("image.align") - private ImageBiomeProvider.Align align; - - public ImageProviderTemplate(Registry set) { - this.biomes = set; - } - - @Override - public BiomeProvider build(long seed) { - return new ImageBiomeProvider(biomes.entries().stream().map(biomeBuilder -> biomeBuilder.apply(seed)).collect(Collectors.toSet()), image, resolution, align); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/SingleBiomeProviderTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/SingleBiomeProviderTemplate.java deleted file mode 100644 index 525315454..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/provider/SingleBiomeProviderTemplate.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.provider; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.biome.provider.SingleBiomeProvider; -import com.dfsek.terra.config.builder.BiomeBuilder; - -public class SingleBiomeProviderTemplate extends BiomeProviderTemplate { - @Value("biome") - private BiomeBuilder biome; - - public SingleBiomeProviderTemplate() { - } - - @Override - public BiomeProvider build(long seed) { - return new SingleBiomeProvider(biome.apply(seed)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/NoiseSourceTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/NoiseSourceTemplate.java deleted file mode 100644 index 7df6255d0..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/NoiseSourceTemplate.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.source; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; -import com.dfsek.terra.api.world.biome.pipeline.source.RandomSource; -import com.dfsek.terra.config.builder.BiomeBuilder; - -public class NoiseSourceTemplate extends SourceTemplate { - @Value("noise") - private NoiseSeeded noise; - - @Value("biomes") - private ProbabilityCollection biomes; - - @Override - public BiomeSource apply(Long seed) { - return new RandomSource(biomes.map((biome) -> biome.apply(seed), false), noise.apply(seed)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SourceTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SourceTemplate.java deleted file mode 100644 index cee30713b..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SourceTemplate.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.source; - -import com.dfsek.tectonic.loading.object.ObjectTemplate; -import com.dfsek.terra.api.util.seeded.SourceSeeded; -import com.dfsek.terra.api.world.biome.pipeline.source.BiomeSource; - -public abstract class SourceTemplate implements ObjectTemplate, SourceSeeded { - @Override - public SourceSeeded get() { - return this; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java deleted file mode 100644 index 151eaedef..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.stage; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.loading.object.ObjectTemplate; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.util.seeded.SeededBuilder; -import com.dfsek.terra.api.util.seeded.StageSeeded; -import com.dfsek.terra.api.world.biome.pipeline.stages.Stage; - -public abstract class StageTemplate implements ObjectTemplate>, StageSeeded { - @Value("noise") - protected NoiseSeeded noise; - - @Override - public StageSeeded get() { - return this; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/expander/ExpanderStageTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/expander/ExpanderStageTemplate.java deleted file mode 100644 index fb396ddbc..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/expander/ExpanderStageTemplate.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.stage.expander; - -import com.dfsek.terra.api.world.biome.pipeline.expand.FractalExpander; -import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage; -import com.dfsek.terra.api.world.biome.pipeline.stages.Stage; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.StageTemplate; - -public class ExpanderStageTemplate extends StageTemplate { - @Override - public Stage apply(Long seed) { - return new ExpanderStage(new FractalExpander(noise.apply(seed))); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java deleted file mode 100644 index 76146a088..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderListMutatorTemplate.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderListMutator; -import com.dfsek.terra.config.builder.BiomeBuilder; - -import java.util.HashMap; -import java.util.Map; - -@SuppressWarnings("unused") -public class BorderListMutatorTemplate extends MutatorStageTemplate { - @Value("from") - private String from; - - @Value("default-replace") - private String defaultReplace; - - @Value("default-to") - private ProbabilityCollection defaultTo; - - @Value("replace") - private Map> replace; - - - @Override - public BiomeMutator build(long seed) { - Map> replaceMap = new HashMap<>(); - - replace.forEach((keyBuilder, replacements) -> replaceMap.put(keyBuilder.apply(seed), replacements.map(replacement -> replacement.apply(seed), true))); - - return new BorderListMutator(replaceMap, from, defaultReplace, noise.apply(seed), defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderMutatorTemplate.java deleted file mode 100644 index 5502a412f..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/BorderMutatorTemplate.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderMutator; -import com.dfsek.terra.config.builder.BiomeBuilder; - -@SuppressWarnings("unused") -public class BorderMutatorTemplate extends MutatorStageTemplate { - @Value("from") - private String from; - - @Value("replace") - private String replace; - - @Value("to") - private ProbabilityCollection to; - - @Override - public BiomeMutator build(long seed) { - return new BorderMutator(from, replace, noise.apply(seed), to.map(biomeBuilder -> biomeBuilder.apply(seed), true)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/MutatorStageTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/MutatorStageTemplate.java deleted file mode 100644 index 84283ffcc..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/MutatorStageTemplate.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; - -import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage; -import com.dfsek.terra.api.world.biome.pipeline.stages.Stage; -import com.dfsek.terra.config.loaders.config.biome.templates.stage.StageTemplate; - -public abstract class MutatorStageTemplate extends StageTemplate { - public abstract BiomeMutator build(long seed); - - @Override - public Stage apply(Long seed) { - return new MutatorStage(build(seed)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceListMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceListMutatorTemplate.java deleted file mode 100644 index d40eec7b4..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceListMutatorTemplate.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceListMutator; -import com.dfsek.terra.config.builder.BiomeBuilder; - -import java.util.HashMap; -import java.util.Map; - -@SuppressWarnings("unused") -public class ReplaceListMutatorTemplate extends MutatorStageTemplate { - @Value("default-from") - private String defaultFrom; - - @Value("default-to") - private ProbabilityCollection defaultTo; - - @Value("to") - private Map> replace; - - @Override - public BiomeMutator build(long seed) { - Map> replaceMap = new HashMap<>(); - - replace.forEach((biomeBuilder, biomeBuilders) -> replaceMap.put(biomeBuilder.apply(seed), biomeBuilders.map(builder -> builder.apply(seed), true))); - - return new ReplaceListMutator(replaceMap, defaultFrom, defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceMutatorTemplate.java deleted file mode 100644 index fbe801fbf..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/ReplaceMutatorTemplate.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceMutator; -import com.dfsek.terra.config.builder.BiomeBuilder; - -@SuppressWarnings("unused") -public class ReplaceMutatorTemplate extends MutatorStageTemplate { - @Value("from") - private String from; - - @Value("to") - private ProbabilityCollection to; - - @Override - public BiomeMutator build(long seed) { - return new ReplaceMutator(from, to.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/SmoothMutatorTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/SmoothMutatorTemplate.java deleted file mode 100644 index a5c27c54a..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/mutator/SmoothMutatorTemplate.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator; - -import com.dfsek.terra.api.world.biome.pipeline.mutator.BiomeMutator; -import com.dfsek.terra.api.world.biome.pipeline.mutator.SmoothMutator; - -public class SmoothMutatorTemplate extends MutatorStageTemplate { - @Override - public BiomeMutator build(long seed) { - return new SmoothMutator(noise.apply(seed)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/function/FunctionTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/function/FunctionTemplate.java deleted file mode 100644 index 640dd1999..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/function/FunctionTemplate.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dfsek.terra.config.loaders.config.function; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.loading.object.ObjectTemplate; - -import java.util.List; - -@SuppressWarnings("unused") -public class FunctionTemplate implements ObjectTemplate { - @Value("arguments") - private List args; - - @Value("function") - private String function; - - public List getArgs() { - return args; - } - - public String getFunction() { - return function; - } - - @Override - public FunctionTemplate get() { - return this; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java deleted file mode 100644 index 65ebf9d38..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler; - -import com.dfsek.tectonic.config.Configuration; -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.tectonic.loading.object.ObjectTemplate; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.registry.config.NoiseRegistry; - -import java.lang.reflect.Type; -import java.util.Locale; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class NoiseSamplerBuilderLoader implements TypeLoader { - private final NoiseRegistry noiseRegistry; - - public NoiseSamplerBuilderLoader(NoiseRegistry noiseRegistry) { - this.noiseRegistry = noiseRegistry; - } - - @Override - public NoiseSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException { - Map map = (Map) c; - try { - ObjectTemplate normalizerTemplate = noiseRegistry.get(((String) map.get("type")).toUpperCase(Locale.ROOT)).get(); - loader.load(normalizerTemplate, new Configuration(map)); - return normalizerTemplate.get(); - } catch(ConfigException e) { - throw new LoadException("Unable to load noise function: ", e); - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/DomainWarpTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/DomainWarpTemplate.java deleted file mode 100644 index 3607c17e9..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/DomainWarpTemplate.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.DomainWarpedSampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class DomainWarpTemplate extends SamplerTemplate { - @Value("warp") - private NoiseSeeded warp; - - @Value("function") - private NoiseSeeded function; - - @Value("salt") - @Default - private int salt = 0; - - @Value("amplitude") - @Default - private double amplitude = 1; - - @Override - public NoiseSampler apply(Long seed) { - return new DomainWarpedSampler(function.apply(seed), warp.apply(seed), (int) (seed + salt), amplitude); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/ImageSamplerTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/ImageSamplerTemplate.java deleted file mode 100644 index db2ced46e..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/ImageSamplerTemplate.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.ImageSampler; - -import java.awt.image.BufferedImage; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class ImageSamplerTemplate extends SamplerTemplate { - - @Value("image") - private BufferedImage image; - - @Value("frequency") - private double frequency; - - @Value("channel") - private ImageSampler.Channel channel; - - @Override - public NoiseSampler apply(Long seed) { - return new ImageSampler(image, channel, frequency); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/SamplerTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/SamplerTemplate.java deleted file mode 100644 index 7914ec957..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/SamplerTemplate.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ValidatedConfigTemplate; -import com.dfsek.tectonic.exception.ValidationException; -import com.dfsek.tectonic.loading.object.ObjectTemplate; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; - -@SuppressWarnings("FieldMayBeFinal") -public abstract class SamplerTemplate implements ValidatedConfigTemplate, ObjectTemplate, NoiseSeeded { - @Value("dimensions") - @Default - private int dimensions = 2; - - public int getDimensions() { - return dimensions; - } - - @Override - public boolean validate() throws ValidationException { - if(dimensions != 2 && dimensions != 3) throw new ValidationException("Illegal amount of dimensions: " + dimensions); - return true; - } - - @Override - public NoiseSeeded get() { - return this; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/CellularNoiseTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/CellularNoiseTemplate.java deleted file mode 100644 index 90a53d277..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/CellularNoiseTemplate.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.noise; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.CellularSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; - -@SuppressWarnings("FieldMayBeFinal") -public class CellularNoiseTemplate extends NoiseTemplate { - @Value("distance") - @Default - private CellularSampler.DistanceFunction cellularDistanceFunction = CellularSampler.DistanceFunction.EuclideanSq; - - @Value("return") - @Default - private CellularSampler.ReturnType cellularReturnType = CellularSampler.ReturnType.Distance; - - @Value("jitter") - @Default - private double cellularJitter = 1.0D; - - - @Value("lookup") - @Default - private NoiseSeeded lookup = new NoiseSeeded() { - @Override - public NoiseSampler apply(Long seed) { - - return new OpenSimplex2Sampler((int) (long) seed); - } - - @Override - public int getDimensions() { - return 2; - } - }; - - @Override - public NoiseSampler apply(Long seed) { - CellularSampler sampler = new CellularSampler((int) (long) seed + salt); - sampler.setNoiseLookup(lookup.apply(seed)); - sampler.setFrequency(frequency); - sampler.setJitterModifier(cellularJitter); - sampler.setReturnType(cellularReturnType); - sampler.setDistanceFunction(cellularDistanceFunction); - return sampler; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ConstantNoiseTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ConstantNoiseTemplate.java deleted file mode 100644 index ba4aa14a4..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ConstantNoiseTemplate.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.noise; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler; -import com.dfsek.terra.config.loaders.config.sampler.templates.SamplerTemplate; - -@SuppressWarnings("FieldMayBeFinal") -public class ConstantNoiseTemplate extends SamplerTemplate { - @Value("value") - @Default - private double value = 0d; - - @Override - public NoiseSampler apply(Long seed) { - return new ConstantSampler(value); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java deleted file mode 100644 index 90926aea6..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/ExpressionFunctionTemplate.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.noise; - -import com.dfsek.paralithic.eval.parser.Parser; -import com.dfsek.paralithic.eval.parser.Scope; -import com.dfsek.paralithic.eval.tokenizer.ParseException; -import com.dfsek.paralithic.functions.Function; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ValidatedConfigTemplate; -import com.dfsek.tectonic.exception.ValidationException; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.ExpressionFunction; -import com.dfsek.terra.api.math.paralithic.BlankFunction; -import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction; -import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction2; -import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction3; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.SamplerTemplate; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; - - -@SuppressWarnings({"FieldMayBeFinal", "unused"}) -public class ExpressionFunctionTemplate extends SamplerTemplate implements ValidatedConfigTemplate { - @Value("variables") - @Default - private Map vars = new HashMap<>(); - - @Value("equation") - private String equation; - - @Value("functions") - @Default - private LinkedHashMap functions = new LinkedHashMap<>(); - - @Value("expressions") - @Default - private LinkedHashMap expressions = new LinkedHashMap<>(); - - @Override - public NoiseSampler apply(Long seed) { - try { - Map noiseFunctionMap = generateFunctions(seed); - return new ExpressionFunction(noiseFunctionMap, equation, vars); - } catch(ParseException e) { - throw new IllegalStateException(e); - } - } - - @Override - public boolean validate() throws ValidationException { - try { - Map noiseFunctionMap = generateFunctions(0L); - new ExpressionFunction(noiseFunctionMap, equation, vars); - } catch(ParseException e) { - throw new ValidationException("Errors occurred while parsing noise equation: ", e); - } - return super.validate(); - } - - private Map generateFunctions(Long seed) throws ParseException { - Map noiseFunctionMap = new HashMap<>(); - - for(Map.Entry entry : expressions.entrySet()) { - noiseFunctionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), new Parser(), new Scope())); - } - - functions.forEach((id, function) -> { - if(function.getDimensions() == 2) { - noiseFunctionMap.put(id, new NoiseFunction2(function.apply(seed))); - } else noiseFunctionMap.put(id, new NoiseFunction3(function.apply(seed))); - }); - - return noiseFunctionMap; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/GaborNoiseTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/GaborNoiseTemplate.java deleted file mode 100644 index b15aa75cd..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/GaborNoiseTemplate.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.noise; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.GaborNoiseSampler; - -public class GaborNoiseTemplate extends NoiseTemplate { - @Value("rotation") - @Default - private double rotation = 0.25; - - @Value("isotropic") - @Default - private boolean isotropic = true; - - @Value("deviation") - @Default - private double deviation = 1.0; - - @Value("impulses") - @Default - private double impulses = 64d; - - @Value("frequency_0") - @Default - private double f0 = 0.625; - - @Override - public NoiseSampler apply(Long seed) { - GaborNoiseSampler gaborNoiseSampler = new GaborNoiseSampler((int) (long) seed + salt); - gaborNoiseSampler.setFrequency(frequency); - gaborNoiseSampler.setRotation(rotation); - gaborNoiseSampler.setIsotropic(isotropic); - gaborNoiseSampler.setDeviation(deviation); - gaborNoiseSampler.setImpulsesPerKernel(impulses); - gaborNoiseSampler.setFrequency0(f0); - return gaborNoiseSampler; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/NoiseTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/NoiseTemplate.java deleted file mode 100644 index 9fb123865..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/NoiseTemplate.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.noise; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction; -import com.dfsek.terra.config.loaders.config.sampler.templates.SamplerTemplate; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public abstract class NoiseTemplate extends SamplerTemplate { - @Value("frequency") - @Default - protected double frequency = 0.02d; - - @Value("salt") - @Default - protected int salt = 0; -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/SimpleNoiseTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/SimpleNoiseTemplate.java deleted file mode 100644 index 9c1ab1cb2..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/SimpleNoiseTemplate.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.noise; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.NoiseFunction; - -import java.util.function.Function; - -public class SimpleNoiseTemplate extends NoiseTemplate { - private final Function samplerSupplier; - - public SimpleNoiseTemplate(Function samplerSupplier) { - this.samplerSupplier = samplerSupplier; - } - - @Override - public NoiseSampler apply(Long seed) { - NoiseFunction sampler = samplerSupplier.apply((int) (long) seed + salt); - sampler.setFrequency(frequency); - return sampler; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/BrownianMotionTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/BrownianMotionTemplate.java deleted file mode 100644 index 155822003..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/BrownianMotionTemplate.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.fractal.BrownianMotionSampler; - -public class BrownianMotionTemplate extends FractalTemplate { - @Override - public NoiseSampler apply(Long seed) { - BrownianMotionSampler sampler = new BrownianMotionSampler((int) (long) seed, function.apply(seed)); - sampler.setGain(fractalGain); - sampler.setLacunarity(fractalLacunarity); - sampler.setOctaves(octaves); - sampler.setWeightedStrength(weightedStrength); - return sampler; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/FractalTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/FractalTemplate.java deleted file mode 100644 index 5a1bb3602..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/FractalTemplate.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.samplers.noise.fractal.FractalNoiseFunction; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.config.loaders.config.sampler.templates.SamplerTemplate; - -public abstract class FractalTemplate extends SamplerTemplate { - @Value("octaves") - @Default - protected int octaves = 3; - - @Value("gain") - @Default - protected double fractalGain = 0.5D; - - @Value("lacunarity") - @Default - protected double fractalLacunarity = 2.0D; - - @Value("weighted-strength") - @Default - protected double weightedStrength = 0.0D; - - @Value("function") - protected NoiseSeeded function; -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/PingPongTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/PingPongTemplate.java deleted file mode 100644 index b0319155e..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/PingPongTemplate.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.fractal.PingPongSampler; -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class PingPongTemplate extends FractalTemplate { - @Value("ping-pong") - @Default - private double pingPong = 2.0D; - - @Override - public NoiseSampler apply(Long seed) { - PingPongSampler sampler = new PingPongSampler((int) (long) seed, function.apply(seed)); - sampler.setGain(fractalGain); - sampler.setLacunarity(fractalLacunarity); - sampler.setOctaves(octaves); - sampler.setWeightedStrength(weightedStrength); - sampler.setPingPongStrength(pingPong); - return sampler; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/RidgedFractalTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/RidgedFractalTemplate.java deleted file mode 100644 index d74b34e91..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/noise/fractal/RidgedFractalTemplate.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.fractal.RidgedFractalSampler; - -public class RidgedFractalTemplate extends FractalTemplate { - @Override - public NoiseSampler apply(Long seed) { - RidgedFractalSampler sampler = new RidgedFractalSampler((int) (long) seed, function.apply(seed)); - sampler.setGain(fractalGain); - sampler.setLacunarity(fractalLacunarity); - sampler.setOctaves(octaves); - sampler.setWeightedStrength(weightedStrength); - return sampler; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/ClampNormalizerTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/ClampNormalizerTemplate.java deleted file mode 100644 index 1701e8223..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/ClampNormalizerTemplate.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.normalizer; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.normalizer.ClampNormalizer; -import com.dfsek.terra.api.math.noise.normalizer.LinearNormalizer; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class ClampNormalizerTemplate extends NormalizerTemplate { - @Value("max") - private double max; - - @Value("min") - private double min; - - @Override - public NoiseSampler apply(Long seed) { - return new ClampNormalizer(function.apply(seed), min, max); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/LinearNormalizerTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/LinearNormalizerTemplate.java deleted file mode 100644 index 42b7cb2f8..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/LinearNormalizerTemplate.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.normalizer; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.normalizer.LinearNormalizer; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class LinearNormalizerTemplate extends NormalizerTemplate { - @Value("max") - private double max; - - @Value("min") - private double min; - - @Override - public NoiseSampler apply(Long seed) { - return new LinearNormalizer(function.apply(seed), min, max); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/NormalNormalizerTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/NormalNormalizerTemplate.java deleted file mode 100644 index cdc9cc48f..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/NormalNormalizerTemplate.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.normalizer; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.normalizer.NormalNormalizer; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class NormalNormalizerTemplate extends NormalizerTemplate { - @Value("mean") - private double mean; - - @Value("standard-deviation") - private double stdDev; - - @Value("groups") - @Default - private int groups = 16384; - - @Override - public NoiseSampler apply(Long seed) { - return new NormalNormalizer(function.apply(seed), groups, mean, stdDev); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/NormalizerTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/NormalizerTemplate.java deleted file mode 100644 index 35ad8c7fe..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/NormalizerTemplate.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.config.loaders.config.sampler.templates.normalizer; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.normalizer.Normalizer; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.config.loaders.config.sampler.templates.SamplerTemplate; - -public abstract class NormalizerTemplate extends SamplerTemplate { - @Value("function") - protected NoiseSeeded function; -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java deleted file mode 100644 index 696683dd5..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/palette/CarverPaletteLoader.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dfsek.terra.config.loaders.palette; - -import com.dfsek.tectonic.config.Configuration; -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.carving.CarverPalette; -import com.dfsek.terra.config.loaders.Types; - -import java.lang.reflect.Type; -import java.util.List; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class CarverPaletteLoader implements TypeLoader { - - - @Override - public CarverPalette load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - Configuration configuration = new Configuration((Map) o); - CarverPalette palette = new CarverPalette((MaterialSet) configLoader.loadType(MaterialSet.class, configuration.get("replace")), (Boolean) configuration.get("replace-blacklist")); - - for(Map map : (List>) configuration.get("layers")) { - ProbabilityCollection layer = (ProbabilityCollection) configLoader.loadType(Types.BLOCK_DATA_PROBABILITY_COLLECTION_TYPE, map.get("materials")); - palette.add(layer, (Integer) map.get("y")); - } - palette.build(); - return palette; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteHolderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteHolderLoader.java deleted file mode 100644 index a0e7929e0..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteHolderLoader.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.config.loaders.palette; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.api.world.palette.holder.PaletteHolder; -import com.dfsek.terra.api.world.palette.holder.PaletteHolderBuilder; -import com.dfsek.terra.config.loaders.Types; - -import java.lang.reflect.Type; -import java.util.List; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class PaletteHolderLoader implements TypeLoader { - @Override - public PaletteHolder load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - List> palette = (List>) o; - PaletteHolderBuilder builder = new PaletteHolderBuilder(); - for(Map layer : palette) { - for(Map.Entry entry : layer.entrySet()) { - builder.add(entry.getValue(), (Palette) configLoader.loadType(Types.BLOCK_DATA_PALETTE_TYPE, entry.getKey())); - } - } - return builder.build(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java deleted file mode 100644 index 01a30a2e2..000000000 --- a/common/src/main/java/com/dfsek/terra/config/loaders/palette/PaletteLayerLoader.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.config.loaders.palette; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; -import com.dfsek.terra.config.loaders.Types; - -import java.lang.reflect.Type; -import java.util.Map; - -@SuppressWarnings("unchecked") -public class PaletteLayerLoader implements TypeLoader { - @Override - public PaletteLayerHolder load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - Map map = (Map) o; - ProbabilityCollection collection = (ProbabilityCollection) configLoader.loadType(Types.BLOCK_DATA_PROBABILITY_COLLECTION_TYPE, map.get("materials")); - - NoiseSampler sampler = null; - if(map.containsKey("noise")) { - sampler = configLoader.loadClass(NoiseSeeded.class, map.get("noise")).apply(2403L); - } - - if(collection == null) throw new LoadException("Collection is null: " + map.get("materials")); - return new PaletteLayerHolder(collection, sampler, (Integer) map.get("layers")); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java deleted file mode 100644 index 871b4ebe3..000000000 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java +++ /dev/null @@ -1,356 +0,0 @@ -package com.dfsek.terra.config.pack; - -import com.dfsek.paralithic.eval.parser.Scope; -import com.dfsek.tectonic.abstraction.AbstractConfigLoader; -import com.dfsek.tectonic.config.Configuration; -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.tectonic.loading.object.ObjectTemplate; -import com.dfsek.terra.api.LoaderRegistrar; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.event.events.config.ConfigPackPostLoadEvent; -import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.registry.CheckedRegistry; -import com.dfsek.terra.api.structures.loot.LootTable; -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.flora.Flora; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.carving.UserDefinedCarver; -import com.dfsek.terra.config.builder.BiomeBuilder; -import com.dfsek.terra.config.dummy.DummyWorld; -import com.dfsek.terra.config.factories.BiomeFactory; -import com.dfsek.terra.config.factories.CarverFactory; -import com.dfsek.terra.config.factories.ConfigFactory; -import com.dfsek.terra.config.factories.FloraFactory; -import com.dfsek.terra.config.factories.OreFactory; -import com.dfsek.terra.config.factories.PaletteFactory; -import com.dfsek.terra.config.factories.StructureFactory; -import com.dfsek.terra.config.factories.TreeFactory; -import com.dfsek.terra.config.fileloaders.FolderLoader; -import com.dfsek.terra.config.fileloaders.Loader; -import com.dfsek.terra.config.fileloaders.ZIPLoader; -import com.dfsek.terra.config.loaders.config.BufferedImageLoader; -import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate; -import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; -import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; -import com.dfsek.terra.config.templates.AbstractableTemplate; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.config.templates.CarverTemplate; -import com.dfsek.terra.config.templates.FloraTemplate; -import com.dfsek.terra.config.templates.OreTemplate; -import com.dfsek.terra.config.templates.PaletteTemplate; -import com.dfsek.terra.config.templates.StructureTemplate; -import com.dfsek.terra.config.templates.TreeTemplate; -import com.dfsek.terra.registry.OpenRegistry; -import com.dfsek.terra.registry.config.BiomeRegistry; -import com.dfsek.terra.registry.config.CarverRegistry; -import com.dfsek.terra.registry.config.FloraRegistry; -import com.dfsek.terra.registry.config.FunctionRegistry; -import com.dfsek.terra.registry.config.LootRegistry; -import com.dfsek.terra.registry.config.NoiseRegistry; -import com.dfsek.terra.registry.config.OreRegistry; -import com.dfsek.terra.registry.config.PaletteRegistry; -import com.dfsek.terra.registry.config.ScriptRegistry; -import com.dfsek.terra.registry.config.StructureRegistry; -import com.dfsek.terra.registry.config.TreeRegistry; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.population.items.TerraStructure; -import com.dfsek.terra.world.population.items.ores.Ore; -import org.apache.commons.io.IOUtils; -import org.json.simple.parser.ParseException; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.Enumeration; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * Represents a Terra configuration pack. - */ -public class ConfigPack implements LoaderRegistrar { - private final ConfigPackTemplate template = new ConfigPackTemplate(); - - private final BiomeRegistry biomeRegistry = new BiomeRegistry(); - private final StructureRegistry structureRegistry = new StructureRegistry(); - private final PaletteRegistry paletteRegistry; - private final FloraRegistry floraRegistry; - private final OreRegistry oreRegistry = new OreRegistry(); - private final TreeRegistry treeRegistry; - private final ScriptRegistry scriptRegistry = new ScriptRegistry(); - private final LootRegistry lootRegistry = new LootRegistry(); - - private final CarverRegistry carverRegistry = new CarverRegistry(); - - private final NoiseRegistry noiseRegistry = new NoiseRegistry(); - private final FunctionRegistry functionRegistry = new FunctionRegistry(); - - private final AbstractConfigLoader abstractConfigLoader = new AbstractConfigLoader(); - private final ConfigLoader selfLoader = new ConfigLoader(); - private final Scope varScope = new Scope(); - - private final TerraPlugin main; - private final Loader loader; - - private final Configuration configuration; - - private final BiomeProvider.BiomeProviderBuilder biomeProviderBuilder; - - - public ConfigPack(File folder, TerraPlugin main) throws ConfigException { - try { - this.loader = new FolderLoader(folder.toPath()); - this.main = main; - long l = System.nanoTime(); - floraRegistry = new FloraRegistry(main); - paletteRegistry = new PaletteRegistry(main); - treeRegistry = new TreeRegistry(); - register(abstractConfigLoader); - register(selfLoader); - - main.register(selfLoader); - main.register(abstractConfigLoader); - - File pack = new File(folder, "pack.yml"); - - try { - configuration = new Configuration(new FileInputStream(pack)); - selfLoader.load(template, configuration); - - main.logger().info("Loading config pack \"" + template.getID() + "\""); - - main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, configuration))); - - load(l, main); - - ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate(); - selfLoader.load(packPostTemplate, new FileInputStream(pack)); - biomeProviderBuilder = packPostTemplate.getProviderBuilder(); - biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time. - checkDeadEntries(main); - } catch(FileNotFoundException e) { - throw new LoadException("No pack.yml file found in " + folder.getAbsolutePath(), e); - } - } catch(Exception e) { - main.logger().severe("Failed to load config pack from folder \"" + folder.getAbsolutePath() + "\""); - throw e; - } - toWorldConfig(new TerraWorld(new DummyWorld(), this, main)); // Build now to catch any errors immediately. - } - - public ConfigPack(ZipFile file, TerraPlugin main) throws ConfigException { - try { - this.loader = new ZIPLoader(file); - this.main = main; - long l = System.nanoTime(); - floraRegistry = new FloraRegistry(main); - paletteRegistry = new PaletteRegistry(main); - treeRegistry = new TreeRegistry(); - register(abstractConfigLoader); - register(selfLoader); - - main.register(selfLoader); - main.register(abstractConfigLoader); - - try { - ZipEntry pack = null; - Enumeration entries = file.entries(); - while(entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if(entry.getName().equals("pack.yml")) pack = entry; - } - - if(pack == null) throw new LoadException("No pack.yml file found in " + file.getName()); - - configuration = new Configuration(file.getInputStream(pack)); - selfLoader.load(template, configuration); - main.logger().info("Loading config pack \"" + template.getID() + "\""); - - main.getEventManager().callEvent(new ConfigPackPreLoadEvent(this, template -> selfLoader.load(template, configuration))); - - load(l, main); - - ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate(); - - selfLoader.load(packPostTemplate, file.getInputStream(pack)); - biomeProviderBuilder = packPostTemplate.getProviderBuilder(); - biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time. - checkDeadEntries(main); - } catch(IOException e) { - throw new LoadException("Unable to load pack.yml from ZIP file", e); - } - } catch(Exception e) { - main.logger().severe("Failed to load config pack from ZIP archive \"" + file.getName() + "\""); - throw e; - } - - toWorldConfig(new TerraWorld(new DummyWorld(), this, main)); // Build now to catch any errors immediately. - } - - public static void buildAll(ConfigFactory factory, OpenRegistry registry, List configTemplates, TerraPlugin main) throws LoadException { - for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main)); - } - - private void checkDeadEntries(TerraPlugin main) { - biomeRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in biome registry: '" + id + "'")); - paletteRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in palette registry: '" + id + "'")); - floraRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in flora registry: '" + id + "'")); - carverRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in carver registry: '" + id + "'")); - treeRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in tree registry: '" + id + "'")); - oreRegistry.getDeadEntries().forEach((id, value) -> main.getDebugLogger().warn("Dead entry in ore registry: '" + id + "'")); - } - - - private void load(long start, TerraPlugin main) throws ConfigException { - for(Map.Entry var : template.getVariables().entrySet()) { - varScope.create(var.getKey(), var.getValue()); - } - - loader.open("structures/data", ".tesf").thenEntries(entries -> { - for(Map.Entry entry : entries) { - try(InputStream stream = entry.getValue()) { - StructureScript structureScript = new StructureScript(stream, main, scriptRegistry, lootRegistry, functionRegistry); - scriptRegistry.add(structureScript.getId(), structureScript); - } catch(com.dfsek.terra.api.structures.parser.exceptions.ParseException | IOException e) { - throw new LoadException("Unable to load script \"" + entry.getKey() + "\"", e); - } - } - }).close().open("structures/loot", ".json").thenEntries(entries -> { - for(Map.Entry entry : entries) { - try { - lootRegistry.add(entry.getKey(), new LootTable(IOUtils.toString(entry.getValue(), StandardCharsets.UTF_8), main)); - } catch(ParseException | IOException | NullPointerException e) { - throw new LoadException("Unable to load loot table \"" + entry.getKey() + "\"", e); - } - } - }).close(); - - loader - .open("carving", ".yml").then(configs -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.loadConfigs(configs, CarverTemplate::new), main)).close() - .open("palettes", ".yml").then(configs -> buildAll(new PaletteFactory(), paletteRegistry, abstractConfigLoader.loadConfigs(configs, PaletteTemplate::new), main)).close() - .open("ores", ".yml").then(configs -> buildAll(new OreFactory(), oreRegistry, abstractConfigLoader.loadConfigs(configs, OreTemplate::new), main)).close() - .open("structures/trees", ".yml").then(configs -> buildAll(new TreeFactory(), treeRegistry, abstractConfigLoader.loadConfigs(configs, TreeTemplate::new), main)).close() - .open("structures/structures", ".yml").then(configs -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.loadConfigs(configs, StructureTemplate::new), main)).close() - .open("flora", ".yml").then(configs -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.loadConfigs(configs, FloraTemplate::new), main)).close() - .open("biomes", ".yml").then(configs -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.loadConfigs(configs, () -> new BiomeTemplate(this, main)), main)).close(); - - main.getEventManager().callEvent(new ConfigPackPostLoadEvent(this, template -> selfLoader.load(template, configuration))); - main.logger().info("Loaded config pack \"" + template.getID() + "\" v" + template.getVersion() + " by " + template.getAuthor() + " in " + (System.nanoTime() - start) / 1000000D + "ms."); - } - - public TerraStructure getStructure(String id) { - return structureRegistry.get(id); - } - - public Set getStructures() { - return structureRegistry.entries(); - } - - public List getStructureIDs() { - return structureRegistry.entries().stream().map(terraStructure -> terraStructure.getTemplate().getID()).collect(Collectors.toList()); - } - - public ConfigPackTemplate getTemplate() { - return template; - } - - public Scope getVarScope() { - return varScope; - } - - - @Override - public void register(TypeRegistry registry) { - registry - .registerLoader(Palette.class, paletteRegistry) - .registerLoader(BiomeBuilder.class, biomeRegistry) - .registerLoader(Flora.class, floraRegistry) - .registerLoader(Ore.class, oreRegistry) - .registerLoader(Tree.class, treeRegistry) - .registerLoader(StructureScript.class, scriptRegistry) - .registerLoader(TerraStructure.class, structureRegistry) - .registerLoader(LootTable.class, lootRegistry) - .registerLoader(UserDefinedCarver.class, carverRegistry) - .registerLoader(BufferedImage.class, new BufferedImageLoader(loader)) - .registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(noiseRegistry)) - .registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new) - .registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(main)) - .registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry)) - .registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(biomeRegistry)); - } - - public Set getCarvers() { - return carverRegistry.entries(); - } - - public BiomeProvider.BiomeProviderBuilder getBiomeProviderBuilder() { - return biomeProviderBuilder; - } - - public CheckedRegistry getScriptRegistry() { - return new CheckedRegistry<>(scriptRegistry); - } - - public CheckedRegistry getBiomeRegistry() { - return new CheckedRegistry<>(biomeRegistry); - } - - public CheckedRegistry getTreeRegistry() { - return new CheckedRegistry<>(treeRegistry); - } - - public CheckedRegistry> getFunctionRegistry() { - return new CheckedRegistry<>(functionRegistry); - } - - public CheckedRegistry>> getNormalizerRegistry() { - return new CheckedRegistry<>(noiseRegistry); - } - - public CheckedRegistry getCarverRegistry() { - return new CheckedRegistry<>(carverRegistry); - } - - public CheckedRegistry getFloraRegistry() { - return new CheckedRegistry<>(floraRegistry); - } - - public CheckedRegistry getLootRegistry() { - return new CheckedRegistry<>(lootRegistry); - } - - public CheckedRegistry getOreRegistry() { - return new CheckedRegistry<>(oreRegistry); - } - - public CheckedRegistry> getPaletteRegistry() { - return new CheckedRegistry<>(paletteRegistry); - } - - public CheckedRegistry getStructureRegistry() { - return new CheckedRegistry<>(structureRegistry); - } - - public WorldConfig toWorldConfig(TerraWorld world){ - return new WorldConfig(world, this, main); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java deleted file mode 100644 index dd24def46..000000000 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.config.pack; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; - -public class ConfigPackPostTemplate implements ConfigTemplate { - @Value("biomes") - private BiomeProvider.BiomeProviderBuilder providerBuilder; - - public BiomeProvider.BiomeProviderBuilder getProviderBuilder() { - return providerBuilder; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java deleted file mode 100644 index bfebcb717..000000000 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java +++ /dev/null @@ -1,175 +0,0 @@ -package com.dfsek.terra.config.pack; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class ConfigPackTemplate implements ConfigTemplate { - @Value("id") - private String id; - - @Value("noise") - private Map noiseBuilderMap; - - @Value("addons") - @Default - private Set addons = new HashSet<>(); - - @Value("variables") - @Default - private Map variables = new HashMap<>(); - - @Value("beta.carving") - @Default - private boolean betaCarvers = false; - - @Value("functions") - @Default - private LinkedHashMap functions = new LinkedHashMap<>(); - - @Value("structures.locatable") - @Default - private Map locatable = new HashMap<>(); - - @Value("blend.terrain.elevation") - @Default - private int elevationBlend = 4; - - @Value("vanilla.mobs") - @Default - private boolean vanillaMobs = true; - - @Value("vanilla.caves") - @Default - private boolean vanillaCaves = false; - - @Value("vanilla.decorations") - @Default - private boolean vanillaDecorations = false; - - @Value("vanilla.structures") - @Default - private boolean vanillaStructures = false; - - @Value("author") - @Default - private String author = "Anon Y. Mous"; - - @Value("disable.sapling") - @Default - private boolean disableSaplings = false; - - @Value("version") - @Default - private String version = "0.1.0"; - - @Value("disable.carvers") - @Default - private boolean disableCarvers = false; - - @Value("disable.structures") - @Default - private boolean disableStructures = false; - - @Value("disable.ores") - @Default - private boolean disableOres = false; - - @Value("disable.trees") - @Default - private boolean disableTrees = false; - - @Value("disable.flora") - @Default - private boolean disableFlora = false; - - public boolean disableCarvers() { - return disableCarvers; - } - - public boolean disableFlora() { - return disableFlora; - } - - public boolean disableOres() { - return disableOres; - } - - public boolean disableStructures() { - return disableStructures; - } - - public boolean disableTrees() { - return disableTrees; - } - - public LinkedHashMap getFunctions() { - return functions; - } - - public String getVersion() { - return version; - } - - public boolean isDisableSaplings() { - return disableSaplings; - } - - public String getID() { - return id; - } - - public String getAuthor() { - return author; - } - - public boolean vanillaMobs() { - return vanillaMobs; - } - - public boolean vanillaCaves() { - return vanillaCaves; - } - - public boolean vanillaDecorations() { - return vanillaDecorations; - } - - public boolean vanillaStructures() { - return vanillaStructures; - } - - public Map getNoiseBuilderMap() { - return noiseBuilderMap; - } - - public Map getVariables() { - return variables; - } - - public int getElevationBlend() { - return elevationBlend; - } - - public Map getLocatable() { - return locatable; - } - - public boolean doBetaCarvers() { - return betaCarvers; - } - - public Set getAddons() { - return addons; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/pack/WorldConfig.java b/common/src/main/java/com/dfsek/terra/config/pack/WorldConfig.java deleted file mode 100644 index 6ddc798ef..000000000 --- a/common/src/main/java/com/dfsek/terra/config/pack/WorldConfig.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.dfsek.terra.config.pack; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.registry.LockedRegistry; -import com.dfsek.terra.api.structures.loot.LootTable; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.flora.Flora; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.carving.UserDefinedCarver; -import com.dfsek.terra.registry.OpenRegistry; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.generation.math.SamplerCache; -import com.dfsek.terra.world.population.items.TerraStructure; -import com.dfsek.terra.world.population.items.ores.Ore; - -import java.util.Set; - -public class WorldConfig { - private final LockedRegistry scriptRegistry; - private final LockedRegistry biomeRegistry; - private final SamplerCache samplerCache; - private final LockedRegistry carverRegistry; - private final LockedRegistry treeRegistry; - private final LockedRegistry floraRegistry; - private final LockedRegistry lootRegistry; - private final LockedRegistry oreRegistry; - private final LockedRegistry> paletteRegistry; - private final LockedRegistry structureRegistry; - - private final BiomeProvider provider; - - private final TerraWorld world; - private final ConfigPack pack; - - public WorldConfig(TerraWorld world, ConfigPack pack, TerraPlugin main) { - this.world = world; - this.pack = pack; - this.samplerCache = new SamplerCache(main, world); - this.scriptRegistry = new LockedRegistry<>(pack.getScriptRegistry()); - - OpenRegistry biomeOpenRegistry = new OpenRegistry<>(); - pack.getBiomeRegistry().forEach((id, biome) -> biomeOpenRegistry.add(id, biome.apply(world.getWorld().getSeed()))); - - this.biomeRegistry = new LockedRegistry<>(biomeOpenRegistry); - this.carverRegistry = new LockedRegistry<>(pack.getCarverRegistry()); - this.treeRegistry = new LockedRegistry<>(pack.getTreeRegistry()); - this.floraRegistry = new LockedRegistry<>(pack.getFloraRegistry()); - this.lootRegistry = new LockedRegistry<>(pack.getLootRegistry()); - this.oreRegistry = new LockedRegistry<>(pack.getOreRegistry()); - this.paletteRegistry = new LockedRegistry<>(pack.getPaletteRegistry()); - this.structureRegistry = new LockedRegistry<>(pack.getStructureRegistry()); - - this.provider = pack.getBiomeProviderBuilder().build(world.getWorld().getSeed()); - } - - public TerraWorld getWorld() { - return world; - } - - public SamplerCache getSamplerCache() { - return samplerCache; - } - - public Set getCarvers() { - return carverRegistry.entries(); - } - - public LockedRegistry getScriptRegistry() { - return scriptRegistry; - } - - public LockedRegistry getBiomeRegistry() { - return biomeRegistry; - } - - public LockedRegistry getTreeRegistry() { - return treeRegistry; - } - - public LockedRegistry getCarverRegistry() { - return carverRegistry; - } - - public LockedRegistry getFloraRegistry() { - return floraRegistry; - } - - public LockedRegistry getLootRegistry() { - return lootRegistry; - } - - public LockedRegistry getOreRegistry() { - return oreRegistry; - } - - public LockedRegistry> getPaletteRegistry() { - return paletteRegistry; - } - - public LockedRegistry getStructureRegistry() { - return structureRegistry; - } - - public BiomeProvider getProvider() { - return provider; - } - - public Set getStructures() { - return structureRegistry.entries(); - } - - public ConfigPackTemplate getTemplate() { - return pack.getTemplate(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/templates/AbstractableTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/AbstractableTemplate.java deleted file mode 100644 index e243fc3ad..000000000 --- a/common/src/main/java/com/dfsek/terra/config/templates/AbstractableTemplate.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.config.templates; - -import com.dfsek.tectonic.config.ConfigTemplate; - -public abstract class AbstractableTemplate implements ConfigTemplate { - public abstract String getID(); -} diff --git a/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java deleted file mode 100644 index f8f62a4db..000000000 --- a/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java +++ /dev/null @@ -1,391 +0,0 @@ -package com.dfsek.terra.config.templates; - -import com.dfsek.paralithic.eval.parser.Parser; -import com.dfsek.paralithic.eval.parser.Scope; -import com.dfsek.paralithic.eval.tokenizer.ParseException; -import com.dfsek.tectonic.annotations.Abstractable; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ValidatedConfigTemplate; -import com.dfsek.tectonic.exception.ValidationException; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.ConstantSampler; -import com.dfsek.terra.api.math.paralithic.BlankFunction; -import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.util.GlueList; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.api.world.palette.SinglePalette; -import com.dfsek.terra.api.world.palette.holder.PaletteHolder; -import com.dfsek.terra.carving.UserDefinedCarver; -import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.world.population.items.TerraStructure; -import com.dfsek.terra.world.population.items.flora.FloraLayer; -import com.dfsek.terra.world.population.items.ores.OreHolder; -import com.dfsek.terra.world.population.items.tree.TreeLayer; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -@SuppressWarnings({"FieldMayBeFinal", "unused"}) -public class BiomeTemplate extends AbstractableTemplate implements ValidatedConfigTemplate { - private final ConfigPack pack; - - @Value("id") - private String id; - - @Value("extends") - @Default - private List extended = Collections.emptyList(); - - @Value("variables") - @Abstractable - @Default - private Map variables = new HashMap<>(); - - @Value("functions") - @Default - @Abstractable - private LinkedHashMap functions = new LinkedHashMap<>(); - - @Value("beta.carving.equation") - @Abstractable - @Default - private String carvingEquation = "0"; - - @Value("palette") - @Abstractable - private PaletteHolder palette; - - @Value("slant.palette") - @Abstractable - @Default - private PaletteHolder slantPalette = null; - - @Value("vanilla") - @Abstractable - private ProbabilityCollection vanilla; - - @Value("biome-noise") - @Default - @Abstractable - private NoiseSeeded biomeNoise; - - @Value("blend.distance") - @Abstractable - @Default - private int blendDistance = 3; - - @Value("blend.weight") - @Abstractable - @Default - private double blendWeight = 1; - - @Value("blend.step") - @Abstractable - @Default - private int blendStep = 4; - - @Value("erode") - @Abstractable - @Default - private String erode = null; - - @Value("structures") - @Abstractable - @Default - private List structures = new GlueList<>(); - - @Value("noise-equation") - @Abstractable - private String noiseEquation; - - @Value("ores") - @Abstractable - @Default - private OreHolder oreHolder = new OreHolder(); - - @Value("ocean.level") - @Abstractable - @Default - private int seaLevel = 62; - - @Value("ocean.palette") - @Abstractable - @Default - private Palette oceanPalette; - - @Value("elevation.equation") - @Default - @Abstractable - private String elevationEquation = null; - - @Value("elevation.weight") - @Default - @Abstractable - private double elevationWeight = 1; - - @Value("flora") - @Abstractable - @Default - private List flora = new GlueList<>(); - - @Value("trees") - @Abstractable - @Default - private List trees = new GlueList<>(); - - @Value("slabs.enable") - @Abstractable - @Default - private boolean doSlabs = false; - - @Value("slabs.threshold") - @Abstractable - @Default - private double slabThreshold = 0.0075D; - - @Value("slabs.palettes") - @Abstractable - @Default - private Map> slabPalettes; - - @Value("slabs.stair-palettes") - @Abstractable - @Default - private Map> stairPalettes; - - @Value("slant.threshold") - @Abstractable - @Default - private double slantThreshold = 0.1; - - @Value("interpolate-elevation") - @Abstractable - @Default - private boolean interpolateElevation = true; - - @Value("color") - @Default - private int color = 0; - - @Value("tags") - @Default - @Abstractable - private Set tags = new HashSet<>(); - - @Value("carving") - @Abstractable - @Default - private Map carvers = new HashMap<>(); - - @Value("colors") - @Abstractable - @Default - private Map colors = new HashMap<>(); // Plain ol' map, so platforms can decide what to do with colors (if anything). - - public List getExtended() { - return extended; - } - - public Set getTags() { - return tags; - } - - public Map getColors() { - return colors; - } - - public Map getCarvers() { - return carvers; - } - - public Map getFunctions() { - return functions; - } - - public double getBlendWeight() { - return blendWeight; - } - - public int getColor() { - return color; - } - - public int getBlendDistance() { - return blendDistance; - } - - public boolean interpolateElevation() { - return interpolateElevation; - } - - public double getSlantThreshold() { - return slantThreshold; - } - - public double getSlabThreshold() { - return slabThreshold; - } - - public List getFlora() { - return flora; - } - - public boolean doSlabs() { - return doSlabs; - } - - public Map> getSlabPalettes() { - return slabPalettes; - } - - public Map> getStairPalettes() { - return stairPalettes; - } - - public BiomeTemplate(ConfigPack pack, TerraPlugin main) { - this.pack = pack; - biomeNoise = new NoiseSeeded() { - @Override - public NoiseSampler apply(Long seed) { - return new ConstantSampler(0); - } - - @Override - public int getDimensions() { - return 2; - } - }; - oceanPalette = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:water")); - } - - public NoiseSeeded getBiomeNoise() { - return biomeNoise; - } - - public String getElevationEquation() { - return elevationEquation; - } - - public String getCarvingEquation() { - return carvingEquation; - } - - public ConfigPack getPack() { - return pack; - } - - public int getSeaLevel() { - return seaLevel; - } - - public Palette getOceanPalette() { - return oceanPalette; - } - - public String getID() { - return id; - } - - public PaletteHolder getPalette() { - return palette; - } - - public List getTrees() { - return trees; - } - - public PaletteHolder getSlantPalette() { - return slantPalette; - } - - public ProbabilityCollection getVanilla() { - return vanilla; - } - - public String getErode() { - return erode; - } - - public List getStructures() { - return structures; - } - - public String getNoiseEquation() { - return noiseEquation; - } - - public OreHolder getOreHolder() { - return oreHolder; - } - - public double getElevationWeight() { - return elevationWeight; - } - - public int getBlendStep() { - return blendStep; - } - - public Map getVariables() { - return variables; - } - - @Override - public boolean validate() throws ValidationException { - color |= 0xff000000; // Alpha adjustment - Parser tester = new Parser(); - Scope testScope = new Scope().withParent(pack.getVarScope()); - - variables.forEach(testScope::create); - - testScope.addInvocationVariable("x"); - testScope.addInvocationVariable("y"); - testScope.addInvocationVariable("z"); - - - pack.getTemplate().getNoiseBuilderMap().forEach((id, builder) -> tester.registerFunction(id, new BlankFunction(builder.getDimensions()))); // Register dummy functions - - Map testFunctions = new LinkedHashMap<>(pack.getTemplate().getFunctions()); - testFunctions.putAll(functions); - for(Map.Entry entry : testFunctions.entrySet()) { - try { - tester.registerFunction(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), tester, testScope)); - } catch(ParseException e) { - throw new ValidationException("Invalid function: ", e); - } - } - - try { - tester.parse(noiseEquation, testScope); - } catch(ParseException e) { - throw new ValidationException("Invalid noise equation: ", e); - } - - try { - tester.parse(carvingEquation, testScope); - } catch(ParseException e) { - throw new ValidationException("Invalid carving equation: ", e); - } - - try { - if(elevationEquation != null) tester.parse(elevationEquation, testScope); - } catch(ParseException e) { - throw new ValidationException("Invalid elevation equation: ", e); - } - - return true; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java deleted file mode 100644 index 96cdbde03..000000000 --- a/common/src/main/java/com/dfsek/terra/config/templates/CarverTemplate.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.dfsek.terra.config.templates; - -import com.dfsek.tectonic.annotations.Abstractable; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.carving.CarverPalette; - -import java.util.HashMap; -import java.util.Map; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class CarverTemplate extends AbstractableTemplate { - @Value("id") - private String id; - - @Value("step") - @Abstractable - @Default - private int step = 2; - - @Value("recalculate-magnitude") - @Default - @Abstractable - private double recaclulateMagnitude = 4; - - @Value("recalculate-direction") - @Abstractable - @Default - private Range recalc = new Range(8, 10); - - @Value("length") - @Abstractable - private Range length; - - @Value("start.x") - @Abstractable - private double startX; - - @Value("start.y") - @Abstractable - private double startY; - - @Value("start.z") - @Abstractable - private double startZ; - - @Value("start.radius.x") - @Abstractable - private String radMX; - - @Value("start.radius.y") - @Abstractable - private String radMY; - - @Value("start.radius.z") - @Abstractable - private String radMZ; - - @Value("start.height") - @Abstractable - private Range height; - - @Value("cut.bottom") - @Abstractable - @Default - private int cutBottom = 0; - - @Value("cut.top") - @Abstractable - @Default - private int cutTop = 0; - - @Value("mutate.x") - @Abstractable - private double mutateX; - - @Value("mutate.y") - @Abstractable - private double mutateY; - - @Value("mutate.z") - @Abstractable - private double mutateZ; - - @Value("palette.top") - @Abstractable - private CarverPalette top; - - @Value("palette.bottom") - @Abstractable - private CarverPalette bottom; - - @Value("palette.outer") - @Abstractable - private CarverPalette outer; - - @Value("palette.inner") - @Abstractable - private CarverPalette inner; - - @Value("shift") - @Abstractable - @Default - private Map shift = new HashMap<>(); - - @Value("update") - @Abstractable - @Default - private MaterialSet update = new MaterialSet(); - - public String getID() { - return id; - } - - public int getStep() { - return step; - } - - public Range getLength() { - return length; - } - - public double getStartX() { - return startX; - } - - public double getStartY() { - return startY; - } - - public double getStartZ() { - return startZ; - } - - public String getRadMX() { - return radMX; - } - - public String getRadMY() { - return radMY; - } - - public String getRadMZ() { - return radMZ; - } - - public Range getHeight() { - return height; - } - - public int getCutBottom() { - return cutBottom; - } - - public int getCutTop() { - return cutTop; - } - - public double getMutateX() { - return mutateX; - } - - public double getMutateY() { - return mutateY; - } - - public double getMutateZ() { - return mutateZ; - } - - public CarverPalette getTop() { - return top; - } - - public CarverPalette getBottom() { - return bottom; - } - - public CarverPalette getOuter() { - return outer; - } - - public CarverPalette getInner() { - return inner; - } - - public Map getShift() { - return shift; - } - - public MaterialSet getUpdate() { - return update; - } - - public Range getRecalc() { - return recalc; - } - - public double getRecaclulateMagnitude() { - return recaclulateMagnitude; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java deleted file mode 100644 index 8e1564e4a..000000000 --- a/common/src/main/java/com/dfsek/terra/config/templates/FloraTemplate.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.dfsek.terra.config.templates; - -import com.dfsek.tectonic.annotations.Abstractable; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; -import com.dfsek.terra.world.population.items.flora.TerraFlora; - -import java.util.List; - -@SuppressWarnings({"FieldMayBeFinal", "unused"}) -public class FloraTemplate extends AbstractableTemplate { - @Value("id") - private String id; - - @Value("spawnable") - @Abstractable - private MaterialSet spawnable; - - @Value("spawn-blacklist") - @Abstractable - @Default - private boolean spawnBlacklist = false; - - - @Value("replaceable") - @Abstractable - @Default - private MaterialSet replaceable = new MaterialSet(); - - @Value("irrigable") - @Abstractable - @Default - private MaterialSet irrigable = null; - - @Value("rotatable") - @Abstractable - @Default - private MaterialSet rotatable = new MaterialSet(); - - @Value("layers") - @Abstractable - private List palette; - - @Value("physics") - @Abstractable - @Default - private boolean doPhysics = false; - - @Value("ceiling") - @Abstractable - @Default - private boolean ceiling = false; - - @Value("search") - @Default - @Abstractable - private TerraFlora.Search search = TerraFlora.Search.UP; - - @Value("max-placements") - @Default - @Abstractable - private int maxPlacements = -1; - - @Value("irrigable-offset") - @Abstractable - @Default - private int irrigableOffset; - - public int getIrrigableOffset() { - return irrigableOffset; - } - - public TerraFlora.Search getSearch() { - return search; - } - - public int getMaxPlacements() { - return maxPlacements; - } - - public MaterialSet getReplaceable() { - return replaceable; - } - - public MaterialSet getSpawnable() { - return spawnable; - } - - public MaterialSet getIrrigable() { - return irrigable; - } - - public String getID() { - return id; - } - - public List getFloraPalette() { - return palette; - } - - public boolean doPhysics() { - return doPhysics; - } - - public boolean isCeiling() { - return ceiling; - } - - public boolean isSpawnBlacklist() { - return spawnBlacklist; - } - - public MaterialSet getRotatable() { - return rotatable; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java deleted file mode 100644 index 90e780a85..000000000 --- a/common/src/main/java/com/dfsek/terra/config/templates/OreTemplate.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.dfsek.terra.config.templates; - -import com.dfsek.tectonic.annotations.Abstractable; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.world.population.items.ores.Ore; - -import java.util.HashMap; -import java.util.Map; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class OreTemplate extends AbstractableTemplate { - @Value("id") - private String id; - - @Value("material") - @Abstractable - private BlockData material; - - @Value("material-overrides") - @Default - @Abstractable - private Map materials = new HashMap<>(); - - @Value("type") - @Abstractable - @Default - private Ore.Type oreType = Ore.Type.VANILLA; - - @Value("replace") - @Abstractable - private MaterialSet replaceable; - - @Value("physics") - @Abstractable - @Default - private boolean physics = false; - - @Value("size") - @Abstractable - private Range size; - - @Value("deform") - @Abstractable - @Default - private double deform = 0.75D; - - @Value("deform-frequency") - @Abstractable - @Default - private double deformFrequency = 0.1D; - - public double getDeform() { - return deform; - } - - public double getDeformFrequency() { - return deformFrequency; - } - - public Range getSize() { - return size; - } - - public BlockData getMaterial() { - return material; - } - - public MaterialSet getReplaceable() { - return replaceable; - } - - public boolean doPhysics() { - return physics; - } - - public String getID() { - return id; - } - - public Ore.Type getType() { - return oreType; - } - - public Map getMaterialOverrides() { - return materials; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java deleted file mode 100644 index e18ae2618..000000000 --- a/common/src/main/java/com/dfsek/terra/config/templates/PaletteTemplate.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.config.templates; - -import com.dfsek.tectonic.annotations.Abstractable; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; - -import java.util.List; - -@SuppressWarnings({"FieldMayBeFinal", "unused"}) -public class PaletteTemplate extends AbstractableTemplate { - @Value("noise") - @Abstractable - @Default - private NoiseSeeded noise; - - @Value("id") - private String id; - - @Value("layers") - @Abstractable - private List palette; - - public PaletteTemplate() { - this.noise = new NoiseSeeded() { - @Override - public NoiseSampler apply(Long seed) { - return new WhiteNoiseSampler((int) (long) seed); - } - - @Override - public int getDimensions() { - return 3; - } - }; - } - - public String getID() { - return id; - } - - public List getPalette() { - return palette; - } - - public NoiseSeeded getNoise() { - return noise; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java deleted file mode 100644 index a291ae3f9..000000000 --- a/common/src/main/java/com/dfsek/terra/config/templates/StructureTemplate.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.dfsek.terra.config.templates; - -import com.dfsek.tectonic.annotations.Abstractable; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.terra.api.math.GridSpawn; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.util.GlueList; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; - -import java.util.List; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class StructureTemplate extends AbstractableTemplate implements ConfigTemplate { - @Value("id") - private String id; - - @Value("scripts") - @Abstractable - private ProbabilityCollection structure; - - @Value("spawn.start") - @Abstractable - private Range y; - - @Value("spawn") - @Abstractable - private GridSpawn spawn; - - @Value("features") - @Abstractable - @Default - private List features = new GlueList<>(); - - public String getID() { - return id; - } - - public ProbabilityCollection getStructures() { - return structure; - } - - public Range getY() { - return y; - } - - public List getFeatures() { - return features; - } - - public GridSpawn getSpawn() { - return spawn; - } -} diff --git a/common/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java deleted file mode 100644 index 008d05d4f..000000000 --- a/common/src/main/java/com/dfsek/terra/config/templates/TreeTemplate.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.dfsek.terra.config.templates; - -import com.dfsek.tectonic.annotations.Abstractable; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; - -@SuppressWarnings({"unused", "FieldMayBeFinal"}) -public class TreeTemplate extends AbstractableTemplate { - @Value("scripts") - @Abstractable - private ProbabilityCollection structure; - - @Value("id") - private String id; - - @Value("y-offset") - @Abstractable - @Default - private int yOffset = 0; - - @Value("spawnable") - @Abstractable - private MaterialSet spawnable; - - public ProbabilityCollection getStructures() { - return structure; - } - - public String getID() { - return id; - } - - public int getyOffset() { - return yOffset; - } - - public MaterialSet getSpawnable() { - return spawnable; - } -} diff --git a/common/src/main/java/com/dfsek/terra/profiler/Frame.java b/common/src/main/java/com/dfsek/terra/profiler/Frame.java deleted file mode 100644 index 7b7be66b5..000000000 --- a/common/src/main/java/com/dfsek/terra/profiler/Frame.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.dfsek.terra.profiler; - -public class Frame { - private final String id; - private final long start; - - public Frame(String id) { - this.id = id; - this.start = System.nanoTime(); - } - - public String getId() { - return id; - } - - public long getStart() { - return start; - } - - @Override - public String toString() { - return id; - } -} diff --git a/common/src/main/java/com/dfsek/terra/profiler/ProfileFrame.java b/common/src/main/java/com/dfsek/terra/profiler/ProfileFrame.java deleted file mode 100644 index bf5c64dab..000000000 --- a/common/src/main/java/com/dfsek/terra/profiler/ProfileFrame.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.profiler; - -public class ProfileFrame implements AutoCloseable { - private final Runnable action; - - public ProfileFrame(Runnable action) { - this.action = action; - } - - @Override - public void close() { - action.run(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java b/common/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java deleted file mode 100644 index f91deecd1..000000000 --- a/common/src/main/java/com/dfsek/terra/profiler/ProfilerImpl.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.dfsek.terra.profiler; - -import com.dfsek.terra.api.util.mutable.MutableInteger; -import com.dfsek.terra.profiler.exception.MalformedStackException; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Stack; - -public class ProfilerImpl implements Profiler { - private static final ThreadLocal> THREAD_STACK = ThreadLocal.withInitial(Stack::new); - private static final ThreadLocal>> TIMINGS = ThreadLocal.withInitial(HashMap::new); - private final List>> accessibleThreadMaps = new ArrayList<>(); - private volatile boolean running = false; - private static boolean instantiated = false; - - private static final ThreadLocal SAFE = ThreadLocal.withInitial(() -> false); - private static final ThreadLocal STACK_SIZE = ThreadLocal.withInitial(() -> new MutableInteger(0)); - - public ProfilerImpl() { - if(instantiated) throw new IllegalStateException("Only one instance of Profiler may exist!"); - instantiated = true; - } - - @Override - public void push(String frame) { - STACK_SIZE.get().increment(); - if(running && SAFE.get()) { - Stack stack = THREAD_STACK.get(); - stack.push(new Frame(stack.isEmpty() ? frame : stack.peek().getId() + "." + frame)); - } else SAFE.set(false); - } - - @Override - public void pop(String frame) { - MutableInteger size = STACK_SIZE.get(); - size.decrement(); - if(running && SAFE.get()) { - long time = System.nanoTime(); - Stack stack = THREAD_STACK.get(); - - Map> timingsMap = TIMINGS.get(); - - if(timingsMap.size() == 0) { - synchronized(accessibleThreadMaps) { - accessibleThreadMaps.add(timingsMap); - } - } - - Frame top = stack.pop(); - if((stack.size() != 0 && !top.getId().endsWith("." + frame)) || (stack.size() == 0 && !top.getId().equals(frame))) - throw new MalformedStackException("Expected " + frame + ", found " + top); - - List timings = timingsMap.computeIfAbsent(top.getId(), id -> new ArrayList<>()); - - timings.add(time - top.getStart()); - } - if(size.get() == 0) SAFE.set(true); - } - - @Override - public void start() { - running = true; - } - - @Override - public void stop() { - running = false; - } - - @Override - public Map getTimings() { - Map map = new HashMap<>(); - accessibleThreadMaps.forEach(smap -> smap.forEach((key, list) -> { - String[] keys = key.split("\\."); - Timings timings = map.computeIfAbsent(keys[0], id -> new Timings()); - for(int i = 1; i < keys.length; i++) { - timings = timings.getSubItem(keys[i]); - } - list.forEach(timings::addTime); - })); - return map; - } - - @Override - public void reset() { - accessibleThreadMaps.forEach(Map::clear); - } -} diff --git a/common/src/main/java/com/dfsek/terra/profiler/exception/MalformedStackException.java b/common/src/main/java/com/dfsek/terra/profiler/exception/MalformedStackException.java deleted file mode 100644 index 0ae345a0f..000000000 --- a/common/src/main/java/com/dfsek/terra/profiler/exception/MalformedStackException.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.profiler.exception; - -public class MalformedStackException extends ProfilerException { - private static final long serialVersionUID = -3009539681021691054L; - - public MalformedStackException(String message) { - super(message); - } - - public MalformedStackException(String message, Throwable cause) { - super(message, cause); - } - - public MalformedStackException(Throwable cause) { - super(cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/profiler/exception/ProfilerException.java b/common/src/main/java/com/dfsek/terra/profiler/exception/ProfilerException.java deleted file mode 100644 index 27c6d734f..000000000 --- a/common/src/main/java/com/dfsek/terra/profiler/exception/ProfilerException.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.profiler.exception; - -public class ProfilerException extends RuntimeException { - private static final long serialVersionUID = 8206737998791649002L; - - public ProfilerException(String message) { - super(message); - } - - public ProfilerException(String message, Throwable cause) { - super(message, cause); - } - - public ProfilerException(Throwable cause) { - super(cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java b/common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java deleted file mode 100644 index 6f4c179f0..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/OpenRegistry.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.dfsek.terra.registry; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.terra.api.registry.Registry; -import com.dfsek.terra.registry.exception.DuplicateEntryException; - -import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -/** - * Registry implementation with read/write access. For internal use only. - * @param - */ -public class OpenRegistry implements Registry { - private final Map> objects = new HashMap<>(); - - @Override - public T load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - T obj = get((String) o); - if(obj == null) - throw new LoadException("No such " + type.getTypeName() + " matching \"" + o + "\" was found in this registry."); - return obj; - } - - /** - * Add a value to this registry. - * - * @param identifier Identifier to assign value. - * @param value Value to add. - */ - public boolean add(String identifier, T value) { - return add(identifier, new Entry<>(value)); - } - - protected boolean add(String identifier, Entry value) { - boolean exists = objects.containsKey(identifier); - objects.put(identifier, value); - return exists; - } - - /** - * Add a value to this registry, checking whether it is present first. - * - * @param identifier Identifier to assign value. - * @param value Value to add. - * @throws DuplicateEntryException If an entry with the same identifier is already present. - */ - public void addChecked(String identifier, T value) throws DuplicateEntryException { - if(objects.containsKey(identifier)) - throw new DuplicateEntryException("Value with identifier \"" + identifier + "\" is already defined in registry."); - add(identifier, value); - } - - @Override - public boolean contains(String identifier) { - return objects.containsKey(identifier); - } - - @Override - public T get(String identifier) { - Entry entry = objects.get(identifier); - if(entry == null) return null; - return entry.getValue(); - } - - @Override - public void forEach(Consumer consumer) { - objects.forEach((id, obj) -> consumer.accept(obj.getRaw())); - } - - @Override - public void forEach(BiConsumer consumer) { - objects.forEach((id, entry) -> consumer.accept(id, entry.getRaw())); - } - - @Override - public Set entries() { - return objects.values().stream().map(Entry::getRaw).collect(Collectors.toSet()); - } - - @Override - public Set keys() { - return objects.keySet(); - } - - public Map getDeadEntries() { - Map dead = new HashMap<>(); - objects.forEach((id, entry) -> { - if(entry.dead()) dead.put(id, entry.value); // dont increment value here. - }); - return dead; - } - - /** - * Clears all entries from the registry. - */ - public void clear() { - objects.clear(); - } - - - protected static final class Entry { - private final T value; - private final AtomicInteger access = new AtomicInteger(0); - - public Entry(T value) { - this.value = value; - } - - public T getValue() { - access.incrementAndGet(); - return value; - } - - private T getRaw() { - return value; - } - - public boolean dead() { - return access.get() == 0; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/BiomeRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/BiomeRegistry.java deleted file mode 100644 index 5ad1d32a6..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/BiomeRegistry.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.terra.config.builder.BiomeBuilder; -import com.dfsek.terra.registry.OpenRegistry; - -import java.lang.reflect.Type; - -public class BiomeRegistry extends OpenRegistry { - @Override - public BiomeBuilder load(Type type, Object o, ConfigLoader configLoader) throws LoadException { - if(o.equals("SELF")) return null; - BiomeBuilder biome = get((String) o); - if(biome == null) - throw new LoadException("No such " + type.getTypeName() + " matching \"" + o + "\" was found in this registry."); - return biome; - } -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/CarverRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/CarverRegistry.java deleted file mode 100644 index 63b80f715..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/CarverRegistry.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.terra.carving.UserDefinedCarver; -import com.dfsek.terra.registry.OpenRegistry; - -public class CarverRegistry extends OpenRegistry { -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java deleted file mode 100644 index 65858b8ad..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.api.world.flora.Flora; -import com.dfsek.terra.registry.OpenRegistry; -import com.dfsek.terra.world.population.items.flora.ConstantFlora; - -import java.util.Arrays; -import java.util.Collections; -import java.util.concurrent.Callable; - -public class FloraRegistry extends OpenRegistry { - private final TerraPlugin main; - - public FloraRegistry(TerraPlugin main) { - this.main = main; - MaterialSet grassy = MaterialSet.get(create("minecraft:grass_block"), create("minecraft:podzol")); - addItem("TALL_GRASS", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:tall_grass[half=lower]"), data("minecraft:tall_grass[half=upper]")))); - addItem("TALL_FERN", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:large_fern[half=lower]"), data("minecraft:large_fern[half=upper]")))); - addItem("SUNFLOWER", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:sunflower[half=lower]"), data("minecraft:sunflower[half=upper]")))); - addItem("ROSE_BUSH", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:rose_bush[half=lower]"), data("minecraft:rose_bush[half=upper]")))); - addItem("LILAC", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:lilac[half=lower]"), data("minecraft:lilac[half=upper]")))); - addItem("PEONY", () -> new ConstantFlora(grassy, Arrays.asList(data("minecraft:peony[half=lower]"), data("minecraft:peony[half=upper]")))); - addItem("GRASS", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:grass")))); - addItem("FERN", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:fern")))); - addItem("AZURE_BLUET", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:azure_bluet")))); - addItem("LILY_OF_THE_VALLEY", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:lily_of_the_valley")))); - addItem("BLUE_ORCHID", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:blue_orchid")))); - addItem("POPPY", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:poppy")))); - addItem("DANDELION", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:dandelion")))); - addItem("WITHER_ROSE", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:wither_rose")))); - addItem("DEAD_BUSH", () -> new ConstantFlora(MaterialSet.get(create("minecraft:terracotta"), create("minecraft:black_terracotta"), - create("minecraft:blue_terracotta"), create("minecraft:brown_terracotta"), create("minecraft:cyan_terracotta"), - create("minecraft:gray_terracotta"), create("minecraft:green_terracotta"), create("minecraft:light_blue_terracotta"), - create("minecraft:light_gray_terracotta"), create("minecraft:lime_terracotta"), create("minecraft:magenta_terracotta"), - create("minecraft:orange_terracotta"), create("minecraft:pink_terracotta"), create("minecraft:purple_terracotta"), - create("minecraft:red_terracotta"), create("minecraft:white_terracotta"), create("minecraft:yellow_terracotta"), - create("minecraft:red_sand"), create("minecraft:sand"), create("minecraft:coarse_dirt")), Collections.singletonList(data("minecraft:dead_bush")))); - addItem("RED_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:red_tulip")))); - addItem("ORANGE_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:orange_tulip")))); - addItem("WHITE_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:white_tulip")))); - addItem("PINK_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:pink_tulip")))); - addItem("OXEYE_DAISY", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:oxeye_daisy")))); - addItem("ALLIUM", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:allium")))); - addItem("CORNFLOWER", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:cornflower")))); - addItem("LILY_PAD", () -> new ConstantFlora(MaterialSet.get(create("minecraft:water")), Collections.singletonList(data("minecraft:lily_pad")))); - MaterialSet mushroom = MaterialSet.get(create("minecraft:grass_block"), create("minecraft:stone"), create("minecraft:podzol"), create("minecraft:netherrack"), create("minecraft:mycelium")); - addItem("RED_MUSHROOM", () -> new ConstantFlora(mushroom, Collections.singletonList(data("minecraft:red_mushroom")))); - addItem("BROWN_MUSHROOM", () -> new ConstantFlora(mushroom, Collections.singletonList(data("minecraft:brown_mushroom")))); - } - - private BlockData create(String s) { - return main.getWorldHandle().createBlockData(s); - } - - private void addItem(String id, Callable flora) { - try { - Entry entry = new Entry<>(flora.call()); - entry.getValue(); // Mark as not dead. - add(id, entry); - } catch(Exception e) { - main.logger().warning("Failed to load Flora item: " + id + ": " + e.getMessage()); - } - } - - private BlockData data(String s) { - return main.getWorldHandle().createBlockData(s); - } -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/FunctionRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/FunctionRegistry.java deleted file mode 100644 index 2d140137a..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/FunctionRegistry.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.registry.OpenRegistry; - -public class FunctionRegistry extends OpenRegistry> { -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/LootRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/LootRegistry.java deleted file mode 100644 index 8c8e987aa..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/LootRegistry.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.terra.api.structures.loot.LootTable; -import com.dfsek.terra.registry.OpenRegistry; - -public class LootRegistry extends OpenRegistry { -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java deleted file mode 100644 index ccbfee9ca..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/NoiseRegistry.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.tectonic.loading.object.ObjectTemplate; -import com.dfsek.terra.api.math.noise.samplers.noise.random.GaussianNoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.random.WhiteNoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2SSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler; -import com.dfsek.terra.api.math.noise.samplers.noise.simplex.PerlinSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.simplex.SimplexSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.value.ValueCubicSampler; -import com.dfsek.terra.api.math.noise.samplers.noise.value.ValueSampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.config.loaders.config.sampler.templates.DomainWarpTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.KernelTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.noise.CellularNoiseTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.noise.ConstantNoiseTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.noise.ExpressionFunctionTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.noise.GaborNoiseTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.noise.SimpleNoiseTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal.BrownianMotionTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal.PingPongTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.noise.fractal.RidgedFractalTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.ClampNormalizerTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.LinearNormalizerTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.NormalNormalizerTemplate; -import com.dfsek.terra.registry.OpenRegistry; - -import java.util.function.Supplier; - -public class NoiseRegistry extends OpenRegistry>> { - public NoiseRegistry() { - add("LINEAR", LinearNormalizerTemplate::new); - add("NORMAL", NormalNormalizerTemplate::new); - add("CLAMP", ClampNormalizerTemplate::new); - add("EXPRESSION", ExpressionFunctionTemplate::new); - - add("IMAGE", ImageSamplerTemplate::new); - - add("DOMAINWARP", DomainWarpTemplate::new); - - add("FBM", BrownianMotionTemplate::new); - add("PINGPONG", PingPongTemplate::new); - add("RIDGED", RidgedFractalTemplate::new); - - add("OPENSIMPLEX2", () -> new SimpleNoiseTemplate(OpenSimplex2Sampler::new)); - add("OPENSIMPLEX2S", () -> new SimpleNoiseTemplate(OpenSimplex2SSampler::new)); - add("PERLIN", () -> new SimpleNoiseTemplate(PerlinSampler::new)); - add("SIMPLEX", () -> new SimpleNoiseTemplate(SimplexSampler::new)); - add("GABOR", GaborNoiseTemplate::new); - - - add("VALUE", () -> new SimpleNoiseTemplate(ValueSampler::new)); - add("VALUECUBIC", () -> new SimpleNoiseTemplate(ValueCubicSampler::new)); - - add("CELLULAR", CellularNoiseTemplate::new); - - add("WHITENOISE", () -> new SimpleNoiseTemplate(WhiteNoiseSampler::new)); - add("GAUSSIAN", () -> new SimpleNoiseTemplate(GaussianNoiseSampler::new)); - - add("CONSTANT", ConstantNoiseTemplate::new); - - add("KERNEL", KernelTemplate::new); - } -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/OreRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/OreRegistry.java deleted file mode 100644 index 010a812f2..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/OreRegistry.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.terra.registry.OpenRegistry; -import com.dfsek.terra.world.population.items.ores.Ore; - -public class OreRegistry extends OpenRegistry { -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/PaletteRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/PaletteRegistry.java deleted file mode 100644 index e54c8ec81..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/PaletteRegistry.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.api.world.palette.SinglePalette; -import com.dfsek.terra.registry.OpenRegistry; - -public class PaletteRegistry extends OpenRegistry> { - private final TerraPlugin main; - public PaletteRegistry(TerraPlugin main) { - this.main = main; - } - - - @Override - public Palette get(String identifier) { - if(identifier.startsWith("BLOCK:")) - return new SinglePalette<>(main.getWorldHandle().createBlockData(identifier.substring(6))); // Return single palette for BLOCK: shortcut. - return super.get(identifier); - } -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/ScriptRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/ScriptRegistry.java deleted file mode 100644 index a715c5ad9..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/ScriptRegistry.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.registry.OpenRegistry; - -public class ScriptRegistry extends OpenRegistry { -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/StructureRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/StructureRegistry.java deleted file mode 100644 index 56a24711d..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/StructureRegistry.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.terra.registry.OpenRegistry; -import com.dfsek.terra.world.population.items.TerraStructure; - -public class StructureRegistry extends OpenRegistry { -} diff --git a/common/src/main/java/com/dfsek/terra/registry/config/TreeRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/TreeRegistry.java deleted file mode 100644 index cc100ac3f..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/config/TreeRegistry.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dfsek.terra.registry.config; - -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.registry.OpenRegistry; - -public class TreeRegistry extends OpenRegistry { - @Override - public boolean add(String identifier, Tree value) { - return super.add(identifier, value); - } -} diff --git a/common/src/main/java/com/dfsek/terra/registry/exception/DuplicateEntryException.java b/common/src/main/java/com/dfsek/terra/registry/exception/DuplicateEntryException.java deleted file mode 100644 index 477c93f50..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/exception/DuplicateEntryException.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.registry.exception; - -/** - * Thrown when a duplicate entry is found in a registry. - */ -public class DuplicateEntryException extends Exception { - private static final long serialVersionUID = -7199021672428288780L; - - public DuplicateEntryException(String message) { - super(message); - } - - public DuplicateEntryException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/common/src/main/java/com/dfsek/terra/registry/master/AddonRegistry.java b/common/src/main/java/com/dfsek/terra/registry/master/AddonRegistry.java deleted file mode 100644 index f2c50acfb..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/master/AddonRegistry.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.dfsek.terra.registry.master; - -import com.dfsek.terra.addon.AddonClassLoader; -import com.dfsek.terra.addon.AddonPool; -import com.dfsek.terra.addon.PreLoadAddon; -import com.dfsek.terra.addon.exception.AddonLoadException; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.injection.Injector; -import com.dfsek.terra.api.injection.exception.InjectionException; -import com.dfsek.terra.registry.OpenRegistry; -import com.dfsek.terra.registry.exception.DuplicateEntryException; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.logging.LogManager; -import java.util.logging.Logger; - -public class AddonRegistry extends OpenRegistry { - private final TerraPlugin main; - - public AddonRegistry(TerraPlugin main) { - - this.main = main; - } - - public AddonRegistry(TerraAddon addon, TerraPlugin main) { - this.main = main; - add(addon.getName(), addon); - } - - @Override - public boolean add(String identifier, TerraAddon addon) { - if(contains(identifier)) throw new IllegalArgumentException("Addon " + identifier + " is already registered."); - addon.initialize(); - main.logger().info("Loaded addon " + addon.getName() + " v" + addon.getVersion() + ", by " + addon.getAuthor()); - return super.add(identifier, addon); - } - - @Override - public void clear() { - throw new UnsupportedOperationException(); - } - - public boolean loadAll() { - Injector pluginInjector = new Injector<>(main); - pluginInjector.addExplicitTarget(TerraPlugin.class); - - boolean valid = true; - File addonsFolder = new File(main.getDataFolder(), "addons"); - addonsFolder.mkdirs(); - - AddonPool pool = new AddonPool(); - - try { - for(File jar : addonsFolder.listFiles(file -> file.getName().endsWith(".jar"))) { - main.logger().info("Loading Addon(s) from: " + jar.getName()); - for(Class addonClass : AddonClassLoader.fetchAddonClasses(jar)) { - pool.add(new PreLoadAddon(addonClass, jar)); - } - } - - pool.buildAll(); - - for(PreLoadAddon addon : pool.getAddons()) { - Class addonClass = addon.getAddonClass(); - Constructor constructor; - - String logPrefix = "Terra:" + addon.getId(); - Logger addonLogger = Logger.getLogger(logPrefix); - - if(!LogManager.getLogManager().addLogger(addonLogger)) { - addonLogger = LogManager.getLogManager().getLogger(logPrefix); - } - - Injector loggerInjector = new Injector<>(addonLogger); - loggerInjector.addExplicitTarget(Logger.class); - - try { - constructor = addonClass.getConstructor(); - } catch(NoSuchMethodException e) { - throw new AddonLoadException("Addon class has no valid constructor: " + addonClass.getCanonicalName(), e); - } - TerraAddon loadedAddon; - try { - loadedAddon = constructor.newInstance(); - pluginInjector.inject(loadedAddon); - loggerInjector.inject(loadedAddon); - } catch(InstantiationException | IllegalAccessException | InvocationTargetException | InjectionException e) { - throw new AddonLoadException("Failed to load addon \" + " + addon.getId() + "\": ", e); - } - try { - addChecked(loadedAddon.getName(), loadedAddon); - } catch(DuplicateEntryException e) { - valid = false; - main.logger().severe("Duplicate addon ID; addon with ID " + loadedAddon.getName() + " is already loaded."); - main.logger().severe("Existing addon class: " + get(loadedAddon.getName()).getClass().getCanonicalName()); - main.logger().severe("Duplicate addon class: " + addonClass.getCanonicalName()); - } - } - } catch(AddonLoadException | IOException e) { - e.printStackTrace(); - valid = false; - } - - return valid; - } -} diff --git a/common/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java b/common/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java deleted file mode 100644 index c756a2b2b..000000000 --- a/common/src/main/java/com/dfsek/terra/registry/master/ConfigRegistry.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.dfsek.terra.registry.master; - -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.registry.OpenRegistry; - -import java.io.File; -import java.io.IOException; -import java.util.zip.ZipFile; - -/** - * Class to hold config packs - */ -public class ConfigRegistry extends OpenRegistry { - public void load(File folder, TerraPlugin main) throws ConfigException { - ConfigPack pack = new ConfigPack(folder, main); - add(pack.getTemplate().getID(), pack); - } - - public boolean loadAll(TerraPlugin main) { - boolean valid = true; - File packsFolder = new File(main.getDataFolder(), "packs"); - packsFolder.mkdirs(); - for(File dir : packsFolder.listFiles(File::isDirectory)) { - try { - load(dir, main); - } catch(ConfigException e) { - e.printStackTrace(); - valid = false; - } - } - for(File zip : packsFolder.listFiles(file -> file.getName().endsWith(".zip") || file.getName().endsWith(".terra"))) { - try { - main.getDebugLogger().info("Loading ZIP archive: " + zip.getName()); - load(new ZipFile(zip), main); - } catch(IOException | ConfigException e) { - e.printStackTrace(); - valid = false; - } - } - return valid; - } - - public void load(ZipFile file, TerraPlugin main) throws ConfigException { - ConfigPack pack = new ConfigPack(file, main); - add(pack.getTemplate().getID(), pack); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/Carver.java b/common/src/main/java/com/dfsek/terra/world/Carver.java deleted file mode 100644 index 869abc92d..000000000 --- a/common/src/main/java/com/dfsek/terra/world/Carver.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.world; - -import com.dfsek.terra.api.platform.world.ChunkAccess; -import com.dfsek.terra.api.platform.world.World; - -public interface Carver { - void carve(World world, int chunkX, int chunkZ, ChunkAccess chunk); -} diff --git a/common/src/main/java/com/dfsek/terra/world/TerraWorld.java b/common/src/main/java/com/dfsek/terra/world/TerraWorld.java deleted file mode 100644 index a92f35b8c..000000000 --- a/common/src/main/java/com/dfsek/terra/world/TerraWorld.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.dfsek.terra.world; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.event.events.world.TerraWorldLoadEvent; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.pack.WorldConfig; -import com.dfsek.terra.world.generation.math.samplers.Sampler; -import net.jafama.FastMath; - -public class TerraWorld { - private final BiomeProvider provider; - private final WorldConfig config; - private final boolean safe; - private final World world; - private final BlockData air; - - - public TerraWorld(World w, ConfigPack c, TerraPlugin main) { - if(!w.isTerraWorld()) throw new IllegalArgumentException("World " + w + " is not a Terra World!"); - this.world = w; - config = c.toWorldConfig(this); - this.provider = config.getProvider(); - air = main.getWorldHandle().createBlockData("minecraft:air"); - main.getEventManager().callEvent(new TerraWorldLoadEvent(this, c)); - safe = true; - } - - - public World getWorld() { - return world; - } - - - public BiomeProvider getBiomeProvider() { - return provider; - } - - public WorldConfig getConfig() { - return config; - } - - public boolean isSafe() { - return safe; - } - - - /** - * Get a block at an ungenerated location - * - * @param x X coordinate - * @param y Y coordinate - * @param z Z coordinate - * @return BlockData - */ - public BlockData getUngeneratedBlock(int x, int y, int z) { - UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(x, z); - Palette palette = biome.getGenerator(world).getPalette(y); - Sampler sampler = config.getSamplerCache().get(x, z); - int fdX = FastMath.floorMod(x, 16); - int fdZ = FastMath.floorMod(z, 16); - double noise = sampler.sample(fdX, y, fdZ); - if(noise > 0) { - int level = 0; - for(int yi = world.getMaxHeight() - 1; yi > y; yi--) { - if(sampler.sample(fdX, yi, fdZ) > 0) level++; - else level = 0; - } - return palette.get(level, x, y, z); - } else if(y <= biome.getConfig().getSeaLevel()) { - return biome.getConfig().getOceanPalette().get(biome.getConfig().getSeaLevel() - y, x, y, z); - } else return air; - } - - public BlockData getUngeneratedBlock(Location l) { - return getUngeneratedBlock(l.getBlockX(), l.getBlockY(), l.getBlockZ()); - } - - public BlockData getUngeneratedBlock(Vector3 v) { - return getUngeneratedBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ()); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/carving/NoiseCarver.java b/common/src/main/java/com/dfsek/terra/world/carving/NoiseCarver.java deleted file mode 100644 index e325e7a0c..000000000 --- a/common/src/main/java/com/dfsek/terra/world/carving/NoiseCarver.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.world.carving; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.ChunkAccess; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.world.Carver; -import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator; -import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator3D; - -public class NoiseCarver implements Carver { - private final Range range; - private final BlockData data; - private final TerraPlugin main; - - public NoiseCarver(Range range, BlockData data, TerraPlugin main) { - this.range = range; - this.data = data; - this.main = main; - } - - @Override - public void carve(World world, int chunkX, int chunkZ, ChunkAccess chunk) { - ChunkInterpolator interpolator = new ChunkInterpolator3D(world, chunkX, chunkZ, main.getWorld(world).getBiomeProvider(), (gen, coord) -> gen.getCarver().getNoise(coord.setY(coord.getY()))); - for(int y : range) { - for(int x = 0; x < 16; x++) { - for(int z = 0; z < 16; z++) { - double n = interpolator.getNoise(x, y, z); - if(n > 0) chunk.setBlock(x, y, z, data); - } - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/WorldGenerator.java b/common/src/main/java/com/dfsek/terra/world/generation/WorldGenerator.java deleted file mode 100644 index 971241ca5..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/WorldGenerator.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.dfsek.terra.world.generation; - -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.api.world.palette.holder.PaletteHolder; - -public class WorldGenerator implements Generator { - @SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"}) - private final PaletteHolder palettes; - @SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"}) - private final PaletteHolder slantPalettes; - - private final NoiseSampler noise; - private final NoiseSampler elevation; - private final NoiseSampler carving; - - private final NoiseSampler biomeNoise; - private final double elevationWeight; - private final int blendDistance; - private final int blendStep; - private final double blendWeight; - - public WorldGenerator(PaletteHolder palettes, PaletteHolder slantPalettes, NoiseSampler noise, NoiseSampler elevation, NoiseSampler carving, NoiseSampler biomeNoise, double elevationWeight, int blendDistance, int blendStep, double blendWeight) { - this.palettes = palettes; - this.slantPalettes = slantPalettes; - this.noise = noise; - this.elevation = elevation; - this.carving = carving; - - this.biomeNoise = biomeNoise; - this.elevationWeight = elevationWeight; - this.blendDistance = blendDistance; - this.blendStep = blendStep; - this.blendWeight = blendWeight; - } - - @Override - public NoiseSampler getBaseSampler() { - return noise; - } - - @Override - public NoiseSampler getElevationSampler() { - return elevation; - } - - @Override - public NoiseSampler getCarver() { - return carving; - } - - @Override - public int getBlendDistance() { - return blendDistance; - } - - @Override - public double getWeight() { - return blendWeight; - } - - /** - * Gets the BlockPalette to generate the biome with. - * - * @return BlockPalette - The biome's palette. - */ - @Override - public Palette getPalette(int y) { - return palettes.getPalette(y); - } - - @Override - public NoiseSampler getBiomeNoise() { - return biomeNoise; - } - - @Override - public double getElevationWeight() { - return elevationWeight; - } - - @Override - public int getBlendStep() { - return blendStep; - } - - public Palette getSlantPalette(int y) { - return slantPalettes.getPalette(y); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator2D.java b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator2D.java deleted file mode 100644 index be9268205..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator2D.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.dfsek.terra.world.generation.generators; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.BiomeGrid; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkData; -import com.dfsek.terra.api.util.world.PaletteUtil; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.profiler.ProfileFrame; -import com.dfsek.terra.world.Carver; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.carving.NoiseCarver; -import com.dfsek.terra.world.generation.math.SamplerCache; -import com.dfsek.terra.world.generation.math.samplers.Sampler; -import com.dfsek.terra.world.generation.math.samplers.Sampler2D; -import com.dfsek.terra.world.population.CavePopulator; -import com.dfsek.terra.world.population.OrePopulator; -import com.dfsek.terra.world.population.StructurePopulator; -import com.dfsek.terra.world.population.TreePopulator; -import net.jafama.FastMath; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -public class DefaultChunkGenerator2D implements TerraChunkGenerator { - private final ConfigPack configPack; - private final TerraPlugin main; - - private final Carver carver; - private final List blockPopulators = new ArrayList<>(); - - private final SamplerCache cache; - - public DefaultChunkGenerator2D(ConfigPack c, TerraPlugin main, SamplerCache cache) { - this.configPack = c; - this.main = main; - blockPopulators.add(new CavePopulator(main)); - blockPopulators.add(new StructurePopulator(main)); - blockPopulators.add(new OrePopulator(main)); - blockPopulators.add(new TreePopulator(main)); - blockPopulators.add(new TreePopulator(main)); - carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main); - this.cache = cache; - } - - @Override - public boolean isParallelCapable() { - return true; - } - - @Override - public boolean shouldGenerateCaves() { - return configPack.getTemplate().vanillaCaves(); - } - - @Override - public boolean shouldGenerateDecorations() { - return configPack.getTemplate().vanillaDecorations(); - } - - @Override - public boolean shouldGenerateMobs() { - return configPack.getTemplate().vanillaMobs(); - } - - @Override - public boolean shouldGenerateStructures() { - return configPack.getTemplate().vanillaStructures(); - } - - @Override - public ConfigPack getConfigPack() { - return configPack; - } - - @Override - public TerraPlugin getMain() { - return main; - } - - @Override - @SuppressWarnings({"try"}) - public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) { - TerraWorld tw = main.getWorld(world); - BiomeProvider grid = tw.getBiomeProvider(); - try(ProfileFrame ignore = main.getProfiler().profile("chunk_base_2d")) { - if(!tw.isSafe()) return chunk; - int xOrig = (chunkX << 4); - int zOrig = (chunkZ << 4); - - Sampler sampler = cache.getChunk(chunkX, chunkZ); - - for(int x = 0; x < 16; x++) { - for(int z = 0; z < 16; z++) { - int paletteLevel = 0; - int seaPaletteLevel = 0; - - int cx = xOrig + x; - int cz = zOrig + z; - - TerraBiome b = grid.getBiome(xOrig + x, zOrig + z); - BiomeTemplate c = ((UserDefinedBiome) b).getConfig(); - - Palette seaPalette = c.getOceanPalette(); - - int height = FastMath.min((int) sampler.sample(x, 0, z), world.getMaxHeight() - 1); - - for(int y = FastMath.max(height, c.getSeaLevel()); y >= 0; y--) { - BlockData data = y > height ? seaPalette.get(seaPaletteLevel++, cx, y, cz) : PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel++, cx, y, cz); - chunk.setBlock(x, y, z, data); - } - } - } - if(configPack.getTemplate().doBetaCarvers()) { - carver.carve(world, chunkX, chunkZ, chunk); - } - return chunk; - } - } - - @Override - public void generateBiomes(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, @NotNull BiomeGrid biome) { - DefaultChunkGenerator3D.biomes(world, chunkX, chunkZ, biome, main); - } - - @Override - public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) { - return new Sampler2D(chunkX, chunkZ, provider, world, elevationSmooth); - } - - @Override - public List getPopulators() { - return blockPopulators; - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java b/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java deleted file mode 100644 index 01ddbe380..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/generators/DefaultChunkGenerator3D.java +++ /dev/null @@ -1,262 +0,0 @@ -package com.dfsek.terra.world.generation.generators; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.block.data.Bisected; -import com.dfsek.terra.api.platform.block.data.Slab; -import com.dfsek.terra.api.platform.block.data.Stairs; -import com.dfsek.terra.api.platform.block.data.Waterlogged; -import com.dfsek.terra.api.platform.world.BiomeGrid; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkData; -import com.dfsek.terra.api.util.world.PaletteUtil; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.api.world.palette.Palette; -import com.dfsek.terra.api.world.palette.SinglePalette; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.profiler.ProfileFrame; -import com.dfsek.terra.world.Carver; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.carving.NoiseCarver; -import com.dfsek.terra.world.generation.math.samplers.Sampler; -import com.dfsek.terra.world.generation.math.samplers.Sampler3D; -import com.dfsek.terra.world.population.CavePopulator; -import com.dfsek.terra.world.population.FloraPopulator; -import com.dfsek.terra.world.population.OrePopulator; -import com.dfsek.terra.world.population.StructurePopulator; -import com.dfsek.terra.world.population.TreePopulator; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Random; - -public class DefaultChunkGenerator3D implements TerraChunkGenerator { - private final ConfigPack configPack; - private final TerraPlugin main; - private final BlockType water; - private final SinglePalette blank; - private final List blockPopulators = new ArrayList<>(); - - private final Carver carver; - - public DefaultChunkGenerator3D(ConfigPack c, TerraPlugin main) { - this.configPack = c; - this.main = main; - - blockPopulators.add(new CavePopulator(main)); - blockPopulators.add(new StructurePopulator(main)); - blockPopulators.add(new OrePopulator(main)); - blockPopulators.add(new TreePopulator(main)); - blockPopulators.add(new FloraPopulator(main)); - - carver = new NoiseCarver(new Range(0, 255), main.getWorldHandle().createBlockData("minecraft:air"), main); - water = main.getWorldHandle().createBlockData("minecraft:water").getBlockType(); - blank = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:air")); - } - - @Override - public boolean isParallelCapable() { - return true; - } - - @Override - public boolean shouldGenerateCaves() { - return configPack.getTemplate().vanillaCaves(); - } - - @Override - public boolean shouldGenerateDecorations() { - return configPack.getTemplate().vanillaDecorations(); - } - - @Override - public boolean shouldGenerateMobs() { - return configPack.getTemplate().vanillaMobs(); - } - - @Override - public boolean shouldGenerateStructures() { - return configPack.getTemplate().vanillaStructures(); - } - - @Override - public ConfigPack getConfigPack() { - return configPack; - } - - @Override - public TerraPlugin getMain() { - return main; - } - - @Override - @SuppressWarnings({"try"}) - public ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkData chunk) { - try(ProfileFrame ignore = main.getProfiler().profile("chunk_base_3d")) { - TerraWorld tw = main.getWorld(world); - BiomeProvider grid = tw.getBiomeProvider(); - - if(!tw.isSafe()) return chunk; - int xOrig = (chunkX << 4); - int zOrig = (chunkZ << 4); - - Sampler sampler = tw.getConfig().getSamplerCache().getChunk(chunkX, chunkZ); - - for(int x = 0; x < 16; x++) { - for(int z = 0; z < 16; z++) { - int paletteLevel = 0; - - int cx = xOrig + x; - int cz = zOrig + z; - - TerraBiome b = grid.getBiome(cx, cz); - BiomeTemplate c = ((UserDefinedBiome) b).getConfig(); - - int sea = c.getSeaLevel(); - Palette seaPalette = c.getOceanPalette(); - - boolean justSet = false; - BlockData data = null; - for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { - if(sampler.sample(x, y, z) > 0) { - justSet = true; - data = PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel, cx, y, cz); - chunk.setBlock(x, y, z, data); - if(paletteLevel == 0 && c.doSlabs() && y < 255) { - prepareBlockPartFloor(data, chunk.getBlockData(x, y + 1, z), chunk, new Vector3(x, y + 1, z), c.getSlabPalettes(), - c.getStairPalettes(), c.getSlabThreshold(), sampler); - } - paletteLevel++; - } else if(y <= sea) { - chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig)); - if(justSet && c.doSlabs()) { - prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector3(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler); - } - justSet = false; - paletteLevel = 0; - } else { - if(justSet && c.doSlabs()) { - prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector3(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler); - } - justSet = false; - paletteLevel = 0; - } - } - } - } - if(configPack.getTemplate().doBetaCarvers()) { - carver.carve(world, chunkX, chunkZ, chunk); - } - return chunk; - } - } - - private void prepareBlockPartFloor(BlockData down, BlockData orig, ChunkData chunk, Vector3 block, Map> slabs, - Map> stairs, double thresh, Sampler sampler) { - if(sampler.sample(block.getX(), block.getY() - 0.4, block.getZ()) > thresh) { - if(stairs != null) { - Palette stairPalette = stairs.get(down.getBlockType()); - if(stairPalette != null) { - BlockData stair = stairPalette.get(0, block.getX(), block.getY(), block.getZ()).clone(); - if(stair instanceof Stairs) { - Stairs stairNew = (Stairs) stair; - if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part. - } - } - } - BlockData slab = slabs.getOrDefault(down.getBlockType(), blank).get(0, block.getX(), block.getY(), block.getZ()); - if(slab instanceof Waterlogged) { - ((Waterlogged) slab).setWaterlogged(orig.getBlockType().equals(water)); - } else if(orig.getBlockType().equals(water)) return; - chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), slab); - } - } - - private void prepareBlockPartCeiling(BlockData up, BlockData orig, ChunkData chunk, Vector3 block, Map> slabs, - Map> stairs, double thresh, Sampler sampler) { - if(sampler.sample(block.getX(), block.getY() + 0.4, block.getZ()) > thresh) { - if(stairs != null) { - Palette stairPalette = stairs.get(up.getBlockType()); - if(stairPalette != null) { - BlockData stair = stairPalette.get(0, block.getX(), block.getY(), block.getZ()).clone(); - if(stair instanceof Stairs) { - Stairs stairNew = (Stairs) stair.clone(); - stairNew.setHalf(Bisected.Half.TOP); - if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part. - } - } - } - BlockData slab = slabs.getOrDefault(up.getBlockType(), blank).get(0, block.getX(), block.getY(), block.getZ()).clone(); - if(slab instanceof Bisected) ((Bisected) slab).setHalf(Bisected.Half.TOP); - if(slab instanceof Slab) ((Slab) slab).setType(Slab.Type.TOP); - if(slab instanceof Waterlogged) { - ((Waterlogged) slab).setWaterlogged(orig.getBlockType().equals(water)); - } else if(orig.getBlockType().equals(water)) return; // Only replace water if waterlogged. - chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), slab); - } - } - - private boolean placeStair(BlockData orig, ChunkData chunk, Vector3 block, double thresh, Sampler sampler, Stairs stairNew) { - - if(sampler.sample(block.getBlockX() - 0.55, block.getY(), block.getZ()) > thresh) { - - stairNew.setFacing(BlockFace.WEST); - } else if(sampler.sample(block.getBlockX(), block.getY(), block.getZ() - 0.55) > thresh) { - stairNew.setFacing(BlockFace.NORTH); - } else if(sampler.sample(block.getBlockX(), block.getY(), block.getZ() + 0.55) > thresh) { - stairNew.setFacing(BlockFace.SOUTH); - } else if(sampler.sample(block.getX() + 0.55, block.getY(), block.getZ()) > thresh) { - stairNew.setFacing(BlockFace.EAST); - } else stairNew = null; - if(stairNew != null) { - if(orig.getBlockType().equals(water)) stairNew.setWaterlogged(orig.getBlockType().equals(water)); - chunk.setBlock(block.getBlockX(), block.getBlockY(), block.getBlockZ(), stairNew); - return true; - } - return false; - } - - @SuppressWarnings({"try"}) - static void biomes(@NotNull World world, int chunkX, int chunkZ, @NotNull BiomeGrid biome, TerraPlugin main) { - try(ProfileFrame ignore = main.getProfiler().profile("biomes")) { - int xOrig = (chunkX << 4); - int zOrig = (chunkZ << 4); - BiomeProvider grid = main.getWorld(world).getBiomeProvider(); - for(int x = 0; x < 4; x++) { - for(int z = 0; z < 4; z++) { - int cx = xOrig + (x << 2); - int cz = zOrig + (z << 2); - TerraBiome b = grid.getBiome(cx, cz); - - biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz)); - } - } - } - } - - @Override - public void generateBiomes(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, @NotNull BiomeGrid biome) { - biomes(world, chunkX, chunkZ, biome, main); - } - - @Override - public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) { - return new Sampler3D(chunkX, chunkZ, provider, world, elevationSmooth); - } - - @Override - public List getPopulators() { - return blockPopulators; - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/SamplerCache.java b/common/src/main/java/com/dfsek/terra/world/generation/math/SamplerCache.java deleted file mode 100644 index e9965d49b..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/SamplerCache.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dfsek.terra.world.generation.math; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.generation.math.samplers.Sampler; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import net.jafama.FastMath; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public class SamplerCache { - private final LoadingCache cache; - - public SamplerCache(TerraPlugin main, TerraWorld world) { - cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getSamplerCache()) - .build(new CacheLoader() { - @Override - public Sampler load(@NotNull Long key) { - int cx = (int) (key >> 32); - int cz = (int) key.longValue(); - return world.getWorld().getTerraGenerator().createSampler(cx, cz, world.getBiomeProvider(), world.getWorld(), world.getConfig().getTemplate().getElevationBlend()); - } - }); - } - - public Sampler get(int x, int z) { - int cx = FastMath.floorDiv(x, 16); - int cz = FastMath.floorDiv(z, 16); - return getChunk(cx, cz); - } - - public Sampler getChunk(int cx, int cz) { - long key = MathUtil.squash(cx, cz); - return cache.getUnchecked(key); - } - - public void clear() { - cache.invalidateAll(); - cache.cleanUp(); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator.java deleted file mode 100644 index a17757c9f..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.world.generation.math.interpolation; - -import com.dfsek.terra.api.util.mutable.MutableInteger; -import com.dfsek.terra.api.world.biome.Generator; - -import java.util.Map; - -public interface ChunkInterpolator { - /** - * Gets the noise at a pair of internal chunk coordinates. - * - * @param x The internal X coordinate (0-15). - * @param z The internal Z coordinate (0-15). - * @return double - The interpolated noise at the coordinates. - */ - double getNoise(double x, double y, double z); - - default double getNoise(int x, int y, int z) { // Floating-point modulus operations are expensive. This allows implementations to optionally handle integers separately. - return getNoise((double) x, y, z); - } - - - default double computeNoise(Map gens, double x, double y, double z) { - double n = 0; - double div = 0; - for(Map.Entry entry : gens.entrySet()) { - Generator gen = entry.getKey(); - int weight = entry.getValue().get(); - double noise = computeNoise(gen, x, y, z); - - n += noise * weight; - div += gen.getWeight() * weight; - } - return n / div; - } - - double computeNoise(Generator generator, double x, double y, double z); -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator2D.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator2D.java deleted file mode 100644 index 27c0d42e7..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator2D.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.dfsek.terra.world.generation.math.interpolation; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.mutable.MutableInteger; -import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import net.jafama.FastMath; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.BiFunction; - -/** - * Class to abstract away the Interpolators needed to generate a chunk.
- * Contains method to get interpolated noise at a coordinate within the chunk. - */ -public class ChunkInterpolator2D implements ChunkInterpolator { - private final Interpolator[][] interpGrid = new Interpolator[4][4]; - private final BiFunction noiseGetter; - - /** - * Instantiates a 3D ChunkInterpolator3D at a pair of chunk coordinates. - * - * @param chunkX X coordinate of the chunk. - * @param chunkZ Z coordinate of the chunk. - * @param provider Biome Provider to use for biome fetching. - */ - public ChunkInterpolator2D(World w, int chunkX, int chunkZ, BiomeProvider provider, BiFunction noiseGetter) { - this.noiseGetter = noiseGetter; - int xOrigin = chunkX << 4; - int zOrigin = chunkZ << 4; - - double[][] noiseStorage = new double[5][5]; - - for(int x = 0; x < 5; x++) { - for(int z = 0; z < 5; z++) { - Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w); - Map genMap = new HashMap<>(); - - int step = generator.getBlendStep(); - int blend = generator.getBlendDistance(); - - for(int xi = -blend; xi <= blend; xi++) { - for(int zi = -blend; zi <= blend; zi++) { - genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1 - } - } - - noiseStorage[x][z] = computeNoise(genMap, (x << 2) + xOrigin, 0, (z << 2) + zOrigin); - } - } - - for(int x = 0; x < 4; x++) { - for(int z = 0; z < 4; z++) { - interpGrid[x][z] = new Interpolator( - noiseStorage[x][z], - noiseStorage[x + 1][z], - noiseStorage[x][z + 1], - noiseStorage[x + 1][z + 1]); - } - } - } - - private static int reRange(int value, int high) { - return FastMath.max(FastMath.min(value, high), 0); - } - - public double computeNoise(Generator generator, double x, double y, double z) { - return noiseGetter.apply(generator, new Vector3(x, y, z)); - } - - /** - * Gets the noise at a pair of internal chunk coordinates. - * - * @param x The internal X coordinate (0-15). - * @param z The internal Z coordinate (0-15). - * @return double - The interpolated noise at the coordinates. - */ - @Override - public double getNoise(double x, double y, double z) { - return interpGrid[reRange(((int) x) / 4, 3)][reRange(((int) z) / 4, 3)].bilerp((x % 4) / 4, (z % 4) / 4); - } - - public double getNoise(int x, int y, int z) { - return interpGrid[x / 4][z / 4].bilerp((double) (x % 4) / 4, (double) (z % 4) / 4); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator3D.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator3D.java deleted file mode 100644 index 9d71d8774..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ChunkInterpolator3D.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.dfsek.terra.world.generation.math.interpolation; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.mutable.MutableInteger; -import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import net.jafama.FastMath; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.BiFunction; - -/** - * Class to abstract away the Interpolators needed to generate a chunk.
- * Contains method to get interpolated noise at a coordinate within the chunk. - */ -public class ChunkInterpolator3D implements ChunkInterpolator { - private final Interpolator3[][][] interpGrid; - private final BiFunction noiseGetter; - - private final int min; - private final int max; - - /** - * Instantiates a 3D ChunkInterpolator3D at a pair of chunk coordinates. - * - * @param chunkX X coordinate of the chunk. - * @param chunkZ Z coordinate of the chunk. - * @param provider Biome Provider to use for biome fetching. - */ - public ChunkInterpolator3D(World w, int chunkX, int chunkZ, BiomeProvider provider, BiFunction noiseGetter) { - this.noiseGetter = noiseGetter; - int xOrigin = chunkX << 4; - int zOrigin = chunkZ << 4; - - this.max = w.getMaxHeight(); - this.min = w.getMinHeight(); - int range = max - min + 1; - - int size = range >> 2; - - interpGrid = new Interpolator3[4][size][4]; - - double[][][] noiseStorage = new double[5][5][size + 1]; - - for(int x = 0; x < 5; x++) { - for(int z = 0; z < 5; z++) { - Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w); - Map genMap = new HashMap<>(); - - int step = generator.getBlendStep(); - int blend = generator.getBlendDistance(); - - for(int xi = -blend; xi <= blend; xi++) { - for(int zi = -blend; zi <= blend; zi++) { - genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1 - } - } - - for(int y = 0; y < size + 1; y++) { - noiseStorage[x][z][y] = computeNoise(genMap, (x << 2) + xOrigin, (y << 2) + min, (z << 2) + zOrigin); - } - } - } - - for(int x = 0; x < 4; x++) { - for(int z = 0; z < 4; z++) { - for(int y = 0; y < size; y++) { - interpGrid[x][y][z] = new Interpolator3( - noiseStorage[x][z][y], - noiseStorage[x + 1][z][y], - noiseStorage[x][z][y + 1], - noiseStorage[x + 1][z][y + 1], - noiseStorage[x][z + 1][y], - noiseStorage[x + 1][z + 1][y], - noiseStorage[x][z + 1][y + 1], - noiseStorage[x + 1][z + 1][y + 1]); - } - } - } - } - - public double computeNoise(Generator generator, double x, double y, double z) { - return noiseGetter.apply(generator, new Vector3(x, y, z)); - } - - private static int reRange(int value, int high) { - return FastMath.max(FastMath.min(value, high), 0); - } - - /** - * Gets the noise at a pair of internal chunk coordinates. - * - * @param x The internal X coordinate (0-15). - * @param z The internal Z coordinate (0-15). - * @return double - The interpolated noise at the coordinates. - */ - @Override - public double getNoise(double x, double y, double z) { - return interpGrid[reRange(((int) x) / 4, 3)][(FastMath.max(FastMath.min(((int) y), max), min) - min) / 4][reRange(((int) z) / 4, 3)].trilerp((x % 4) / 4, (y % 4) / 4, (z % 4) / 4); - } - - public double getNoise(int x, int y, int z) { - return interpGrid[x / 4][(y - min) / 4][z / 4].trilerp((double) (x % 4) / 4, (double) (y % 4) / 4, (double) (z % 4) / 4); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ElevationInterpolator.java b/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ElevationInterpolator.java deleted file mode 100644 index 330cafdc8..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/interpolation/ElevationInterpolator.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.dfsek.terra.world.generation.math.interpolation; - -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.world.generation.WorldGenerator; - -public class ElevationInterpolator { - private final double[][] values = new double[18][18]; - - public ElevationInterpolator(World world, int chunkX, int chunkZ, BiomeProvider provider, int smooth) { - int xOrigin = chunkX << 4; - int zOrigin = chunkZ << 4; - - WorldGenerator[][] gens = new WorldGenerator[18 + 2 * smooth][18 + 2 * smooth]; - - // Precompute generators. - for(int x = -1 - smooth; x <= 16 + smooth; x++) { - for(int z = -1 - smooth; z <= 16 + smooth; z++) { - gens[x + 1 + smooth][z + 1 + smooth] = (WorldGenerator) provider.getBiome(xOrigin + x, zOrigin + z).getGenerator(world); - } - } - - for(int x = -1; x <= 16; x++) { - for(int z = -1; z <= 16; z++) { - double noise = 0; - double div = 0; - for(int xi = -smooth; xi <= smooth; xi++) { - for(int zi = -smooth; zi <= smooth; zi++) { - Generator gen = gens[x + 1 + smooth + xi][z + 1 + smooth + zi]; - noise += gen.getElevationSampler().getNoise(xOrigin + x, zOrigin + z) * gen.getElevationWeight(); - div += gen.getElevationWeight(); - } - } - values[x + 1][z + 1] = noise / div; - } - } - } - - public double getElevation(int x, int z) { - return values[x + 1][z + 1]; - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler.java b/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler.java deleted file mode 100644 index d7dffcbe4..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.dfsek.terra.world.generation.math.samplers; - -@FunctionalInterface -public interface Sampler { - double sample(double x, double y, double z); - - default double sample(int x, int y, int z) { // Floating-point modulus operations are expensive. This allows implementations to optionally handle integers separately. - return sample((double) x, y, z); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler2D.java b/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler2D.java deleted file mode 100644 index 8b1b53bf7..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler2D.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.world.generation.math.samplers; - -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator2D; -import com.dfsek.terra.world.generation.math.interpolation.ElevationInterpolator; -import net.jafama.FastMath; - -public class Sampler2D implements Sampler { - private final ChunkInterpolator2D interpolator; - private final ElevationInterpolator elevationInterpolator; - - public Sampler2D(int x, int z, BiomeProvider provider, World world, int elevationSmooth) { - this.interpolator = new ChunkInterpolator2D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoise(coord)); - this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth); - } - - @Override - public double sample(double x, double y, double z) { - return interpolator.getNoise(x, 0, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); - } - - @Override - public double sample(int x, int y, int z) { - return interpolator.getNoise(x, 0, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler3D.java b/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler3D.java deleted file mode 100644 index 6a6c085b6..000000000 --- a/common/src/main/java/com/dfsek/terra/world/generation/math/samplers/Sampler3D.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.dfsek.terra.world.generation.math.samplers; - -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.world.generation.math.interpolation.ChunkInterpolator3D; -import com.dfsek.terra.world.generation.math.interpolation.ElevationInterpolator; -import net.jafama.FastMath; - -public class Sampler3D implements Sampler { - private final ChunkInterpolator3D interpolator; - private final ElevationInterpolator elevationInterpolator; - - public Sampler3D(int x, int z, BiomeProvider provider, World world, int elevationSmooth) { - this.interpolator = new ChunkInterpolator3D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoise(coord)); - this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth); - } - - @Override - public double sample(double x, double y, double z) { - return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); - } - - @Override - public double sample(int x, int y, int z) { - return interpolator.getNoise(x, y, z) + elevationInterpolator.getElevation(FastMath.roundToInt(x), FastMath.roundToInt(z)); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java deleted file mode 100644 index 09ce5976a..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/CavePopulator.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.dfsek.terra.world.population; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.world.PopulationUtil; -import com.dfsek.terra.api.world.generation.Chunkified; -import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.carving.UserDefinedCarver; -import com.dfsek.terra.config.pack.WorldConfig; -import com.dfsek.terra.config.templates.CarverTemplate; -import com.dfsek.terra.profiler.ProfileFrame; -import com.dfsek.terra.world.TerraWorld; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Random; -import java.util.Set; - -public class CavePopulator implements TerraBlockPopulator, Chunkified { - private static final Map shiftStorage = new HashMap<>(); // Persist BlockData created for shifts, to avoid re-calculating each time. - private final TerraPlugin main; - - public CavePopulator(TerraPlugin main) { - this.main = main; - } - - @SuppressWarnings("try") - @Override - public void populate(@NotNull World world, @NotNull Chunk chunk) { - TerraWorld tw = main.getWorld(world); - WorldHandle handle = main.getWorldHandle(); - BlockData AIR = handle.createBlockData("minecraft:air"); - try(ProfileFrame ignore = main.getProfiler().profile("carving")) { - Random random = PopulationUtil.getRandom(chunk); - if(!tw.isSafe()) return; - WorldConfig config = tw.getConfig(); - if(config.getTemplate().disableCarvers()) return; - - for(UserDefinedCarver c : config.getCarvers()) { - CarverTemplate template = c.getConfig(); - Map shiftCandidate = new HashMap<>(); - Set updateNeeded = new HashSet<>(); - c.carve(chunk.getX(), chunk.getZ(), world, (v, type) -> { - try(ProfileFrame ignored = main.getProfiler().profile("carving:" + c.getConfig().getID())) { - Block b = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ()); - BlockData m = b.getBlockData(); - BlockType re = m.getBlockType(); - switch(type) { - case CENTER: - if(template.getInner().canReplace(re)) { - b.setBlockData(template.getInner().get(v.getBlockY()).get(random), false); - if(template.getUpdate().contains(re)) updateNeeded.add(b); - if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m); - } - break; - case WALL: - if(template.getOuter().canReplace(re)) { - b.setBlockData(template.getOuter().get(v.getBlockY()).get(random), false); - if(template.getUpdate().contains(re)) updateNeeded.add(b); - if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m); - } - break; - case TOP: - if(template.getTop().canReplace(re)) { - b.setBlockData(template.getTop().get(v.getBlockY()).get(random), false); - if(template.getUpdate().contains(re)) updateNeeded.add(b); - if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m); - } - break; - case BOTTOM: - if(template.getBottom().canReplace(re)) { - b.setBlockData(template.getBottom().get(v.getBlockY()).get(random), false); - if(template.getUpdate().contains(re)) updateNeeded.add(b); - if(template.getShift().containsKey(re)) shiftCandidate.put(b.getLocation(), m); - } - break; - } - } - }); - for(Map.Entry entry : shiftCandidate.entrySet()) { - Location l = entry.getKey(); - Location mut = l.clone(); - BlockData orig = l.getBlock().getBlockData(); - do mut.subtract(0, 1, 0); - while(mut.getY() > world.getMinHeight() && mut.getBlock().getBlockData().matches(orig)); - try { - if(template.getShift().get(entry.getValue().getBlockType()).contains(mut.getBlock().getBlockData().getBlockType())) { - mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(entry.getValue().getBlockType(), BlockType::getDefaultData), false); - } - } catch(NullPointerException ignored) { - } - } - for(Block b : updateNeeded) { - BlockData orig = b.getBlockData(); - b.setBlockData(AIR, false); - b.setBlockData(orig, true); - } - } - - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/FloraPopulator.java b/common/src/main/java/com/dfsek/terra/world/population/FloraPopulator.java deleted file mode 100644 index 99c97f411..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/FloraPopulator.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.dfsek.terra.world.population; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.world.PopulationUtil; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.profiler.ProfileFrame; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.population.items.flora.FloraLayer; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -/** - * Populates Flora - */ -public class FloraPopulator implements TerraBlockPopulator { - private final TerraPlugin main; - - public FloraPopulator(TerraPlugin main) { - this.main = main; - } - - @SuppressWarnings("try") - @Override - public void populate(@NotNull World world, @NotNull Chunk chunk) { - TerraWorld tw = main.getWorld(world); - try(ProfileFrame ignore = main.getProfiler().profile("flora")) { - if(tw.getConfig().getTemplate().disableFlora()) return; - - if(!tw.isSafe()) return; - BiomeProvider provider = tw.getBiomeProvider(); - Map> layers = new HashMap<>(); - for(int x = 0; x < 16; x++) { - for(int z = 0; z < 16; z++) { - UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z); - Vector2 l = new Vector2(x, z); - layers.put(l, biome.getConfig().getFlora()); - } - } - - Random random = PopulationUtil.getRandom(chunk); - - int iter = 0; - boolean finished = false; - while(!finished) { - finished = true; - for(Map.Entry> entry : layers.entrySet()) { - if(entry.getValue().size() <= iter) continue; - finished = false; - FloraLayer layer = entry.getValue().get(iter); - if(layer.getDensity() >= random.nextDouble() * 100D) layer.place(chunk, entry.getKey()); - } - iter++; - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/OrePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/OrePopulator.java deleted file mode 100644 index 3d5c0966a..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/OrePopulator.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.dfsek.terra.world.population; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.profiler.ProfileFrame; -import com.dfsek.terra.world.TerraWorld; -import org.jetbrains.annotations.NotNull; - -import java.util.Random; - -public class OrePopulator implements TerraBlockPopulator { - private final TerraPlugin main; - - public OrePopulator(TerraPlugin main) { - this.main = main; - } - - @SuppressWarnings("try") - @Override - public void populate(@NotNull World world, @NotNull Chunk chunk) { - TerraWorld tw = main.getWorld(world); - try(ProfileFrame ignore = main.getProfiler().profile("ore")) { - if(tw.getConfig().getTemplate().disableOres()) return; - - if(!tw.isSafe()) return; - for(int cx = -1; cx <= 1; cx++) { - for(int cz = -1; cz <= 1; cz++) { - Random random = new FastRandom(MathUtil.getCarverChunkSeed(chunk.getX() + cx, chunk.getZ() + cz, world.getSeed())); - int originX = ((chunk.getX() + cx) << 4); - int originZ = ((chunk.getZ() + cz) << 4); - TerraBiome b = tw.getBiomeProvider().getBiome(originX + 8, originZ + 8); - BiomeTemplate config = ((UserDefinedBiome) b).getConfig(); - int finalCx = cx; - int finalCz = cz; - config.getOreHolder().forEach((id, orePair) -> { - try(ProfileFrame ignored = main.getProfiler().profile("ore:" + id)) { - int amount = orePair.getRight().getAmount().get(random); - for(int i = 0; i < amount; i++) { - Vector3 location = new Vector3(random.nextInt(16) + 16 * finalCx, orePair.getRight().getHeight().get(random), random.nextInt(16) + 16 * finalCz); - orePair.getLeft().generate(location, chunk, random); - } - } - }); - } - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java deleted file mode 100644 index 30346917c..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/StructurePopulator.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.world.population; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.MathUtil; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.structures.structure.Rotation; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.generation.Chunkified; -import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.config.pack.WorldConfig; -import com.dfsek.terra.profiler.ProfileFrame; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.population.items.TerraStructure; -import net.jafama.FastMath; -import org.jetbrains.annotations.NotNull; - -import java.util.Random; - -public class StructurePopulator implements TerraBlockPopulator, Chunkified { - private final TerraPlugin main; - - public StructurePopulator(TerraPlugin main) { - this.main = main; - } - - @SuppressWarnings("try") - @Override - public void populate(@NotNull World world, @NotNull Chunk chunk) { - TerraWorld tw = main.getWorld(world); - try(ProfileFrame ignore = main.getProfiler().profile("structure")) { - if(tw.getConfig().getTemplate().disableStructures()) return; - - int cx = (chunk.getX() << 4); - int cz = (chunk.getZ() << 4); - if(!tw.isSafe()) return; - BiomeProvider provider = tw.getBiomeProvider(); - WorldConfig config = tw.getConfig(); - for(TerraStructure conf : config.getStructures()) { - Location spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed()).toLocation(world); - - if(!((UserDefinedBiome) provider.getBiome(spawn)).getConfig().getStructures().contains(conf)) - continue; - Random random = new FastRandom(MathUtil.getCarverChunkSeed(FastMath.floorDiv(spawn.getBlockX(), 16), FastMath.floorDiv(spawn.getBlockZ(), 16), world.getSeed())); - conf.getStructure().get(random).execute(spawn.setY(conf.getSpawnStart().get(random)), chunk, random, Rotation.fromDegrees(90 * random.nextInt(4))); - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/TreePopulator.java b/common/src/main/java/com/dfsek/terra/world/population/TreePopulator.java deleted file mode 100644 index 5dd58fb92..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/TreePopulator.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.dfsek.terra.world.population; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.world.PopulationUtil; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.profiler.ProfileFrame; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.population.items.tree.TreeLayer; -import net.jafama.FastMath; -import org.jetbrains.annotations.NotNull; - -import java.util.Random; - - -public class TreePopulator implements TerraBlockPopulator { - private final TerraPlugin main; - - public TreePopulator(TerraPlugin main) { - this.main = main; - } - - private static int offset(Random r, int i) { - return FastMath.min(FastMath.max(i + r.nextInt(3) - 1, 0), 15); - } - - @Override - @SuppressWarnings("try") - public void populate(@NotNull World world, @NotNull Chunk chunk) { - TerraWorld tw = main.getWorld(world); - try(ProfileFrame ignore = main.getProfiler().profile("tree")) { - if(tw.getConfig().getTemplate().disableTrees()) return; - - if(!tw.isSafe()) return; - BiomeProvider provider = tw.getBiomeProvider(); - Random random = PopulationUtil.getRandom(chunk); - for(int x = 0; x < 16; x += 2) { - for(int z = 0; z < 16; z += 2) { - UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z); - for(TreeLayer layer : biome.getConfig().getTrees()) { - if(layer.getDensity() >= random.nextDouble() * 100) { - layer.place(chunk, new Vector2(offset(random, x), offset(random, z))); - } - } - } - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/PlaceableLayer.java b/common/src/main/java/com/dfsek/terra/world/population/items/PlaceableLayer.java deleted file mode 100644 index e150d92fe..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/PlaceableLayer.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.dfsek.terra.world.population.items; - -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; - -public abstract class PlaceableLayer { - protected final double density; - protected final Range level; - protected final ProbabilityCollection layer; - protected final NoiseSampler noise; - - public PlaceableLayer(double density, Range level, ProbabilityCollection layer, NoiseSampler noise) { - this.density = density; - this.level = level; - this.layer = layer; - this.noise = noise; - } - - public NoiseSampler getNoise() { - return noise; - } - - public double getDensity() { - return density; - } - - public Range getLevel() { - return level; - } - - public ProbabilityCollection getLayer() { - return layer; - } - - public abstract void place(Chunk chunk, Vector2 coords); -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/TerraStructure.java b/common/src/main/java/com/dfsek/terra/world/population/items/TerraStructure.java deleted file mode 100644 index f3976fbab..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/TerraStructure.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.dfsek.terra.world.population.items; - -import com.dfsek.terra.api.math.GridSpawn; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.config.templates.StructureTemplate; - -public class TerraStructure { - private final ProbabilityCollection structure; - private final Range spawnStart; - private final GridSpawn spawn; - private final StructureTemplate template; - - public TerraStructure(ProbabilityCollection structures, Range spawnStart, GridSpawn spawn, StructureTemplate template) { - this.structure = structures; - this.spawnStart = spawnStart; - this.spawn = spawn; - this.template = template; - } - - public StructureTemplate getTemplate() { - return template; - } - - public ProbabilityCollection getStructure() { - return structure; - } - - public Range getSpawnStart() { - return spawnStart; - } - - public GridSpawn getSpawn() { - return spawn; - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/flora/BlockFlora.java b/common/src/main/java/com/dfsek/terra/world/population/items/flora/BlockFlora.java deleted file mode 100644 index dbc714388..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/flora/BlockFlora.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.dfsek.terra.world.population.items.flora; - -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.util.GlueList; -import com.dfsek.terra.api.world.flora.Flora; - -import java.util.List; - -/** - * Flora that is just 1 layer of a single block. - */ -public class BlockFlora implements Flora { - - private final BlockData data; - - public BlockFlora(BlockData data) { - this.data = data; - } - - @Override - public List getValidSpawnsAt(Chunk chunk, int x, int z, Range range) { - Block current = chunk.getBlock(x, range.getMin(), z); - List blocks = new GlueList<>(); - for(int y : range) { - if(y > 255 || y < 0) continue; - current = current.getRelative(BlockFace.UP); - if(current.getType().isSolid() && current.getRelative(BlockFace.UP).isEmpty()) { - blocks.add(current); // Add all blocks that are solid with air directly above. - } - } - return blocks; - } - - @Override - public boolean plant(Location location) { - location.add(0, 1, 0).getBlock().setBlockData(data, true); - return true; - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/flora/ConstantFlora.java b/common/src/main/java/com/dfsek/terra/world/population/items/flora/ConstantFlora.java deleted file mode 100644 index d7bec46bf..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/flora/ConstantFlora.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.world.population.items.flora; - -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.util.GlueList; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.api.world.flora.Flora; - -import java.util.List; - -public class ConstantFlora implements Flora { - private final List data; - - private final MaterialSet spawns; - - public ConstantFlora(MaterialSet spawns, List data) { - this.data = data; - this.spawns = spawns; - } - - @Override - public List getValidSpawnsAt(Chunk chunk, int x, int z, Range check) { - List blocks = new GlueList<>(); - for(int y : check) { - Block block = chunk.getBlock(x, y, z); - if(spawns.contains(block.getType()) && valid(block)) { - blocks.add(chunk.getBlock(x, y, z)); - } - } - return blocks; - } - - private boolean valid(Block block) { - for(int i = 1; i < data.size() + 1; i++) { - block = block.getRelative(BlockFace.UP); - if(!block.isEmpty()) return false; - } - return true; - } - - @Override - public boolean plant(Location l) { - for(int i = 1; i < data.size() + 1; i++) { - l.clone().add(0, i, 0).getBlock().setBlockData(data.get(i - 1), false); - } - return true; - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/flora/FloraLayer.java b/common/src/main/java/com/dfsek/terra/world/population/items/flora/FloraLayer.java deleted file mode 100644 index 579b70035..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/flora/FloraLayer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dfsek.terra.world.population.items.flora; - -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.flora.Flora; -import com.dfsek.terra.world.population.items.PlaceableLayer; - -public class FloraLayer extends PlaceableLayer { - - public FloraLayer(double density, Range level, ProbabilityCollection layer, NoiseSampler noise) { - super(density, level, layer, noise); - } - - public double getDensity() { - return density; - } - - @Override - public void place(Chunk chunk, Vector2 coords) { - Flora item = layer.get(noise, (chunk.getX() << 4) + coords.getX(), (chunk.getZ() << 4) + coords.getZ()); - item.getValidSpawnsAt(chunk, (int) coords.getX(), (int) coords.getZ(), level).forEach(block -> item.plant(block.getLocation())); - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/flora/TerraFlora.java b/common/src/main/java/com/dfsek/terra/world/population/items/flora/TerraFlora.java deleted file mode 100644 index 0893d1c92..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/flora/TerraFlora.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.dfsek.terra.world.population.items.flora; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Directional; -import com.dfsek.terra.api.platform.block.data.MultipleFacing; -import com.dfsek.terra.api.platform.block.data.Rotatable; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.util.GlueList; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.api.world.flora.Flora; -import com.dfsek.terra.api.world.palette.Palette; -import net.jafama.FastMath; - -import java.util.ArrayList; -import java.util.List; - -public class TerraFlora implements Flora { - private final Palette floraPalette; - private final boolean physics; - private final boolean ceiling; - - private final MaterialSet irrigable; - - private final MaterialSet spawnable; - private final MaterialSet replaceable; - - private final MaterialSet testRotation; - - private final int maxPlacements; - - private final Search search; - - private final boolean spawnBlacklist; - - private final int irrigableOffset; - - private final TerraPlugin main; - - public TerraFlora(Palette floraPalette, boolean physics, boolean ceiling, MaterialSet irrigable, MaterialSet spawnable, MaterialSet replaceable, MaterialSet testRotation, int maxPlacements, Search search, boolean spawnBlacklist, int irrigableOffset, TerraPlugin main) { - this.floraPalette = floraPalette; - this.physics = physics; - this.testRotation = testRotation; - this.spawnBlacklist = spawnBlacklist; - this.ceiling = ceiling; - this.irrigable = irrigable; - this.spawnable = spawnable; - this.replaceable = replaceable; - this.maxPlacements = maxPlacements; - this.search = search; - this.irrigableOffset = irrigableOffset; - this.main = main; - } - - @Override - public List getValidSpawnsAt(Chunk chunk, int x, int z, Range range) { - int size = floraPalette.getSize(); - Block current = chunk.getBlock(x, search.equals(Search.UP) ? range.getMin() : range.getMax(), z); - List blocks = new ArrayList<>(); - for(int y : range) { - if(y > 255 || y < 0) continue; - current = current.getRelative(search.equals(Search.UP) ? BlockFace.UP : BlockFace.DOWN); - if((spawnBlacklist != spawnable.contains(current.getType())) && isIrrigated(current.getRelative(BlockFace.UP, irrigableOffset)) && valid(size, current)) { - blocks.add(current); - if(maxPlacements > 0 && blocks.size() >= maxPlacements) break; - } - } - return blocks; - } - - private boolean valid(int size, Block block) { - for(int i = 0; i < size; i++) { // Down if ceiling, up if floor - if(block.getY() + 1 > 255 || block.getY() < 0) return false; - block = block.getRelative(ceiling ? BlockFace.DOWN : BlockFace.UP); - if(!replaceable.contains(block.getType())) return false; - } - return true; - } - - private boolean isIrrigated(Block b) { - if(irrigable == null) return true; - return irrigable.contains(b.getRelative(BlockFace.NORTH).getType()) - || irrigable.contains(b.getRelative(BlockFace.SOUTH).getType()) - || irrigable.contains(b.getRelative(BlockFace.EAST).getType()) - || irrigable.contains(b.getRelative(BlockFace.WEST).getType()); - } - - - @Override - public boolean plant(Location location) { - WorldHandle handle = main.getWorldHandle(); - - boolean doRotation = testRotation.size() > 0; - int size = floraPalette.getSize(); - int c = ceiling ? -1 : 1; - - List faces = doRotation ? getFaces(location.clone().add(0, c, 0).getBlock()) : new GlueList<>(); - if(doRotation && faces.size() == 0) return false; // Don't plant if no faces are valid. - - for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor - int lvl = (FastMath.abs(i)); - BlockData data = floraPalette.get((ceiling ? lvl : size - lvl - 1), location.getX(), location.getY(), location.getZ()).clone(); - if(doRotation) { - BlockFace oneFace = faces.get(new FastRandom(location.getBlockX() ^ location.getBlockZ()).nextInt(faces.size())); // Get random face. - if(data instanceof Directional) { - ((Directional) data).setFacing(oneFace.getOppositeFace()); - } else if(data instanceof MultipleFacing) { - MultipleFacing o = (MultipleFacing) data; - for(BlockFace face : o.getFaces()) o.setFace(face, false); - for(BlockFace face : faces) o.setFace(face, true); - } else if(data instanceof Rotatable) { - ((Rotatable) data).setRotation(oneFace); - } - } - location.clone().add(0, i + c, 0).getBlock().setBlockData(data, physics); - } - return true; - } - - private List getFaces(Block b) { - List faces = new GlueList<>(); - test(faces, BlockFace.NORTH, b); - test(faces, BlockFace.SOUTH, b); - test(faces, BlockFace.EAST, b); - test(faces, BlockFace.WEST, b); - return faces; - } - - private void test(List faces, BlockFace f, Block b) { - if(testRotation.contains(b.getRelative(f).getType())) faces.add(f); - } - - public enum Search { - UP, - DOWN - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java deleted file mode 100644 index 2bc782196..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/DeformedSphereOre.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.dfsek.terra.world.population.items.ores; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.noise.samplers.noise.simplex.OpenSimplex2Sampler; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.util.collections.MaterialSet; - -import java.util.Map; -import java.util.Random; - -public class DeformedSphereOre extends Ore { - private final double deform; - private final double deformFrequency; - private final Range size; - - public DeformedSphereOre(BlockData material, MaterialSet replaceable, boolean applyGravity, double deform, double deformFrequency, Range size, TerraPlugin main, Map materials) { - super(material, replaceable, applyGravity, main, materials); - this.deform = deform; - this.deformFrequency = deformFrequency; - this.size = size; - } - - - @Override - public void generate(Vector3 origin, Chunk c, Random r) { - OpenSimplex2Sampler ore = new OpenSimplex2Sampler(r.nextInt()); - ore.setFrequency(deformFrequency); - int rad = size.get(r); - for(int x = -rad; x <= rad; x++) { - for(int y = -rad; y <= rad; y++) { - for(int z = -rad; z <= rad; z++) { - Vector3 oreLoc = origin.clone().add(new Vector3(x, y, z)); - if(oreLoc.getBlockX() > 15 || oreLoc.getBlockZ() > 15 || oreLoc.getBlockY() > c.getWorld().getMaxHeight() || oreLoc.getBlockX() < 0 || oreLoc.getBlockZ() < 0 || oreLoc.getBlockY() < c.getWorld().getMinHeight()) - continue; - if(oreLoc.distance(origin) < (rad + 0.5) * ((ore.getNoise(x, y, z) + 1) * deform)) { - Block b = c.getBlock(oreLoc.getBlockX(), oreLoc.getBlockY(), oreLoc.getBlockZ()); - BlockType type = b.getType(); - if(getReplaceable().contains(type) && b.getLocation().getY() >= c.getWorld().getMinHeight()) - b.setBlockData(getMaterial(type), isApplyGravity()); - } - } - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java deleted file mode 100644 index d52bdf4a0..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/Ore.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.dfsek.terra.world.population.items.ores; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.util.collections.MaterialSet; - -import java.util.Map; -import java.util.Random; - -public abstract class Ore { - - private final BlockData material; - private final MaterialSet replaceable; - private final boolean applyGravity; - protected TerraPlugin main; - private final Map materials; - - public Ore(BlockData material, MaterialSet replaceable, boolean applyGravity, TerraPlugin main, Map materials) { - this.material = material; - this.replaceable = replaceable; - this.applyGravity = applyGravity; - this.main = main; - this.materials = materials; - } - - public abstract void generate(Vector3 origin, Chunk c, Random r); - - public BlockData getMaterial(BlockType replace) { - return materials.getOrDefault(replace, material); - } - - public MaterialSet getReplaceable() { - return replaceable; - } - - public boolean isApplyGravity() { - return applyGravity; - } - - public enum Type { - VANILLA, SPHERE - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/OreConfig.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/OreConfig.java deleted file mode 100644 index 67048c34d..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/OreConfig.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.world.population.items.ores; - -import com.dfsek.terra.api.math.Range; - -public class OreConfig { - private final Range amount; - private final Range height; - - public OreConfig(Range amount, Range height) { - this.amount = amount; - this.height = height; - } - - public Range getAmount() { - return amount; - } - - public Range getHeight() { - return height; - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/OreHolder.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/OreHolder.java deleted file mode 100644 index 43e461895..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/OreHolder.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.dfsek.terra.world.population.items.ores; - -import com.dfsek.terra.api.util.GlueList; -import com.dfsek.terra.api.util.generic.pair.ImmutablePair; - -import java.util.List; -import java.util.function.BiConsumer; - -/** - * Holds ordered list of ores mapped to their configs. - */ -public class OreHolder { - private final List entries = new GlueList<>(); - - public void forEach(BiConsumer> consumer) { - entries.forEach(entry -> consumer.accept(entry.getId(), ImmutablePair.of(entry.getOre(), entry.getConfig()))); - } - - public OreHolder add(Ore ore, OreConfig config, String id) { - entries.add(new Entry(ore, config, id)); - return this; - } - - private static final class Entry { - private final Ore ore; - private final OreConfig config; - private final String id; - - private Entry(Ore ore, OreConfig config, String id) { - this.ore = ore; - this.config = config; - this.id = id; - } - - public OreConfig getConfig() { - return config; - } - - public Ore getOre() { - return ore; - } - - public String getId() { - return id; - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java b/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java deleted file mode 100644 index 0e5e5d4af..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/ores/VanillaOre.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.dfsek.terra.world.population.items.ores; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.util.collections.MaterialSet; -import net.jafama.FastMath; - -import java.util.Map; -import java.util.Random; - - -public class VanillaOre extends Ore { - private final Range sizeRange; - - public VanillaOre(BlockData material, MaterialSet replaceable, boolean applyGravity, Range size, TerraPlugin main, Map materials) { - super(material, replaceable, applyGravity, main, materials); - this.sizeRange = size; - } - - @Override - public void generate(Vector3 location, Chunk chunk, Random random) { - double size = sizeRange.get(random); - - int centerX = location.getBlockX(); - int centerZ = location.getBlockZ(); - int centerY = location.getBlockY(); - - - double f = random.nextFloat() * Math.PI; - - double fS = FastMath.sin(f) * size / 8.0F; - double fC = FastMath.cos(f) * size / 8.0F; - - double d1 = centerX + 8 + fS; - double d2 = centerX + 8 - fS; - double d3 = centerZ + 8 + fC; - double d4 = centerZ + 8 - fC; - - double d5 = centerY + random.nextInt(3) - 2D; - double d6 = centerY + random.nextInt(3) - 2D; - - for(int i = 0; i < size; i++) { - double iFactor = i / size; - - double d10 = random.nextDouble() * size / 16.0D; - double d11 = (FastMath.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0; - - int xStart = FastMath.roundToInt(FastMath.floor(d1 + (d2 - d1) * iFactor - d11 / 2.0D)); - int yStart = FastMath.roundToInt(FastMath.floor(d5 + (d6 - d5) * iFactor - d11 / 2.0D)); - int zStart = FastMath.roundToInt(FastMath.floor(d3 + (d4 - d3) * iFactor - d11 / 2.0D)); - - int xEnd = FastMath.roundToInt(FastMath.floor(d1 + (d2 - d1) * iFactor + d11 / 2.0D)); - int yEnd = FastMath.roundToInt(FastMath.floor(d5 + (d6 - d5) * iFactor + d11 / 2.0D)); - int zEnd = FastMath.roundToInt(FastMath.floor(d3 + (d4 - d3) * iFactor + d11 / 2.0D)); - - for(int x = xStart; x <= xEnd; x++) { - double d13 = (x + 0.5D - (d1 + (d2 - d1) * iFactor)) / (d11 / 2.0D); - - if(d13 * d13 < 1.0D) { - for(int y = yStart; y <= yEnd; y++) { - double d14 = (y + 0.5D - (d5 + (d6 - d5) * iFactor)) / (d11 / 2.0D); - if(d13 * d13 + d14 * d14 < 1.0D) { - for(int z = zStart; z <= zEnd; z++) { - double d15 = (z + 0.5D - (d3 + (d4 - d3) * iFactor)) / (d11 / 2.0D); - if(x > 15 || z > 15 || y > 255 || x < 0 || z < 0 || y < 0) continue; - Block block = chunk.getBlock(x, y, z); - BlockType type = block.getType(); - if((d13 * d13 + d14 * d14 + d15 * d15 < 1.0D) && getReplaceable().contains(type)) { - block.setBlockData(getMaterial(type), isApplyGravity()); - } - } - } - } - } - } - } - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/tree/TerraTree.java b/common/src/main/java/com/dfsek/terra/world/population/items/tree/TerraTree.java deleted file mode 100644 index 2576d2eca..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/tree/TerraTree.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.world.population.items.tree; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.structures.script.StructureScript; -import com.dfsek.terra.api.structures.structure.Rotation; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; - -import java.util.Random; - -public class TerraTree implements Tree { - private final MaterialSet spawnable; - private final int yOffset; - private final ProbabilityCollection structure; - - public TerraTree(MaterialSet spawnable, int yOffset, ProbabilityCollection structure) { - this.spawnable = spawnable; - this.yOffset = yOffset; - this.structure = structure; - } - - @Override - public synchronized boolean plant(Location location, Random random) { - return structure.get(random).executeDirect(location.clone().add(0, yOffset, 0), random, Rotation.fromDegrees(90 * random.nextInt(4))); - } - - @Override - public MaterialSet getSpawnable() { - return spawnable; - } -} diff --git a/common/src/main/java/com/dfsek/terra/world/population/items/tree/TreeLayer.java b/common/src/main/java/com/dfsek/terra/world/population/items/tree/TreeLayer.java deleted file mode 100644 index 707a062cc..000000000 --- a/common/src/main/java/com/dfsek/terra/world/population/items/tree/TreeLayer.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.world.population.items.tree; - -import com.dfsek.terra.api.math.Range; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.vector.Vector2; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.world.PopulationUtil; -import com.dfsek.terra.world.population.items.PlaceableLayer; - -public class TreeLayer extends PlaceableLayer { - - public TreeLayer(double density, Range level, ProbabilityCollection layer, NoiseSampler noise) { - super(density, level, layer, noise); - } - - @Override - public void place(Chunk chunk, Vector2 coords) { - Tree item = layer.get(noise, coords.getX(), coords.getZ()); - Block current = chunk.getBlock((int) coords.getX(), level.getMax(), (int) coords.getZ()); - for(int ignored : level) { - current = current.getRelative(BlockFace.DOWN); - if(item.getSpawnable().contains(current.getType())) { - item.plant(current.getLocation().add(0, 1, 0), PopulationUtil.getRandom(chunk, coords.hashCode())); - } - } - } -} diff --git a/common/src/main/resources/config.yml b/common/src/main/resources/config.yml deleted file mode 100644 index e7572c935..000000000 --- a/common/src/main/resources/config.yml +++ /dev/null @@ -1,12 +0,0 @@ -debug: false -data-save: PT6M -language: "en_us" -dump-default: true -biome-search-resolution: 4 -cache: - carver: 512 - structure: 32 - sampler: 128 - biome-provider: 32 -script: - max-recursion: 1000 \ No newline at end of file diff --git a/common/src/main/resources/lang/afr_sa.yml b/common/src/main/resources/lang/afr_sa.yml deleted file mode 100644 index 662be3461..000000000 --- a/common/src/main/resources/lang/afr_sa.yml +++ /dev/null @@ -1,122 +0,0 @@ -enable: - - "As u van Terra hou, oorweeg dit om die projek op Patreon te ondersteun!" - - "U kry toegang tot eksperimentele funksies voordat dit vrygestel word!" - - "Ondersteun die projek hier: https://www.patreon.com/dfsek" -disable: - - "Dankie dat u Terra gebruik!" -command: - debug-only: "Hierdie opdrag moet gebruik word as die ontfoutmodus geaktiveer is!" - player-only: "Hierdie opdrag is slegs vir spelers!" - invalid: "Ongeldige opdrag.(verwag %1$s argumente, argumente gevind is %2$s)." - players-only: "Hierdie opdrag is slegs vir spelers." - world: "This command must be executed in a Terra world!" - reload: "Terra instel herlaai" - reload-error: "Foute het voorgekom tydens die herlaai van Terra-konfigurasies. Gaan sien logboeke vir meer inligting." - version: "Hierdie bediener gebruik die Terra-weergawe \"%s\"" - main-menu: - - "--------------------Terra--------------------" - - "Herlaai - Herlaai konfigurasiedata" - - "bioom - Kry huidige bioom" - - "erts - Genereer 'n ertsader op die plek waar u te staan kom (vir foutopsporing)" - - "stoor-data - Stoor bevolkingsdata" - - "struktuur - Laai en stoor strukture" - - "profiel - Profielopsies" - - "beeld - Beeld / GUI-opsies" - biome: - biome-found: "Bioom geleë te (%1$s, %2$s)" - unable-to-locate: "Kan bioom nie opspoor nie." - invalid-radius: "Ongeldige radius: \"%s\"" - invalid: "Ongeldige Biome-ID: \"%s\"" - in: "Jy is in \"%s\"" - packs: - main: "Tans geïnstalleerde konfigurasiepakkette:" - pack: " - %1$s v%3$s by %2$s" - none: "Geen konfigurasiepakkette is geïnstalleer nie." - ore: - main-menu: - - "---------------Terra/erts---------------" - - "Genereer 'n ertsader by die blok waarna u kyk." - out-of-range: "Blok buite bereik" - invalid-ore: "Kan nie Erts vind nie \"%s\"" - geometry: - main-menu: - - "---------------Terra/meetkunde----------------" - - "Verskeie opsporingsopdragte vir voxel-meetkunde" - - "sfeer - Genereer 'n sfeer" - - "vervorming - Genereer 'n misvormde sfeer" - - "tube - Genereer 'n tube" - deform: - invalid-radius: "Ongeldige radius: \"%s\"" - invalid-deform: "Ongeldige vervorm: \"%s\"" - invalid-frequency: "Ongeldige frekwensie: \"%s\"" - sphere: - invalid-radius: "Ongeldige radius: \"%s\"" - tube: - invalid-radius: "Ongeldige radius: \"%s\"" - image: - main-menu: - - "---------------Terra/beeld---------------" - - "weergee - gee 'n beeld met 'n gegewe breedte en hoogte, wat later as 'n wêreld ingevoer kan word." - - "gui - Open debug GUI (moet in config geaktiveer word)" - gui: - main-menu: - - "-------------Terra/beeld/gui-------------" - - "rou - Open GUI met rou bioom-data" - - "stap - Gee data weer om die grense duideliker aan te dui" - debug: "Ontfoutmodus moet geaktiveer wees om die ontfout-GUI te gebruik! Die foutopsporing-GUI is NIE PRODUKSIEVEILIG NIE!" - render: - save: "Beeld gestoor as \"%s\"" - error: "Vout ondervind terwel die prent besig was om te genereer!" - profile: - main-menu: - - "---------------Terra/profiel---------------" - - "begin - Begin die profiel" - - "stop - stop die profiel" - - "navraag - Haal profiele-data op" - - "reset - Stel profieldata terug" - reset: "Profiler is teruggestel." - start: "Profiler het begin." - stop: "Profiler het opgehou." - structure: - main-menu: - - "---------------Terra/struktuur---------------" - - "uitvoer - voer u huidige WorldEdit-keuse uit as 'n Terra-struktuur." - - "laai - Laai 'n Terra-struktuur" - invalid-radius: "Ongeldig radius: \"%s\"" - invalid-rotation: "Ongeldige rotasie: \"%s\"" - invalid: "Ongeldig Struktuur ID: \"%s\"" - export: "struktuur gestoor na \"%s\"" -world-config: - loading: "Laai wêreldkonfigurasiewaardes vir wêreld %s..." - not-found: "Konfigurasie vir wêreld \"%s\" nie gevind nie. Kopieer standaardinstelling." - using-image: "Laai wêreld vanaf prent." - error: "Kon nie konfigurasie vir wêreld laai nie %s" - done: "Wêreldlading voltooi. Tyd verloop: %sms" -config-pack: - loaded: "Laai konfigurasie %1$s in %2$sms." -config: - loaded: "Laai %1$s vanaf %2$s" - loaded-all: "%1$s %2$s(s) gelaai in %3$sms." - error: - invalid-failover: "Ongeldige failover-tipe: \"%s\"" - duplicate: "Duplikaat-ID gevind in lêer: %s" - file: - - "Konfigurasiefout vir Terra-voorwerp. lêer: %1$s" - - "%2$s" - - "Stel dit reg voordat u verder gaan!" - generic: - - "Kon nie konfigurasies laai nie." - - "Rapporteer dit asseblief aan Terra." -warning: - no-population: "Geen bevolkingstukke is gelaai nie. As dit die eerste keer is dat u u bediener met Terra begin, of as u 'n nuwe wêreld skep, is dit normaal." -error: - severe-config: "N Ernstige konfigurasiefout het Terra verhoed om terrein op koördinate behoorlik te genereer by: %1$s, %2$s. Gaan u konfigurasie na vir foute. Enige konfiguratiefoute sal hierbo gerapporteer word." -debug: - data-save: "Bevolkingsdata vir wêreld \"%s\" is gestoor" -use-paper: - - "Dit lyk asof u Spigot/CraftBukkit gebruik." - - "terwel Terra &owel&r werk op Spigot, sal sommige funksies verlore gaan. (Terra is ongetoets op CraftBukkit; geen ondersteuning sal gegee word vir CraftBukkit)." - - "Skakel asseblief oor na Paper om die beste uit Terra te kry." - - "Plus bied Paper geweldige prestasieverbeterings ten opsigte van Spigot, en alle Spigot-inproppe moet met Paper werk!" - - "Gebruik Paper om die beste ervaring met Terra en al u inproppe te hê." - - "Lees meer op Paper se webwerf: https://papermc.io/" \ No newline at end of file diff --git a/common/src/main/resources/lang/cs_cz.yml b/common/src/main/resources/lang/cs_cz.yml deleted file mode 100644 index c01c6fcf9..000000000 --- a/common/src/main/resources/lang/cs_cz.yml +++ /dev/null @@ -1,122 +0,0 @@ -enable: - - "Pokud se vám líbí Terra, můžete nás podpořit na Patreon!" - - "Získáte přístup k experimentálním funkcím, než budou vydány!" - - "Podpořit projekt můžete zde: https://www.patreon.com/dfsek" -disable: - - "Děkujeme, že používáte Terra!" -command: - debug-only: "Tento příkaz musí být použit se zapnutým debug modem!" - player-only: "Tento příkaz je pouze pro hráče!" - invalid: "Neznámý příkaz. (Očekáváno %1$s argumentů, nalezeno %2$s)." - players-only: "Příkaz je pouze pro použití hráčem." - world: "Tento příkaz musí být použit v Terra světě!" - reload: "Obnoven Terra konfig." - reload-error: "Nastaly chyby při obnově Terra konfigurace. Podívejte se do logů pro více informací." - version: "Na tomto serveru běží Terra verze \"%1$s\", na platformě \"%2$s\"" - main-menu: - - "--------------------Terra--------------------" - - "reload - Obnoví konfigurační data" - - "biome - Ukáže aktuální biom" - - "ore - Generuje žílu rud v lokaci, ve směru kam se koukáte (Pro debugging)" - - "save-data - Uložit populační data" - - "structure - Nahrát a exportovat struktury" - - "profile - Profiler možnosti" - - "image - Obrázek/GUI možnosti" - biome: - biome-found: "Lokalizován biom na (%1$s, %2$s)" - unable-to-locate: "Nelze lokalizovat biom." - invalid-radius: "Nesprávný radius: \"%s\"" - invalid: "Nesprávné ID bomu: \"%s\"" - in: "Jste v \"%s\"" - packs: - main: "Aktuální instalované konfigurační balíčky:" - pack: " - %1$s v%3$s od %2$s" - none: "Žádné konfigurační balíčky nejsou nainstalovány." - ore: - main-menu: - - "---------------Terra/ore---------------" - - "Generuje žílu rud na bloku, na který koukáte." - out-of-range: "Blok mimo dosah" - invalid-ore: "Nelze nalézt Rudu \"%s\"" - geometry: - main-menu: - - "---------------Terra/geometry----------------" - - "Různé voxel geometrické debugging příkazy" - - "sphere - Generuje kouli" - - "deformsphere - Generuje deformovanou kouli" - - "tube - Generuje válec" - deform: - invalid-radius: "Nesprávný radius: \"%s\"" - invalid-deform: "Nesprávná deformace: \"%s\"" - invalid-frequency: "Nesprávná frekvence: \"%s\"" - sphere: - invalid-radius: "Nesprávný radius: \"%s\"" - tube: - invalid-radius: "Nesprávný radius: \"%s\"" - image: - main-menu: - - "---------------Terra/image---------------" - - "render - Vykreslí obrázek s danou šířkou a výškou, který může být později importován jako svět." - - "gui - Otevřít debug GUI (Musí být zapnuto v konfigu)" - gui: - main-menu: - - "-------------Terra/image/gui-------------" - - "raw - Otevře GUI s raw Biom daty" - - "step - Znovu vykreslí data k lepšímu zobrazení borderu" - debug: "Debug mod musí být zapnutý pro použití této možnosti! Debug GUI NENÍ PRODUKČNĚ BEZPEČNÉ!" - render: - save: "Uložen obrázek jako \"%s\"" - error: "Nastala chyba při generování obrázku!" - profile: - main-menu: - - "---------------Terra/profile---------------" - - "start - Zapne profiler" - - "stop - Vypne profiler" - - "query - Ukáže profiler data" - - "reset - Resetuje profiler data" - reset: "Profiler byl resetován." - start: "Profiler byl zapnut." - stop: "Profiler byl vypnut." - structure: - main-menu: - - "---------------Terra/structure---------------" - - "export - Export vašeho výběru WorldEdit jako Terra struktura." - - "load - Načíst Terra strukturu" - invalid-radius: "Nesprávný radius: \"%s\"" - invalid-rotation: "Nesprávná rotace: \"%s\"" - invalid: "Nesprávné ID struktury: \"%s\"" - export: "Uložena struktura do \"%s\"" -world-config: - load: "Načteny konfigurační hodnoty světa pro svět \"%s\"..." - not-found: "Konfigurace pro svět \"%s\" nenalezena. Kopíruji defaultní konfig." - using-image: "Načítám svět z obrázku." - error: "Nelze načíst konfigurace pro svět %s" - done: "Načítání světa \"%1$s\" dokončeno. Uplynulý čas: %2$sms" -config-pack: - loaded: "Konfigurační balíček %1$s v%4$s od %3$s byl načten za %2$sms." -config: - loaded: "Načten %1$s ze souboru %2$s" - loaded-all: "Načteno %1$s %2$s(s) za %3$sms." - error: - invalid-failover: "Nesprávný typ failover: \"%s\"" - duplicate: "Duplikační ID nalezeno v souboru: %s" - file: - - "Konfigurační chyba pro Terra objekt. Soubor: %1$s" - - "%2$s" - - "Opravte jej před pokračováním!" - generic: - - "Nastala chyba při načítání konfigurace." - - "Prosíme nahlašte to na Terra." -warning: - no-population: "Žádné populační chunky nebyly načteny. Pokud je to poprvé, co zapínáte server s Terra, či vytváříte nový svět, je tohle normální." -error: - severe-config: "Vážná konfigurační chyba zabránila Terra ze správné generace terénu na koordinátech: %1$s, %2$s. Prosíme zkontrolujte konfiguraci pro chyby. Jakékoli konfigurační chyby jsou vypsány výše." -debug: - data-save : "Uložena populační data." -use-paper: - - "Vypadá to, že používáte Spigot/CraftBukkit." - - "Ačkoli Terra &ofunguje&r na Spigot, některé funkce budou ztraceny. (Terra je netestována na CraftBukkit; žádná podpora nebude dána pro CraftBukkit)." - - "Pro nejvíce funkcí s Terra, použijte Paper." - - "Navíc, Paper přináší obrovské výkonnostní zlepešení než Spigot, a všechny Spigot pluginy by měli fungovat s Paper!" - - "Pro nejlepší zážitek s Terra a všemi pluginy, použijte prosím Paper." - - "Více info najdete na stránce Paperu: https://papermc.io/" diff --git a/common/src/main/resources/lang/da.yml b/common/src/main/resources/lang/da.yml deleted file mode 100644 index 7a0ab0920..000000000 --- a/common/src/main/resources/lang/da.yml +++ /dev/null @@ -1,122 +0,0 @@ -enable: - - "Hvis du kan lide Terra, kan du overveje at støtte projektet på Patreon!" - - "Du vil få adgang til eksperimentelle funktioner, før de udgives!" - - "Støt projektet her: https://www.patreon.com/dfsek" -disable: - - "Tak for at du bruger Terra!" -command: - debug-only: "Denne kommando skal bruges med fejlfindingstilstand aktiveret!" - player-only: "Denne kommando er kun til spillere!" - invalid: "Ugyldig kommando. (Forventede %1$s argumenter, fandt %2$s)." - players-only: "Kommando er kun til spillere." - world: "Denne kommando skal anvendes i en Terra verden!" - reload: "Genindlæste Terra konfigurationen." - reload-error: "Der opstod fejl under genindlæsning af Terra konfigurationer. Tjek logfilerne for at få flere oplysninger." - version: "Denne server kører Terra version \"%1$s\", implementerer Gaea version \"%2$s\"" - main-menu: - - "--------------------Terra--------------------" - - "reload - Genindlæs konfigurationsdataene" - - "biome - Få den nuværende biome" - - "ore - Generer en åre malm ved den lokation du står overfor (Til fejlfinding)" - - "save-data - Gem populations data" - - "structure - Indlæs og eksporter strukturer" - - "profile - Profiler indstillinger" - - "image - Billede/GUI indstillinger" - biome: - biome-found: "Lokaliserede biome ved (%1$s, %2$s)" - unable-to-locate: "Kan ikke lokalisere biome." - invalid-radius: "Ugyldig radius: \"%s\"" - invalid: "Ugyldigt Biome ID: \"%s\"" - in: "Du er i \"%s\"" - packs: - main: "Aktuelt installerede konfigurationspakker:" - pack: " - %1$s v%3$s ved %2$s" - none: "Ingen konfigurationspakker er installeret." - ore: - main-menu: - - "---------------Terra/malm---------------" - - "Genererer en åre malm ved den blok, du kigger på." - out-of-range: "Blok uden for rækkevidde" - invalid-ore: "Kan ikke finde Malm \"%s\"" - geometry: - main-menu: - - "---------------Terra/geometri----------------" - - "Forskellige kommandoer til fejlfinding af voxel-geometri" - - "sphere - Generer en kugle" - - "deformsphere - Generer en deformeret kugle" - - "tube - Generer et rør" - deform: - invalid-radius: "Ugyldig radius: \"%s\"" - invalid-deform: "Ugyldig deformering: \"%s\"" - invalid-frequency: "Ugyldig frekvens: \"%s\"" - sphere: - invalid-radius: "Ugyldig radius: \"%s\"" - tube: - invalid-radius: "Ugyldig radius: \"%s\"" - image: - main-menu: - - "---------------Terra/billede---------------" - - "render - Render et billede med en given bredde og højde, der senere kan importeres som en verden." - - "gui - Åbn fejlfindings-GUI (Skal være aktiveret i konfigurationen)" - gui: - main-menu: - - "-------------Terra/billede/gui-------------" - - "raw - Åbn GUI med rå Biome-data" - - "step - Re-render data igen for at vise grænser mere tydeligt" - debug: "Fejlfindingstilstand skal være aktiveret for at bruge fejlfindings-GUI! Fejlfindings-GUI'en er IKKE PRODUKTIONSSIKKER!" - render: - save: "Gemte billede som \"%s\"" - error: "Der opstod en fejl under generering af billedet!" - profile: - main-menu: - - "---------------Terra/profiler---------------" - - "start - Starter profiler" - - "stop - Stopper profiler" - - "query - Henter profiler data" - - "reset - Nulstiller profiler data" - reset: "Profiler er blevet nulstillet." - start: "Profiler er startet." - stop: "Profiler er stoppet." - structure: - main-menu: - - "---------------Terra/struktur---------------" - - "export - Eksporter din nuværende WorldEdit selektion som en Terra struktur." - - "load - Indlæs en Terra struktur" - invalid-radius: "Ugyldig radius: \"%s\"" - invalid-rotation: "Ugyldig rotation: \"%s\"" - invalid: "Ugyldigt Struktur ID: \"%s\"" - export: "Gemte struktur til \"%s\"" -world-config: - loading: "Indlæser verdenskonfigurationsværdier til verden \"%s\"..." - not-found: "Konfiguration til verden \"%s\" ikke fundet. Kopier standardkonfigurationen." - using-image: "Indlæser verden fra billede." - error: "Kan ikke indlæse konfiguration til verden %s" - done: "Indlæsning af verden \"%1$s\" er færdig. Forløbet tid: %2$sms" -config-pack: - loaded: "Konfigurationspakke %1$s v%4$s ved %3$s indlæst på %2$sms." -config: - loaded: "Indlæste %1$s fra fil %2$s" - loaded-all: "Indlæste %1$s %2$s(s) på %3$sms." - error: - invalid-failover: "Ugyldig failover type: \"%s\"" - duplicate: "Duplikeret ID fundet i filen: %s" - file: - - "Konfigurationsfejl for Terra objekt. Fil: %1$s" - - "%2$s" - - "Ret dette, inden du fortsætter!" - generic: - - "Der opstod en fejl under indlæsning af konfigurationer." - - "Rapporter dette til Terra." -warning: - no-population: "Ingen populations chunks blev indlæst. Hvis dette er første gang du starter din server med Terra, eller hvis du opretter en ny verden, er dette normalt." -error: - severe-config: "En alvorlig konfigurationsfejl har forhindret Terra i at generere terræn korrekt ved koordinater: %1$s, %2$s. Kontroller din konfiguration for fejl. Eventuelle konfigurationsfejl vil være rapporteret ovenfor." -debug: - data-save: "Gemte populations data for verden \"%s\"" -use-paper: - - "Det ser ud til, at du bruger Spigot/CraftBukkit." - - "Mens Terra &ovil&r virke på Spigot, vil nogle funktioner gå tabt. (Terra er uprøvet på CraftBukkit; ingen support vil blive givet til CraftBukkit)." - - "For at få mest muligt ud af Terra, skal du skifte til Paper." - - "Plus, Paper tilbyder store ydeevne forbedringer over Spigot, og alle Spigot plugins bør virke med Paper!" - - "For at få den bedste oplevelse med Terra, og alle dine plugins, brug Paper." - - "Få mere at vide på Paper's hjemmeside: https://papermc.io/" diff --git a/common/src/main/resources/lang/de_de.yml b/common/src/main/resources/lang/de_de.yml deleted file mode 100644 index af69511ad..000000000 --- a/common/src/main/resources/lang/de_de.yml +++ /dev/null @@ -1,117 +0,0 @@ -enable: - - "Wenn dir Terra gefällt, denk bitte darüber nach, das Projekt auf Patreon zu unterstützen!" - - "Dadurch erhältst du Zugriff auf experimentelle Funktionen!" - - "Unterstütze das Projekt hier: https://www.patreon.com/dfsek" -disable: - - "Danke, dass du Terra benutzt!!" -command: - debug-only: "Dieser Befehl kann nur im Debugmodus benutzt werden!" - player-only: "Dieser Befehl kann nur von Spielern benutzt werden!" - invalid: "Ungültiger Befehl. (Erwartet %1$s Argumente, fand %2$s)." - players-only: "Dieser Befehl kann nur von Spielern benutzt werden." - world: "Dieser Befehl muss in einer von Terra generierten Welt ausgeführt werden!" - reload: "Terra-Konfiguration wurde neu geladen." - version: "Dieser Server verwendet Terra \"%s\"" - main-menu: - - "--------------------Terra--------------------" - - "reload - Lädt die Konfiguration neu" - - "biome - Zeigt dir das derzeitige Biom" - - "ore - Erzader an derzeitiger Position erzeugen (zum Debuggen)" - - "save-data - Bevölkerungsdaten speichern" - - "structure - Laden/Exportieren von Strukturen" - - "profile - Profiler-Optionen" - - "image - Bild-/GUI-Optionen" - biome: - biome-found: "Biom gefunden bei: (%1$s, %2$s)" - unable-to-locate: "Biom konnte nicht gefunden werden!" - invalid-radius: "Ungültiger Radius: \"%s\"" - invalid: "Ungültige Biom-ID: \"%s\"" - in: "Du bist in: \"%s\"" - ore: - main-menu: - - "---------------Terra/Erz---------------" - - "Generiert eine Erzader an dem Block, den du anguckst" - out-of-range: "Block außer Reichweite" - invalid-ore: "Kann Erz \"%s\" nicht finden" - geometry: - main-menu: - - "---------------Terra/Geometrie----------------" - - "Verschiedene Debugging-Befehle für die Voxelgeometrie" - - "sphere - Generiert eine Kugel" - - "deformsphere - Generiert eine deformierte Kugel" - - "tube - Generiert ein Rohr" - deform: - invalid-radius: "Ungültiger Radius: \"%s\"" - invalid-deform: "Ungültiger Deformation: \"%s\"" - invalid-frequency: "Ungültige Frequenz: \"%s\"" - sphere: - invalid-radius: "Ungültiger Radius: \"%s\"" - tube: - invalid-radius: "Ungültiger Radius: \"%s\"" - image: - main-menu: - - "---------------Terra/Bilde---------------" - - "render - Rendert ein Bild mit einer bestimmten Breite und Höhe, das später als Welt importiert werden kann." - - "gui - Debug-GUI öffnen (muss in der Konfiguration aktiviert sein)" - gui: - main-menu: - - "-------------Terra/image/gui-------------" - - "raw - Öffnet eine GUI mit Biome-Rohdaten" - - "step - Daten erneut rendern, um Ränder deutlicher darzustellen" - debug: "Der Debug-Modus muss aktiviert sein, um die Debug-GUI verwenden zu können! Die Debug-GUI ist NICHT PRODUKTIONSSICHER!" - render: - save: "Bild gespeichert unter: \"%s\"" - error: "Beim Speichern ist ein Fehler aufgetreten!" - profile: - main-menu: - - "---------------Terra/Profiler---------------" - - "start - Startet den Profiler" - - "stop - Stoppt den Profiler" - - "query - Profiler-Daten anzeigen" - - "reset - Profiler-Daten zurücksetzen" - reset: "Profiler-Daten wurden zurückgesetzt." - start: "Der Profiler wurde gestartet." - stop: "Der Profiler wurde gestoppt." - structure: - main-menu: - - "---------------Terra/Strukturen---------------" - - "export - Exportiert deine aktuelle WorldEdit-Auswahl als Terra-Struktur." - - "load - Lädt eine Terra-Struktur." - invalid-radius: "Ungültiger Radius: \"%s\"" - invalid-rotation: "Ungültige Rotation: \"%s\"" - invalid: "Ungültige Strukturen-ID: \"%s\"" - export: "Struktur unter \"%s\" gespeichert." -world-config: - loading: "Lade Weltkonfigurationswerte für Welt %s..." - not-found: "Weltkonfigurationswerte für Welt \"%s\" nicht gefunden. Lade Standardwerte." - using-image: "Lade Welt von Bild." - error: "Konfiguration für Welt %s kann nicht geladen werden!" - done: "Laden der Welt abgeschlossen. Ladedauer: %sms" -config-pack: - loaded: "Konfiguration %1$s wurde in %2$sms geladen." -config: - loaded: "Erfolgreich %1$s aus Datei %2$s geladen" - loaded-all: "%1$s %2$s(s) in %3$sms geladen." - error: - invalid-failover: "Ungültiger Failover-Typ: \"%s\"" - duplicate: "ID doppelt belegt in Datei: %s" - file: - - "Konfigurationsfehler in Terra-Objekt. Datei: %1$s" - - "%2$s" - - "Korrigier bitte diese(n) Fehler, bevor du fortfährst!" - generic: - - "Ein Fehler ist beim Laden der Konfiguration aufgetreten." - - "Bitte melde diesen Fehler!" -warning: - no-population: "Es wurden keine Bevölkerungs-Chunks geladen. Wenn du den Server zum ersten Mal mit Terra startest oder eine neue Welt erstellst, ist dies normal." -error: - severe-config: "Ein schwerwiegender Konfigurationsfehler hat Terra daran gehindert, Gelände an folgenden Koordinaten ordnungsgemäß zu generieren: %1$s, %2$s. Bitte überprüfe die Konfiguration auf Fehler. Alle Konfigurationsfehler wurden oben gemeldet." -debug: - data-save: "Bevölkerungsdaten für Welt \"%s\" gespeichert." -use-paper: - - "Anscheinend benutzt du Spigot/CraftBukkit." - - "Terra funktioniert auf Spigot/CraftBukkit, aber einige Funktionen gehen verloren. (Terra wurde nicht auf Spigot/CraftBukkit getestet; Es gibt keine Hilfe für Spigot/CraftBukkit-Server)." - - "Um Terra optimal zu benutzen, wechsle bitte zu Paper." - - "Außerdem bietet Paper immense Leistungsverbesserungen gegenüber Spigot und CraftBukkit und (normalerweise) funktionieren alle Spigot/CraftBukkit Plugins auch auf Paper!" - - "Benutze Paper, um die beste Erfahrung mit Terra und allen anderen Plugins zu haben." - - "Finde mehr über Paper heraus: https://papermc.io" diff --git a/common/src/main/resources/lang/en_us.yml b/common/src/main/resources/lang/en_us.yml deleted file mode 100644 index cde2101d9..000000000 --- a/common/src/main/resources/lang/en_us.yml +++ /dev/null @@ -1,122 +0,0 @@ -enable: - - "If you like Terra, please consider supporting the project on Patreon!" - - "You'll gain access to experimental features before they are released!" - - "Support the project here: https://www.patreon.com/dfsek" -disable: - - "Thank you for using Terra!" -command: - debug-only: "This command must be used with debug mode enabled!" - player-only: "This command is for players only!" - invalid: "Invalid command. (Expected %1$s arguments, found %2$s)." - players-only: "Command is for players only." - world: "This command must be executed in a Terra world!" - reload: "Reloaded Terra config." - reload-error: "Errors occurred while reloading Terra configurations. See logs for more information." - version: "This server is running Terra version \"%1$s\", on platform \"%2$s\"" - main-menu: - - "--------------------Terra--------------------" - - "reload - Reload configuration data" - - "biome - Get current biome" - - "ore - Generate an ore vein at the location you are facing (For debugging)" - - "save-data - Save population data" - - "structure - Load and export structures" - - "profile - Profiler options" - - "image - Image/GUI options" - biome: - biome-found: "Located biome at (%1$s, %2$s)" - unable-to-locate: "Unable to locate biome." - invalid-radius: "Invalid radius: \"%s\"" - invalid: "Invalid Biome ID: \"%s\"" - in: "You are in \"%s\"" - packs: - main: "Currently installed config packs:" - pack: " - %1$s v%3$s by %2$s" - none: "No config packs are installed." - ore: - main-menu: - - "---------------Terra/ore---------------" - - "Generates a vein of ore at the block you are looking at." - out-of-range: "Block out of range" - invalid-ore: "Unable to find Ore \"%s\"" - geometry: - main-menu: - - "---------------Terra/geometry----------------" - - "Various voxel geometry debugging commands" - - "sphere - Generate a sphere" - - "deformsphere - Generate a deformed sphere" - - "tube - Generate a tube" - deform: - invalid-radius: "Invalid radius: \"%s\"" - invalid-deform: "Invalid deform: \"%s\"" - invalid-frequency: "Invalid frequency: \"%s\"" - sphere: - invalid-radius: "Invalid radius: \"%s\"" - tube: - invalid-radius: "Invalid radius: \"%s\"" - image: - main-menu: - - "---------------Terra/image---------------" - - "render - Render an image with a given width and height, that can later be imported as a world." - - "gui - Open debug GUI (Must be enabled in config)" - gui: - main-menu: - - "-------------Terra/image/gui-------------" - - "raw - Open GUI with raw Biome data" - - "step - Re-render data to show borders more clearly" - debug: "Debug mode must be enabled to use the debug GUI! The debug GUI is NOT PRODUCTION SAFE!" - render: - save: "Saved image as \"%s\"" - error: "An error occurred while generating the image!" - profile: - main-menu: - - "---------------Terra/profile---------------" - - "start - Starts the profiler" - - "stop - Stops the profiler" - - "query - Fetches profiler data" - - "reset - Resets profiler data" - reset: "Profiler has been reset." - start: "Profiler has started." - stop: "Profiler has stopped." - structure: - main-menu: - - "---------------Terra/structure---------------" - - "export - Export your current WorldEdit selection as a Terra structure." - - "load - Load a Terra structure" - invalid-radius: "Invalid radius: \"%s\"" - invalid-rotation: "Invalid rotation: \"%s\"" - invalid: "Invalid Structure ID: \"%s\"" - export: "Saved structure to \"%s\"" -world-config: - load: "Loading world configuration values for world \"%s\"..." - not-found: "Configuration for world \"%s\" not found. Copying default config." - using-image: "Loading world from image." - error: "Unable to load configuration for world %s" - done: "World load for world \"%1$s\" complete. Time elapsed: %2$sms" -config-pack: - loaded: "Config pack %1$s v%4$s by %3$s loaded in %2$sms." -config: - loaded: "Loaded %1$s from file %2$s" - loaded-all: "Loaded %1$s %2$s(s) in %3$sms." - error: - invalid-failover: "Invalid failover type: \"%s\"" - duplicate: "Duplicate ID found in file: %s" - file: - - "Configuration error for Terra object. File: %1$s" - - "%2$s" - - "Correct this before proceeding!" - generic: - - "An error occurred while loading configurations." - - "Please report this to Terra." -warning: - no-population: "No population chunks were loaded. If this is your first time starting your server with Terra, or if you are creating a new world, this is normal." -error: - severe-config: "A severe configuration error has prevented Terra from properly generating terrain at coordinates: %1$s, %2$s. Please check your configuration for errors. Any config errors will have been reported above." -debug: - data-save : "Saved population data." -use-paper: - - "You appear to be using Spigot/CraftBukkit." - - "While Terra &odoes&r work on Spigot, some functionality will be lost. (Terra is untested on CraftBukkit; no support will be given for CraftBukkit)." - - "To get the most out of Terra, please switch to Paper." - - "Plus, Paper offers immense performance improvements over Spigot, and all Spigot plugins should work with Paper!" - - "To have the best experience with Terra, and all your plugins, please use Paper." - - "Find out more on Paper's website: https://papermc.io/" \ No newline at end of file diff --git a/common/src/main/resources/lang/es.yml b/common/src/main/resources/lang/es.yml deleted file mode 100644 index 4ca8138b2..000000000 --- a/common/src/main/resources/lang/es.yml +++ /dev/null @@ -1,107 +0,0 @@ -enable: - - "Si te gusta Terra, puedes considerar apoyar el proyecto en Patreon!" - - "Tendrás acceso anticipado a caracteristicas experimentales antes de que sean lanzadas oficialmente!" - - "Puedes apoyar el proyecto aquí: https://www.patreon.com/dfsek" -disable: - - "Gracias por usar Terra!" -command: - player-only: "Este comando solo puede ser usado por jugadores!" - terra-world: "Este comando solo puede ser usado en un mundo Terra!" - invalid: "Comando invalido. (Expected %1$s arguments, found %2$s)." - players-only: "Este comando solo puede ser usado por jugadores" - world: "Este comando puede ejecutarse solo en un mundo terra!" - reload: "La configuración Terra ha sido recargada." - main-menu: - - "--------------------Terra--------------------" - - "reload - Recarga los datos de configuración del plugin." - - "biome - Obtienes información del bioma actual" - - "ore - Genera una mena de ore en el lugar que estes mirando.(For debugging)" - - "save-data - Guarda los datos actuales." - - "structure - Cargar o exportar estructuras." - - "profile - Opciones de perfil." - - "image - Opciones de imagen/GUI." - biome: - biome-found: "Bioma localizado en (%1$s, %2$s)" - unable-to-locate: "No se pudo localizar el bioma." - invalid-radius: "Radio invalido: \"%s\"" - invalid: "ID del bioma invalido: \"%s\"" - in: "Te encuentras en \"%s\"" - ore: - main-menu: - - "---------------Terra/ore---------------" - - "Generas una mena de ore en el bloque que te encuentres mirando." - out-of-range: "Bloque fuera de rango." - invalid-ore: "No se pudo encontrar el Ore \"%s\"" - geometry: - main-menu: - - "---------------Terra/geometry----------------" - - "Various voxel geometry debugging commands" - - "sphere - Generas un sphere" - - "deformsphere - Generas un sphere deformado" - - "tube - Generas un tube" - deform: - invalid-radius: "Radio invalido: \"%s\"" - invalid-deform: "Deform invalido: \"%s\"" - invalid-frequency: "Frequencia invalida: \"%s\"" - sphere: - invalid-radius: "Radio invalido: \"%s\"" - tube: - invalid-radius: "Radio invalido: \"%s\"" - image: - main-menu: - - "---------------Terra/image---------------" - - "render - Renderiza una imagen con alto y ancho, y este después podrá ser importado como un mundo." - - "gui - Abre el debug GUI.(Puede ser habilitado en la configuración)" - gui: - main-menu: - - "-------------Terra/image/gui-------------" - - "raw - Abre el GUI con la configuración del bioma sin procesar." - - "step - Vuelve a renderizar la configuración para mostrar los límites más claro." - debug: "El modo debug puede habilitarse para usar el debug GUI! LA CREACIÓN DEL DEBUG GUI NO PODRÍA SER SEGURA!" - render: - save: "Guarda una imagen como \"%s\"" - error: "Un error ha ocurrido mientras se generaba la imagen!" - profile: - main-menu: - - "---------------Terra/profile---------------" - - "start - Se incia la generación del Profiler." - - "stop - Se detiene la generación del Profiler." - - "query - Fetches profiler data" - - "reset - Reinicia la configuración del Profiler." - reset: "El Profiler ha sido reiniciado." - start: "El Profiler se ha iniciado." - stop: "El Profiler se ha detenido." - structure: - main-menu: - - "---------------Terra/structure---------------" - - "export - Exporta tus estructuras de Worldedit como estructuras Terra." - - "load - Carga una estructura Terra." - invalid-radius: "Radio invalido: \"%s\"" - invalid: "ID de la estructura es invalida: \"%s\"" - export: "Estructura guardada como \"%s\"" -world-config: - loading: "Carga los parametros de configuración para el mundo %s..." - not-found: "La configuración para el mundo \"%s\" no se puede encontrar. Copiando la configuración por defecto." - using-image: "Carga el mundo a partir de una imagen." - error: "No se pudo cargar la configuración para el mundo %s" - done: "el mundo se ha cargado completamente. Tiempo transcurrido: %sms" -config-pack: - loaded: "Configuración %1$s fue cargada en %2$sms." -config: - loaded: "Cargado en %1$s desde el archivo %2$s" - loaded-all: "Cargado en %1$s %2$s(s) en %3$sms." - error: - duplicate: "Una ID duplicada fué encontrado en el archivo: %s" - file: - - "Error de configuración para el objeto Terra. Archivo: %1$s" - - "%2$s" - - "Corrigelo antes de proseguir!" - generic: - - "Un error ha ocurrido mientras se cargaba las configuraciónes." - - "Es recomendable reportar esto a Terra." -warning: - no-population: "No se cargaron fragmentos de población. Si es la primera vez que inicias tu servidor con Terra, esto es normal si estás creando un nuevo mundo." -error: - severe-config: "Un grave error de configuración ha impedido que Terra genere correctamente el terreno en las coordenadas: %1$s, %2$s. Compruebe si hay errores en su configuración. Cualquier error de configuración se habrá informado anteriormente." -debug: - data-save: "Datos de población guardados para el mundo \"%s\"" \ No newline at end of file diff --git a/common/src/main/resources/lang/it_it.yml b/common/src/main/resources/lang/it_it.yml deleted file mode 100644 index 09237b315..000000000 --- a/common/src/main/resources/lang/it_it.yml +++ /dev/null @@ -1,121 +0,0 @@ -enable: - - "Se ti piace Terra, per favore considera di sostenere il progetto su Patreon!" - - "Avrai accesso a funzionalità sperimentali prima che vengano rilasciate!" - - "Sostieni il progetto qui: https://www.patreon.com/dfsek" -disable: - - "Grazie per aver usato Terra!" -command: - debug-only: "Questo comando deve essere usato con la modalità debug attivata!" - player-only: "Solo i giocatori possono eseguire questo comando!" - invalid: "Comando invalido. (%1$s argomenti previsti, %2$s trovati)." - players-only: "Solo i giocatori possono eseguire questo comando!" - world: "Questo comando può solo essere eseguito in un mondo creato da Terra!" - reload: "Configurazione Terra ricaricata." - reload-error: "Si sono verificati errori durante il ricaricamento delle configurazioni Terra. Vedere i log per ulteriori informazioni." - version: "Questo server sta usando la versione \"%1$s\" Terra, sulla piattaforma \"%2$s\"" - main-menu: - - "--------------------Terra--------------------" - - "reload - Ricarica i dati di configurazione" - - "biome - Ottieni il bioma attuale" - - "ore - Genera una vena minerale davanti a te (per fare debug)" - - "save-data - Salva i dati sulla popolazione" - - "structure - Carica ed esporta strutture" - - "profile - Opzioni dell'analizzatore" - - "image - Opzioni immagine / menu" - biome: - biome-found: "Trovato un bioma alle coordinate (%1$s, %2$s)" - unable-to-locate: "Ricerca bioma fallita." - invalid-radius: "Raggio invalido: \"%s\"" - invalid: "ID bioma invalido: \"%s\"" - in: "Tu sei nel bioma \"%s\"" - packs: - main: "Pacchetti di configurazione installati:" - pack: " - %1$s v%3$s (autore: %2$s)" - none: "Nessun pacchetto di configurazione è installato." - ore: - main-menu: - - "---------------Terra/ore---------------" - - "Genera una vena di minerale nel blocco che stai guardando." - out-of-range: "Blocco fuori portata" - invalid-ore: "Ricerca minerale \"%s\" fallita!" - geometry: - main-menu: - - "---------------Terra/geometry----------------" - - "Vari comandi di debug della geometria voxel" - - "sphere - Genera una sfera" - - "deformsphere - Genera una sfera deformata" - - "tube - Genera un tubo" - deform: - invalid-radius: "Raggio non valido: \"%s\"" - invalid-deform: "Deformazione non valida: \"%s\"" - invalid-frequency: "Frequenza non valida: \"%s\"" - sphere: - invalid-radius: "Raggio non valido: \"%s\"" - tube: - invalid-radius: "Raggio non valido: \"%s\"" - image: - main-menu: - - "---------------Terra/image---------------" - - "render - Renderizza un'immagine con una data larghezza e altezza, che può essere successivamente importata come mondo." - - "gui - Apri il menu di debug (deve essere abilitato nella configurazione)" - gui: - main-menu: - - "-------------Terra/image/gui-------------" - - "raw - Apri il menu con dati grezzi sui biomi" - - "step - Riesegui il rendering dei dati per mostrare i bordi più chiaramente" - debug: "La modalità di debug deve essere abilitata per utilizzare la GUI di debug! La GUI di debug NON È SICURA PER LA PRODUZIONE!" - render: - save: "Immagine salvata come \"%s\"" - error: "Si è verificato un errore durante la generazione dell'immagine!" - profile: - main-menu: - - "---------------Terra/profile---------------" - - "start - Inizia il profiler" - - "stop - Ferma il profiler" - - "query - Recupera i dati del profiler" - - "reset - Resetta i dati del profiler" - reset: "Il profiler è stato resettato." - start: "Il profiler è stato avviato." - stop: "Il profiler è stato fermato." - structure: - main-menu: - - "---------------Terra/structure---------------" - - "export - Esporta la tua selezione attuale di WorldEdit come struttura Terra." - - "load - Carica una struttura Terra" - invalid-radius: "Raggio invalido: \"%s\"" - invalid-rotation: "Rotazione invalida: \"%s\"" - invalid: "ID struttura invalido: \"%s\"" - export: "Struttura salvata come \"%s\"" -world-config: - load: "Caricamento dei valori di configurazione per il mondo \"%s\"..." - not-found: "Configurazione per il mondo \"%s\" non trovata. La configurazione predefinita sarà utilizzata." - using-image: "Caricamento mondo da immagine." - error: "Impossibile caricare la configurazione per il mondo \"%s\"" - done: "Caricamento del mondo \"%1$s\" completato. Tempo trascorso: %2$sms" -config-pack: - loaded: "Pacchetto di configurazione %1$s v%4$s (autore: %3$s) caricato in %2$sms." -config: - loaded: "Caricato %1$s dal file %2$s" - loaded-all: "Caricato %1$s %2$s(s) in %3$sms." - error: - invalid-failover: "Tipo di failover non valido: \"%s\"" - duplicate: "ID duplicato trovato nel file: %s" - file: - - "Errore di configurazione Terra nel file: %1$s" - - "%2$s" - - "Correggilo prima di procedere!" - generic: - - "Si è verificato un errore durante il caricamento delle configurazioni." - - "Per favore, segnalatelo a Terra." -warning: - no-population: "Non sono stati caricati chunk preesistenti. Se è la prima volta che avvii il tuo server con Terra, o se stai creando un nuovo mondo, è normale." -error: - severe-config: "Un grave errore di configurazione ha impedito a Terra di generare correttamente il terreno alle coordinate: %1$s, %2$s. Controlla la tua configurazione per errori. Eventuali errori di configurazione saranno stati segnalati sopra." -debug: - data-save: "Dati sulla popolazione salvati per il mondo \"%s\"" -use-paper: - - "Sembra che tu stia usando Spigot/CraftBukkit." - - "Nonostante Terra &ofunzioni&r su Spigot, delle funzionalità verranno perse. (Terra non è testato su CraftBukkit; nessun supporto verrà dato per la piattaforma CraftBukkit)." - - "Inoltre, Paper offre enormi miglioramenti delle prestazioni rispetto a Spigot e tutti i plug-in di Spigot dovrebbero funzionare con Paper!" - - "Per avere la migliore esperienza con Terra e tutti i tuoi plugin, usa Paper." - - "Scopri di più sul sito web di Paper: https://papermc.io/" \ No newline at end of file diff --git a/common/src/main/resources/lang/ja_jp.yml b/common/src/main/resources/lang/ja_jp.yml deleted file mode 100644 index 49f183760..000000000 --- a/common/src/main/resources/lang/ja_jp.yml +++ /dev/null @@ -1,122 +0,0 @@ -enable: - - "Terraを気に入っていただけたのであれば、Patreonでの支援をご検討ください!" - - "リリース前の実験的な機能を使うことができます!" - - "プロジェクトの支援はこちらから: https://www.patreon.com/dfsek" -disable: - - "Terraをご利用いただきありがとうございます!" -command: - debug-only: "このコマンドは、デバッグモードを有効にして使用する必要があります。" - player-only: "このコマンドはプレイヤー専用です!" - invalid: "Invalid command. (Expected %1$s arguments, found %2$s)." - players-only: "コマンドはプレイヤー専用です。" - world: "このコマンドはTerraのワールドで実行する必要があります!" - reload: "Terraの設定を再読み込みしました。" - reload-error: "Terraの設定の再ロード中にエラーが発生しました。詳細はログを参照してください。" - version: "このサーバーでは Terraバージョン\"%1$s\" が実行されており、プラットフォームは \"%2$s\" です。" - main-menu: - - "--------------------Terra--------------------" - - "reload - 設定データを再読み込み" - - "biome - 現在のバイオームを取得" - - "ore - 向いている場所に鉱石を生成する(デバッグ用)" - - "save-data - データを保存" - - "structure - ストラクチャーのロード及びエクスポート" - - "profile - プロファイラ オプション" - - "image - 画像/GUI オプション" - biome: - biome-found: "バイオームの座標 (%1$s, %2$s)" - unable-to-locate: "バイオームが見つけられません。" - invalid-radius: "無効な半径: \"%s\"" - invalid: "無効なバイオームID: \"%s\"" - in: "あなたは \"%s\" にいます。" - packs: - main: "現在インストールされているコンフィグパック:" - pack: " - %1$s v%3$s by %2$s" - none: "コンフィグパックはインストールされていません。" - ore: - main-menu: - - "---------------Terra/ore---------------" - - "見ているブロックに鉱石を生成します。" - out-of-range: "範囲外のブロック" - invalid-ore: "鉱石 \"%s\" が見つかりません。" - geometry: - main-menu: - - "---------------Terra/geometry----------------" - - "様々なボクセルジオメトリのデバッグコマンド" - - "sphere - 球体を生成" - - "deformsphere - 変形した球体を生成" - - "tube - チューブを生成" - deform: - invalid-radius: "無効な半径: \"%s\"" - invalid-deform: "無効な変形: \"%s\"" - invalid-frequency: "無効な周波数: \"%s\"" - sphere: - invalid-radius: "無効な半径: \"%s\"" - tube: - invalid-radius: "無効な半径: \"%s\"" - image: - main-menu: - - "---------------Terra/image---------------" - - "render - 指定された幅と高さの画像をレンダリングします。" - - "gui - デバッグGUIを開く(設定で有効にする必要があります)" - gui: - main-menu: - - "-------------Terra/image/gui-------------" - - "raw - 生のBiomeデータを利用したGUIを開く" - - "step - 境界線をより明確に表示するためにデータを再レンダリング" - debug: "デバッグGUIを使用するには、デバッグモードを有効にする必要があります。デバッグGUIは安全ではありません!" - render: - save: "\"%s\" として画像を保存" - error: "画像生成中にエラーが発生しました!" - profile: - main-menu: - - "---------------Terra/profile---------------" - - "start - プロファイラを起動" - - "stop - プロファイラを停止" - - "query - プロファイラデータを取得" - - "reset - プロファイラのデータをリセット" - reset: "プロファイラがリセットされました。" - start: "プロファイラが起動しました。" - stop: "プロファイラが停止しました。" - structure: - main-menu: - - "---------------Terra/structure---------------" - - "export - 現在のWorldEditの選択範囲をTerraストラクチャーとしてエクスポート" - - "load - Terraストラクチャーを読み込む" - invalid-radius: "無効な半径: \"%s\"" - invalid-rotation: "無効な回転: \"%s\"" - invalid: "無効なストラクチャーID: \"%s\"" - export: "\"%s\" にストラクチャーを保存" -world-config: - load: "ワールド \"%s\" のワールド設定値を読み込み中..." - not-found: "ワールド \"%s\" の設定が見つかりませんでした。デフォルトの設定をコピーします。" - using-image: "画像からワールドを読み込みます。" - error: "ワールド %s の設定を読み込めませんでした" - done: "ワールドの読み込みが完了しました。経過時間: %sms" -config-pack: - loaded: "%2$sms で設定 %1$s が読み込まれました。" -config: - loaded: "ファイル %2$s から %1$s を読み込まれました。" - loaded-all: "%3$sms で %1$s %2$s で読み込まれました。" - error: - invalid-failover: "無効なフェイルオーバータイプ: \"%s\"" - duplicate: "ファイルに重複したIDが見つかりました: %s" - file: - - "Terraオブジェクトに設定エラーがあります。ファイル: %1$s" - - "%2$s" - - "先に進む前にこれを修正してください!" - generic: - - "設定の読み込み中にエラーが発生しました。" - - "Terraに報告してください。" -warning: - no-population: "チャンクが読み込まれませんでした。初めてTerraでサーバーを起動した場合、または新しいワールドを作成した場合、これは正常です。" -error: - severe-config: "重大な設定エラーによりTerraが正しく地形を生成できません。座標: %1$s, %2$s エラーがないか設定をチェックしてください。設定エラーは上記で報告されています。" -debug: - data-save: "ワールド \"%s\" のデータを保存" -use-paper: - - "Spigot/CraftBukkitを使用していています。" - - "TerraはSpigot上で&o動作します&rが、いくつかの機能は使用できません。(TerraはCraftBukkitではテストされていません。CraftBukkitはサポートされません)。" - - "Terraを最大限活用するにはPaperに切り替えてください。" - - "さらに、PaperはSpigotよりもパフォーマンスが大幅に向上しており、すべてのSpigotプラグインはPaperで動作するはずです。" - - "Terraとすべてのプラグインで最高の体験をするためには、Paperをご利用ください。" - - "詳細については、Paperのウェブサイトをご覧ください: https://papermc.io/" \ No newline at end of file diff --git a/common/src/main/resources/lang/nl_NL.yml b/common/src/main/resources/lang/nl_NL.yml deleted file mode 100644 index f34f8241e..000000000 --- a/common/src/main/resources/lang/nl_NL.yml +++ /dev/null @@ -1,122 +0,0 @@ -enable: - - "Als je Terra leuk vindt, overweeg dan om het project op Patreon te steunen!" - - "Je krijgt toegang tot experimentele functies voordat ze uitgebracht worden!" - - "Steun het project hier: https://www.patreon.com/dfsek" -disable: - - "Bedankt voor het gebruiken van Terra!" -command: - debug-only: "Dit commando moet worden gebruikt met debug-modus ingeschakeld!" - player-only: "Dit commando is alleen voor spelers!" - invalid: "Ongeldig commando. (Verwachte %1$s argumenten, vond er %2$s)." - players-only: "Dit commando is alleen voor spelers." - world: "Dit commando moet worden uitgevoerd in een Terra-wereld!" - reload: "Terra configuratie herladen." - reload-error: "Er zijn fouten opgetreden tijdens het herladen van de Terra-configuratie. Zie de logboeken voor meer informatie." - version: "Deze server draait Terra versie \"%1$s\", op platform \"%2$s\"" - main-menu: - - "--------------------Terra--------------------" - - "reload - Herlaad de configuratie gegevens" - - "biome - Find het huidige bioom (klimaatgebied)" - - "ore - Genereer een ertsader op de locatie waar je heen kijkt (voor debuggen)" - - "save-data - Sla populatie data op" - - "structure - Laad en exporteer constructies" - - "profile - Profiler opties" - - "image - Afbeelding/GUI opties" - biome: - biome-found: "bioom (klimaatgebied) gevonden op (%1$s, %2$s)" - unable-to-locate: "Geen bioom (klimaatgebied) kunnen vinden." - invalid-radius: "Ongeldige straal: \"%s\"" - invalid: "Ongeldig bioom ID: \"%s\"" - in: "Je bent in \"%s\"" - packs: - main: "Momenteel geïnstalleerde configuratiepakketten:" - pack: " - %1$s v%3$s door %2$s" - none: "Er zijn geen configuratiepakketten geïnstalleerd." - ore: - main-menu: - - "---------------Terra/erts---------------" - - "Genereer een ertsader bij het blok waar je naar kijkt." - out-of-range: "Blok buiten bereik" - invalid-ore: "Kan \"%s\" erts niet vinden" - geometry: - main-menu: - - "---------------Terra/geometrie----------------" - - "Diverse voxelgeometrie debug commando's" - - "sphere - Genereer een bol" - - "deformsphere - Genereer een vervormde bol" - - "tube - Genereer een tube" - deform: - invalid-radius: "Ongeldige straal: \"%s\"" - invalid-deform: "Ongeldige vervorming: \"%s\"" - invalid-frequency: "Ongeldige frequentie: \"%s\"" - sphere: - invalid-radius: "Ongeldige straal: \"%s\"" - tube: - invalid-radius: "Ongeldige straal: \"%s\"" - image: - main-menu: - - "---------------Terra/afbeelding---------------" - - "render - Genereer en beeld met een bepaalde breedte en hoogte, deze kan later als een wereld worden geïmporteerd." - - "gui - Open debug GUI (moet worden ingeschakeld in de configuratie)." - gui: - main-menu: - - "-------------Terra/afbeelding/gui-------------" - - "raw - Open GUI met ruwe bioom (klimaatgebied) gegevens" - - "step - Regenereer de gegevens om de grenzen duidelijker te laten zien"" - debug: "De debug-modus moet ingeschakeld zijn om de debug GUI te kunnen gebruiken! Gebruik de debug GUI alleen om te testen, HET IS NIET VEILIG OM TE GEBRUIKEN IN PRODUCTIE!" - render: - save: "Afbeelding opgeslagen als \"%s\"" - error: "Er is een fout opgetreden tijdens het genereren van het beeld!" - profile: - main-menu: - - "---------------Terra/profile---------------" - - "start - Start de profiler" - - "stop - Stop de profiler" - - "query - Haal profiler gegevens op" - - "reset - Resets profiler gegevens" - reset: "Profiler is gereset." - start: "Profiler is gestart." - stop: "Profiler is gestopt." - structure: - main-menu: - - "---------------Terra/constructies---------------" - - "export - Exporteer je huidige WorldEdit selectie als een Terra constructie." - - "load - Laad een Terra constructie" - invalid-radius: "Ongeldige straal: \"%s\"" - invalid-rotation: "Ongeldige rotatie: \"%s\"" - invalid: "Ongeldig constructie ID: \"%s\"" - export: "Constructie opgeslagen naar \"%s\"" -world-config: - load: "Laden van configuratiewaarden voor wereld \"%s\"..." - not-found: "Configuratie voor wereld \"%s\" niet gevonden. Standaard configuratie wordt gebruikt" - using-image: "Laden van wereld uit een afbeelding." - error: "Niet in staat om de configuratie voor wereld %s te laden" - done: "Laden van wereld \"%1$s\" compleet. Tijd verstreken: %2$sms" -config-pack: - loaded: "Configuratiepakket %1$s v%4$s door %3$s geladen in %2$sms." -config: - loaded: "%1$s geladen van bestand %2$s" - loaded-all: "%1$s %2$s(s) in %3$sms geladen." - error: - invalid-failover: "Ongeldig failover type: \"%s\"" - duplicate: "Duplicaat ID gevonden in bestand: %s" - file: - - "Configuratiefout voor Terra-object. Bestand: %1$s" - - "%2$s" - - "Corrigeer dit voordat je verder gaat!" - generic: - - "Er is een fout opgetreden tijdens het laden van de configuraties." - - "Rapporteer dit alsjeblieft aan Terra." -warning: - no-population: "Geen populatie chunks kunnen laden. Als dit de eerste keer is dat de server met Terra gestart wordt is er niks aan de hand." -error: - severe-config: "Een ernstige configuratiefout heeft ervoor gezorgd dat Terra geen terrein op de coördinaten %1$s, %2$s heeft kunnen genereren. Controleer je configuratie op fouten. Eventuele configuratiefouten zullen hierboven zijn gemeld." -debug: - data-save: "Populatie gegevens voor wereld \"%s\" opgeslagen" -use-paper: - - "Het lijkt erop dat je Spigot/CraftBukkit gebruikt." - - "Terra &owerkt&r op Spigot, maar sommige functionaliteit zal verloren gaan. (Terra is niet getest op CraftBukkit; er wordt dus ook geen ondersteuning voor gegeven)." - - "Om het meeste uit Terra te halen, schakel dan over op Paper." - - "Bovendien biedt Paper enorme prestatieverbeteringen ten opzichte van Spigot, en zelfs alle Spigot plugins zouden met Paper moeten werken!" - - "Om de beste ervaring met Terra, en al je andere plugins, te hebben, gebruik dan Paper." - - "Lees meer op de website van Paper: https://papermc.io/" diff --git a/common/src/main/resources/lang/pl.yml b/common/src/main/resources/lang/pl.yml deleted file mode 100644 index 7c72d280c..000000000 --- a/common/src/main/resources/lang/pl.yml +++ /dev/null @@ -1,117 +0,0 @@ -enable: - - "Jezeli spodoba ci sie Terra, rozwaz wsparcie projektu na Patreon!" - - "Otrzymasz dostep do eksperymentalnych funkcji przed ich premiera!" - - "Wspieraj projekt na: https://www.patreon.com/dfsek" -disable: - - "Dziekuje za korzystanie z Terra!" -command: - debug-only: "Ta komenda musi byc uzyta z trybem debugowym wlaczonym!" - player-only: "Ta komenda jest tylko dla graczy!" - invalid: "Niepoprawna komenda. (Oczekiwane %1$s argumenty, znalezione %2$s)." - players-only: "Komenda jest tylko dla graczy." - world: "Ta komenda musi byc wpisana w swiecie Terra!" - reload: "Przeladowano plik konfiguracyjny Terra." - version: "Ten serwer korzysta z wersji Terra \"%s\"" - main-menu: - - "--------------------Terra--------------------" - - "reload - Przeladuj dane konfiguracyjne" - - "biome - Otrzymaj informacje o obecnym biomie" - - "ore - Wygeneruj zloze rud w strone w ktora patrzysz (Do debugowania)" - - "save-data - Zapisz dane" - - "structure - Zaladuj i wyeksportuj dane struktur" - - "profile - Opcje profilera" - - "image - Opcje obrazu/GUI" - biome: - biome-found: "Zlokalizowano biom na (%1$s, %2$s)" - unable-to-locate: "Nie moglismy zlokalizowac biomu." - invalid-radius: "Niepoprawny zakres: \"%s\"" - invalid: "Niepoprawne Biome ID: \"%s\"" - in: "Jestes na \"%s\"" - ore: - main-menu: - - "---------------Terra/rudy---------------" - - "Generuje zloze rud w strone w ktora patrzysz." - out-of-range: "Blok spoza zakresu" - invalid-ore: "Niemoglismy znalezc Rudy \"%s\"" - geometry: - main-menu: - - "---------------Terra/geometria----------------" - - "Zroznicowane komendy geometrii voxeli do debugowania" - - "sphere - Generuje kule" - - "deformsphere - Generuje zdeformowana kul" - - "tube - Generaje tube" - deform: - invalid-radius: "Niepoprawny zakres: \"%s\"" - invalid-deform: "Niepoprawna deformacja: \"%s\"" - invalid-frequency: "Niepoprawna czestotliwosc: \"%s\"" - sphere: - invalid-radius: "Niepoprawny zakres: \"%s\"" - tube: - invalid-radius: "Niepoprawny zakres: \"%s\"" - image: - main-menu: - - "---------------Terra/obraz---------------" - - "render - Renderuje obraz o podanej szerokosci i wysokosci, moze byc potem zaimportowane jako swiat." - - "gui - Otwiera GUI debugowania (Musi byc wlaczone w pliku konfiguracyjnym)" - gui: - main-menu: - - "-------------Terra/obraz/gui-------------" - - "raw - Otwiera GUI z surowymi danymi Biomu" - - "step - Przerenderowuje dane aby pokazac granice bardziej przejrzyscie" - debug: "Tryb debugowania musi byc wlaczony aby debugowac za pomoca GUI! GUI debugowania NIE JEST STABILNE!" - render: - save: "Zapisano obraz jako \"%s\"" - error: "Wystapil error podczas generowania obrazu!" - profile: - main-menu: - - "---------------Terra/profil---------------" - - "start - Rozpoczyna dzialanie profilera" - - "stop - Zatrzymuje dzialanie profilera" - - "query - Wydobywa dane profilera" - - "reset - Resetuje dane profilera" - reset: "Profiler zostal zresetowany." - start: "Profiler zostal wlaczony." - stop: "Profiler zostal wylaczony." - structure: - main-menu: - - "---------------Terra/struktury---------------" - - "export - Wyeksportuj obecne zaznaczenie w WorldEdicie jako strukture Terra." - - "load - Zaladuj strukture Terra" - invalid-radius: "Niepoprawny zakres: \"%s\"" - invalid-rotation: "Niepoprawny zakres: \"%s\"" - invalid: "Niepoprawne ID Struktury: \"%s\"" - export: "Zapisano strukture jak \"%s\"" -world-config: - loading: "Ladowanie wartosci konfiguracji dla swiata %s..." - not-found: "Konfiguracja dla swiata \"%s\" nie zostala znaleziona. Kopiuje domyslny plik konfiguracyjny." - using-image: "Ladowania swiata z obrazu." - error: "Nie udalo sie zaladowac konfiguracji dla swiata %s" - done: "Ladowanie swiata gotowe. Wykonano to w: %sms" -config-pack: - loaded: "Zaladowano plik konfiguracyjny %1$s w %2$sms." -config: - loaded: "Zaladowano %1$s z pliku %2$s" - loaded-all: "Zaladowano %1$s %2$s(s) w %3$sms." - error: - invalid-failover: "Niepoprawny typ awaryjnego przelaczania: \"%s\"" - duplicate: "Zduplikowano ID znalezione w pliku: %s" - file: - - "Blad konfiguracji w objekcie Terra. Plik: %1$s" - - "%2$s" - - "Popraw to przed rozpoczeciem!" - generic: - - "Wystapil blad podczas ladowania konfiguracji." - - "Prosze zglos to do Terra." -warning: - no-population: "Chunki populacyjne nie zostaly zaladowane. Jezeli to jest pierwszy raz kiedy wlaczasz serwer z Terra, lub tworzysz nowy swiat, to jest normalne." -error: - severe-config: "Powazne bledy konfiguracji zablokowaly generowanie terenu na koordynatach: %1$s, %2$s. Prosze sprawdz konfiguracyje w poszukiwaniu bledow. Wszelkie bledy konfiguracyjne zostaly zgloszone powyzej." -debug: - data-save: "Zapisane dane dla swiata \"%s\"" -use-paper: - - "Wyglada na to ze dalej korzystasz z Spigot/CraftBukkit." - - "Terra &odziala&r na Spigotcie, niektore funkcje moga byc stracone. (Terra nie jest przetestowana na CraftBukkit; wiec nie wspieramy CraftBukkit)." - - "Aby wycisnac jak najwiecej z Terra, prosze przejdz na Paper." - - "Ponadto, Paper oferuje ulepszona wydajnosc wzgledem Spigota, a wszystkie pluginy z Spigota powinny dzialac na Paperze!" - - "Dla jak najlepszych doswiadczen z Terra, i wszystkimi twoimi pluginami, przejdz na Papera." - - "Dowiedz sie wiecej o Paperze na ich stronie: https://papermc.io/" \ No newline at end of file diff --git a/common/src/main/resources/lang/pt_br.yml b/common/src/main/resources/lang/pt_br.yml deleted file mode 100644 index c2b6777f7..000000000 --- a/common/src/main/resources/lang/pt_br.yml +++ /dev/null @@ -1,122 +0,0 @@ -enable: - - "Se você gosta do Terra, considere apoiar o projeto no Patreon!" - - "Você terá acesso a recursos experimentais antes de serem lançados!" - - "Apoie o projeto aqui: https://www.patreon.com/dfsek" -disable: - - "Obrigado por usar o Terra!" -command: - debug-only: "Este comando deve ser usado com o modo de depuração habilitado!" - player-only: "Este comando é apenas para jogadores!" - invalid: "Comando inválido. (Esperados %1$s argumentos, encontrados %2$s)." - players-only: "O comando é apenas para jogadores." - world: "Este comando deve ser executado em um mundo Terra!" - reload: "Configuração do Terra recarregada." - reload-error: "Ocorreram erros ao recarregar as configurações do Terra. Veja os logs para mais informações." - version: "Este servidor está executando a versão Terra \"%1$s\", na plataforma \"%2$s\"" - main-menu: - - "--------------------Terra--------------------" - - "reload - Recarregar dados de configuração" - - "biome - Obtenha bioma atual" - - "ore - Gere um veio de minério no local que você está enfrentando (para depuração)" - - "save-data - Salvar dados populacionais" - - "structure - Carregar e exportar estruturas" - - "profile - Opções do Profiler" - - "image - Opções de imagem/GUI" - biome: - biome-found: "Bioma localizado em (%1$s, %2$s)" - unable-to-locate: "Não foi possível localizar o bioma." - invalid-radius: "Raio inválido: \"%s\"" - invalid: "ID de bioma inválido: \"%s\"" - in: "Você está em \"%s\"" - packs: - main: "Pacotes de configuração atualmente instalados:" - pack: " - %1$s v%3$s de %2$s" - none: "Nenhum pacote de configuração está instalado." - ore: - main-menu: - - "---------------Terra/ore---------------" - - "Gera um veio de minério no bloco que você está olhando." - out-of-range: "Bloco fora do alcance" - invalid-ore: "Incapaz de encontrar minério \"%s\"" - geometry: - main-menu: - - "---------------Terra/geometry----------------" - - "Vários comandos de depuração de geometria de voxel" - - "sphere - Gere uma esfera" - - "deformsphere - Gere uma esfera deformada" - - "tube - Gere um tubo" - deform: - invalid-radius: "Raio inválido: \"%s\"" - invalid-deform: "Deformação inválida: \"%s\"" - invalid-frequency: "Frequência inválida: \"%s\"" - sphere: - invalid-radius: "Raio inválido: \"%s\"" - tube: - invalid-radius: "Raio inválido: \"%s\"" - image: - main-menu: - - "---------------Terra/image---------------" - - "render - Renderize uma imagem com uma determinada largura e altura, que posteriormente pode ser importada como um mundo." - - "gui - Abra a GUI de depuração (deve ser habilitado na configuração)" - gui: - main-menu: - - "-------------Terra/image/gui-------------" - - "raw - Abra a GUI com dados brutos do bioma" - - "step - Renderize novamente os dados para mostrar as bordas com mais clareza" - debug: "O modo de depuração deve ser habilitado para usar a GUI de depuração! A GUI de depuração NÃO É SEGURA PARA A PRODUÇÃO!" - render: - save: "Imagem salva como \"%s\"" - error: "Ocorreu um erro ao gerar a imagem!" - profile: - main-menu: - - "---------------Terra/profile---------------" - - "start - Inicia o profiler" - - "stop - Para o profiler" - - "query - Coleta dados do profiler" - - "reset - Redefine os dados do profiler" - reset: "O Profiler foi redefinido." - start: "O Profiler foi iniciado." - stop: "O Profiler foi interrompido." - structure: - main-menu: - - "---------------Terra/structure---------------" - - "export - Exporte sua seleção atual do WorldEdit como uma estrutura do Terra." - - "load - Carregar uma estrutura Terra" - invalid-radius: "Raio inválido: \"%s\"" - invalid-rotation: "Rotação inválida: \"%s\"" - invalid: "ID de estrutura inválida: \"%s\"" - export: "Estrutura salva em \"%s\"" -world-config: - load: "Carregando valores de configuração mundiais para o mundo \"%s\"..." - not-found: "A configuração do mundo \"%s\" não foi encontrada. Copiando configuração padrão." - using-image: "Carregando mundo da imagem." - error: "Não é possível carregar a configuração para o mundo %s" - done: "Carga mundial para o mundo \"%1$s\" concluída. Tempo decorrido: %2$sms" -config-pack: - loaded: "Pacote de configuração %1$s v%4$s de %3$s carregado em %2$sms." -config: - loaded: "Carregado %1$s de arquivo %2$s" - loaded-all: "Carregado %1$s %2$s(s) em %3$sms." - error: - invalid-failover: "Tipo de failover inválido: \"%s\"" - duplicate: "ID duplicado encontrado no arquivo: %s" - file: - - "Erro de configuração do objeto Terra. Arquivo: %1$s" - - "%2$s" - - "Corrija isso antes de continuar!" - generic: - - "Ocorreu um erro ao carregar as configurações." - - "Por favor, relate isso ao Terra." -warning: - no-population: "Nenhum bloco de população foi carregado. Se esta é sua primeira vez iniciando seu servidor com Terra, ou se você está criando um novo mundo, isso é normal." -error: - severe-config: "Um erro grave de configuração impediu o Terra de gerar terreno corretamente nas coordenadas: %1$s,%2$s. Verifique se há erros na sua configuração. Quaisquer erros de configuração serão relatados acima." -debug: - data-save : "Dados de população salvos." -use-paper: - - "Você parece estar usando o Spigot/CraftBukkit." - - "Enquanto o Terra trabalha no Spigot, algumas funcionalidades serão perdidas. (Terra não foi testado no CraftBukkit; nenhum suporte será fornecido para o CraftBukkit)." - - "Para obter o máximo do Terra, mude para o Paper." - - "Além disso, o Paper oferece imensas melhorias de desempenho em relação ao Spigot, e todos os plug-ins do Spigot devem funcionar com o Paper!" - - "Para ter a melhor experiência com o Terra e todos os seus plug-ins, use o Paper." - - "Saiba mais no site do Paper: https://papermc.io/" \ No newline at end of file diff --git a/common/src/main/resources/lang/ru.yml b/common/src/main/resources/lang/ru.yml deleted file mode 100644 index f0c8db834..000000000 --- a/common/src/main/resources/lang/ru.yml +++ /dev/null @@ -1,122 +0,0 @@ -enable: - - "Если вам нравится Terra, пожалуйста, поддержите проект на Patreon!" - - "Вы получите доступ к экспериментальным функциям ещё до их релиза!" - - "Поддержите проект здесь: https://www.patreon.com/dfsek" -disable: - - "Благодарим за использование Terra!" -command: - debug-only: "Эта команда может быть введена только в режиме отладки!" - player-only: "Эту команду могут вводить только игроки!" - invalid: "Неверная команда. (Ожидался аргумент %1$s, найден %2$s)." - players-only: "Команда только для игроков." - world: "Эта команда может быть введена только в мире с Terra!" - reload: "Конфигурации Terra перезагружена." - reload-error: "Во время перезагрузки конфигураций Terra произошла ошибка. Просмотрите логи для более детальной информации." - version: "This server is running Terra version \"%1$s\", on platform \"%2$s\"" - main-menu: - - "--------------------Terra--------------------" - - "reload - Перезагрузить конфигурации" - - "biome - Узнать текущий биом" - - "ore - Сгенерировать жилу руд на месте вашего взора (Для отладки)" - - "save-data - Сохранить данные популяции" - - "structure - Загрузить и экспортировать структуры" - - "profile - Команды профайлера" - - "image - Команды образа/интерфейса" - biome: - biome-found: "Биом найден на (%1$s, %2$s)" - unable-to-locate: "Не получилось найти биом." - invalid-radius: "Неверный радиус: \"%s\"" - invalid: "Неверный ID биома: \"%s\"" - in: "Вы находитесь в \"%s\"" - packs: - main: "Установленные наборы конфигураций:" - pack: " - %1$s вер.%3$s от %2$s" - none: "Наборы конфигураций не установлены." - ore: - main-menu: - - "---------------Terra/ore---------------" - - "Генерирует жилу руд на месте вашего взора." - out-of-range: "Блок слишком далеко" - invalid-ore: "Не получилось найти руду \"%s\"" - geometry: - main-menu: - - "---------------Terra/geometry----------------" - - "Различные команды отладки воксельной геометрии" - - "sphere - Сгенерировать сферу" - - "deformsphere - Сгенерировать деформированную сферу" - - "tube - Сгенерировать трубу" - deform: - invalid-radius: "Неверный радиус: \"%s\"" - invalid-deform: "Неверная деформация: \"%s\"" - invalid-frequency: "Неверная частота: \"%s\"" - sphere: - invalid-radius: "Неверный радиус: \"%s\"" - tube: - invalid-radius: "Неверный радиус: \"%s\"" - image: - main-menu: - - "---------------Terra/image---------------" - - "render - Прорендерить образ с указанными шириной и высотой, который позже может быть импортирован как мир." - - "gui - Открыть интерфейс отладки (Должно быть включено в конфигурации)" - gui: - main-menu: - - "-------------Terra/image/gui-------------" - - "raw - Открыть интерфейс с сырыми данными биомов" - - "step - Перерендерить данные для более ясного видения границ" - debug: "Для использования этого интерфейса должен быть включен режим отладки! Режим отладки НЕБЕЗОПАСЕН ДЛЯ СЕРВЕРОВ!" - render: - save: "Образ сохранен как \"%s\"" - error: "Во время генерации образа произошла ошибка!" - profile: - main-menu: - - "---------------Terra/profile---------------" - - "start - Начать анализ профайлером" - - "stop - Остановить анализ профайлером" - - "query - Получить данные профайлера" - - "reset - Обнулить данные профайлера" - reset: "Данные профайлера были обнулены." - start: "Анализ профайлером начат." - stop: "Анализ профайлером остановлен." - structure: - main-menu: - - "---------------Terra/structure---------------" - - "export - Экспортировать выделение WorldEdit'а как структуру Terra" - - "load - Загрузить структуру Terra" - invalid-radius: "Неверный радиус: \"%s\"" - invalid-rotation: "Неверный поворот: \"%s\"" - invalid: "Неверный ID структуры: \"%s\"" - export: "Структура сохранена как \"%s\"" -world-config: - load: "Значения конфигурации мира \"%s\" загружаются..." - not-found: "Конфигурация мира \"%s\" не найдена. Копирование обычной." - using-image: "Загрузка мира с образа." - error: "Не получилось загрузить конфигурацию мира %s" - done: "Загрузка мира \"%1$s\" завершена. Затрачено времени: %2$sмс" -config-pack: - loaded: "Набор конфигураций %1$s вер.%4$s от %3$s загружен за %2$sмс." -config: - loaded: "Загружен %1$s с файла %2$s" - loaded-all: "Загружено %1$s %2$s за %3$sмс." - error: - invalid-failover: "Неверный тип аварийного переключения: \"%s\"" - duplicate: "Дублирующийся ID найден в файле: %s" - file: - - "Ошибка конфигурации объекта Terra. Файл: %1$s" - - "%2$s" - - "Прежде чем продолжить, исправьте это!" - generic: - - "Во время загрузки конфигураций произошла ошибка." - - "Пожалуйста, сообщите об этом разработчикам Terra." -warning: - no-population: "Не было загружено популяторов чанков. Если вы впервые запускаете сервер с Terra или создаете новый мир, то всё в порядке." -error: - severe-config: "Несколько ошибок конфигруации не позволили Terra сгенерировать область нормально по этим координатам: %1$s, %2$s. Пожалуйста, проверьте свою конфигурацию на наличие ошибок. Все ошибки были показаны выше." -debug: - data-save: "Данные популяции мира \"%s\" сохранены" -use-paper: - - "Похоже, что вы используете Spigot/CraftBukkit." - - "Пускай Terra и &oработает&r со Spigot, часть функционала плагина не работает. (Terra не тестировался с CraftBukkit; не ожидайте поддержки для CraftBukkit)." - - "Чтобы получить весь функционал Terra, пожалуйста, используйте Paper." - - "Кроме того, Paper намного производительнее, чем Spigot, а все плагины Spigot должны работать и на Paper!" - - "Если вы хотите получить лучший опыт использования Terra и иных плагинов, пожалуйста, предпочтите Paper." - - "Больше о Paper можно узнать на сайте: https://papermc.io/" diff --git a/common/src/main/resources/lang/zh_cn.yml b/common/src/main/resources/lang/zh_cn.yml deleted file mode 100644 index f72c8b505..000000000 --- a/common/src/main/resources/lang/zh_cn.yml +++ /dev/null @@ -1,107 +0,0 @@ -enable: - - "如果你喜欢Terra,请考虑在Patreon上支持该项目!" - - "你会在项目正式发布前获得实验性特性!" - - "前往该网址支持我们:https://www.patreon.com/dfsek" -disable: - - "感谢使用Terra!" -command: - player-only: "该指令只能由玩家使用!" - terra-world: "该指令只能在Terra世界内使用!" - invalid: "无效的指令。(应有%1$s项参数,现在只有%2$s项)。" - players-only: "指令只能由玩家使用。" - world: "该指令只能在Terra世界内使用!" - reload: "重载Terra配置。" - main-menu: - - "--------------------Terra--------------------" - - "reload - 重载配置数据" - - "biome - 查看所在群系" - - "ore - 在你面朝的位置生成矿脉(用于调试)" - - "save-data - 保存数据" - - "structure - 加载和导出建筑" - - "profile - 分析工具选项" - - "image - 图像/GUI 选项" - biome: - biome-found: "群系位于(%1$s, %2$s)" - unable-to-locate: "无法定位群系。" - invalid-radius: "无效范围:\"%s\"" - invalid: "无效的群系ID: \"%s\"" - in: "你位于\"%s\"" - ore: - main-menu: - - "---------------Terra/矿物---------------" - - "在你所视位置生成矿脉。" - out-of-range: "所视方块超出范围" - invalid-ore: "找不到矿物 \"%s\"" - geometry: - main-menu: - - "---------------Terra/几何----------------" - - "各种几何调试指令" - - "sphere - 生成球体" - - "deformsphere - 生成变形球体" - - "tube - 生成管形" - deform: - invalid-radius: "无效范围:\"%s\"" - invalid-deform: "无效变形:\"%s\"" - invalid-frequency: "无效频率:\"%s\"" - sphere: - invalid-radius: "无效范围:\"%s\"" - tube: - invalid-radius: "无效范围:\"%s\"" - image: - main-menu: - - "---------------Terra/图像---------------" - - "render - 根据给定宽度和高度渲染图像,以便于之后导入到世界内。" - - "gui - 打开调试GUI (必须先在配置内启用)" - gui: - main-menu: - - "-------------Terra/图像/GUI-------------" - - "raw - 打开纯群系数据的GUI" - - "step - 重渲染数据以更清晰地显示边界" - debug: "必须先启用调试模式才能使用GUI!调试GUI不适合在运行中的服务器里使用!" - render: - save: "已将图像保存为\"%s\"" - error: "生成图像时出错!" - profile: - main-menu: - - "---------------Terra/分析---------------" - - "start - 启动分析工具" - - "stop - 关闭分析工具" - - "query - 获取分析数据" - - "reset - 重置分析数据" - reset: "分析工具已重置。" - start: "分析工具已启动。" - stop: "分析工具已关闭。" - structure: - main-menu: - - "---------------Terra/建筑---------------" - - "export - 导出你当前的WorldEdit选区为Terra的建筑。" - - "load - 加载Terra的建筑。" - invalid-radius: "无效范围:\"%s\"" - invalid: "无效建筑ID:\"%s\"" - export: "已将建筑保存为\"%s\"" -world-config: - loading: "正在加载世界%s配置数值……" - not-found: "找不到世界\"%s\"的配置。正应用默认配置。" - using-image: "加载图像中" - error: "无法加载世界%s的配置" - done: "加载世界完成。耗时:%sms" -config-pack: - loaded: "已加载配置%1$s,耗时%2$sms。" -config: - loaded: "已加载%1$s,源自文件%2$s" - loaded-all: "已加载%1$s %2$s(s),耗时%3$sms。" - error: - duplicate: "该文件内的ID重复:%s" - file: - - "Terra目标的配置出错。文件:%1$s" - - "%2$s" - - "请先校正该配置!" - generic: - - "加载配置时出错。" - - "请汇报该错误。" -warning: - no-population: "未加载区块。如果这是你第一次安装Terra后开服,或者你只是创建新世界,那么你看到这条消息很正常。" -error: - severe-config: "严重配置错误,该错误阻止Terra正常生成位于该坐标的地形:%1$s, %2$s。请检查你的配置。任何配置错误都会显示在上面。" -debug: - data-save: "已保存该世界的地形数据:\"%s\"" \ No newline at end of file diff --git a/common/src/test/java/biome/DistributionTest.java b/common/src/test/java/biome/DistributionTest.java deleted file mode 100644 index 11b3dcef8..000000000 --- a/common/src/test/java/biome/DistributionTest.java +++ /dev/null @@ -1,358 +0,0 @@ -package biome; - -import com.dfsek.tectonic.abstraction.AbstractConfigLoader; -import com.dfsek.tectonic.annotations.Abstractable; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.tectonic.config.ValidatedConfigTemplate; -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.event.EventManager; -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.registry.CheckedRegistry; -import com.dfsek.terra.api.registry.LockedRegistry; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.logging.DebugLogger; -import com.dfsek.terra.api.util.logging.JavaLogger; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.config.GenericLoaders; -import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.builder.BiomeBuilder; -import com.dfsek.terra.config.fileloaders.FolderLoader; -import com.dfsek.terra.config.lang.Language; -import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader; -import com.dfsek.terra.config.loaders.config.BufferedImageLoader; -import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader; -import com.dfsek.terra.config.loaders.config.biome.templates.provider.BiomePipelineTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.provider.ImageProviderTemplate; -import com.dfsek.terra.config.loaders.config.biome.templates.provider.SingleBiomeProviderTemplate; -import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.AbstractableTemplate; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.profiler.Profiler; -import com.dfsek.terra.registry.config.BiomeRegistry; -import com.dfsek.terra.registry.config.NoiseRegistry; -import com.dfsek.terra.world.TerraWorld; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.WritableRaster; -import java.io.File; -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.ThreadLocalRandom; -import java.util.logging.Logger; - -public class DistributionTest { - private static final TerraPlugin MAIN = new TerraPlugin() { - @Override - public WorldHandle getWorldHandle() { - return null; - } - - @Override - public TerraWorld getWorld(World world) { - return null; - } - - @Override - public com.dfsek.terra.api.util.logging.Logger logger() { - return new JavaLogger(Logger.getLogger("Terra")); - } - - @Override - public PluginConfig getTerraConfig() { - return new PluginConfig(); - } - - @Override - public File getDataFolder() { - return null; - } - - @Override - public boolean isDebug() { - return false; - } - - @Override - public Language getLanguage() { - return null; - } - - @Override - public CheckedRegistry getConfigRegistry() { - return null; - } - - @Override - public LockedRegistry getAddons() { - return null; - } - - @Override - public boolean reload() { - return true; - } - - @Override - public ItemHandle getItemHandle() { - return null; - } - - @Override - public void saveDefaultConfig() { - - } - - @Override - public String platformName() { - return null; - } - - @Override - public DebugLogger getDebugLogger() { - return new DebugLogger(new JavaLogger(Logger.getLogger("Terra"))); - } - - @Override - public EventManager getEventManager() { - return null; - } - - @Override - public Profiler getProfiler() { - return null; - } - - @Override - public void register(TypeRegistry registry) { - - } - }; - - - private static BiomeProvider getProvider(long seed) throws ConfigException, IOException { - System.out.println(seed); - File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/default/"); - FolderLoader folderLoader = new FolderLoader(pack.toPath()); - - AbstractConfigLoader loader = new AbstractConfigLoader(); - new GenericLoaders(MAIN).register(loader); - - BiomeRegistry biomeRegistry = new BiomeRegistry(); - folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.loadConfigs(inputStreams, TestBiome::new), MAIN)); - - BiomeProviderTemplate template = new BiomeProviderTemplate(); - ConfigLoader pipeLoader = new ConfigLoader() - .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader()) - .registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader()) - .registerLoader(BiomeBuilder.class, biomeRegistry) - .registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader)) - .registerLoader(SingleBiomeProviderTemplate.class, SingleBiomeProviderTemplate::new) - .registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(MAIN)) - .registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry)); - new GenericLoaders(MAIN).register(pipeLoader); - - pipeLoader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(new NoiseRegistry())); - - pipeLoader.load(template, folderLoader.get("pack.yml")); - return template.getBiomeProviderBuilder().build(seed); - } - - public static void main(String... args) throws ConfigException, IOException { - JFrame testFrame = new JFrame("Biome Viewer"); - - - final BiomeProvider[] provider = {getProvider(2403)}; - - - int size = 1024; - final BufferedImage[] image = {new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB)}; - for(int x = 0; x < size; x++) { - for(int z = 0; z < size; z++) { - image[0].setRGB(x, z, provider[0].getBiome(x, z).getColor()); - } - } - - JLabel img = new JLabel(new ImageIcon(image[0])); - - testFrame.add(img); - testFrame.pack(); - img.addMouseListener(new MouseListener() { - @Override - public void mouseClicked(MouseEvent e) { - BufferedImage newImage = deepCopy(image[0]); - Graphics graphics = newImage.getGraphics(); - graphics.setColor(Color.WHITE); - graphics.fillRect(0, 0, 512, 24); - graphics.setColor(Color.BLACK); - graphics.setFont(new Font("Monospace", Font.BOLD, 20)); - graphics.drawString(provider[0].getBiome(e.getX(), e.getY()).toString(), 0, 20); - - graphics.setColor(Color.WHITE); - graphics.fillOval(e.getX() - 2, e.getY() - 2, 12, 12); - graphics.setColor(Color.BLACK); - graphics.fillOval(e.getX(), e.getY(), 8, 8); - - img.setIcon(new ImageIcon(newImage)); - } - - @Override - public void mousePressed(MouseEvent e) { - - } - - @Override - public void mouseReleased(MouseEvent e) { - - } - - @Override - public void mouseEntered(MouseEvent e) { - - } - - @Override - public void mouseExited(MouseEvent e) { - - } - }); - - testFrame.addKeyListener(new KeyListener() { - @Override - public void keyTyped(KeyEvent e) { - if(e.getKeyChar() == 's') { - long l = System.nanoTime(); - try { - provider[0] = getProvider(ThreadLocalRandom.current().nextLong()); - } catch(ConfigException | IOException configException) { - configException.printStackTrace(); - } - image[0] = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); - for(int x = 0; x < size; x++) { - for(int z = 0; z < size; z++) { - image[0].setRGB(x, z, provider[0].getBiome(x, z).getColor()); - } - } - long n = System.nanoTime(); - double t = n - l; - System.out.println("Time: " + t / 1000000 + "ms"); - img.setIcon(new ImageIcon(image[0])); - } - } - - @Override - public void keyPressed(KeyEvent e) { - - } - - @Override - public void keyReleased(KeyEvent e) { - - } - }); - - testFrame.setResizable(false); - testFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - testFrame.setVisible(true); - - } - - private static BufferedImage deepCopy(BufferedImage bi) { - ColorModel cm = bi.getColorModel(); - boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); - WritableRaster raster = bi.copyData(null); - return new BufferedImage(cm, raster, isAlphaPremultiplied, null); - } - - private static final class BiomeProviderTemplate implements ConfigTemplate { - @Value("biomes") - BiomeProvider.BiomeProviderBuilder biomeProviderBuilder; - - public BiomeProvider.BiomeProviderBuilder getBiomeProviderBuilder() { - return biomeProviderBuilder; - } - } - - private static final class TestBiome extends AbstractableTemplate implements TerraBiome, ValidatedConfigTemplate, BiomeBuilder { - - @Value("color") - @Default - @Abstractable - private int color; - - @Value("tags") - @Abstractable - @Default - private Set tags = new HashSet<>(); - - @Value("id") - private String id; - - @Override - public ProbabilityCollection getVanillaBiomes() { - return null; - } - - @Override - public BiomeTemplate getTemplate() { - return null; - } - - @Override - public Generator getGenerator(World w) { - return null; - } - - @Override - public int getColor() { - return color; - } - - @Override - public Set getTags() { - return tags; - } - - @Override - public boolean validate() { - color += (255 << 24); // Alpha adjustment - tags.add("BIOME:" + id); - return true; - } - - @Override - public String getID() { - return id; - } - - @Override - public String toString() { - return id; - } - - @Override - public TestBiome apply(Long aLong) { - return this; - } - } -} diff --git a/common/src/test/java/biome/ImageTest.java b/common/src/test/java/biome/ImageTest.java deleted file mode 100644 index 04bcee35b..000000000 --- a/common/src/test/java/biome/ImageTest.java +++ /dev/null @@ -1,218 +0,0 @@ -package biome; - -import com.dfsek.tectonic.abstraction.AbstractConfigLoader; -import com.dfsek.tectonic.annotations.Abstractable; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.tectonic.config.ValidatedConfigTemplate; -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.api.world.biome.TerraBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.api.world.biome.provider.ImageBiomeProvider; -import com.dfsek.terra.config.fileloaders.FolderLoader; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.AbstractableTemplate; -import com.dfsek.terra.registry.OpenRegistry; -import org.junit.jupiter.api.Test; - -import javax.imageio.ImageIO; -import javax.swing.*; -import java.awt.*; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; -import java.awt.image.WritableRaster; -import java.io.File; -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.ThreadLocalRandom; - -public class ImageTest { - private static ImageBiomeProvider getProvider(long seed) throws ConfigException, IOException { - System.out.println(seed); - File pack = new File("/home/dfsek/Documents/Terra/platforms/bukkit/target/server/plugins/Terra/packs/default/"); - FolderLoader folderLoader = new FolderLoader(pack.toPath()); - - AbstractConfigLoader loader = new AbstractConfigLoader(); - - OpenRegistry biomeRegistry = new OpenRegistry() { - }; - folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.loadConfigs(inputStreams, TestBiome::new), null)); - - return new ImageBiomeProvider(biomeRegistry.entries(), ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER); - } - - @Test - public static void main(String... args) throws ConfigException, IOException { - JFrame testFrame = new JFrame("Biome Viewer"); - - - final BiomeProvider[] provider = {getProvider(2403)}; - - - int size = 1024; - final BufferedImage[] image = {new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB)}; - for(int x = 0; x < size; x++) { - for(int z = 0; z < size; z++) { - image[0].setRGB(x, z, provider[0].getBiome(x, z).getColor()); - } - } - - JLabel img = new JLabel(new ImageIcon(image[0])); - - testFrame.add(img); - testFrame.pack(); - img.addMouseListener(new MouseListener() { - @Override - public void mouseClicked(MouseEvent e) { - BufferedImage newImage = deepCopy(image[0]); - Graphics graphics = newImage.getGraphics(); - graphics.setColor(Color.WHITE); - graphics.fillRect(0, 0, 512, 24); - graphics.setColor(Color.BLACK); - graphics.setFont(new Font("Monospace", Font.BOLD, 20)); - graphics.drawString(provider[0].getBiome(e.getX(), e.getY()).toString(), 0, 20); - - graphics.setColor(Color.WHITE); - graphics.fillOval(e.getX() - 2, e.getY() - 2, 12, 12); - graphics.setColor(Color.BLACK); - graphics.fillOval(e.getX(), e.getY(), 8, 8); - - img.setIcon(new ImageIcon(newImage)); - } - - @Override - public void mousePressed(MouseEvent e) { - - } - - @Override - public void mouseReleased(MouseEvent e) { - - } - - @Override - public void mouseEntered(MouseEvent e) { - - } - - @Override - public void mouseExited(MouseEvent e) { - - } - }); - - testFrame.addKeyListener(new KeyListener() { - @Override - public void keyTyped(KeyEvent e) { - if(e.getKeyChar() == 's') { - try { - provider[0] = getProvider(ThreadLocalRandom.current().nextLong()); - } catch(ConfigException | IOException configException) { - configException.printStackTrace(); - } - image[0] = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); - for(int x = 0; x < size; x++) { - for(int z = 0; z < size; z++) { - image[0].setRGB(x, z, provider[0].getBiome(x, z).getColor()); - } - } - img.setIcon(new ImageIcon(image[0])); - } - } - - @Override - public void keyPressed(KeyEvent e) { - - } - - @Override - public void keyReleased(KeyEvent e) { - - } - }); - - testFrame.setResizable(false); - testFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - testFrame.setVisible(true); - - } - - private static BufferedImage deepCopy(BufferedImage bi) { - ColorModel cm = bi.getColorModel(); - boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); - WritableRaster raster = bi.copyData(null); - return new BufferedImage(cm, raster, isAlphaPremultiplied, null); - } - - private static final class BiomeProviderTemplate implements ConfigTemplate { - @Value("biome-pipeline") - BiomeProvider.BiomeProviderBuilder biomeProviderBuilder; - - public BiomeProvider.BiomeProviderBuilder getBiomeProviderBuilder() { - return biomeProviderBuilder; - } - } - - private static final class TestBiome extends AbstractableTemplate implements TerraBiome, ValidatedConfigTemplate { - - @Value("color") - @Default - @Abstractable - private int color; - - @Value("tags") - @Abstractable - @Default - private Set tags = new HashSet<>(); - - @Value("id") - private String id; - - @Override - public ProbabilityCollection getVanillaBiomes() { - return null; - } - - @Override - public Generator getGenerator(World w) { - return null; - } - - @Override - public int getColor() { - return color; - } - - @Override - public Set getTags() { - return tags; - } - - @Override - public boolean validate() { - color += (255 << 24); // Alpha adjustment - tags.add("BIOME:" + id); - return true; - } - - @Override - public String getID() { - return id; - } - - @Override - public String toString() { - return id; - } - } -} diff --git a/common/src/test/java/command/CommandTest.java b/common/src/test/java/command/CommandTest.java deleted file mode 100644 index 2598be813..000000000 --- a/common/src/test/java/command/CommandTest.java +++ /dev/null @@ -1,236 +0,0 @@ -package command; - -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.TerraCommandManager; -import com.dfsek.terra.api.command.annotation.Argument; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.Subcommand; -import com.dfsek.terra.api.command.annotation.Switch; -import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget; -import com.dfsek.terra.api.command.annotation.inject.SwitchTarget; -import com.dfsek.terra.api.command.arg.DoubleArgumentParser; -import com.dfsek.terra.api.command.arg.IntegerArgumentParser; -import com.dfsek.terra.api.command.exception.CommandException; -import com.dfsek.terra.api.command.exception.InvalidArgumentsException; -import com.dfsek.terra.api.command.exception.MalformedCommandException; -import com.dfsek.terra.api.platform.CommandSender; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; - -import static org.junit.jupiter.api.Assertions.fail; - -public class CommandTest { - @Test - public void subcommand() throws CommandException { - CommandManager manager = new TerraCommandManager(null); - manager.register("test", DemoParentCommand.class); - - manager.execute("test", null, Arrays.asList("subcommand1", "first", "2")); - manager.execute("test", null, Arrays.asList("subcommand2", "first", "2")); - manager.execute("test", null, Arrays.asList("s1", "first", "2", "3.4")); - manager.execute("test", null, Arrays.asList("s2", "first", "2")); - manager.execute("test", null, Arrays.asList("sub1", "first", "2", "3.4")); - manager.execute("test", null, Arrays.asList("sub2", "first", "2")); - manager.execute("test", null, Arrays.asList("first", "2")); // Parent command args - - System.out.println("ARGS: " + manager.getMaxArgumentDepth()); - } - - @Test - public void args() throws CommandException { - CommandManager manager = new TerraCommandManager(null); - manager.register("test", DemoCommand.class); - - manager.execute("test", null, Arrays.asList("first", "2")); - manager.execute("test", null, Arrays.asList("first", "2", "3.4")); - } - - @Test - public void argsBeforeFlags() throws CommandException { - CommandManager manager = new TerraCommandManager(null); - manager.register("test", DemoCommand.class); - - try { - manager.execute("test", null, Arrays.asList("first", "-flag", "2")); - fail(); - } catch(InvalidArgumentsException ignore) { - } - } - - @Test - public void requiredArgsFirst() throws CommandException { - CommandManager manager = new TerraCommandManager(null); - manager.register("test", DemoInvalidCommand.class); - - try { - manager.execute("test", null, Arrays.asList("first", "2")); - fail(); - } catch(MalformedCommandException ignore) { - } - } - - @Test - public void switches() throws CommandException { - CommandManager manager = new TerraCommandManager(null); - manager.register("test", DemoSwitchCommand.class); - - manager.execute("test", null, Arrays.asList("first", "2")); - manager.execute("test", null, Arrays.asList("first", "2", "3.4")); - - manager.execute("test", null, Arrays.asList("first", "2", "-a")); - manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-b")); - - manager.execute("test", null, Arrays.asList("first", "2", "-aSwitch")); - manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-bSwitch")); - - manager.execute("test", null, Arrays.asList("first", "2", "-aSwitch", "-b")); - manager.execute("test", null, Arrays.asList("first", "2", "3.4", "-bSwitch", "-a")); - } - - @Command( - arguments = { - @Argument(value = "arg0"), - @Argument(value = "arg1", argumentParser = IntegerArgumentParser.class), - @Argument(value = "arg2", required = false, argumentParser = DoubleArgumentParser.class, defaultValue = "0") - } - ) - public static final class DemoCommand implements CommandTemplate { - - @ArgumentTarget("arg0") - private String arg0; - - @ArgumentTarget("arg1") - private Integer arg1; - - @ArgumentTarget("arg2") - private Double arg2; - - - @Override - public void execute(CommandSender sender) { - System.out.println(arg0); - System.out.println(arg1); - System.out.println(arg2); - } - } - - @Command( - arguments = { - @Argument(value = "arg0"), - @Argument(value = "arg1"), - @Argument(value = "arg2", required = false) - }, - switches = { - @Switch(value = "a", aliases = {"aSwitch"}), - @Switch(value = "b", aliases = {"bSwitch"}) - } - ) - public static final class DemoSwitchCommand implements CommandTemplate { - @ArgumentTarget("arg0") - private String arg0; - - @ArgumentTarget("arg1") - private String arg1; - - @ArgumentTarget("arg2") - private String arg2; - - @SwitchTarget("a") - private boolean a; - - @SwitchTarget("b") - private boolean b; - - - @Override - public void execute(CommandSender sender) { - System.out.println(arg0); - System.out.println(arg1); - System.out.println(arg2); - - System.out.println("A: " + a); - System.out.println("B: " + b); - } - } - - @Command( - arguments = { - @Argument(value = "arg0"), - @Argument(value = "arg2", required = false), // optional arguments must be last. this command is invalid. - @Argument(value = "arg1") - } - ) - public static final class DemoInvalidCommand implements CommandTemplate { - - @Override - public void execute(CommandSender sender) { - throw new Error("this should never be reached"); - } - } - - @Command( - arguments = { - @Argument(value = "arg0"), - @Argument(value = "arg1"), - @Argument(value = "arg2", required = false), - }, - subcommands = { - @Subcommand( - value = "subcommand1", - aliases = {"s1", "sub1"}, - clazz = DemoChildCommand.class - ), - @Subcommand( - value = "subcommand2", - aliases = {"s2", "sub2"}, - clazz = DemoChildCommand.class // Duplicate command intentional. - ) - } - ) - public static final class DemoParentCommand implements CommandTemplate { - @ArgumentTarget("arg0") - private String arg0; - - @ArgumentTarget("arg1") - private String arg1; - - @ArgumentTarget("arg2") - private String arg2; - - - @Override - public void execute(CommandSender sender) { - System.out.println(arg0); - System.out.println(arg1); - System.out.println(arg2); - } - } - - @Command( - arguments = { - @Argument(value = "arg0"), - @Argument(value = "arg1"), - @Argument(value = "arg2", required = false), - } - ) - public static final class DemoChildCommand implements CommandTemplate { - @ArgumentTarget("arg0") - private String arg0; - - @ArgumentTarget("arg1") - private String arg1; - - @ArgumentTarget("arg2") - private String arg2; - - - @Override - public void execute(CommandSender sender) { - System.out.println(arg0); - System.out.println(arg1); - System.out.println(arg2); - } - } -} diff --git a/common/src/test/java/noise/ColorConfigTemplate.java b/common/src/test/java/noise/ColorConfigTemplate.java deleted file mode 100644 index ddc3ba9f0..000000000 --- a/common/src/test/java/noise/ColorConfigTemplate.java +++ /dev/null @@ -1,23 +0,0 @@ -package noise; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; - -public class ColorConfigTemplate implements ConfigTemplate { - @Value("colors") - private ProbabilityCollection colors; - - @Value("enable") - @Default - private boolean enable = false; - - public boolean enable() { - return enable; - } - - public ProbabilityCollection getColors() { - return colors; - } -} diff --git a/common/src/test/java/noise/NoiseConfigTemplate.java b/common/src/test/java/noise/NoiseConfigTemplate.java deleted file mode 100644 index 8d671db4e..000000000 --- a/common/src/test/java/noise/NoiseConfigTemplate.java +++ /dev/null @@ -1,16 +0,0 @@ -package noise; - -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; - - -@SuppressWarnings("unused") -public class NoiseConfigTemplate implements ConfigTemplate { - @Value(".") - private NoiseSeeded builder; - - public NoiseSeeded getBuilder() { - return builder; - } -} diff --git a/common/src/test/java/noise/NoiseTool.java b/common/src/test/java/noise/NoiseTool.java deleted file mode 100644 index a335a88de..000000000 --- a/common/src/test/java/noise/NoiseTool.java +++ /dev/null @@ -1,205 +0,0 @@ -package noise; - -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.tectonic.loading.ConfigLoader; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.collections.ProbabilityCollection; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import com.dfsek.terra.config.GenericLoaders; -import com.dfsek.terra.config.fileloaders.FolderLoader; -import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader; -import com.dfsek.terra.config.loaders.config.BufferedImageLoader; -import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; -import com.dfsek.terra.registry.config.NoiseRegistry; -import org.apache.commons.io.FileUtils; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.KeyEvent; -import java.awt.event.KeyListener; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Paths; -import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.atomic.AtomicInteger; - -public class NoiseTool { - public static void main(String... args) throws ConfigException, IOException { - JFrame frame = new JFrame("Noise Viewer"); - - AtomicInteger seed = new AtomicInteger(2403); - JLabel label = new JLabel(new ImageIcon(load(seed.get(), false, false))); - frame.add(label); - frame.pack(); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - - - frame.addKeyListener(new KeyListener() { - @Override - public void keyTyped(KeyEvent e) { - if(e.getKeyChar() == 'r') { - try { - label.setIcon(new ImageIcon(load(seed.get(), false, false))); - } catch(ConfigException | IOException configException) { - configException.printStackTrace(); - } - } else if(e.getKeyChar() == 's') { - try { - seed.set(ThreadLocalRandom.current().nextInt()); - label.setIcon(new ImageIcon(load(seed.get(), false, false))); - } catch(ConfigException | IOException configException) { - configException.printStackTrace(); - } - } else if(e.getKeyChar() == 'd') { - try { - label.setIcon(new ImageIcon(load(seed.get(), true, false))); - } catch(ConfigException | IOException configException) { - configException.printStackTrace(); - } - } else if(e.getKeyChar() == 'c') { - try { - label.setIcon(new ImageIcon(load(seed.get(), false, true))); - } catch(ConfigException | IOException configException) { - configException.printStackTrace(); - } - } - } - - @Override - public void keyPressed(KeyEvent e) { - } - - @Override - public void keyReleased(KeyEvent e) { - } - }); - - frame.setVisible(true); - } - - private static int normal(double in, double out, double min, double max) { - double range = max - min; - return (int) (((in - min) * out) / range); - } - - private static int buildRGBA(int in) { - return (255 << 24) - + (in << 16) - + (in << 8) - + in; - } - - private static BufferedImage load(int seed, boolean distribution, boolean chunk) throws ConfigException, IOException { - long s = System.nanoTime(); - - FolderLoader folderLoader = new FolderLoader(Paths.get("./")); - - ConfigLoader loader = new ConfigLoader(); - loader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(new NoiseRegistry())) - .registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader)) - .registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader()); - - new GenericLoaders(null).register(loader); - NoiseConfigTemplate template = new NoiseConfigTemplate(); - - File file = new File("./config.yml"); - - System.out.println(file.getAbsolutePath()); - - File colorFile = new File("./color.yml"); - - - System.out.println(file.getAbsolutePath()); - if(!file.exists()) { - file.getParentFile().mkdirs(); - FileUtils.copyInputStreamToFile(NoiseTool.class.getResourceAsStream("/config.yml"), file); - } - - - boolean colors = false; - ColorConfigTemplate color = new ColorConfigTemplate(); - if(colorFile.exists()) { - loader.load(color, new FileInputStream(colorFile)); - colors = color.enable(); - } - ProbabilityCollection colorCollection = color.getColors(); - - loader.load(template, new FileInputStream(file)); - System.out.println(template.getBuilder().getDimensions()); - NoiseSampler noise = template.getBuilder().apply((long) seed); - - - int size = 1024; - - BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); - - double[][] noiseVals = new double[size][size]; - int[][] rgbVals = new int[size][size]; - double max = Double.MIN_VALUE; - double min = Double.MAX_VALUE; - - int[] buckets = new int[1024]; - - for(int x = 0; x < noiseVals.length; x++) { - for(int z = 0; z < noiseVals[x].length; z++) { - double n = noise.getNoise(x, z); - noiseVals[x][z] = n; - max = Math.max(n, max); - min = Math.min(n, min); - if(colors) rgbVals[x][z] = colorCollection.get(noise, x, z); - } - } - - for(int x = 0; x < noiseVals.length; x++) { - for(int z = 0; z < noiseVals[x].length; z++) { - if(colors) image.setRGB(x, z, rgbVals[x][z] + (255 << 24)); - else image.setRGB(x, z, buildRGBA(normal(noiseVals[x][z], 255, min, max))); - buckets[normal(noiseVals[x][z], size - 1, min, max)]++; - } - } - - long time = System.nanoTime() - s; - - double ms = time / 1000000d; - - - if(chunk) { - for(int x = 0; x < image.getWidth(); x += 16) { - for(int y = 0; y < image.getHeight(); y++) image.setRGB(x, y, buildRGBA(0)); - } - for(int y = 0; y < image.getWidth(); y += 16) { - for(int x = 0; x < image.getHeight(); x++) image.setRGB(x, y, buildRGBA(0)); - } - } - - Graphics graphics = image.getGraphics(); - graphics.setColor(Color.WHITE); - graphics.fillRect(0, 0, 325, 90); - graphics.setColor(Color.BLACK); - graphics.setFont(new Font("Monospace", Font.BOLD, 20)); - graphics.drawString("min: " + min, 0, 20); - graphics.drawString("max: " + max, 0, 40); - graphics.drawString("seed: " + seed, 0, 60); - graphics.drawString("time: " + ms + "ms", 0, 80); - - if(distribution) { - graphics.setColor(Color.WHITE); - graphics.fillRect(0, size - (size / 4) - 1, size, (size / 4) - 1); - int highestBucket = Integer.MIN_VALUE; - for(int i : buckets) highestBucket = Math.max(highestBucket, i); - graphics.setColor(Color.BLACK); - graphics.drawString("" + highestBucket, 0, size - (size / 4) - 1 + 20); - - for(int x = 0; x < size; x++) { - for(int y = 0; y < ((double) buckets[x] / highestBucket) * ((double) size / 4); y++) { - image.setRGB(x, size - y - 1, buildRGBA(0)); - } - } - - } - - return image; - } -} diff --git a/gradle.properties b/gradle.properties index 59ea64a1a..baf5d0e6a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,8 +7,9 @@ org.gradle.parallel=true org.gradle.caching=true org.gradle.warning.mode=all #org.gradle.logging.level=info +#org.gradle.configureondemand=true # Project information -terra.description=A fast, modern, extensible, platform-agnostic data-driven world generator +terra.description=A modern voxel world generation modding platform terra.source=https://github.com/PolyhedralDev/Terra terra.issues=https://github.com/PolyhedralDev/Terra/issues terra.wiki=https://github.com/PolyhedralDev/Terra/wiki diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cc9cd46e9..3e7c5fc21 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists org.gradle.jvmargs=-Xmx4096m \ No newline at end of file diff --git a/platforms/LICENSE b/platforms/LICENSE new file mode 100644 index 000000000..f288702d2 --- /dev/null +++ b/platforms/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/platforms/bukkit/build.gradle.kts b/platforms/bukkit/build.gradle.kts index 4c7c3648f..97ca84242 100644 --- a/platforms/bukkit/build.gradle.kts +++ b/platforms/bukkit/build.gradle.kts @@ -1,48 +1,39 @@ -import com.dfsek.terra.configureCommon -import com.dfsek.terra.gitClone import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import java.net.URL import java.nio.channels.Channels import java.nio.file.Files -import java.nio.file.Paths import java.nio.file.StandardCopyOption -plugins { - `java-library` - `maven-publish` -} -configureCommon() -group = "com.dfsek.terra.bukkit" - -val mcVersion = "1.17" +val mcVersion = "1.18.2" val testDir = "target/server" val testMem = "3G" -val paperURL = "https://papermc.io/api/v1/paper/%version%/latest/download/" -val purpurURL = "https://ci.pl3x.net/job/Purpur/lastSuccessfulBuild/artifact/final/purpurclip.jar" +val paperBuild = 350 +val paperURL = "https://papermc.io/api/v2/projects/paper/versions/%version%/builds/$paperBuild/downloads/paper-%version%-$paperBuild.jar" +val purpurURL = "https://api.purpurmc.org/v2/purpur/%version%/latest/download" dependencies { - "shadedApi"(project(":common")) - - "compileOnly"("io.papermc.paper:paper-api:1.17-R0.1-SNAPSHOT") - "shadedImplementation"("io.papermc:paperlib:1.0.5") - - "shadedImplementation"("org.bstats:bstats-bukkit:1.7") - - "compileOnly"("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT") - - "shadedApi"("com.google.guava:guava:30.0-jre") + shaded(project(":platforms:bukkit:common")) + shaded(project(":platforms:bukkit:nms:v1_18_R2")) +} + +val throttleCoreCount = 0 + +val jvmFlags = mutableListOf( + "-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200", + "-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch", + "-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M", + "-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4", + "-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90", + "-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem", + "-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs", + "-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear", /*"-javaagent:paperclip.jar"*/ + ) +if(throttleCoreCount > 0) { + jvmFlags.add("-XX:ActiveProcessorCount=$throttleCoreCount") } -val jvmFlags = listOf("-XX:+UseG1GC", "-XX:+ParallelRefProcEnabled", "-XX:MaxGCPauseMillis=200", - "-XX:+UnlockExperimentalVMOptions", "-XX:+DisableExplicitGC", "-XX:+AlwaysPreTouch", - "-XX:G1NewSizePercent=30", "-XX:G1MaxNewSizePercent=40", "-XX:G1HeapRegionSize=8M", - "-XX:G1ReservePercent=20", "-XX:G1HeapWastePercent=5", "-XX:G1MixedGCCountTarget=4", - "-XX:InitiatingHeapOccupancyPercent=15", "-XX:G1MixedGCLiveThresholdPercent=90", - "-XX:G1RSetUpdatingPauseTimePercent=5", "-XX:SurvivorRatio=32", "-XX:+PerfDisableSharedMem", - "-XX:MaxTenuringThreshold=1", "-Dusing.aikars.flags=https://mcflags.emc.gs", - "-Daikars.new.flags=true", "-DIReallyKnowWhatIAmDoingISwear", "-javaagent:paperclip.jar") fun downloadPaperclip(url: String, dir: String) { val clip = URL(url.replace("%version%", mcVersion)) @@ -55,7 +46,7 @@ fun downloadPaperclip(url: String, dir: String) { fun copyTerra(dir: String) { file("$testDir/$dir").walk().forEach { - if(it.name.startsWith("Terra-") && it.name.endsWith(".jar")) it.delete() // Delete old Terra jar(s) + if (it.name.startsWith("Terra-bukkit") && it.name.endsWith(".jar")) it.delete() // Delete old Terra jar(s) } copy { from("$buildDir/libs/Terra-bukkit-$version-shaded.jar") @@ -70,28 +61,30 @@ fun installServer(dir: String) { // Cloning test setup. gitClone("https://github.com/PolyhedralDev/WorldGenTestServer") // Copying plugins - Files.move(file("WorldGenTestServer/plugins").toPath(), - file("$testDir/$dir/plugins").toPath(), - StandardCopyOption.REPLACE_EXISTING) + Files.move( + file("WorldGenTestServer/plugins").toPath(), + file("$testDir/$dir/plugins").toPath(), + StandardCopyOption.REPLACE_EXISTING + ) // Copying config val serverText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/server.properties").readText() file("$testDir/$dir/server.properties").writeText(serverText) val bukkitText = URL("https://raw.githubusercontent.com/PolyhedralDev/WorldGenTestServer/master/bukkit.yml").readText() file("$testDir/$dir/bukkit.yml").writeText(bukkitText.replace("\${world}", "world").replace("\${gen}", "Terra:DEFAULT")) - + println("By proceeding, you are agreeing to the Minecraft EULA: https://account.mojang.com/documents/minecraft_eula") file("$testDir/$dir/eula.txt").writeText("eula=true") - + // clean up file("WorldGenTestServer").deleteRecursively() } fun deleteFolder(folder: File) { - if(folder.exists()) folder.deleteRecursively() + if (folder.exists()) folder.deleteRecursively() } fun deleteFile(file: File) { - if(file.exists()) file.delete() + if (file.exists()) file.delete() } tasks.create("cleanWorlds") { @@ -100,7 +93,7 @@ tasks.create("cleanWorlds") { deleteFolder(file("$testDir/paper/world")) deleteFolder(file("$testDir/paper/world_nether")) deleteFolder(file("$testDir/paper/world_the_end")) - + deleteFolder(file("$testDir/purpur/world")) deleteFolder(file("$testDir/purpur/world_nether")) deleteFolder(file("$testDir/purpur/world_the_end")) @@ -151,12 +144,12 @@ task(name = "runPaper") { doFirst { copyTerra("paper") } - - main = "io.papermc.paperclip.Paperclip" + + mainClass.set("io.papermc.paperclip.Paperclip") jvmArgs = jvmFlags maxHeapSize = testMem minHeapSize = testMem - //args = listOf("nogui") + args = listOf("nogui") workingDir = file("$testDir/paper") classpath = files("$testDir/paper/paperclip.jar") } @@ -169,8 +162,8 @@ task(name = "runPurpur") { doFirst { copyTerra("purpur") } - - main = "io.papermc.paperclip.Paperclip" + + mainClass.set("io.papermc.paperclip.Paperclip") jvmArgs = jvmFlags maxHeapSize = testMem minHeapSize = testMem @@ -183,28 +176,16 @@ tasks.named("shadowJar") { relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats") relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib") relocate("com.google.common", "com.dfsek.terra.lib.google.common") + relocate("org.apache.logging.slf4j", "com.dfsek.terra.lib.slf4j-over-log4j") + exclude("org/slf4j/**") + exclude("org/checkerframework/**") + exclude("org/jetbrains/annotations/**") + exclude("org/intellij/**") + exclude("com/google/errorprone/**") + exclude("com/google/j2objc/**") + exclude("javax/**") } -publishing { - publications { - create("mavenJava") { - artifact(tasks["sourcesJar"]) - artifact(tasks["jar"]) - } - } - repositories { - val mavenUrl = "https://repo.codemc.io/repository/maven-releases/" - - maven(mavenUrl) { - val mavenUsername: String? by project - val mavenPassword: String? by project - if (mavenUsername != null && mavenPassword != null) { - credentials { - username = mavenUsername - password = mavenPassword - } - } - } - } -} \ No newline at end of file +addonDir(project.file("./target/server/paper/plugins/Terra/addons"), tasks.named("runPaper").get()) +addonDir(project.file("./target/server/purpur/plugins/Terra/addons"), tasks.named("runPurpur").get()) diff --git a/platforms/bukkit/common/build.gradle.kts b/platforms/bukkit/common/build.gradle.kts new file mode 100644 index 000000000..b29891d4d --- /dev/null +++ b/platforms/bukkit/common/build.gradle.kts @@ -0,0 +1,18 @@ +repositories { + +} + +dependencies { + shadedApi(project(":common:implementation:base")) + + api("org.slf4j:slf4j-api:1.8.0-beta4") { + because("Minecraft 1.17+ includes slf4j 1.8.0-beta4, so we need to shade it for other versions.") + } + + compileOnly("io.papermc.paper:paper-api:1.18.2-R0.1-SNAPSHOT") + + shadedApi("io.papermc", "paperlib", Versions.Bukkit.paperLib) + shadedApi("com.google.guava:guava:30.0-jre") + + shadedApi("cloud.commandframework", "cloud-paper", Versions.Libraries.cloud) +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitAddon.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitAddon.java new file mode 100644 index 000000000..38d3ff2dc --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitAddon.java @@ -0,0 +1,48 @@ +package com.dfsek.terra.bukkit; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.version.Version; + +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.world.biome.Biome; + +import com.dfsek.terra.bukkit.config.VanillaBiomeProperties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class BukkitAddon implements BaseAddon { + private static final Version VERSION = Versions.getVersion(1, 0, 0); + + private final PlatformImpl terraBukkitPlugin; + + public BukkitAddon(PlatformImpl terraBukkitPlugin) { + this.terraBukkitPlugin = terraBukkitPlugin; + } + + @Override + public void initialize() { + terraBukkitPlugin.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigurationLoadEvent.class) + .then(event -> { + if(event.is(Biome.class)) { + event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties())); + } + }) + .global(); + } + + @Override + public Version getVersion() { + return VERSION; + } + + @Override + public String getID() { + return "terra-bukkit"; + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitCommandSender.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitCommandSender.java new file mode 100644 index 000000000..af1627c93 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitCommandSender.java @@ -0,0 +1,62 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit; + +import org.bukkit.ChatColor; + +import java.util.Optional; + +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.Player; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + + +public class BukkitCommandSender implements CommandSender { + private final org.bukkit.command.CommandSender delegate; + + public BukkitCommandSender(org.bukkit.command.CommandSender delegate) { + this.delegate = delegate; + } + + @Override + public void sendMessage(String message) { + delegate.sendMessage(ChatColor.translateAlternateColorCodes('&', message)); + } + + @Override + public Optional getEntity() { + if(delegate instanceof org.bukkit.entity.Entity entity) { + return Optional.of(BukkitAdapter.adapt(entity)); + } + return Optional.empty(); + } + + @Override + public Optional getPlayer() { + if(delegate instanceof org.bukkit.entity.Player player) { + return Optional.of(BukkitAdapter.adapt(player)); + } + return Optional.empty(); + } + + @Override + public org.bukkit.command.CommandSender getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java new file mode 100644 index 000000000..f36436471 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java @@ -0,0 +1,61 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit; + +import org.bukkit.Location; + +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + + +public class BukkitEntity implements Entity { + private final org.bukkit.entity.Entity entity; + + public BukkitEntity(org.bukkit.entity.Entity entity) { + this.entity = entity; + } + + @Override + public org.bukkit.entity.Entity getHandle() { + return entity; + } + + @Override + public Vector3 position() { + return BukkitAdapter.adapt(entity.getLocation().toVector()); + } + + @Override + public void position(Vector3 location) { + entity.teleport(BukkitAdapter.adapt(location).toLocation(entity.getWorld())); + } + + @Override + public void world(ServerWorld world) { + Location newLoc = entity.getLocation().clone(); + newLoc.setWorld(BukkitAdapter.adapt(world)); + entity.teleport(newLoc); + } + + @Override + public ServerWorld world() { + return BukkitAdapter.adapt(entity.getWorld()); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java new file mode 100644 index 000000000..7d8b0a5f0 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java @@ -0,0 +1,62 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit; + +import org.bukkit.Location; + +import com.dfsek.terra.api.entity.Player; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + + +public class BukkitPlayer implements Player { + private final org.bukkit.entity.Player delegate; + + public BukkitPlayer(org.bukkit.entity.Player delegate) { + this.delegate = delegate; + } + + @Override + public org.bukkit.entity.Player getHandle() { + return delegate; + } + + @Override + public Vector3 position() { + org.bukkit.Location bukkit = delegate.getLocation(); + return Vector3.of(bukkit.getX(), bukkit.getY(), bukkit.getZ()); + } + + @Override + public void position(Vector3 location) { + delegate.teleport(BukkitAdapter.adapt(location).toLocation(delegate.getWorld())); + } + + @Override + public void world(ServerWorld world) { + Location newLoc = delegate.getLocation().clone(); + newLoc.setWorld(BukkitAdapter.adapt(world)); + delegate.teleport(newLoc); + } + + @Override + public ServerWorld world() { + return BukkitAdapter.adapt(delegate.getWorld()); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java new file mode 100644 index 000000000..a58cc1a3d --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/PlatformImpl.java @@ -0,0 +1,126 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit; + +import com.dfsek.tectonic.api.TypeRegistry; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; + +import com.dfsek.terra.api.addon.BaseAddon; + +import org.bukkit.Bukkit; +import org.bukkit.entity.EntityType; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.List; +import java.util.Locale; + +import com.dfsek.terra.AbstractPlatform; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.api.world.biome.PlatformBiome; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; +import com.dfsek.terra.bukkit.handles.BukkitItemHandle; +import com.dfsek.terra.bukkit.handles.BukkitWorldHandle; +import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; + + +public class PlatformImpl extends AbstractPlatform { + private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); + + private final ItemHandle itemHandle = new BukkitItemHandle(); + + private final WorldHandle handle = new BukkitWorldHandle(); + + private final TerraBukkitPlugin plugin; + + public PlatformImpl(TerraBukkitPlugin plugin) { + this.plugin = plugin; + load(); + } + + public TerraBukkitPlugin getPlugin() { + return plugin; + } + + @Override + public boolean reload() { + getTerraConfig().load(this); + getRawConfigRegistry().clear(); + boolean succeed = getRawConfigRegistry().loadAll(this); + + Bukkit.getWorlds().forEach(world -> { + if(world.getGenerator() instanceof BukkitChunkGeneratorWrapper wrapper) { + getConfigRegistry().get(wrapper.getPack().getRegistryKey()).ifPresent(pack -> { + wrapper.setPack(pack); + LOGGER.info("Replaced pack in chunk generator for world {}", world); + }); + } + }); + + return succeed; + } + + @Override + public @NotNull String platformName() { + return "Bukkit"; + } + + @Override + public void runPossiblyUnsafeTask(@NotNull Runnable task) { + Bukkit.getScheduler().runTask(plugin, task); + } + + @Override + protected Iterable platformAddon() { + return List.of(new BukkitAddon(this)); + } + + @Override + public @NotNull WorldHandle getWorldHandle() { + return handle; + } + + @Override + public @NotNull File getDataFolder() { + return plugin.getDataFolder(); + } + + @Override + public @NotNull ItemHandle getItemHandle() { + return itemHandle; + } + + @Override + public void register(TypeRegistry registry) { + super.register(registry); + registry.registerLoader(BlockState.class, (type, o, loader, depthTracker) -> handle.createBlockState((String) o)) + .registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker)) + .registerLoader(EntityType.class, (type, o, loader, depthTracker) -> EntityType.valueOf((String) o)); + + } + + private BukkitPlatformBiome parseBiome(String id, DepthTracker depthTracker) throws LoadException { + if(!id.startsWith("minecraft:")) throw new LoadException("Invalid biome identifier " + id, depthTracker); + return new BukkitPlatformBiome(org.bukkit.block.Biome.valueOf(id.toUpperCase(Locale.ROOT).substring(10))); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java new file mode 100644 index 000000000..8c0b226ef --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java @@ -0,0 +1,180 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit; + +import cloud.commandframework.brigadier.CloudBrigadierManager; +import cloud.commandframework.bukkit.CloudBukkitCapabilities; +import cloud.commandframework.execution.CommandExecutionCoordinator; +import cloud.commandframework.paper.PaperCommandManager; +import org.bukkit.Bukkit; +import org.bukkit.generator.ChunkGenerator; +import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; +import com.dfsek.terra.bukkit.listeners.CommonListener; +import com.dfsek.terra.bukkit.nms.Initializer; +import com.dfsek.terra.bukkit.util.PaperUtil; +import com.dfsek.terra.bukkit.util.VersionUtil; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + + +public class TerraBukkitPlugin extends JavaPlugin { + private static final Logger logger = LoggerFactory.getLogger(TerraBukkitPlugin.class); + + private final PlatformImpl platform = new PlatformImpl(this); + private final Map generatorMap = new HashMap<>(); + + @Override + public void onEnable() { + if(!doVersionCheck()) { + return; + } + + platform.getEventManager().callEvent(new PlatformInitializationEvent()); + + + try { + PaperCommandManager commandManager = new PaperCommandManager<>(this, + CommandExecutionCoordinator.simpleCoordinator(), + BukkitAdapter::adapt, + BukkitAdapter::adapt); + if(commandManager.queryCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) { + commandManager.registerBrigadier(); + final CloudBrigadierManager brigManager = commandManager.brigadierManager(); + if(brigManager != null) { + brigManager.setNativeNumberSuggestions(false); + } + } + + if(commandManager.queryCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) { + commandManager.registerAsynchronousCompletions(); + } + + platform.getEventManager().callEvent(new CommandRegistrationEvent(commandManager)); + + } catch(Exception e) { // This should never happen. + logger.error(""" + TERRA HAS BEEN DISABLED + + Errors occurred while registering commands. + Please report this to Terra. + """.strip(), e); + Bukkit.getPluginManager().disablePlugin(this); + return; + } + + Bukkit.getPluginManager().registerEvents(new CommonListener(), this); // Register master event listener + PaperUtil.checkPaper(this); + + Initializer.init(platform); + } + + public PlatformImpl getPlatform() { + return platform; + } + + @SuppressWarnings({ "deprecation", "AccessOfSystemProperties" }) + private boolean doVersionCheck() { + logger.info("Running on Minecraft version {} with server implementation {}.", VersionUtil.getMinecraftVersionInfo(), + Bukkit.getServer().getName()); + + if(!VersionUtil.getSpigotVersionInfo().isSpigot()) + logger.error("YOU ARE RUNNING A CRAFTBUKKIT OR BUKKIT SERVER. PLEASE UPGRADE TO PAPER."); + + if(VersionUtil.getSpigotVersionInfo().isMohist()) { + if(System.getProperty("IKnowMohistCausesLotsOfIssuesButIWillUseItAnyways") == null) { + Runnable runnable = () -> { // scary big block of text + logger.error(""" + .----------------------------------------------------------------------------------. + | | + | ⚠ !! Warning !! ⚠ | + | | + | You are currently using Mohist. | + | | + | Do not use Mohist. | + | | + | The concept of combining the rigid Bukkit platform, which assumes a 100% | + | Vanilla server, with the flexible Forge platform, which allows changing | + | core components of the game, simply does not work. These platforms are | + | incompatible at a conceptual level, the only way to combine them would | + | be to make incompatible changes to both. As a result, Mohist's Bukkit | + | API implementation is not compliant. This will cause many plugins to | + | break. Rather than fix their platform, Mohist has chosen to distribute | + | unofficial builds of plugins they deem to be "fixed". These builds are not | + | "fixed", they are simply hacked together to work with Mohist's half-baked | + | Bukkit implementation. To distribute these as "fixed" versions implies that: | + | - These builds are endorsed by the original developers. (They are not) | + | - The issue is on the plugin's end, not Mohist's. (It is not. The issue | + | is that Mohist chooses to not create a compliant Bukkit implementation) | + | Please, do not use Mohist. It causes issues with most plugins, and rather | + | than fixing their platform, Mohist has chosen to distribute unofficial | + | hacked-together builds of plugins, calling them "fixed". If you want | + | to use a server API with Forge mods, look at the Sponge project, an | + | API that is designed to be implementation-agnostic, with first-party | + | support for the Forge mod loader. You are bound to encounter issues if | + | you use Terra with Mohist. We will provide NO SUPPORT for servers running | + | Mohist. If you wish to proceed anyways, you can add the JVM System Property | + | "IKnowMohistCausesLotsOfIssuesButIWillUseItAnyways" to enable the plugin. No | + | support will be provided for servers running Mohist. | + | | + | Because of this **TERRA HAS BEEN DISABLED**. | + | Do not come ask us why it is not working. | + | | + |----------------------------------------------------------------------------------| + """.strip()); + }; + runnable.run(); + Bukkit.getScheduler().scheduleAsyncDelayedTask(this, runnable, 200L); + // Bukkit.shutdown(); // we're not *that* evil + Bukkit.getPluginManager().disablePlugin(this); + return false; + } else { + logger.warn(""" + You are using Mohist, so we will not give you any support for issues that may arise. + Since you enabled the "IKnowMohistCausesLotsOfIssuesButIWillUseItAnyways" flag, we won't disable Terra. But be warned. + + > I felt a great disturbance in the JVM, as if millions of plugins suddenly cried out in stack traces and were suddenly silenced. + > I fear something terrible has happened. + > - Astrash + """.strip()); + } + } + return true; + } + + @Override + public @Nullable + ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, String id) { + return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> { + ConfigPack pack = platform.getConfigRegistry().getByID(id).orElseThrow( + () -> new IllegalArgumentException("No such config pack \"" + id + "\"")); + return pack.getGeneratorProvider().newInstance(pack); + }), platform.getRawConfigRegistry().getByID(id).orElseThrow(), platform.getWorldHandle().air()); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/config/VanillaBiomeProperties.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/config/VanillaBiomeProperties.java new file mode 100644 index 000000000..8b2d77e50 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/config/VanillaBiomeProperties.java @@ -0,0 +1,58 @@ +package com.dfsek.terra.bukkit.config; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.api.properties.Properties; + + +public class VanillaBiomeProperties implements ConfigTemplate, Properties { + @Value("colors.grass") + @Default + private Integer grassColor = null; + + @Value("colors.fog") + @Default + private Integer fogColor = null; + + @Value("colors.water") + @Default + private Integer waterColor = null; + + @Value("colors.water-fog") + @Default + private Integer waterFogColor = null; + + @Value("colors.foliage") + @Default + private Integer foliageColor = null; + + @Value("colors.sky") + @Default + private Integer skyColor = null; + + public Integer getFogColor() { + return fogColor; + } + + public Integer getFoliageColor() { + return foliageColor; + } + + public Integer getGrassColor() { + return grassColor; + } + + public Integer getWaterColor() { + return waterColor; + } + + public Integer getWaterFogColor() { + return waterFogColor; + } + + public Integer getSkyColor() { + return skyColor; + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitBiomeProvider.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitBiomeProvider.java new file mode 100644 index 000000000..dfff71ccc --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitBiomeProvider.java @@ -0,0 +1,37 @@ +package com.dfsek.terra.bukkit.generator; + +import org.bukkit.generator.BiomeProvider; +import org.bukkit.generator.WorldInfo; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +import com.dfsek.terra.api.Handle; +import com.dfsek.terra.api.world.biome.Biome; + + +public class BukkitBiomeProvider extends BiomeProvider implements Handle { + private final com.dfsek.terra.api.world.biome.generation.BiomeProvider delegate; + + public BukkitBiomeProvider(com.dfsek.terra.api.world.biome.generation.BiomeProvider delegate) { this.delegate = delegate; } + + @Override + public @NotNull org.bukkit.block.Biome getBiome(@NotNull WorldInfo worldInfo, int x, int y, int z) { + Biome biome = delegate.getBiome(x, y, z, worldInfo.getSeed()); + return (org.bukkit.block.Biome) biome.getPlatformBiome().getHandle(); + } + + @Override + public @NotNull List getBiomes(@NotNull WorldInfo worldInfo) { + return StreamSupport.stream(delegate.getBiomes().spliterator(), false) + .map(terraBiome -> (org.bukkit.block.Biome) terraBiome.getPlatformBiome().getHandle()) + .collect(Collectors.toList()); + } + + @Override + public Object getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java new file mode 100644 index 000000000..ac7444da2 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java @@ -0,0 +1,123 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.generator; + +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.data.BlockData; +import org.bukkit.generator.BiomeProvider; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.generator.LimitedRegion; +import org.bukkit.generator.WorldInfo; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; +import com.dfsek.terra.bukkit.world.BukkitProtoWorld; +import com.dfsek.terra.bukkit.world.BukkitWorldProperties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGenerator implements GeneratorWrapper { + private static final Logger LOGGER = LoggerFactory.getLogger(BukkitChunkGeneratorWrapper.class); + private final BlockState air; + private ChunkGenerator delegate; + private ConfigPack pack; + + public BukkitChunkGeneratorWrapper(ChunkGenerator delegate, ConfigPack pack, BlockState air) { + this.delegate = delegate; + this.pack = pack; + this.air = air; + } + + public void setDelegate(ChunkGenerator delegate) { + this.delegate = delegate; + } + + @Override + public @Nullable BiomeProvider getDefaultBiomeProvider(@NotNull WorldInfo worldInfo) { + return new BukkitBiomeProvider(pack.getBiomeProvider()); + } + + @Override + public void generateNoise(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull ChunkData chunkData) { + BukkitWorldProperties properties = new BukkitWorldProperties(worldInfo); + delegate.generateChunkData(new BukkitProtoChunk(chunkData), properties, pack.getBiomeProvider().caching(properties), x, z); + } + + @Override + public @NotNull List getDefaultPopulators(@NotNull World world) { + return pack.getStages() + .stream() + .map(generationStage -> new BlockPopulator() { + @Override + public void populate(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, + @NotNull LimitedRegion limitedRegion) { + generationStage.populate(new BukkitProtoWorld(limitedRegion, air)); + } + }) + .collect(Collectors.toList()); + } + + @Override + public boolean shouldGenerateCaves() { + return false; + //return pack.vanillaCaves(); + } + + @Override + public boolean shouldGenerateDecorations() { + return true; + } + + + @Override + public boolean shouldGenerateMobs() { + return true; + } + + @Override + public boolean shouldGenerateStructures() { + return true; + } + + public ConfigPack getPack() { + return pack; + } + + public void setPack(ConfigPack pack) { + this.pack = pack; + setDelegate(pack.getGeneratorProvider().newInstance(pack)); + } + + @Override + public ChunkGenerator getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitProtoChunk.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitProtoChunk.java new file mode 100644 index 000000000..666d0ab52 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/generator/BukkitProtoChunk.java @@ -0,0 +1,57 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.generator; + +import org.bukkit.generator.ChunkGenerator; +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState; + + +public class BukkitProtoChunk implements ProtoChunk { + + private final ChunkGenerator.ChunkData delegate; + + public BukkitProtoChunk(ChunkGenerator.ChunkData delegate) { + this.delegate = delegate; + } + + @Override + public ChunkGenerator.ChunkData getHandle() { + return delegate; + } + + @Override + public int getMaxHeight() { + return delegate.getMaxHeight(); + } + + + @Override + public void setBlock(int x, int y, int z, @NotNull BlockState blockState) { + delegate.setBlock(x, y, z, ((BukkitBlockState) blockState).getHandle()); + } + + + @Override + public @NotNull BlockState getBlock(int x, int y, int z) { + return BukkitBlockState.newInstance(delegate.getBlockData(x, y, z)); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java new file mode 100644 index 000000000..b4e7bc18c --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java @@ -0,0 +1,51 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.handles; + +import org.bukkit.Material; +import org.bukkit.NamespacedKey; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.item.Enchantment; +import com.dfsek.terra.bukkit.util.MinecraftUtils; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + + +public class BukkitItemHandle implements ItemHandle { + + @Override + public Item createItem(String data) { + return BukkitAdapter.adapt(Material.matchMaterial(data)); + } + + @Override + public Enchantment getEnchantment(String id) { + return BukkitAdapter.adapt( + org.bukkit.enchantments.Enchantment.getByKey(NamespacedKey.minecraft(MinecraftUtils.stripMinecraftNamespace(id)))); + } + + @Override + public Set getEnchantments() { + return Arrays.stream(org.bukkit.enchantments.Enchantment.values()).map(BukkitAdapter::adapt).collect(Collectors.toSet()); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java new file mode 100644 index 000000000..33e2f6708 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java @@ -0,0 +1,58 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.handles; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.jetbrains.annotations.NotNull; + +import java.util.Locale; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState; +import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; + + +public class BukkitWorldHandle implements WorldHandle { + private final BlockState air; + + public BukkitWorldHandle() { + this.air = BukkitBlockState.newInstance(Material.AIR.createBlockData()); + } + + @Override + public synchronized @NotNull BlockState createBlockState(@NotNull String data) { + org.bukkit.block.data.BlockData bukkitData = Bukkit.createBlockData( + data); // somehow bukkit managed to make this not thread safe! :) + return BukkitBlockState.newInstance(bukkitData); + } + + @Override + public @NotNull BlockState air() { + return air; + } + + @Override + public @NotNull EntityType getEntity(@NotNull String id) { + if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id); + return new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(id.toUpperCase(Locale.ROOT).substring(10))); + } + +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java new file mode 100644 index 000000000..84d836fd7 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java @@ -0,0 +1,29 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.listeners; + +import org.bukkit.event.Listener; + + +/** + * Listener for events on all implementations. + */ +public class CommonListener implements Listener { + public CommonListener() { + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java new file mode 100644 index 000000000..796053e82 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java @@ -0,0 +1,104 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.listeners; + +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.bukkit.event.entity.VillagerAcquireTradeEvent; +import org.bukkit.event.entity.VillagerCareerChangeEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dfsek.terra.api.Platform; + + +/** + * Listener to load on Spigot servers, contains Villager crash prevention and hacky ender eye redirection. + *

+ * (This is currently loaded on all servers; once Paper accepts the StructureLocateEvent PR this will only be loaded on servers without + * StructureLocateEvent). + */ +public class SpigotListener implements Listener { + private static final Logger logger = LoggerFactory.getLogger(SpigotListener.class); + private final Platform platform; + + public SpigotListener(Platform platform) { + this.platform = platform; + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onEnderEye(EntitySpawnEvent e) { +/* + Entity entity = e.getEntity(); + if(e.getEntityType() == EntityType.ENDER_SIGNAL) { + logger.info("Detected Ender Signal..."); + World w = BukkitAdapter.adapt(e.getEntity().getWorld()); + EnderSignal signal = (EnderSignal) entity; + ConfiguredStructure config = tw.getConfig().getRegistry(TerraStructure.class).get(w.getConfig().getLocatable().get + ("STRONGHOLD")); + if(config != null) { + logger.info("Overriding Ender Signal..."); + AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getLocation() + .toVector()), tw.getWorld(), 0, 500, location -> { + if(location != null) + signal.setTargetLocation(BukkitAdapter.adapt(location).toLocation(e.getLocation().getWorld())); + logger.info("Location: {}", location); + }, main); + finder.run(); // Do this synchronously so eye doesn't change direction several ticks after spawning. + } else + logger.warn("No overrides are defined for Strongholds. Ender Signals will not work correctly."); + } +*/ + } + + @EventHandler + public void onCartographerChange(VillagerAcquireTradeEvent e) { + if(!(e.getEntity() instanceof Villager)) + return; + if(((Villager) e.getEntity()).getProfession() == Villager.Profession.CARTOGRAPHER) { + logger.error(""" + .------------------------------------------------------------------------. + | Prevented server crash by stopping Cartographer villager from | + | spawning. Please upgrade to Paper, which has a StructureLocateEvent | + | that fixes this issue at the source, and doesn't require us to do | + | stupid band-aids. | + |------------------------------------------------------------------------| + """.strip()); + e.setCancelled(true); // Cancel leveling if the villager is a Cartographer, to prevent crashing server. + } + } + + @EventHandler + public void onCartographerLevel(VillagerCareerChangeEvent e) { + if(e.getProfession() == Villager.Profession.CARTOGRAPHER) { + logger.error(""" + .------------------------------------------------------------------------. + | Prevented server crash by stopping Cartographer villager from leveling | + | up. Please upgrade to Paper, which has a StructureLocateEvent that | + | fixes this issue at the source, and doesn't require us to do stupid | + | band-aids. | + |------------------------------------------------------------------------| + """.strip()); + e.getEntity().setProfession(Villager.Profession.NITWIT); // Give villager new profession to prevent server crash. + e.setCancelled(true); + } + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/nms/Initializer.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/nms/Initializer.java new file mode 100644 index 000000000..b86a37f89 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/nms/Initializer.java @@ -0,0 +1,43 @@ +package com.dfsek.terra.bukkit.nms; + +import com.dfsek.terra.bukkit.PlatformImpl; +import com.dfsek.terra.bukkit.TerraBukkitPlugin; + +import org.bukkit.Bukkit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.InvocationTargetException; + + +public interface Initializer { + String NMS = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + String TERRA_PACKAGE = Initializer.class.getPackageName(); + + void initialize(PlatformImpl plugin); + + static void init(PlatformImpl platform) { + Logger logger = LoggerFactory.getLogger(Initializer.class); + try { + Class initializerClass = Class.forName(TERRA_PACKAGE + "." + NMS + ".NMSInitializer"); + try { + Initializer initializer = (Initializer) initializerClass.getConstructor().newInstance(); + initializer.initialize(platform); + } catch(ReflectiveOperationException e) { + throw new RuntimeException("Error initializing NMS bindings. Report this to Terra.", e); + } + } catch(ClassNotFoundException e) { + logger.error("NMS bindings for version {} do not exist. Support for this version is limited.", NMS); + logger.error("This is usually due to running Terra on an unsupported Minecraft version."); + logger.error(""); + logger.error(""); + for(int i = 0; i < 20; i++) { + logger.error("PROCEEDING WITH AN EXISTING TERRA WORLD WILL RESULT IN CORRUPTION!!!"); + } + logger.error(""); + logger.error(""); + logger.error("NMS bindings for version {} do not exist. Support for this version is limited.", NMS); + logger.error("This is usually due to running Terra on an unsupported Minecraft version."); + } + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/MinecraftUtils.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/MinecraftUtils.java new file mode 100644 index 000000000..98da508b2 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/MinecraftUtils.java @@ -0,0 +1,25 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.util; + +public final class MinecraftUtils { + public static String stripMinecraftNamespace(String in) { + if(in.startsWith("minecraft:")) return in.substring("minecraft:".length()); + return in; + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/PaperUtil.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/PaperUtil.java new file mode 100644 index 000000000..d7b06b93d --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/PaperUtil.java @@ -0,0 +1,35 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.util; + +import io.papermc.lib.PaperLib; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +import static io.papermc.lib.PaperLib.suggestPaper; + + +public final class PaperUtil { + public static void checkPaper(JavaPlugin main) { + Bukkit.getScheduler().scheduleSyncDelayedTask(main, () -> { + if(!PaperLib.isPaper()) { + suggestPaper(main); + } + }, 100L); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/VersionUtil.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/VersionUtil.java new file mode 100644 index 000000000..08e9b4864 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/VersionUtil.java @@ -0,0 +1,132 @@ +package com.dfsek.terra.bukkit.util; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.version.Version; +import io.papermc.lib.PaperLib; +import org.bukkit.Bukkit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +public final class VersionUtil { + public static final SpigotVersionInfo SPIGOT_VERSION_INFO; + public static final MinecraftVersionInfo MINECRAFT_VERSION_INFO; + + private static final Logger logger = LoggerFactory.getLogger(VersionUtil.class); + + static { + SPIGOT_VERSION_INFO = new SpigotVersionInfo(); + + MinecraftVersionInfo mcVersionInfo; + try { + mcVersionInfo = new MinecraftVersionInfo(); + } catch(Throwable t) { + logger.error("Error while parsing minecraft version info. Continuing launch, but setting all versions to -1."); + mcVersionInfo = new MinecraftVersionInfo(-1, -1, -1); + } + MINECRAFT_VERSION_INFO = mcVersionInfo; + } + + public static MinecraftVersionInfo getMinecraftVersionInfo() { + return MINECRAFT_VERSION_INFO; + } + + public static SpigotVersionInfo getSpigotVersionInfo() { + return SPIGOT_VERSION_INFO; + } + + public static final class SpigotVersionInfo { + private final boolean spigot; + private final boolean paper; + private final boolean mohist; + + + public SpigotVersionInfo() { + logger.debug("Parsing spigot version info..."); + + paper = PaperLib.isPaper(); + spigot = PaperLib.isSpigot(); + + + boolean isMohist = false; + try { + Class.forName("com.mohistmc.MohistMC"); + // it's mohist + isMohist = true; + } catch(ClassNotFoundException ignore) { } + this.mohist = isMohist; + + logger.debug("Spigot version info parsed successfully."); + } + + public boolean isPaper() { + return paper; + } + + public boolean isMohist() { + return mohist; + } + + public boolean isSpigot() { + return spigot; + } + } + + + public static final class MinecraftVersionInfo { + private static final Logger logger = LoggerFactory.getLogger(MinecraftVersionInfo.class); + + private static final Pattern VERSION_PATTERN = Pattern.compile("v?(\\d+)_(\\d+)_R(\\d+)"); + private final int major; + private final int minor; + private final int patch; + + private MinecraftVersionInfo() { + this(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]); + } + + private MinecraftVersionInfo(int major, int minor, int patch) { + this.major = major; + this.minor = minor; + this.patch = patch; + } + + private MinecraftVersionInfo(String versionString) { + Matcher versionMatcher = VERSION_PATTERN.matcher(versionString); + if(versionMatcher.find()) { + major = Integer.parseInt(versionMatcher.group(1)); + minor = Integer.parseInt(versionMatcher.group(2)); + patch = Integer.parseInt(versionMatcher.group(3)); + } else { + logger.warn("Error while parsing minecraft version info. Continuing launch, but setting all versions to -1."); + + major = -1; + minor = -1; + patch = -1; + } + } + + @Override + public String toString() { + if(major == -1 && minor == -1 && patch == -1) + return "Unknown"; + + return String.format("v%d.%d.%d", major, minor, patch); + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + public int getPatch() { + return patch; + } + } +} \ No newline at end of file diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java new file mode 100644 index 000000000..e517129f2 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java @@ -0,0 +1,235 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.world; + + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.TreeType; +import org.bukkit.entity.Player; +import org.bukkit.generator.WorldInfo; +import org.bukkit.util.Vector; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.block.state.properties.enums.Axis; +import com.dfsek.terra.api.block.state.properties.enums.Half; +import com.dfsek.terra.api.block.state.properties.enums.RailShape; +import com.dfsek.terra.api.block.state.properties.enums.RedstoneConnection; +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.inventory.ItemStack; +import com.dfsek.terra.api.inventory.item.Enchantment; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.chunk.Chunk; +import com.dfsek.terra.api.world.info.WorldProperties; +import com.dfsek.terra.bukkit.BukkitCommandSender; +import com.dfsek.terra.bukkit.BukkitEntity; +import com.dfsek.terra.bukkit.BukkitPlayer; +import com.dfsek.terra.bukkit.world.block.BukkitBlockTypeAndItem; +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState; +import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack; +import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment; +import com.dfsek.terra.transform.MapTransform; +import com.dfsek.terra.transform.TransformerImpl; + + +/** + * Utility class to adapt Bukkit enums to Terra enums. + */ +public final class BukkitAdapter { + public static TransformerImpl TREE_TRANSFORMER = new TransformerImpl.Builder() + .addTransform(new MapTransform() + .add(TreeType.COCOA_TREE, "JUNGLE_COCOA") + .add(TreeType.BIG_TREE, "LARGE_OAK") + .add(TreeType.TALL_REDWOOD, "LARGE_SPRUCE") + .add(TreeType.REDWOOD, "SPRUCE") + .add(TreeType.TREE, "OAK") + .add(TreeType.MEGA_REDWOOD, "MEGA_SPRUCE") + .add(TreeType.SWAMP, "SWAMP_OAK")) + .addTransform(TreeType::toString) + .build(); + + + public static BlockState adapt(org.bukkit.block.data.BlockData data) { + return BukkitBlockState.newInstance(data); + } + + public static org.bukkit.block.data.BlockData adapt(BlockState data) { + return ((BukkitBlockState) data).getHandle(); + } + + public static Axis adapt(org.bukkit.Axis axis) { + return switch(axis) { + case X -> Axis.X; + case Y -> Axis.Y; + case Z -> Axis.Z; + }; + } + + public static WorldProperties adapt(WorldInfo worldInfo) { + return new BukkitWorldProperties(worldInfo); + } + + public static WorldInfo adapt(WorldProperties properties) { + return (WorldInfo) properties.getHandle(); + } + + public static Half adapt(org.bukkit.block.data.Bisected.Half half) { + return switch(half) { + case BOTTOM -> Half.BOTTOM; + case TOP -> Half.TOP; + }; + } + + public static RedstoneConnection adapt(org.bukkit.block.data.type.RedstoneWire.Connection connection) { + return switch(connection) { + case NONE -> RedstoneConnection.NONE; + case UP -> RedstoneConnection.UP; + case SIDE -> RedstoneConnection.SIDE; + }; + } + + public static org.bukkit.block.data.type.RedstoneWire.Connection adapt(RedstoneConnection connection) { + return switch(connection) { + case SIDE -> org.bukkit.block.data.type.RedstoneWire.Connection.SIDE; + case UP -> org.bukkit.block.data.type.RedstoneWire.Connection.UP; + case NONE -> org.bukkit.block.data.type.RedstoneWire.Connection.NONE; + }; + } + + public static RailShape adapt(org.bukkit.block.data.Rail.Shape shape) { + return switch(shape) { + case SOUTH_WEST -> RailShape.SOUTH_WEST; + case SOUTH_EAST -> RailShape.SOUTH_EAST; + case NORTH_EAST -> RailShape.NORTH_EAST; + case NORTH_WEST -> RailShape.NORTH_WEST; + case ASCENDING_EAST -> RailShape.ASCENDING_EAST; + case ASCENDING_WEST -> RailShape.ASCENDING_WEST; + case ASCENDING_SOUTH -> RailShape.ASCENDING_SOUTH; + case ASCENDING_NORTH -> RailShape.ASCENDING_NORTH; + case NORTH_SOUTH -> RailShape.NORTH_SOUTH; + case EAST_WEST -> RailShape.EAST_WEST; + }; + } + + public static org.bukkit.block.data.Rail.Shape adapt(RailShape shape) { + return switch(shape) { + case EAST_WEST -> org.bukkit.block.data.Rail.Shape.EAST_WEST; + case NORTH_SOUTH -> org.bukkit.block.data.Rail.Shape.NORTH_SOUTH; + case ASCENDING_NORTH -> org.bukkit.block.data.Rail.Shape.ASCENDING_NORTH; + case ASCENDING_SOUTH -> org.bukkit.block.data.Rail.Shape.ASCENDING_SOUTH; + case ASCENDING_WEST -> org.bukkit.block.data.Rail.Shape.ASCENDING_WEST; + case ASCENDING_EAST -> org.bukkit.block.data.Rail.Shape.ASCENDING_EAST; + case NORTH_WEST -> org.bukkit.block.data.Rail.Shape.NORTH_WEST; + case NORTH_EAST -> org.bukkit.block.data.Rail.Shape.NORTH_EAST; + case SOUTH_EAST -> org.bukkit.block.data.Rail.Shape.SOUTH_EAST; + case SOUTH_WEST -> org.bukkit.block.data.Rail.Shape.SOUTH_WEST; + }; + } + + + public static org.bukkit.block.data.Bisected.Half adapt(Half half) { + return switch(half) { + case TOP -> org.bukkit.block.data.Bisected.Half.TOP; + case BOTTOM -> org.bukkit.block.data.Bisected.Half.BOTTOM; + default -> throw new IllegalStateException(); + }; + } + + public static org.bukkit.Axis adapt(Axis axis) { + return switch(axis) { + case Z -> org.bukkit.Axis.Z; + case Y -> org.bukkit.Axis.Y; + case X -> org.bukkit.Axis.X; + }; + } + + public static Vector3 adapt(Location location) { + return Vector3.of(location.getX(), location.getY(), location.getZ()); + } + + public static Vector adapt(Vector3 vector3) { + return new Vector(vector3.getX(), vector3.getY(), vector3.getZ()); + } + + public static Vector3 adapt(Vector vector) { + return Vector3.of(vector.getX(), vector.getY(), vector.getZ()); + } + + public static CommandSender adapt(org.bukkit.command.CommandSender sender) { + return new BukkitCommandSender(sender); + } + + public static Entity adapt(org.bukkit.entity.Entity entity) { + return new BukkitEntity(entity); + } + + public static org.bukkit.command.CommandSender adapt(CommandSender sender) { + return ((BukkitCommandSender) sender).getHandle(); + } + + public static ServerWorld adapt(org.bukkit.World world) { + return new BukkitServerWorld(world); + } + + public static org.bukkit.World adapt(ServerWorld world) { + return (org.bukkit.World) world.getHandle(); + } + + public static Chunk adapt(org.bukkit.Chunk chunk) { + return new BukkitChunk(chunk); + } + + public static org.bukkit.Chunk adapt(Chunk chunk) { + return (org.bukkit.Chunk) chunk.getHandle(); + } + + public static Enchantment adapt(org.bukkit.enchantments.Enchantment enchantment) { + return new BukkitEnchantment(enchantment); + } + + public static org.bukkit.enchantments.Enchantment adapt(Enchantment enchantment) { + return ((BukkitEnchantment) enchantment).getHandle(); + } + + public static Player adapt(com.dfsek.terra.api.entity.Player player) { + return ((BukkitPlayer) player).getHandle(); + } + + public static com.dfsek.terra.api.entity.Player adapt(Player player) { + return new BukkitPlayer(player); + } + + public static BukkitBlockTypeAndItem adapt(Material material) { + return new BukkitBlockTypeAndItem(material); + } + + public static Material adapt(BlockType type) { + return ((BukkitBlockTypeAndItem) type).getHandle(); + } + + public static ItemStack adapt(org.bukkit.inventory.ItemStack in) { + return new BukkitItemStack(in); + } + + public static org.bukkit.inventory.ItemStack adapt(ItemStack in) { + return ((BukkitItemStack) in).getHandle(); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitChunk.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitChunk.java new file mode 100644 index 000000000..a7ce8c62b --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitChunk.java @@ -0,0 +1,68 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.world; + +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.chunk.Chunk; + + +public class BukkitChunk implements Chunk { + private final org.bukkit.Chunk delegate; + + public BukkitChunk(org.bukkit.Chunk delegate) { + this.delegate = delegate; + } + + @Override + public org.bukkit.Chunk getHandle() { + return delegate; + } + + @Override + public void setBlock(int x, int y, int z, BlockState data, boolean physics) { + delegate.getBlock(x, y, z).setBlockData(BukkitAdapter.adapt(data), physics); + } + + @Override + public void setBlock(int x, int y, int z, @NotNull BlockState blockState) { + delegate.getBlock(x, y, z).setBlockData(BukkitAdapter.adapt(blockState)); + } + + @Override + public @NotNull BlockState getBlock(int x, int y, int z) { + return BukkitAdapter.adapt(delegate.getBlock(x, y, z).getBlockData()); + } + + @Override + public int getX() { + return delegate.getX(); + } + + @Override + public int getZ() { + return delegate.getZ(); + } + + @Override + public ServerWorld getWorld() { + return BukkitAdapter.adapt(delegate.getWorld()); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitPlatformBiome.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitPlatformBiome.java new file mode 100644 index 000000000..aff5773fa --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitPlatformBiome.java @@ -0,0 +1,42 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.world; + +import com.dfsek.terra.api.properties.Context; +import com.dfsek.terra.api.properties.PropertyHolder; +import com.dfsek.terra.api.world.biome.PlatformBiome; + + +public class BukkitPlatformBiome implements PlatformBiome, PropertyHolder { + private final org.bukkit.block.Biome biome; + private final Context context = new Context(); + + public BukkitPlatformBiome(org.bukkit.block.Biome biome) { + this.biome = biome; + } + + @Override + public org.bukkit.block.Biome getHandle() { + return biome; + } + + @Override + public Context getContext() { + return context; + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java new file mode 100644 index 000000000..579fc4825 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java @@ -0,0 +1,140 @@ +package com.dfsek.terra.bukkit.world; + +import org.bukkit.Location; +import org.bukkit.generator.LimitedRegion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.bukkit.BukkitEntity; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState; +import com.dfsek.terra.bukkit.world.block.state.BukkitBlockEntity; +import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; + + +public class BukkitProtoWorld implements ProtoWorld { + private static final Logger LOGGER = LoggerFactory.getLogger(BukkitProtoWorld.class); + private static final AtomicBoolean warn = new AtomicBoolean(true); + private final LimitedRegion delegate; + private final BlockState air; + + public BukkitProtoWorld(LimitedRegion delegate, BlockState air) { + this.delegate = delegate; + this.air = air; + } + + @Override + public LimitedRegion getHandle() { + return delegate; + } + + @Override + public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { + access(x, y, z, () -> { + delegate.setBlockData(x, y, z, BukkitAdapter.adapt(data)); + if(physics) { + delegate.scheduleBlockUpdate(x, y, z); + } + }); + } + + @Override + public long getSeed() { + return delegate.getWorld().getSeed(); + } + + @Override + public int getMaxHeight() { + return delegate.getWorld().getMaxHeight(); + } + + @Override + public BlockState getBlockState(int x, int y, int z) { + return access(x, y, z, () -> BukkitBlockState.newInstance(delegate.getBlockData(x, y, z))).orElse(air); + } + + @Override + public BlockEntity getBlockEntity(int x, int y, int z) { + return access(x, y, z, () -> BukkitBlockEntity.newInstance(delegate.getBlockState(x, y, z))).orElse(null); + } + + @Override + public int getMinHeight() { + return delegate.getWorld().getMinHeight(); + } + + @Override + public Entity spawnEntity(double x, double y, double z, EntityType entityType) { + return access((int) x, (int) y, (int) z, () -> new BukkitEntity( + delegate.spawnEntity(new Location(delegate.getWorld(), x, y, z), ((BukkitEntityType) entityType).getHandle()))).orElse( + null); + } + + @Override + public ChunkGenerator getGenerator() { + return ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getHandle(); + } + + @Override + public BiomeProvider getBiomeProvider() { + return ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getPack().getBiomeProvider(); + } + + @Override + public ConfigPack getPack() { + return ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getPack(); + } + + @Override + public int centerChunkX() { + return delegate.getCenterChunkX(); + } + + @Override + public int centerChunkZ() { + return delegate.getCenterChunkZ(); + } + + @Override + public ServerWorld getWorld() { + return new BukkitServerWorld(delegate.getWorld()); + } + + private Optional access(int x, int y, int z, Supplier action) { + if(delegate.isInRegion(x, y, z)) { + return Optional.of(action.get()); + } else if(warn.getAndSet(false)) { + LOGGER.warn("Detected world access at coordinates out of bounds: ({}, {}, {}) accessed for region [{}, {}]", x, y, z, + delegate.getCenterChunkX(), delegate.getCenterChunkZ()); + } else { + LOGGER.debug("Detected world access at coordinates out of bounds: ({}, {}, {}) accessed for region [{}, {}]", x, y, z, + delegate.getCenterChunkX(), delegate.getCenterChunkZ()); + } + return Optional.empty(); + } + + private void access(int x, int y, int z, Runnable action) { + if(delegate.isInRegion(x, y, z)) { + action.run(); + } else if(warn.getAndSet(false)) { + LOGGER.warn("Detected world access at coordinates out of bounds: ({}, {}, {}) accessed for region [{}, {}]", x, y, z, + delegate.getCenterChunkX(), delegate.getCenterChunkZ()); + } else { + LOGGER.debug("Detected world access at coordinates out of bounds: ({}, {}, {}) accessed for region [{}, {}]", x, y, z, + delegate.getCenterChunkX(), delegate.getCenterChunkZ()); + } + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitServerWorld.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitServerWorld.java new file mode 100644 index 000000000..b7923ee26 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitServerWorld.java @@ -0,0 +1,120 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.world; + +import org.bukkit.Location; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.Chunk; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.bukkit.BukkitEntity; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; +import com.dfsek.terra.bukkit.world.block.state.BukkitBlockEntity; +import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; + + +public class BukkitServerWorld implements ServerWorld { + private final org.bukkit.World delegate; + + public BukkitServerWorld(org.bukkit.World delegate) { + this.delegate = delegate; + } + + @Override + public Entity spawnEntity(double x, double y, double z, EntityType entityType) { + return new BukkitEntity( + delegate.spawnEntity(new Location(delegate, x, y, z), ((BukkitEntityType) entityType).getHandle())); + } + + @Override + public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { + delegate.getBlockAt(x, y, z).setBlockData(BukkitAdapter.adapt(data), physics); + } + + @Override + public long getSeed() { + return delegate.getSeed(); + } + + @Override + public int getMaxHeight() { + return delegate.getMaxHeight(); + } + + @Override + public Chunk getChunkAt(int x, int z) { + return BukkitAdapter.adapt(delegate.getChunkAt(x, z)); + } + + @Override + public BlockState getBlockState(int x, int y, int z) { + return BukkitAdapter.adapt(delegate.getBlockAt(x, y, z).getBlockData()); + } + + @Override + public BlockEntity getBlockEntity(int x, int y, int z) { + return BukkitBlockEntity.newInstance(delegate.getBlockAt(x, y, z).getState()); + } + + @Override + public int getMinHeight() { + return delegate.getMinHeight(); + } + + @Override + public ChunkGenerator getGenerator() { + return ((BukkitChunkGeneratorWrapper) delegate.getGenerator()).getHandle(); + } + + @Override + public BiomeProvider getBiomeProvider() { + return ((BukkitChunkGeneratorWrapper) delegate.getGenerator()).getPack().getBiomeProvider(); + } + + @Override + public ConfigPack getPack() { + return ((BukkitChunkGeneratorWrapper) delegate.getGenerator()).getPack(); + } + + @Override + public org.bukkit.World getHandle() { + return delegate; + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof BukkitServerWorld other)) return false; + return other.getHandle().equals(delegate); + } + + @Override + public String toString() { + return delegate.toString(); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorldProperties.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorldProperties.java new file mode 100644 index 000000000..e324a62d7 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorldProperties.java @@ -0,0 +1,34 @@ +package com.dfsek.terra.bukkit.world; + +import org.bukkit.generator.WorldInfo; + +import com.dfsek.terra.api.world.info.WorldProperties; + + +public class BukkitWorldProperties implements WorldProperties { + private final WorldInfo delegate; + + public BukkitWorldProperties(WorldInfo delegate) { + this.delegate = delegate; + } + + @Override + public Object getHandle() { + return delegate; + } + + @Override + public long getSeed() { + return delegate.getSeed(); + } + + @Override + public int getMaxHeight() { + return delegate.getMaxHeight(); + } + + @Override + public int getMinHeight() { + return delegate.getMinHeight(); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlockTypeAndItem.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlockTypeAndItem.java similarity index 54% rename from platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlockTypeAndItem.java rename to platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlockTypeAndItem.java index 5b3e0767c..8c03645b0 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlockTypeAndItem.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlockTypeAndItem.java @@ -1,54 +1,73 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.bukkit.world.block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.bukkit.world.BukkitAdapter; import org.bukkit.Material; +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.ItemStack; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + + public class BukkitBlockTypeAndItem implements BlockType, Item { private final Material delegate; - + public BukkitBlockTypeAndItem(Material delegate) { this.delegate = delegate; } - + @Override public Material getHandle() { return delegate; } - + @Override - public BlockData getDefaultData() { + public BlockState getDefaultState() { return BukkitAdapter.adapt(delegate.createBlockData()); } - + @Override public boolean isSolid() { - return delegate.isSolid(); + return delegate.isOccluding(); } - + @Override public boolean isWater() { return delegate == Material.WATER; } - + @Override public ItemStack newItemStack(int amount) { return BukkitAdapter.adapt(new org.bukkit.inventory.ItemStack(delegate, amount)); } - + @Override public double getMaxDurability() { return delegate.getMaxDurability(); } - + @Override public int hashCode() { return delegate.hashCode(); } - + @Override public boolean equals(Object obj) { if(!(obj instanceof BukkitBlockTypeAndItem)) return false; diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java new file mode 100644 index 000000000..f670d4f03 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java @@ -0,0 +1,77 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.world.block.data; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.block.state.properties.Property; +import com.dfsek.terra.bukkit.world.BukkitAdapter; + + +public class BukkitBlockState implements BlockState { + private org.bukkit.block.data.BlockData delegate; + + protected BukkitBlockState(org.bukkit.block.data.BlockData delegate) { + this.delegate = delegate; + } + + public static BlockState newInstance(org.bukkit.block.data.BlockData bukkitData) { + return new BukkitBlockState(bukkitData); + } + + + @Override + public org.bukkit.block.data.BlockData getHandle() { + return delegate; + } + + @Override + public boolean matches(BlockState data) { + return delegate.getMaterial() == ((BukkitBlockState) data).getHandle().getMaterial(); + } + + @Override + public > boolean has(Property property) { + return false; + } + + @Override + public > T get(Property property) { + return null; + } + + @Override + public > BlockState set(Property property, T value) { + return null; + } + + @Override + public BlockType getBlockType() { + return BukkitAdapter.adapt(delegate.getMaterial()); + } + + @Override + public String getAsString(boolean properties) { + return delegate.getAsString(!properties); + } + + @Override + public boolean isAir() { + return delegate.getMaterial().isAir(); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitBlockEntity.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitBlockEntity.java new file mode 100644 index 000000000..57bb052e2 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitBlockEntity.java @@ -0,0 +1,79 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.world.block.state; + +import org.bukkit.block.Container; +import org.bukkit.block.CreatureSpawner; +import org.bukkit.block.Sign; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState; + + +public class BukkitBlockEntity implements BlockEntity { + private final org.bukkit.block.BlockState delegate; + + protected BukkitBlockEntity(org.bukkit.block.BlockState block) { + this.delegate = block; + } + + public static BukkitBlockEntity newInstance(org.bukkit.block.BlockState block) { + if(block instanceof Container) return new BukkitContainer((Container) block); + if(block instanceof Sign) return new BukkitSign((Sign) block); + if(block instanceof CreatureSpawner) return new BukkitMobSpawner((CreatureSpawner) block); + return new BukkitBlockEntity(block); + } + + @Override + public org.bukkit.block.BlockState getHandle() { + return delegate; + } + + @Override + public boolean update(boolean applyPhysics) { + return delegate.update(true, applyPhysics); + } + + @Override + public Vector3 getPosition() { + return BukkitAdapter.adapt(delegate.getBlock().getLocation().toVector()); + } + + @Override + public int getX() { + return delegate.getX(); + } + + @Override + public int getY() { + return delegate.getY(); + } + + @Override + public int getZ() { + return delegate.getZ(); + } + + @Override + public BlockState getBlockState() { + return BukkitBlockState.newInstance(delegate.getBlockData()); + } +} diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java new file mode 100644 index 000000000..ecde57209 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java @@ -0,0 +1,40 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.world.block.state; + +import com.dfsek.terra.api.block.entity.Container; +import com.dfsek.terra.api.inventory.Inventory; +import com.dfsek.terra.bukkit.world.inventory.BukkitInventory; + + +public class BukkitContainer extends BukkitBlockEntity implements Container { + + protected BukkitContainer(org.bukkit.block.Container block) { + super(block); + } + + @Override + public Inventory getInventory() { + return new BukkitInventory(((org.bukkit.block.Container) getHandle()).getInventory()); + } + + @Override + public boolean update(boolean applyPhysics) { + return false; // This clears the inventory. we don't want that. + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java similarity index 60% rename from platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java rename to platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java index 526d1481d..71485ea13 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java @@ -1,127 +1,129 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.bukkit.world.block.state; -import com.dfsek.terra.api.platform.block.state.MobSpawner; -import com.dfsek.terra.api.platform.block.state.SerialState; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; import org.bukkit.block.CreatureSpawner; import org.jetbrains.annotations.NotNull; -public class BukkitMobSpawner extends BukkitBlockState implements MobSpawner { +import com.dfsek.terra.api.block.entity.MobSpawner; +import com.dfsek.terra.api.block.entity.SerialState; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; + + +public class BukkitMobSpawner extends BukkitBlockEntity implements MobSpawner { protected BukkitMobSpawner(CreatureSpawner block) { super(block); } - + @Override public EntityType getSpawnedType() { return new BukkitEntityType(((CreatureSpawner) getHandle()).getSpawnedType()); } - + @Override public void setSpawnedType(@NotNull EntityType creatureType) { ((CreatureSpawner) getHandle()).setSpawnedType(((BukkitEntityType) creatureType).getHandle()); } - + @Override public int getDelay() { return ((CreatureSpawner) getHandle()).getDelay(); } - + @Override public void setDelay(int delay) { ((CreatureSpawner) getHandle()).setDelay(delay); } - + @Override public int getMinSpawnDelay() { return ((CreatureSpawner) getHandle()).getMinSpawnDelay(); } - + @Override public void setMinSpawnDelay(int delay) { ((CreatureSpawner) getHandle()).setMinSpawnDelay(delay); } - + @Override public int getMaxSpawnDelay() { return ((CreatureSpawner) getHandle()).getMaxSpawnDelay(); } - + @Override public void setMaxSpawnDelay(int delay) { ((CreatureSpawner) getHandle()).setMaxSpawnDelay(delay); } - + @Override public int getSpawnCount() { return ((CreatureSpawner) getHandle()).getSpawnCount(); } - + @Override public void setSpawnCount(int spawnCount) { ((CreatureSpawner) getHandle()).setSpawnCount(spawnCount); } - + @Override public int getMaxNearbyEntities() { return ((CreatureSpawner) getHandle()).getMaxNearbyEntities(); } - + @Override public void setMaxNearbyEntities(int maxNearbyEntities) { ((CreatureSpawner) getHandle()).setMaxNearbyEntities(maxNearbyEntities); } - + @Override public int getRequiredPlayerRange() { return ((CreatureSpawner) getHandle()).getRequiredPlayerRange(); } - + @Override public void setRequiredPlayerRange(int requiredPlayerRange) { ((CreatureSpawner) getHandle()).setRequiredPlayerRange(requiredPlayerRange); } - + @Override public int getSpawnRange() { return ((CreatureSpawner) getHandle()).getSpawnRange(); } - + @Override public void setSpawnRange(int spawnRange) { ((CreatureSpawner) getHandle()).setSpawnRange(spawnRange); } - + @Override public void applyState(String state) { SerialState.parse(state).forEach((k, v) -> { switch(k) { - case "type": - setSpawnedType(new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(v.toUpperCase()))); - return; - case "delay": - setDelay(Integer.parseInt(v)); - return; - case "min_delay": - setMinSpawnDelay(Integer.parseInt(v)); - return; - case "max_delay": - setMaxSpawnDelay(Integer.parseInt(v)); - return; - case "spawn_count": - setSpawnCount(Integer.parseInt(v)); - return; - case "spawn_range": - setSpawnRange(Integer.parseInt(v)); - return; - case "max_nearby": - setMaxNearbyEntities(Integer.parseInt(v)); - return; - case "required_player_range": - setRequiredPlayerRange(Integer.parseInt(v)); - return; - default: - throw new IllegalArgumentException("Invalid property: " + k); + case "type" -> setSpawnedType(new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(v.toUpperCase()))); + case "delay" -> setDelay(Integer.parseInt(v)); + case "min_delay" -> setMinSpawnDelay(Integer.parseInt(v)); + case "max_delay" -> setMaxSpawnDelay(Integer.parseInt(v)); + case "spawn_count" -> setSpawnCount(Integer.parseInt(v)); + case "spawn_range" -> setSpawnRange(Integer.parseInt(v)); + case "max_nearby" -> setMaxNearbyEntities(Integer.parseInt(v)); + case "required_player_range" -> setRequiredPlayerRange(Integer.parseInt(v)); + default -> throw new IllegalArgumentException("Invalid property: " + k); } }); } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java similarity index 53% rename from platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java rename to platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java index 05625cc1a..65c6f303f 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitSign.java @@ -1,30 +1,49 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.bukkit.world.block.state; -import com.dfsek.terra.api.platform.block.state.SerialState; -import com.dfsek.terra.api.platform.block.state.Sign; import org.jetbrains.annotations.NotNull; +import com.dfsek.terra.api.block.entity.SerialState; +import com.dfsek.terra.api.block.entity.Sign; + + @SuppressWarnings("deprecation") -public class BukkitSign extends BukkitBlockState implements Sign { +public class BukkitSign extends BukkitBlockEntity implements Sign { protected BukkitSign(org.bukkit.block.Sign block) { super(block); } - - @Override - public @NotNull String[] getLines() { - return ((org.bukkit.block.Sign) getHandle()).getLines(); - } - - @Override - public @NotNull String getLine(int index) throws IndexOutOfBoundsException { - return ((org.bukkit.block.Sign) getHandle()).getLine(index); - } - + @Override public void setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { ((org.bukkit.block.Sign) getHandle()).setLine(index, line); } - + + @Override + public @NotNull String[] getLines() { + return ((org.bukkit.block.Sign) getHandle()).getLines(); + } + + @Override + public @NotNull String getLine(int index) throws IndexOutOfBoundsException { + return ((org.bukkit.block.Sign) getHandle()).getLine(index); + } + @Override public void applyState(String state) { SerialState.parse(state).forEach((k, v) -> { diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/entity/BukkitEntityType.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/entity/BukkitEntityType.java new file mode 100644 index 000000000..8f8786867 --- /dev/null +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/entity/BukkitEntityType.java @@ -0,0 +1,34 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.bukkit.world.entity; + +import com.dfsek.terra.api.entity.EntityType; + + +public class BukkitEntityType implements EntityType { + private final org.bukkit.entity.EntityType delegate; + + public BukkitEntityType(org.bukkit.entity.EntityType delegate) { + this.delegate = delegate; + } + + @Override + public org.bukkit.entity.EntityType getHandle() { + return delegate; + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitInventory.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitInventory.java similarity index 51% rename from platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitInventory.java rename to platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitInventory.java index f567bff01..d4c5039b5 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitInventory.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitInventory.java @@ -1,31 +1,49 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.bukkit.world.inventory; -import com.dfsek.terra.api.platform.inventory.Inventory; -import com.dfsek.terra.api.platform.inventory.ItemStack; +import com.dfsek.terra.api.inventory.Inventory; +import com.dfsek.terra.api.inventory.ItemStack; + public class BukkitInventory implements Inventory { private final org.bukkit.inventory.Inventory delegate; - + public BukkitInventory(org.bukkit.inventory.Inventory delegate) { this.delegate = delegate; } - + + @Override + public void setItem(int slot, ItemStack newStack) { + delegate.setItem(slot, ((BukkitItemStack) newStack).getHandle()); + } + @Override public int getSize() { return delegate.getSize(); } - + @Override public ItemStack getItem(int slot) { org.bukkit.inventory.ItemStack itemStack = delegate.getItem(slot); return itemStack == null ? null : new BukkitItemStack(itemStack); } - - @Override - public void setItem(int slot, ItemStack newStack) { - delegate.setItem(slot, ((BukkitItemStack) newStack).getHandle()); - } - + @Override public org.bukkit.inventory.Inventory getHandle() { return delegate; diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemMeta.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemMeta.java similarity index 63% rename from platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemMeta.java rename to platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemMeta.java index a8bc30131..3aaa8a382 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemMeta.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemMeta.java @@ -1,41 +1,60 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.bukkit.world.inventory; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.bukkit.world.inventory.meta.BukkitDamageable; -import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment; import org.bukkit.inventory.meta.Damageable; import java.util.HashMap; import java.util.Map; +import com.dfsek.terra.api.inventory.item.Enchantment; +import com.dfsek.terra.api.inventory.item.ItemMeta; +import com.dfsek.terra.bukkit.world.BukkitAdapter; +import com.dfsek.terra.bukkit.world.inventory.meta.BukkitDamageable; +import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment; + + public class BukkitItemMeta implements ItemMeta { private final org.bukkit.inventory.meta.ItemMeta delegate; - + protected BukkitItemMeta(org.bukkit.inventory.meta.ItemMeta delegate) { this.delegate = delegate; } - + public static BukkitItemMeta newInstance(org.bukkit.inventory.meta.ItemMeta delegate) { if(delegate instanceof Damageable) return new BukkitDamageable((Damageable) delegate); return new BukkitItemMeta(delegate); } - + @Override public org.bukkit.inventory.meta.ItemMeta getHandle() { return delegate; } - + + @Override + public void addEnchantment(Enchantment enchantment, int level) { + delegate.addEnchant(((BukkitEnchantment) enchantment).getHandle(), level, true); + } + @Override public Map getEnchantments() { Map map = new HashMap<>(); delegate.getEnchants().forEach((enchantment, integer) -> map.put(BukkitAdapter.adapt(enchantment), integer)); return map; } - - @Override - public void addEnchantment(Enchantment enchantment, int level) { - delegate.addEnchant(((BukkitEnchantment) enchantment).getHandle(), level, true); - } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java similarity index 53% rename from platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java rename to platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java index b42f7319d..a3a9557cd 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/BukkitItemStack.java @@ -1,42 +1,60 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.bukkit.world.inventory; -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.ItemStack; +import com.dfsek.terra.api.inventory.item.ItemMeta; import com.dfsek.terra.bukkit.world.BukkitAdapter; + public class BukkitItemStack implements ItemStack { private final org.bukkit.inventory.ItemStack delegate; - + public BukkitItemStack(org.bukkit.inventory.ItemStack delegate) { this.delegate = delegate; } - + @Override public int getAmount() { return delegate.getAmount(); } - + @Override public void setAmount(int i) { delegate.setAmount(i); } - + @Override public Item getType() { return BukkitAdapter.adapt(delegate.getType()); } - + @Override public ItemMeta getItemMeta() { return BukkitItemMeta.newInstance(delegate.getItemMeta()); } - + @Override public void setItemMeta(ItemMeta meta) { delegate.setItemMeta(((BukkitItemMeta) meta).getHandle()); } - + @Override public org.bukkit.inventory.ItemStack getHandle() { return delegate; diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java similarity index 50% rename from platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java rename to platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java index 0c2ba018f..09e2e167b 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitDamageable.java @@ -1,24 +1,43 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.bukkit.world.inventory.meta; -import com.dfsek.terra.api.platform.inventory.item.Damageable; -import com.dfsek.terra.bukkit.world.inventory.BukkitItemMeta; import org.bukkit.inventory.meta.ItemMeta; +import com.dfsek.terra.api.inventory.item.Damageable; +import com.dfsek.terra.bukkit.world.inventory.BukkitItemMeta; + + public class BukkitDamageable extends BukkitItemMeta implements Damageable { public BukkitDamageable(org.bukkit.inventory.meta.Damageable delegate) { super((ItemMeta) delegate); } - + @Override public int getDamage() { return ((org.bukkit.inventory.meta.Damageable) getHandle()).getDamage(); } - + @Override public void setDamage(int damage) { ((org.bukkit.inventory.meta.Damageable) getHandle()).setDamage(damage); } - + @Override public boolean hasDamage() { return ((org.bukkit.inventory.meta.Damageable) getHandle()).hasDamage(); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitEnchantment.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitEnchantment.java similarity index 54% rename from platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitEnchantment.java rename to platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitEnchantment.java index 577414c28..13fc3b690 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitEnchantment.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/inventory/meta/BukkitEnchantment.java @@ -1,36 +1,54 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.bukkit.world.inventory.meta; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; +import com.dfsek.terra.api.inventory.ItemStack; +import com.dfsek.terra.api.inventory.item.Enchantment; import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack; + public class BukkitEnchantment implements Enchantment { private final org.bukkit.enchantments.Enchantment delegate; - + public BukkitEnchantment(org.bukkit.enchantments.Enchantment delegate) { this.delegate = delegate; } - + @Override public org.bukkit.enchantments.Enchantment getHandle() { return delegate; } - + @Override public boolean canEnchantItem(ItemStack itemStack) { return delegate.canEnchantItem(((BukkitItemStack) itemStack).getHandle()); } - - @Override - public String getID() { - return delegate.getKey().toString(); - } - + @Override public boolean conflictsWith(Enchantment other) { return delegate.conflictsWith(((BukkitEnchantment) other).getHandle()); } - + + @Override + public String getID() { + return delegate.getKey().toString(); + } + @Override public int getMaxLevel() { return delegate.getMaxLevel(); diff --git a/platforms/bukkit/src/main/resources/plugin.yml b/platforms/bukkit/common/src/main/resources/plugin.yml similarity index 53% rename from platforms/bukkit/src/main/resources/plugin.yml rename to platforms/bukkit/common/src/main/resources/plugin.yml index 1daeb981f..15f937a48 100644 --- a/platforms/bukkit/src/main/resources/plugin.yml +++ b/platforms/bukkit/common/src/main/resources/plugin.yml @@ -6,10 +6,3 @@ author: dfsek website: "@WIKI@" api-version: "1.13" description: "@DESCRIPTION@" -softdepend: [ "WorldEdit" ] -commands: - terra: - description: "Terra base command" - usage: "/terra " - aliases: [ "te" ] - permission: "terra.command" \ No newline at end of file diff --git a/platforms/bukkit/nms/v1_18_R2/build.gradle.kts b/platforms/bukkit/nms/v1_18_R2/build.gradle.kts new file mode 100644 index 000000000..f3cb6a90a --- /dev/null +++ b/platforms/bukkit/nms/v1_18_R2/build.gradle.kts @@ -0,0 +1,6 @@ +dependencies { + api(project(":platforms:bukkit:common")) + + compileOnly("io.papermc.paper:paper-api:1.18.2-R0.1-20220519.005047-123") + compileOnly(group = "org.spigotmc", name = "spigot", version = "1.18.2-R0.1-SNAPSHOT") +} \ No newline at end of file diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInfo.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInfo.java new file mode 100644 index 000000000..2cba0bfe2 --- /dev/null +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInfo.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.bukkit.nms.v1_18_R2; + +import com.dfsek.terra.api.properties.Properties; + +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.biome.BiomeBase; + + +public record NMSBiomeInfo(ResourceKey biomeKey) implements Properties { +} diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java new file mode 100644 index 000000000..cbd8ab74b --- /dev/null +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeInjector.java @@ -0,0 +1,188 @@ +package com.dfsek.terra.bukkit.nms.v1_18_R2; + +import com.google.common.collect.ImmutableMap; +import com.mojang.serialization.Lifecycle; +import net.minecraft.core.Holder; +import net.minecraft.core.IRegistry; +import net.minecraft.core.IRegistryWritable; +import net.minecraft.core.RegistryMaterials; +import net.minecraft.data.RegistryGeneration; +import net.minecraft.resources.MinecraftKey; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.biome.BiomeBase; +import net.minecraft.world.level.biome.BiomeFog; +import net.minecraft.world.level.biome.BiomeFog.GrassColor; +import net.minecraft.world.level.biome.BiomeSettingsGeneration; +import net.minecraft.world.level.biome.BiomeSettingsMobs; +import org.bukkit.NamespacedKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.bukkit.config.VanillaBiomeProperties; +import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; +import com.dfsek.terra.registry.master.ConfigRegistry; + + +public class NMSBiomeInjector { + private static final Logger LOGGER = LoggerFactory.getLogger(NMSBiomeInjector.class); + private static final Map> terraBiomeMap = new HashMap<>(); + + + public static void registerBiomes(ConfigRegistry configRegistry) { + try { + LOGGER.info("Hacking biome registry..."); + IRegistryWritable biomeRegistry = (IRegistryWritable) Registries.biomeRegistry(); + Field frozen = RegistryMaterials.class.getDeclaredField("bL"); // registry frozen field + frozen.setAccessible(true); + frozen.set(biomeRegistry, false); + + configRegistry.forEach(pack -> pack.getRegistry(Biome.class).forEach((key, biome) -> { + try { + BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome(); + NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey(); + MinecraftKey vanillaMinecraftKey = new MinecraftKey(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey()); + BiomeBase platform = createBiome( + biome, + biomeRegistry.a(vanillaMinecraftKey) // get + ); + + ResourceKey delegateKey = ResourceKey.a(IRegistry.aP, new MinecraftKey("terra", createBiomeID(pack, key))); + + RegistryGeneration.a(RegistryGeneration.i, delegateKey, platform); + biomeRegistry.a(delegateKey, platform, Lifecycle.stable()); + platformBiome.getContext().put(new NMSBiomeInfo(delegateKey)); + + terraBiomeMap.computeIfAbsent(vanillaMinecraftKey, i -> new ArrayList<>()).add(delegateKey.a()); + + LOGGER.debug("Registered biome: " + delegateKey); + } catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + throw new RuntimeException(e); + } + })); + + frozen.set(biomeRegistry, true); // freeze registry again :) + + LOGGER.info("Doing tag garbage...."); + Map, List>> collect = biomeRegistry + .g() // streamKeysAndEntries + .collect(HashMap::new, + (map, pair) -> + map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().a().toList())), + HashMap::putAll); + + terraBiomeMap + .forEach((vb, terraBiomes) -> + getEntry(biomeRegistry, vb) + .ifPresentOrElse( + vanilla -> terraBiomes + .forEach(tb -> getEntry(biomeRegistry, tb) + .ifPresentOrElse( + terra -> { + LOGGER.debug(vanilla.e().orElseThrow().a() + + " (vanilla for " + + terra.e().orElseThrow().a() + + ": " + + vanilla.c().toList()); + + vanilla.c() + .forEach( + tag -> collect + .computeIfAbsent(tag, + t -> new ArrayList<>()) + .add(terra)); + }, + () -> LOGGER.error( + "No such biome: {}", + tb))), + () -> LOGGER.error("No vanilla biome: {}", vb))); + + biomeRegistry.k(); // clearTags + biomeRegistry.a(ImmutableMap.copyOf(collect)); // populateTags + + } catch(NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException exception) { + throw new RuntimeException(exception); + } + } + + public static Optional> getEntry(IRegistry registry, MinecraftKey identifier) { + return registry.b(identifier) + .flatMap(registry::c) + .map(registry::c); + } + + private static BiomeBase createBiome(Biome biome, BiomeBase vanilla) + throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + BiomeBase.a builder = new BiomeBase.a(); // Builder + + Field f = BiomeBase.class.getDeclaredField("l"); // category + f.setAccessible(true); + builder.a((BiomeBase.Geography) f.get(vanilla)) + .a(vanilla.c()); // getPrecipitation + + + Field biomeSettingMobsField = BiomeBase.class.getDeclaredField("k"); // spawn settings + biomeSettingMobsField.setAccessible(true); + BiomeSettingsMobs biomeSettingMobs = (BiomeSettingsMobs) biomeSettingMobsField.get(vanilla); + builder.a(biomeSettingMobs); + + + BiomeSettingsGeneration.a generationBuilder = new BiomeSettingsGeneration.a(); // builder + builder.a(generationBuilder.a()) + .a(vanilla.c()) + .b(vanilla.h()) // precipitation + .a(vanilla.i()); // temp + + + BiomeFog.a effects = new BiomeFog.a(); // Builder + effects.a(GrassColor.a); // magic + + VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); + + // fog + effects.a(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.f())); + + // water + effects.b(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.k())); + + // water fog + effects.c(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.l())); + + // sky + effects.d(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.a())); + + if(vanillaBiomeProperties.getFoliageColor() == null) { + vanilla.j().e().ifPresent(effects::e); + } else { + // foliage + effects.e(vanillaBiomeProperties.getFoliageColor()); + } + + if(vanillaBiomeProperties.getGrassColor() == null) { + vanilla.j().f().ifPresent(effects::f); + } else { + // grass + effects.f(vanillaBiomeProperties.getGrassColor()); + } + + builder.a(effects.a()); // build() + + return builder.a(); // build() + } + + public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) { + return pack.getID() + .toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT); + } +} diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeProvider.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeProvider.java new file mode 100644 index 000000000..c4fc62749 --- /dev/null +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSBiomeProvider.java @@ -0,0 +1,54 @@ +package com.dfsek.terra.bukkit.nms.v1_18_R2; + +import com.mojang.serialization.Codec; +import net.minecraft.core.Holder; +import net.minecraft.core.IRegistry; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.world.level.biome.BiomeBase; +import net.minecraft.world.level.biome.Climate.Sampler; +import net.minecraft.world.level.biome.WorldChunkManager; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_18_R2.CraftServer; + +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.bukkit.world.BukkitPlatformBiome; + + +public class NMSBiomeProvider extends WorldChunkManager { + private final BiomeProvider delegate; + private final WorldChunkManager vanilla; + private final long seed; + + private static final Lazy> biomeRegistry = Lazy.lazy(() -> { + DedicatedServer dedicatedserver = ((CraftServer) Bukkit.getServer()).getServer(); + return dedicatedserver.aU().b(IRegistry.aP); + }); + + public NMSBiomeProvider(BiomeProvider delegate, WorldChunkManager vanilla, long seed) { + super(delegate.stream().map(biome -> biomeRegistry.value().g(((BukkitPlatformBiome) biome.getPlatformBiome()).getContext().get(NMSBiomeInfo.class).biomeKey()))); + this.delegate = delegate; + this.vanilla = vanilla; + this.seed = seed; + } + + @Override + protected Codec a() { + return WorldChunkManager.a; + } + + @Override + public WorldChunkManager a(long seed) { + return withSeed(seed); + } + + public WorldChunkManager withSeed(long seed) { + return new NMSBiomeProvider(delegate, vanilla, seed); + } + + @Override + public Holder getNoiseBiome(int x, int y, int z, Sampler sampler) { + //return CraftBlock.biomeToBiomeBase(biomeRegistry.value(), ((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed).getPlatformBiome()).getHandle()); + return biomeRegistry.value().g(((BukkitPlatformBiome) delegate.getBiome(x << 2, y << 2, z << 2, seed).getPlatformBiome()).getContext().get(NMSBiomeInfo.class).biomeKey()); + } +} diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java new file mode 100644 index 000000000..fc68790e3 --- /dev/null +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSChunkGeneratorDelegate.java @@ -0,0 +1,239 @@ +package com.dfsek.terra.bukkit.nms.v1_18_R2; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.info.WorldProperties; + +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Codec; +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; +import net.minecraft.core.BlockPosition; +import net.minecraft.core.Holder; +import net.minecraft.core.IRegistryCustom; +import net.minecraft.core.SectionPosition; +import net.minecraft.server.level.RegionLimitedWorldAccess; +import net.minecraft.world.level.BlockColumn; +import net.minecraft.world.level.ChunkCoordIntPair; +import net.minecraft.world.level.LevelHeightAccessor; +import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.biome.BiomeBase; +import net.minecraft.world.level.biome.BiomeManager; +import net.minecraft.world.level.biome.Climate; +import net.minecraft.world.level.biome.Climate.Sampler; +import net.minecraft.world.level.block.state.IBlockData; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.chunk.IChunkAccess; +import net.minecraft.world.level.levelgen.ChunkGeneratorAbstract; +import net.minecraft.world.level.levelgen.HeightMap; +import net.minecraft.world.level.levelgen.WorldGenStage; +import net.minecraft.world.level.levelgen.blending.Blender; +import net.minecraft.world.level.levelgen.structure.StructureSet; +import net.minecraft.world.level.levelgen.structure.placement.ConcentricRingsStructurePlacement; +import net.minecraft.world.level.levelgen.structure.placement.StructurePlacement; +import net.minecraft.world.level.levelgen.structure.templatesystem.DefinedStructureManager; +import org.bukkit.craftbukkit.v1_18_R2.block.data.CraftBlockData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.stream.Collectors; + + +public class NMSChunkGeneratorDelegate extends ChunkGenerator { + private static final Logger LOGGER = LoggerFactory.getLogger(NMSChunkGeneratorDelegate.class); + private final NMSBiomeProvider biomeSource; + private final com.dfsek.terra.api.world.chunk.generation.ChunkGenerator delegate; + + private final ChunkGenerator vanilla; + private final ConfigPack pack; + + private final long seed; + + private final Map>> h = new Object2ObjectArrayMap<>(); + + + + public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBiomeProvider biomeProvider, long seed) { + super(Registries.structureSet(), Optional.empty(), biomeProvider, biomeProvider, seed); + this.delegate = pack.getGeneratorProvider().newInstance(pack); + this.vanilla = vanilla; + this.biomeSource = biomeProvider; + this.pack = pack; + this.seed = seed; + } + + @Override //applyCarvers + public void a(RegionLimitedWorldAccess regionlimitedworldaccess, long var2, BiomeManager var4, StructureManager var5, + IChunkAccess ichunkaccess, WorldGenStage.Features var7) { + // no-op + } + + @Override // getSeaLevel + public int g() { + return vanilla.g(); + } + + @Override //fillFromNoise + public CompletableFuture a(Executor executor, Blender blender, StructureManager structuremanager, + IChunkAccess ichunkaccess) { + return vanilla.a(executor, blender, structuremanager, ichunkaccess); + } + + + @Override //buildSurface. Used to be buildBase + public void a(RegionLimitedWorldAccess regionlimitedworldaccess, StructureManager structuremanager, IChunkAccess ichunkaccess) { + + } + + @Override + protected Codec b() { + return ChunkGeneratorAbstract.a; + } + + @Override // getColumn + public BlockColumn a(int x, int z, LevelHeightAccessor height) { + IBlockData[] array = new IBlockData[height.v_()]; + WorldProperties properties = new NMSWorldProperties(seed, height); + BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); + for(int y = properties.getMaxHeight() - 1; y >= properties.getMinHeight(); y--) { + array[y - properties.getMinHeight()] = ((CraftBlockData) delegate.getBlock(properties, x, y, z, biomeProvider) + .getHandle()).getState(); + } + return new BlockColumn(getMinimumY(), array); + } + + @Override // withSeed + public ChunkGenerator a(long seed) { + return new NMSChunkGeneratorDelegate(vanilla, pack, biomeSource, seed); + } + + //spawnOriginalMobs + public void a(RegionLimitedWorldAccess regionlimitedworldaccess) { + vanilla.a(regionlimitedworldaccess); + } + + // getGenDepth + public int f() { + return vanilla.f(); + } + + // climateSampler + public Sampler d() { + return Climate.a(); + } + + //getMinY + @Override + public int h() { + return vanilla.h(); + } + + @Override // getBaseHeight + public int a(int x, int z, HeightMap.Type heightmap, LevelHeightAccessor height) { + WorldProperties properties = new NMSWorldProperties(seed, height); + int y = properties.getMaxHeight(); + BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); + while(y >= getMinimumY() && !heightmap.e().test( + ((CraftBlockData) delegate.getBlock(properties, x, y - 1, z, biomeProvider).getHandle()).getState())) { + y--; + } + return y; + } + + @Override + public void a(IRegistryCustom iregistrycustom, StructureManager structuremanager, IChunkAccess ichunkaccess, + DefinedStructureManager definedstructuremanager, long i) { + super.a(iregistrycustom, structuremanager, ichunkaccess, definedstructuremanager, i); + } + + @Nullable + @Override + public List a(ConcentricRingsStructurePlacement concentricringsstructureplacement) { + this.i(); + return this.h.get(concentricringsstructureplacement).value(); + } + + private volatile boolean rings = false; + + @Override + public synchronized void i() { + if(!this.rings) { + super.i(); + this.populateStrongholdData(); + this.rings = true; + } + } + + private void populateStrongholdData() { + LOGGER.info("Generating safe stronghold data. This may take up to a minute."); + Set> set = this.d.b(); + a().map(h -> h.a()).forEach((holder) -> { // we dont need the spigot crap because it doesnt touch concentric. + StructurePlacement structureplacement = holder.b(); + if(structureplacement instanceof ConcentricRingsStructurePlacement concentricringsstructureplacement) { + if(holder.a().stream().anyMatch((structureset_a1) -> structureset_a1.a(set::contains))) { + this.h.put(concentricringsstructureplacement, + Lazy.lazy(() -> this.generateRingPositions(holder, concentricringsstructureplacement))); + } + } + }); + } + + private List generateRingPositions(StructureSet holder, + ConcentricRingsStructurePlacement concentricringsstructureplacement) { + if(concentricringsstructureplacement.d() == 0) { + return List.of(); + } + List list = new ArrayList<>(); + Set> set = holder.a().stream().flatMap((structureset_a) -> (structureset_a.a().a()).a().a()).collect( + Collectors.toSet()); + int i = concentricringsstructureplacement.b(); + int j = concentricringsstructureplacement.d(); + int k = concentricringsstructureplacement.c(); + Random random = new Random(); + random.setSeed(this.j); + double d0 = random.nextDouble() * Math.PI * 2.0; + int l = 0; + int i1 = 0; + + for(int j1 = 0; j1 < j; ++j1) { + double d1 = (double) (4 * i + i * i1 * 6) + (random.nextDouble() - 0.5) * (double) i * 2.5; + int k1 = (int) Math.round(Math.cos(d0) * d1); + int l1 = (int) Math.round(Math.sin(d0) * d1); + int i2 = SectionPosition.a(k1, 8); + int j2 = SectionPosition.a(l1, 8); + Objects.requireNonNull(set); + Pair> pair = this.c.a(i2, 0, j2, 112, set::contains, random, this.d()); + if(pair != null) { + BlockPosition blockposition = pair.getFirst(); + k1 = SectionPosition.a(blockposition.u()); + l1 = SectionPosition.a(blockposition.w()); + } + + list.add(new ChunkCoordIntPair(k1, l1)); + d0 += 6.283185307179586 / (double) k; + ++l; + if(l == k) { + ++i1; + l = 0; + k += 2 * k / (i1 + 1); + k = Math.min(k, j - j1); + d0 += random.nextDouble() * Math.PI * 2.0; + } + } + return list; + + } + + public int getMinimumY() { + return h(); + } + + @Override //addDebugScreenInfo + public void a(List arg0, BlockPosition arg1) { + + } +} diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInitializer.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInitializer.java new file mode 100644 index 000000000..60c7e1c1d --- /dev/null +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInitializer.java @@ -0,0 +1,15 @@ +package com.dfsek.terra.bukkit.nms.v1_18_R2; + +import org.bukkit.Bukkit; + +import com.dfsek.terra.bukkit.PlatformImpl; +import com.dfsek.terra.bukkit.nms.Initializer; + + +public class NMSInitializer implements Initializer { + @Override + public void initialize(PlatformImpl platform) { + NMSBiomeInjector.registerBiomes(platform.getRawConfigRegistry()); + Bukkit.getPluginManager().registerEvents(new NMSInjectListener(), platform.getPlugin()); + } +} diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInjectListener.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInjectListener.java new file mode 100644 index 000000000..7402c1463 --- /dev/null +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSInjectListener.java @@ -0,0 +1,52 @@ +package com.dfsek.terra.bukkit.nms.v1_18_R2; + +import net.minecraft.server.level.WorldServer; +import net.minecraft.world.level.chunk.ChunkGenerator; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.world.WorldInitEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.locks.ReentrantLock; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; + + +public class NMSInjectListener implements Listener { + private static final Logger LOGGER = LoggerFactory.getLogger(NMSInjectListener.class); + private static final Set INJECTED = new HashSet<>(); + private static final ReentrantLock INJECT_LOCK = new ReentrantLock(); + + @EventHandler + public void onWorldInit(WorldInitEvent event) { + if (!INJECTED.contains(event.getWorld()) && event.getWorld().getGenerator() instanceof BukkitChunkGeneratorWrapper bukkitChunkGeneratorWrapper) { + INJECT_LOCK.lock(); + INJECTED.add(event.getWorld()); + LOGGER.info("Preparing to take over the world: {}", event.getWorld().getName()); + CraftWorld craftWorld = (CraftWorld) event.getWorld(); + WorldServer serverWorld = craftWorld.getHandle(); + + ConfigPack pack = bukkitChunkGeneratorWrapper.getPack(); + + ChunkGenerator vanilla = serverWorld.k().g(); + NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), vanilla.e(), craftWorld.getSeed()); + NMSChunkGeneratorDelegate custom = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed()); + + custom.conf = vanilla.conf; // world config from Spigot + + serverWorld.k().a.u = custom; + + LOGGER.info("Successfully injected into world."); + + serverWorld.k().a.u.i(); // generate stronghold data now + + INJECT_LOCK.unlock(); + } + } +} diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSWorldProperties.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSWorldProperties.java new file mode 100644 index 000000000..97dd66167 --- /dev/null +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/NMSWorldProperties.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.bukkit.nms.v1_18_R2; + +import net.minecraft.world.level.LevelHeightAccessor; + +import com.dfsek.terra.api.world.info.WorldProperties; + + +public class NMSWorldProperties implements WorldProperties { + private final long seed; + private final LevelHeightAccessor height; + + public NMSWorldProperties(long seed, LevelHeightAccessor height) { + this.seed = seed; + this.height = height; + } + + @Override + public Object getHandle() { + return height; + } + + @Override + public long getSeed() { + return seed; + } + + @Override + public int getMaxHeight() { + return height.ag(); + } + + @Override + public int getMinHeight() { + return height.u_(); + } +} diff --git a/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/Registries.java b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/Registries.java new file mode 100644 index 000000000..0702b25c9 --- /dev/null +++ b/platforms/bukkit/nms/v1_18_R2/src/main/java/com/dfsek/terra/bukkit/nms/v1_18_R2/Registries.java @@ -0,0 +1,30 @@ +package com.dfsek.terra.bukkit.nms.v1_18_R2; + +import net.minecraft.core.IRegistry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.world.level.biome.BiomeBase; +import net.minecraft.world.level.levelgen.structure.StructureSet; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_18_R2.CraftServer; + + +public class Registries { + private static IRegistry getRegistry(ResourceKey> key) { + CraftServer craftserver = (CraftServer) Bukkit.getServer(); + DedicatedServer dedicatedserver = craftserver.getServer(); + return dedicatedserver + .aU() // getRegistryManager + .b( // getRegistry + key + ); + } + + public static IRegistry biomeRegistry() { + return getRegistry(IRegistry.aP); + } + + public static IRegistry structureSet() { + return getRegistry(IRegistry.aM); + } +} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitCommandSender.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitCommandSender.java deleted file mode 100644 index ed65c569a..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitCommandSender.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.bukkit; - -import com.dfsek.terra.api.platform.CommandSender; -import org.bukkit.ChatColor; - -public class BukkitCommandSender implements CommandSender { - private final org.bukkit.command.CommandSender delegate; - - public BukkitCommandSender(org.bukkit.command.CommandSender delegate) { - this.delegate = delegate; - } - - @Override - public void sendMessage(String message) { - delegate.sendMessage(ChatColor.translateAlternateColorCodes('&', message)); - } - - @Override - public org.bukkit.command.CommandSender getHandle() { - return delegate; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java deleted file mode 100644 index ff3bd80ec..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitEntity.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.dfsek.terra.bukkit; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -public class BukkitEntity implements Entity { - private final org.bukkit.entity.Entity entity; - - public BukkitEntity(org.bukkit.entity.Entity entity) { - this.entity = entity; - } - - @Override - public org.bukkit.entity.Entity getHandle() { - return entity; - } - - @Override - public Location getLocation() { - return BukkitAdapter.adapt(entity.getLocation()); - } - - @Override - public void setLocation(Location location) { - entity.teleport(BukkitAdapter.adapt(location)); - } - - @Override - public World getWorld() { - return BukkitAdapter.adapt(entity.getWorld()); - } - - @Override - public void sendMessage(String message) { - entity.sendMessage(message); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java deleted file mode 100644 index 822fa0d7c..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/BukkitPlayer.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dfsek.terra.bukkit; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -public class BukkitPlayer implements Player { - private final org.bukkit.entity.Player delegate; - - public BukkitPlayer(org.bukkit.entity.Player delegate) { - this.delegate = delegate; - } - - @Override - public org.bukkit.entity.Player getHandle() { - return delegate; - } - - @Override - public Location getLocation() { - org.bukkit.Location bukkit = delegate.getLocation(); - return new Location(BukkitAdapter.adapt(bukkit.getWorld()), bukkit.getX(), bukkit.getY(), bukkit.getZ()); - } - - @Override - public void setLocation(Location location) { - delegate.teleport(BukkitAdapter.adapt(location)); - } - - @Override - public World getWorld() { - return BukkitAdapter.adapt(delegate.getWorld()); - } - - @Override - public void sendMessage(String message) { - delegate.sendMessage(message); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java deleted file mode 100644 index 2df87d72c..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java +++ /dev/null @@ -1,360 +0,0 @@ -package com.dfsek.terra.bukkit; - -import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.addons.annotations.Addon; -import com.dfsek.terra.api.addons.annotations.Author; -import com.dfsek.terra.api.addons.annotations.Version; -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.TerraCommandManager; -import com.dfsek.terra.api.command.exception.MalformedCommandException; -import com.dfsek.terra.api.event.EventManager; -import com.dfsek.terra.api.event.TerraEventManager; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.registry.CheckedRegistry; -import com.dfsek.terra.api.registry.LockedRegistry; -import com.dfsek.terra.api.util.logging.DebugLogger; -import com.dfsek.terra.api.util.logging.JavaLogger; -import com.dfsek.terra.api.util.logging.Logger; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.bukkit.command.BukkitCommandAdapter; -import com.dfsek.terra.bukkit.command.FixChunkCommand; -import com.dfsek.terra.bukkit.command.SaveDataCommand; -import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; -import com.dfsek.terra.bukkit.handles.BukkitItemHandle; -import com.dfsek.terra.bukkit.handles.BukkitWorldHandle; -import com.dfsek.terra.bukkit.listeners.CommonListener; -import com.dfsek.terra.bukkit.listeners.PaperListener; -import com.dfsek.terra.bukkit.listeners.SpigotListener; -import com.dfsek.terra.bukkit.listeners.TerraListener; -import com.dfsek.terra.bukkit.util.PaperUtil; -import com.dfsek.terra.bukkit.world.BukkitBiome; -import com.dfsek.terra.bukkit.world.BukkitWorld; -import com.dfsek.terra.commands.CommandUtil; -import com.dfsek.terra.config.GenericLoaders; -import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.config.lang.Language; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.profiler.Profiler; -import com.dfsek.terra.profiler.ProfilerImpl; -import com.dfsek.terra.registry.master.AddonRegistry; -import com.dfsek.terra.registry.master.ConfigRegistry; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; -import io.papermc.lib.PaperLib; -import org.bstats.bukkit.Metrics; -import org.bukkit.Bukkit; -import org.bukkit.command.PluginCommand; -import org.bukkit.entity.EntityType; -import org.bukkit.generator.ChunkGenerator; -import org.bukkit.plugin.java.JavaPlugin; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - - -public class TerraBukkitPlugin extends JavaPlugin implements TerraPlugin { - private final Map generatorMap = new HashMap<>(); - private final Map worldMap = new HashMap<>(); - private final Map worlds = new HashMap<>(); - - private final Profiler profiler = new ProfilerImpl(); - - private final ConfigRegistry registry = new ConfigRegistry(); - private final CheckedRegistry checkedRegistry = new CheckedRegistry<>(registry); - - private final PluginConfig config = new PluginConfig(); - private final ItemHandle itemHandle = new BukkitItemHandle(); - private WorldHandle handle = new BukkitWorldHandle(); - private final GenericLoaders genericLoaders = new GenericLoaders(this); - private DebugLogger debugLogger; - - - private final EventManager eventManager = new TerraEventManager(this); - public static final BukkitVersion BUKKIT_VERSION; - - static { - String ver = Bukkit.getServer().getClass().getPackage().getName(); - if(ver.contains("1_17")) BUKKIT_VERSION = BukkitVersion.V1_17; - else if(ver.contains("1_16")) BUKKIT_VERSION = BukkitVersion.V1_16; - else if(ver.contains("1_15")) BUKKIT_VERSION = BukkitVersion.V1_15; - else if(ver.contains("1_14")) BUKKIT_VERSION = BukkitVersion.V1_14; - else if(ver.contains("1_13")) BUKKIT_VERSION = BukkitVersion.V1_13; - else BUKKIT_VERSION = BukkitVersion.UNKNOWN; - } - - private final AddonRegistry addonRegistry = new AddonRegistry(new BukkitAddon(this), this); - private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); - - - - public boolean reload() { - config.load(this); - LangUtil.load(config.getLanguage(), this); // Load language. - boolean succeed = registry.loadAll(this); - Map newMap = new HashMap<>(); - worldMap.forEach((world, tw) -> { - tw.getConfig().getSamplerCache().clear(); - String packID = tw.getConfig().getTemplate().getID(); - newMap.put(world, new TerraWorld(world, registry.get(packID), this)); - }); - worldMap.clear(); - worldMap.putAll(newMap); - return succeed; - } - - @Override - public ItemHandle getItemHandle() { - return itemHandle; - } - - @Override - public String platformName() { - return "Bukkit"; - } - - public void setHandle(WorldHandle handle) { - getLogger().warning("|-------------------------------------------------------|"); - getLogger().warning("A third-party addon has injected a custom WorldHandle!"); - getLogger().warning("If you encounter issues, try *without* the addon before"); - getLogger().warning("reporting to Terra. Report issues with the addon to the"); - getLogger().warning("addon's maintainers!"); - getLogger().warning("|-------------------------------------------------------|"); - this.handle = handle; - } - - @Override - public DebugLogger getDebugLogger() { - return debugLogger; - } - - @Override - public EventManager getEventManager() { - return eventManager; - } - - @Override - public void runPossiblyUnsafeTask(Runnable task) { - Bukkit.getScheduler().runTask(this, task); - } - - @Override - public Profiler getProfiler() { - return profiler; - } - - @Override - public void onDisable() { - BukkitChunkGeneratorWrapper.saveAll(); - } - - @Override - public void onEnable() { - debugLogger = new DebugLogger(logger()); - - getLogger().info("Running on version " + BUKKIT_VERSION); - if(BUKKIT_VERSION == BukkitVersion.UNKNOWN) { - getLogger().warning("Terra is running on an unknown Bukkit version. Proceed with caution."); - } - - saveDefaultConfig(); - - Metrics metrics = new Metrics(this, 9017); // Set up bStats. - metrics.addCustomChart(new Metrics.SingleLineChart("worlds", worldMap::size)); // World number chart. - - config.load(this); // Load master config.yml - LangUtil.load(config.getLanguage(), this); // Load language. - debugLogger.setDebug(isDebug()); - - if(!addonRegistry.loadAll()) { - getLogger().severe("Failed to load addons. Please correct addon installations to continue."); - Bukkit.getPluginManager().disablePlugin(this); - return; - } - - registry.loadAll(this); // Load all config packs. - - PluginCommand c = Objects.requireNonNull(getCommand("terra")); - - CommandManager manager = new TerraCommandManager(this); - - - try { - CommandUtil.registerAll(manager); - manager.register("save-data", SaveDataCommand.class); - manager.register("fix-chunk", FixChunkCommand.class); - } catch(MalformedCommandException e) { // This should never happen. - logger().severe("Errors occurred while registering commands."); - e.printStackTrace(); - logger().severe("Please report this to Terra."); - Bukkit.getPluginManager().disablePlugin(this); - return; - } - - BukkitCommandAdapter command = new BukkitCommandAdapter(manager); - - c.setExecutor(command); - c.setTabCompleter(command); - - - long save = config.getDataSaveInterval(); - Bukkit.getScheduler().runTaskTimerAsynchronously(this, BukkitChunkGeneratorWrapper::saveAll, save, save); // Schedule population data saving - Bukkit.getPluginManager().registerEvents(new CommonListener(this), this); // Register master event listener - PaperUtil.checkPaper(this); - - if(PaperLib.isPaper()) { - try { - Class.forName("io.papermc.paper.event.world.StructureLocateEvent"); // Check if user is on Paper version with event. - Bukkit.getPluginManager().registerEvents(new PaperListener(this), this); // Register Paper events. - } catch(ClassNotFoundException e) { - registerSpigotEvents(true); // Outdated Paper version. - } - } else { - registerSpigotEvents(false); - } - } - - private void registerSpigotEvents(boolean outdated) { - if(outdated) { - getLogger().severe("You are using an outdated version of Paper."); - getLogger().severe("This version does not contain StructureLocateEvent."); - getLogger().severe("Terra will now fall back to Spigot events."); - getLogger().severe("This will prevent cartographer villagers from spawning,"); - getLogger().severe("and cause structure location to not function."); - getLogger().severe("If you want these functionalities, update to the latest build of Paper."); - getLogger().severe("If you use a fork, update to the latest version, then if you still"); - getLogger().severe("receive this message, ask the fork developer to update upstream."); - } else { - getLogger().severe("Paper is not in use. Falling back to Spigot events."); - getLogger().severe("This will prevent cartographer villagers from spawning,"); - getLogger().severe("and cause structure location to not function."); - getLogger().severe("If you want these functionalities (and all the other"); - getLogger().severe("benefits that Paper offers), upgrade your server to Paper."); - getLogger().severe("Find out more at https://papermc.io/"); - } - - Bukkit.getPluginManager().registerEvents(new SpigotListener(this), this); // Register Spigot event listener - } - - @Override - public @Nullable ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, @Nullable String id) { - return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> { - if(!registry.contains(id)) throw new IllegalArgumentException("No such config pack \"" + id + "\""); - ConfigPack pack = registry.get(id); - worlds.put(worldName, pack); - return new DefaultChunkGenerator3D(registry.get(id), this); - })); - } - - @Override - public boolean isDebug() { - return config.isDebug(); - } - - - @Override - public Language getLanguage() { - return LangUtil.getLanguage(); - } - - public CheckedRegistry getConfigRegistry() { - return checkedRegistry; - } - - public TerraWorld getWorld(World world) { - BukkitWorld w = (BukkitWorld) world; - if(!w.isTerraWorld()) - throw new IllegalArgumentException("Not a Terra world! " + w.getGenerator()); - if(!worlds.containsKey(w.getName())) { - getLogger().warning("Unexpected world load detected: \"" + w.getName() + "\""); - return new TerraWorld(w, ((TerraChunkGenerator) w.getGenerator().getHandle()).getConfigPack(), this); - } - return worldMap.computeIfAbsent(w, w2 -> new TerraWorld(w, worlds.get(w.getName()), this)); - } - - @Override - public Logger logger() { - return new JavaLogger(getLogger()); - } - - @NotNull - @Override - public PluginConfig getTerraConfig() { - return config; - } - - @Override - public WorldHandle getWorldHandle() { - return handle; - } - - - @Override - public void register(TypeRegistry registry) { - registry - .registerLoader(BlockData.class, (t, o, l) -> handle.createBlockData((String) o)) - .registerLoader(Biome.class, (t, o, l) -> new BukkitBiome(org.bukkit.block.Biome.valueOf((String) o))) - .registerLoader(EntityType.class, (t, o, l) -> EntityType.valueOf((String) o)); - genericLoaders.register(registry); - } - - @Override - public LockedRegistry getAddons() { - return addonLockedRegistry; - } - - public enum BukkitVersion { - V1_13(13), - - V1_14(14), - - V1_15(15), - - V1_16(16), - - V1_17(17), - - UNKNOWN(Integer.MAX_VALUE); // Assume unknown version is latest. - - private final int index; - - BukkitVersion(int index) { - this.index = index; - } - - /** - * Gets if this version is above or equal to another. - * - * @param other Other version - * @return Whether this version is equal to or later than other. - */ - public boolean above(BukkitVersion other) { - return this.index >= other.index; - } - } - - @Addon("Terra-Bukkit") - @Version("1.0.0") - @Author("Terra") - private static final class BukkitAddon extends TerraAddon { - private final TerraPlugin main; - - private BukkitAddon(TerraPlugin main) { - this.main = main; - } - - @Override - public void initialize() { - main.getEventManager().registerListener(this, new TerraListener(main)); - } - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java deleted file mode 100644 index 7a4d1227e..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.dfsek.terra.bukkit.command; - -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.exception.CommandException; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.stream.Collectors; - -public class BukkitCommandAdapter implements CommandExecutor, TabCompleter { - private final CommandManager manager; - - public BukkitCommandAdapter(CommandManager manager) { - this.manager = manager; - } - - @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - List argList = new ArrayList<>(Arrays.asList(args)); - if(argList.isEmpty()) { - sender.sendMessage("Command requires arguments."); - return true; - } - try { - manager.execute(argList.remove(0), BukkitAdapter.adapt(sender), argList); - } catch(CommandException e) { - sender.sendMessage(e.getMessage()); - } - return true; - } - - @Override - public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { - List argList = new ArrayList<>(Arrays.asList(args)); - - try { - return manager.tabComplete(argList.remove(0), BukkitAdapter.adapt(sender), argList).stream() - .filter(s -> s.toLowerCase(Locale.ROOT).startsWith(args[args.length - 1].toLowerCase(Locale.ROOT))).sorted(String::compareTo).collect(Collectors.toList()); - } catch(CommandException e) { - e.printStackTrace(); - return Collections.emptyList(); - } - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/FixChunkCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/FixChunkCommand.java deleted file mode 100644 index 87d69c115..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/FixChunkCommand.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.bukkit.command; - -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.command.annotation.type.PlayerCommand; -import com.dfsek.terra.api.command.annotation.type.WorldCommand; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; - -@Command -@WorldCommand -@PlayerCommand -public class FixChunkCommand implements CommandTemplate { - @Override - public void execute(CommandSender sender) { - Player player = (Player) sender; - BukkitChunkGeneratorWrapper.fixChunk(player.getWorld().getChunkAt(player.getLocation())); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/SaveDataCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/SaveDataCommand.java deleted file mode 100644 index 4648cb01e..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/SaveDataCommand.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.bukkit.command; - -import com.dfsek.terra.api.command.CommandTemplate; -import com.dfsek.terra.api.command.annotation.Command; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; -import com.dfsek.terra.config.lang.LangUtil; - -@Command -public class SaveDataCommand implements CommandTemplate { - @Override - public void execute(CommandSender sender) { - BukkitChunkGeneratorWrapper.saveAll(); - LangUtil.send("debug.data-save", sender); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGenerator.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGenerator.java deleted file mode 100644 index da186a425..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGenerator.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.dfsek.terra.bukkit.generator; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.generator.ChunkData; -import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; -import org.bukkit.generator.ChunkGenerator; -import org.jetbrains.annotations.NotNull; - -public class BukkitChunkGenerator implements com.dfsek.terra.api.platform.world.generator.ChunkGenerator { - private final ChunkGenerator delegate; - - public BukkitChunkGenerator(ChunkGenerator delegate) { - this.delegate = delegate; - } - - @Override - public ChunkGenerator getHandle() { - return delegate; - } - - public static class BukkitChunkData implements ChunkData { - - private final ChunkGenerator.ChunkData delegate; - - public BukkitChunkData(ChunkGenerator.ChunkData delegate) { - this.delegate = delegate; - } - - @Override - public ChunkGenerator.ChunkData getHandle() { - return delegate; - } - - @Override - public int getMaxHeight() { - return delegate.getMaxHeight(); - } - - - @Override - public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { - delegate.setBlock(x, y, z, ((BukkitBlockData) blockData).getHandle()); - } - - - @Override - public @NotNull BlockData getBlockData(int x, int y, int z) { - return BukkitBlockData.newInstance(delegate.getBlockData(x, y, z)); - } - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java deleted file mode 100644 index 67b7148e6..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.dfsek.terra.bukkit.generator; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.bukkit.population.PopulationManager; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.bukkit.world.BukkitBiomeGrid; -import com.dfsek.terra.world.TerraWorld; -import org.bukkit.World; -import org.bukkit.generator.BlockPopulator; -import org.bukkit.generator.ChunkGenerator; -import org.jetbrains.annotations.NotNull; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -public class BukkitChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { - - private static final Map popMap = new HashMap<>(); - - private final PopulationManager popMan; - - private final TerraChunkGenerator delegate; - - private final TerraPlugin main; - - private boolean needsLoad = true; - - public BukkitChunkGeneratorWrapper(TerraChunkGenerator delegate) { - this.delegate = delegate; - this.main = delegate.getMain(); - this.popMan = new PopulationManager(delegate, main); - - } - - - public static synchronized void saveAll() { - for(Map.Entry e : popMap.entrySet()) { - try { - e.getValue().saveBlocks(e.getKey()); - } catch(IOException ioException) { - ioException.printStackTrace(); - } - } - } - - public static synchronized void fixChunk(Chunk c) { - if(!c.getWorld().isTerraWorld()) throw new IllegalArgumentException(); - popMap.get(c.getWorld()).checkNeighbors(c.getX(), c.getZ(), c.getWorld()); - } - - private void load(com.dfsek.terra.api.platform.world.World w) { - try { - popMan.loadBlocks(w); - } catch(FileNotFoundException ignore) { - - } catch(IOException | ClassNotFoundException e) { - e.printStackTrace(); - } - popMap.put(w, popMan); - needsLoad = false; - } - - @Override - public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random random, int x, int z, @NotNull BiomeGrid biome) { - com.dfsek.terra.api.platform.world.World bukkitWorld = BukkitAdapter.adapt(world); - if(needsLoad) load(bukkitWorld); // Load population data for world. - delegate.generateBiomes(bukkitWorld, random, x, z, new BukkitBiomeGrid(biome)); - return (ChunkData) delegate.generateChunkData(bukkitWorld, random, x, z, new BukkitChunkGenerator.BukkitChunkData(createChunkData(world))).getHandle(); - } - - @Override - public @NotNull List getDefaultPopulators(@NotNull World world) { - return Arrays.asList(popMan, new BukkitPopulatorWrapper(delegate)); - } - - @Override - public boolean isParallelCapable() { - return delegate.isParallelCapable(); - } - - @Override - public boolean shouldGenerateCaves() { - return delegate.shouldGenerateCaves(); - } - - @Override - public boolean shouldGenerateDecorations() { - return delegate.shouldGenerateDecorations(); - } - - @Override - public boolean shouldGenerateMobs() { - return delegate.shouldGenerateMobs(); - } - - @Override - public boolean shouldGenerateStructures() { - return delegate.shouldGenerateStructures(); - } - - @Override - public TerraChunkGenerator getHandle() { - return delegate; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulatorWrapper.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulatorWrapper.java deleted file mode 100644 index eb57cb2dc..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitPopulatorWrapper.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.bukkit.generator; - -import com.dfsek.terra.api.world.generation.Chunkified; -import com.dfsek.terra.api.world.generation.TerraBlockPopulator; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.generator.BlockPopulator; -import org.jetbrains.annotations.NotNull; - -import java.util.Random; - -public class BukkitPopulatorWrapper extends BlockPopulator { - private final TerraChunkGenerator delegate; - - public BukkitPopulatorWrapper(TerraChunkGenerator delegate) { - this.delegate = delegate; - } - - @Override - public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk source) { - delegate.getPopulators().forEach(populator -> { - if(populator instanceof Chunkified) { - populator.populate(BukkitAdapter.adapt(world), BukkitAdapter.adapt(source)); - } - }); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java deleted file mode 100644 index f13783203..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitItemHandle.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.bukkit.handles; - -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.dfsek.terra.bukkit.util.MinecraftUtils; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; - -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -public class BukkitItemHandle implements ItemHandle { - - @Override - public Item createItem(String data) { - return BukkitAdapter.adapt(Material.matchMaterial(data)); - } - - @Override - public Enchantment getEnchantment(String id) { - return BukkitAdapter.adapt(org.bukkit.enchantments.Enchantment.getByKey(NamespacedKey.minecraft(MinecraftUtils.stripMinecraftNamespace(id)))); - } - - @Override - public Set getEnchantments() { - return Arrays.stream(org.bukkit.enchantments.Enchantment.values()).map(BukkitAdapter::adapt).collect(Collectors.toSet()); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java deleted file mode 100644 index 8f3736103..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dfsek.terra.bukkit.handles; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.dfsek.terra.bukkit.structure.WorldEditUtil; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; -import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; -import org.bukkit.Bukkit; - -public class BukkitWorldHandle implements WorldHandle { - - @Override - public BlockData createBlockData(String data) { - org.bukkit.block.data.BlockData bukkitData = Bukkit.createBlockData(data); - return BukkitBlockData.newInstance(bukkitData); - } - - @Override - public EntityType getEntity(String id) { - return new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(id)); - } - - @Override - public Pair getSelectedLocation(Player player) { - org.bukkit.Location[] locations = WorldEditUtil.getSelectionLocations(BukkitAdapter.adapt(player)); - return new Pair<>(BukkitAdapter.adapt(locations[0]), BukkitAdapter.adapt(locations[1])); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java deleted file mode 100644 index ac0fd6356..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.dfsek.terra.bukkit.listeners; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.transform.MapTransform; -import com.dfsek.terra.api.transform.Transformer; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.config.pack.WorldConfig; -import com.dfsek.terra.world.TerraWorld; -import org.bukkit.Material; -import org.bukkit.TreeType; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.world.StructureGrowEvent; - -/** - * Listener for events on all implementations. - */ -public class CommonListener implements Listener { - private final TerraPlugin main; - - public CommonListener(TerraPlugin main) { - this.main = main; - } - - private static final Transformer TREE_TYPE_STRING_TRANSFORMER = new Transformer.Builder() - .addTransform(new MapTransform() - .add(TreeType.COCOA_TREE, "JUNGLE_COCOA") - .add(TreeType.BIG_TREE, "LARGE_OAK") - .add(TreeType.TALL_REDWOOD, "LARGE_SPRUCE") - .add(TreeType.REDWOOD, "SPRUCE") - .add(TreeType.TREE, "OAK") - .add(TreeType.MEGA_REDWOOD, "MEGA_SPRUCE") - .add(TreeType.SWAMP, "SWAMP_OAK")) - .addTransform(TreeType::toString).build(); - - @EventHandler(priority = EventPriority.HIGHEST) - public void onSaplingGrow(StructureGrowEvent e) { - if(e.isCancelled()) return; - World bukkit = BukkitAdapter.adapt(e.getWorld()); - if(!bukkit.isTerraWorld()) return; - TerraWorld tw = main.getWorld(bukkit); - WorldConfig c = tw.getConfig(); - if(c.getTemplate().isDisableSaplings()) return; - e.setCancelled(true); - Block block = e.getLocation().getBlock(); - BlockData data = block.getBlockData(); - block.setType(Material.AIR); - Tree tree = c.getTreeRegistry().get(TREE_TYPE_STRING_TRANSFORMER.translate(e.getSpecies())); - org.bukkit.Location location = e.getLocation(); - if(!tree.plant(new Location(bukkit, location.getX(), location.getY(), location.getZ()), new FastRandom())) block.setBlockData(data); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java deleted file mode 100644 index 2e98877f8..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/PaperListener.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.dfsek.terra.bukkit.listeners; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.world.locate.AsyncStructureFinder; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.population.items.TerraStructure; -import io.papermc.paper.event.world.StructureLocateEvent; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; - -public class PaperListener implements Listener { - private final TerraPlugin main; - - public PaperListener(TerraPlugin main) { - this.main = main; - } - - @EventHandler - public void onStructureLocate(StructureLocateEvent e) { - if(!BukkitAdapter.adapt(e.getWorld()).isTerraWorld()) return; - String name = "minecraft:" + e.getType().getName(); - main.getDebugLogger().info("Overriding structure location for \"" + name + "\""); - TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getWorld())); - TerraStructure config = tw.getConfig().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get(name)); - if(config != null) { - AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getOrigin()), 0, 500, location -> { - if(location != null) - e.setResult(BukkitAdapter.adapt(location.toLocation(BukkitAdapter.adapt(e.getWorld())))); - main.getDebugLogger().info("Location: " + location); - }, main); - finder.run(); // Do this synchronously. - } else { - e.setResult(e.getOrigin()); - main.logger().warning("No overrides are defined for \"" + name + "\". Locating this structure will NOT work properly!"); - } - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java deleted file mode 100644 index 5034c4863..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/SpigotListener.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.dfsek.terra.bukkit.listeners; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.world.locate.AsyncStructureFinder; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.population.items.TerraStructure; -import org.bukkit.entity.EnderSignal; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Villager; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntitySpawnEvent; -import org.bukkit.event.entity.VillagerAcquireTradeEvent; -import org.bukkit.event.entity.VillagerCareerChangeEvent; - -/** - * Listener to load on Spigot servers, contains Villager crash prevention and hacky ender eye redirection. - *

- * (This is currently loaded on all servers; once Paper accepts the StructureLocateEvent PR this will only be loaded on servers without - * StructureLocateEvent). - */ -public class SpigotListener implements Listener { - private final TerraPlugin main; - - public SpigotListener(TerraPlugin main) { - this.main = main; - } - - @EventHandler(priority = EventPriority.NORMAL) - public void onEnderEye(EntitySpawnEvent e) { - Entity entity = e.getEntity(); - if(e.getEntityType().equals(EntityType.ENDER_SIGNAL)) { - main.getDebugLogger().info("Detected Ender Signal..."); - if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return; - TerraWorld tw = main.getWorld(BukkitAdapter.adapt(e.getEntity().getWorld())); - EnderSignal signal = (EnderSignal) entity; - TerraStructure config = tw.getConfig().getStructureRegistry().get(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD")); - if(config != null) { - main.getDebugLogger().info("Overriding Ender Signal..."); - AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getLocation()), 0, 500, location -> { - if(location != null) - signal.setTargetLocation(BukkitAdapter.adapt(location.toLocation(BukkitAdapter.adapt(signal.getWorld())))); - main.getDebugLogger().info("Location: " + location); - }, main); - finder.run(); // Do this synchronously so eye doesn't change direction several ticks after spawning. - } else - main.logger().warning("No overrides are defined for Strongholds. Ender Signals will not work correctly."); - } - } - - @EventHandler - public void onCartographerChange(VillagerAcquireTradeEvent e) { - if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return; - if(!(e.getEntity() instanceof Villager)) return; - if(((Villager) e.getEntity()).getProfession().equals(Villager.Profession.CARTOGRAPHER)) { - main.logger().severe("Prevented server crash by stopping Cartographer villager from spawning."); - main.logger().severe("Please upgrade to Paper, which has a StructureLocateEvent that fixes this issue"); - main.logger().severe("at the source, and doesn't require us to do stupid band-aids."); - e.setCancelled(true); // Cancel leveling if the villager is a Cartographer, to prevent crashing server. - } - } - - @EventHandler - public void onCartographerLevel(VillagerCareerChangeEvent e) { - if(!BukkitAdapter.adapt(e.getEntity().getWorld()).isTerraWorld()) return; - if(e.getProfession().equals(Villager.Profession.CARTOGRAPHER)) { - main.logger().severe("Prevented server crash by stopping Cartographer villager from spawning."); - main.logger().severe("Please upgrade to Paper, which has a StructureLocateEvent that fixes this issue"); - main.logger().severe("at the source, and doesn't require us to do stupid band-aids."); - e.getEntity().setProfession(Villager.Profession.NITWIT); // Give villager new profession to prevent server crash. - e.setCancelled(true); - } - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java deleted file mode 100644 index 4eb05f91e..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/TerraListener.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.bukkit.listeners; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.event.EventListener; -import com.dfsek.terra.api.event.annotations.Global; -import com.dfsek.terra.api.event.annotations.Priority; -import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.bukkit.world.BukkitTree; -import com.dfsek.terra.registry.exception.DuplicateEntryException; -import org.bukkit.TreeType; - -public class TerraListener implements EventListener { - private final TerraPlugin main; - - public TerraListener(TerraPlugin main) { - this.main = main; - } - - @Global - @Priority(Priority.LOWEST) - public void injectTrees(ConfigPackPreLoadEvent event) { - for(TreeType value : TreeType.values()) { - try { - String id = BukkitAdapter.TREE_TRANSFORMER.translate(value); - event.getPack().getTreeRegistry().add(id, new BukkitTree(value, main)); - event.getPack().getTreeRegistry().get(id); // Platform trees should never be marked "dead" - } catch(DuplicateEntryException ignore) { // If another addon has already registered trees, do nothing. - } - } - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/ChunkCoordinate.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/ChunkCoordinate.java deleted file mode 100644 index a68e575fa..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/ChunkCoordinate.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.dfsek.terra.bukkit.population; - - -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.bukkit.world.BukkitWorld; - -import java.io.Serializable; -import java.util.UUID; - -public class ChunkCoordinate implements Serializable { - public static final long serialVersionUID = 7102462856296750285L; - private final int x; - private final int z; - private final UUID worldID; - - public ChunkCoordinate(int x, int z, UUID worldID) { - this.x = x; - this.z = z; - this.worldID = worldID; - } - - public ChunkCoordinate(Chunk c) { - this.x = c.getX(); - this.z = c.getZ(); - this.worldID = ((BukkitWorld) c.getWorld()).getUID(); - } - - public UUID getWorldID() { - return worldID; - } - - public int getX() { - return x; - } - - public int getZ() { - return z; - } - - @Override - public int hashCode() { - return x * 31 + z; - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof ChunkCoordinate)) return false; - ChunkCoordinate other = (ChunkCoordinate) obj; - return other.getX() == x && other.getZ() == z; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java deleted file mode 100644 index e783c0118..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/PopulationManager.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.dfsek.terra.bukkit.population; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.world.generation.Chunkified; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.bukkit.TerraBukkitPlugin; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.bukkit.world.BukkitWorld; -import com.dfsek.terra.profiler.ProfileFrame; -import org.bukkit.generator.BlockPopulator; -import org.jetbrains.annotations.NotNull; - -import java.io.File; -import java.io.IOException; -import java.util.HashSet; -import java.util.Random; - -/** - * Cursed management class for the horrors of Bukkit population - */ -public class PopulationManager extends BlockPopulator { - private final TerraChunkGenerator generator; - private final HashSet needsPop = new HashSet<>(); - private final TerraPlugin main; - - public PopulationManager(TerraChunkGenerator generator, TerraPlugin main) { - this.generator = generator; - this.main = main; - } - - @SuppressWarnings("unchecked") - public synchronized void saveBlocks(World w) throws IOException { - File f = new File(getDataFolder(w), "chunks.bin"); - f.createNewFile(); - SerializationUtil.toFile((HashSet) needsPop.clone(), f); - } - - @SuppressWarnings("unchecked") - public synchronized void loadBlocks(World w) throws IOException, ClassNotFoundException { - File f = new File(getDataFolder(w), "chunks.bin"); - needsPop.addAll((HashSet) SerializationUtil.fromFile(f)); - } - - public static File getDataFolder(World w) { - File f = new File(((BukkitWorld) w).getWorldFolder(), "gaea"); - f.mkdirs(); - return f; - } - - - // Synchronize to prevent chunks from being queued for population multiple times. - public synchronized void checkNeighbors(int x, int z, World world) { - BukkitWorld w = (BukkitWorld) world; - ChunkCoordinate c = new ChunkCoordinate(x, z, (w).getUID()); - if(w.isChunkGenerated(x + 1, z) - && w.isChunkGenerated(x - 1, z) - && w.isChunkGenerated(x, z + 1) - && w.isChunkGenerated(x, z - 1) && needsPop.contains(c)) { - Random random = new FastRandom(w.getSeed()); - long xRand = (random.nextLong() / 2L << 1L) + 1L; - long zRand = (random.nextLong() / 2L << 1L) + 1L; - random.setSeed((long) x * xRand + (long) z * zRand ^ w.getSeed()); - Chunk currentChunk = w.getChunkAt(x, z); - generator.getPopulators().forEach(populator -> { - if(!(populator instanceof Chunkified)) { - populator.populate(w, currentChunk); - } - }); - needsPop.remove(c); - } - } - - @Override - @SuppressWarnings("try") - public void populate(org.bukkit.@NotNull World world, @NotNull Random random, org.bukkit.@NotNull Chunk source) { - try(ProfileFrame ignore = main.getProfiler().profile("popman")) { - Chunk chunk = BukkitAdapter.adapt(source); - needsPop.add(new ChunkCoordinate(chunk)); - int x = chunk.getX(); - int z = chunk.getZ(); - if(((TerraBukkitPlugin) main).isEnabled()) { - for(int xi = -1; xi <= 1; xi++) { - for(int zi = -1; zi <= 1; zi++) { - if(xi == 0 && zi == 0) continue; - if(world.isChunkGenerated(xi + x, zi + z)) checkNeighbors(xi + x, zi + z, BukkitAdapter.adapt(world)); - } - } - } - } - } -} \ No newline at end of file diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/SerializationUtil.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/SerializationUtil.java deleted file mode 100644 index a297259c5..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/population/SerializationUtil.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.dfsek.terra.bukkit.population; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.ObjectStreamClass; -import java.io.Serializable; -import java.lang.reflect.Field; - -public final class SerializationUtil { - public static Object fromFile(File f) throws IOException, ClassNotFoundException { - ObjectInputStream ois = new MovedObjectInputStream(new FileInputStream(f), "com.dfsek.terra.api.world.generation.population", "com.dfsek.terra.bukkit.population"); // Backwards compat with old Gaea location - Object o = ois.readObject(); - ois.close(); - return o; - } - - public static void toFile(Serializable o, File f) throws IOException { - ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f)); - oos.writeObject(o); - oos.close(); - } - - public static class MovedObjectInputStream extends ObjectInputStream { - private final String oldNameSpace; - private final String newNameSpace; - - public MovedObjectInputStream(InputStream in, String oldNameSpace, String newNameSpace) throws IOException { - super(in); - this.oldNameSpace = oldNameSpace; - this.newNameSpace = newNameSpace; - } - - @Override - protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { - ObjectStreamClass result = super.readClassDescriptor(); - try { - if(result.getName().contains(oldNameSpace)) { - String newClassName = result.getName().replace(oldNameSpace, newNameSpace); - Class localClass = Class.forName(newClassName); - - Field nameField = ObjectStreamClass.class.getDeclaredField("name"); - nameField.setAccessible(true); - nameField.set(result, newClassName); - - ObjectStreamClass localClassDescriptor = ObjectStreamClass.lookup(localClass); - Field suidField = ObjectStreamClass.class.getDeclaredField("suid"); - suidField.setAccessible(true); - suidField.set(result, localClassDescriptor.getSerialVersionUID()); - } - } catch(Exception e) { - throw new IOException("Exception when trying to replace namespace", e); - } - return result; - } - - @Override - protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { - if(desc.getName().contains(oldNameSpace)) { - String newClassName = desc.getName().replace(oldNameSpace, newNameSpace); - return Class.forName(newClassName); - } - return super.resolveClass(desc); - } - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditNotFoundException.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditNotFoundException.java deleted file mode 100644 index 619cbe75f..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditNotFoundException.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.dfsek.terra.bukkit.structure; - -public class WorldEditNotFoundException extends RuntimeException { - private static final long serialVersionUID = 3678822468346338227L; - - public WorldEditNotFoundException() { - } - - public WorldEditNotFoundException(String message) { - super(message); - } - - public WorldEditNotFoundException(String message, Throwable cause) { - super(message, cause); - } - - public WorldEditNotFoundException(Throwable cause) { - super(cause); - } - - public WorldEditNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditUtil.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditUtil.java deleted file mode 100644 index f7e5deb6c..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/structure/WorldEditUtil.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.dfsek.terra.bukkit.structure; - -import com.sk89q.worldedit.IncompleteRegionException; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.CuboidRegion; -import com.sk89q.worldedit.regions.Region; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.jetbrains.annotations.NotNull; - -public final class WorldEditUtil { - public static Location[] getSelectionLocations(Player sender) { - WorldEditPlugin we; - try { - we = WorldEditUtil.getWorldEdit(); - } catch(WorldEditNotFoundException e) { - sender.sendMessage("WorldEdit is not installed! Please install WorldEdit before attempting to export structures."); - throw e; - } - Region selection; - try { - selection = we.getSession(sender).getSelection(BukkitAdapter.adapt(sender.getWorld())); - } catch(IncompleteRegionException | ClassCastException e) { - throw new IllegalStateException("Invalid/incomplete selection!"); - } - if(selection == null) { - throw new IllegalStateException("Please make a selection before attempting to export!"); - } - BlockVector3 min = selection.getMinimumPoint(); - BlockVector3 max = selection.getMaximumPoint(); - Location l1 = new Location(sender.getWorld(), min.getBlockX(), min.getBlockY(), min.getBlockZ()); - Location l2 = new Location(sender.getWorld(), max.getBlockX(), max.getBlockY(), max.getBlockZ()); - return new Location[] {l1, l2}; - } - - /** - * Gets an instance of the WorldEditPlugin class. - * - * @return The world edit plugin instance. - * @throws WorldEditNotFoundException Thrown when worldedit cannot be found. - */ - @NotNull - public static WorldEditPlugin getWorldEdit() { - Plugin p = Bukkit.getServer().getPluginManager().getPlugin("WorldEdit"); - if(p instanceof WorldEditPlugin) return (WorldEditPlugin) p; - Bukkit.getLogger().severe("[Terra] a command requiring WorldEdit was executed, but WorldEdit was not detected!"); - throw new WorldEditNotFoundException("Could not find World Edit!"); - } - - public static Location[] getSelectionPositions(Player sender) { - WorldEditPlugin we; - try { - we = WorldEditUtil.getWorldEdit(); - } catch(WorldEditNotFoundException e) { - sender.sendMessage("WorldEdit is not installed! Please install WorldEdit before attempting to export structures."); - throw e; - } - CuboidRegion selection; - try { - selection = (CuboidRegion) we.getSession(sender).getSelection(BukkitAdapter.adapt(sender.getWorld())); - } catch(IncompleteRegionException | ClassCastException e) { - sender.sendMessage("Invalid/incomplete selection!"); - return null; - } - if(selection == null) { - sender.sendMessage("Please make a selection before attempting to export!"); - return null; - } - BlockVector3 min = selection.getPos1(); - BlockVector3 max = selection.getPos2(); - Location l1 = new Location(sender.getWorld(), min.getBlockX(), min.getBlockY(), min.getBlockZ()); - Location l2 = new Location(sender.getWorld(), max.getBlockX(), max.getBlockY(), max.getBlockZ()); - return new Location[] {l1, l2}; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/MinecraftUtils.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/MinecraftUtils.java deleted file mode 100644 index 0c36bc946..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/MinecraftUtils.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.bukkit.util; - -public final class MinecraftUtils { - public static String stripMinecraftNamespace(String in) { - if(in.startsWith("minecraft:")) return in.substring("minecraft:".length()); - return in; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/PaperUtil.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/PaperUtil.java deleted file mode 100644 index 05eba8c9b..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/util/PaperUtil.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.bukkit.util; - -import io.papermc.lib.PaperLib; -import org.bukkit.Bukkit; -import org.bukkit.plugin.java.JavaPlugin; - -import static io.papermc.lib.PaperLib.suggestPaper; - -public final class PaperUtil { - public static void checkPaper(JavaPlugin main) { - Bukkit.getScheduler().scheduleSyncDelayedTask(main, () -> { - if(!PaperLib.isPaper()) { - suggestPaper(main); - } - }, 100L); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java deleted file mode 100644 index c50cd2711..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java +++ /dev/null @@ -1,412 +0,0 @@ -package com.dfsek.terra.bukkit.world; - - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.block.Axis; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.block.data.Bisected; -import com.dfsek.terra.api.platform.block.data.Rail; -import com.dfsek.terra.api.platform.block.data.RedstoneWire; -import com.dfsek.terra.api.platform.block.data.Slab; -import com.dfsek.terra.api.platform.block.data.Stairs; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.transform.MapTransform; -import com.dfsek.terra.api.transform.Transformer; -import com.dfsek.terra.bukkit.BukkitCommandSender; -import com.dfsek.terra.bukkit.BukkitEntity; -import com.dfsek.terra.bukkit.BukkitPlayer; -import com.dfsek.terra.bukkit.world.block.BukkitBlockTypeAndItem; -import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; -import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack; -import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.TreeType; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -/** - * Utility class to adapt Bukkit enums to Terra enums. - */ -public final class BukkitAdapter { - public static Transformer TREE_TRANSFORMER = new Transformer.Builder() - .addTransform(new MapTransform() - .add(TreeType.COCOA_TREE, "JUNGLE_COCOA") - .add(TreeType.BIG_TREE, "LARGE_OAK") - .add(TreeType.TALL_REDWOOD, "LARGE_SPRUCE") - .add(TreeType.REDWOOD, "SPRUCE") - .add(TreeType.TREE, "OAK") - .add(TreeType.MEGA_REDWOOD, "MEGA_SPRUCE") - .add(TreeType.SWAMP, "SWAMP_OAK")) - .addTransform(TreeType::toString) - .build(); - - - public static Stairs.Shape adapt(org.bukkit.block.data.type.Stairs.Shape shape) { - switch(shape) { - case STRAIGHT: - return Stairs.Shape.STRAIGHT; - case INNER_LEFT: - return Stairs.Shape.INNER_LEFT; - case OUTER_LEFT: - return Stairs.Shape.OUTER_LEFT; - case INNER_RIGHT: - return Stairs.Shape.INNER_RIGHT; - case OUTER_RIGHT: - return Stairs.Shape.OUTER_RIGHT; - default: - throw new IllegalStateException(); - } - } - - public static BlockData adapt(org.bukkit.block.data.BlockData data) { - return BukkitBlockData.newInstance(data); - } - - public static org.bukkit.block.data.BlockData adapt(BlockData data) { - return ((BukkitBlockData) data).getHandle(); - } - - public static Axis adapt(org.bukkit.Axis axis) { - switch(axis) { - case X: - return Axis.X; - case Y: - return Axis.Y; - case Z: - return Axis.Z; - default: - throw new IllegalStateException(); - } - } - - public static Bisected.Half adapt(org.bukkit.block.data.Bisected.Half half) { - switch(half) { - case BOTTOM: - return Bisected.Half.BOTTOM; - case TOP: - return Bisected.Half.TOP; - default: - throw new IllegalStateException(); - } - } - - public static BlockFace adapt(org.bukkit.block.BlockFace face) { - switch(face) { - case DOWN: - return BlockFace.DOWN; - case UP: - return BlockFace.UP; - case NORTH_WEST: - return BlockFace.NORTH_WEST; - case NORTH_EAST: - return BlockFace.NORTH_EAST; - case SOUTH_EAST: - return BlockFace.SOUTH_EAST; - case SOUTH_WEST: - return BlockFace.SOUTH_WEST; - case NORTH_NORTH_WEST: - return BlockFace.NORTH_NORTH_WEST; - case WEST_NORTH_WEST: - return BlockFace.WEST_NORTH_WEST; - case WEST_SOUTH_WEST: - return BlockFace.WEST_SOUTH_WEST; - case SOUTH_SOUTH_WEST: - return BlockFace.SOUTH_SOUTH_WEST; - case EAST_NORTH_EAST: - return BlockFace.EAST_NORTH_EAST; - case WEST: - return BlockFace.WEST; - case SOUTH: - return BlockFace.SOUTH; - case EAST: - return BlockFace.EAST; - case NORTH: - return BlockFace.NORTH; - case SELF: - return BlockFace.SELF; - case EAST_SOUTH_EAST: - return BlockFace.EAST_SOUTH_EAST; - case NORTH_NORTH_EAST: - return BlockFace.NORTH_NORTH_EAST; - case SOUTH_SOUTH_EAST: - return BlockFace.SOUTH_SOUTH_EAST; - default: - throw new IllegalStateException(); - } - } - - public static Slab.Type adapt(org.bukkit.block.data.type.Slab.Type type) { - switch(type) { - case BOTTOM: - return Slab.Type.BOTTOM; - case TOP: - return Slab.Type.TOP; - case DOUBLE: - return Slab.Type.DOUBLE; - default: - throw new IllegalStateException(); - } - } - - public static RedstoneWire.Connection adapt(org.bukkit.block.data.type.RedstoneWire.Connection connection) { - switch(connection) { - case NONE: - return RedstoneWire.Connection.NONE; - case UP: - return RedstoneWire.Connection.UP; - case SIDE: - return RedstoneWire.Connection.SIDE; - default: - throw new IllegalStateException(); - } - } - - public static org.bukkit.block.data.type.RedstoneWire.Connection adapt(RedstoneWire.Connection connection) { - switch(connection) { - case SIDE: - return org.bukkit.block.data.type.RedstoneWire.Connection.SIDE; - case UP: - return org.bukkit.block.data.type.RedstoneWire.Connection.UP; - case NONE: - return org.bukkit.block.data.type.RedstoneWire.Connection.NONE; - default: - throw new IllegalStateException(); - } - } - - public static org.bukkit.block.data.type.Stairs.Shape adapt(Stairs.Shape shape) { - switch(shape) { - case STRAIGHT: - return org.bukkit.block.data.type.Stairs.Shape.STRAIGHT; - case INNER_LEFT: - return org.bukkit.block.data.type.Stairs.Shape.INNER_LEFT; - case OUTER_LEFT: - return org.bukkit.block.data.type.Stairs.Shape.OUTER_LEFT; - case INNER_RIGHT: - return org.bukkit.block.data.type.Stairs.Shape.INNER_RIGHT; - case OUTER_RIGHT: - return org.bukkit.block.data.type.Stairs.Shape.OUTER_RIGHT; - default: - throw new IllegalStateException(); - } - } - - public static Rail.Shape adapt(org.bukkit.block.data.Rail.Shape shape) { - switch(shape) { - case SOUTH_WEST: - return Rail.Shape.SOUTH_WEST; - case SOUTH_EAST: - return Rail.Shape.SOUTH_EAST; - case NORTH_EAST: - return Rail.Shape.NORTH_EAST; - case NORTH_WEST: - return Rail.Shape.NORTH_WEST; - case ASCENDING_EAST: - return Rail.Shape.ASCENDING_EAST; - case ASCENDING_WEST: - return Rail.Shape.ASCENDING_WEST; - case ASCENDING_SOUTH: - return Rail.Shape.ASCENDING_SOUTH; - case ASCENDING_NORTH: - return Rail.Shape.ASCENDING_NORTH; - case NORTH_SOUTH: - return Rail.Shape.NORTH_SOUTH; - case EAST_WEST: - return Rail.Shape.EAST_WEST; - default: - throw new IllegalStateException(); - } - } - - public static org.bukkit.block.data.Rail.Shape adapt(Rail.Shape shape) { - switch(shape) { - case EAST_WEST: - return org.bukkit.block.data.Rail.Shape.EAST_WEST; - case NORTH_SOUTH: - return org.bukkit.block.data.Rail.Shape.NORTH_SOUTH; - case ASCENDING_NORTH: - return org.bukkit.block.data.Rail.Shape.ASCENDING_NORTH; - case ASCENDING_SOUTH: - return org.bukkit.block.data.Rail.Shape.ASCENDING_SOUTH; - case ASCENDING_WEST: - return org.bukkit.block.data.Rail.Shape.ASCENDING_WEST; - case ASCENDING_EAST: - return org.bukkit.block.data.Rail.Shape.ASCENDING_EAST; - case NORTH_WEST: - return org.bukkit.block.data.Rail.Shape.NORTH_WEST; - case NORTH_EAST: - return org.bukkit.block.data.Rail.Shape.NORTH_EAST; - case SOUTH_EAST: - return org.bukkit.block.data.Rail.Shape.SOUTH_EAST; - case SOUTH_WEST: - return org.bukkit.block.data.Rail.Shape.SOUTH_WEST; - default: - throw new IllegalStateException(); - } - } - - - public static org.bukkit.block.data.Bisected.Half adapt(Bisected.Half half) { - switch(half) { - case TOP: - return org.bukkit.block.data.Bisected.Half.TOP; - case BOTTOM: - return org.bukkit.block.data.Bisected.Half.BOTTOM; - default: - throw new IllegalStateException(); - } - } - - public static org.bukkit.Axis adapt(Axis axis) { - switch(axis) { - case Z: - return org.bukkit.Axis.Z; - case Y: - return org.bukkit.Axis.Y; - case X: - return org.bukkit.Axis.X; - default: - throw new IllegalStateException(); - } - } - - public static org.bukkit.block.BlockFace adapt(BlockFace face) { - switch(face) { - case DOWN: - return org.bukkit.block.BlockFace.DOWN; - case UP: - return org.bukkit.block.BlockFace.UP; - case NORTH_WEST: - return org.bukkit.block.BlockFace.NORTH_WEST; - case NORTH_EAST: - return org.bukkit.block.BlockFace.NORTH_EAST; - case SOUTH_EAST: - return org.bukkit.block.BlockFace.SOUTH_EAST; - case SOUTH_WEST: - return org.bukkit.block.BlockFace.SOUTH_WEST; - case NORTH_NORTH_WEST: - return org.bukkit.block.BlockFace.NORTH_NORTH_WEST; - case WEST_NORTH_WEST: - return org.bukkit.block.BlockFace.WEST_NORTH_WEST; - case WEST_SOUTH_WEST: - return org.bukkit.block.BlockFace.WEST_SOUTH_WEST; - case SOUTH_SOUTH_WEST: - return org.bukkit.block.BlockFace.SOUTH_SOUTH_WEST; - case EAST_NORTH_EAST: - return org.bukkit.block.BlockFace.EAST_NORTH_EAST; - case WEST: - return org.bukkit.block.BlockFace.WEST; - case SOUTH: - return org.bukkit.block.BlockFace.SOUTH; - case EAST: - return org.bukkit.block.BlockFace.EAST; - case NORTH: - return org.bukkit.block.BlockFace.NORTH; - case SELF: - return org.bukkit.block.BlockFace.SELF; - case EAST_SOUTH_EAST: - return org.bukkit.block.BlockFace.EAST_SOUTH_EAST; - case NORTH_NORTH_EAST: - return org.bukkit.block.BlockFace.NORTH_NORTH_EAST; - case SOUTH_SOUTH_EAST: - return org.bukkit.block.BlockFace.SOUTH_SOUTH_EAST; - default: - throw new IllegalStateException(); - } - } - - public static org.bukkit.block.data.type.Slab.Type adapt(Slab.Type type) { - switch(type) { - case TOP: - return org.bukkit.block.data.type.Slab.Type.TOP; - case DOUBLE: - return org.bukkit.block.data.type.Slab.Type.DOUBLE; - case BOTTOM: - return org.bukkit.block.data.type.Slab.Type.BOTTOM; - default: - throw new IllegalStateException(); - } - } - - public static Location adapt(com.dfsek.terra.api.math.vector.Location location) { - return new Location(((BukkitWorld) location.getWorld()).getHandle(), location.getX(), location.getY(), location.getZ()); - } - - public static com.dfsek.terra.api.math.vector.Location adapt(Location location) { - return new com.dfsek.terra.api.math.vector.Location(adapt(location.getWorld()), location.getX(), location.getY(), location.getZ()); - } - - public static Vector adapt(Vector3 vector3) { - return new Vector(vector3.getX(), vector3.getY(), vector3.getZ()); - } - - public static Vector3 adapt(Vector vector) { - return new Vector3(vector.getX(), vector.getY(), vector.getZ()); - } - - public static CommandSender adapt(org.bukkit.command.CommandSender sender) { - if(sender instanceof Player) return new BukkitPlayer((Player) sender); - if(sender instanceof Entity) return new BukkitEntity((Entity) sender); - return new BukkitCommandSender(sender); - } - - public static org.bukkit.command.CommandSender adapt(CommandSender sender) { - return ((BukkitCommandSender) sender).getHandle(); - } - - public static World adapt(org.bukkit.World world) { - return new BukkitWorld(world); - } - - public static org.bukkit.World adapt(World world) { - return (org.bukkit.World) world.getHandle(); - } - - public static Chunk adapt(org.bukkit.Chunk chunk) { - return new BukkitChunk(chunk); - } - - public static org.bukkit.Chunk adapt(Chunk chunk) { - return (org.bukkit.Chunk) chunk.getHandle(); - } - - public static Enchantment adapt(org.bukkit.enchantments.Enchantment enchantment) { - return new BukkitEnchantment(enchantment); - } - - public static org.bukkit.enchantments.Enchantment adapt(Enchantment enchantment) { - return ((BukkitEnchantment) enchantment).getHandle(); - } - - public static Player adapt(com.dfsek.terra.api.platform.entity.Player player) { - return ((BukkitPlayer) player).getHandle(); - } - - public static com.dfsek.terra.api.platform.entity.Player adapt(Player player) { - return new BukkitPlayer(player); - } - - public static BukkitBlockTypeAndItem adapt(Material material) { - return new BukkitBlockTypeAndItem(material); - } - - public static Material adapt(BlockType type) { - return ((BukkitBlockTypeAndItem) type).getHandle(); - } - - public static ItemStack adapt(org.bukkit.inventory.ItemStack in) { - return new BukkitItemStack(in); - } - - public static org.bukkit.inventory.ItemStack adapt(ItemStack in) { - return ((BukkitItemStack) in).getHandle(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiome.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiome.java deleted file mode 100644 index 843268183..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiome.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.bukkit.world; - -import com.dfsek.terra.api.platform.world.Biome; - -public class BukkitBiome implements Biome { - private final org.bukkit.block.Biome biome; - - public BukkitBiome(org.bukkit.block.Biome biome) { - this.biome = biome; - } - - @Override - public org.bukkit.block.Biome getHandle() { - return biome; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiomeGrid.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiomeGrid.java deleted file mode 100644 index 9f3b91a23..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitBiomeGrid.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dfsek.terra.bukkit.world; - -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.platform.world.BiomeGrid; -import org.bukkit.generator.ChunkGenerator; -import org.jetbrains.annotations.NotNull; - -@SuppressWarnings("deprecation") -public class BukkitBiomeGrid implements BiomeGrid { - private final ChunkGenerator.BiomeGrid delegate; - - public BukkitBiomeGrid(ChunkGenerator.BiomeGrid biomeGrid) { - this.delegate = biomeGrid; - } - - @Override - public ChunkGenerator.BiomeGrid getHandle() { - return delegate; - } - - @Override - public @NotNull Biome getBiome(int x, int z) { - return new BukkitBiome(delegate.getBiome(x, z)); - } - - @Override - public @NotNull Biome getBiome(int x, int y, int z) { - return new BukkitBiome(delegate.getBiome(x, y, z)); - } - - @Override - public void setBiome(int x, int z, @NotNull Biome bio) { - delegate.setBiome(x, z, ((BukkitBiome) bio).getHandle()); - } - - @Override - public void setBiome(int x, int y, int z, @NotNull Biome bio) { - delegate.setBiome(x, y, z, ((BukkitBiome) bio).getHandle()); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitChunk.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitChunk.java deleted file mode 100644 index e27f02ab6..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitChunk.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.dfsek.terra.bukkit.world; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.bukkit.world.block.BukkitBlock; -import org.jetbrains.annotations.NotNull; - -public class BukkitChunk implements Chunk { - private final org.bukkit.Chunk delegate; - - public BukkitChunk(org.bukkit.Chunk delegate) { - this.delegate = delegate; - } - - @Override - public int getX() { - return delegate.getX(); - } - - @Override - public int getZ() { - return delegate.getZ(); - } - - @Override - public World getWorld() { - return BukkitAdapter.adapt(delegate.getWorld()); - } - - @Override - public Block getBlock(int x, int y, int z) { - return new BukkitBlock(delegate.getBlock(x, y, z)); - } - - @Override - public org.bukkit.Chunk getHandle() { - return delegate; - } - - @Override - public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { - delegate.getBlock(x, y, z).setBlockData(BukkitAdapter.adapt(blockData)); - } - - @Override - public @NotNull BlockData getBlockData(int x, int y, int z) { - return getBlock(x, y, z).getBlockData(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitTree.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitTree.java deleted file mode 100644 index f7ba8e93f..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitTree.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.dfsek.terra.bukkit.world; - -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.profiler.ProfileFrame; -import org.bukkit.TreeType; - -import java.util.Locale; -import java.util.Random; - -public class BukkitTree implements Tree { - private final TreeType delegate; - private final MaterialSet spawnable; - private final TerraPlugin main; - - public BukkitTree(TreeType delegate, TerraPlugin main) { - this.delegate = delegate; - this.main = main; - this.spawnable = getSpawnable(delegate); - } - - private MaterialSet getSpawnable(TreeType type) { - WorldHandle handle = main.getWorldHandle(); - switch(type) { - case CRIMSON_FUNGUS: - return MaterialSet.get(handle.createBlockData("minecraft:crimson_nylium")); - case WARPED_FUNGUS: - return MaterialSet.get(handle.createBlockData("minecraft:warped_nylium")); - case BROWN_MUSHROOM: - case RED_MUSHROOM: - return MaterialSet.get(handle.createBlockData("minecraft:mycelium"), handle.createBlockData("minecraft:grass_block"), - handle.createBlockData("minecraft:podzol")); - case CHORUS_PLANT: - return MaterialSet.get(handle.createBlockData("minecraft:end_stone")); - default: - return MaterialSet.get(handle.createBlockData("minecraft:grass_block"), handle.createBlockData("minecraft:dirt"), - handle.createBlockData("minecraft:podzol")); - } - } - - @Override - @SuppressWarnings("try") - public boolean plant(Location l, Random r) { - try(ProfileFrame ignore = main.getProfiler().profile("bukkit_tree:" + delegate.toString().toLowerCase(Locale.ROOT))) { - return ((BukkitWorld) l.getWorld()).getHandle().generateTree(BukkitAdapter.adapt(l), delegate); - } catch(IndexOutOfBoundsException ignored) { // Workaround for https://github.com/PaperMC/Paper/issues/6028 - return false; - } - } - - @Override - public MaterialSet getSpawnable() { - return spawnable; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java deleted file mode 100644 index 158041ae5..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorld.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.dfsek.terra.bukkit.world; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.bukkit.BukkitEntity; -import com.dfsek.terra.bukkit.generator.BukkitChunkGenerator; -import com.dfsek.terra.bukkit.world.block.BukkitBlock; -import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; - -import java.io.File; -import java.util.UUID; - -public class BukkitWorld implements World { - private final org.bukkit.World delegate; - - public BukkitWorld(org.bukkit.World delegate) { - this.delegate = delegate; - } - - @Override - public long getSeed() { - return delegate.getSeed(); - } - - @Override - public int getMaxHeight() { - return delegate.getMaxHeight(); - } - - @Override - public ChunkGenerator getGenerator() { - return new BukkitChunkGenerator(delegate.getGenerator()); - } - - public String getName() { - return delegate.getName(); - } - - public UUID getUID() { - return delegate.getUID(); - } - - public boolean isChunkGenerated(int x, int z) { - return delegate.isChunkGenerated(x, z); - } - - @Override - public Chunk getChunkAt(int x, int z) { - return BukkitAdapter.adapt(delegate.getChunkAt(x, z)); - } - - public File getWorldFolder() { - return delegate.getWorldFolder(); - } - - @Override - public Block getBlockAt(int x, int y, int z) { - return new BukkitBlock(delegate.getBlockAt(x, y, z)); - } - - @Override - public Entity spawnEntity(Location location, EntityType entityType) { - return new BukkitEntity(delegate.spawnEntity(BukkitAdapter.adapt(location), ((BukkitEntityType) entityType).getHandle())); - } - - @Override - public int getMinHeight() { - return delegate.getMinHeight(); - } - - @Override - public org.bukkit.World getHandle() { - return delegate; - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof BukkitWorld)) return false; - BukkitWorld other = (BukkitWorld) obj; - return other.getHandle().equals(delegate); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public String toString() { - return delegate.toString(); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlock.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlock.java deleted file mode 100644 index dcf49acdd..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/BukkitBlock.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.dfsek.terra.bukkit.world.block; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; -import com.dfsek.terra.bukkit.world.block.state.BukkitBlockState; - -public class BukkitBlock implements Block { - private final org.bukkit.block.Block delegate; - - public BukkitBlock(org.bukkit.block.Block delegate) { - this.delegate = delegate; - } - - @Override - public void setBlockData(BlockData data, boolean physics) { - delegate.setBlockData(((BukkitBlockData) data).getHandle(), physics); - } - - @Override - public BlockData getBlockData() { - return BukkitBlockData.newInstance(delegate.getBlockData()); - } - - @Override - public BlockState getState() { - return BukkitBlockState.newInstance(delegate.getState()); - } - - @Override - public Block getRelative(BlockFace face) { - return new BukkitBlock(delegate.getRelative(BukkitAdapter.adapt(face))); - } - - @Override - public Block getRelative(BlockFace face, int len) { - return new BukkitBlock(delegate.getRelative(BukkitAdapter.adapt(face), len)); - } - - @Override - public boolean isEmpty() { - return delegate.isEmpty(); - } - - @Override - public Location getLocation() { - return BukkitAdapter.adapt(delegate.getLocation()); - } - - @Override - public BlockType getType() { - return BukkitAdapter.adapt(delegate.getType()); - } - - @Override - public int getX() { - return delegate.getX(); - } - - @Override - public int getZ() { - return delegate.getZ(); - } - - @Override - public int getY() { - return delegate.getY(); - } - - @Override - public boolean isPassable() { - return delegate.isPassable(); - } - - @Override - public org.bukkit.block.Block getHandle() { - return delegate; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitAnaloguePowerable.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitAnaloguePowerable.java deleted file mode 100644 index 71cd99513..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitAnaloguePowerable.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.data.AnaloguePowerable; - -public class BukkitAnaloguePowerable extends BukkitBlockData implements AnaloguePowerable { - public BukkitAnaloguePowerable(org.bukkit.block.data.AnaloguePowerable delegate) { - super(delegate); - } - - @Override - public int getMaximumPower() { - return ((org.bukkit.block.data.AnaloguePowerable) getHandle()).getMaximumPower(); - } - - @Override - public int getPower() { - return ((org.bukkit.block.data.AnaloguePowerable) getHandle()).getPower(); - } - - @Override - public void setPower(int power) { - ((org.bukkit.block.data.AnaloguePowerable) getHandle()).setPower(power); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockData.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockData.java deleted file mode 100644 index e0dffe72b..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockData.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.bukkit.TerraBukkitPlugin; -import com.dfsek.terra.bukkit.world.BukkitAdapter; -import org.bukkit.Material; -import org.bukkit.block.data.AnaloguePowerable; -import org.bukkit.block.data.Directional; -import org.bukkit.block.data.MultipleFacing; -import org.bukkit.block.data.Orientable; -import org.bukkit.block.data.Rail; -import org.bukkit.block.data.Rotatable; -import org.bukkit.block.data.Waterlogged; -import org.bukkit.block.data.type.RedstoneWire; -import org.bukkit.block.data.type.Slab; -import org.bukkit.block.data.type.Stairs; -import org.bukkit.block.data.type.Wall; - -public class BukkitBlockData implements BlockData { - private org.bukkit.block.data.BlockData delegate; - - protected BukkitBlockData(org.bukkit.block.data.BlockData delegate) { - this.delegate = delegate; - } - - public static BukkitBlockData newInstance(org.bukkit.block.data.BlockData bukkitData) { - - if(bukkitData instanceof Rail) return new BukkitRail((Rail) bukkitData); - if(bukkitData instanceof Stairs) return new BukkitStairs((Stairs) bukkitData); - if(bukkitData instanceof Slab) return new BukkitSlab((Slab) bukkitData); - if(TerraBukkitPlugin.BUKKIT_VERSION.above(TerraBukkitPlugin.BukkitVersion.V1_16) && bukkitData instanceof Wall) { // Wall only exists on 1.16 and up. - return new BukkitWall((Wall) bukkitData); - } - - if(bukkitData instanceof RedstoneWire) return new BukkitRedstoneWire((RedstoneWire) bukkitData); - if(bukkitData instanceof AnaloguePowerable) return new BukkitAnaloguePowerable((AnaloguePowerable) bukkitData); - - if(bukkitData instanceof MultipleFacing) return new BukkitMultipleFacing((MultipleFacing) bukkitData); - if(bukkitData instanceof Rotatable) return new BukkitRotatable((Rotatable) bukkitData); - if(bukkitData instanceof Directional) return new BukkitDirectional((Directional) bukkitData); - if(bukkitData instanceof Orientable) return new BukkitOrientable((Orientable) bukkitData); - - if(bukkitData instanceof Waterlogged) return new BukkitWaterlogged((Waterlogged) bukkitData); - - return new BukkitBlockData(bukkitData); - } - - - @Override - public org.bukkit.block.data.BlockData getHandle() { - return delegate; - } - - @Override - public BlockType getBlockType() { - return BukkitAdapter.adapt(delegate.getMaterial()); - } - - @Override - public boolean matches(BlockData data) { - return delegate.getMaterial() == ((BukkitBlockData) data).getHandle().getMaterial(); - } - - @Override - public BukkitBlockData clone() { - try { - BukkitBlockData n = (BukkitBlockData) super.clone(); - n.delegate = delegate.clone(); - return n; - } catch(CloneNotSupportedException e) { - throw new Error(e); - } - } - - @Override - public String getAsString() { - return delegate.getAsString(false); - } - - @Override - public boolean isAir() { - return delegate.getMaterial().isAir(); - } - - @Override - public boolean isStructureVoid() { - return delegate.getMaterial() == Material.STRUCTURE_VOID; - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitDirectional.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitDirectional.java deleted file mode 100644 index 13d610774..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitDirectional.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Directional; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -public class BukkitDirectional extends BukkitBlockData implements Directional { - public BukkitDirectional(org.bukkit.block.data.Directional delegate) { - super(delegate); - } - - @Override - public BlockFace getFacing() { - return BukkitAdapter.adapt(((org.bukkit.block.data.Directional) getHandle()).getFacing()); - } - - @Override - public void setFacing(BlockFace facing) { - ((org.bukkit.block.data.Directional) getHandle()).setFacing(BukkitAdapter.adapt(facing)); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitMultipleFacing.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitMultipleFacing.java deleted file mode 100644 index 4e01a62f3..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitMultipleFacing.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.MultipleFacing; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -import java.util.Set; -import java.util.stream.Collectors; - -public class BukkitMultipleFacing extends BukkitBlockData implements MultipleFacing { - - public BukkitMultipleFacing(org.bukkit.block.data.MultipleFacing delegate) { - super(delegate); - } - - @Override - public Set getFaces() { - return ((org.bukkit.block.data.MultipleFacing) super.getHandle()).getFaces().stream().map(BukkitAdapter::adapt).collect(Collectors.toSet()); - } - - @Override - public void setFace(BlockFace face, boolean facing) { - ((org.bukkit.block.data.MultipleFacing) super.getHandle()).setFace(BukkitAdapter.adapt(face), facing); - } - - @Override - public Set getAllowedFaces() { - return ((org.bukkit.block.data.MultipleFacing) super.getHandle()).getAllowedFaces().stream().map(BukkitAdapter::adapt).collect(Collectors.toSet()); - } - - @Override - public boolean hasFace(BlockFace f) { - return ((org.bukkit.block.data.MultipleFacing) super.getHandle()).hasFace(BukkitAdapter.adapt(f)); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitOrientable.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitOrientable.java deleted file mode 100644 index c6cfdca18..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitOrientable.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.Axis; -import com.dfsek.terra.api.platform.block.data.Orientable; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -import java.util.Set; -import java.util.stream.Collectors; - -public class BukkitOrientable extends BukkitBlockData implements Orientable { - - public BukkitOrientable(org.bukkit.block.data.Orientable delegate) { - super(delegate); - } - - @Override - public Set getAxes() { - return ((org.bukkit.block.data.Orientable) getHandle()).getAxes().stream().map(BukkitAdapter::adapt).collect(Collectors.toSet()); - } - - @Override - public Axis getAxis() { - return BukkitAdapter.adapt(((org.bukkit.block.data.Orientable) getHandle()).getAxis()); - } - - @Override - public void setAxis(Axis axis) { - ((org.bukkit.block.data.Orientable) getHandle()).setAxis(BukkitAdapter.adapt(axis)); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRail.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRail.java deleted file mode 100644 index ae85d2b76..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRail.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.data.Rail; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -public class BukkitRail extends BukkitBlockData implements Rail { - public BukkitRail(org.bukkit.block.data.Rail delegate) { - super(delegate); - } - - @Override - public Shape getShape() { - return BukkitAdapter.adapt(((org.bukkit.block.data.Rail) getHandle()).getShape()); - } - - @Override - public void setShape(Shape newShape) { - ((org.bukkit.block.data.Rail) getHandle()).setShape(BukkitAdapter.adapt(newShape)); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRedstoneWire.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRedstoneWire.java deleted file mode 100644 index 708c1316b..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRedstoneWire.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.RedstoneWire; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -import java.util.Set; -import java.util.stream.Collectors; - -public class BukkitRedstoneWire extends BukkitAnaloguePowerable implements RedstoneWire { - public BukkitRedstoneWire(org.bukkit.block.data.type.RedstoneWire delegate) { - super(delegate); - } - - @Override - public Set getAllowedFaces() { - return ((org.bukkit.block.data.type.RedstoneWire) getHandle()).getAllowedFaces().stream().map(BukkitAdapter::adapt).collect(Collectors.toSet()); - } - - @Override - public Connection getFace(BlockFace face) { - return BukkitAdapter.adapt(((org.bukkit.block.data.type.RedstoneWire) getHandle()).getFace(BukkitAdapter.adapt(face))); - } - - @Override - public void setFace(BlockFace face, Connection connection) { - ((org.bukkit.block.data.type.RedstoneWire) getHandle()).setFace(BukkitAdapter.adapt(face), BukkitAdapter.adapt(connection)); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRotatable.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRotatable.java deleted file mode 100644 index 0da5c04b9..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitRotatable.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Rotatable; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -public class BukkitRotatable extends BukkitBlockData implements Rotatable { - public BukkitRotatable(org.bukkit.block.data.Rotatable delegate) { - super(delegate); - } - - @Override - public BlockFace getRotation() { - return BukkitAdapter.adapt(((org.bukkit.block.data.Rotatable) getHandle()).getRotation()); - } - - @Override - public void setRotation(BlockFace face) { - ((org.bukkit.block.data.Rotatable) getHandle()).setRotation(BukkitAdapter.adapt(face)); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitSlab.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitSlab.java deleted file mode 100644 index 6ddf160b3..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitSlab.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.data.Slab; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -public class BukkitSlab extends BukkitWaterlogged implements Slab { - public BukkitSlab(org.bukkit.block.data.type.Slab delegate) { - super(delegate); - } - - @Override - public Type getType() { - return BukkitAdapter.adapt(((org.bukkit.block.data.type.Slab) getHandle()).getType()); - } - - @Override - public void setType(Type type) { - ((org.bukkit.block.data.type.Slab) getHandle()).setType(BukkitAdapter.adapt(type)); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitStairs.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitStairs.java deleted file mode 100644 index c54d4a993..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitStairs.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Stairs; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -public class BukkitStairs extends BukkitBlockData implements Stairs { - - public BukkitStairs(org.bukkit.block.data.type.Stairs delegate) { - super(delegate); - } - - @Override - public Shape getShape() { - return BukkitAdapter.adapt(((org.bukkit.block.data.type.Stairs) super.getHandle()).getShape()); - } - - @Override - public void setShape(Shape shape) { - ((org.bukkit.block.data.type.Stairs) super.getHandle()).setShape(BukkitAdapter.adapt(shape)); - } - - @Override - public Half getHalf() { - return BukkitAdapter.adapt(((org.bukkit.block.data.type.Stairs) super.getHandle()).getHalf()); - } - - @Override - public void setHalf(Half half) { - ((org.bukkit.block.data.type.Stairs) super.getHandle()).setHalf(BukkitAdapter.adapt(half)); - } - - @Override - public BlockFace getFacing() { - return BukkitAdapter.adapt(((org.bukkit.block.data.type.Stairs) super.getHandle()).getFacing()); - } - - @Override - public void setFacing(BlockFace facing) { - ((org.bukkit.block.data.type.Stairs) super.getHandle()).setFacing(BukkitAdapter.adapt(facing)); - } - - @Override - public boolean isWaterlogged() { - return ((org.bukkit.block.data.type.Stairs) super.getHandle()).isWaterlogged(); - } - - @Override - public void setWaterlogged(boolean waterlogged) { - ((org.bukkit.block.data.type.Stairs) super.getHandle()).setWaterlogged(waterlogged); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWall.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWall.java deleted file mode 100644 index 2addb83b7..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWall.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Wall; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - -public class BukkitWall extends BukkitWaterlogged implements Wall { - public BukkitWall(org.bukkit.block.data.type.Wall delegate) { - super(delegate); - } - - @Override - public boolean isUp() { - return ((org.bukkit.block.data.type.Wall) getHandle()).isUp(); - } - - @Override - public void setUp(boolean up) { - ((org.bukkit.block.data.type.Wall) getHandle()).setUp(up); - } - - public static org.bukkit.block.data.type.Wall.Height adapt(com.dfsek.terra.api.platform.block.data.Wall.Height height) { - switch(height) { - case NONE: - return org.bukkit.block.data.type.Wall.Height.NONE; - case LOW: - return org.bukkit.block.data.type.Wall.Height.LOW; - case TALL: - return org.bukkit.block.data.type.Wall.Height.TALL; - default: - throw new IllegalStateException(); - } - } - - public static com.dfsek.terra.api.platform.block.data.Wall.Height adapt(org.bukkit.block.data.type.Wall.Height height) { - switch(height) { - case TALL: - return com.dfsek.terra.api.platform.block.data.Wall.Height.TALL; - case LOW: - return com.dfsek.terra.api.platform.block.data.Wall.Height.LOW; - case NONE: - return com.dfsek.terra.api.platform.block.data.Wall.Height.NONE; - default: - throw new IllegalStateException(); - } - } - - @Override - public void setHeight(BlockFace face, Height height) { - ((org.bukkit.block.data.type.Wall) getHandle()).setHeight(BukkitAdapter.adapt(face), adapt(height)); - } - - @Override - public Height getHeight(BlockFace face) { - return adapt(((org.bukkit.block.data.type.Wall) getHandle()).getHeight(BukkitAdapter.adapt(face))); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWaterlogged.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWaterlogged.java deleted file mode 100644 index b75c6c170..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitWaterlogged.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.data; - -import com.dfsek.terra.api.platform.block.data.Waterlogged; - -public class BukkitWaterlogged extends BukkitBlockData implements Waterlogged { - public BukkitWaterlogged(org.bukkit.block.data.Waterlogged delegate) { - super(delegate); - } - - @Override - public boolean isWaterlogged() { - return ((org.bukkit.block.data.Waterlogged) super.getHandle()).isWaterlogged(); - } - - @Override - public void setWaterlogged(boolean waterlogged) { - ((org.bukkit.block.data.Waterlogged) super.getHandle()).setWaterlogged(waterlogged); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitBlockState.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitBlockState.java deleted file mode 100644 index c96c520de..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitBlockState.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.state; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.bukkit.world.block.BukkitBlock; -import com.dfsek.terra.bukkit.world.block.data.BukkitBlockData; -import org.bukkit.block.Container; -import org.bukkit.block.CreatureSpawner; -import org.bukkit.block.Sign; - -public class BukkitBlockState implements BlockState { - private final org.bukkit.block.BlockState delegate; - - protected BukkitBlockState(org.bukkit.block.BlockState block) { - this.delegate = block; - } - - public static BukkitBlockState newInstance(org.bukkit.block.BlockState block) { - if(block instanceof Container) return new BukkitContainer((Container) block); - if(block instanceof Sign) return new BukkitSign((Sign) block); - if(block instanceof CreatureSpawner) return new BukkitMobSpawner((CreatureSpawner) block); - return new BukkitBlockState(block); - } - - @Override - public org.bukkit.block.BlockState getHandle() { - return delegate; - } - - @Override - public Block getBlock() { - return new BukkitBlock(delegate.getBlock()); - } - - @Override - public int getX() { - return delegate.getX(); - } - - @Override - public int getY() { - return delegate.getY(); - } - - @Override - public int getZ() { - return delegate.getZ(); - } - - @Override - public BlockData getBlockData() { - return BukkitBlockData.newInstance(delegate.getBlockData()); - } - - @Override - public boolean update(boolean applyPhysics) { - return delegate.update(true, applyPhysics); - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java deleted file mode 100644 index cdb1fe636..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitContainer.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.bukkit.world.block.state; - -import com.dfsek.terra.api.platform.block.state.Container; -import com.dfsek.terra.api.platform.inventory.Inventory; -import com.dfsek.terra.bukkit.world.inventory.BukkitInventory; - -public class BukkitContainer extends BukkitBlockState implements Container { - - protected BukkitContainer(org.bukkit.block.Container block) { - super(block); - } - - @Override - public Inventory getInventory() { - return new BukkitInventory(((org.bukkit.block.Container) getHandle()).getInventory()); - } - - @Override - public boolean update(boolean applyPhysics) { - return false; // This clears the inventory. we don't want that. - } -} diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/entity/BukkitEntityType.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/entity/BukkitEntityType.java deleted file mode 100644 index 280ebc5b4..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/entity/BukkitEntityType.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.bukkit.world.entity; - -import com.dfsek.terra.api.platform.entity.EntityType; - -public class BukkitEntityType implements EntityType { - private final org.bukkit.entity.EntityType delegate; - - public BukkitEntityType(org.bukkit.entity.EntityType delegate) { - this.delegate = delegate; - } - - @Override - public org.bukkit.entity.EntityType getHandle() { - return delegate; - } -} diff --git a/platforms/bukkit/src/main/resources/world.yml b/platforms/bukkit/src/main/resources/world.yml deleted file mode 100644 index 8b1378917..000000000 --- a/platforms/bukkit/src/main/resources/world.yml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/platforms/cli/build.gradle.kts b/platforms/cli/build.gradle.kts new file mode 100644 index 000000000..36eb49cdf --- /dev/null +++ b/platforms/cli/build.gradle.kts @@ -0,0 +1,24 @@ +repositories { + maven { url = uri("https://jitpack.io/") } +} + +dependencies { + shadedApi("commons-io:commons-io:2.7") + shadedApi("com.github.Querz:NBT:6.1") + shadedApi(project(":common:implementation:base")) + + shadedImplementation("com.google.guava:guava:31.0.1-jre") + + shadedImplementation("ch.qos.logback:logback-classic:1.2.9") + + implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) +} + +tasks.withType() { + entryCompression = ZipEntryCompression.STORED + manifest { + attributes( + "Main-Class" to "com.dfsek.terra.cli.TerraCLI", + ) + } +} \ No newline at end of file diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/CLIPlatform.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/CLIPlatform.java new file mode 100644 index 000000000..4a73c53ee --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/CLIPlatform.java @@ -0,0 +1,61 @@ +package com.dfsek.terra.cli; + +import com.dfsek.tectonic.api.TypeRegistry; +import com.dfsek.tectonic.api.loader.type.TypeLoader; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; + +import com.dfsek.terra.AbstractPlatform; +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.api.world.biome.PlatformBiome; +import com.dfsek.terra.cli.handle.CLIItemHandle; +import com.dfsek.terra.cli.handle.CLIWorldHandle; + + +public class CLIPlatform extends AbstractPlatform { + private static final Logger LOGGER = LoggerFactory.getLogger(CLIPlatform.class); + + private final CLIWorldHandle worldHandle = new CLIWorldHandle(); + private final CLIItemHandle itemHandle = new CLIItemHandle(); + + public CLIPlatform() { + LOGGER.info("Root directory: {}", getDataFolder().getAbsoluteFile()); + load(); + LOGGER.info("Initialized Terra platform."); + } + + @Override + public boolean reload() { + return false; + } + + @Override + public @NotNull String platformName() { + return "CLI"; + } + + @Override + public @NotNull WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public @NotNull File getDataFolder() { + return new File("./"); + } + + @Override + public @NotNull ItemHandle getItemHandle() { + return itemHandle; + } + + @Override + public void register(TypeRegistry registry) { + super.register(registry); + registry.registerLoader(PlatformBiome.class, (TypeLoader) (annotatedType, o, configLoader, depthTracker) -> () -> o); + } +} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/NBTSerializable.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/NBTSerializable.java new file mode 100644 index 000000000..0c05a1652 --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/NBTSerializable.java @@ -0,0 +1,5 @@ +package com.dfsek.terra.cli; + +public interface NBTSerializable { + T serialize(); +} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/TerraCLI.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/TerraCLI.java new file mode 100644 index 000000000..39eaf59c6 --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/TerraCLI.java @@ -0,0 +1,45 @@ +package com.dfsek.terra.cli; + +import net.querz.mca.MCAUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.api.util.vector.Vector2Int; +import com.dfsek.terra.cli.world.CLIWorld; + + +public final class TerraCLI { + private static final Logger LOGGER = LoggerFactory.getLogger(TerraCLI.class); + + public static void main(String... args) { + LOGGER.info("Starting Terra CLI..."); + + CLIPlatform platform = new CLIPlatform(); + platform.getEventManager().callEvent(new PlatformInitializationEvent()); + + ConfigPack generate = platform.getConfigRegistry().getByID("OVERWORLD").orElseThrow(); // TODO: make this a cli argument + + CLIWorld world = new CLIWorld(2, 2, 384, -64, generate); + + world.generate(); + + world.serialize().parallel().forEach(mcaFile -> { + Vector2Int pos = mcaFile.getLeft(); + String name = MCAUtil.createNameFromRegionLocation(pos.getX(), pos.getZ()); + LOGGER.info("Writing region ({}, {}) to {}", pos.getX(), pos.getZ(), name); + + try { + MCAUtil.write(mcaFile.getRight(), name); + } catch(IOException e) { + e.printStackTrace(); + } + LOGGER.info("Wrote region to file."); + }); + LOGGER.info("Done."); + System.exit(0); + } +} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/block/CLIBlockState.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/block/CLIBlockState.java new file mode 100644 index 000000000..53cbc5e90 --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/block/CLIBlockState.java @@ -0,0 +1,84 @@ +package com.dfsek.terra.cli.block; + +import net.querz.nbt.tag.CompoundTag; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.block.state.properties.Property; + + +public class CLIBlockState implements BlockState { + private final String value; + private final CLIBlockType type; + private final boolean isAir; + private final CompoundTag nbt; + + public CLIBlockState(String value) { + this.value = value; + if(value.contains("[")) { + + } else { + + } + this.isAir = value.startsWith("minecraft:air"); + this.nbt = new CompoundTag(); + if(value.contains("[")) { + this.type = new CLIBlockType(value.substring(0, value.indexOf("["))); + String properties = value.substring(value.indexOf('[') + 1, value.indexOf(']')); + String[] props = properties.split(","); + CompoundTag pTag = new CompoundTag(); + for(String property : props) { + String name = property.substring(0, property.indexOf('=')); + String val = property.substring(property.indexOf('=') + 1); + + pTag.putString(name, val); + } + this.nbt.put("Properties", pTag); + } else this.type = new CLIBlockType(value); + this.nbt.putString("Name", type.getHandle()); + } + + @Override + public Object getHandle() { + return value; + } + + @Override + public boolean matches(BlockState other) { + return false; + } + + @Override + public > boolean has(Property property) { + return false; + } + + @Override + public > T get(Property property) { + return null; + } + + @Override + public > BlockState set(Property property, T value) { + return null; + } + + @Override + public BlockType getBlockType() { + return type; + } + + @Override + public String getAsString(boolean properties) { + return value; + } + + @Override + public boolean isAir() { + return isAir; + } + + public CompoundTag getNbt() { + return nbt; + } +} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/block/CLIBlockType.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/block/CLIBlockType.java new file mode 100644 index 000000000..361a283da --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/block/CLIBlockType.java @@ -0,0 +1,41 @@ +package com.dfsek.terra.cli.block; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.util.generic.Lazy; + + +public class CLIBlockType implements BlockType { + private final String value; + private final boolean solid; + private final boolean water; + private final Lazy defaultState; + + public CLIBlockType(String value) { + if(value.contains("[")) throw new IllegalArgumentException("Block Type must not contain properties"); + this.value = value; + this.solid = !value.equals("minecraft:air"); + this.water = value.equals("minecraft:water"); + this.defaultState = Lazy.lazy(() -> new CLIBlockState(value)); + } + + @Override + public String getHandle() { + return value; + } + + @Override + public BlockState getDefaultState() { + return defaultState.value(); + } + + @Override + public boolean isSolid() { + return solid; + } + + @Override + public boolean isWater() { + return water; + } +} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/generator/CLIChunkGenerator.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/generator/CLIChunkGenerator.java new file mode 100644 index 000000000..0b58929b3 --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/generator/CLIChunkGenerator.java @@ -0,0 +1,12 @@ +package com.dfsek.terra.cli.generator; + +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; + + +public class CLIChunkGenerator implements GeneratorWrapper { + @Override + public ChunkGenerator getHandle() { + return null; + } +} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/handle/CLIItemHandle.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/handle/CLIItemHandle.java new file mode 100644 index 000000000..719729138 --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/handle/CLIItemHandle.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.cli.handle; + +import java.util.Set; + +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.item.Enchantment; + + +public class CLIItemHandle implements ItemHandle { + @Override + public Item createItem(String data) { + return null; + } + + @Override + public Enchantment getEnchantment(String id) { + return null; + } + + @Override + public Set getEnchantments() { + return null; + } +} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/handle/CLIWorldHandle.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/handle/CLIWorldHandle.java new file mode 100644 index 000000000..a6ec3a0e7 --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/handle/CLIWorldHandle.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.cli.handle; + +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.cli.block.CLIBlockState; + + +public class CLIWorldHandle implements WorldHandle { + private static final CLIBlockState AIR = new CLIBlockState("minecraft:air"); + + public static CLIBlockState getAIR() { + return AIR; + } + + @Override + public @NotNull BlockState createBlockState(@NotNull String data) { + return new CLIBlockState(data); + } + + @Override + public @NotNull BlockState air() { + return AIR; + } + + @Override + public @NotNull EntityType getEntity(@NotNull String id) { + return null; + } +} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java new file mode 100644 index 000000000..c385ff8eb --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/CLIWorld.java @@ -0,0 +1,305 @@ +package com.dfsek.terra.cli.world; + +import com.google.common.collect.Streams; +import net.jafama.FastMath; +import net.querz.mca.MCAFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Stream; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.util.generic.pair.Pair; +import com.dfsek.terra.api.util.vector.Vector2Int; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.cli.NBTSerializable; +import com.dfsek.terra.cli.world.chunk.CLIChunk; + + +public class CLIWorld implements ServerWorld, NBTSerializable>> { + private static final Logger LOGGER = LoggerFactory.getLogger(CLIWorld.class); + private final Region[] regions; + private final Region[] negativeRegions; + private final int size; + private final long seed; + private final int maxHeight; + private final int minHeight; + private final ChunkGenerator chunkGenerator; + private final BiomeProvider biomeProvider; + private final ConfigPack pack; + private final AtomicInteger amount = new AtomicInteger(0); + + private final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() - 1); + + public CLIWorld(int size, + long seed, + int maxHeight, + int minHeight, + ConfigPack pack) { + this.size = size; + this.maxHeight = maxHeight; + this.minHeight = minHeight; + this.seed = seed; + this.chunkGenerator = pack.getGeneratorProvider().newInstance(pack); + this.biomeProvider = pack.getBiomeProvider(); + this.pack = pack; + + + size += 1; + this.regions = new Region[size * size]; + this.negativeRegions = new Region[size * size]; + for(int x = 0; x < size; x++) { + for(int z = 0; z < size; z++) { + regions[x + z * size] = new Region(this, x, z); + negativeRegions[x + z * size] = new Region(this, x, z); + } + } + } + + public void generate() { + int sizeChunks = size * 32; + List> futures = new ArrayList<>(); + final AtomicLong start = new AtomicLong(System.nanoTime()); + for(int x = 0; x < sizeChunks; x++) { + for(int z = 0; z < sizeChunks; z++) { + int finalX = x; + int finalZ = z; + futures.add(executor.submit(() -> { + try { + int num = amount.getAndIncrement(); + CLIChunk chunk = getChunkAt(finalX, finalZ); + chunkGenerator.generateChunkData(chunk, this, pack.getBiomeProvider().caching(this), finalX, finalZ); + CLIProtoWorld protoWorld = new CLIProtoWorld(this, finalX, finalZ); + pack.getStages().forEach(stage -> stage.populate(protoWorld)); + if(num % 240 == 239) { + long time = System.nanoTime(); + double cps = num / ((double) (time - start.get()) / 1000000000); + LOGGER.info("Generating chunk at ({}, {}), generated {} chunks at {}cps", finalX, finalZ, num, cps); + amount.set(0); + start.set(System.nanoTime()); + } + } catch(Exception e) { + e.printStackTrace(); + } + })); + } + } + + for(Future future : futures) { + try { + future.get(); + } catch(InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + } + + @Override + public Object getHandle() { + return this; + } + + @Override + public BlockState getBlockState(int x, int y, int z) { + return getChunkAt(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16)) + .getBlock(FastMath.floorMod(x, 16), y, FastMath.floorMod(z, 16)); + } + + @Override + public BlockEntity getBlockEntity(int x, int y, int z) { + return new BlockEntity() { + @Override + public boolean update(boolean applyPhysics) { + return false; + } + + @Override + public Vector3 getPosition() { + return Vector3.of(x, y, z); + } + + @Override + public int getX() { + return x; + } + + @Override + public int getY() { + return y; + } + + @Override + public int getZ() { + return z; + } + + @Override + public BlockState getBlockState() { + return CLIWorld.this.getBlockState(x, y, z); + } + + @Override + public Object getHandle() { + return this; + } + }; + } + + @Override + public CLIChunk getChunkAt(int x, int z) { + return getRegion(FastMath.floorDiv(x, 32), FastMath.floorDiv(z, 32)) + .get(FastMath.floorMod(x, 32), FastMath.floorMod(z, 32)); + } + + public Region getRegion(int x, int z) { + int key = x + z * size; + if(key >= 0) return regions[key]; + else return negativeRegions[-key]; + } + + @Override + public long getSeed() { + return seed; + } + + @Override + public int getMaxHeight() { + return maxHeight; + } + + @Override + public int getMinHeight() { + return minHeight; + } + + @Override + public ChunkGenerator getGenerator() { + return chunkGenerator; + } + + @Override + public BiomeProvider getBiomeProvider() { + return biomeProvider; + } + + @Override + public ConfigPack getPack() { + return pack; + } + + @Override + public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { + getChunkAt(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16)) + .setBlock(FastMath.floorMod(x, 16), y, FastMath.floorMod(z, 16), data, physics); + } + + @Override + public Entity spawnEntity(double x, double y, double z, EntityType entityType) { + return null; + } + + @Override + public Stream> serialize() { + return Streams + .concat(Arrays.stream(regions), Arrays.stream(negativeRegions)) + .map(region -> Pair.of(Vector2Int.of(region.getX(), region.getZ()), region.serialize())); + } + + private static final class CLIProtoWorld implements ProtoWorld { + private final CLIWorld delegate; + private final int x, z; + + private CLIProtoWorld(CLIWorld delegate, int x, int z) { + this.delegate = delegate; + this.x = x; + this.z = z; + } + + @Override + public Object getHandle() { + return this; + } + + @Override + public BlockState getBlockState(int x, int y, int z) { + return delegate.getBlockState(x, y, z); + } + + @Override + public BlockEntity getBlockEntity(int x, int y, int z) { + return delegate.getBlockEntity(x, y, z); + } + + @Override + public long getSeed() { + return delegate.seed; + } + + @Override + public int getMaxHeight() { + return delegate.maxHeight; + } + + @Override + public int getMinHeight() { + return delegate.minHeight; + } + + @Override + public ChunkGenerator getGenerator() { + return delegate.chunkGenerator; + } + + @Override + public BiomeProvider getBiomeProvider() { + return delegate.biomeProvider; + } + + @Override + public ConfigPack getPack() { + return delegate.pack; + } + + @Override + public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { + delegate.setBlockState(x, y, z, data, physics); + } + + @Override + public Entity spawnEntity(double x, double y, double z, EntityType entityType) { + return delegate.spawnEntity(x, y, z, entityType); + } + + @Override + public int centerChunkX() { + return x; + } + + @Override + public int centerChunkZ() { + return z; + } + + @Override + public ServerWorld getWorld() { + return delegate; + } + } +} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/world/Region.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/Region.java new file mode 100644 index 000000000..0f644d515 --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/Region.java @@ -0,0 +1,58 @@ +package com.dfsek.terra.cli.world; + +import net.querz.mca.MCAFile; + +import com.dfsek.terra.cli.NBTSerializable; +import com.dfsek.terra.cli.world.chunk.CLIChunk; + + +public class Region implements NBTSerializable { + private final CLIChunk[] chunks; + private final int x, z; + private final CLIWorld world; + + public Region(CLIWorld world, int x, int z) { + this.x = x; + this.z = z; + this.world = world; + this.chunks = new CLIChunk[32 * 32]; + ; + } + + public CLIChunk get(int x, int z) { + int key = x + z * 32; + CLIChunk chunk = chunks[key]; + if(chunk == null) { + chunk = new CLIChunk(x, z, world); + chunks[key] = chunk; + } + return chunk; + } + + @Override + public MCAFile serialize() { + MCAFile mcaFile = new MCAFile(x, z); + int count = 0; + for(int cx = 0; cx < 32; cx++) { + for(int cz = 0; cz < 32; cz++) { + CLIChunk chunk = chunks[cx + cz * 32]; + if(chunk != null) { + count++; + mcaFile.setChunk(cx + cz * 32, chunk.serialize()); + } + } + } + if(count > 0) { + mcaFile.cleanupPalettesAndBlockStates(); + } + return mcaFile; + } + + public int getX() { + return x; + } + + public int getZ() { + return z; + } +} diff --git a/platforms/cli/src/main/java/com/dfsek/terra/cli/world/chunk/CLIChunk.java b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/chunk/CLIChunk.java new file mode 100644 index 000000000..7bf397bef --- /dev/null +++ b/platforms/cli/src/main/java/com/dfsek/terra/cli/world/chunk/CLIChunk.java @@ -0,0 +1,88 @@ +package com.dfsek.terra.cli.world.chunk; + +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.chunk.Chunk; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; +import com.dfsek.terra.cli.NBTSerializable; +import com.dfsek.terra.cli.block.CLIBlockState; +import com.dfsek.terra.cli.world.CLIWorld; + +import static com.dfsek.terra.cli.handle.CLIWorldHandle.getAIR; + + +public class CLIChunk implements Chunk, ProtoChunk, NBTSerializable { + private final int x; + private final int z; + private final CLIBlockState[][][] blocks; + private final int minHeight; + private final int maxHeight; + private final CLIWorld world; + + public CLIChunk(int x, int z, CLIWorld world) { + this.x = x; + this.z = z; + this.minHeight = world.getMinHeight(); + this.maxHeight = world.getMaxHeight(); + this.world = world; + this.blocks = new CLIBlockState[16][16][maxHeight - minHeight]; + } + + @Override + public Object getHandle() { + return null; + } + + @Override + public void setBlock(int x, int y, int z, BlockState data, boolean physics) { + blocks[x][z][y - minHeight] = (CLIBlockState) data; + } + + @Override + public @NotNull CLIBlockState getBlock(int x, int y, int z) { + CLIBlockState blockState = blocks[x][z][y - minHeight]; + if(blockState == null) return getAIR(); + return blockState; + } + + @Override + public int getX() { + return x; + } + + @Override + public int getZ() { + return z; + } + + @Override + public ServerWorld getWorld() { + return world; + } + + @Override + public net.querz.mca.Chunk serialize() { + net.querz.mca.Chunk chunk = net.querz.mca.Chunk.newChunk(2230); + for(int x = 0; x < blocks.length; x++) { + for(int z = 0; z < blocks[x].length; z++) { + for(int y = 0; y < blocks[z][z].length; y++) { + int yi = y + minHeight; + if(yi < 0 || yi >= 256) continue; + CLIBlockState blockState = blocks[x][z][y]; + if(blockState != null) { + chunk.setBlockStateAt(x, yi, z, blockState.getNbt(), false); + } + } + } + } + chunk.setStatus("features"); + return chunk; + } + + @Override + public int getMaxHeight() { + return maxHeight; + } +} diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index 7d3de271a..610606dc1 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -1,64 +1,71 @@ -import com.dfsek.terra.configureCommon import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.modrinth.minotaur.TaskModrinthUpload -import net.fabricmc.loom.LoomGradleExtension import net.fabricmc.loom.task.RemapJarTask plugins { - `java-library` - `maven-publish` - id("fabric-loom").version("0.8-SNAPSHOT") + id("fabric-loom").version("0.11-SNAPSHOT") id("com.modrinth.minotaur").version("1.1.0") } -configureCommon() - -tasks.named("shadowJar") { - relocate("org.json", "com.dfsek.terra.lib.json") - relocate("org.yaml", "com.dfsek.terra.lib.yaml") +dependencies { + shadedApi(project(":common:implementation:base")) + + minecraft("com.mojang:minecraft:${Versions.Fabric.minecraft}") + mappings("net.fabricmc:yarn:${Versions.Fabric.yarn}:v2") + + modImplementation("net.fabricmc:fabric-loader:${Versions.Fabric.fabricLoader}") + + setOf("fabric-command-api-v1", "fabric-lifecycle-events-v1", "fabric-resource-loader-v0", "fabric-api-base").forEach { apiModule -> + val module = fabricApi.module(apiModule, Versions.Fabric.fabricAPI) + modImplementation(module) + include(module) + } + + include(modImplementation("me.lucko", "fabric-permissions-api", Versions.Fabric.permissionsAPI)) + include("me.lucko", "fabric-permissions-api", Versions.Fabric.permissionsAPI) + + include(modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud)) + include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) } -group = "com.dfsek.terra.fabric" - -dependencies { - "shadedApi"(project(":common")) - - "minecraft"("com.mojang:minecraft:1.17.1") - "mappings"("net.fabricmc:yarn:1.17.1+build.1:v2") - "modImplementation"("net.fabricmc:fabric-loader:0.11.3") - - "modCompileOnly"("com.sk89q.worldedit:worldedit-fabric-mc1.16:7.2.0-SNAPSHOT") { - exclude(group = "com.google.guava", module = "guava") - exclude(group = "com.google.code.gson", module = "gson") - exclude(group = "it.unimi.dsi", module = "fastutil") - exclude(group = "org.apache.logging.log4j", module = "log4j-api") - exclude(group = "org.apache.logging.log4j", module = "log4j-core") +loom { + accessWidenerPath.set(file("src/main/resources/terra.accesswidener")) + mixin { + defaultRefmapName.set("terra-refmap.json") } } -tasks.named("shadowJar") { - relocate("org.json", "com.dfsek.terra.lib.json") - relocate("org.yaml", "com.dfsek.terra.lib.yaml") + +addonDir(project.rootProject.file("./run/config/Terra/addons"), tasks.named("runClient").get()) +addonDir(project.rootProject.file("./run/config/Terra/addons"), tasks.named("runServer").get()) + +tasks.withType().configureEach { + options.release.set(17) } - -configure { - accessWidener("src/main/resources/terra.accesswidener") - refmapName = "terra-refmap.json" +tasks.getByName("shadowJar") { + exclude("org/slf4j/**") } val remapped = tasks.register("remapShadedJar") { + dependsOn("installAddons") group = "fabric" val shadowJar = tasks.getByName("shadowJar") dependsOn(shadowJar) - input.set(shadowJar.archiveFile) + inputFile.set(shadowJar.archiveFile) archiveFileName.set(shadowJar.archiveFileName.get().replace(Regex("-shaded\\.jar$"), "-shaded-mapped.jar")) addNestedDependencies.set(true) - remapAccessWidener.set(true) } +tasks.named("assemble").configure { + dependsOn("remapShadedJar") +} -tasks.register("publishModrinthFabric") { +tasks.withType { + finalizedBy(remapped) +} + +tasks.register("publishModrinth") { dependsOn("remapShadedJar") group = "fabric" token = System.getenv("MODRINTH_SECRET") @@ -66,31 +73,6 @@ tasks.register("publishModrinthFabric") { versionNumber = "${project.version}-fabric" uploadFile = remapped.get().archiveFile.get().asFile releaseType = "beta" - addGameVersion("1.16.4") - addGameVersion("1.16.5") + addGameVersion(Versions.Fabric.minecraft) addLoader("fabric") -} - -publishing { - publications { - create("mavenJava") { - artifact(tasks["sourcesJar"]) - artifact(tasks["jar"]) - } - } - - repositories { - val mavenUrl = "https://repo.codemc.io/repository/maven-releases/" - - maven(mavenUrl) { - val mavenUsername: String? by project - val mavenPassword: String? by project - if (mavenUsername != null && mavenPassword != null) { - credentials { - username = mavenUsername - password = mavenPassword - } - } - } - } } \ No newline at end of file diff --git a/platforms/fabric/gradle.properties b/platforms/fabric/gradle.properties deleted file mode 100644 index 95b4763a8..000000000 --- a/platforms/fabric/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.gradle.jvmargs=-Xmx4G diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java new file mode 100644 index 000000000..347244a54 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricAddon.java @@ -0,0 +1,80 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.fabric; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.version.Version; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.event.events.config.ConfigurationLoadEvent; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPostLoadEvent; +import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; +import com.dfsek.terra.api.event.functional.FunctionalEventHandler; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions; +import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.fabric.config.VanillaBiomeProperties; + + +public final class FabricAddon implements BaseAddon { + private static final Version VERSION = Versions.getVersion(1, 0, 0); + private static final Logger logger = LoggerFactory.getLogger(FabricAddon.class); + private final PlatformImpl terraFabricPlugin; + + public FabricAddon(PlatformImpl terraFabricPlugin) { + this.terraFabricPlugin = terraFabricPlugin; + } + + @Override + public void initialize() { + terraFabricPlugin.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigPackPreLoadEvent.class) + .then(event -> event.getPack().getContext().put(event.loadTemplate(new PreLoadCompatibilityOptions()))) + .global(); + + terraFabricPlugin.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigPackPostLoadEvent.class) + .then(event -> event.getPack().getContext().put(event.loadTemplate(new PostLoadCompatibilityOptions()))) + .priority(100) + .global(); + + terraFabricPlugin.getEventManager() + .getHandler(FunctionalEventHandler.class) + .register(this, ConfigurationLoadEvent.class) + .then(event -> { + if(event.is(Biome.class)) { + event.getLoadedObject(Biome.class).getContext().put(event.load(new VanillaBiomeProperties())); + } + }) + .global(); + } + + @Override + public Version getVersion() { + return VERSION; + } + + @Override + public String getID() { + return "terra-fabric"; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java new file mode 100644 index 000000000..a6bd9b341 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java @@ -0,0 +1,64 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.fabric; + +import cloud.commandframework.execution.CommandExecutionCoordinator; +import cloud.commandframework.fabric.FabricServerCommandManager; +import net.fabricmc.api.ModInitializer; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; +import com.dfsek.terra.fabric.data.Codecs; + + +public class FabricEntryPoint implements ModInitializer { + private static final Logger logger = LoggerFactory.getLogger(FabricEntryPoint.class); + + private static final PlatformImpl TERRA_PLUGIN = new PlatformImpl(); + + + public static PlatformImpl getPlatform() { + return TERRA_PLUGIN; + } + + public static void register() { // register the things + Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER); + Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); + } + + @Override + public void onInitialize() { + logger.info("Initializing Terra Fabric mod..."); + + FabricServerCommandManager manager = new FabricServerCommandManager<>( + CommandExecutionCoordinator.simpleCoordinator(), + serverCommandSource -> (CommandSender) serverCommandSource, + commandSender -> (ServerCommandSource) commandSender + ); + + + manager.brigadierManager().setNativeNumberSuggestions(false); + + TERRA_PLUGIN.getEventManager().callEvent(new CommandRegistrationEvent(manager)); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java new file mode 100644 index 000000000..299465f20 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/PlatformImpl.java @@ -0,0 +1,171 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.fabric; + +import ca.solostudios.strata.Versions; +import ca.solostudios.strata.parser.tokenizer.ParseException; +import ca.solostudios.strata.version.Version; +import com.dfsek.tectonic.api.TypeRegistry; +import com.dfsek.tectonic.api.depth.DepthTracker; +import com.dfsek.tectonic.api.exception.LoadException; +import com.dfsek.terra.fabric.util.BiomeUtil; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.MinecraftVersion; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.world.biome.Biome.Category; +import net.minecraft.world.biome.Biome.Precipitation; +import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import com.dfsek.terra.AbstractPlatform; +import com.dfsek.terra.addon.EphemeralAddon; +import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.api.world.biome.PlatformBiome; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.handle.FabricItemHandle; +import com.dfsek.terra.fabric.handle.FabricWorldHandle; +import com.dfsek.terra.fabric.util.ProtoPlatformBiome; + + +public class PlatformImpl extends AbstractPlatform { + private static final Logger LOGGER = LoggerFactory.getLogger(PlatformImpl.class); + private final ItemHandle itemHandle = new FabricItemHandle(); + private final WorldHandle worldHandle = new FabricWorldHandle(); + private final Lazy dataFolder = Lazy.lazy(() -> new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra")); + private MinecraftServer server; + + public PlatformImpl() { + load(); + } + + public void setServer(MinecraftServer server) { + this.server = server; + } + + @Override + public boolean reload() { + getTerraConfig().load(this); + getRawConfigRegistry().clear(); + boolean succeed = getRawConfigRegistry().loadAll(this); + + + if(server != null) { + server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> { + LOGGER.warn("Failed to execute reload", throwable); + return null; + }).join(); + BiomeUtil.registerBiomes(); + server.getWorlds().forEach(world -> { + if(world.getChunkManager().getChunkGenerator() instanceof FabricChunkGeneratorWrapper chunkGeneratorWrapper) { + getConfigRegistry().get(chunkGeneratorWrapper.getPack().getRegistryKey()).ifPresent(pack -> { + chunkGeneratorWrapper.setPack(pack); + LOGGER.info("Replaced pack in chunk generator for world {}", world); + }); + } + }); + } + return succeed; + } + + @Override + protected Iterable platformAddon() { + List addons = new ArrayList<>(); + + addons.add(new FabricAddon(this)); + + String mcVersion = MinecraftVersion.CURRENT.getReleaseTarget(); + try { + addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion), "minecraft")); + } catch(ParseException e) { + try { + addons.add(new EphemeralAddon(Versions.parseVersion(mcVersion + ".0"), "minecraft")); + } catch(ParseException ex) { + LOGGER.warn("Failed to parse Minecraft version", e); + } + } + + FabricLoader.getInstance().getAllMods().forEach(mod -> { + String id = mod.getMetadata().getId(); + if(id.equals("terra") || id.equals("minecraft") || id.equals("java")) return; + try { + Version version = Versions.parseVersion(mod.getMetadata().getVersion().getFriendlyString()); + addons.add(new EphemeralAddon(version, "fabric:" + id)); + } catch(ParseException e) { + LOGGER.warn( + "Mod {}, version {} does not follow semantic versioning specification, Terra addons will be unable to depend on " + + "it.", + id, mod.getMetadata().getVersion().getFriendlyString()); + } + }); + + return addons; + } + + @Override + public @NotNull String platformName() { + return "Fabric"; + } + + @Override + public @NotNull WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public @NotNull File getDataFolder() { + return dataFolder.value(); + } + + @Override + public @NotNull ItemHandle getItemHandle() { + return itemHandle; + } + + @Override + public void register(TypeRegistry registry) { + super.register(registry); + registry.registerLoader(PlatformBiome.class, (type, o, loader, depthTracker) -> parseBiome((String) o, depthTracker)) + .registerLoader(Identifier.class, (type, o, loader, depthTracker) -> { + Identifier identifier = Identifier.tryParse((String) o); + if(identifier == null) + throw new LoadException("Invalid identifier: " + o, depthTracker); + return identifier; + }) + .registerLoader(Precipitation.class, (type, o, loader, depthTracker) -> Precipitation.byName((String) o)) + .registerLoader(Category.class, (type, o, loader, depthTracker) -> Category.byName((String) o)) + .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> GrassColorModifier.byName((String) o)); + } + + + private ProtoPlatformBiome parseBiome(String id, DepthTracker tracker) throws LoadException { + Identifier identifier = Identifier.tryParse(id); + if(BuiltinRegistries.BIOME.get(identifier) == null) throw new LoadException("Invalid Biome ID: " + identifier, tracker); // failure. + return new ProtoPlatformBiome(identifier); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java deleted file mode 100644 index 0863bf5d9..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/TerraFabricPlugin.java +++ /dev/null @@ -1,433 +0,0 @@ -package com.dfsek.terra.fabric; - -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.addons.annotations.Addon; -import com.dfsek.terra.api.addons.annotations.Author; -import com.dfsek.terra.api.addons.annotations.Version; -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.TerraCommandManager; -import com.dfsek.terra.api.command.exception.MalformedCommandException; -import com.dfsek.terra.api.event.EventListener; -import com.dfsek.terra.api.event.EventManager; -import com.dfsek.terra.api.event.TerraEventManager; -import com.dfsek.terra.api.event.annotations.Global; -import com.dfsek.terra.api.event.annotations.Priority; -import com.dfsek.terra.api.event.events.config.ConfigPackPostLoadEvent; -import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.registry.CheckedRegistry; -import com.dfsek.terra.api.registry.LockedRegistry; -import com.dfsek.terra.api.transform.Transformer; -import com.dfsek.terra.api.transform.Validator; -import com.dfsek.terra.api.util.JarUtil; -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.dfsek.terra.api.util.logging.DebugLogger; -import com.dfsek.terra.api.util.logging.Logger; -import com.dfsek.terra.commands.CommandUtil; -import com.dfsek.terra.config.GenericLoaders; -import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.config.lang.Language; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions; -import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.fabric.event.BiomeRegistrationEvent; -import com.dfsek.terra.fabric.event.GameInitializationEvent; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.fabric.generation.PopulatorFeature; -import com.dfsek.terra.fabric.generation.TerraBiomeSource; -import com.dfsek.terra.fabric.handle.FabricItemHandle; -import com.dfsek.terra.fabric.handle.FabricWorldHandle; -import com.dfsek.terra.fabric.util.FabricUtil; -import com.dfsek.terra.fabric.util.ProtoBiome; -import com.dfsek.terra.profiler.Profiler; -import com.dfsek.terra.profiler.ProfilerImpl; -import com.dfsek.terra.registry.exception.DuplicateEntryException; -import com.dfsek.terra.registry.master.AddonRegistry; -import com.dfsek.terra.registry.master.ConfigRegistry; -import com.dfsek.terra.world.TerraWorld; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryKey; -import net.minecraft.world.WorldAccess; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.dimension.DimensionType; -import net.minecraft.world.gen.decorator.Decorator; -import net.minecraft.world.gen.decorator.NopeDecoratorConfig; -import net.minecraft.world.gen.feature.ConfiguredFeature; -import net.minecraft.world.gen.feature.ConfiguredFeatures; -import net.minecraft.world.gen.feature.DefaultFeatureConfig; -import net.minecraft.world.gen.feature.FeatureConfig; -import org.apache.commons.io.FileUtils; -import org.apache.logging.log4j.LogManager; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicReference; -import java.util.jar.JarFile; - - -public class TerraFabricPlugin implements TerraPlugin, ModInitializer { - private final org.apache.logging.log4j.Logger log4jLogger = LogManager.getLogger(); - public static final PopulatorFeature POPULATOR_FEATURE = new PopulatorFeature(DefaultFeatureConfig.CODEC); - public static final ConfiguredFeature POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configure(FeatureConfig.DEFAULT).decorate(Decorator.NOPE.configure(NopeDecoratorConfig.INSTANCE)); - private static TerraFabricPlugin instance; - private final Map> worldMap = new HashMap<>(); - - public Map> getWorldMap() { - return worldMap; - } - - private final EventManager eventManager = new TerraEventManager(this); - private final GenericLoaders genericLoaders = new GenericLoaders(this); - - private final Profiler profiler = new ProfilerImpl(); - - private final Logger logger = new Logger() { - @Override - public void info(String message) { - log4jLogger.info(message); - } - - @Override - public void warning(String message) { - log4jLogger.warn(message); - } - - @Override - public void severe(String message) { - log4jLogger.error(message); - } - }; - - private final DebugLogger debugLogger = new DebugLogger(logger); - private final ItemHandle itemHandle = new FabricItemHandle(); - private final WorldHandle worldHandle = new FabricWorldHandle(); - private final ConfigRegistry configRegistry = new ConfigRegistry(); - private final CheckedRegistry checkedRegistry = new CheckedRegistry<>(configRegistry); - - private final FabricAddon fabricAddon = new FabricAddon(); - private final AddonRegistry addonRegistry = new AddonRegistry(fabricAddon, this); - private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); - - private final PluginConfig config = new PluginConfig(); - - private final Transformer biomeFixer = new Transformer.Builder() - .addTransform(this::parseBiome, Validator.notNull()) - .addTransform(id -> parseBiome("minecraft:" + id.toLowerCase()), Validator.notNull()).build(); - - private ProtoBiome parseBiome(String id) { - Identifier identifier = Identifier.tryParse(id); - if(BuiltinRegistries.BIOME.get(identifier) == null) return null; // failure. - return new ProtoBiome(identifier); - } - - private File dataFolder; - private final CommandManager manager = new TerraCommandManager(this); - - private final AtomicReference terraModJar = new AtomicReference<>(null); - - @Override - public JarFile getModJar() throws URISyntaxException, IOException { - if(!FabricLoader.getInstance().isDevelopmentEnvironment()) return TerraPlugin.super.getModJar(); - final File _jarFile1 = terraModJar.get(); - if(_jarFile1 != null) return new JarFile(_jarFile1); - synchronized(terraModJar) { - final File _jarFile2 = terraModJar.get(); - if(_jarFile2 != null) return new JarFile(_jarFile2); - - // uncached here - final URI jarURI = JarUtil.getJarURL().toURI(); - if(jarURI.getScheme() == null || !jarURI.getScheme().equalsIgnoreCase("file")) { - final File tempFile = File.createTempFile("terra-jar-" + UUID.randomUUID(), ".jar"); - try(final FileOutputStream out = new FileOutputStream(tempFile)) { - Files.copy(Paths.get(jarURI), out); - } - tempFile.deleteOnExit(); - terraModJar.set(tempFile); - return new JarFile(tempFile); - } else { - final File jarFile = new File(jarURI); - terraModJar.set(jarFile); - return new JarFile(jarFile); - } - } - } - - public CommandManager getManager() { - return manager; - } - - public static TerraFabricPlugin getInstance() { - return instance; - } - - @Override - public WorldHandle getWorldHandle() { - return worldHandle; - } - - @Override - public TerraWorld getWorld(World world) { - return getWorld(((WorldAccess) world).getDimension()); - } - - public TerraWorld getWorld(DimensionType type) { - TerraWorld world = worldMap.get(type).getRight(); - if(world == null) throw new IllegalArgumentException("No world exists with dimension type " + type); - return world; - } - - @Override - public Logger logger() { - return logger; - } - - @Override - public PluginConfig getTerraConfig() { - return config; - } - - @Override - public File getDataFolder() { - return dataFolder; - } - - @Override - public boolean isDebug() { - return config.isDebug(); - } - - @Override - public Language getLanguage() { - return LangUtil.getLanguage(); - } - - public FabricAddon getFabricAddon() { - return fabricAddon; - } - - @Override - public CheckedRegistry getConfigRegistry() { - return checkedRegistry; - } - - @Override - public LockedRegistry getAddons() { - return addonLockedRegistry; - } - - @Override - public boolean reload() { - config.load(this); - LangUtil.load(config.getLanguage(), this); // Load language. - boolean succeed = configRegistry.loadAll(this); - worldMap.forEach((seed, pair) -> { - pair.getRight().getConfig().getSamplerCache().clear(); - String packID = pair.getRight().getConfig().getTemplate().getID(); - pair.setRight(new TerraWorld(pair.getRight().getWorld(), configRegistry.get(packID), this)); - }); - return succeed; - } - - @Override - public ItemHandle getItemHandle() { - return itemHandle; - } - - @Override - public void saveDefaultConfig() { - try(InputStream stream = getClass().getResourceAsStream("/config.yml")) { - File configFile = new File(getDataFolder(), "config.yml"); - if(!configFile.exists()) FileUtils.copyInputStreamToFile(stream, configFile); - } catch(IOException e) { - e.printStackTrace(); - } - } - - @Override - public String platformName() { - return "Fabric"; - } - - @Override - public DebugLogger getDebugLogger() { - return debugLogger; - } - - @Override - public void register(TypeRegistry registry) { - genericLoaders.register(registry); - registry - .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) - .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> biomeFixer.translate((String) o)) - .registerLoader(Identifier.class, (t, o, l) -> { - Identifier identifier = Identifier.tryParse((String) o); - if(identifier == null) throw new LoadException("Invalid identifier: " + o); - return identifier; - }); - } - - @Override - public void onInitialize() { - instance = this; - - this.dataFolder = new File(FabricLoader.getInstance().getConfigDir().toFile(), "Terra"); - saveDefaultConfig(); - config.load(this); - debugLogger.setDebug(config.isDebug()); - LangUtil.load(config.getLanguage(), this); - logger.info("Initializing Terra..."); - - if(!addonRegistry.loadAll()) { - throw new IllegalStateException("Failed to load addons. Please correct addon installations to continue."); - } - logger.info("Loaded addons."); - - - Registry.register(Registry.FEATURE, new Identifier("terra", "populator"), POPULATOR_FEATURE); - RegistryKey> floraKey = RegistryKey.of(Registry.CONFIGURED_FEATURE_KEY, new Identifier("terra", "populator")); - Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, floraKey.getValue(), POPULATOR_CONFIGURED_FEATURE); - - Registry.register(Registry.CHUNK_GENERATOR, new Identifier("terra:terra"), FabricChunkGeneratorWrapper.CODEC); - Registry.register(Registry.BIOME_SOURCE, new Identifier("terra:terra"), TerraBiomeSource.CODEC); - - try { - CommandUtil.registerAll(manager); - } catch(MalformedCommandException e) { - e.printStackTrace(); // TODO do something here even though this should literally never happen - } - - logger.info("Finished initialization."); - } - - - @Override - public EventManager getEventManager() { - return eventManager; - } - - @Override - public Profiler getProfiler() { - return profiler; - } - - @Addon("Terra-Fabric") - @Author("Terra") - @Version("1.0.0") - public final class FabricAddon extends TerraAddon implements EventListener { - private final Map> templates = new HashMap<>(); - - @Override - public void initialize() { - eventManager.registerListener(this, this); - } - - @Priority(Priority.LOWEST) - @Global - public void injectTrees(ConfigPackPreLoadEvent event) { - CheckedRegistry treeRegistry = event.getPack().getTreeRegistry(); - injectTree(treeRegistry, "BROWN_MUSHROOM", ConfiguredFeatures.HUGE_BROWN_MUSHROOM); - injectTree(treeRegistry, "RED_MUSHROOM", ConfiguredFeatures.HUGE_RED_MUSHROOM); - injectTree(treeRegistry, "JUNGLE", ConfiguredFeatures.MEGA_JUNGLE_TREE); - injectTree(treeRegistry, "JUNGLE_COCOA", ConfiguredFeatures.JUNGLE_TREE); - injectTree(treeRegistry, "LARGE_OAK", ConfiguredFeatures.FANCY_OAK); - injectTree(treeRegistry, "LARGE_SPRUCE", ConfiguredFeatures.PINE); - injectTree(treeRegistry, "SMALL_JUNGLE", ConfiguredFeatures.JUNGLE_TREE); - injectTree(treeRegistry, "SWAMP_OAK", ConfiguredFeatures.SWAMP_OAK); - injectTree(treeRegistry, "TALL_BIRCH", ConfiguredFeatures.BIRCH_TALL); - injectTree(treeRegistry, "ACACIA", ConfiguredFeatures.ACACIA); - injectTree(treeRegistry, "BIRCH", ConfiguredFeatures.BIRCH); - injectTree(treeRegistry, "DARK_OAK", ConfiguredFeatures.DARK_OAK); - injectTree(treeRegistry, "OAK", ConfiguredFeatures.OAK); - injectTree(treeRegistry, "CHORUS_PLANT", ConfiguredFeatures.CHORUS_PLANT); - injectTree(treeRegistry, "SPRUCE", ConfiguredFeatures.SPRUCE); - injectTree(treeRegistry, "JUNGLE_BUSH", ConfiguredFeatures.JUNGLE_BUSH); - injectTree(treeRegistry, "MEGA_SPRUCE", ConfiguredFeatures.MEGA_SPRUCE); - injectTree(treeRegistry, "CRIMSON_FUNGUS", ConfiguredFeatures.CRIMSON_FUNGI); - injectTree(treeRegistry, "WARPED_FUNGUS", ConfiguredFeatures.WARPED_FUNGI); - - PreLoadCompatibilityOptions template = new PreLoadCompatibilityOptions(); - try { - event.loadTemplate(template); - } catch(ConfigException e) { - e.printStackTrace(); - } - - if(template.doRegistryInjection()) { - BuiltinRegistries.CONFIGURED_FEATURE.getEntries().forEach(entry -> { - if(!template.getExcludedRegistryFeatures().contains(entry.getKey().getValue())) { - try { - event.getPack().getTreeRegistry().add(entry.getKey().getValue().toString(), (Tree) entry.getValue()); - debugLogger.info("Injected ConfiguredFeature " + entry.getKey().getValue() + " as Tree."); - } catch(DuplicateEntryException ignored) { - } - } - }); - } - templates.put(event.getPack(), Pair.of(template, null)); - } - - @Priority(Priority.HIGHEST) - @Global - public void createInjectionOptions(ConfigPackPostLoadEvent event) { - PostLoadCompatibilityOptions template = new PostLoadCompatibilityOptions(); - - try { - event.loadTemplate(template); - } catch(ConfigException e) { - e.printStackTrace(); - } - - templates.get(event.getPack()).setRight(template); - } - - @Global - public void injectBiomes(BiomeRegistrationEvent event) { - logger.info("Registering biomes..."); - Registry biomeRegistry = event.getRegistryManager().get(Registry.BIOME_KEY); - configRegistry.forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> FabricUtil.registerOrOverwrite(biomeRegistry, Registry.BIOME_KEY, new Identifier("terra", FabricUtil.createBiomeID(pack, id)), FabricUtil.createBiome(biome, pack, event.getRegistryManager())))); // Register all Terra biomes. - logger.info("Biomes registered."); - } - - @Global - public void initializePacks(GameInitializationEvent event) { - TerraFabricPlugin main = TerraFabricPlugin.getInstance(); - main.logger().info("Loading config packs..."); - configRegistry.loadAll(TerraFabricPlugin.this); - logger.info("Loaded packs."); - } - - private void injectTree(CheckedRegistry registry, String id, ConfiguredFeature tree) { - try { - registry.add(id, (Tree) tree); - } catch(DuplicateEntryException ignore) { - } - } - - public Map> getTemplates() { - return templates; - } - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlock.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlock.java deleted file mode 100644 index 78c1211b5..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlock.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.dfsek.terra.fabric.block; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.fabric.util.FabricAdapter; -import net.minecraft.block.FluidBlock; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.WorldAccess; - -public class FabricBlock implements Block { - private final Handle delegate; - - public FabricBlock(BlockPos position, WorldAccess worldAccess) { - this.delegate = new Handle(position, worldAccess); - } - - @Override - public void setBlockData(BlockData data, boolean physics) { - delegate.worldAccess.setBlockState(delegate.position, ((FabricBlockData) data).getHandle(), physics ? 3 : 1042); - if(physics && ((FabricBlockData) data).getHandle().getBlock() instanceof FluidBlock) { - delegate.worldAccess.getFluidTickScheduler().schedule(delegate.position, ((FluidBlock) ((FabricBlockData) data).getHandle().getBlock()).getFluidState(((FabricBlockData) data).getHandle()).getFluid(), 0); - } - } - - @Override - public BlockData getBlockData() { - return new FabricBlockData(delegate.worldAccess.getBlockState(delegate.position)); - } - - @Override - public BlockState getState() { - return FabricAdapter.adapt(this); - } - - @Override - public Block getRelative(BlockFace face, int len) { - BlockPos newPos = delegate.position.add(face.getModX() * len, face.getModY() * len, face.getModZ() * len); - return new FabricBlock(newPos, delegate.worldAccess); - } - - @Override - public boolean isEmpty() { - return getBlockData().isAir(); - } - - @Override - public Location getLocation() { - return FabricAdapter.adapt(delegate.position).toLocation((World) delegate.worldAccess); - } - - @Override - public BlockType getType() { - return getBlockData().getBlockType(); - } - - @Override - public int getX() { - return delegate.position.getX(); - } - - @Override - public int getZ() { - return delegate.position.getZ(); - } - - @Override - public int getY() { - return delegate.position.getY(); - } - - @Override - public boolean isPassable() { - return isEmpty(); - } - - @Override - public Handle getHandle() { - return delegate; - } - - public static final class Handle { - private final BlockPos position; - private final WorldAccess worldAccess; - - public Handle(BlockPos position, WorldAccess worldAccess) { - this.position = position; - this.worldAccess = worldAccess; - } - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlockData.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlockData.java deleted file mode 100644 index 6fd723bfb..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/FabricBlockData.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.dfsek.terra.fabric.block; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.fabric.mixin.access.StateAccessor; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.util.registry.Registry; - -import java.util.stream.Collectors; - -public class FabricBlockData implements BlockData { - protected BlockState delegate; - - public FabricBlockData(BlockState delegate) { - this.delegate = delegate; - } - - @Override - public BlockType getBlockType() { - return (BlockType) delegate.getBlock(); - } - - @Override - public boolean matches(BlockData other) { - return delegate.getBlock() == ((FabricBlockData) other).delegate.getBlock(); - } - - @Override - public BlockData clone() { - try { - return (FabricBlockData) super.clone(); - } catch(CloneNotSupportedException e) { - throw new Error(e); - } - } - - @Override - public String getAsString() { - StringBuilder data = new StringBuilder(Registry.BLOCK.getId(delegate.getBlock()).toString()); - if(!delegate.getEntries().isEmpty()) { - data.append('['); - data.append(delegate.getEntries().entrySet().stream().map(StateAccessor.getPropertyMapPrinter()).collect(Collectors.joining(","))); - data.append(']'); - } - return data.toString(); - } - - @Override - public boolean isAir() { - return delegate.isAir(); - } - - @Override - public boolean isStructureVoid() { - return delegate.getBlock() == Blocks.STRUCTURE_VOID; - } - - @Override - public BlockState getHandle() { - return delegate; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricAnaloguePowerable.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricAnaloguePowerable.java deleted file mode 100644 index b2fab164e..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricAnaloguePowerable.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.fabric.block.data; - -import com.dfsek.terra.api.platform.block.data.AnaloguePowerable; -import com.dfsek.terra.fabric.block.FabricBlockData; -import net.minecraft.block.BlockState; - -/** - * None of this actually has implementation, TODO: implement this if we ever end up needing it. - */ -public class FabricAnaloguePowerable extends FabricBlockData implements AnaloguePowerable { - public FabricAnaloguePowerable(BlockState delegate) { - super(delegate); - } - - @Override - public int getMaximumPower() { - return 0; - } - - @Override - public int getPower() { - return 0; - } - - @Override - public void setPower(int power) { - - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricDirectional.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricDirectional.java deleted file mode 100644 index be4eb316b..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricDirectional.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dfsek.terra.fabric.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Directional; -import com.dfsek.terra.fabric.block.FabricBlockData; -import com.dfsek.terra.fabric.util.FabricAdapter; -import net.minecraft.block.BlockState; -import net.minecraft.state.property.DirectionProperty; - -public class FabricDirectional extends FabricBlockData implements Directional { - private final DirectionProperty property; - - public FabricDirectional(BlockState delegate, DirectionProperty property) { - super(delegate); - this.property = property; - } - - @Override - public BlockFace getFacing() { - switch(delegate.get(property)) { - case SOUTH: - return BlockFace.SOUTH; - case DOWN: - return BlockFace.DOWN; - case UP: - return BlockFace.UP; - case EAST: - return BlockFace.EAST; - case WEST: - return BlockFace.WEST; - case NORTH: - return BlockFace.NORTH; - default: - throw new IllegalStateException(); - } - } - - @Override - public void setFacing(BlockFace facing) { - delegate = delegate.with(property, FabricAdapter.adapt(facing)); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricMultipleFacing.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricMultipleFacing.java deleted file mode 100644 index d1caae8e1..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricMultipleFacing.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.dfsek.terra.fabric.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.MultipleFacing; -import com.dfsek.terra.fabric.block.FabricBlockData; -import net.minecraft.block.BlockState; -import net.minecraft.state.property.Properties; - -import java.util.HashSet; -import java.util.Set; - -public class FabricMultipleFacing extends FabricBlockData implements MultipleFacing { - public FabricMultipleFacing(BlockState delegate) { - super(delegate); - } - - @Override - public Set getFaces() { - Set set = new HashSet<>(); - if(delegate.get(Properties.NORTH)) set.add(BlockFace.NORTH); - if(delegate.get(Properties.SOUTH)) set.add(BlockFace.SOUTH); - if(delegate.get(Properties.EAST)) set.add(BlockFace.EAST); - if(delegate.get(Properties.WEST)) set.add(BlockFace.WEST); - if(delegate.contains(Properties.UP) && delegate.get(Properties.UP)) set.add(BlockFace.UP); - if(delegate.contains(Properties.DOWN) && delegate.get(Properties.DOWN)) set.add(BlockFace.DOWN); - return set; - } - - @Override - public void setFace(BlockFace face, boolean facing) { - switch(face) { - case NORTH: - delegate = delegate.with(Properties.NORTH, facing); - break; - case SOUTH: - delegate = delegate.with(Properties.SOUTH, facing); - break; - case EAST: - delegate = delegate.with(Properties.EAST, facing); - break; - case WEST: - delegate = delegate.with(Properties.WEST, facing); - break; - case UP: - delegate = delegate.with(Properties.UP, facing); - break; - case DOWN: - delegate = delegate.with(Properties.DOWN, facing); - break; - } - } - - @Override - public Set getAllowedFaces() { - Set set = new HashSet<>(); - if(delegate.contains(Properties.NORTH)) set.add(BlockFace.NORTH); - if(delegate.contains(Properties.SOUTH)) set.add(BlockFace.SOUTH); - if(delegate.contains(Properties.EAST)) set.add(BlockFace.EAST); - if(delegate.contains(Properties.WEST)) set.add(BlockFace.WEST); - if(delegate.contains(Properties.UP)) set.add(BlockFace.UP); - if(delegate.contains(Properties.DOWN)) set.add(BlockFace.DOWN); - return set; - } - - @Override - public boolean hasFace(BlockFace f) { - return getFaces().contains(f); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricOrientable.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricOrientable.java deleted file mode 100644 index d8e88d566..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricOrientable.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.dfsek.terra.fabric.block.data; - -import com.dfsek.terra.api.platform.block.Axis; -import com.dfsek.terra.api.platform.block.data.Orientable; -import com.dfsek.terra.fabric.block.FabricBlockData; -import com.dfsek.terra.fabric.util.FabricAdapter; -import net.minecraft.block.BlockState; -import net.minecraft.state.property.EnumProperty; -import net.minecraft.util.math.Direction; - -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -public class FabricOrientable extends FabricBlockData implements Orientable { - private final EnumProperty property; - - public FabricOrientable(BlockState delegate, EnumProperty property) { - super(delegate); - this.property = property; - } - - @Override - public Set getAxes() { - return Arrays.stream(Axis.values()).collect(Collectors.toSet()); - } - - @Override - public Axis getAxis() { - return FabricAdapter.adapt(getHandle().get(property)); - } - - @Override - public void setAxis(Axis axis) { - delegate = delegate.with(property, FabricAdapter.adapt(axis)); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricRotatable.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricRotatable.java deleted file mode 100644 index 4b7a971ea..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricRotatable.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.dfsek.terra.fabric.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Rotatable; -import com.dfsek.terra.fabric.block.FabricBlockData; -import net.minecraft.block.BlockState; -import net.minecraft.state.property.Properties; - -public class FabricRotatable extends FabricBlockData implements Rotatable { - public FabricRotatable(BlockState delegate) { - super(delegate); - } - - @Override - public BlockFace getRotation() { - int r = delegate.get(Properties.ROTATION); - switch(r) { - case 0: - return BlockFace.SOUTH; - case 1: - return BlockFace.SOUTH_SOUTH_WEST; - case 2: - return BlockFace.SOUTH_WEST; - case 3: - return BlockFace.WEST_SOUTH_WEST; - case 4: - return BlockFace.WEST; - case 5: - return BlockFace.WEST_NORTH_WEST; - case 6: - return BlockFace.NORTH_WEST; - case 7: - return BlockFace.NORTH_NORTH_WEST; - case 8: - return BlockFace.NORTH; - case 9: - return BlockFace.NORTH_NORTH_EAST; - case 10: - return BlockFace.NORTH_EAST; - case 11: - return BlockFace.EAST_NORTH_EAST; - case 12: - return BlockFace.EAST; - case 13: - return BlockFace.EAST_SOUTH_EAST; - case 14: - return BlockFace.SOUTH_EAST; - case 15: - return BlockFace.SOUTH_SOUTH_EAST; - default: - throw new IllegalArgumentException("Unknown rotation " + r); - } - } - - @Override - public void setRotation(BlockFace face) { - switch(face) { - case UP: - case DOWN: - throw new IllegalArgumentException("Illegal rotation " + face); - case SOUTH: - delegate = delegate.with(Properties.ROTATION, 0); - return; - case SOUTH_SOUTH_WEST: - delegate = delegate.with(Properties.ROTATION, 1); - return; - case SOUTH_WEST: - delegate = delegate.with(Properties.ROTATION, 2); - return; - case WEST_SOUTH_WEST: - delegate = delegate.with(Properties.ROTATION, 3); - return; - case WEST: - delegate = delegate.with(Properties.ROTATION, 4); - return; - case WEST_NORTH_WEST: - delegate = delegate.with(Properties.ROTATION, 5); - return; - case NORTH_WEST: - delegate = delegate.with(Properties.ROTATION, 6); - return; - case NORTH_NORTH_WEST: - delegate = delegate.with(Properties.ROTATION, 7); - return; - case NORTH: - delegate = delegate.with(Properties.ROTATION, 8); - return; - case NORTH_NORTH_EAST: - delegate = delegate.with(Properties.ROTATION, 9); - return; - case NORTH_EAST: - delegate = delegate.with(Properties.ROTATION, 10); - return; - case EAST_NORTH_EAST: - delegate = delegate.with(Properties.ROTATION, 11); - return; - case EAST: - delegate = delegate.with(Properties.ROTATION, 12); - return; - case EAST_SOUTH_EAST: - delegate = delegate.with(Properties.ROTATION, 13); - return; - case SOUTH_EAST: - delegate = delegate.with(Properties.ROTATION, 14); - return; - case SOUTH_SOUTH_EAST: - delegate = delegate.with(Properties.ROTATION, 15); - return; - } - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricSlab.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricSlab.java deleted file mode 100644 index cf0d0c277..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricSlab.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.fabric.block.data; - -import com.dfsek.terra.api.platform.block.data.Slab; -import com.dfsek.terra.fabric.util.FabricAdapter; -import net.minecraft.block.BlockState; -import net.minecraft.state.property.Properties; - -public class FabricSlab extends FabricWaterlogged implements Slab { - public FabricSlab(BlockState delegate) { - super(delegate); - } - - @Override - public Type getType() { - return FabricAdapter.adapt(delegate.get(Properties.SLAB_TYPE)); - } - - @Override - public void setType(Type type) { - delegate = delegate.with(Properties.SLAB_TYPE, FabricAdapter.adapt(type)); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricStairs.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricStairs.java deleted file mode 100644 index d18ec13da..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricStairs.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.dfsek.terra.fabric.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Stairs; -import com.dfsek.terra.fabric.util.FabricAdapter; -import net.minecraft.block.BlockState; -import net.minecraft.state.property.Properties; - -public class FabricStairs extends FabricWaterlogged implements Stairs { - public FabricStairs(BlockState delegate) { - super(delegate); - } - - @Override - public Shape getShape() { - return FabricAdapter.adapt(getHandle().get(Properties.STAIR_SHAPE)); - } - - @Override - public void setShape(Shape shape) { - super.delegate = getHandle().with(Properties.STAIR_SHAPE, FabricAdapter.adapt(shape)); - } - - @Override - public Half getHalf() { - return FabricAdapter.adapt(getHandle().get(Properties.BLOCK_HALF)); - } - - @Override - public void setHalf(Half half) { - super.delegate = getHandle().with(Properties.BLOCK_HALF, FabricAdapter.adapt(half)); - } - - @Override - public BlockFace getFacing() { - return FabricAdapter.adapt(getHandle().get(Properties.HORIZONTAL_FACING)); - } - - @Override - public void setFacing(BlockFace facing) { - super.delegate = getHandle().with(Properties.HORIZONTAL_FACING, FabricAdapter.adapt(facing)); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricWaterlogged.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricWaterlogged.java deleted file mode 100644 index 7e3636bde..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/block/data/FabricWaterlogged.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.fabric.block.data; - -import com.dfsek.terra.api.platform.block.data.Waterlogged; -import com.dfsek.terra.fabric.block.FabricBlockData; -import net.minecraft.block.BlockState; -import net.minecraft.state.property.Properties; - -public class FabricWaterlogged extends FabricBlockData implements Waterlogged { - public FabricWaterlogged(BlockState delegate) { - super(delegate); - } - - @Override - public boolean isWaterlogged() { - return delegate.get(Properties.WATERLOGGED); - } - - @Override - public void setWaterlogged(boolean waterlogged) { - super.delegate = delegate.with(Properties.WATERLOGGED, waterlogged); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java index ae812bed5..9a13e0029 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PostLoadCompatibilityOptions.java @@ -1,30 +1,28 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.config; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.terra.config.builder.BiomeBuilder; -import net.minecraft.util.Identifier; +import com.dfsek.tectonic.api.config.template.ConfigTemplate; + +import com.dfsek.terra.api.properties.Properties; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; @SuppressWarnings("FieldMayBeFinal") -public class PostLoadCompatibilityOptions implements ConfigTemplate { - @Value("structures.inject-biome.exclude-biomes") - @Default - private Map> excludedPerBiomeStructures = new HashMap<>(); +public class PostLoadCompatibilityOptions implements ConfigTemplate, Properties { - @Value("features.inject-biome.exclude-biomes") - @Default - private Map> excludedPerBiomeFeatures = new HashMap<>(); - - public Map> getExcludedPerBiomeFeatures() { - return excludedPerBiomeFeatures; - } - - public Map> getExcludedPerBiomeStructures() { - return excludedPerBiomeStructures; - } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PreLoadCompatibilityOptions.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PreLoadCompatibilityOptions.java index 0dfbccf00..0bf7f0de1 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PreLoadCompatibilityOptions.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/PreLoadCompatibilityOptions.java @@ -1,52 +1,52 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.config; -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import net.minecraft.util.Identifier; +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; + +import com.dfsek.terra.api.properties.Properties; -import java.util.HashSet; -import java.util.Set; @SuppressWarnings("FieldMayBeFinal") -public class PreLoadCompatibilityOptions implements ConfigTemplate { - @Value("features.inject-registry.enable") +public class PreLoadCompatibilityOptions implements ConfigTemplate, Properties { + @Value("fabric.use-vanilla-biomes") @Default - private boolean doRegistryInjection = false; - - @Value("features.inject-biome.enable") + private boolean vanillaBiomes = false; + + @Value("fabric.beard.enable") @Default - private boolean doBiomeInjection = false; - - @Value("features.inject-registry.excluded-features") + private boolean beard = true; + + @Value("fabric.beard.threshold") @Default - private Set excludedRegistryFeatures = new HashSet<>(); - - @Value("features.inject-biome.excluded-features") - @Default - private Set excludedBiomeFeatures = new HashSet<>(); - - @Value("structures.inject-biome.excluded-features") - @Default - private Set excludedBiomeStructures = new HashSet<>(); - - public boolean doBiomeInjection() { - return doBiomeInjection; + private double beardThreshold = 0.5; + + public boolean useVanillaBiomes() { + return vanillaBiomes; } - - public boolean doRegistryInjection() { - return doRegistryInjection; + + public boolean isBeard() { + return beard; } - - public Set getExcludedBiomeFeatures() { - return excludedBiomeFeatures; - } - - public Set getExcludedRegistryFeatures() { - return excludedRegistryFeatures; - } - - public Set getExcludedBiomeStructures() { - return excludedBiomeStructures; + + public double getBeardThreshold() { + return beardThreshold; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java new file mode 100644 index 000000000..52dbf7162 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/config/VanillaBiomeProperties.java @@ -0,0 +1,85 @@ +package com.dfsek.terra.fabric.config; + +import com.dfsek.tectonic.api.config.template.ConfigTemplate; +import com.dfsek.tectonic.api.config.template.annotations.Default; +import com.dfsek.tectonic.api.config.template.annotations.Value; +import net.minecraft.world.biome.Biome.Category; +import net.minecraft.world.biome.Biome.Precipitation; +import net.minecraft.world.biome.BiomeEffects.GrassColorModifier; + +import com.dfsek.terra.api.properties.Properties; + + +public class VanillaBiomeProperties implements ConfigTemplate, Properties { + @Value("colors.grass") + @Default + private Integer grassColor = null; + + @Value("colors.fog") + @Default + private Integer fogColor = null; + + @Value("colors.water") + @Default + private Integer waterColor = null; + + @Value("colors.water-fog") + @Default + private Integer waterFogColor = null; + + @Value("colors.foliage") + @Default + private Integer foliageColor = null; + + @Value("colors.sky") + @Default + private Integer skyColor = null; + + @Value("colors.modifier") + @Default + private GrassColorModifier modifier = null; + + @Value("climate.precipitation") + @Default + private Precipitation precipitation = null; + + @Value("climate.category") + @Default + private Category category = null; + + public Integer getFogColor() { + return fogColor; + } + + public Integer getFoliageColor() { + return foliageColor; + } + + public Integer getGrassColor() { + return grassColor; + } + + public Integer getWaterColor() { + return waterColor; + } + + public Integer getWaterFogColor() { + return waterFogColor; + } + + public Integer getSkyColor() { + return skyColor; + } + + public Category getCategory() { + return category; + } + + public Precipitation getPrecipitation() { + return precipitation; + } + + public GrassColorModifier getModifier() { + return modifier; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/data/Codecs.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/data/Codecs.java new file mode 100644 index 000000000..a1164de1e --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/data/Codecs.java @@ -0,0 +1,70 @@ +package com.dfsek.terra.fabric.data; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.registry.key.RegistryKey; +import com.dfsek.terra.fabric.FabricEntryPoint; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.generation.TerraBiomeSource; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.util.dynamic.RegistryOps; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; + + +public final class Codecs { + public static final Codec TERRA_REGISTRY_KEY = RecordCodecBuilder + .create(registryKey -> registryKey.group(Codec.STRING.fieldOf("namespace") + .stable() + .forGetter(RegistryKey::getNamespace), + Codec.STRING.fieldOf("id") + .stable() + .forGetter(RegistryKey::getID)) + .apply(registryKey, registryKey.stable(RegistryKey::of))); + + public static final Codec CONFIG_PACK = RecordCodecBuilder + .create(config -> config.group(TERRA_REGISTRY_KEY.fieldOf("pack") + .stable() + .forGetter(ConfigPack::getRegistryKey)) + .apply(config, config.stable(id -> FabricEntryPoint.getPlatform() + .getConfigRegistry() + .get(id) + .orElseThrow(() -> new IllegalArgumentException( + "No such config pack " + + id))))); + + public static final Codec TERRA_BIOME_SOURCE = RecordCodecBuilder + .create(instance -> instance.group(RegistryOps.createRegistryCodec(Registry.BIOME_KEY) + .fieldOf("biome_registry") + .stable() + .forGetter(TerraBiomeSource::getBiomeRegistry), + Codec.LONG.fieldOf("seed") + .stable() + .forGetter(TerraBiomeSource::getSeed), + CONFIG_PACK.fieldOf("pack") + .stable() + .forGetter(TerraBiomeSource::getPack)) + .apply(instance, instance.stable(TerraBiomeSource::new))); + + public static final Codec FABRIC_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder.create( + instance -> instance.group( + RegistryOps.createRegistryCodec(Registry.STRUCTURE_SET_KEY) + .fieldOf("structure_registry") + .stable() + .forGetter(FabricChunkGeneratorWrapper::getNoiseRegistry), + TERRA_BIOME_SOURCE.fieldOf("biome_source") + .stable() + .forGetter(FabricChunkGeneratorWrapper::getBiomeSource), + Codec.LONG.fieldOf("seed") + .stable() + .forGetter(FabricChunkGeneratorWrapper::getSeed), + CONFIG_PACK.fieldOf("pack") + .stable() + .forGetter(FabricChunkGeneratorWrapper::getPack), + ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings") + .stable() + .forGetter(FabricChunkGeneratorWrapper::getSettings) + ).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new)) + ); +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/BiomeRegistrationEvent.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/BiomeRegistrationEvent.java deleted file mode 100644 index 747645e67..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/BiomeRegistrationEvent.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.fabric.event; - -import com.dfsek.terra.api.event.events.Event; -import net.minecraft.util.registry.DynamicRegistryManager; - -/** - * Fired when biomes should be registered. - */ -public class BiomeRegistrationEvent implements Event { - private final DynamicRegistryManager registryManager; - - public BiomeRegistrationEvent(DynamicRegistryManager registryManager) { - this.registryManager = registryManager; - } - - public DynamicRegistryManager getRegistryManager() { - return registryManager; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/GameInitializationEvent.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/GameInitializationEvent.java deleted file mode 100644 index 1a2ca827f..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/event/GameInitializationEvent.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.dfsek.terra.fabric.event; - -import com.dfsek.terra.api.event.events.Event; - -/** - * Called when the game is initialized and packs should be registered. - */ -public class GameInitializationEvent implements Event { -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BeardGenerator.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BeardGenerator.java new file mode 100644 index 000000000..114320488 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/BeardGenerator.java @@ -0,0 +1,178 @@ +package com.dfsek.terra.fabric.generation; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; +import it.unimi.dsi.fastutil.objects.ObjectListIterator; +import net.minecraft.block.BlockState; +import net.minecraft.structure.JigsawJunction; +import net.minecraft.structure.PoolStructurePiece; +import net.minecraft.structure.StructurePiece; +import net.minecraft.structure.StructureStart; +import net.minecraft.structure.pool.StructurePool.Projection; +import net.minecraft.util.Util; +import net.minecraft.util.math.BlockBox; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.ChunkSectionPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.gen.StructureAccessor; +import net.minecraft.world.gen.StructureWeightType; + +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.info.WorldProperties; + + +// net.minecraft.world.gen.StructureWeightSampler +public class BeardGenerator { + private static final float[] STRUCTURE_WEIGHT_TABLE = Util.make(new float[13824], array -> { + for(int i = 0; i < 24; ++i) { + for(int j = 0; j < 24; ++j) { + for(int k = 0; k < 24; ++k) { + array[i * 24 * 24 + j * 24 + k] = (float) calculateStructureWeight(j - 12, k - 12, i - 12); + } + } + } + }); + private final ObjectList pieces; + private final ObjectList junctions; + private final ObjectListIterator pieceIterator; + private final ObjectListIterator junctionIterator; + private final Chunk chunk; + private final int minY; + private final int maxY; + + private final double threshold; + + public BeardGenerator(StructureAccessor structureAccessor, Chunk chunk, double threshold) { + this.chunk = chunk; + this.threshold = threshold; + ChunkPos chunkPos = chunk.getPos(); + int i = chunkPos.getStartX(); + int j = chunkPos.getStartZ(); + this.junctions = new ObjectArrayList<>(32); + this.pieces = new ObjectArrayList<>(10); + int minY = chunk.getBottomY(); + int maxY = chunk.getTopY(); + for(StructureStart start : structureAccessor.method_41035(ChunkSectionPos.from(chunk), + configuredStructureFeature -> configuredStructureFeature.field_37144)) { + for(StructurePiece structurePiece : start.getChildren()) { + if(!structurePiece.intersectsChunk(chunkPos, 12)) continue; + if(structurePiece instanceof PoolStructurePiece poolStructurePiece) { + Projection projection = poolStructurePiece.getPoolElement().getProjection(); + if(projection == Projection.RIGID) { + this.pieces.add(poolStructurePiece); + } + for(JigsawJunction jigsawJunction : poolStructurePiece.getJunctions()) { + int k = jigsawJunction.getSourceX(); + int l = jigsawJunction.getSourceZ(); + if(k <= i - 12 || l <= j - 12 || k >= i + 15 + 12 || l >= j + 15 + 12) continue; + maxY = Math.max(maxY, jigsawJunction.getSourceGroundY()); + minY = Math.min(minY, jigsawJunction.getSourceGroundY()); + this.junctions.add(jigsawJunction); + } + continue; + } + maxY = Math.max(maxY, structurePiece.getCenter().getY()); + minY = Math.min(minY, structurePiece.getCenter().getY()); + this.pieces.add(structurePiece); + } + } + this.pieceIterator = this.pieces.iterator(); + this.junctionIterator = this.junctions.iterator(); + this.minY = minY; + this.maxY = maxY; + } + + private static double getMagnitudeWeight(int x, int y, int z) { + double d = MathHelper.magnitude(x, (double) y / 2.0, z); + return MathHelper.clampedLerpFromProgress(d, 0.0, 6.0, 1.0, 0.0); + } + + /** + * Gets the structure weight from the array from the given position, or 0 if the position is out of bounds. + */ + private static double getStructureWeight(int x, int y, int z) { + int xOffset = x + 12; + int yOffset = y + 12; + int zOffset = z + 12; + if(xOffset < 0 || xOffset >= 24) { + return 0.0; + } + if(yOffset < 0 || yOffset >= 24) { + return 0.0; + } + if(zOffset < 0 || zOffset >= 24) { + return 0.0; + } + return STRUCTURE_WEIGHT_TABLE[zOffset * 24 * 24 + xOffset * 24 + yOffset]; + } + + /** + * Calculates the structure weight for the given position. + *

The weight increases as x and z approach {@code (0, 0)}, and positive y values make the weight negative while negative y + * values make the weight positive. + */ + private static double calculateStructureWeight(int x, int y, int z) { + double horizontalDistanceSquared = x * x + z * z; + double yOffset = y + 0.5; + double verticalSquared = yOffset * yOffset; + double naturalDistance = Math.pow(Math.E, -(verticalSquared / 16.0 + horizontalDistanceSquared / 16.0)); + double inverseSquareRootDistance = -yOffset * MathHelper.fastInverseSqrt(verticalSquared / 2.0 + horizontalDistanceSquared / 2.0) / + 2.0; + return inverseSquareRootDistance * naturalDistance; + } + + public void generate(ChunkGenerator generator, WorldProperties worldProperties, BiomeProvider biomeProvider) { + int xi = chunk.getPos().x << 4; + int zi = chunk.getPos().z << 4; + for(int x = 0; x < 16; x++) { + for(int z = 0; z < 16; z++) { + int depth = 0; + for(int y = maxY; y >= minY; y--) { + if(calculateNoise(x + xi, y, z + zi) > threshold) { + chunk.setBlockState(new BlockPos(x, y, z), (BlockState) generator + .getPalette(x + xi, y, z + zi, worldProperties, biomeProvider) + .get(depth, x + xi, y, z + zi, worldProperties.getSeed()), false); + depth++; + } else { + depth = 0; + } + } + } + } + } + + public double calculateNoise(int x, int y, int z) { + double noise = 0.0; + + while(this.pieceIterator.hasNext()) { + StructurePiece structurePiece = this.pieceIterator.next(); + BlockBox blockBox = structurePiece.getBoundingBox(); + int structureX = Math.max(0, Math.max(blockBox.getMinX() - x, x - blockBox.getMaxX())); + int structureY = y - (blockBox.getMinY() + (structurePiece instanceof PoolStructurePiece + ? ((PoolStructurePiece) structurePiece).getGroundLevelDelta() + : 0)); + int structureZ = Math.max(0, Math.max(blockBox.getMinZ() - z, z - blockBox.getMaxZ())); + StructureWeightType structureWeightType = structurePiece.getWeightType(); + if(structureWeightType == StructureWeightType.BURY) { + noise += getMagnitudeWeight(structureX, structureY, structureZ); + continue; + } + if(structureWeightType != StructureWeightType.BEARD) continue; + + noise += getStructureWeight(structureX, structureY, structureZ) * 0.8; + } + this.pieceIterator.back(this.pieces.size()); + while(this.junctionIterator.hasNext()) { + JigsawJunction structurePiece = this.junctionIterator.next(); + int structureX = x - structurePiece.getSourceX(); + int structureY = y - structurePiece.getSourceGroundY(); + int structureZ = z - structurePiece.getSourceZ(); + noise += getStructureWeight(structureX, structureY, structureZ) * 0.4; + } + this.junctionIterator.back(this.junctions.size()); + return noise; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java index cae1e2f90..b5f328239 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/FabricChunkGeneratorWrapper.java @@ -1,240 +1,228 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.generation; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkData; -import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.world.generation.Chunkified; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.api.world.locate.AsyncStructureFinder; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.dfsek.terra.fabric.block.FabricBlockData; -import com.dfsek.terra.fabric.mixin.StructureAccessorAccessor; -import com.dfsek.terra.fabric.util.FabricAdapter; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; -import com.dfsek.terra.world.population.items.TerraStructure; +import com.dfsek.terra.api.world.info.WorldProperties; + import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.block.BlockState; -import net.minecraft.entity.SpawnGroup; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.structure.StructureManager; -import net.minecraft.util.collection.Pool; +import net.minecraft.structure.StructureSet; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; import net.minecraft.world.ChunkRegion; import net.minecraft.world.HeightLimitView; import net.minecraft.world.Heightmap; import net.minecraft.world.SpawnHelper; +import net.minecraft.world.StructureWorldAccess; import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.SpawnSettings; import net.minecraft.world.biome.source.BiomeAccess; +import net.minecraft.world.biome.source.util.MultiNoiseUtil; import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.dimension.DimensionType; -import net.minecraft.world.gen.ChunkRandom; import net.minecraft.world.gen.GenerationStep; import net.minecraft.world.gen.StructureAccessor; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.gen.chunk.StructuresConfig; +import net.minecraft.world.gen.chunk.Blender; +import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; import net.minecraft.world.gen.chunk.VerticalBlockSample; -import net.minecraft.world.gen.feature.StructureFeature; -import org.jetbrains.annotations.Nullable; +import net.minecraft.world.gen.random.AtomicSimpleRandom; +import net.minecraft.world.gen.random.ChunkRandom; +import net.minecraft.world.gen.random.RandomSeed; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import java.util.Objects; +import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; -public class FabricChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { - public static final Codec PACK_CODEC = RecordCodecBuilder.create( - config -> config.group( - Codec.STRING.fieldOf("pack") - .forGetter(pack -> pack.getTemplate().getID()) - ).apply(config, config.stable(TerraFabricPlugin.getInstance().getConfigRegistry()::get))); +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.api.world.chunk.generation.stage.Chunkified; +import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; +import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.fabric.data.Codecs; +import com.dfsek.terra.fabric.mixin.access.StructureAccessorAccessor; +import com.dfsek.terra.fabric.util.FabricAdapter; - public static final Codec CODEC = RecordCodecBuilder.create( - instance -> instance.group( - TerraBiomeSource.CODEC.fieldOf("biome_source") - .forGetter(generator -> generator.biomeSource), - Codec.LONG.fieldOf("seed").stable() - .forGetter(generator -> generator.seed), - PACK_CODEC.fieldOf("pack").stable() - .forGetter(generator -> generator.pack) - ).apply(instance, instance.stable(FabricChunkGeneratorWrapper::new)) - ); +public class FabricChunkGeneratorWrapper extends net.minecraft.world.gen.chunk.ChunkGenerator implements GeneratorWrapper { + private static final Logger logger = LoggerFactory.getLogger(FabricChunkGeneratorWrapper.class); + private final long seed; - private final DefaultChunkGenerator3D delegate; private final TerraBiomeSource biomeSource; - - private final ConfigPack pack; - private DimensionType dimensionType; - - public FabricChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) { - super(biomeSource, new StructuresConfig(false)); + private final Registry noiseRegistry; + private final RegistryEntry settings; + private ChunkGenerator delegate; + private ConfigPack pack; + + public FabricChunkGeneratorWrapper(Registry noiseRegistry, TerraBiomeSource biomeSource, long seed, ConfigPack configPack, + RegistryEntry settingsSupplier) { + super(noiseRegistry, Optional.empty(), biomeSource, biomeSource, seed); + this.noiseRegistry = noiseRegistry; this.pack = configPack; - - this.delegate = new DefaultChunkGenerator3D(pack, TerraFabricPlugin.getInstance()); - delegate.getMain().logger().info("Loading world with config pack " + pack.getTemplate().getID()); + this.settings = settingsSupplier; + + this.delegate = pack.getGeneratorProvider().newInstance(pack); + logger.info("Loading world with config pack {}", pack.getID()); this.biomeSource = biomeSource; - + this.seed = seed; } - - + + public Registry getNoiseRegistry() { + return noiseRegistry; + } + @Override - protected Codec getCodec() { - return CODEC; + protected Codec getCodec() { + return Codecs.FABRIC_CHUNK_GENERATOR_WRAPPER; } - + @Override - public ChunkGenerator withSeed(long seed) { - return new FabricChunkGeneratorWrapper((TerraBiomeSource) this.biomeSource.withSeed(seed), seed, pack); + public net.minecraft.world.gen.chunk.ChunkGenerator withSeed(long seed) { + return new FabricChunkGeneratorWrapper(noiseRegistry, (TerraBiomeSource) this.biomeSource.withSeed(seed), seed, pack, settings); } - - public ConfigPack getPack() { - return pack; - } - + @Override - public void buildSurface(ChunkRegion region, Chunk chunk) { - // No-op + public MultiNoiseUtil.MultiNoiseSampler getMultiNoiseSampler() { + return MultiNoiseUtil.method_40443(); // zero } - - public void setDimensionType(DimensionType dimensionType) { - this.dimensionType = dimensionType; - } - - @Nullable + @Override - public BlockPos locateStructure(ServerWorld world, StructureFeature feature, BlockPos center, int radius, boolean skipExistingChunks) { - if(!pack.getTemplate().disableStructures()) { - String name = Objects.requireNonNull(Registry.STRUCTURE_FEATURE.getId(feature)).toString(); - TerraWorld terraWorld = TerraFabricPlugin.getInstance().getWorld((World) world); - TerraStructure located = pack.getStructure(pack.getTemplate().getLocatable().get(name)); - if(located != null) { - CompletableFuture result = new CompletableFuture<>(); - AsyncStructureFinder finder = new AsyncStructureFinder(terraWorld.getBiomeProvider(), located, FabricAdapter.adapt(center).toLocation((World) world), 0, 500, location -> { - result.complete(FabricAdapter.adapt(location)); - }, TerraFabricPlugin.getInstance()); - finder.run(); // Do this synchronously. - try { - return result.get(); - } catch(InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - } - } - return super.locateStructure(world, feature, center, radius, skipExistingChunks); + public void buildSurface(ChunkRegion region, StructureAccessor structures, Chunk chunk) { + // no op } - + @Override - public void carve(long seed, BiomeAccess access, Chunk chunk, GenerationStep.Carver carver) { - if(pack.getTemplate().vanillaCaves()) { - super.carve(seed, access, chunk, carver); - } + public void populateEntities(ChunkRegion region) { + ChunkPos chunkPos = region.getCenterPos(); + RegistryEntry biome = region.getBiome(chunkPos.getStartPos().withY(region.getTopY() - 1)); + ChunkRandom chunkRandom = new ChunkRandom(new AtomicSimpleRandom(RandomSeed.getSeed())); + chunkRandom.setPopulationSeed(region.getSeed(), chunkPos.getStartX(), chunkPos.getStartZ()); + SpawnHelper.populateEntities(region, biome, chunkPos, chunkRandom); } - + @Override - public void setStructureStarts(DynamicRegistryManager dynamicRegistryManager, StructureAccessor structureAccessor, Chunk chunk, StructureManager structureManager, long worldSeed) { - if(pack.getTemplate().vanillaStructures()) { - super.setStructureStarts(dynamicRegistryManager, structureAccessor, chunk, structureManager, worldSeed); - } + public int getWorldHeight() { + return settings.value().generationShapeConfig().height(); } - + @Override - public CompletableFuture populateNoise(Executor executor, StructureAccessor accessor, Chunk chunk) { + public CompletableFuture populateNoise(Executor executor, Blender arg, StructureAccessor structureAccessor, Chunk chunk) { return CompletableFuture.supplyAsync(() -> { - World world = (World) ((StructureAccessorAccessor) accessor).getWorld(); - delegate.generateChunkData(world, new FastRandom(), chunk.getPos().x, chunk.getPos().z, (ChunkData) chunk); - delegate.getPopulators().forEach(populator -> { - if(populator instanceof Chunkified) { - populator.populate(world, (com.dfsek.terra.api.platform.world.Chunk) world); - } - }); + ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(); + BiomeProvider biomeProvider = pack.getBiomeProvider().caching(world); + delegate.generateChunkData((ProtoChunk) chunk, world, biomeProvider, chunk.getPos().x, chunk.getPos().z); + + PreLoadCompatibilityOptions compatibilityOptions = pack.getContext().get(PreLoadCompatibilityOptions.class); + if(compatibilityOptions.isBeard()) { + new BeardGenerator(structureAccessor, chunk, compatibilityOptions.getBeardThreshold()).generate(delegate, world, + biomeProvider); + } return chunk; }, executor); } - + @Override - public boolean isStrongholdStartingChunk(ChunkPos chunkPos) { - if(pack.getTemplate().vanillaStructures()) { - return super.isStrongholdStartingChunk(chunkPos); - } - return false; - } - - @Override - public int getHeightOnGround(int x, int z, Heightmap.Type heightmap, HeightLimitView world) { - return super.getHeightOnGround(x, z, heightmap, world); - } - - @Override - public int getHeight(int x, int z, Heightmap.Type heightmap, HeightLimitView heightmapType) { - TerraWorld world = TerraFabricPlugin.getInstance().getWorld(dimensionType); - int height = world.getWorld().getMaxHeight(); - while(height >= world.getWorld().getMinHeight() && !heightmap.getBlockPredicate().test(((FabricBlockData) world.getUngeneratedBlock(x, height - 1, z)).getHandle())) { - height--; - } - return height; - } - - @Override - public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView view) { - TerraWorld world = TerraFabricPlugin.getInstance().getWorld(dimensionType); - BlockState[] array = new BlockState[view.getHeight()]; - for(int y = view.getBottomY() + view.getHeight() - 1; y >= view.getBottomY(); y--) { - array[y] = ((FabricBlockData) world.getUngeneratedBlock(x, y, z)).getHandle(); - } - return new VerticalBlockSample(view.getBottomY(), array); - } - - @Override - public void populateEntities(ChunkRegion region) { - if(pack.getTemplate().vanillaMobs()) { - int cx = region.getCenterPos().x; - int cy = region.getCenterPos().z; - Biome biome = region.getBiome((new ChunkPos(cx, cy)).getStartPos()); - ChunkRandom chunkRandom = new ChunkRandom(); - chunkRandom.setPopulationSeed(region.getSeed(), cx << 4, cy << 4); - SpawnHelper.populateEntities(region, biome, region.getCenterPos(), chunkRandom); - } - } - - public Pool getEntitySpawnList(Biome biome, StructureAccessor accessor, SpawnGroup group, BlockPos pos) { - if(accessor.getStructureAt(pos, true, StructureFeature.SWAMP_HUT).hasChildren()) { - if(group == SpawnGroup.MONSTER) { - return StructureFeature.SWAMP_HUT.getMonsterSpawns(); + public void generateFeatures(StructureWorldAccess world, Chunk chunk, StructureAccessor structureAccessor) { + super.generateFeatures(world, chunk, structureAccessor); + pack.getStages().forEach(populator -> { + if(!(populator instanceof Chunkified)) { + populator.populate((ProtoWorld) world); } - - if(group == SpawnGroup.CREATURE) { - return StructureFeature.SWAMP_HUT.getCreatureSpawns(); - } - } - - if(group == SpawnGroup.MONSTER) { - if(accessor.getStructureAt(pos, false, StructureFeature.PILLAGER_OUTPOST).hasChildren()) { - return StructureFeature.PILLAGER_OUTPOST.getMonsterSpawns(); - } - - if(accessor.getStructureAt(pos, false, StructureFeature.MONUMENT).hasChildren()) { - return StructureFeature.MONUMENT.getMonsterSpawns(); - } - - if(accessor.getStructureAt(pos, true, StructureFeature.FORTRESS).hasChildren()) { - return StructureFeature.FORTRESS.getMonsterSpawns(); - } - } - - return group == SpawnGroup.UNDERGROUND_WATER_CREATURE && accessor.getStructureAt(pos, false, StructureFeature.MONUMENT).hasChildren() ? StructureFeature.MONUMENT.getUndergroundWaterCreatureSpawns() : super.getEntitySpawnList(biome, accessor, group, pos); + }); } - + @Override - public TerraChunkGenerator getHandle() { + public int getSeaLevel() { + return settings.value().seaLevel(); + } + + @Override + public int getMinimumY() { + return settings.value().generationShapeConfig().minimumY(); + } + + @Override + public int getHeight(int x, int z, Heightmap.Type heightmap, HeightLimitView height) { + int y = height.getTopY(); + WorldProperties properties = FabricAdapter.adapt(height, seed); + BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); + while(y >= getMinimumY() && !heightmap.getBlockPredicate().test( + (BlockState) delegate.getBlock(properties, x, y - 1, z, biomeProvider))) { + y--; + } + return y; + } + + @Override + public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView height) { + BlockState[] array = new BlockState[height.getHeight()]; + WorldProperties properties = FabricAdapter.adapt(height, seed); + BiomeProvider biomeProvider = pack.getBiomeProvider().caching(properties); + for(int y = height.getTopY() - 1; y >= height.getBottomY(); y--) { + array[y - height.getBottomY()] = (BlockState) delegate.getBlock(properties, x, y, z, biomeProvider); + } + return new VerticalBlockSample(height.getBottomY(), array); + } + + @Override + public void getDebugHudText(List text, BlockPos pos) { + + } + + public ConfigPack getPack() { + return pack; + } + + public void setPack(ConfigPack pack) { + this.pack = pack; + this.delegate = pack.getGeneratorProvider().newInstance(pack); + biomeSource.setPack(pack); + + logger.debug("Loading world with config pack {}", pack.getID()); + } + + @Override + public void carve(ChunkRegion chunkRegion, long seed, BiomeAccess biomeAccess, StructureAccessor structureAccessor, Chunk chunk, + GenerationStep.Carver generationStep) { + + } + + @Override + public ChunkGenerator getHandle() { return delegate; } + + public long getSeed() { + return seed; + } + + public RegistryEntry getSettings() { + return settings; + } + + @Override + public TerraBiomeSource getBiomeSource() { + return biomeSource; + } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/PopulatorFeature.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/PopulatorFeature.java deleted file mode 100644 index 99a30d378..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/PopulatorFeature.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.dfsek.terra.fabric.generation; - -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.world.generation.Chunkified; -import com.mojang.serialization.Codec; -import net.minecraft.world.StructureWorldAccess; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.gen.feature.DefaultFeatureConfig; -import net.minecraft.world.gen.feature.Feature; -import net.minecraft.world.gen.feature.util.FeatureContext; - -/** - * Feature wrapper for Terra populator - */ -public class PopulatorFeature extends Feature { - public PopulatorFeature(Codec codec) { - super(codec); - } - - @Override - public boolean generate(FeatureContext context) { - ChunkGenerator chunkGenerator = context.getGenerator(); - if(!(chunkGenerator instanceof FabricChunkGeneratorWrapper)) return true; - StructureWorldAccess world = context.getWorld(); - FabricChunkGeneratorWrapper gen = (FabricChunkGeneratorWrapper) chunkGenerator; - gen.getHandle().getPopulators().forEach(populator -> { - if(!(populator instanceof Chunkified)) { - populator.populate((World) world, (Chunk) world); - } - }); - return true; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java index d8ee36830..e90e5d46c 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraBiomeSource.java @@ -1,59 +1,95 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.generation; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.dfsek.terra.fabric.util.FabricUtil; -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.util.Identifier; -import net.minecraft.util.dynamic.RegistryLookupCodec; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.source.BiomeSource; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.fabric.data.Codecs; +import com.dfsek.terra.fabric.util.ProtoPlatformBiome; + +import com.mojang.serialization.Codec; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.world.biome.source.BiomeSource; +import net.minecraft.world.biome.source.util.MultiNoiseUtil.MultiNoiseSampler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.stream.StreamSupport; -import java.util.Objects; -import java.util.stream.Collectors; public class TerraBiomeSource extends BiomeSource { - public static final Codec PACK_CODEC = (RecordCodecBuilder.create(config -> config.group( - Codec.STRING.fieldOf("pack").forGetter(pack -> pack.getTemplate().getID()) - ).apply(config, config.stable(TerraFabricPlugin.getInstance().getConfigRegistry()::get)))); - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - RegistryLookupCodec.of(Registry.BIOME_KEY).forGetter(source -> source.biomeRegistry), - Codec.LONG.fieldOf("seed").stable().forGetter(source -> source.seed), - PACK_CODEC.fieldOf("pack").stable().forGetter(source -> source.pack)) - .apply(instance, instance.stable(TerraBiomeSource::new))); - - private final Registry biomeRegistry; + + private static final Logger LOGGER = LoggerFactory.getLogger(TerraBiomeSource.class); + private final Registry biomeRegistry; private final long seed; - private final BiomeProvider grid; - private final ConfigPack pack; - - public TerraBiomeSource(Registry biomes, long seed, ConfigPack pack) { - super(biomes.stream() - .filter(biome -> Objects.requireNonNull(biomes.getId(biome)).getNamespace().equals("terra")) // Filter out non-Terra biomes. - .collect(Collectors.toList())); + private ConfigPack pack; + + public TerraBiomeSource(Registry biomes, long seed, ConfigPack pack) { + super(StreamSupport + .stream(pack.getBiomeProvider() + .getBiomes() + .spliterator(), false) + .map(b -> biomes.getOrCreateEntry(((ProtoPlatformBiome) b.getPlatformBiome()).getDelegate()))); this.biomeRegistry = biomes; this.seed = seed; - this.grid = pack.getBiomeProviderBuilder().build(seed); this.pack = pack; + + LOGGER.debug("Biomes: " + getBiomes()); } - + @Override protected Codec getCodec() { - return CODEC; + return Codecs.TERRA_BIOME_SOURCE; } - + @Override public BiomeSource withSeed(long seed) { return new TerraBiomeSource(this.biomeRegistry, seed, pack); } - + @Override - public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) { - UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX << 2, biomeZ << 2); - return biomeRegistry.get(new Identifier("terra", FabricUtil.createBiomeID(pack, biome.getID()))); + public RegistryEntry getBiome(int biomeX, int biomeY, int biomeZ, MultiNoiseSampler noiseSampler) { + return biomeRegistry + .entryOf(((ProtoPlatformBiome) pack + .getBiomeProvider() + .getBiome(biomeX << 2, biomeY << 2, biomeZ << 2, seed) + .getPlatformBiome()).getDelegate() + ); + } + + public BiomeProvider getProvider() { + return pack.getBiomeProvider(); + } + + public Registry getBiomeRegistry() { + return biomeRegistry; + } + + public ConfigPack getPack() { + return pack; + } + + public void setPack(ConfigPack pack) { + this.pack = pack; + } + + public long getSeed() { + return seed; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraGeneratorType.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraGeneratorType.java index fb842a330..9b2dfa40f 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraGeneratorType.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/generation/TerraGeneratorType.java @@ -1,38 +1,51 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.generation; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.dfsek.terra.fabric.event.BiomeRegistrationEvent; -import com.dfsek.terra.fabric.util.FabricUtil; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.world.GeneratorType; -import net.minecraft.util.Identifier; +import net.minecraft.structure.StructureSet; import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.Registry; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.GeneratorOptions; +import net.minecraft.util.registry.RegistryEntry; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; +import com.dfsek.terra.api.config.ConfigPack; + + @Environment(EnvType.CLIENT) public class TerraGeneratorType extends GeneratorType { private final ConfigPack pack; - + public TerraGeneratorType(ConfigPack pack) { - super("terra." + pack.getTemplate().getID()); + super("terra." + pack.getID()); this.pack = pack; } - + @Override - public GeneratorOptions createDefaultOptions(DynamicRegistryManager.Impl registryManager, long seed, boolean generateStructures, boolean bonusChest) { - GeneratorOptions options = super.createDefaultOptions(registryManager, seed, generateStructures, bonusChest); - TerraFabricPlugin.getInstance().getEventManager().callEvent(new BiomeRegistrationEvent(registryManager)); // register biomes - return options; - } - - @Override - protected ChunkGenerator getChunkGenerator(Registry biomeRegistry, Registry chunkGeneratorSettingsRegistry, long seed) { - return new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); + protected ChunkGenerator getChunkGenerator(DynamicRegistryManager manager, long seed) { + Registry chunkGeneratorSettingsRegistry = manager.get(Registry.CHUNK_GENERATOR_SETTINGS_KEY); + RegistryEntry + settingsSupplier = chunkGeneratorSettingsRegistry.getEntry(ChunkGeneratorSettings.OVERWORLD).orElseThrow(); + Registry noiseRegistry = manager.get(Registry.STRUCTURE_SET_KEY); + return new FabricChunkGeneratorWrapper(noiseRegistry, new TerraBiomeSource(manager.get(Registry.BIOME_KEY), seed, pack), seed, pack, + settingsSupplier); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricItemHandle.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricItemHandle.java index 4ea99a542..6084a68ac 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricItemHandle.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricItemHandle.java @@ -1,8 +1,22 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.handle; -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.command.argument.ItemStackArgumentType; @@ -12,8 +26,13 @@ import net.minecraft.util.registry.Registry; import java.util.Set; import java.util.stream.Collectors; -public class FabricItemHandle implements ItemHandle { +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.item.Enchantment; + +public class FabricItemHandle implements ItemHandle { + @Override public Item createItem(String data) { try { @@ -22,12 +41,12 @@ public class FabricItemHandle implements ItemHandle { throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e); } } - + @Override public Enchantment getEnchantment(String id) { return (Enchantment) (Registry.ENCHANTMENT.get(Identifier.tryParse(id))); } - + @Override public Set getEnchantments() { return Registry.ENCHANTMENT.stream().map(enchantment -> (Enchantment) enchantment).collect(Collectors.toSet()); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java index 1f801f1d0..50b0083e5 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/handle/FabricWorldHandle.java @@ -1,50 +1,60 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.handle; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.dfsek.terra.fabric.block.FabricBlockData; -import com.dfsek.terra.fabric.util.FabricAdapter; -import com.dfsek.terra.fabric.util.WorldEditUtil; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; import net.minecraft.command.argument.BlockArgumentParser; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; +import org.jetbrains.annotations.NotNull; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.handle.WorldHandle; -import java.util.Locale; public class FabricWorldHandle implements WorldHandle { - + + private static final BlockState AIR = (BlockState) Blocks.AIR.getDefaultState(); + @Override - public FabricBlockData createBlockData(String data) { + public @NotNull BlockState createBlockState(@NotNull String data) { BlockArgumentParser parser = new BlockArgumentParser(new StringReader(data), true); try { - BlockState state = parser.parse(true).getBlockState(); + net.minecraft.block.BlockState state = parser.parse(true).getBlockState(); if(state == null) throw new IllegalArgumentException("Invalid data: " + data); - return FabricAdapter.adapt(state); + return (BlockState) state; } catch(CommandSyntaxException e) { throw new IllegalArgumentException(e); } } - + @Override - public EntityType getEntity(String id) { + public @NotNull BlockState air() { + return AIR; + } + + @Override + public @NotNull EntityType getEntity(@NotNull String id) { Identifier identifier = Identifier.tryParse(id); - if(identifier == null) identifier = Identifier.tryParse("minecraft:" + id.toLowerCase(Locale.ROOT)); + if(identifier == null) identifier = Identifier.tryParse(id); return (EntityType) Registry.ENTITY_TYPE.get(identifier); } - - @Override - public Pair getSelectedLocation(Player player) { - try { - Class.forName("com.sk89q.worldedit.WorldEdit"); - } catch(ClassNotFoundException e) { - throw new IllegalStateException("WorldEdit is not installed."); - } - return WorldEditUtil.getSelection(player); - } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/CommandManagerMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/CommandManagerMixin.java deleted file mode 100644 index 2e98614df..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/CommandManagerMixin.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.dfsek.terra.fabric.mixin; - -import com.dfsek.terra.api.command.exception.CommandException; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.LiteralText; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static net.minecraft.server.command.CommandManager.argument; -import static net.minecraft.server.command.CommandManager.literal; - -@Mixin(CommandManager.class) -public abstract class CommandManagerMixin { - @Shadow - @Final - private CommandDispatcher dispatcher; - - @Inject(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/brigadier/CommandDispatcher;findAmbiguities(Lcom/mojang/brigadier/AmbiguityConsumer;)V", remap = false)) - private void injectTerraCommands(CommandManager.RegistrationEnvironment environment, CallbackInfo ci) { - com.dfsek.terra.api.command.CommandManager manager = TerraFabricPlugin.getInstance().getManager(); - int max = manager.getMaxArgumentDepth(); - RequiredArgumentBuilder arg = argument("arg" + (max - 1), StringArgumentType.word()); - for(int i = 0; i < max; i++) { - RequiredArgumentBuilder next = argument("arg" + (max - i - 1), StringArgumentType.word()); - - arg = next.then(assemble(arg, manager)); - } - - dispatcher.register(literal("terra").executes(context -> 1).then(assemble(arg, manager))); - dispatcher.register(literal("te").executes(context -> 1).then(assemble(arg, manager))); - } - - private RequiredArgumentBuilder assemble(RequiredArgumentBuilder in, com.dfsek.terra.api.command.CommandManager manager) { - return in.suggests((context, builder) -> { - List args = parseCommand(context.getInput()); - CommandSender sender = (CommandSender) context.getSource(); - try { - sender = (Entity) context.getSource().getEntityOrThrow(); - } catch(CommandSyntaxException ignore) { - } - try { - manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest); - } catch(CommandException e) { - sender.sendMessage(e.getMessage()); - } - return builder.buildFuture(); - }).executes(context -> { - List args = parseCommand(context.getInput()); - CommandSender sender = (CommandSender) context.getSource(); - try { - sender = (Entity) context.getSource().getEntityOrThrow(); - } catch(CommandSyntaxException ignore) { - } - try { - manager.execute(args.remove(0), sender, args); - } catch(CommandException e) { - context.getSource().sendError(new LiteralText(e.getMessage())); - } - return 1; - }); - } - - private List parseCommand(String command) { - if(command.startsWith("/terra ")) command = command.substring("/terra ".length()); - else if(command.startsWith("/te ")) command = command.substring("/te ".length()); - List c = new ArrayList<>(Arrays.asList(command.split(" "))); - if(command.endsWith(" ")) c.add(""); - return c; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/ServerWorldMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/ServerWorldMixin.java deleted file mode 100644 index b3d5d7c97..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/ServerWorldMixin.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.fabric.mixin; - -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.world.TerraWorld; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.WorldGenerationProgressListener; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.registry.RegistryKey; -import net.minecraft.world.World; -import net.minecraft.world.dimension.DimensionType; -import net.minecraft.world.gen.Spawner; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.level.ServerWorldProperties; -import net.minecraft.world.level.storage.LevelStorage; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.List; -import java.util.concurrent.Executor; - -@Mixin(ServerWorld.class) -public abstract class ServerWorldMixin { - @Inject(method = "", at = @At(value = "RETURN")) - public void injectConstructor(MinecraftServer server, Executor workerExecutor, LevelStorage.Session session, ServerWorldProperties properties, RegistryKey registryKey, DimensionType dimensionType, WorldGenerationProgressListener worldGenerationProgressListener, ChunkGenerator chunkGenerator, boolean debugWorld, long l, List list, boolean bl, CallbackInfo ci) { - if(chunkGenerator instanceof FabricChunkGeneratorWrapper) { - TerraFabricPlugin.getInstance().getWorldMap().put(dimensionType, Pair.of((ServerWorld) (Object) this, new TerraWorld((com.dfsek.terra.api.platform.world.World) this, ((FabricChunkGeneratorWrapper) chunkGenerator).getPack(), TerraFabricPlugin.getInstance()))); - ((FabricChunkGeneratorWrapper) chunkGenerator).setDimensionType(dimensionType); - TerraFabricPlugin.getInstance().logger().info("Registered world " + this + " to dimension type " + dimensionType); - } - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/StructureAccessorAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/StructureAccessorAccessor.java deleted file mode 100644 index 888c8cd83..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/StructureAccessorAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.fabric.mixin; - -import net.minecraft.world.WorldAccess; -import net.minecraft.world.gen.StructureAccessor; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(StructureAccessor.class) -public interface StructureAccessorAccessor { - @Accessor - WorldAccess getWorld(); -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/BiomeEffectsAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/BiomeEffectsAccessor.java deleted file mode 100644 index 2fe2391dc..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/BiomeEffectsAccessor.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.dfsek.terra.fabric.mixin.access; - -import net.minecraft.world.biome.BiomeEffects; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Optional; - -@Mixin(BiomeEffects.class) -public interface BiomeEffectsAccessor { - @Accessor("fogColor") - int getFogColor(); - - @Accessor("waterColor") - int getWaterColor(); - - @Accessor("waterFogColor") - int getWaterFogColor(); - - @Accessor("skyColor") - int getSkyColor(); - - @Accessor("foliageColor") - Optional getFoliageColor(); - - @Accessor("grassColor") - Optional getGrassColor(); - - @Accessor("grassColorModifier") - BiomeEffects.GrassColorModifier getGrassColorModifier(); -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/GeneratorTypeAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/GeneratorTypeAccessor.java index bd315cc54..0b218a0ed 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/GeneratorTypeAccessor.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/GeneratorTypeAccessor.java @@ -1,3 +1,20 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.access; import net.minecraft.client.world.GeneratorType; @@ -8,14 +25,15 @@ import org.spongepowered.asm.mixin.gen.Accessor; import java.util.List; + @Mixin(GeneratorType.class) public interface GeneratorTypeAccessor { @Accessor("VALUES") static List getValues() { throw new UnsupportedOperationException(); } - + @Mutable - @Accessor("translationKey") - void setTranslationKey(Text translationKey); + @Accessor("displayName") + void setDisplayName(Text translationKey); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java index e1d051d08..28cda62be 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/MobSpawnerLogicAccessor.java @@ -1,14 +1,30 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.access; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; +import net.minecraft.world.MobSpawnerEntry; import net.minecraft.world.MobSpawnerLogic; -import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; +import org.spongepowered.asm.mixin.gen.Accessor; + @Mixin(MobSpawnerLogic.class) public interface MobSpawnerLogicAccessor { - @Invoker("getEntityId") - Identifier callGetEntityId(World world, BlockPos blockPos); + @Accessor("spawnEntry") + MobSpawnerEntry getSpawnEntry(); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StateAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StateAccessor.java index 8518443af..1ec51c2dc 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StateAccessor.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StateAccessor.java @@ -1,3 +1,20 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.access; import net.minecraft.state.State; @@ -8,6 +25,7 @@ import org.spongepowered.asm.mixin.gen.Accessor; import java.util.Map; import java.util.function.Function; + @Mixin(State.class) public interface StateAccessor { @Accessor("PROPERTY_MAP_PRINTER") diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StructureAccessorAccessor.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StructureAccessorAccessor.java new file mode 100644 index 000000000..da33618d2 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/access/StructureAccessorAccessor.java @@ -0,0 +1,30 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.fabric.mixin.access; + +import net.minecraft.world.WorldAccess; +import net.minecraft.world.gen.StructureAccessor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + + +@Mixin(StructureAccessor.class) +public interface StructureAccessorAccessor { + @Accessor + WorldAccess getWorld(); +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/compat/GenerationSettingsFloraFeaturesMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/compat/GenerationSettingsFloraFeaturesMixin.java new file mode 100644 index 000000000..f625fb1ba --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/compat/GenerationSettingsFloraFeaturesMixin.java @@ -0,0 +1,32 @@ +package com.dfsek.terra.fabric.mixin.compat; + +import com.dfsek.terra.fabric.util.FloraFeatureHolder; + +import net.minecraft.world.biome.GenerationSettings; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + + +@Mixin(GenerationSettings.class) +@Implements(@Interface(iface = FloraFeatureHolder.class, prefix = "terra$")) +public class GenerationSettingsFloraFeaturesMixin { + private List> flora; + + public void terra$setFloraFeatures(List> features) { + this.flora = features; + } + + @Inject(method = "getFlowerFeatures", cancellable = true, at = @At("HEAD")) + public void inject(CallbackInfoReturnable>> cir) { + if(flora != null) { + cir.setReturnValue(flora); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java index 4a928cbb6..aedbe6332 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/BiomeMixin.java @@ -1,16 +1,31 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations; import net.minecraft.world.biome.Biome; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; +import com.dfsek.terra.api.world.biome.PlatformBiome; + + @Mixin(Biome.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.world.Biome.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = PlatformBiome.class, prefix = "terra$")) public abstract class BiomeMixin { - @Intrinsic - public Object terra$getHandle() { - return this; - } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ChunkGeneratorMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ChunkGeneratorMixin.java deleted file mode 100644 index cc7b82e80..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ChunkGeneratorMixin.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.fabric.mixin.implementations; - -import net.minecraft.world.gen.chunk.ChunkGenerator; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(ChunkGenerator.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.world.generator.ChunkGenerator.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ChunkGeneratorMixin { - @Intrinsic - public Object terra$getHandle() { - return this; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ConfiguredFeatureMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ConfiguredFeatureMixin.java deleted file mode 100644 index 0398a2d4c..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/ConfiguredFeatureMixin.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dfsek.terra.fabric.mixin.implementations; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.dfsek.terra.profiler.ProfileFrame; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.registry.BuiltinRegistries; -import net.minecraft.world.StructureWorldAccess; -import net.minecraft.world.gen.chunk.ChunkGenerator; -import net.minecraft.world.gen.feature.ConfiguredFeature; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Locale; -import java.util.Random; - -@Mixin(ConfiguredFeature.class) -@Implements(@Interface(iface = Tree.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ConfiguredFeatureMixin { - @Shadow - public abstract boolean generate(StructureWorldAccess world, ChunkGenerator chunkGenerator, Random random, BlockPos pos); - - @SuppressWarnings({"ConstantConditions", "try"}) - public boolean terra$plant(Location l, Random r) { - String id = BuiltinRegistries.CONFIGURED_FEATURE.getId((ConfiguredFeature) (Object) this).toString(); - try(ProfileFrame ignore = TerraFabricPlugin.getInstance().getProfiler().profile("fabric_tree:" + id.toLowerCase(Locale.ROOT))) { - StructureWorldAccess fabricWorldAccess = ((StructureWorldAccess) l.getWorld()); - ChunkGenerator generatorWrapper = (ChunkGenerator) l.getWorld().getGenerator(); - return generate(fabricWorldAccess, generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ())); - } - } - - public MaterialSet terra$getSpawnable() { - return MaterialSet.get(TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:grass_block"), - TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:podzol"), - TerraFabricPlugin.getInstance().getWorldHandle().createBlockData("minecraft:mycelium")); - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/HandleImplementationMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/HandleImplementationMixin.java new file mode 100644 index 000000000..edf5d7e69 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/HandleImplementationMixin.java @@ -0,0 +1,61 @@ +package com.dfsek.terra.fabric.mixin.implementations; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.LockableContainerBlockEntity; +import net.minecraft.block.entity.LootableContainerBlockEntity; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.world.ChunkRegion; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.ProtoChunk; +import net.minecraft.world.chunk.WorldChunk; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.Handle; + + +/** + * A ton of Minecraft classes must implement Handle identically, we can just take care of it here + */ +@Mixin({ + ServerWorld.class, + ChunkRegion.class, + + Block.class, + BlockState.class, + + BlockEntity.class, + LootableContainerBlockEntity.class, + LockableContainerBlockEntity.class, + + ProtoChunk.class, + WorldChunk.class, + + Entity.class, + EntityType.class, + + ServerCommandSource.class, + + Item.class, + ItemStack.class, + Enchantment.class, + + Biome.class +}) +@Implements(@Interface(iface = Handle.class, prefix = "terra$")) +public class HandleImplementationMixin { + @Intrinsic + public Object terra$getHandle() { + return this; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockEntityMixin.java deleted file mode 100644 index 5082204d9..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockEntityMixin.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.dfsek.terra.fabric.mixin.implementations.block; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.fabric.block.FabricBlock; -import com.dfsek.terra.fabric.util.FabricAdapter; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(BlockEntity.class) -@Implements(@Interface(iface = BlockState.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class BlockEntityMixin { - @Final - @Shadow - protected BlockPos pos; - @Shadow - @Nullable - protected World world; - - @Shadow - public abstract net.minecraft.block.BlockState getCachedState(); - - @Shadow - public abstract boolean hasWorld(); - - @Intrinsic - public Object terra$getHandle() { - return this; - } - - public Block terra$getBlock() { - return new FabricBlock(pos, world); - } - - public int terra$getX() { - return pos.getX(); - } - - public int terra$getY() { - return pos.getY(); - } - - public int terra$getZ() { - return pos.getZ(); - } - - public BlockData terra$getBlockData() { - return FabricAdapter.adapt(getCachedState()); - } - - public boolean terra$update(boolean applyPhysics) { - if(hasWorld()) world.getChunk(pos).setBlockEntity((BlockEntity) (Object) this); - return true; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java index 579b404f8..8f0167ab6 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/BlockMixin.java @@ -1,36 +1,42 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.fabric.util.FabricAdapter; import net.minecraft.block.Block; -import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; + +import com.dfsek.terra.api.block.BlockType; + @Mixin(Block.class) -@Implements(@Interface(iface = BlockType.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = BlockType.class, prefix = "terra$")) public abstract class BlockMixin { - @Shadow - private BlockState defaultState; - - @Intrinsic - public Object terra$getHandle() { - return this; + public com.dfsek.terra.api.block.state.BlockState terra$getDefaultState() { + return (com.dfsek.terra.api.block.state.BlockState) ((Block) (Object) this).getDefaultState(); } - - public BlockData terra$getDefaultData() { - return FabricAdapter.adapt(defaultState); - } - + public boolean terra$isSolid() { - return defaultState.isOpaque(); + return ((Block) (Object) this).getDefaultState().isOpaque(); } - + @SuppressWarnings("ConstantConditions") public boolean terra$isWater() { return ((Object) this) == Blocks.WATER; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/BlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/BlockEntityMixin.java new file mode 100644 index 000000000..cb501f580 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/BlockEntityMixin.java @@ -0,0 +1,54 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.fabric.mixin.implementations.block.entity; + +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; + + +@Mixin(net.minecraft.block.entity.BlockEntity.class) +@Implements(@Interface(iface = BlockEntity.class, prefix = "terra$")) +public abstract class BlockEntityMixin { + public boolean terra$update(boolean applyPhysics) { + if(((net.minecraft.block.entity.BlockEntity) (Object) this).hasWorld()) //noinspection ConstantConditions + ((net.minecraft.block.entity.BlockEntity) (Object) this).getWorld().getChunk( + ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos()).setBlockEntity( + (net.minecraft.block.entity.BlockEntity) (Object) this); + return true; + } + + public int terra$getX() { + return ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos().getX(); + } + + public int terra$getY() { + return ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos().getY(); + } + + public int terra$getZ() { + return ((net.minecraft.block.entity.BlockEntity) (Object) this).getPos().getZ(); + } + + public BlockState terra$getBlockState() { + return (BlockState) ((net.minecraft.block.entity.BlockEntity) (Object) this).getCachedState(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/LootableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/LootableContainerBlockEntityMixin.java new file mode 100644 index 000000000..ffa217be9 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/LootableContainerBlockEntityMixin.java @@ -0,0 +1,35 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.fabric.mixin.implementations.block.entity; + +import net.minecraft.block.entity.LootableContainerBlockEntity; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; + +import com.dfsek.terra.api.block.entity.Container; +import com.dfsek.terra.api.inventory.Inventory; + + +@Mixin(LootableContainerBlockEntity.class) +@Implements(@Interface(iface = Container.class, prefix = "terra$")) +public abstract class LootableContainerBlockEntityMixin extends BlockEntityMixin { + public Inventory terra$getInventory() { + return (Inventory) this; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/MobSpawnerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/MobSpawnerBlockEntityMixin.java similarity index 53% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/MobSpawnerBlockEntityMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/MobSpawnerBlockEntityMixin.java index f678ab0a7..2f0363190 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/MobSpawnerBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/MobSpawnerBlockEntityMixin.java @@ -1,127 +1,130 @@ -package com.dfsek.terra.fabric.mixin.implementations.block.state; +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.fabric.mixin.implementations.block.entity; -import com.dfsek.terra.api.platform.block.state.MobSpawner; -import com.dfsek.terra.api.platform.block.state.SerialState; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.dfsek.terra.fabric.mixin.access.MobSpawnerLogicAccessor; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.MobSpawnerBlockEntity; +import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; import net.minecraft.world.MobSpawnerLogic; -import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import com.dfsek.terra.api.block.entity.MobSpawner; +import com.dfsek.terra.api.block.entity.SerialState; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.fabric.FabricEntryPoint; +import com.dfsek.terra.fabric.mixin.access.MobSpawnerLogicAccessor; + + @Mixin(MobSpawnerBlockEntity.class) -@Implements(@Interface(iface = MobSpawner.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = MobSpawner.class, prefix = "terra$")) public abstract class MobSpawnerBlockEntityMixin extends BlockEntity { private MobSpawnerBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { super(type, pos, state); } - + @Shadow public abstract MobSpawnerLogic getLogic(); - + public EntityType terra$getSpawnedType() { - return (EntityType) Registry.ENTITY_TYPE.get(((MobSpawnerLogicAccessor) getLogic()).callGetEntityId(world, pos)); + return (EntityType) Registry.ENTITY_TYPE.get( + Identifier.tryParse(((MobSpawnerLogicAccessor) getLogic()).getSpawnEntry().getNbt().getString("id"))); } - + public void terra$setSpawnedType(@NotNull EntityType creatureType) { getLogic().setEntityId((net.minecraft.entity.EntityType) creatureType); } - + public int terra$getDelay() { return 0; } - + public void terra$setDelay(int delay) { } - + public int terra$getMinSpawnDelay() { return 0; } - + public void terra$setMinSpawnDelay(int delay) { } - + public int terra$getMaxSpawnDelay() { return 0; } - + public void terra$setMaxSpawnDelay(int delay) { } - + public int terra$getSpawnCount() { return 0; } - + public void terra$setSpawnCount(int spawnCount) { } - + public int terra$getMaxNearbyEntities() { return 0; } - + public void terra$setMaxNearbyEntities(int maxNearbyEntities) { } - + public int terra$getRequiredPlayerRange() { return 0; } - + public void terra$setRequiredPlayerRange(int requiredPlayerRange) { } - + public int terra$getSpawnRange() { return 0; } - + public void terra$setSpawnRange(int spawnRange) { } - + public void terra$applyState(String state) { SerialState.parse(state).forEach((k, v) -> { switch(k) { - case "type": - terra$setSpawnedType(TerraFabricPlugin.getInstance().getWorldHandle().getEntity(v)); - return; - case "delay": - terra$setDelay(Integer.parseInt(v)); - return; - case "min_delay": - terra$setMinSpawnDelay(Integer.parseInt(v)); - return; - case "max_delay": - terra$setMaxSpawnDelay(Integer.parseInt(v)); - return; - case "spawn_count": - terra$setSpawnCount(Integer.parseInt(v)); - return; - case "spawn_range": - terra$setSpawnRange(Integer.parseInt(v)); - return; - case "max_nearby": - terra$setMaxNearbyEntities(Integer.parseInt(v)); - return; - case "required_player_range": - terra$setRequiredPlayerRange(Integer.parseInt(v)); - return; - default: - throw new IllegalArgumentException("Invalid property: " + k); + case "type" -> terra$setSpawnedType(FabricEntryPoint.getPlatform().getWorldHandle().getEntity(v)); + case "delay" -> terra$setDelay(Integer.parseInt(v)); + case "min_delay" -> terra$setMinSpawnDelay(Integer.parseInt(v)); + case "max_delay" -> terra$setMaxSpawnDelay(Integer.parseInt(v)); + case "spawn_count" -> terra$setSpawnCount(Integer.parseInt(v)); + case "spawn_range" -> terra$setSpawnRange(Integer.parseInt(v)); + case "max_nearby" -> terra$setMaxNearbyEntities(Integer.parseInt(v)); + case "required_player_range" -> terra$setRequiredPlayerRange(Integer.parseInt(v)); + default -> throw new IllegalArgumentException("Invalid property: " + k); } }); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/SignBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/SignBlockEntityMixin.java similarity index 60% rename from platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/SignBlockEntityMixin.java rename to platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/SignBlockEntityMixin.java index c9dd3f065..41bdc67c3 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/SignBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/entity/SignBlockEntityMixin.java @@ -1,7 +1,22 @@ -package com.dfsek.terra.fabric.mixin.implementations.block.state; +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.fabric.mixin.implementations.block.entity; -import com.dfsek.terra.api.platform.block.state.SerialState; -import com.dfsek.terra.api.platform.block.state.Sign; import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; @@ -12,16 +27,24 @@ import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -@Mixin(SignBlockEntity.class) -@Implements(@Interface(iface = Sign.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class SignBlockEntityMixin { - @Shadow - public abstract void setTextOnRow(int row, Text text); +import com.dfsek.terra.api.block.entity.SerialState; +import com.dfsek.terra.api.block.entity.Sign; + +@Mixin(SignBlockEntity.class) +@Implements(@Interface(iface = Sign.class, prefix = "terra$")) +public abstract class SignBlockEntityMixin { @Shadow @Final private Text[] texts; - + + @Shadow + public abstract void setTextOnRow(int row, Text text); + + public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { + setTextOnRow(index, new LiteralText(line)); + } + public @NotNull String[] terra$getLines() { String[] lines = new String[texts.length]; for(int i = 0; i < texts.length; i++) { @@ -29,15 +52,11 @@ public abstract class SignBlockEntityMixin { } return lines; } - + public @NotNull String terra$getLine(int index) throws IndexOutOfBoundsException { return texts[index].asString(); } - - public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { - setTextOnRow(index, new LiteralText(line)); - } - + public void terra$applyState(String state) { SerialState.parse(state).forEach((k, v) -> { if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/BlockStateMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/BlockStateMixin.java new file mode 100644 index 000000000..4963fc4cb --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/BlockStateMixin.java @@ -0,0 +1,83 @@ +package com.dfsek.terra.fabric.mixin.implementations.block.state; + + +import com.google.common.collect.ImmutableMap; +import com.mojang.serialization.MapCodec; +import net.minecraft.block.AbstractBlock.AbstractBlockState; +import net.minecraft.block.Block; +import net.minecraft.state.State; +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.stream.Collectors; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.block.state.properties.Property; +import com.dfsek.terra.fabric.mixin.access.StateAccessor; + + +@Mixin(AbstractBlockState.class) +@Implements(@Interface(iface = BlockState.class, prefix = "terra$")) +public abstract class BlockStateMixin extends State { + private BlockStateMixin(Block owner, ImmutableMap, Comparable> entries, + MapCodec codec) { + super(owner, entries, codec); + } + + @Shadow + public abstract Block getBlock(); + + @Shadow + public abstract boolean isAir(); + + public boolean terra$matches(BlockState other) { + return getBlock() == ((net.minecraft.block.BlockState) other).getBlock(); + } + + @Intrinsic + public > boolean terra$has(Property property) { + if(property instanceof net.minecraft.state.property.Property minecraftProperty) { + return contains(minecraftProperty); + } + return false; + } + + @SuppressWarnings("unchecked") + @Intrinsic + public > T terra$get(Property property) { + return get((net.minecraft.state.property.Property) property); + } + + @SuppressWarnings("unchecked") + @Intrinsic + public > BlockState terra$set(Property property, T value) { + return (BlockState) with((net.minecraft.state.property.Property) property, value); + } + + @Intrinsic + public BlockType terra$getBlockType() { + return (BlockType) getBlock(); + } + + @Intrinsic + public String terra$getAsString(boolean properties) { + StringBuilder data = new StringBuilder(Registry.BLOCK.getId(getBlock()).toString()); + if(properties && !getEntries().isEmpty()) { + data.append('['); + data.append( + getEntries().entrySet().stream().map(StateAccessor.getPropertyMapPrinter()).collect(Collectors.joining(","))); + data.append(']'); + } + return data.toString(); + } + + @Intrinsic + public boolean terra$isAir() { + return isAir(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/LootableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/LootableContainerBlockEntityMixin.java deleted file mode 100644 index f72957753..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/LootableContainerBlockEntityMixin.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.dfsek.terra.fabric.mixin.implementations.block.state; - -import com.dfsek.terra.api.platform.block.state.Container; -import com.dfsek.terra.api.platform.inventory.Inventory; -import com.dfsek.terra.fabric.mixin.implementations.block.BlockEntityMixin; -import net.minecraft.block.entity.LootableContainerBlockEntity; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(LootableContainerBlockEntity.class) -@Implements(@Interface(iface = Container.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class LootableContainerBlockEntityMixin extends BlockEntityMixin { - public Inventory terra$getInventory() { - return (Inventory) this; - } - - @Intrinsic - public Object terra$getHandle() { - return this; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/PropertyMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/PropertyMixin.java new file mode 100644 index 000000000..c0cb10943 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/block/state/PropertyMixin.java @@ -0,0 +1,43 @@ +package com.dfsek.terra.fabric.mixin.implementations.block.state; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Interface.Remap; +import org.spongepowered.asm.mixin.Intrinsic; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Collection; + +import com.dfsek.terra.api.block.state.properties.Property; + + +@Mixin(net.minecraft.state.property.Property.class) +@Implements(@Interface(iface = Property.class, prefix = "terra$", remap = Remap.NONE)) +public abstract class PropertyMixin { + @Shadow + @Final + private Class type; + @Shadow + @Final + private String name; + + @Shadow + public abstract Collection getValues(); + + @Intrinsic + public Collection terra$values() { + return getValues(); + } + + @Intrinsic + public Class terra$getType() { + return type; + } + + @Intrinsic + public String terra$getID() { + return name; + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java index 7912b2f2a..0acb33459 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/ChunkRegionMixin.java @@ -1,13 +1,23 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.chunk; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.fabric.block.FabricBlock; -import com.dfsek.terra.fabric.block.FabricBlockData; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; import net.minecraft.world.ChunkRegion; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Final; @@ -16,37 +26,33 @@ import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.chunk.Chunk; + + @Mixin(ChunkRegion.class) -@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = Chunk.class, prefix = "terraChunk$")) public abstract class ChunkRegionMixin { - @Final + @Shadow - private ChunkPos centerPos; - - public int terra$getX() { - return centerPos.x; + @Final + private net.minecraft.world.chunk.Chunk centerPos; + + public void terraChunk$setBlock(int x, int y, int z, @NotNull BlockState blockState, boolean physics) { + ((ChunkRegion) (Object) this).setBlockState(new BlockPos(x + (centerPos.getPos().x << 4), y, z + (centerPos.getPos().z << 4)), + (net.minecraft.block.BlockState) blockState, 0); } - - public int terra$getZ() { - return centerPos.z; + + public @NotNull BlockState terraChunk$getBlock(int x, int y, int z) { + return (BlockState) ((ChunkRegion) (Object) this).getBlockState( + new BlockPos(x + (centerPos.getPos().x << 4), y, z + (centerPos.getPos().z << 4))); } - - public World terra$getWorld() { - return (World) this; + + public int terraChunk$getX() { + return centerPos.getPos().x; } - - public Block terra$getBlock(int x, int y, int z) { - BlockPos pos = new BlockPos(x + (centerPos.x << 4), y, z + (centerPos.z << 4)); - return new FabricBlock(pos, (ChunkRegion) (Object) this); + + public int terraChunk$getZ() { + return centerPos.getPos().z; } - - public @NotNull BlockData terra$getBlockData(int x, int y, int z) { - return terra$getBlock(x, y, z).getBlockData(); - } - - public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { - ((ChunkRegion) (Object) this).setBlockState(new BlockPos(x + (centerPos.x << 4), y, z + (centerPos.z << 4)), ((FabricBlockData) blockData).getHandle(), 0); - } - - // getHandle already added in world/ChunkRegionMixin. } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java index 56681d0ab..f89d96b62 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/WorldChunkMixin.java @@ -1,14 +1,26 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.chunk; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.fabric.block.FabricBlock; -import com.dfsek.terra.fabric.block.FabricBlockData; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.WorldChunk; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; @@ -16,40 +28,48 @@ import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.chunk.Chunk; + + @Mixin(WorldChunk.class) -@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = Chunk.class, prefix = "terra$")) public abstract class WorldChunkMixin { @Final @Shadow - private net.minecraft.world.World world; - - public int terra$getX() { - return ((net.minecraft.world.chunk.Chunk) this).getPos().x; + net.minecraft.world.World world; + + @Shadow + public abstract net.minecraft.block.BlockState getBlockState(BlockPos pos); + + @Shadow + @Nullable + public abstract net.minecraft.block.BlockState setBlockState(BlockPos pos, net.minecraft.block.BlockState state, boolean moved); + + public void terra$setBlock(int x, int y, int z, BlockState data, boolean physics) { + setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) data, false); } - - public int terra$getZ() { - return ((net.minecraft.world.chunk.Chunk) this).getPos().z; + + public void terra$setBlock(int x, int y, int z, @NotNull BlockState blockState) { + ((net.minecraft.world.chunk.Chunk) (Object) this).setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) blockState, + false); } - - public World terra$getWorld() { - return (World) world; - } - - public Block terra$getBlock(int x, int y, int z) { - BlockPos pos = new BlockPos(x + (terra$getX() << 4), y, z + (terra$getZ() << 4)); - return new FabricBlock(pos, world); - } - - public @NotNull BlockData terra$getBlockData(int x, int y, int z) { - return terra$getBlock(x, y, z).getBlockData(); - } - - public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { - ((net.minecraft.world.chunk.Chunk) this).setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false); - } - + @Intrinsic - public Object terra$getHandle() { - return this; + public @NotNull BlockState terra$getBlock(int x, int y, int z) { + return (BlockState) getBlockState(new BlockPos(x, y, z)); + } + + public int terra$getX() { + return ((net.minecraft.world.chunk.Chunk) (Object) this).getPos().x; + } + + public int terra$getZ() { + return ((net.minecraft.world.chunk.Chunk) (Object) this).getPos().z; + } + + public ServerWorld terra$getWorld() { + return (ServerWorld) world; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java index 2b2b87eb4..627a1766f 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/chunk/data/ProtoChunkMixin.java @@ -1,37 +1,48 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.chunk.data; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.generator.ChunkData; -import com.dfsek.terra.fabric.block.FabricBlockData; -import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.chunk.ProtoChunk; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -@Mixin(ProtoChunk.class) -@Implements(@Interface(iface = ChunkData.class, prefix = "terra$", remap = Interface.Remap.NONE)) +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.world.chunk.generation.ProtoChunk; + + +@Mixin(net.minecraft.world.chunk.ProtoChunk.class) +@Implements(@Interface(iface = ProtoChunk.class, prefix = "terra$")) public abstract class ProtoChunkMixin { @Shadow - public abstract BlockState getBlockState(BlockPos pos); - - public @NotNull BlockData terra$getBlockData(int x, int y, int z) { - return new FabricBlockData(getBlockState(new BlockPos(x, y, z))); + public abstract net.minecraft.block.BlockState getBlockState(BlockPos pos); + + public void terra$setBlock(int x, int y, int z, @NotNull BlockState blockState) { + ((net.minecraft.world.chunk.Chunk) (Object) this).setBlockState(new BlockPos(x, y, z), (net.minecraft.block.BlockState) blockState, + false); } - - public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { - ((net.minecraft.world.chunk.Chunk) this).setBlockState(new BlockPos(x, y, z), ((FabricBlockData) blockData).getHandle(), false); + + public @NotNull BlockState terra$getBlock(int x, int y, int z) { + return (BlockState) getBlockState(new BlockPos(x, y, z)); } - - @Intrinsic - public Object terra$getHandle() { - return this; - } - + public int terra$getMaxHeight() { return 255; // TODO: 1.17 - Implement dynamic height. } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java index d829f7fe3..7a59632f9 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityMixin.java @@ -1,53 +1,61 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.entity; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.fabric.util.FabricAdapter; import net.minecraft.entity.Entity; -import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.util.math.BlockPos; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import java.util.UUID; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.fabric.util.FabricAdapter; + + @Mixin(Entity.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.Entity.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = com.dfsek.terra.api.entity.Entity.class, prefix = "terra$")) public abstract class EntityMixin { @Shadow public net.minecraft.world.World world; - + @Shadow private BlockPos blockPos; - + @Shadow public abstract void teleport(double destX, double destY, double destZ); - + @Shadow public abstract void sendSystemMessage(Text message, UUID senderUuid); - - @Intrinsic - public Object terra$getHandle() { - return this; + + public Vector3 terra$position() { + return FabricAdapter.adapt(blockPos); } - - public Location terra$getLocation() { - return new Location((World) world, FabricAdapter.adapt(blockPos)); - } - - public void terra$setLocation(Location location) { + + public void terra$position(Vector3 location) { teleport(location.getX(), location.getY(), location.getZ()); } - - public World terra$getWorld() { - return (World) world; - } - - public void terra$sendMessage(String message) { - sendSystemMessage(new LiteralText(message), UUID.randomUUID()); // TODO: look into how this actually works and make it less jank + + public ServerWorld terra$world() { + return (ServerWorld) world; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java index 85ffb4c25..3acee886c 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/EntityTypeMixin.java @@ -1,16 +1,29 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.entity; import net.minecraft.entity.EntityType; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; + @Mixin(EntityType.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.EntityType.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = com.dfsek.terra.api.entity.EntityType.class, prefix = "terra$")) public abstract class EntityTypeMixin { - @Intrinsic - public Object terra$getHandle() { - return this; - } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/PlayerEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/PlayerEntityMixin.java index b4bf0d35e..daf784d88 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/PlayerEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/PlayerEntityMixin.java @@ -1,13 +1,31 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.entity; -import com.dfsek.terra.api.platform.entity.Player; import net.minecraft.entity.player.PlayerEntity; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Mixin; -@Mixin(PlayerEntity.class) -@Implements(@Interface(iface = Player.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class PlayerEntityMixin extends EntityMixin { +import com.dfsek.terra.api.entity.Player; + +@Mixin(PlayerEntity.class) +@Implements(@Interface(iface = Player.class, prefix = "terra$")) +public abstract class PlayerEntityMixin extends EntityMixin { } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java index 9b0593521..3f6e16d1f 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/entity/ServerCommandSourceMixin.java @@ -1,27 +1,67 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.entity; -import com.dfsek.terra.api.platform.CommandSender; +import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import java.util.Optional; + +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.Player; + + @Mixin(ServerCommandSource.class) -@Implements(@Interface(iface = CommandSender.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = CommandSender.class, prefix = "terra$")) public abstract class ServerCommandSourceMixin { @Shadow public abstract void sendFeedback(Text message, boolean broadcastToOps); - + + @Shadow + public abstract ServerPlayerEntity getPlayer() throws CommandSyntaxException; + + @Shadow + @Nullable + public abstract net.minecraft.entity.@Nullable Entity getEntity(); + public void terra$sendMessage(String message) { sendFeedback(new LiteralText(message), true); } - - @Intrinsic - public Object terra$getHandle() { - return this; + + @Nullable + public Optional terra$getEntity() { + return Optional.ofNullable((Entity) getEntity()); + } + + public Optional terra$getPlayer() { + try { + return Optional.ofNullable((Player) getPlayer()); + } catch(CommandSyntaxException e) { + return Optional.empty(); + } } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java index cff0892bb..bb9ccf63b 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/LockableContainerBlockEntityMixin.java @@ -1,34 +1,47 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.inventory; -import com.dfsek.terra.api.platform.inventory.Inventory; -import com.dfsek.terra.api.platform.inventory.ItemStack; import net.minecraft.block.entity.LockableContainerBlockEntity; import net.minecraft.item.Items; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; -@Mixin(LockableContainerBlockEntity.class) -@Implements(@Interface(iface = Inventory.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public class LockableContainerBlockEntityMixin { - @Intrinsic - public Object terra$getHandle() { - return this; - } +import com.dfsek.terra.api.inventory.Inventory; +import com.dfsek.terra.api.inventory.ItemStack; + +@Mixin(LockableContainerBlockEntity.class) +@Implements(@Interface(iface = Inventory.class, prefix = "terra$")) +public class LockableContainerBlockEntityMixin { + @SuppressWarnings("ConstantConditions") + public void terra$setItem(int slot, ItemStack newStack) { + ((LockableContainerBlockEntity) (Object) this).setStack(slot, (net.minecraft.item.ItemStack) (Object) newStack); + } + public int terra$getSize() { return ((LockableContainerBlockEntity) (Object) this).size(); } - + @SuppressWarnings("ConstantConditions") public ItemStack terra$getItem(int slot) { net.minecraft.item.ItemStack itemStack = ((LockableContainerBlockEntity) (Object) this).getStack(slot); return itemStack.getItem() == Items.AIR ? null : (ItemStack) (Object) itemStack; } - - @SuppressWarnings("ConstantConditions") - public void terra$setItem(int slot, ItemStack newStack) { - ((LockableContainerBlockEntity) (Object) this).setStack(slot, (net.minecraft.item.ItemStack) (Object) newStack); - } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java index b14939c1c..a7d5da4ed 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemMixin.java @@ -1,29 +1,42 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.inventory.item; -import com.dfsek.terra.api.platform.inventory.ItemStack; import net.minecraft.item.Item; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import com.dfsek.terra.api.inventory.ItemStack; + + @Mixin(Item.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.Item.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = com.dfsek.terra.api.inventory.Item.class, prefix = "terra$")) public abstract class ItemMixin { @Shadow public abstract int getMaxDamage(); - - @Intrinsic - public Object terra$getHandle() { - return this; - } - + @SuppressWarnings("ConstantConditions") public ItemStack terra$newItemStack(int amount) { return (ItemStack) (Object) new net.minecraft.item.ItemStack((Item) (Object) this, amount); } - + public double terra$getMaxDurability() { return getMaxDamage(); } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java index 864e4724a..dcddca234 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/item/ItemStackMixin.java @@ -1,7 +1,22 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.inventory.item; -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import org.jetbrains.annotations.Nullable; @@ -11,50 +26,49 @@ import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import com.dfsek.terra.api.inventory.Item; +import com.dfsek.terra.api.inventory.item.ItemMeta; + + @Mixin(ItemStack.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.ItemStack.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = com.dfsek.terra.api.inventory.ItemStack.class, prefix = "terra$")) public abstract class ItemStackMixin { @Shadow public abstract int getCount(); - + @Shadow public abstract void setCount(int count); - + @Shadow public abstract net.minecraft.item.Item getItem(); - + @Shadow public abstract boolean isDamageable(); - + @Shadow - public abstract void setTag(@Nullable NbtCompound tag); - + public abstract void setNbt(@Nullable NbtCompound tag); + public int terra$getAmount() { return getCount(); } - + public void terra$setAmount(int i) { setCount(i); } - + public Item terra$getType() { return (Item) getItem(); } - + public ItemMeta terra$getItemMeta() { return (ItemMeta) this; } - + @SuppressWarnings("ConstantConditions") public void terra$setItemMeta(ItemMeta meta) { - setTag(((ItemStack) (Object) meta).getTag()); + setNbt(((ItemStack) (Object) meta).getNbt()); } - - @Intrinsic - public Object terra$getHandle() { - return this; - } - + @Intrinsic public boolean terra$isDamageable() { return isDamageable(); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java index eb47a6498..3d10a2241 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/EnchantmentMixin.java @@ -1,40 +1,53 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.inventory.meta; -import com.dfsek.terra.api.platform.inventory.ItemStack; import net.minecraft.enchantment.Enchantment; import net.minecraft.util.registry.Registry; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import java.util.Objects; +import com.dfsek.terra.api.inventory.ItemStack; + + @Mixin(Enchantment.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.item.Enchantment.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = com.dfsek.terra.api.inventory.item.Enchantment.class, prefix = "terra$")) public abstract class EnchantmentMixin { @Shadow public abstract boolean isAcceptableItem(net.minecraft.item.ItemStack stack); - + @Shadow public abstract boolean canCombine(Enchantment other); - - @Intrinsic - public Object terra$getHandle() { - return this; - } - + @SuppressWarnings("ConstantConditions") public boolean terra$canEnchantItem(ItemStack itemStack) { return isAcceptableItem((net.minecraft.item.ItemStack) (Object) itemStack); } - + + public boolean terra$conflictsWith(com.dfsek.terra.api.inventory.item.Enchantment other) { + return !canCombine((Enchantment) other); + } + public String terra$getID() { return Objects.requireNonNull(Registry.ENCHANTMENT.getId((Enchantment) (Object) this)).toString(); } - - public boolean terra$conflictsWith(com.dfsek.terra.api.platform.inventory.item.Enchantment other) { - return !canCombine((Enchantment) other); - } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java index 0d3a2fd06..217ff86ba 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java @@ -1,6 +1,22 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.inventory.meta; -import com.dfsek.terra.api.platform.inventory.item.Damageable; import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; @@ -8,29 +24,32 @@ import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import com.dfsek.terra.api.inventory.item.Damageable; + + @Mixin(ItemStack.class) -@Implements(@Interface(iface = Damageable.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = Damageable.class, prefix = "terra$")) public abstract class ItemStackDamageableMixin { @Shadow public abstract boolean isDamaged(); - + @Shadow public abstract int getDamage(); - + @Shadow public abstract void setDamage(int damage); - - public boolean terra$hasDamage() { - return isDamaged(); - } - - @Intrinsic - public void terra$setDamage(int damage) { - setDamage(damage); - } - + @Intrinsic public int terra$getDamage() { return getDamage(); } + + @Intrinsic + public void terra$setDamage(int damage) { + setDamage(damage); + } + + public boolean terra$hasDamage() { + return isDamaged(); + } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java index 5ddaca96a..60c33fc68 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/inventory/meta/ItemStackMetaMixin.java @@ -1,7 +1,22 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.inventory.meta; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtList; @@ -16,36 +31,35 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import com.dfsek.terra.api.inventory.item.Enchantment; +import com.dfsek.terra.api.inventory.item.ItemMeta; + + @Mixin(ItemStack.class) -@Implements(@Interface(iface = ItemMeta.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = ItemMeta.class, prefix = "terra$")) public abstract class ItemStackMetaMixin { @Shadow public abstract boolean hasEnchantments(); - + @Shadow public abstract NbtList getEnchantments(); - + @Shadow public abstract void addEnchantment(net.minecraft.enchantment.Enchantment enchantment, int level); - - @Intrinsic - public Object terra$getHandle() { - return this; + + public void terra$addEnchantment(Enchantment enchantment, int level) { + addEnchantment((net.minecraft.enchantment.Enchantment) enchantment, level); } - + @Intrinsic(displace = true) public Map terra$getEnchantments() { if(!hasEnchantments()) return Collections.emptyMap(); Map map = new HashMap<>(); - + getEnchantments().forEach(enchantment -> { NbtCompound eTag = (NbtCompound) enchantment; map.put((Enchantment) Registry.ENCHANTMENT.get(eTag.getInt("id")), eTag.getInt("lvl")); }); return map; } - - public void terra$addEnchantment(Enchantment enchantment, int level) { - addEnchantment((net.minecraft.enchantment.Enchantment) enchantment, level); - } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/package-info.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/package-info.java index ec0453641..262b1c464 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/package-info.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/package-info.java @@ -1,5 +1,23 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + /** * Mixins in this package implement Terra * interfaces in Minecraft classes. */ + package com.dfsek.terra.fabric.mixin.implementations; \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java index 0a2b05d57..796d2c424 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ChunkRegionMixin.java @@ -1,110 +1,161 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.world; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.fabric.block.FabricBlock; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import net.minecraft.server.world.ServerWorld; +import net.minecraft.block.FluidBlock; +import net.minecraft.fluid.Fluid; import net.minecraft.util.math.BlockPos; import net.minecraft.world.ChunkRegion; -import net.minecraft.world.ServerWorldAccess; +import net.minecraft.world.WorldAccess; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkStatus; +import net.minecraft.world.tick.MultiTickScheduler; +import net.minecraft.world.tick.OrderedTick; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.List; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.generation.TerraBiomeSource; +import com.dfsek.terra.fabric.util.FabricUtil; + @Mixin(ChunkRegion.class) -@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE)) +@Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$")) public abstract class ChunkRegionMixin { + private ConfigPack config; + @Shadow @Final - private ServerWorld world; - + private net.minecraft.server.world.ServerWorld world; + @Shadow @Final private long seed; - - public int terra$getMaxHeight() { - return (((ChunkRegion) (Object) this).getBottomY()) + ((ChunkRegion) (Object) this).getHeight(); + @Shadow + @Final + private Chunk centerPos; + + @Shadow + @Final + private MultiTickScheduler fluidTickScheduler; + + @Inject(at = @At("RETURN"), + method = "(Lnet/minecraft/server/world/ServerWorld;Ljava/util/List;Lnet/minecraft/world/chunk/ChunkStatus;I)V") + public void injectConstructor(net.minecraft.server.world.ServerWorld world, List list, + ChunkStatus chunkStatus, int i, + CallbackInfo ci) { + this.config = ((ServerWorld) world).getPack(); } - + @SuppressWarnings("deprecation") - public ChunkGenerator terra$getGenerator() { - return (ChunkGenerator) ((ChunkRegion) (Object) this).toServerWorld().getChunkManager().getChunkGenerator(); - } - - public Chunk terra$getChunkAt(int x, int z) { - return (Chunk) ((ChunkRegion) (Object) this).getChunk(x, z); - } - - public Block terra$getBlockAt(int x, int y, int z) { - return new FabricBlock(new BlockPos(x, y, z), ((ChunkRegion) (Object) this)); - } - - @SuppressWarnings("deprecation") - public Entity terra$spawnEntity(Location location, EntityType entityType) { - net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(((ChunkRegion) (Object) this).toServerWorld()); + public Entity terraWorld$spawnEntity(Vector3 location, EntityType entityType) { + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create( + ((ChunkRegion) (Object) this).toServerWorld()); entity.setPos(location.getX(), location.getY(), location.getZ()); ((ChunkRegion) (Object) this).spawnEntity(entity); return (Entity) entity; } - + + @Intrinsic(displace = true) + public void terraWorld$setBlockState(int x, int y, int z, BlockState data, boolean physics) { + BlockPos pos = new BlockPos(x, y, z); + ((ChunkRegion) (Object) this).setBlockState(pos, (net.minecraft.block.BlockState) data, physics ? 3 : 1042); + if(physics && ((net.minecraft.block.BlockState) data).getBlock() instanceof FluidBlock) { + fluidTickScheduler.scheduleTick( + OrderedTick.create(((FluidBlock) ((net.minecraft.block.BlockState) data).getBlock()).getFluidState( + (net.minecraft.block.BlockState) data).getFluid(), pos)); + } + } + @Intrinsic - public long terra$getSeed() { + public long terraWorld$getSeed() { return seed; } - - public int terra$getMinHeight() { + + public int terraWorld$getMaxHeight() { + return (((ChunkRegion) (Object) this).getBottomY()) + ((ChunkRegion) (Object) this).getHeight(); + } + + @Intrinsic(displace = true) + public BlockState terraWorld$getBlockState(int x, int y, int z) { + BlockPos pos = new BlockPos(x, y, z); + return (BlockState) ((ChunkRegion) (Object) this).getBlockState(pos); + } + + public BlockEntity terraWorld$getBlockEntity(int x, int y, int z) { + return FabricUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); + } + + public int terraWorld$getMinHeight() { return ((ChunkRegion) (Object) this).getBottomY(); } - - @Intrinsic - public Object terra$getHandle() { - return this; + + public ChunkGenerator terraWorld$getGenerator() { + return ((FabricChunkGeneratorWrapper) world.getChunkManager().getChunkGenerator()).getHandle(); } - - public boolean terra$isTerraWorld() { - return terra$getGenerator() instanceof GeneratorWrapper; + + @SuppressWarnings("deprecation") + public BiomeProvider terraWorld$getBiomeProvider() { + return ((TerraBiomeSource) ((ChunkRegion) (Object) this).toServerWorld() + .getChunkManager() + .getChunkGenerator() + .getBiomeSource()).getProvider(); } - - public TerraChunkGenerator terra$getTerraGenerator() { - return ((FabricChunkGeneratorWrapper) terra$getGenerator()).getHandle(); + + public Entity terraWorld$spawnEntity(double x, double y, double z, EntityType entityType) { + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(world); + entity.setPos(x, y, z); + ((ChunkRegion) (Object) this).spawnEntity(entity); + return (Entity) entity; } - - /** - * We need regions delegating to the same world - * to have the same hashcode. This - * minimizes cache misses. - *

- * This is sort of jank, but shouldn't(tm) - * break any other mods, unless they're doing - * something they really shouldn't, since - * ChunkRegions are not supposed to persist. - */ - @Override - public int hashCode() { - return world.hashCode(); + + public int terraWorld$centerChunkX() { + return centerPos.getPos().x; } - - /** - * Overridden in the same manner as {@link #hashCode()} - * - * @param other Another object - * @return Whether this world is the same as other. - * @see #hashCode() - */ - @Override - public boolean equals(Object other) { - if(!(other instanceof ServerWorldAccess)) return false; - return world.equals(((ServerWorldAccess) other).toServerWorld()); + + public int terraWorld$centerChunkZ() { + return centerPos.getPos().z; + } + + public ServerWorld terraWorld$getWorld() { + return (ServerWorld) world; + } + + public ConfigPack terraWorld$getPack() { + return config; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java index 71b6de5e8..4273446f6 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/implementations/world/ServerWorldMixin.java @@ -1,88 +1,103 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.implementations.world; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.fabric.block.FabricBlock; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import net.minecraft.server.world.ServerWorld; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.ChunkRegion; -import net.minecraft.world.ServerWorldAccess; +import net.minecraft.world.WorldAccess; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -@Mixin(ServerWorld.class) -@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE)) +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.entity.Entity; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.world.ServerWorld; +import com.dfsek.terra.api.world.biome.generation.BiomeProvider; +import com.dfsek.terra.api.world.chunk.Chunk; +import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.generation.TerraBiomeSource; +import com.dfsek.terra.fabric.util.FabricUtil; + + +@Mixin(net.minecraft.server.world.ServerWorld.class) +@Implements(@Interface(iface = ServerWorld.class, prefix = "terra$")) public abstract class ServerWorldMixin { - @Shadow - public abstract long getSeed(); - - public int terra$getMaxHeight() { - return (((ServerWorld) (Object) this).getBottomY()) + ((ServerWorld) (Object) this).getHeight(); - } - - public ChunkGenerator terra$getGenerator() { - return (ChunkGenerator) ((ServerWorld) (Object) this).getChunkManager().getChunkGenerator(); - } - - public Chunk terra$getChunkAt(int x, int z) { - return (Chunk) ((ServerWorld) (Object) this).getChunk(x, z); - } - - public Block terra$getBlockAt(int x, int y, int z) { - return new FabricBlock(new BlockPos(x, y, z), ((ServerWorld) (Object) this)); - } - - public Entity terra$spawnEntity(Location location, EntityType entityType) { - net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(((ServerWorld) (Object) this)); - entity.setPos(location.getX(), location.getY(), location.getZ()); - ((ServerWorld) (Object) this).spawnEntity(entity); + public Entity terra$spawnEntity(double x, double y, double z, EntityType entityType) { + net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create( + ((net.minecraft.server.world.ServerWorld) (Object) this)); + entity.setPos(x, y, z); + ((net.minecraft.server.world.ServerWorld) (Object) this).spawnEntity(entity); return (Entity) entity; } - + + public void terra$setBlockState(int x, int y, int z, BlockState data, boolean physics) { + BlockPos pos = new BlockPos(x, y, z); + ((net.minecraft.server.world.ServerWorld) (Object) this).setBlockState(pos, (net.minecraft.block.BlockState) data, + physics ? 3 : 1042); + } + @Intrinsic public long terra$getSeed() { - return getSeed(); + return ((net.minecraft.server.world.ServerWorld) (Object) this).getSeed(); } - + + public int terra$getMaxHeight() { + return (((net.minecraft.server.world.ServerWorld) (Object) this).getBottomY()) + + ((net.minecraft.server.world.ServerWorld) (Object) this).getHeight(); + } + + public Chunk terra$getChunkAt(int x, int z) { + return (Chunk) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunk(x, z); + } + + public BlockState terra$getBlockState(int x, int y, int z) { + return (BlockState) ((net.minecraft.server.world.ServerWorld) (Object) this).getBlockState(new BlockPos(x, y, z)); + } + + public BlockEntity terra$getBlockEntity(int x, int y, int z) { + return FabricUtil.createState((WorldAccess) this, new BlockPos(x, y, z)); + } + public int terra$getMinHeight() { - return ((ServerWorld) (Object) this).getBottomY(); + return ((net.minecraft.server.world.ServerWorld) (Object) this).getBottomY(); } - - @Intrinsic - public Object terra$getHandle() { - return this; + + public ChunkGenerator terra$getGenerator() { + return ((FabricChunkGeneratorWrapper) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager() + .getChunkGenerator()).getHandle(); } - - public boolean terra$isTerraWorld() { - return terra$getGenerator() instanceof GeneratorWrapper; + + public BiomeProvider terra$getBiomeProvider() { + return ((TerraBiomeSource) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager() + .getChunkGenerator() + .getBiomeSource()).getProvider(); } - - public TerraChunkGenerator terra$getTerraGenerator() { - return ((FabricChunkGeneratorWrapper) terra$getGenerator()).getHandle(); - } - - /** - * Overridden in the same manner as {@link ChunkRegionMixin#hashCode()} - * - * @param other Another object - * @return Whether this world is the same as other. - * @see ChunkRegionMixin#hashCode() - */ - @SuppressWarnings("ConstantConditions") - @Override - public boolean equals(Object other) { - if(!(other instanceof ServerWorldAccess)) return false; - return (ServerWorldAccess) this == (((ServerWorldAccess) other).toServerWorld()); + + public ConfigPack terra$getPack() { + net.minecraft.world.gen.chunk.ChunkGenerator generator = + (((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager()).getChunkGenerator(); + if(generator instanceof FabricChunkGeneratorWrapper fabricChunkGeneratorWrapper) { + return fabricChunkGeneratorWrapper.getPack(); + } + return null; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java new file mode 100644 index 000000000..fc4597597 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/DataPackContentsMixin.java @@ -0,0 +1,26 @@ +package com.dfsek.terra.fabric.mixin.lifecycle; + +import com.dfsek.terra.fabric.util.BiomeUtil; +import com.dfsek.terra.fabric.util.TagUtil; +import net.minecraft.server.DataPackContents; +import net.minecraft.util.registry.DynamicRegistryManager; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.biome.Biome; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + + +@Mixin(DataPackContents.class) +public class DataPackContentsMixin { + /* + * #refresh populates all tags in the registries + */ + @Inject(method = "refresh(Lnet/minecraft/util/registry/DynamicRegistryManager;)V", at = @At("RETURN")) + private void injectReload(DynamicRegistryManager dynamicRegistryManager, CallbackInfo ci) { + Registry biomeRegistry = dynamicRegistryManager.get(Registry.BIOME_KEY); + TagUtil.registerTags(biomeRegistry); + BiomeUtil.registerFlora(biomeRegistry); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java new file mode 100644 index 000000000..66f03a7c5 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/MinecraftServerMixin.java @@ -0,0 +1,36 @@ +package com.dfsek.terra.fabric.mixin.lifecycle; + +import com.mojang.authlib.GameProfileRepository; +import com.mojang.authlib.minecraft.MinecraftSessionService; +import com.mojang.datafixers.DataFixer; +import net.minecraft.resource.ResourcePackManager; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.SaveLoader; +import net.minecraft.server.WorldGenerationProgressListenerFactory; +import net.minecraft.util.UserCache; +import net.minecraft.world.level.storage.LevelStorage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.net.Proxy; + +import com.dfsek.terra.fabric.FabricEntryPoint; + + +@Mixin(MinecraftServer.class) +public class MinecraftServerMixin { + @Inject(method = "(Ljava/lang/Thread;Lnet/minecraft/world/level/storage/LevelStorage$Session;" + + "Lnet/minecraft/resource/ResourcePackManager;Lnet/minecraft/server/SaveLoader;Ljava/net/Proxy;" + + "Lcom/mojang/datafixers/DataFixer;Lcom/mojang/authlib/minecraft/MinecraftSessionService;" + + "Lcom/mojang/authlib/GameProfileRepository;Lnet/minecraft/util/UserCache;" + + "Lnet/minecraft/server/WorldGenerationProgressListenerFactory;)V", + at = @At("RETURN")) + private void injectConstructor(Thread serverThread, LevelStorage.Session session, ResourcePackManager dataPackManager, + SaveLoader saveLoader, Proxy proxy, DataFixer dataFixer, MinecraftSessionService sessionService, + GameProfileRepository gameProfileRepo, UserCache userCache, + WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) { + FabricEntryPoint.getPlatform().setServer((MinecraftServer) (Object) this); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/RegistryMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/RegistryMixin.java new file mode 100644 index 000000000..0f6ccd532 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/RegistryMixin.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.fabric.mixin.lifecycle; + + +import net.minecraft.util.registry.Registry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.dfsek.terra.fabric.FabricEntryPoint; + + +// Register Terra things to the builtin registries. +@Mixin(Registry.class) +public class RegistryMixin { + @Inject(method = "", at = @At("RETURN")) + private static void registerTerraGenerators(CallbackInfo ci) { + FabricEntryPoint.register(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java index aa2a4aee1..e6ecb2626 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/client/MinecraftClientMixin.java @@ -1,9 +1,23 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.lifecycle.client; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.dfsek.terra.fabric.event.GameInitializationEvent; -import com.dfsek.terra.fabric.generation.TerraGeneratorType; -import com.dfsek.terra.fabric.mixin.access.GeneratorTypeAccessor; +import com.dfsek.terra.fabric.util.BiomeUtil; import net.minecraft.client.MinecraftClient; import net.minecraft.client.RunArgs; import net.minecraft.client.world.GeneratorType; @@ -13,18 +27,28 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.fabric.FabricEntryPoint; +import com.dfsek.terra.fabric.generation.TerraGeneratorType; +import com.dfsek.terra.fabric.mixin.access.GeneratorTypeAccessor; + + @Mixin(MinecraftClient.class) public class MinecraftClientMixin { @Inject(method = "", at = @At(value = "INVOKE", - target = "Lnet/minecraft/client/util/WindowProvider;createWindow(Lnet/minecraft/client/WindowSettings;Ljava/lang/String;Ljava/lang/String;)Lnet/minecraft/client/util/Window;", // sorta arbitrary position, after mod init, before window opens - shift = At.Shift.BEFORE)) + target = "Lnet/minecraft/client/util/WindowProvider;createWindow" + + "(Lnet/minecraft/client/WindowSettings;Ljava/lang/String;Ljava/lang/String;)" + + "Lnet/minecraft/client/util/Window;", + // sorta arbitrary position, after mod init, before window opens + shift = At.Shift.BEFORE)) public void injectConstructor(RunArgs args, CallbackInfo callbackInfo) { - TerraFabricPlugin.getInstance().getEventManager().callEvent(new GameInitializationEvent()); - TerraFabricPlugin.getInstance().getConfigRegistry().forEach(pack -> { + FabricEntryPoint.getPlatform().getEventManager().callEvent(new PlatformInitializationEvent()); + FabricEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { final GeneratorType generatorType = new TerraGeneratorType(pack); //noinspection ConstantConditions - ((GeneratorTypeAccessor) generatorType).setTranslationKey(new LiteralText("Terra:" + pack.getTemplate().getID())); + ((GeneratorTypeAccessor) generatorType).setDisplayName(new LiteralText("Terra:" + pack.getID())); GeneratorTypeAccessor.getValues().add(1, generatorType); }); + BiomeUtil.registerBiomes(); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java index 428f9772c..ad90c31eb 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/package-info.java @@ -1,4 +1,22 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + /** * Mixins that inject behavior into the client/server lifecycle. */ + package com.dfsek.terra.fabric.mixin.lifecycle; \ No newline at end of file diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/GeneratorOptionsMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/GeneratorOptionsMixin.java index c665bb3c4..ef2a587f5 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/GeneratorOptionsMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/GeneratorOptionsMixin.java @@ -1,16 +1,27 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.lifecycle.server; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.dfsek.terra.fabric.event.BiomeRegistrationEvent; -import com.dfsek.terra.fabric.generation.TerraBiomeSource; -import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; -import com.dfsek.terra.fabric.util.FabricUtil; -import com.google.common.base.MoreObjects; -import net.minecraft.util.Identifier; +import net.minecraft.server.dedicated.ServerPropertiesHandler; +import net.minecraft.structure.StructureSet; import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.SimpleRegistry; +import net.minecraft.util.registry.RegistryEntry; import net.minecraft.world.biome.Biome; import net.minecraft.world.dimension.DimensionOptions; import net.minecraft.world.dimension.DimensionType; @@ -21,50 +32,80 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Properties; +import java.util.Locale; import java.util.Random; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.registry.CheckedRegistry; +import com.dfsek.terra.fabric.FabricEntryPoint; +import com.dfsek.terra.fabric.PlatformImpl; +import com.dfsek.terra.fabric.generation.FabricChunkGeneratorWrapper; +import com.dfsek.terra.fabric.generation.TerraBiomeSource; + + @Mixin(GeneratorOptions.class) public abstract class GeneratorOptionsMixin { - @Inject(method = "fromProperties(Lnet/minecraft/util/registry/DynamicRegistryManager;Ljava/util/Properties;)Lnet/minecraft/world/gen/GeneratorOptions;", at = @At("HEAD"), cancellable = true) - private static void fromProperties(DynamicRegistryManager registryManager, Properties properties, CallbackInfoReturnable cir) { - if(properties.get("level-type") == null) { + @Inject(method = "fromProperties(Lnet/minecraft/util/registry/DynamicRegistryManager;" + + "Lnet/minecraft/server/dedicated/ServerPropertiesHandler$WorldGenProperties;)" + + "Lnet/minecraft/world/gen/GeneratorOptions;", + at = @At("HEAD"), + cancellable = true) + private static void fromProperties(DynamicRegistryManager manager, + ServerPropertiesHandler.WorldGenProperties properties, + CallbackInfoReturnable cir) { + if(properties.levelType() == null) { return; } - - TerraFabricPlugin main = TerraFabricPlugin.getInstance(); - - String prop = properties.get("level-type").toString().trim(); - if(prop.startsWith("Terra")) { - String seed = (String) MoreObjects.firstNonNull(properties.get("level-seed"), ""); - long l = new Random().nextLong(); - if(!seed.isEmpty()) { + + PlatformImpl main = FabricEntryPoint.getPlatform(); + + String levelType = properties.levelType(); + + if(levelType.toLowerCase(Locale.ROOT).startsWith("terra")) { + String seedProperty = properties.levelSeed(); + long seed = new Random().nextLong(); + if(seedProperty != null) { try { - long m = Long.parseLong(seed); + long m = Long.parseLong(seedProperty); if(m != 0L) { - l = m; + seed = m; } } catch(NumberFormatException exception) { - l = seed.hashCode(); + seed = seedProperty.hashCode(); } } - - String generate_structures = (String) properties.get("generate-structures"); - boolean generateStructures = generate_structures == null || Boolean.parseBoolean(generate_structures); - Registry dimensionTypes = registryManager.get(Registry.DIMENSION_TYPE_KEY); - Registry biomeRegistry = registryManager.get(Registry.BIOME_KEY); - Registry chunkGeneratorSettings = registryManager.get(Registry.CHUNK_GENERATOR_SETTINGS_KEY); - SimpleRegistry dimensionOptions = DimensionType.createDefaultDimensionOptions(dimensionTypes, biomeRegistry, chunkGeneratorSettings, l); - - prop = prop.substring(prop.indexOf(":") + 1); - - ConfigPack config = main.getConfigRegistry().get(prop); - - if(config == null) throw new IllegalArgumentException("No such pack " + prop); - - main.getEventManager().callEvent(new BiomeRegistrationEvent(registryManager)); // register biomes - - cir.setReturnValue(new GeneratorOptions(l, generateStructures, false, GeneratorOptions.getRegistryWithReplacedOverworldGenerator(dimensionTypes, dimensionOptions, new FabricChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, l, config), l, config)))); + + boolean generateStructures = properties.generateStructures(); + Registry dimensionTypes = manager.get(Registry.DIMENSION_TYPE_KEY); + Registry biomeRegistry = manager.get(Registry.BIOME_KEY); + Registry dimensionOptions = DimensionType.createDefaultDimensionOptions(manager, seed, false); + + Registry chunkGeneratorSettingsRegistry = manager.get(Registry.CHUNK_GENERATOR_SETTINGS_KEY); + RegistryEntry + settingsSupplier = chunkGeneratorSettingsRegistry.getEntry(ChunkGeneratorSettings.OVERWORLD).orElseThrow(); + Registry noiseRegistry = manager.get(Registry.STRUCTURE_SET_KEY); + + String pack = levelType.substring(levelType.indexOf(":") + 1); + + CheckedRegistry configRegistry = main.getConfigRegistry(); + ConfigPack config = configRegistry + .getByID(pack) + .or(() -> configRegistry.getByID(pack.toUpperCase(Locale.ROOT))) + .orElseThrow(() -> new IllegalArgumentException("No such pack " + pack)); + + cir.setReturnValue( + new GeneratorOptions(seed, + generateStructures, + false, + GeneratorOptions + .getRegistryWithReplacedOverworldGenerator( + dimensionTypes, + dimensionOptions, + new FabricChunkGeneratorWrapper(noiseRegistry, + new TerraBiomeSource(biomeRegistry, seed, config), + seed, + config, + settingsSupplier)))); } } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java index b32f2e591..6bd8e2272 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/lifecycle/server/ServerMainMixin.java @@ -1,17 +1,45 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.mixin.lifecycle.server; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.dfsek.terra.fabric.event.GameInitializationEvent; +import com.dfsek.terra.fabric.util.BiomeUtil; import net.minecraft.server.Main; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; +import com.dfsek.terra.fabric.FabricEntryPoint; + + @Mixin(Main.class) public class ServerMainMixin { - @Inject(method = "main([Ljava/lang/String;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/DynamicRegistryManager;create()Lnet/minecraft/util/registry/DynamicRegistryManager$Impl;")) + @Inject(method = "main([Ljava/lang/String;)V", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/resource/ResourcePackManager;(Lnet/minecraft/resource/ResourceType;" + + "[Lnet/minecraft/resource/ResourcePackProvider;)V") + // after registry manager creation + ) private static void injectConstructor(String[] args, CallbackInfo ci) { - TerraFabricPlugin.getInstance().getEventManager().callEvent(new GameInitializationEvent()); // Load during MinecraftServer construction, after other mods have registered blocks and stuff + FabricEntryPoint.getPlatform().getEventManager().callEvent( + new PlatformInitializationEvent()); // Load during MinecraftServer construction, after other mods have registered blocks + // and stuff + BiomeUtil.registerBiomes(); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java new file mode 100644 index 000000000..b02f0b08b --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/BiomeUtil.java @@ -0,0 +1,166 @@ +package com.dfsek.terra.fabric.util; + +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.world.biome.Biome; +import com.dfsek.terra.fabric.FabricEntryPoint; +import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; +import com.dfsek.terra.fabric.config.VanillaBiomeProperties; + +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.BuiltinRegistries; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.biome.Biome.Builder; +import net.minecraft.world.biome.BiomeEffects; +import net.minecraft.world.biome.GenerationSettings; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + + +public final class BiomeUtil { + private static final Logger logger = LoggerFactory.getLogger(BiomeUtil.class); + + private static final Map> + TERRA_BIOME_MAP = new HashMap<>(); + + private BiomeUtil() { + + } + + public static String createBiomeID(ConfigPack pack, com.dfsek.terra.api.registry.key.RegistryKey biomeID) { + return pack.getID() + .toLowerCase() + "/" + biomeID.getNamespace().toLowerCase(Locale.ROOT) + "/" + biomeID.getID().toLowerCase(Locale.ROOT); + } + + public static void registerBiomes() { + logger.info("Registering biomes..."); + FabricEntryPoint.getPlatform().getConfigRegistry().forEach(pack -> { // Register all Terra biomes. + pack.getCheckedRegistry(Biome.class) + .forEach((id, biome) -> registerBiome(biome, pack, id)); + }); + registerFlora(BuiltinRegistries.BIOME); + logger.info("Terra biomes registered."); + } + + /** + * Clones a Vanilla biome and injects Terra data to create a Terra-vanilla biome delegate. + * + * @param biome The Terra BiomeBuilder. + * @param pack The ConfigPack this biome belongs to. + */ + private static void registerBiome(Biome biome, ConfigPack pack, + com.dfsek.terra.api.registry.key.RegistryKey id) { + Registry registry = BuiltinRegistries.BIOME; + RegistryKey vanilla = ((ProtoPlatformBiome) biome.getPlatformBiome()).get(registry); + + + if(pack.getContext().get(PreLoadCompatibilityOptions.class).useVanillaBiomes()) { + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(vanilla); + } else { + net.minecraft.world.biome.Biome minecraftBiome = createBiome(biome, registry.get(vanilla)); + + Identifier identifier = new Identifier("terra", createBiomeID(pack, id)); + + if(registry.containsId(identifier)) { + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(FabricUtil.getEntry(registry, identifier) + .orElseThrow() + .getKey() + .orElseThrow()); + } else { + ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(BuiltinRegistries.add(registry, + registerKey(identifier).getValue(), + minecraftBiome).getKey().orElseThrow()); + } + + TERRA_BIOME_MAP.computeIfAbsent(vanilla.getValue(), i -> new ArrayList<>()).add(identifier); + } + } + + public static void registerFlora(Registry biomes) { + logger.info("Injecting flora into Terra biomes..."); + TERRA_BIOME_MAP + .forEach((vb, terraBiomes) -> + biomes.getOrEmpty(vb) + .ifPresentOrElse(vanilla -> terraBiomes + .forEach(tb -> biomes.getOrEmpty(tb) + .ifPresentOrElse( + terra -> { + List> flowerFeatures = List.copyOf(vanilla.getGenerationSettings().getFlowerFeatures()); + logger.debug("Injecting flora into biome {} : {}", tb, flowerFeatures); + ((FloraFeatureHolder) terra.getGenerationSettings()).setFloraFeatures(flowerFeatures); + }, + () -> logger.error( + "No such biome: {}", + tb))), + () -> logger.error("No vanilla biome: {}", vb))); + + } + + public static Map> getTerraBiomeMap() { + return Map.copyOf(TERRA_BIOME_MAP); + } + + private static RegistryKey registerKey(Identifier identifier) { + return RegistryKey.of(Registry.BIOME_KEY, identifier); + } + + public static net.minecraft.world.biome.Biome createBiome(Biome biome, net.minecraft.world.biome.Biome vanilla) { + GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); + + BiomeEffects.Builder effects = new BiomeEffects.Builder(); + + net.minecraft.world.biome.Biome.Builder builder = new Builder(); + + if(biome.getContext().has(VanillaBiomeProperties.class)) { + VanillaBiomeProperties vanillaBiomeProperties = biome.getContext().get(VanillaBiomeProperties.class); + + effects.waterColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterColor(), vanilla.getWaterColor())) + .waterFogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getWaterFogColor(), vanilla.getWaterFogColor())) + .fogColor(Objects.requireNonNullElse(vanillaBiomeProperties.getFogColor(), vanilla.getFogColor())) + .skyColor(Objects.requireNonNullElse(vanillaBiomeProperties.getSkyColor(), vanilla.getSkyColor())) + .grassColorModifier( + Objects.requireNonNullElse(vanillaBiomeProperties.getModifier(), vanilla.getEffects().getGrassColorModifier())); + + + if(vanillaBiomeProperties.getGrassColor() == null) { + vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); + } else { + effects.grassColor(vanillaBiomeProperties.getGrassColor()); + } + + if(vanillaBiomeProperties.getFoliageColor() == null) { + vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); + } else { + effects.foliageColor(vanillaBiomeProperties.getFoliageColor()); + } + + + builder.precipitation(Objects.requireNonNullElse(vanillaBiomeProperties.getPrecipitation(), vanilla.getPrecipitation())) + .category(Objects.requireNonNullElse(vanillaBiomeProperties.getCategory(), vanilla.getCategory())); + + } else { + + effects.waterColor(vanilla.getWaterColor()) + .waterFogColor(vanilla.getWaterFogColor()) + .fogColor(vanilla.getFogColor()) + .skyColor(vanilla.getSkyColor()); + vanilla.getEffects().getFoliageColor().ifPresent(effects::foliageColor); + vanilla.getEffects().getGrassColor().ifPresent(effects::grassColor); + + builder.precipitation(vanilla.getPrecipitation()) + .category(vanilla.getCategory()); + } + + + return builder + .temperature(vanilla.getTemperature()) + .downfall(vanilla.getDownfall()) + .effects(effects.build()) + .spawnSettings(vanilla.getSpawnSettings()) + .generationSettings(generationSettings.build()) + .build(); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java index 8c197d573..da6c3f6f8 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricAdapter.java @@ -1,224 +1,185 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.util; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.Axis; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Bisected; -import com.dfsek.terra.api.platform.block.data.Slab; -import com.dfsek.terra.api.platform.block.data.Stairs; -import com.dfsek.terra.api.platform.block.state.Container; -import com.dfsek.terra.api.platform.block.state.MobSpawner; -import com.dfsek.terra.api.platform.block.state.Sign; -import com.dfsek.terra.fabric.block.FabricBlockData; -import com.dfsek.terra.fabric.block.data.FabricDirectional; -import com.dfsek.terra.fabric.block.data.FabricMultipleFacing; -import com.dfsek.terra.fabric.block.data.FabricOrientable; -import com.dfsek.terra.fabric.block.data.FabricRotatable; -import com.dfsek.terra.fabric.block.data.FabricSlab; -import com.dfsek.terra.fabric.block.data.FabricStairs; -import com.dfsek.terra.fabric.block.data.FabricWaterlogged; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.LootableContainerBlockEntity; -import net.minecraft.block.entity.MobSpawnerBlockEntity; -import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.block.enums.BlockHalf; -import net.minecraft.block.enums.SlabType; -import net.minecraft.block.enums.StairShape; -import net.minecraft.state.property.Properties; +import net.minecraft.block.enums.WallShape; +import net.minecraft.block.enums.WireConnection; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import net.minecraft.world.WorldAccess; +import net.minecraft.world.HeightLimitView; + +import com.dfsek.terra.api.block.state.properties.enums.Axis; +import com.dfsek.terra.api.block.state.properties.enums.Half; +import com.dfsek.terra.api.block.state.properties.enums.RailShape; +import com.dfsek.terra.api.block.state.properties.enums.RedstoneConnection; +import com.dfsek.terra.api.block.state.properties.enums.WallHeight; +import com.dfsek.terra.api.util.vector.Vector3; +import com.dfsek.terra.api.world.info.WorldProperties; -import java.util.Arrays; public final class FabricAdapter { public static BlockPos adapt(Vector3 v) { return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ()); } - + public static Vector3 adapt(BlockPos pos) { - return new Vector3(pos.getX(), pos.getY(), pos.getZ()); + return Vector3.of(pos.getX(), pos.getY(), pos.getZ()); } - - public static FabricBlockData adapt(BlockState state) { - if(state.contains(Properties.STAIR_SHAPE)) return new FabricStairs(state); - - if(state.contains(Properties.SLAB_TYPE)) return new FabricSlab(state); - - if(state.contains(Properties.AXIS)) return new FabricOrientable(state, Properties.AXIS); - if(state.contains(Properties.HORIZONTAL_AXIS)) return new FabricOrientable(state, Properties.HORIZONTAL_AXIS); - - if(state.contains(Properties.ROTATION)) return new FabricRotatable(state); - - if(state.contains(Properties.FACING)) return new FabricDirectional(state, Properties.FACING); - if(state.contains(Properties.HOPPER_FACING)) return new FabricDirectional(state, Properties.HOPPER_FACING); - if(state.contains(Properties.HORIZONTAL_FACING)) return new FabricDirectional(state, Properties.HORIZONTAL_FACING); - - if(state.getProperties().containsAll(Arrays.asList(Properties.NORTH, Properties.SOUTH, Properties.EAST, Properties.WEST))) - return new FabricMultipleFacing(state); - if(state.contains(Properties.WATERLOGGED)) return new FabricWaterlogged(state); - return new FabricBlockData(state); + + public static Direction adapt(com.dfsek.terra.api.block.state.properties.enums.Direction direction) { + return switch(direction) { + case SOUTH -> Direction.SOUTH; + case NORTH -> Direction.NORTH; + case WEST -> Direction.WEST; + case EAST -> Direction.EAST; + case UP -> Direction.UP; + case DOWN -> Direction.DOWN; + }; } - - public static Direction adapt(BlockFace face) { - switch(face) { - case NORTH: - return Direction.NORTH; - case WEST: - return Direction.WEST; - case SOUTH: - return Direction.SOUTH; - case EAST: - return Direction.EAST; - case UP: - return Direction.UP; - case DOWN: - return Direction.DOWN; - default: - throw new IllegalArgumentException("Illegal direction: " + face); - } + + public static WorldProperties adapt(HeightLimitView height, long seed) { + return new WorldProperties() { + @Override + public long getSeed() { + return seed; + } + + @Override + public int getMaxHeight() { + return height.getTopY(); + } + + @Override + public int getMinHeight() { + return height.getBottomY(); + } + + @Override + public Object getHandle() { + return height; + } + }; } - - - public static com.dfsek.terra.api.platform.block.state.BlockState adapt(com.dfsek.terra.api.platform.block.Block block) { - WorldAccess worldAccess = (WorldAccess) block.getLocation().getWorld(); - - BlockEntity entity = worldAccess.getBlockEntity(adapt(block.getLocation().toVector())); - if(entity instanceof SignBlockEntity) { - return (Sign) entity; - } else if(entity instanceof MobSpawnerBlockEntity) { - return (MobSpawner) entity; - } else if(entity instanceof LootableContainerBlockEntity) { - return (Container) entity; - } - return null; + + public static com.dfsek.terra.api.block.state.properties.enums.Direction adapt(Direction direction) { + return switch(direction) { + case SOUTH -> com.dfsek.terra.api.block.state.properties.enums.Direction.SOUTH; + case NORTH -> com.dfsek.terra.api.block.state.properties.enums.Direction.NORTH; + case WEST -> com.dfsek.terra.api.block.state.properties.enums.Direction.WEST; + case EAST -> com.dfsek.terra.api.block.state.properties.enums.Direction.EAST; + case UP -> com.dfsek.terra.api.block.state.properties.enums.Direction.UP; + case DOWN -> com.dfsek.terra.api.block.state.properties.enums.Direction.DOWN; + }; } - - public static Stairs.Shape adapt(StairShape shape) { - switch(shape) { - case OUTER_RIGHT: - return Stairs.Shape.OUTER_RIGHT; - case INNER_RIGHT: - return Stairs.Shape.INNER_RIGHT; - case OUTER_LEFT: - return Stairs.Shape.OUTER_LEFT; - case INNER_LEFT: - return Stairs.Shape.INNER_LEFT; - case STRAIGHT: - return Stairs.Shape.STRAIGHT; - default: - throw new IllegalStateException(); - } + + public static WallHeight adapt(WallShape shape) { + return switch(shape) { + case LOW -> WallHeight.LOW; + case NONE -> WallHeight.NONE; + case TALL -> WallHeight.TALL; + }; } - - public static Bisected.Half adapt(BlockHalf half) { - switch(half) { - case BOTTOM: - return Bisected.Half.BOTTOM; - case TOP: - return Bisected.Half.TOP; - default: - throw new IllegalStateException(); - } + + public static WallShape adapt(WallHeight shape) { + return switch(shape) { + case LOW -> WallShape.LOW; + case NONE -> WallShape.NONE; + case TALL -> WallShape.TALL; + }; } - - public static BlockFace adapt(Direction direction) { - switch(direction) { - case DOWN: - return BlockFace.DOWN; - case UP: - return BlockFace.UP; - case WEST: - return BlockFace.WEST; - case EAST: - return BlockFace.EAST; - case NORTH: - return BlockFace.NORTH; - case SOUTH: - return BlockFace.SOUTH; - default: - throw new IllegalStateException(); - } + + public static RedstoneConnection adapt(WireConnection connection) { + return switch(connection) { + case NONE -> RedstoneConnection.NONE; + case UP -> RedstoneConnection.UP; + case SIDE -> RedstoneConnection.SIDE; + }; } - - public static Slab.Type adapt(SlabType type) { - switch(type) { - case BOTTOM: - return Slab.Type.BOTTOM; - case TOP: - return Slab.Type.TOP; - case DOUBLE: - return Slab.Type.DOUBLE; - default: - throw new IllegalStateException(); - } + + public static WireConnection adapt(RedstoneConnection connection) { + return switch(connection) { + case NONE -> WireConnection.NONE; + case UP -> WireConnection.UP; + case SIDE -> WireConnection.SIDE; + }; } - - public static StairShape adapt(Stairs.Shape shape) { - switch(shape) { - case STRAIGHT: - return StairShape.STRAIGHT; - case INNER_LEFT: - return StairShape.INNER_LEFT; - case OUTER_LEFT: - return StairShape.OUTER_LEFT; - case INNER_RIGHT: - return StairShape.INNER_RIGHT; - case OUTER_RIGHT: - return StairShape.OUTER_RIGHT; - default: - throw new IllegalStateException(); - } + + + public static Half adapt(BlockHalf half) { + return switch(half) { + case BOTTOM -> Half.BOTTOM; + case TOP -> Half.TOP; + }; } - - public static BlockHalf adapt(Bisected.Half half) { - switch(half) { - case TOP: - return BlockHalf.TOP; - case BOTTOM: - return BlockHalf.BOTTOM; - default: - throw new IllegalStateException(); - } + + public static BlockHalf adapt(Half half) { + return switch(half) { + case TOP -> BlockHalf.TOP; + case BOTTOM -> BlockHalf.BOTTOM; + default -> throw new IllegalStateException(); + }; } - - public static SlabType adapt(Slab.Type type) { - switch(type) { - case DOUBLE: - return SlabType.DOUBLE; - case TOP: - return SlabType.TOP; - case BOTTOM: - return SlabType.BOTTOM; - default: - throw new IllegalStateException(); - } + + public static RailShape adapt(net.minecraft.block.enums.RailShape railShape) { + return switch(railShape) { + case EAST_WEST -> RailShape.EAST_WEST; + case NORTH_EAST -> RailShape.NORTH_EAST; + case NORTH_WEST -> RailShape.NORTH_WEST; + case SOUTH_EAST -> RailShape.SOUTH_EAST; + case SOUTH_WEST -> RailShape.SOUTH_WEST; + case NORTH_SOUTH -> RailShape.NORTH_SOUTH; + case ASCENDING_EAST -> RailShape.ASCENDING_EAST; + case ASCENDING_NORTH -> RailShape.ASCENDING_NORTH; + case ASCENDING_SOUTH -> RailShape.ASCENDING_SOUTH; + case ASCENDING_WEST -> RailShape.ASCENDING_WEST; + }; } - + + public static net.minecraft.block.enums.RailShape adapt(RailShape railShape) { + return switch(railShape) { + case EAST_WEST -> net.minecraft.block.enums.RailShape.EAST_WEST; + case NORTH_EAST -> net.minecraft.block.enums.RailShape.NORTH_EAST; + case NORTH_WEST -> net.minecraft.block.enums.RailShape.NORTH_WEST; + case SOUTH_EAST -> net.minecraft.block.enums.RailShape.SOUTH_EAST; + case SOUTH_WEST -> net.minecraft.block.enums.RailShape.SOUTH_WEST; + case NORTH_SOUTH -> net.minecraft.block.enums.RailShape.NORTH_SOUTH; + case ASCENDING_EAST -> net.minecraft.block.enums.RailShape.ASCENDING_EAST; + case ASCENDING_NORTH -> net.minecraft.block.enums.RailShape.ASCENDING_NORTH; + case ASCENDING_SOUTH -> net.minecraft.block.enums.RailShape.ASCENDING_SOUTH; + case ASCENDING_WEST -> net.minecraft.block.enums.RailShape.ASCENDING_WEST; + }; + } + + public static Axis adapt(Direction.Axis axis) { - switch(axis) { - case X: - return Axis.X; - case Y: - return Axis.Y; - case Z: - return Axis.Z; - default: - throw new IllegalStateException(); - } + return switch(axis) { + case X -> Axis.X; + case Y -> Axis.Y; + case Z -> Axis.Z; + }; } - + public static Direction.Axis adapt(Axis axis) { - switch(axis) { - case Z: - return Direction.Axis.Z; - case Y: - return Direction.Axis.Y; - case X: - return Direction.Axis.X; - default: - throw new IllegalStateException(); - } + return switch(axis) { + case Z -> Direction.Axis.Z; + case Y -> Direction.Axis.Y; + case X -> Direction.Axis.X; + }; } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java index eb6bdee7d..7e00aa900 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FabricUtil.java @@ -1,133 +1,61 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.fabric.util; -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.dfsek.terra.config.builder.BiomeBuilder; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.fabric.TerraFabricPlugin; -import com.dfsek.terra.fabric.config.PostLoadCompatibilityOptions; -import com.dfsek.terra.fabric.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.fabric.mixin.access.BiomeEffectsAccessor; -import com.mojang.serialization.Lifecycle; +import net.minecraft.block.entity.LootableContainerBlockEntity; +import net.minecraft.block.entity.MobSpawnerBlockEntity; +import net.minecraft.block.entity.SignBlockEntity; import net.minecraft.util.Identifier; -import net.minecraft.util.registry.DynamicRegistryManager; -import net.minecraft.util.registry.MutableRegistry; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryKey; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.BiomeEffects; -import net.minecraft.world.biome.GenerationSettings; -import net.minecraft.world.gen.GenerationStep; -import net.minecraft.world.gen.carver.ConfiguredCarver; -import net.minecraft.world.gen.feature.ConfiguredFeature; -import net.minecraft.world.gen.feature.ConfiguredStructureFeature; +import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.world.WorldAccess; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Optional; + +import com.dfsek.terra.api.block.entity.BlockEntity; +import com.dfsek.terra.api.block.entity.Container; +import com.dfsek.terra.api.block.entity.MobSpawner; +import com.dfsek.terra.api.block.entity.Sign; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.function.Supplier; public final class FabricUtil { - public static String createBiomeID(ConfigPack pack, String biomeID) { - return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT); + private FabricUtil() { + } - - /** - * Clones a Vanilla biome and injects Terra data to create a Terra-vanilla biome delegate. - * - * @param biome The Terra BiomeBuilder. - * @param pack The ConfigPack this biome belongs to. - * @return The Minecraft delegate biome. - */ - public static Biome createBiome(BiomeBuilder biome, ConfigPack pack, DynamicRegistryManager registryManager) { - BiomeTemplate template = biome.getTemplate(); - Map colors = template.getColors(); - - TerraFabricPlugin.FabricAddon fabricAddon = TerraFabricPlugin.getInstance().getFabricAddon(); - - Registry biomeRegistry = registryManager.get(Registry.BIOME_KEY); - Biome vanilla = ((ProtoBiome) (new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0))).get(biomeRegistry); - - GenerationSettings.Builder generationSettings = new GenerationSettings.Builder(); - - generationSettings.surfaceBuilder(vanilla.getGenerationSettings().getSurfaceBuilder()); // It needs a surfacebuilder, even though we dont use it. - - generationSettings.feature(GenerationStep.Feature.VEGETAL_DECORATION, TerraFabricPlugin.POPULATOR_CONFIGURED_FEATURE); - - if(pack.getTemplate().vanillaCaves()) { - for(GenerationStep.Carver carver : GenerationStep.Carver.values()) { - for(Supplier> configuredCarverSupplier : vanilla.getGenerationSettings().getCarversForStep(carver)) { - generationSettings.carver(carver, configuredCarverSupplier.get()); - } - } + + public static BlockEntity createState(WorldAccess worldAccess, BlockPos pos) { + net.minecraft.block.entity.BlockEntity entity = worldAccess.getBlockEntity(pos); + if(entity instanceof SignBlockEntity) { + return (Sign) entity; + } else if(entity instanceof MobSpawnerBlockEntity) { + return (MobSpawner) entity; + } else if(entity instanceof LootableContainerBlockEntity) { + return (Container) entity; } - - Pair pair = fabricAddon.getTemplates().get(pack); - PreLoadCompatibilityOptions compatibilityOptions = pair.getLeft(); - PostLoadCompatibilityOptions postLoadCompatibilityOptions = pair.getRight(); - - TerraFabricPlugin.getInstance().getDebugLogger().info("Injecting Vanilla structures and features into Terra biome " + biome.getTemplate().getID()); - - Registry> configuredStructureFeatureRegistry = registryManager.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY); - for(Supplier> structureFeature : vanilla.getGenerationSettings().getStructureFeatures()) { - Identifier key = configuredStructureFeatureRegistry.getId(structureFeature.get()); - if(!compatibilityOptions.getExcludedBiomeStructures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeStructures().getOrDefault(biome, Collections.emptySet()).contains(key)) { - generationSettings.structureFeature(structureFeature.get()); - TerraFabricPlugin.getInstance().getDebugLogger().info("Injected structure " + key); - } - } - - if(compatibilityOptions.doBiomeInjection()) { - Registry> configuredFeatureRegistry = registryManager.get(Registry.CONFIGURED_FEATURE_KEY); - for(int step = 0; step < vanilla.getGenerationSettings().getFeatures().size(); step++) { - for(Supplier> featureSupplier : vanilla.getGenerationSettings().getFeatures().get(step)) { - Identifier key = configuredFeatureRegistry.getId(featureSupplier.get()); - if(!compatibilityOptions.getExcludedBiomeFeatures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeFeatures().getOrDefault(biome, Collections.emptySet()).contains(key)) { - generationSettings.feature(step, featureSupplier); - TerraFabricPlugin.getInstance().getDebugLogger().info("Injected feature " + key + " at stage " + step); - } - } - } - } - - BiomeEffectsAccessor accessor = (BiomeEffectsAccessor) vanilla.getEffects(); - BiomeEffects.Builder effects = new BiomeEffects.Builder() - .waterColor(colors.getOrDefault("water", accessor.getWaterColor())) - .waterFogColor(colors.getOrDefault("water-fog", accessor.getWaterFogColor())) - .fogColor(colors.getOrDefault("fog", accessor.getFogColor())) - .skyColor(colors.getOrDefault("sky", accessor.getSkyColor())) - .grassColorModifier(accessor.getGrassColorModifier()); - - if(colors.containsKey("grass")) { - effects.grassColor(colors.get("grass")); - } else { - accessor.getGrassColor().ifPresent(effects::grassColor); - } - if(colors.containsKey("foliage")) { - effects.foliageColor(colors.get("foliage")); - } else { - accessor.getFoliageColor().ifPresent(effects::foliageColor); - } - - return new Biome.Builder() - .precipitation(vanilla.getPrecipitation()) - .category(vanilla.getCategory()) - .depth(vanilla.getDepth()) - .scale(vanilla.getScale()) - .temperature(vanilla.getTemperature()) - .downfall(vanilla.getDownfall()) - .effects(effects.build()) - .spawnSettings(vanilla.getSpawnSettings()) - .generationSettings(generationSettings.build()) - .build(); + return null; } - - public static void registerOrOverwrite(Registry registry, RegistryKey> key, Identifier identifier, T item) { - if(registry.containsId(identifier)) { - ((MutableRegistry) registry).set(registry.getRawId(registry.get(identifier)), RegistryKey.of(key, identifier), item, Lifecycle.stable()); - } else { - Registry.register(registry, identifier, item); - } + + public static Optional> getEntry(Registry registry, Identifier identifier) { + return registry.getOrEmpty(identifier) + .flatMap(registry::getKey) + .map(registry::getOrCreateEntry); } } diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FloraFeatureHolder.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FloraFeatureHolder.java new file mode 100644 index 000000000..9b2157d72 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/FloraFeatureHolder.java @@ -0,0 +1,10 @@ +package com.dfsek.terra.fabric.util; + +import net.minecraft.world.gen.feature.ConfiguredFeature; + +import java.util.List; + + +public interface FloraFeatureHolder { + void setFloraFeatures(List> features); +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoBiome.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoBiome.java deleted file mode 100644 index a7ff41ecd..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoBiome.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.fabric.util; - -import com.dfsek.terra.api.platform.world.Biome; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; - -public class ProtoBiome implements Biome { - private final Identifier identifier; - - public ProtoBiome(Identifier identifier) { - this.identifier = identifier; - } - - public net.minecraft.world.biome.Biome get(Registry registry) { - return registry.get(identifier); - } - - @Override - public Object getHandle() { - return identifier; - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoPlatformBiome.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoPlatformBiome.java new file mode 100644 index 000000000..b8262893a --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/ProtoPlatformBiome.java @@ -0,0 +1,55 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.fabric.util; + +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.biome.Biome; + +import java.util.Objects; + +import com.dfsek.terra.api.world.biome.PlatformBiome; + + +public class ProtoPlatformBiome implements PlatformBiome { + private final Identifier identifier; + + private RegistryKey delegate; + + public ProtoPlatformBiome(Identifier identifier) { + this.identifier = identifier; + } + + public RegistryKey get(Registry registry) { + return FabricUtil.getEntry(registry, identifier).orElseThrow().getKey().orElseThrow(); + } + + @Override + public Object getHandle() { + return identifier; + } + + public RegistryKey getDelegate() { + return delegate; + } + + public void setDelegate(RegistryKey delegate) { + this.delegate = Objects.requireNonNull(delegate); + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java new file mode 100644 index 000000000..e39194234 --- /dev/null +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/TagUtil.java @@ -0,0 +1,77 @@ +package com.dfsek.terra.fabric.util; + +import com.google.common.collect.ImmutableMap; +import net.minecraft.tag.TagKey; +import net.minecraft.util.registry.Registry; +import net.minecraft.util.registry.RegistryEntry; +import net.minecraft.world.biome.Biome; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public final class TagUtil { + private static final Logger logger = LoggerFactory.getLogger(TagUtil.class); + + private TagUtil() { + + } + + public static void registerTags(Registry registry) { + logger.info("Doing tag garbage...."); + Map, List>> collect = registry + .streamTagsAndEntries() + .collect(HashMap::new, + (map, pair) -> + map.put(pair.getFirst(), new ArrayList<>(pair.getSecond().stream().toList())), + HashMap::putAll); + + BiomeUtil + .getTerraBiomeMap() + .forEach((vb, terraBiomes) -> + FabricUtil.getEntry(registry, vb) + .ifPresentOrElse(vanilla -> terraBiomes + .forEach(tb -> FabricUtil + .getEntry(registry, tb) + .ifPresentOrElse( + terra -> { + logger.debug( + vanilla.getKey() + .orElseThrow() + .getValue() + + " (vanilla for " + + terra.getKey() + .orElseThrow() + .getValue() + + ": " + + vanilla.streamTags() + .toList()); + + vanilla.streamTags() + .forEach( + tag -> collect + .computeIfAbsent( + tag, + t -> new ArrayList<>()) + .add(terra)); + }, + () -> logger.error( + "No such biome: {}", + tb))), + () -> logger.error("No vanilla biome: {}", vb))); + + registry.clearTags(); + registry.populateTags(ImmutableMap.copyOf(collect)); + + if(logger.isDebugEnabled()) { + registry.streamEntries() + .map(e -> e.registryKey().getValue() + ": " + + e.streamTags().reduce("", (s, t) -> t.id() + ", " + s, String::concat)) + .forEach(logger::debug); + } + } +} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/WorldEditUtil.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/WorldEditUtil.java deleted file mode 100644 index 159e4fbc8..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/util/WorldEditUtil.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.fabric.util; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.entity.Player; -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.sk89q.worldedit.IncompleteRegionException; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.world.World; - -public final class WorldEditUtil { - public static Pair getSelection(Player player) { - WorldEdit worldEdit = WorldEdit.getInstance(); - try { - Region selection = worldEdit.getSessionManager() - .get(com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer((ServerPlayerEntity) player)) - .getSelection(com.sk89q.worldedit.fabric.FabricAdapter.adapt((World) player.getWorld())); - BlockVector3 min = selection.getMinimumPoint(); - BlockVector3 max = selection.getMaximumPoint(); - Location l1 = new Location(player.getWorld(), min.getBlockX(), min.getBlockY(), min.getBlockZ()); - Location l2 = new Location(player.getWorld(), max.getBlockX(), max.getBlockY(), max.getBlockZ()); - return Pair.of(l1, l2); - } catch(IncompleteRegionException e) { - throw new IllegalStateException("No selection has been made", e); - } - } -} diff --git a/platforms/fabric/src/main/resources/assets/terra/lang/en_us.json b/platforms/fabric/src/main/resources/assets/terra/lang/en_us.json index 517b70815..116199214 100644 --- a/platforms/fabric/src/main/resources/assets/terra/lang/en_us.json +++ b/platforms/fabric/src/main/resources/assets/terra/lang/en_us.json @@ -1,4 +1,4 @@ { - "generator.terra": "Terra" + "generator.terra": "Terra" } diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json index cdc7b0742..9216ece30 100644 --- a/platforms/fabric/src/main/resources/fabric.mod.json +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -1,31 +1,32 @@ { - "schemaVersion": 1, - "id": "terra", - "version": "@VERSION@", - "name": "Terra", - "description": "@DESCRIPTION@", - "authors": [ - "dfsek" - ], - "contact": { - "homepage": "@WIKI@", - "sources": "@SOURCE@", - "issues": "@ISSUES@" - }, - "license": "@LICENSE@", - "icon": "assets/terra/icon.png", - "environment": "*", - "entrypoints": { - "main": [ - "com.dfsek.terra.fabric.TerraFabricPlugin" - ] - }, - "mixins": [ - "terra.mixins.json" - ], - "depends": { - "fabricloader": ">=0.7.4", - "minecraft": "1.17.x" - }, - "accessWidener": "terra.accesswidener" + "schemaVersion": 1, + "id": "terra", + "version": "@VERSION@", + "name": "Terra", + "description": "@DESCRIPTION@", + "authors": [ + "dfsek" + ], + "contact": { + "homepage": "@WIKI@", + "sources": "@SOURCE@", + "issues": "@ISSUES@" + }, + "license": "@LICENSE@", + "icon": "assets/terra/icon.png", + "environment": "*", + "entrypoints": { + "main": [ + "com.dfsek.terra.fabric.FabricEntryPoint" + ] + }, + "mixins": [ + "terra.mixins.json" + ], + "depends": { + "fabricloader": ">=0.14.2", + "java": ">=17", + "minecraft": "1.18.x" + }, + "accessWidener": "terra.accesswidener" } \ No newline at end of file diff --git a/platforms/fabric/src/main/resources/terra.accesswidener b/platforms/fabric/src/main/resources/terra.accesswidener index 377aee552..0e84c041c 100644 --- a/platforms/fabric/src/main/resources/terra.accesswidener +++ b/platforms/fabric/src/main/resources/terra.accesswidener @@ -1,3 +1,5 @@ accessWidener v1 named extendable method net/minecraft/client/world/GeneratorType (Ljava/lang/String;)V + +accessible method net/minecraft/world/biome/Biome getCategory ()Lnet/minecraft/world/biome/Biome$Category; diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index f2f42900c..1a638ef5f 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -1,49 +1,51 @@ { - "required": true, - "minVersion": "0.8", - "package": "com.dfsek.terra.fabric.mixin", - "compatibilityLevel": "JAVA_16", - "mixins": [ - "StructureAccessorAccessor", - "CommandManagerMixin", - "ServerWorldMixin", - "access.BiomeEffectsAccessor", - "access.MobSpawnerLogicAccessor", - "access.StateAccessor", - "implementations.BiomeMixin", - "implementations.ChunkGeneratorMixin", - "implementations.ConfiguredFeatureMixin", - "implementations.block.BlockEntityMixin", - "implementations.block.BlockMixin", - "implementations.block.state.LootableContainerBlockEntityMixin", - "implementations.block.state.MobSpawnerBlockEntityMixin", - "implementations.block.state.SignBlockEntityMixin", - "implementations.chunk.ChunkRegionMixin", - "implementations.chunk.WorldChunkMixin", - "implementations.chunk.data.ProtoChunkMixin", - "implementations.entity.EntityMixin", - "implementations.entity.EntityTypeMixin", - "implementations.entity.PlayerEntityMixin", - "implementations.entity.ServerCommandSourceMixin", - "implementations.inventory.LockableContainerBlockEntityMixin", - "implementations.inventory.item.ItemMixin", - "implementations.inventory.item.ItemStackMixin", - "implementations.inventory.meta.EnchantmentMixin", - "implementations.inventory.meta.ItemStackDamageableMixin", - "implementations.inventory.meta.ItemStackMetaMixin", - "implementations.world.ChunkRegionMixin", - "implementations.world.ServerWorldMixin" - ], - "client": [ - "access.GeneratorTypeAccessor", - "lifecycle.client.MinecraftClientMixin" - ], - "server": [ - "lifecycle.server.GeneratorOptionsMixin", - "lifecycle.server.ServerMainMixin" - ], - "injectors": { - "defaultRequire": 1 - }, - "refmap": "terra-refmap.json" + "required": true, + "minVersion": "0.8", + "package": "com.dfsek.terra.fabric.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "access.MobSpawnerLogicAccessor", + "access.StateAccessor", + "access.StructureAccessorAccessor", + "compat.GenerationSettingsFloraFeaturesMixin", + "implementations.BiomeMixin", + "implementations.HandleImplementationMixin", + "implementations.block.BlockMixin", + "implementations.block.entity.BlockEntityMixin", + "implementations.block.entity.LootableContainerBlockEntityMixin", + "implementations.block.entity.MobSpawnerBlockEntityMixin", + "implementations.block.entity.SignBlockEntityMixin", + "implementations.block.state.BlockStateMixin", + "implementations.block.state.PropertyMixin", + "implementations.chunk.ChunkRegionMixin", + "implementations.chunk.WorldChunkMixin", + "implementations.chunk.data.ProtoChunkMixin", + "implementations.entity.EntityMixin", + "implementations.entity.EntityTypeMixin", + "implementations.entity.PlayerEntityMixin", + "implementations.entity.ServerCommandSourceMixin", + "implementations.inventory.LockableContainerBlockEntityMixin", + "implementations.inventory.item.ItemMixin", + "implementations.inventory.item.ItemStackMixin", + "implementations.inventory.meta.EnchantmentMixin", + "implementations.inventory.meta.ItemStackDamageableMixin", + "implementations.inventory.meta.ItemStackMetaMixin", + "implementations.world.ChunkRegionMixin", + "implementations.world.ServerWorldMixin", + "lifecycle.DataPackContentsMixin", + "lifecycle.MinecraftServerMixin", + "lifecycle.RegistryMixin" + ], + "client": [ + "access.GeneratorTypeAccessor", + "lifecycle.client.MinecraftClientMixin" + ], + "server": [ + "lifecycle.server.GeneratorOptionsMixin", + "lifecycle.server.ServerMainMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "refmap": "terra-refmap.json" } \ No newline at end of file diff --git a/platforms/forge/build.gradle.kts.old b/platforms/forge/build.gradle.kts.old deleted file mode 100644 index 682981977..000000000 --- a/platforms/forge/build.gradle.kts.old +++ /dev/null @@ -1,142 +0,0 @@ -import com.dfsek.terra.configureCommon -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.minecraftforge.gradle.common.util.RunConfig -import net.minecraftforge.gradle.userdev.UserDevExtension -import net.minecraftforge.gradle.userdev.tasks.RenameJarInPlace - -buildscript { - repositories { - maven { url = uri("https://files.minecraftforge.net/maven") } - jcenter() - mavenCentral() - maven { url = uri("https://repo.spongepowered.org/repository/maven-public/") } - } - dependencies { - classpath(group = "net.minecraftforge.gradle", name = "ForgeGradle", version = "4.1.+") - classpath("org.spongepowered:mixingradle:0.7-SNAPSHOT") - } -} -apply(plugin = "net.minecraftforge.gradle") -apply(plugin = "org.spongepowered.mixin") - -configure { - add(sourceSets.main.get(), "terra-refmap.json") -} - -plugins { - java - id("com.modrinth.minotaur").version("1.1.0") -} - -configureCommon() - -group = "com.dfsek.terra.forge" - -repositories { - maven { url = uri("https://files.minecraftforge.net/maven") } - jcenter() - mavenCentral() - maven { url = uri("https://repo.spongepowered.org/repository/maven-public/") } -} - -val forgeVersion = "36.1.13" -val mcVersion = "1.16.5" -dependencies { - "shadedApi"(project(":common")) - "minecraft"("net.minecraftforge:forge:$mcVersion-$forgeVersion") - "annotationProcessor"("org.spongepowered:mixin:0.8.2:processor") -} - -if ("true" == System.getProperty("idea.sync.active")) { - afterEvaluate { - tasks.withType().all { - options.annotationProcessorPath = files() - } - } -} - - -tasks.named("shadowJar") { - archiveBaseName.set(tasks.getByName("jar").archiveBaseName.orNull) // Pain. Agony, even. - archiveClassifier.set("") // Suffering, if you will. -} - -afterEvaluate { - tasks.named("reobfJar") { - val shadow = tasks.getByName("shadowJar"); - dependsOn(shadow) - input = shadow.archiveFile.orNull?.asFile - } -} - -configure { - mappings(mapOf( - "channel" to "official", - "version" to mcVersion - )) - runs { - val runConfig = Action { - properties(mapOf( - //"forge.logging.markers" to "SCAN,REGISTRIES,REGISTRYDUMP", - "forge.logging.console.level" to "debug" - )) - arg("-mixin.config=terra.mixins.json") - workingDirectory = project.file("run").canonicalPath - source(sourceSets["main"]) - } - create("client", runConfig) - create("server", runConfig) - } -} - -tasks.register("deobfJar") { - from(sourceSets["main"].output) - archiveClassifier.set("dev") - group = "forge" -} - -val deobfElements = configurations.register("deobfElements") { - isVisible = false - description = "De-obfuscated elements for libs" - isCanBeResolved = false - isCanBeConsumed = true - attributes { - attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage.JAVA_API)) - attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY)) - attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling.EXTERNAL)) - attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR)) - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 8) - } - outgoing.artifact(tasks.named("deobfJar")) -} - -val javaComponent = components["java"] as AdhocComponentWithVariants -javaComponent.addVariantsFromConfiguration(deobfElements.get()) { - mapToMavenScope("runtime") -} - -tasks.jar { - manifest { - attributes(mapOf( - "Specification-Title" to "terra", - "Specification-Vendor" to "Terra", - "Specification-Version" to "1.0", - "Implementation-Title" to "Terra", - "Implementation-Version" to project.version, - "Implementation-Vendor" to "terra", - "MixinConfigs" to "terra.mixins.json" - )) - } -} - -tasks.register("publishModrinthForge") { - dependsOn("reobfJar") - group = "forge" - token = System.getenv("MODRINTH_SECRET") - projectId = "FIlZB9L0" - versionNumber = "${project.version}-forge" - uploadFile = tasks.named("reobfJar").get().input.absoluteFile - releaseType = "alpha" - addGameVersion("1.16.5") - addLoader("forge") -} \ No newline at end of file diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAdapter.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAdapter.java deleted file mode 100644 index 6b9f585d3..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeAdapter.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.dfsek.terra.forge; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.state.Container; -import com.dfsek.terra.api.platform.block.state.MobSpawner; -import com.dfsek.terra.api.platform.block.state.Sign; -import com.dfsek.terra.forge.block.ForgeBlockData; -import com.dfsek.terra.forge.block.data.ForgeDirectional; -import com.dfsek.terra.forge.block.data.ForgeMultipleFacing; -import com.dfsek.terra.forge.block.data.ForgeOrientable; -import com.dfsek.terra.forge.block.data.ForgeRotatable; -import com.dfsek.terra.forge.block.data.ForgeSlab; -import com.dfsek.terra.forge.block.data.ForgeStairs; -import com.dfsek.terra.forge.block.data.ForgeWaterlogged; -import net.minecraft.block.BlockState; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.tileentity.LockableLootTileEntity; -import net.minecraft.tileentity.MobSpawnerTileEntity; -import net.minecraft.tileentity.SignTileEntity; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IWorld; - -import java.util.Arrays; - -public final class ForgeAdapter { - public static BlockPos adapt(Vector3 v) { - return new BlockPos(v.getBlockX(), v.getBlockY(), v.getBlockZ()); - } - - public static Vector3 adapt(BlockPos pos) { - return new Vector3(pos.getX(), pos.getY(), pos.getZ()); - } - - public static ForgeBlockData adapt(BlockState state) { - if(state.hasProperty(BlockStateProperties.STAIRS_SHAPE)) return new ForgeStairs(state); - - if(state.hasProperty(BlockStateProperties.SLAB_TYPE)) return new ForgeSlab(state); - - if(state.hasProperty(BlockStateProperties.AXIS)) return new ForgeOrientable(state, BlockStateProperties.AXIS); - if(state.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) return new ForgeOrientable(state, BlockStateProperties.HORIZONTAL_AXIS); - - if(state.hasProperty(BlockStateProperties.ROTATION_16)) return new ForgeRotatable(state); - - if(state.hasProperty(BlockStateProperties.FACING)) return new ForgeDirectional(state, BlockStateProperties.FACING); - if(state.hasProperty(BlockStateProperties.FACING_HOPPER)) return new ForgeDirectional(state, BlockStateProperties.FACING_HOPPER); - if(state.hasProperty(BlockStateProperties.HORIZONTAL_FACING)) - return new ForgeDirectional(state, BlockStateProperties.HORIZONTAL_FACING); - - if(state.getProperties().containsAll(Arrays.asList(BlockStateProperties.NORTH, BlockStateProperties.SOUTH, BlockStateProperties.EAST, BlockStateProperties.WEST))) - return new ForgeMultipleFacing(state); - if(state.hasProperty(BlockStateProperties.WATERLOGGED)) return new ForgeWaterlogged(state); - return new ForgeBlockData(state); - } - - public static com.dfsek.terra.api.platform.block.state.BlockState adapt(com.dfsek.terra.api.platform.block.Block block) { - IWorld worldAccess = (IWorld) block.getLocation().getWorld(); - - TileEntity entity = worldAccess.getBlockEntity(adapt(block.getLocation().toVector())); - if(entity instanceof SignTileEntity) { - return (Sign) entity; - } else if(entity instanceof MobSpawnerTileEntity) { - return (MobSpawner) entity; - } else if(entity instanceof LockableLootTileEntity) { - return (Container) entity; - } - return null; - } - - public static Direction adapt(BlockFace face) { - switch(face) { - case NORTH: - return Direction.NORTH; - case WEST: - return Direction.WEST; - case SOUTH: - return Direction.SOUTH; - case EAST: - return Direction.EAST; - case UP: - return Direction.UP; - case DOWN: - return Direction.DOWN; - default: - throw new IllegalArgumentException("Illegal direction: " + face); - } - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeUtil.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeUtil.java deleted file mode 100644 index e7f77feec..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/ForgeUtil.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.dfsek.terra.forge; - -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.dfsek.terra.config.builder.BiomeBuilder; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.config.templates.BiomeTemplate; -import com.dfsek.terra.forge.config.PostLoadCompatibilityOptions; -import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.registry.WorldGenRegistries; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.BiomeAmbience; -import net.minecraft.world.biome.BiomeGenerationSettings; -import net.minecraft.world.gen.GenerationStage; -import net.minecraft.world.gen.carver.ConfiguredCarver; -import net.minecraft.world.gen.feature.ConfiguredFeature; -import net.minecraft.world.gen.feature.StructureFeature; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.function.Supplier; - -public final class ForgeUtil { - public static String createBiomeID(ConfigPack pack, String biomeID) { - return pack.getTemplate().getID().toLowerCase() + "/" + biomeID.toLowerCase(Locale.ROOT); - } - - public static Biome createBiome(BiomeBuilder biome, ConfigPack pack, TerraForgePlugin.ForgeAddon forgeAddon) { - BiomeTemplate template = biome.getTemplate(); - Map colors = template.getColors(); - - Biome vanilla = (Biome) (new ArrayList<>(biome.getVanillaBiomes().getContents()).get(0)).getHandle(); - - BiomeGenerationSettings.Builder generationSettings = new BiomeGenerationSettings.Builder(); - - generationSettings.surfaceBuilder(vanilla.getGenerationSettings().getSurfaceBuilder()); // It needs a surfacebuilder, even though we dont use it. - - generationSettings.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, TerraForgePlugin.POPULATOR_CONFIGURED_FEATURE); - - if(pack.getTemplate().vanillaCaves()) { - for(GenerationStage.Carving carver : GenerationStage.Carving.values()) { - for(Supplier> configuredCarverSupplier : vanilla.getGenerationSettings().getCarvers(carver)) { - generationSettings.addCarver(carver, configuredCarverSupplier.get()); - } - } - } - - Pair pair = forgeAddon.getTemplates().get(pack); - PreLoadCompatibilityOptions compatibilityOptions = pair.getLeft(); - PostLoadCompatibilityOptions postLoadCompatibilityOptions = pair.getRight(); - - TerraForgePlugin.getInstance().getDebugLogger().info("Injecting Vanilla structures and features into Terra biome " + biome.getTemplate().getID()); - - for(Supplier> structureFeature : vanilla.getGenerationSettings().structures()) { - ResourceLocation key = WorldGenRegistries.CONFIGURED_STRUCTURE_FEATURE.getKey(structureFeature.get()); - if(!compatibilityOptions.getExcludedBiomeStructures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeStructures().getOrDefault(biome, Collections.emptySet()).contains(key)) { - generationSettings.addStructureStart(structureFeature.get()); - TerraForgePlugin.getInstance().getDebugLogger().info("Injected structure " + key); - } - } - - if(compatibilityOptions.doBiomeInjection()) { - for(int step = 0; step < vanilla.getGenerationSettings().features().size(); step++) { - for(Supplier> featureSupplier : vanilla.getGenerationSettings().features().get(step)) { - ResourceLocation key = WorldGenRegistries.CONFIGURED_FEATURE.getKey(featureSupplier.get()); - if(!compatibilityOptions.getExcludedBiomeFeatures().contains(key) && !postLoadCompatibilityOptions.getExcludedPerBiomeFeatures().getOrDefault(biome, Collections.emptySet()).contains(key)) { - generationSettings.addFeature(step, featureSupplier); - TerraForgePlugin.getInstance().getDebugLogger().info("Injected feature " + key + " at stage " + step); - } - } - } - } - - BiomeAmbience vanillaEffects = vanilla.getSpecialEffects(); - BiomeAmbience.Builder effects = new BiomeAmbience.Builder() - .waterColor(colors.getOrDefault("water", vanillaEffects.getWaterColor())) - .waterFogColor(colors.getOrDefault("water-fog", vanillaEffects.getWaterFogColor())) - .fogColor(colors.getOrDefault("fog", vanillaEffects.getFogColor())) - .skyColor(colors.getOrDefault("sky", vanillaEffects.getSkyColor())) - .grassColorModifier(vanillaEffects.getGrassColorModifier()); - - if(colors.containsKey("grass")) { - effects.grassColorOverride(colors.get("grass")); - } else { - vanillaEffects.getGrassColorOverride().ifPresent(effects::grassColorOverride); - } - - if(colors.containsKey("foliage")) { - effects.foliageColorOverride(colors.get("foliage")); - } else { - vanillaEffects.getFoliageColorOverride().ifPresent(effects::foliageColorOverride); - } - - return new Biome.Builder() - .precipitation(vanilla.getPrecipitation()) - .biomeCategory(vanilla.getBiomeCategory()) - .depth(vanilla.getDepth()) - .scale(vanilla.getScale()) - .temperature(vanilla.getBaseTemperature()) - .downfall(vanilla.getDownfall()) - .specialEffects(effects.build()) - .mobSpawnSettings(vanilla.getMobSettings()) - .generationSettings(generationSettings.build()) - .build() - .setRegistryName("terra", createBiomeID(template.getPack(), template.getID())); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java deleted file mode 100644 index e24229ac7..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/TerraForgePlugin.java +++ /dev/null @@ -1,408 +0,0 @@ -package com.dfsek.terra.forge; - -import com.dfsek.tectonic.exception.ConfigException; -import com.dfsek.tectonic.exception.LoadException; -import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.addons.annotations.Addon; -import com.dfsek.terra.api.addons.annotations.Author; -import com.dfsek.terra.api.addons.annotations.Version; -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.TerraCommandManager; -import com.dfsek.terra.api.command.exception.MalformedCommandException; -import com.dfsek.terra.api.event.EventListener; -import com.dfsek.terra.api.event.EventManager; -import com.dfsek.terra.api.event.TerraEventManager; -import com.dfsek.terra.api.event.annotations.Global; -import com.dfsek.terra.api.event.annotations.Priority; -import com.dfsek.terra.api.event.events.config.ConfigPackPostLoadEvent; -import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.registry.CheckedRegistry; -import com.dfsek.terra.api.registry.LockedRegistry; -import com.dfsek.terra.api.transform.Transformer; -import com.dfsek.terra.api.transform.Validator; -import com.dfsek.terra.api.util.JarUtil; -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.dfsek.terra.api.util.logging.DebugLogger; -import com.dfsek.terra.commands.CommandUtil; -import com.dfsek.terra.config.GenericLoaders; -import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.config.lang.Language; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.forge.config.PostLoadCompatibilityOptions; -import com.dfsek.terra.forge.config.PreLoadCompatibilityOptions; -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import com.dfsek.terra.forge.generation.PopulatorFeature; -import com.dfsek.terra.forge.generation.TerraBiomeSource; -import com.dfsek.terra.forge.handle.ForgeItemHandle; -import com.dfsek.terra.forge.handle.ForgeWorldHandle; -import com.dfsek.terra.profiler.Profiler; -import com.dfsek.terra.profiler.ProfilerImpl; -import com.dfsek.terra.registry.exception.DuplicateEntryException; -import com.dfsek.terra.registry.master.AddonRegistry; -import com.dfsek.terra.registry.master.ConfigRegistry; -import com.dfsek.terra.world.TerraWorld; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.WorldGenRegistries; -import net.minecraft.world.DimensionType; -import net.minecraft.world.IWorld; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.feature.ConfiguredFeature; -import net.minecraft.world.gen.feature.Features; -import net.minecraft.world.gen.feature.IFeatureConfig; -import net.minecraft.world.gen.feature.NoFeatureConfig; -import net.minecraft.world.gen.placement.DecoratedPlacement; -import net.minecraft.world.gen.placement.NoPlacementConfig; -import net.minecraft.world.server.ServerWorld; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.ForgeRegistry; -import org.apache.commons.io.FileUtils; -import org.apache.logging.log4j.LogManager; -import org.objectweb.asm.Type; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.URISyntaxException; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.jar.JarFile; -import java.util.zip.ZipFile; - -@Mod("terra") -@Mod.EventBusSubscriber(modid = "terra", bus = Mod.EventBusSubscriber.Bus.MOD) -public class TerraForgePlugin implements TerraPlugin { - public static final PopulatorFeature POPULATOR_FEATURE = (PopulatorFeature) new PopulatorFeature(NoFeatureConfig.CODEC).setRegistryName("terra", "terra"); - public static final ConfiguredFeature POPULATOR_CONFIGURED_FEATURE = POPULATOR_FEATURE.configured(IFeatureConfig.NONE).decorated(DecoratedPlacement.NOPE.configured(NoPlacementConfig.INSTANCE)); - - private static TerraForgePlugin INSTANCE; - private final Map> worldMap = new HashMap<>(); - private final EventManager eventManager = new TerraEventManager(this); - private final GenericLoaders genericLoaders = new GenericLoaders(this); - private final Profiler profiler = new ProfilerImpl(); - - private final CommandManager manager = new TerraCommandManager(this); - - private final com.dfsek.terra.api.util.logging.Logger logger = new com.dfsek.terra.api.util.logging.Logger() { - private final org.apache.logging.log4j.Logger logger = LogManager.getLogger(); - - @Override - public void info(String message) { - logger.info(message); - } - - @Override - public void warning(String message) { - logger.warn(message); - } - - @Override - public void severe(String message) { - logger.error(message); - } - }; - - private final DebugLogger debugLogger = new DebugLogger(logger); - private final ItemHandle itemHandle = new ForgeItemHandle(); - private final WorldHandle worldHandle = new ForgeWorldHandle(); - private final ConfigRegistry registry = new ConfigRegistry(); - private final CheckedRegistry checkedRegistry = new CheckedRegistry<>(registry); - - private final ForgeAddon addon = new ForgeAddon(this); - - private final AddonRegistry addonRegistry = new AddonRegistry(addon, this); - private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); - private final PluginConfig config = new PluginConfig(); - private final Transformer biomeFixer = new Transformer.Builder() - .addTransform(id -> ForgeRegistries.BIOMES.getValue(ResourceLocation.tryParse(id)), Validator.notNull()) - .addTransform(id -> ForgeRegistries.BIOMES.getValue(ResourceLocation.tryParse("minecraft:" + id.toLowerCase())), Validator.notNull()).build(); - private final File dataFolder; - - public TerraForgePlugin() { - if(INSTANCE != null) throw new IllegalStateException("Only one TerraPlugin instance may exist."); - INSTANCE = this; - this.dataFolder = Paths.get("config", "Terra").toFile(); - saveDefaultConfig(); - config.load(this); - debugLogger.setDebug(config.isDebug()); - LangUtil.load(config.getLanguage(), this); - try { - CommandUtil.registerAll(manager); - } catch(MalformedCommandException e) { - e.printStackTrace(); // TODO do something here even though this should literally never happen - } - } - - public static TerraForgePlugin getInstance() { - return INSTANCE; - } - - @SubscribeEvent - public static void setupListener(FMLCommonSetupEvent event) { - event.enqueueWork(() -> { - Registry.register(Registry.BIOME_SOURCE, "terra:biome", TerraBiomeSource.CODEC); - Registry.register(Registry.CHUNK_GENERATOR, "terra:generator", ForgeChunkGeneratorWrapper.CODEC); - }); - } - - public void init() { - logger.info("Initializing Terra..."); - - if(!addonRegistry.loadAll()) { - throw new IllegalStateException("Failed to load addons. Please correct addon installations to continue."); - } - logger.info("Loaded addons."); - - registry.loadAll(this); - logger.info("Loaded packs."); - - ((ForgeRegistry) ForgeRegistries.BIOMES).unfreeze(); // Evil - getConfigRegistry().forEach(pack -> pack.getBiomeRegistry().forEach((id, biome) -> ForgeRegistries.BIOMES.register(ForgeUtil.createBiome(biome, pack, addon)))); // Register all Terra biomes. - ((ForgeRegistry) ForgeRegistries.BIOMES).freeze(); - } - - @Override - public WorldHandle getWorldHandle() { - return worldHandle; - } - - @Override - public TerraWorld getWorld(World world) { - return getWorld(((IWorld) world).dimensionType()); - } - - public TerraWorld getWorld(DimensionType type) { - TerraWorld world = worldMap.get(type).getRight(); - if(world == null) throw new IllegalArgumentException("No world exists with dimension type " + type); - return world; - } - - /** - * evil code brought to you by Forge Mod Loader - *

- * Forge changes the JAR URI to something that cannot - * be resolved back to the original JAR, so we have to - * do this to get our JAR. - */ - @Override - public JarFile getModJar() throws URISyntaxException, IOException { - File modsDir = new File("./mods"); - - if(!modsDir.exists()) return JarUtil.getJarFile(); - - for(File file : Objects.requireNonNull(modsDir.listFiles((dir, name) -> name.endsWith(".jar")))) { - try(ZipFile zipFile = new ZipFile(file)) { - if(zipFile.getEntry(Type.getInternalName(TerraPlugin.class) + ".class") != null) { - return new JarFile(file); - } - } - } - return JarUtil.getJarFile(); - } - - @Override - public com.dfsek.terra.api.util.logging.Logger logger() { - return logger; - } - - @Override - public PluginConfig getTerraConfig() { - return config; - } - - @Override - public File getDataFolder() { - return dataFolder; - } - - @Override - public boolean isDebug() { - return config.isDebug(); - } - - @Override - public Language getLanguage() { - return LangUtil.getLanguage(); - } - - @Override - public CheckedRegistry getConfigRegistry() { - return checkedRegistry; - } - - @Override - public LockedRegistry getAddons() { - return addonLockedRegistry; - } - - @Override - public boolean reload() { - config.load(this); - LangUtil.load(config.getLanguage(), this); // Load language. - boolean succeed = registry.loadAll(this); - worldMap.forEach((seed, pair) -> { - pair.getRight().getConfig().getSamplerCache().clear(); - String packID = pair.getRight().getConfig().getTemplate().getID(); - pair.setRight(new TerraWorld(pair.getRight().getWorld(), registry.get(packID), this)); - }); - return succeed; - } - - @Override - public ItemHandle getItemHandle() { - return itemHandle; - } - - @Override - public void saveDefaultConfig() { - try(InputStream stream = getClass().getResourceAsStream("/config.yml")) { - File configFile = new File(getDataFolder(), "config.yml"); - if(!configFile.exists()) FileUtils.copyInputStreamToFile(stream, configFile); - } catch(IOException e) { - e.printStackTrace(); - } - } - - @Override - public String platformName() { - return "Forge"; - } - - @Override - public DebugLogger getDebugLogger() { - return debugLogger; - } - - @Override - public void register(TypeRegistry registry) { - genericLoaders.register(registry); - registry - .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) - .registerLoader(com.dfsek.terra.api.platform.world.Biome.class, (t, o, l) -> biomeFixer.translate((String) o)) - .registerLoader(ResourceLocation.class, (t, o, l) -> { - ResourceLocation identifier = ResourceLocation.tryParse((String) o); - if(identifier == null) throw new LoadException("Invalid identifier: " + o); - return identifier; - }); - } - - @Override - public EventManager getEventManager() { - return eventManager; - } - - @Override - public Profiler getProfiler() { - return profiler; - } - - public CommandManager getManager() { - return manager; - } - - public Map> getWorldMap() { - return worldMap; - } - - @Addon("Terra-Forge") - @Author("Terra") - @Version("1.0.0") - public static final class ForgeAddon extends TerraAddon implements EventListener { - - private final Map> templates = new HashMap<>(); - - private final TerraPlugin main; - - private ForgeAddon(TerraPlugin main) { - this.main = main; - } - - @Override - public void initialize() { - main.getEventManager().registerListener(this, this); - } - - @Priority(Priority.LOWEST) - @Global - public void injectTrees(ConfigPackPreLoadEvent event) { - CheckedRegistry treeRegistry = event.getPack().getTreeRegistry(); - injectTree(treeRegistry, "BROWN_MUSHROOM", Features.HUGE_BROWN_MUSHROOM); - injectTree(treeRegistry, "RED_MUSHROOM", Features.HUGE_RED_MUSHROOM); - injectTree(treeRegistry, "JUNGLE", Features.MEGA_JUNGLE_TREE); - injectTree(treeRegistry, "JUNGLE_COCOA", Features.JUNGLE_TREE); - injectTree(treeRegistry, "LARGE_OAK", Features.FANCY_OAK); - injectTree(treeRegistry, "LARGE_SPRUCE", Features.PINE); - injectTree(treeRegistry, "SMALL_JUNGLE", Features.JUNGLE_TREE); - injectTree(treeRegistry, "SWAMP_OAK", Features.SWAMP_TREE); - injectTree(treeRegistry, "TALL_BIRCH", Features.BIRCH_TALL); - injectTree(treeRegistry, "ACACIA", Features.ACACIA); - injectTree(treeRegistry, "BIRCH", Features.BIRCH); - injectTree(treeRegistry, "DARK_OAK", Features.DARK_OAK); - injectTree(treeRegistry, "OAK", Features.OAK); - injectTree(treeRegistry, "CHORUS_PLANT", Features.CHORUS_PLANT); - injectTree(treeRegistry, "SPRUCE", Features.SPRUCE); - injectTree(treeRegistry, "JUNGLE_BUSH", Features.JUNGLE_BUSH); - injectTree(treeRegistry, "MEGA_SPRUCE", Features.MEGA_SPRUCE); - injectTree(treeRegistry, "CRIMSON_FUNGUS", Features.CRIMSON_FUNGI); - injectTree(treeRegistry, "WARPED_FUNGUS", Features.WARPED_FUNGI); - PreLoadCompatibilityOptions template = new PreLoadCompatibilityOptions(); - try { - event.loadTemplate(template); - } catch(ConfigException e) { - e.printStackTrace(); - } - - if(template.doRegistryInjection()) { - WorldGenRegistries.CONFIGURED_FEATURE.entrySet().forEach(entry -> { - if(!template.getExcludedRegistryFeatures().contains(entry.getKey().getRegistryName())) { - try { - event.getPack().getTreeRegistry().add(entry.getKey().getRegistryName().toString(), (Tree) entry.getValue()); - main.getDebugLogger().info("Injected ConfiguredFeature " + entry.getKey().getRegistryName() + " as Tree: " + entry.getValue()); - } catch(DuplicateEntryException ignored) { - } - } - }); - } - templates.put(event.getPack(), Pair.of(template, null)); - } - - @Priority(Priority.HIGHEST) - @Global - public void createInjectionOptions(ConfigPackPostLoadEvent event) { - PostLoadCompatibilityOptions template = new PostLoadCompatibilityOptions(); - - try { - event.loadTemplate(template); - } catch(ConfigException e) { - e.printStackTrace(); - } - - templates.get(event.getPack()).setRight(template); - } - - - private void injectTree(CheckedRegistry registry, String id, ConfiguredFeature tree) { - try { - registry.add(id, (Tree) tree); - } catch(DuplicateEntryException ignore) { - } - } - - public Map> getTemplates() { - return templates; - } - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlock.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlock.java deleted file mode 100644 index 98ad4d61e..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlock.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.dfsek.terra.forge.block; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.forge.ForgeAdapter; -import net.minecraft.block.FlowingFluidBlock; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IWorld; - -public class ForgeBlock implements Block { - private final Handle delegate; - - public ForgeBlock(BlockPos position, IWorld worldAccess) { - this.delegate = new Handle(position, worldAccess); - } - - @Override - public void setBlockData(BlockData data, boolean physics) { - delegate.worldAccess.setBlock(delegate.position, ((ForgeBlockData) data).getHandle(), physics ? 3 : 1042); - if(physics && ((ForgeBlockData) data).getHandle().getBlock() instanceof FlowingFluidBlock) { - delegate.worldAccess.getLiquidTicks().scheduleTick(delegate.position, ((FlowingFluidBlock) ((ForgeBlockData) data).getHandle().getBlock()).getFluidState(((ForgeBlockData) data).getHandle()).getFluidState().getType(), 0); - } - } - - @Override - public BlockData getBlockData() { - return new ForgeBlockData(delegate.worldAccess.getBlockState(delegate.position)); - } - - @Override - public BlockState getState() { - return ForgeAdapter.adapt(this); - } - - @Override - public Block getRelative(BlockFace face, int len) { - BlockPos newPos = delegate.position.offset(face.getModX() * len, face.getModY() * len, face.getModZ() * len); - return new ForgeBlock(newPos, delegate.worldAccess); - } - - @Override - public boolean isEmpty() { - return getBlockData().isAir(); - } - - @Override - public Location getLocation() { - return ForgeAdapter.adapt(delegate.position).toLocation((World) delegate.worldAccess); - } - - @Override - public BlockType getType() { - return getBlockData().getBlockType(); - } - - @Override - public int getX() { - return delegate.position.getX(); - } - - @Override - public int getZ() { - return delegate.position.getZ(); - } - - @Override - public int getY() { - return delegate.position.getY(); - } - - @Override - public boolean isPassable() { - return isEmpty(); - } - - @Override - public Handle getHandle() { - return delegate; - } - - public static final class Handle { - private final BlockPos position; - private final IWorld worldAccess; - - public Handle(BlockPos position, IWorld worldAccess) { - this.position = position; - this.worldAccess = worldAccess; - } - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlockData.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlockData.java deleted file mode 100644 index 1fb22ec35..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/ForgeBlockData.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.dfsek.terra.forge.block; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.state.Property; -import net.minecraftforge.registries.ForgeRegistries; - -import javax.annotation.Nullable; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class ForgeBlockData implements BlockData { - private static final Function, Comparable>, String> PROPERTY_MAPPER = new Function, Comparable>, String>() { - public String apply(@Nullable Map.Entry, Comparable> entry) { - if (entry == null) { - return ""; - } else { - Property property = entry.getKey(); - return property.getName() + "=" + this.getName(property, entry.getValue()); - } - } - - @SuppressWarnings("unchecked") - private > String getName(Property property, Comparable comparable) { - return property.getName((T)comparable); - } - }; - - protected BlockState delegate; - - public ForgeBlockData(BlockState delegate) { - this.delegate = delegate; - } - - @Override - public BlockType getBlockType() { - return (BlockType) delegate.getBlock(); - } - - @Override - public boolean matches(BlockData other) { - return delegate.getBlock() == ((ForgeBlockData) other).delegate.getBlock(); - } - - @Override - public BlockData clone() { - try { - return (ForgeBlockData) super.clone(); - } catch(CloneNotSupportedException e) { - throw new Error(e); - } - } - - @Override - public String getAsString() { - StringBuilder data = new StringBuilder(Objects.requireNonNull(ForgeRegistries.BLOCKS.getKey(delegate.getBlock())).toString()); - if(!delegate.getProperties().isEmpty()) { - data.append('['); - data.append(delegate.getValues().entrySet().stream().map(PROPERTY_MAPPER).collect(Collectors.joining(","))); - data.append(']'); - } - return data.toString(); - } - - @Override - public boolean isAir() { - return delegate.isAir(); - } - - @Override - public boolean isStructureVoid() { - return delegate.getBlock() == Blocks.STRUCTURE_VOID; - } - - @Override - public BlockState getHandle() { - return delegate; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeAnaloguePowerable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeAnaloguePowerable.java deleted file mode 100644 index f8455c5c7..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeAnaloguePowerable.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.forge.block.data; - -import com.dfsek.terra.api.platform.block.data.AnaloguePowerable; -import com.dfsek.terra.forge.block.ForgeBlockData; -import net.minecraft.block.BlockState; - -/** - * None of this actually has implementation, TODO: implement this if we ever end up needing it. - */ -public class ForgeAnaloguePowerable extends ForgeBlockData implements AnaloguePowerable { - public ForgeAnaloguePowerable(BlockState delegate) { - super(delegate); - } - - @Override - public int getMaximumPower() { - return 0; - } - - @Override - public int getPower() { - return 0; - } - - @Override - public void setPower(int power) { - - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeDirectional.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeDirectional.java deleted file mode 100644 index c4cc15636..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeDirectional.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dfsek.terra.forge.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Directional; -import com.dfsek.terra.forge.ForgeAdapter; -import com.dfsek.terra.forge.block.ForgeBlockData; -import net.minecraft.block.BlockState; -import net.minecraft.state.DirectionProperty; - -public class ForgeDirectional extends ForgeBlockData implements Directional { - private final DirectionProperty property; - - public ForgeDirectional(BlockState delegate, DirectionProperty property) { - super(delegate); - this.property = property; - } - - @Override - public BlockFace getFacing() { - switch(delegate.getValue(property)) { - case SOUTH: - return BlockFace.SOUTH; - case DOWN: - return BlockFace.DOWN; - case UP: - return BlockFace.UP; - case EAST: - return BlockFace.EAST; - case WEST: - return BlockFace.WEST; - case NORTH: - return BlockFace.NORTH; - default: - throw new IllegalStateException(); - } - } - - @Override - public void setFacing(BlockFace facing) { - delegate = delegate.setValue(property, ForgeAdapter.adapt(facing)); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeEnumAdapter.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeEnumAdapter.java deleted file mode 100644 index 16ba0bb8a..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeEnumAdapter.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.dfsek.terra.forge.block.data; - -import com.dfsek.terra.api.platform.block.Axis; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Bisected; -import com.dfsek.terra.api.platform.block.data.Slab; -import com.dfsek.terra.api.platform.block.data.Stairs; -import net.minecraft.state.properties.Half; -import net.minecraft.state.properties.SlabType; -import net.minecraft.state.properties.StairsShape; -import net.minecraft.util.Direction; - -public final class ForgeEnumAdapter { - public static Stairs.Shape adapt(StairsShape shape) { - switch(shape) { - case OUTER_RIGHT: - return Stairs.Shape.OUTER_RIGHT; - case INNER_RIGHT: - return Stairs.Shape.INNER_RIGHT; - case OUTER_LEFT: - return Stairs.Shape.OUTER_LEFT; - case INNER_LEFT: - return Stairs.Shape.INNER_LEFT; - case STRAIGHT: - return Stairs.Shape.STRAIGHT; - default: - throw new IllegalStateException(); - } - } - - public static Bisected.Half adapt(Half half) { - switch(half) { - case BOTTOM: - return Bisected.Half.BOTTOM; - case TOP: - return Bisected.Half.TOP; - default: - throw new IllegalStateException(); - } - } - - public static BlockFace adapt(Direction direction) { - switch(direction) { - case DOWN: - return BlockFace.DOWN; - case UP: - return BlockFace.UP; - case WEST: - return BlockFace.WEST; - case EAST: - return BlockFace.EAST; - case NORTH: - return BlockFace.NORTH; - case SOUTH: - return BlockFace.SOUTH; - default: - throw new IllegalStateException(); - } - } - - public static Slab.Type adapt(SlabType type) { - switch(type) { - case BOTTOM: - return Slab.Type.BOTTOM; - case TOP: - return Slab.Type.TOP; - case DOUBLE: - return Slab.Type.DOUBLE; - default: - throw new IllegalStateException(); - } - } - - public static StairsShape adapt(Stairs.Shape shape) { - switch(shape) { - case STRAIGHT: - return StairsShape.STRAIGHT; - case INNER_LEFT: - return StairsShape.INNER_LEFT; - case OUTER_LEFT: - return StairsShape.OUTER_LEFT; - case INNER_RIGHT: - return StairsShape.INNER_RIGHT; - case OUTER_RIGHT: - return StairsShape.OUTER_RIGHT; - default: - throw new IllegalStateException(); - } - } - - public static Half adapt(Bisected.Half half) { - switch(half) { - case TOP: - return Half.TOP; - case BOTTOM: - return Half.BOTTOM; - default: - throw new IllegalStateException(); - } - } - - public static Direction adapt(BlockFace face) { - switch(face) { - case SOUTH: - return Direction.SOUTH; - case NORTH: - return Direction.NORTH; - case EAST: - return Direction.EAST; - case WEST: - return Direction.WEST; - case UP: - return Direction.UP; - case DOWN: - return Direction.DOWN; - default: - throw new IllegalArgumentException(); - } - } - - public static SlabType adapt(Slab.Type type) { - switch(type) { - case DOUBLE: - return SlabType.DOUBLE; - case TOP: - return SlabType.TOP; - case BOTTOM: - return SlabType.BOTTOM; - default: - throw new IllegalStateException(); - } - } - - public static Axis adapt(Direction.Axis axis) { - switch(axis) { - case X: - return Axis.X; - case Y: - return Axis.Y; - case Z: - return Axis.Z; - default: - throw new IllegalStateException(); - } - } - - public static Direction.Axis adapt(Axis axis) { - switch(axis) { - case Z: - return Direction.Axis.Z; - case Y: - return Direction.Axis.Y; - case X: - return Direction.Axis.X; - default: - throw new IllegalStateException(); - } - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeMultipleFacing.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeMultipleFacing.java deleted file mode 100644 index 7e9510282..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeMultipleFacing.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.dfsek.terra.forge.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.MultipleFacing; -import com.dfsek.terra.forge.block.ForgeBlockData; -import net.minecraft.block.BlockState; -import net.minecraft.state.properties.BlockStateProperties; - -import java.util.HashSet; -import java.util.Set; - -public class ForgeMultipleFacing extends ForgeBlockData implements MultipleFacing { - public ForgeMultipleFacing(BlockState delegate) { - super(delegate); - } - - @Override - public Set getFaces() { - Set set = new HashSet<>(); - if(delegate.getValue(BlockStateProperties.NORTH)) set.add(BlockFace.NORTH); - if(delegate.getValue(BlockStateProperties.SOUTH)) set.add(BlockFace.SOUTH); - if(delegate.getValue(BlockStateProperties.EAST)) set.add(BlockFace.EAST); - if(delegate.getValue(BlockStateProperties.WEST)) set.add(BlockFace.WEST); - if(delegate.hasProperty(BlockStateProperties.UP) && delegate.getValue(BlockStateProperties.UP)) set.add(BlockFace.UP); - if(delegate.hasProperty(BlockStateProperties.DOWN) && delegate.getValue(BlockStateProperties.DOWN)) set.add(BlockFace.DOWN); - return set; - } - - @Override - public void setFace(BlockFace face, boolean facing) { - switch(face) { - case NORTH: - delegate = delegate.setValue(BlockStateProperties.NORTH, facing); - break; - case SOUTH: - delegate = delegate.setValue(BlockStateProperties.SOUTH, facing); - break; - case EAST: - delegate = delegate.setValue(BlockStateProperties.EAST, facing); - break; - case WEST: - delegate = delegate.setValue(BlockStateProperties.WEST, facing); - break; - case UP: - delegate = delegate.setValue(BlockStateProperties.UP, facing); - break; - case DOWN: - delegate = delegate.setValue(BlockStateProperties.DOWN, facing); - break; - } - } - - @Override - public Set getAllowedFaces() { - Set set = new HashSet<>(); - if(delegate.hasProperty(BlockStateProperties.NORTH)) set.add(BlockFace.NORTH); - if(delegate.hasProperty(BlockStateProperties.SOUTH)) set.add(BlockFace.SOUTH); - if(delegate.hasProperty(BlockStateProperties.EAST)) set.add(BlockFace.EAST); - if(delegate.hasProperty(BlockStateProperties.WEST)) set.add(BlockFace.WEST); - if(delegate.hasProperty(BlockStateProperties.UP)) set.add(BlockFace.UP); - if(delegate.hasProperty(BlockStateProperties.DOWN)) set.add(BlockFace.DOWN); - return set; - } - - @Override - public boolean hasFace(BlockFace f) { - return getFaces().contains(f); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeOrientable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeOrientable.java deleted file mode 100644 index 9f3e53f2d..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeOrientable.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.forge.block.data; - -import com.dfsek.terra.api.platform.block.Axis; -import com.dfsek.terra.api.platform.block.data.Orientable; -import com.dfsek.terra.forge.block.ForgeBlockData; -import net.minecraft.block.BlockState; -import net.minecraft.state.EnumProperty; -import net.minecraft.util.Direction; - -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -public class ForgeOrientable extends ForgeBlockData implements Orientable { - private final EnumProperty property; - - public ForgeOrientable(BlockState delegate, EnumProperty property) { - super(delegate); - this.property = property; - } - - @Override - public Set getAxes() { - return Arrays.stream(Axis.values()).collect(Collectors.toSet()); - } - - @Override - public Axis getAxis() { - return ForgeEnumAdapter.adapt(getHandle().getValue(property)); - } - - @Override - public void setAxis(Axis axis) { - delegate = delegate.setValue(property, ForgeEnumAdapter.adapt(axis)); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeRotatable.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeRotatable.java deleted file mode 100644 index b64727b59..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeRotatable.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.dfsek.terra.forge.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Rotatable; -import com.dfsek.terra.forge.block.ForgeBlockData; -import net.minecraft.block.BlockState; -import net.minecraft.state.properties.BlockStateProperties; - -public class ForgeRotatable extends ForgeBlockData implements Rotatable { - public ForgeRotatable(BlockState delegate) { - super(delegate); - } - - @Override - public BlockFace getRotation() { - int r = delegate.getValue(BlockStateProperties.ROTATION_16); - switch(r) { - case 0: - return BlockFace.SOUTH; - case 1: - return BlockFace.SOUTH_SOUTH_WEST; - case 2: - return BlockFace.SOUTH_WEST; - case 3: - return BlockFace.WEST_SOUTH_WEST; - case 4: - return BlockFace.WEST; - case 5: - return BlockFace.WEST_NORTH_WEST; - case 6: - return BlockFace.NORTH_WEST; - case 7: - return BlockFace.NORTH_NORTH_WEST; - case 8: - return BlockFace.NORTH; - case 9: - return BlockFace.NORTH_NORTH_EAST; - case 10: - return BlockFace.NORTH_EAST; - case 11: - return BlockFace.EAST_NORTH_EAST; - case 12: - return BlockFace.EAST; - case 13: - return BlockFace.EAST_SOUTH_EAST; - case 14: - return BlockFace.SOUTH_EAST; - case 15: - return BlockFace.SOUTH_SOUTH_EAST; - default: - throw new IllegalArgumentException("Unknown rotation " + r); - } - } - - @Override - public void setRotation(BlockFace face) { - switch(face) { - case UP: - case DOWN: - throw new IllegalArgumentException("Illegal rotation " + face); - case SOUTH: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 0); - return; - case SOUTH_SOUTH_WEST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 1); - return; - case SOUTH_WEST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 2); - return; - case WEST_SOUTH_WEST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 3); - return; - case WEST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 4); - return; - case WEST_NORTH_WEST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 5); - return; - case NORTH_WEST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 6); - return; - case NORTH_NORTH_WEST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 7); - return; - case NORTH: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 8); - return; - case NORTH_NORTH_EAST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 9); - return; - case NORTH_EAST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 10); - return; - case EAST_NORTH_EAST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 11); - return; - case EAST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 12); - return; - case EAST_SOUTH_EAST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 13); - return; - case SOUTH_EAST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 14); - return; - case SOUTH_SOUTH_EAST: - delegate = delegate.setValue(BlockStateProperties.ROTATION_16, 15); - return; - } - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeSlab.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeSlab.java deleted file mode 100644 index 4f294604e..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeSlab.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.forge.block.data; - -import com.dfsek.terra.api.platform.block.data.Slab; -import net.minecraft.block.BlockState; -import net.minecraft.state.properties.BlockStateProperties; - -public class ForgeSlab extends ForgeWaterlogged implements Slab { - public ForgeSlab(BlockState delegate) { - super(delegate); - } - - @Override - public Type getType() { - return ForgeEnumAdapter.adapt(delegate.getValue(BlockStateProperties.SLAB_TYPE)); - } - - @Override - public void setType(Type type) { - delegate = delegate.setValue(BlockStateProperties.SLAB_TYPE, ForgeEnumAdapter.adapt(type)); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeStairs.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeStairs.java deleted file mode 100644 index ef9c6e8ff..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeStairs.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dfsek.terra.forge.block.data; - -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.data.Stairs; -import net.minecraft.block.BlockState; -import net.minecraft.state.properties.BlockStateProperties; - -public class ForgeStairs extends ForgeWaterlogged implements Stairs { - public ForgeStairs(BlockState delegate) { - super(delegate); - } - - @Override - public Shape getShape() { - return ForgeEnumAdapter.adapt(getHandle().getValue(BlockStateProperties.STAIRS_SHAPE)); - } - - @Override - public void setShape(Shape shape) { - super.delegate = getHandle().setValue(BlockStateProperties.STAIRS_SHAPE, ForgeEnumAdapter.adapt(shape)); - } - - @Override - public Half getHalf() { - return ForgeEnumAdapter.adapt(getHandle().getValue(BlockStateProperties.HALF)); - } - - @Override - public void setHalf(Half half) { - super.delegate = getHandle().setValue(BlockStateProperties.HALF, ForgeEnumAdapter.adapt(half)); - } - - @Override - public BlockFace getFacing() { - return ForgeEnumAdapter.adapt(getHandle().getValue(BlockStateProperties.HORIZONTAL_FACING)); - } - - @Override - public void setFacing(BlockFace facing) { - super.delegate = getHandle().setValue(BlockStateProperties.HORIZONTAL_FACING, ForgeEnumAdapter.adapt(facing)); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeWaterlogged.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeWaterlogged.java deleted file mode 100644 index ed6abffbe..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/block/data/ForgeWaterlogged.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.dfsek.terra.forge.block.data; - -import com.dfsek.terra.api.platform.block.data.Waterlogged; -import com.dfsek.terra.forge.block.ForgeBlockData; -import net.minecraft.block.BlockState; -import net.minecraft.state.properties.BlockStateProperties; - -public class ForgeWaterlogged extends ForgeBlockData implements Waterlogged { - public ForgeWaterlogged(BlockState delegate) { - super(delegate); - } - - @Override - public boolean isWaterlogged() { - return delegate.getValue(BlockStateProperties.WATERLOGGED); - } - - @Override - public void setWaterlogged(boolean waterlogged) { - super.delegate = delegate.setValue(BlockStateProperties.WATERLOGGED, waterlogged); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java deleted file mode 100644 index 7d0bd3e5b..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PostLoadCompatibilityOptions.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dfsek.terra.forge.config; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import com.dfsek.terra.config.builder.BiomeBuilder; -import net.minecraft.util.ResourceLocation; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -@SuppressWarnings("FieldMayBeFinal") -public class PostLoadCompatibilityOptions implements ConfigTemplate { - @Value("structures.inject-biome.exclude-biomes") - @Default - private Map> excludedPerBiomeStructures = new HashMap<>(); - - @Value("features.inject-biome.exclude-biomes") - @Default - private Map> excludedPerBiomeFeatures = new HashMap<>(); - - public Map> getExcludedPerBiomeFeatures() { - return excludedPerBiomeFeatures; - } - - public Map> getExcludedPerBiomeStructures() { - return excludedPerBiomeStructures; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java deleted file mode 100644 index 575327b59..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/config/PreLoadCompatibilityOptions.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.forge.config; - -import com.dfsek.tectonic.annotations.Default; -import com.dfsek.tectonic.annotations.Value; -import com.dfsek.tectonic.config.ConfigTemplate; -import net.minecraft.util.ResourceLocation; - -import java.util.HashSet; -import java.util.Set; - -@SuppressWarnings("FieldMayBeFinal") -public class PreLoadCompatibilityOptions implements ConfigTemplate { - @Value("features.inject-registry.enable") - @Default - private boolean doRegistryInjection = false; - - @Value("features.inject-biome.enable") - @Default - private boolean doBiomeInjection = false; - - @Value("features.inject-registry.excluded-features") - @Default - private Set excludedRegistryFeatures = new HashSet<>(); - - @Value("features.inject-biome.excluded-features") - @Default - private Set excludedBiomeFeatures = new HashSet<>(); - - @Value("structures.inject-biome.excluded-features") - @Default - private Set excludedBiomeStructures = new HashSet<>(); - - public boolean doBiomeInjection() { - return doBiomeInjection; - } - - public boolean doRegistryInjection() { - return doRegistryInjection; - } - - public Set getExcludedBiomeFeatures() { - return excludedBiomeFeatures; - } - - public Set getExcludedRegistryFeatures() { - return excludedRegistryFeatures; - } - - public Set getExcludedBiomeStructures() { - return excludedBiomeStructures; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java deleted file mode 100644 index 3a34608b6..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/ForgeChunkGeneratorWrapper.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.dfsek.terra.forge.generation; - -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkData; -import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; -import com.dfsek.terra.api.util.FastRandom; -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.api.world.locate.AsyncStructureFinder; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.forge.ForgeAdapter; -import com.dfsek.terra.forge.TerraForgePlugin; -import com.dfsek.terra.world.TerraWorld; -import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; -import com.dfsek.terra.world.generation.math.samplers.Sampler; -import com.dfsek.terra.world.population.items.TerraStructure; -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.jafama.FastMath; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.util.SharedSeedRandom; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.registry.DynamicRegistries; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.Blockreader; -import net.minecraft.world.DimensionType; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.IWorld; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.BiomeManager; -import net.minecraft.world.chunk.IChunk; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.GenerationStage; -import net.minecraft.world.gen.Heightmap; -import net.minecraft.world.gen.WorldGenRegion; -import net.minecraft.world.gen.feature.structure.Structure; -import net.minecraft.world.gen.feature.structure.StructureManager; -import net.minecraft.world.gen.feature.template.TemplateManager; -import net.minecraft.world.gen.settings.DimensionStructuresSettings; -import net.minecraft.world.server.ServerWorld; -import net.minecraft.world.spawner.WorldEntitySpawner; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -public class ForgeChunkGeneratorWrapper extends ChunkGenerator implements GeneratorWrapper { - private final long seed; - private final DefaultChunkGenerator3D delegate; - private final TerraBiomeSource biomeSource; - public static final Codec PACK_CODEC = (RecordCodecBuilder.create(config -> config.group( - Codec.STRING.fieldOf("pack").forGetter(pack -> pack.getTemplate().getID()) - ).apply(config, config.stable(TerraForgePlugin.getInstance().getConfigRegistry()::get)))); - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - TerraBiomeSource.CODEC.fieldOf("biome_source").forGetter(generator -> generator.biomeSource), - Codec.LONG.fieldOf("seed").stable().forGetter(generator -> generator.seed), - PACK_CODEC.fieldOf("pack").stable().forGetter(generator -> generator.pack)) - .apply(instance, instance.stable(ForgeChunkGeneratorWrapper::new))); - private final ConfigPack pack; - - public ConfigPack getPack() { - return pack; - } - - private DimensionType dimensionType; - - public ForgeChunkGeneratorWrapper(TerraBiomeSource biomeSource, long seed, ConfigPack configPack) { - super(biomeSource, new DimensionStructuresSettings(false)); - this.pack = configPack; - - this.delegate = new DefaultChunkGenerator3D(pack, TerraForgePlugin.getInstance()); - delegate.getMain().logger().info("Loading world with config pack " + pack.getTemplate().getID()); - this.biomeSource = biomeSource; - - this.seed = seed; - } - - @Override - protected @NotNull Codec codec() { - return CODEC; - } - - @Override - public @NotNull ChunkGenerator withSeed(long seed) { - return new ForgeChunkGeneratorWrapper((TerraBiomeSource) this.biomeSource.withSeed(seed), seed, pack); - } - - @Override - public void buildSurfaceAndBedrock(@NotNull WorldGenRegion p_225551_1_, @NotNull IChunk p_225551_2_) { - - } - - @Nullable - @Override - public BlockPos findNearestMapFeature(@NotNull ServerWorld world, @NotNull Structure feature, @NotNull BlockPos center, int radius, boolean skipExistingChunks) { - if(!pack.getTemplate().disableStructures()) { - String name = Objects.requireNonNull(Registry.STRUCTURE_FEATURE.getKey(feature)).toString(); - TerraWorld terraWorld = TerraForgePlugin.getInstance().getWorld((World) world); - TerraStructure located = pack.getStructure(pack.getTemplate().getLocatable().get(name)); - if(located != null) { - CompletableFuture result = new CompletableFuture<>(); - AsyncStructureFinder finder = new AsyncStructureFinder(terraWorld.getBiomeProvider(), located, ForgeAdapter.adapt(center).toLocation((World) world), 0, 500, location -> { - result.complete(ForgeAdapter.adapt(location)); - }, TerraForgePlugin.getInstance()); - finder.run(); // Do this synchronously. - try { - return result.get(); - } catch(InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - } - } - return super.findNearestMapFeature(world, feature, center, radius, skipExistingChunks); - } - - @Override - public boolean hasStronghold(@NotNull ChunkPos p_235952_1_) { - if(pack.getTemplate().vanillaStructures()) return super.hasStronghold(p_235952_1_); - return false; - } - - @Override - public void createStructures(@NotNull DynamicRegistries dynamicRegistries, @NotNull StructureManager manager, @NotNull IChunk chunk, @NotNull TemplateManager templateManager, long p_242707_5_) { - if(pack.getTemplate().vanillaStructures()) super.createStructures(dynamicRegistries, manager, chunk, templateManager, p_242707_5_); - } - - @Override - public void applyCarvers(long p_230350_1_, @NotNull BiomeManager biomeManager, @NotNull IChunk chunk, GenerationStage.@NotNull Carving carving) { - if(pack.getTemplate().vanillaCaves()) super.applyCarvers(p_230350_1_, biomeManager, chunk, carving); - } - - @Override - public void fillFromNoise(@NotNull IWorld world, @NotNull StructureManager p_230352_2_, @NotNull IChunk chunk) { - delegate.generateChunkData((World) world, new FastRandom(), chunk.getPos().x, chunk.getPos().z, (ChunkData) chunk); - } - - @Override - public int getBaseHeight(int x, int z, Heightmap.@NotNull Type p_222529_3_) { - TerraWorld world = TerraForgePlugin.getInstance().getWorld(dimensionType); - Sampler sampler = world.getConfig().getSamplerCache().getChunk(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16)); - int cx = FastMath.floorMod(x, 16); - int cz = FastMath.floorMod(z, 16); - - int height = world.getWorld().getMaxHeight(); - - while(height >= 0 && sampler.sample(cx, height - 1, cz) < 0) height--; - - return height; - } - - @Override - public @NotNull IBlockReader getBaseColumn(int x, int z) { - TerraWorld world = TerraForgePlugin.getInstance().getWorld(dimensionType); - int height = getBaseHeight(x, z, Heightmap.Type.WORLD_SURFACE); - BlockState[] array = new BlockState[256]; - for(int y = 255; y >= 0; y--) { - if(y > height) { - if(y > ((UserDefinedBiome) world.getBiomeProvider().getBiome(x, z)).getConfig().getSeaLevel()) { - array[y] = Blocks.AIR.defaultBlockState(); - } else { - array[y] = Blocks.WATER.defaultBlockState(); - } - } else { - array[y] = Blocks.STONE.defaultBlockState(); - } - } - - return new Blockreader(array); - } - - @Override - public void spawnOriginalMobs(WorldGenRegion region) { - if(pack.getTemplate().vanillaMobs()) { - int cx = region.getCenterX(); - int cy = region.getCenterZ(); - Biome biome = region.getBiome((new ChunkPos(cx, cy)).getWorldPosition()); - SharedSeedRandom chunkRandom = new SharedSeedRandom(); - chunkRandom.setDecorationSeed(region.getSeed(), cx << 4, cy << 4); - WorldEntitySpawner.spawnMobsForChunkGeneration(region, biome, cx, cy, chunkRandom); - } - } - - @Override - public TerraChunkGenerator getHandle() { - return delegate; - } - - public void setDimensionType(DimensionType dimensionType) { - this.dimensionType = dimensionType; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/PopulatorFeature.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/PopulatorFeature.java deleted file mode 100644 index e586e82d4..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/PopulatorFeature.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.dfsek.terra.forge.generation; - -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.mojang.serialization.Codec; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.ISeedReader; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.feature.Feature; -import net.minecraft.world.gen.feature.NoFeatureConfig; -import org.jetbrains.annotations.NotNull; - -import java.util.Random; - -/** - * Feature wrapper for Terra populator - */ -public class PopulatorFeature extends Feature { - public PopulatorFeature(Codec codec) { - super(codec); - } - - @Override - public boolean place(@NotNull ISeedReader world, @NotNull ChunkGenerator generator, @NotNull Random random, @NotNull BlockPos pos, @NotNull NoFeatureConfig config) { - ForgeChunkGeneratorWrapper gen = (ForgeChunkGeneratorWrapper) generator; - gen.getHandle().getPopulators().forEach(populator -> populator.populate((World) world, (Chunk) world)); - return true; - } - -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java deleted file mode 100644 index 3220cfd58..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraBiomeSource.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.dfsek.terra.forge.generation; - -import com.dfsek.terra.api.world.biome.UserDefinedBiome; -import com.dfsek.terra.api.world.biome.provider.BiomeProvider; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.forge.ForgeUtil; -import com.dfsek.terra.forge.TerraForgePlugin; -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.RegistryLookupCodec; -import net.minecraft.world.biome.Biome; -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; -import java.util.stream.Collectors; - -public class TerraBiomeSource extends net.minecraft.world.biome.provider.BiomeProvider { - public static final Codec PACK_CODEC = (RecordCodecBuilder.create(config -> config.group( - Codec.STRING.fieldOf("pack").forGetter(pack -> pack.getTemplate().getID()) - ).apply(config, config.stable(TerraForgePlugin.getInstance().getConfigRegistry()::get)))); - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( - RegistryLookupCodec.create(Registry.BIOME_REGISTRY).forGetter(source -> source.biomeRegistry), - Codec.LONG.fieldOf("seed").stable().forGetter(source -> source.seed), - PACK_CODEC.fieldOf("pack").stable().forGetter(source -> source.pack)) - .apply(instance, instance.stable(TerraBiomeSource::new))); - - private final Registry biomeRegistry; - private final long seed; - private final BiomeProvider grid; - private final ConfigPack pack; - - public TerraBiomeSource(Registry biomes, long seed, ConfigPack pack) { - super(biomes.stream().collect(Collectors.toList())); - this.biomeRegistry = biomes; - this.seed = seed; - this.grid = pack.getBiomeProviderBuilder().build(seed); - this.pack = pack; - } - - @Override - protected @NotNull Codec codec() { - return CODEC; - } - - @Override - public net.minecraft.world.biome.provider.@NotNull BiomeProvider withSeed(long seed) { - return new TerraBiomeSource(this.biomeRegistry, seed, pack); - } - - @Override - public @NotNull Biome getNoiseBiome(int biomeX, int biomeY, int biomeZ) { - UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX << 2, biomeZ << 2); - return Objects.requireNonNull(biomeRegistry.get(new ResourceLocation("terra", ForgeUtil.createBiomeID(pack, biome.getID())))); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraGeneratorType.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraGeneratorType.java deleted file mode 100644 index 91b8fc852..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/generation/TerraGeneratorType.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.dfsek.terra.forge.generation; - -import com.dfsek.terra.config.pack.ConfigPack; -import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.DimensionSettings; -import org.jetbrains.annotations.NotNull; - -public class TerraGeneratorType extends BiomeGeneratorTypeScreens { - private final ConfigPack pack; - - public TerraGeneratorType(ConfigPack pack) { - super(new StringTextComponent("Terra:" + pack.getTemplate().getID())); - this.pack = pack; - } - - @Override - protected @NotNull ChunkGenerator generator(@NotNull Registry biomeRegistry, @NotNull Registry chunkGeneratorSettingsRegistry, long seed) { - return new ForgeChunkGeneratorWrapper(new TerraBiomeSource(biomeRegistry, seed, pack), seed, pack); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java deleted file mode 100644 index e2dc4185a..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeItemHandle.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.dfsek.terra.forge.handle; - -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.command.arguments.ItemArgument; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.registries.ForgeRegistries; - -import java.util.Set; -import java.util.stream.Collectors; - -public class ForgeItemHandle implements ItemHandle { - - @Override - public Item createItem(String data) { - try { - return (Item) new ItemArgument().parse(new StringReader(data)).getItem(); - } catch(CommandSyntaxException e) { - throw new IllegalArgumentException("Invalid item data \"" + data + "\"", e); - } - } - - @Override - public Enchantment getEnchantment(String id) { - return (Enchantment) ForgeRegistries.ENCHANTMENTS.getValue(ResourceLocation.tryParse(id)); - } - - @Override - public Set getEnchantments() { - return ForgeRegistries.ENCHANTMENTS.getEntries().stream().map(entry -> (Enchantment) entry.getValue()).collect(Collectors.toSet()); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java deleted file mode 100644 index 96c2e37fa..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/handle/ForgeWorldHandle.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.forge.handle; - -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.forge.ForgeAdapter; -import com.dfsek.terra.forge.block.ForgeBlockData; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.block.BlockState; -import net.minecraft.command.arguments.BlockStateParser; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.registries.ForgeRegistries; - -import java.util.Locale; - -public class ForgeWorldHandle implements WorldHandle { - - @Override - public ForgeBlockData createBlockData(String data) { - BlockStateParser parser = new BlockStateParser(new StringReader(data), true); - try { - BlockState state = parser.parse(true).getState(); - if(state == null) throw new IllegalArgumentException("Invalid data: " + data); - return ForgeAdapter.adapt(state); - } catch(CommandSyntaxException e) { - throw new IllegalArgumentException(e); - } - } - - @Override - public EntityType getEntity(String id) { - ResourceLocation identifier = ResourceLocation.tryParse(id); - if(identifier == null) identifier = ResourceLocation.tryParse("minecraft:" + id.toLowerCase(Locale.ROOT)); - return (EntityType) ForgeRegistries.ENTITIES.getValue(identifier); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/ForgeListener.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/ForgeListener.java deleted file mode 100644 index 35f0d9d63..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/ForgeListener.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.dfsek.terra.forge.listener; - -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.exception.CommandException; -import com.dfsek.terra.api.platform.CommandSender; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.forge.TerraForgePlugin; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.command.CommandSource; -import net.minecraft.util.text.StringTextComponent; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; -import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument; - -@Mod.EventBusSubscriber(modid = "terra", bus = Mod.EventBusSubscriber.Bus.FORGE) -public class ForgeListener { - private static final TerraForgePlugin INSTANCE = TerraForgePlugin.getInstance(); - - @SuppressWarnings({"unchecked", "rawtypes"}) - @SubscribeEvent - public static void registerCommands(RegisterCommandsEvent event) { - int max = INSTANCE.getManager().getMaxArgumentDepth(); - RequiredArgumentBuilder arg = argument("arg" + (max - 1), StringArgumentType.word()); - for(int i = 0; i < max; i++) { - RequiredArgumentBuilder next = argument("arg" + (max - i - 1), StringArgumentType.word()); - - arg = next.then(assemble(arg, INSTANCE.getManager())); - } - - event.getDispatcher().register(literal("terra").executes(context -> 1).then((ArgumentBuilder) assemble(arg, INSTANCE.getManager()))); - event.getDispatcher().register(literal("te").executes(context -> 1).then((ArgumentBuilder) assemble(arg, INSTANCE.getManager()))); - } - - public static RequiredArgumentBuilder assemble(RequiredArgumentBuilder in, CommandManager manager) { - return in.suggests((context, builder) -> { - List args = parseCommand(context.getInput()); - CommandSender sender = (CommandSender) context.getSource(); - try { - sender = (Entity) context.getSource().getEntityOrException(); - } catch(CommandSyntaxException ignore) { - } - try { - manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest); - } catch(CommandException e) { - sender.sendMessage(e.getMessage()); - } - return builder.buildFuture(); - }).executes(context -> { - List args = parseCommand(context.getInput()); - try { - CommandSender sender = (CommandSender) context.getSource(); - try { - sender = (Entity) context.getSource().getEntityOrException(); - } catch(CommandSyntaxException ignore) { - } - manager.execute(args.remove(0), sender, args); - } catch(CommandException e) { - context.getSource().sendFailure(new StringTextComponent(e.getMessage())); - } - return 1; - }); - } - - private static List parseCommand(String command) { - if(command.startsWith("/terra ")) command = command.substring("/terra ".length()); - else if(command.startsWith("/te ")) command = command.substring("/te ".length()); - List c = new ArrayList<>(Arrays.asList(command.split(" "))); - if(command.endsWith(" ")) c.add(""); - return c; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/RegistryListener.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/RegistryListener.java deleted file mode 100644 index 19847bf0a..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/listener/RegistryListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.forge.listener; - -import com.dfsek.terra.forge.TerraForgePlugin; -import net.minecraft.world.gen.feature.Feature; -import net.minecraftforge.event.RegistryEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) -public class RegistryListener { - @SubscribeEvent - public static void registerPop(RegistryEvent.Register> event) { - event.getRegistry().register(TerraForgePlugin.POPULATOR_FEATURE); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/DimensionGeneratorSettingsMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/DimensionGeneratorSettingsMixin.java deleted file mode 100644 index ca899217a..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/DimensionGeneratorSettingsMixin.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.dfsek.terra.forge.mixin; - -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.forge.TerraForgePlugin; -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import com.dfsek.terra.forge.generation.TerraBiomeSource; -import com.google.common.base.MoreObjects; -import net.minecraft.util.registry.DynamicRegistries; -import net.minecraft.util.registry.Registry; -import net.minecraft.util.registry.SimpleRegistry; -import net.minecraft.world.Dimension; -import net.minecraft.world.DimensionType; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.DimensionSettings; -import net.minecraft.world.gen.settings.DimensionGeneratorSettings; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Properties; -import java.util.Random; - -@Mixin(DimensionGeneratorSettings.class) -public abstract class DimensionGeneratorSettingsMixin { - @Inject(method = "create(Lnet/minecraft/util/registry/DynamicRegistries;Ljava/util/Properties;)Lnet/minecraft/world/gen/settings/DimensionGeneratorSettings;", at = @At("HEAD"), cancellable = true) - private static void fromProperties(DynamicRegistries dynamicRegistries, Properties properties, CallbackInfoReturnable cir) { - if(properties.get("level-type") == null) { - return; - } - - String prop = properties.get("level-type").toString().trim(); - if(prop.startsWith("Terra")) { - String seed = (String) MoreObjects.firstNonNull(properties.get("level-seed"), ""); - long l = new Random().nextLong(); - if(!seed.isEmpty()) { - try { - long m = Long.parseLong(seed); - if(m != 0L) { - l = m; - } - } catch(NumberFormatException exception) { - l = seed.hashCode(); - } - } - - String generate_structures = (String) properties.get("generate-structures"); - boolean generateStructures = generate_structures == null || Boolean.parseBoolean(generate_structures); - Registry dimensionTypes = dynamicRegistries.registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY); - Registry biomes = dynamicRegistries.registryOrThrow(Registry.BIOME_REGISTRY); - Registry chunkGeneratorSettings = dynamicRegistries.registryOrThrow(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY); - SimpleRegistry dimensionOptions = DimensionType.defaultDimensions(dimensionTypes, biomes, chunkGeneratorSettings, l); - - prop = prop.substring(prop.indexOf(":") + 1); - - ConfigPack pack = TerraForgePlugin.getInstance().getConfigRegistry().get(prop); - - if(pack == null) throw new IllegalArgumentException("No such pack " + prop); - - TerraForgePlugin.getInstance().logger().info("Using config pack " + pack.getTemplate().getID()); - cir.setReturnValue(new DimensionGeneratorSettings(l, generateStructures, false, DimensionGeneratorSettings.withOverworld(dimensionTypes, dimensionOptions, new ForgeChunkGeneratorWrapper(new TerraBiomeSource(biomes, l, pack), l, pack)))); - } - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/ServerWorldMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/ServerWorldMixin.java deleted file mode 100644 index 39cdce89d..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/ServerWorldMixin.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.dfsek.terra.forge.mixin; - -import com.dfsek.terra.api.util.generic.pair.Pair; -import com.dfsek.terra.forge.TerraForgePlugin; -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import com.dfsek.terra.world.TerraWorld; -import net.minecraft.world.DimensionType; -import net.minecraft.world.World; -import net.minecraft.world.server.ServerChunkProvider; -import net.minecraft.world.server.ServerWorld; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(ServerWorld.class) -public abstract class ServerWorldMixin { - @Shadow - @Final - private ServerChunkProvider chunkSource; - - @Shadow - protected abstract void initCapabilities(); - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;initCapabilities()V")) - public void injectConstructor(ServerWorld serverWorld) { - if(chunkSource.getGenerator() instanceof ForgeChunkGeneratorWrapper) { - ForgeChunkGeneratorWrapper chunkGeneratorWrapper = (ForgeChunkGeneratorWrapper) chunkSource.getGenerator(); - DimensionType dimensionType = ((World) (Object) this).dimensionType(); - TerraForgePlugin.getInstance().getWorldMap().put(dimensionType, Pair.of((ServerWorld) (Object) this, new TerraWorld((com.dfsek.terra.api.platform.world.World) this, chunkGeneratorWrapper.getPack(), TerraForgePlugin.getInstance()))); - chunkGeneratorWrapper.setDimensionType(dimensionType); - TerraForgePlugin.getInstance().logger().info("Registered world " + this + " to dimension type " + dimensionType); - } - initCapabilities(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/AbstractSpawnerAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/AbstractSpawnerAccessor.java deleted file mode 100644 index 5783c350f..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/AbstractSpawnerAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dfsek.terra.forge.mixin.access; - -import net.minecraft.util.ResourceLocation; -import net.minecraft.world.spawner.AbstractSpawner; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(AbstractSpawner.class) -public interface AbstractSpawnerAccessor { - @Invoker("getEntityId") - ResourceLocation callGetEntityId(); -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/BiomeGeneratorTypeScreensAccessor.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/BiomeGeneratorTypeScreensAccessor.java deleted file mode 100644 index b7d7363b5..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/access/BiomeGeneratorTypeScreensAccessor.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.forge.mixin.access; - -import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens; -import net.minecraft.util.text.ITextComponent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.List; - -@Mixin(BiomeGeneratorTypeScreens.class) -public interface BiomeGeneratorTypeScreensAccessor { - @Accessor("PRESETS") - static List getPresets() { - throw new UnsupportedOperationException(); - } - - @Mutable - @Accessor - void setDescription(ITextComponent description); -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/BiomeMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/BiomeMixin.java deleted file mode 100644 index 317893290..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/BiomeMixin.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations; - -import net.minecraft.world.biome.Biome; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(Biome.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.world.Biome.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class BiomeMixin { - public Object terra$getHandle() { - return this; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ChunkGeneratorMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ChunkGeneratorMixin.java deleted file mode 100644 index 14fa0e2c5..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ChunkGeneratorMixin.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations; - -import net.minecraft.world.gen.ChunkGenerator; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(ChunkGenerator.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.world.generator.ChunkGenerator.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ChunkGeneratorMixin { - public Object terra$getHandle() { - return this; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ConfiguredFeatureMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ConfiguredFeatureMixin.java deleted file mode 100644 index f0e1d0b4a..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/ConfiguredFeatureMixin.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.util.collections.MaterialSet; -import com.dfsek.terra.forge.TerraForgePlugin; -import com.dfsek.terra.profiler.ProfileFrame; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.ISeedReader; -import net.minecraft.world.gen.ChunkGenerator; -import net.minecraft.world.gen.feature.ConfiguredFeature; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Random; - -@Mixin(ConfiguredFeature.class) -@Implements(@Interface(iface = Tree.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ConfiguredFeatureMixin { - - @Shadow - public abstract boolean place(ISeedReader p_242765_1_, ChunkGenerator p_242765_2_, Random p_242765_3_, BlockPos p_242765_4_); - - @SuppressWarnings({"try"}) - public boolean terra$plant(Location l, Random r) { - try(ProfileFrame ignore = TerraForgePlugin.getInstance().getProfiler().profile("forge_tree")) { - ISeedReader world = ((ISeedReader) l.getWorld()); - ChunkGenerator generatorWrapper = (ChunkGenerator) l.getWorld().getGenerator(); - return place(world, generatorWrapper, r, new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ())); - } - } - - public MaterialSet terra$getSpawnable() { - return MaterialSet.get(TerraForgePlugin.getInstance().getWorldHandle().createBlockData("minecraft:grass_block"), - TerraForgePlugin.getInstance().getWorldHandle().createBlockData("minecraft:podzol"), - TerraForgePlugin.getInstance().getWorldHandle().createBlockData("minecraft:mycelium")); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/BlockMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/BlockMixin.java deleted file mode 100644 index ee4bf13ed..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/BlockMixin.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.block; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.forge.ForgeAdapter; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(Block.class) -@Implements(@Interface(iface = BlockType.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class BlockMixin { - @Shadow - private BlockState defaultBlockState; - - public Object terra$getHandle() { - return this; - } - - public BlockData terra$getDefaultData() { - return ForgeAdapter.adapt(defaultBlockState); - } - - public boolean terra$isSolid() { - return defaultBlockState.canOcclude(); - } - - @SuppressWarnings("ConstantConditions") - public boolean terra$isWater() { - return ((Object) this) == Blocks.WATER; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/TileEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/TileEntityMixin.java deleted file mode 100644 index 2f7bd3918..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/TileEntityMixin.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.block; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.state.BlockState; -import com.dfsek.terra.forge.ForgeAdapter; -import com.dfsek.terra.forge.block.ForgeBlock; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import javax.annotation.Nullable; - -@Mixin(TileEntity.class) -@Implements(@Interface(iface = BlockState.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class TileEntityMixin { - @Shadow - protected BlockPos worldPosition; - - @Shadow - @Nullable - protected World level; - - @Shadow - @Nullable - private net.minecraft.block.BlockState blockState; - - @Shadow - public abstract boolean hasLevel(); - - public Object terra$getHandle() { - return this; - } - - public Block terra$getBlock() { - return new ForgeBlock(worldPosition, level); - } - - public int terra$getX() { - return worldPosition.getX(); - } - - public int terra$getY() { - return worldPosition.getY(); - } - - public int terra$getZ() { - return worldPosition.getZ(); - } - - public BlockData terra$getBlockData() { - return ForgeAdapter.adapt(blockState); - } - - public boolean terra$update(boolean applyPhysics) { - if(hasLevel()) level.getChunk(worldPosition).setBlockEntity(worldPosition, (TileEntity) (Object) this); - return true; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/LockableLootTileEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/LockableLootTileEntityMixin.java deleted file mode 100644 index 977309616..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/LockableLootTileEntityMixin.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.block.state; - -import com.dfsek.terra.api.platform.block.state.Container; -import com.dfsek.terra.api.platform.inventory.Inventory; -import com.dfsek.terra.forge.mixin.implementations.block.TileEntityMixin; -import net.minecraft.tileentity.LockableLootTileEntity; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(LockableLootTileEntity.class) -@Implements(@Interface(iface = Container.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class LockableLootTileEntityMixin extends TileEntityMixin { - public Inventory terra$getInventory() { - return (Inventory) this; - } - - public Object terra$getHandle() { - return this; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/MobSpawnerTileEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/MobSpawnerTileEntityMixin.java deleted file mode 100644 index 1f73b7583..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/MobSpawnerTileEntityMixin.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.block.state; - -import com.dfsek.terra.api.platform.block.state.MobSpawner; -import com.dfsek.terra.api.platform.block.state.SerialState; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.forge.TerraForgePlugin; -import com.dfsek.terra.forge.mixin.access.AbstractSpawnerAccessor; -import com.dfsek.terra.forge.mixin.implementations.block.TileEntityMixin; -import net.minecraft.tileentity.MobSpawnerTileEntity; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.spawner.AbstractSpawner; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(MobSpawnerTileEntity.class) -@Implements(@Interface(iface = MobSpawner.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class MobSpawnerTileEntityMixin extends TileEntityMixin { - @Shadow - public abstract AbstractSpawner getSpawner(); - - public EntityType terra$getSpawnedType() { - return (EntityType) Registry.ENTITY_TYPE.get(((AbstractSpawnerAccessor) getSpawner()).callGetEntityId()); - } - - public void terra$setSpawnedType(@NotNull EntityType creatureType) { - getSpawner().setEntityId((net.minecraft.entity.EntityType) creatureType); - } - - public int terra$getDelay() { - return 0; - } - - public void terra$setDelay(int delay) { - - } - - public int terra$getMinSpawnDelay() { - return 0; - } - - public void terra$setMinSpawnDelay(int delay) { - - } - - public int terra$getMaxSpawnDelay() { - return 0; - } - - public void terra$setMaxSpawnDelay(int delay) { - - } - - public int terra$getSpawnCount() { - return 0; - } - - public void terra$setSpawnCount(int spawnCount) { - - } - - public int terra$getMaxNearbyEntities() { - return 0; - } - - public void terra$setMaxNearbyEntities(int maxNearbyEntities) { - - } - - public int terra$getRequiredPlayerRange() { - return 0; - } - - public void terra$setRequiredPlayerRange(int requiredPlayerRange) { - - } - - public int terra$getSpawnRange() { - return 0; - } - - public void terra$setSpawnRange(int spawnRange) { - - } - - public void terra$applyState(String state) { - SerialState.parse(state).forEach((k, v) -> { - switch(k) { - case "type": - terra$setSpawnedType(TerraForgePlugin.getInstance().getWorldHandle().getEntity(v)); - return; - case "delay": - terra$setDelay(Integer.parseInt(v)); - return; - case "min_delay": - terra$setMinSpawnDelay(Integer.parseInt(v)); - return; - case "max_delay": - terra$setMaxSpawnDelay(Integer.parseInt(v)); - return; - case "spawn_count": - terra$setSpawnCount(Integer.parseInt(v)); - return; - case "spawn_range": - terra$setSpawnRange(Integer.parseInt(v)); - return; - case "max_nearby": - terra$setMaxNearbyEntities(Integer.parseInt(v)); - return; - case "required_player_range": - terra$setRequiredPlayerRange(Integer.parseInt(v)); - return; - default: - throw new IllegalArgumentException("Invalid property: " + k); - } - }); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/SignTileEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/SignTileEntityMixin.java deleted file mode 100644 index 40ec0368c..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/block/state/SignTileEntityMixin.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.block.state; - -import com.dfsek.terra.api.platform.block.state.SerialState; -import com.dfsek.terra.api.platform.block.state.Sign; -import net.minecraft.tileentity.SignTileEntity; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(SignTileEntity.class) -@Implements(@Interface(iface = Sign.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class SignTileEntityMixin { - @Shadow - @Final - private ITextComponent[] messages; - - @Shadow - public abstract void setMessage(int p_212365_1_, ITextComponent p_212365_2_); - - public @NotNull String[] terra$getLines() { - String[] lines = new String[messages.length]; - for(int i = 0; i < messages.length; i++) { - lines[i] = messages[i].getString(); - } - return lines; - } - - public @NotNull String terra$getLine(int index) throws IndexOutOfBoundsException { - - return messages[index].getString(); - } - - public void terra$setLine(int index, @NotNull String line) throws IndexOutOfBoundsException { - setMessage(index, new StringTextComponent(line)); - } - - public void terra$applyState(String state) { - SerialState.parse(state).forEach((k, v) -> { - if(!k.startsWith("text")) throw new IllegalArgumentException("Invalid property: " + k); - terra$setLine(Integer.parseInt(k.substring(4)), v); - }); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/ChunkMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/ChunkMixin.java deleted file mode 100644 index 6d93b8cef..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/ChunkMixin.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.chunk; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.forge.block.ForgeBlock; -import com.dfsek.terra.forge.block.ForgeBlockData; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.chunk.IChunk; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(net.minecraft.world.chunk.Chunk.class) -@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ChunkMixin { - - @Shadow - @Final - private net.minecraft.world.World level; - - public int terra$getX() { - return ((IChunk) this).getPos().x; - } - - public int terra$getZ() { - return ((IChunk) this).getPos().z; - } - - public World terra$getWorld() { - return (World) level; - } - - public Block terra$getBlock(int x, int y, int z) { - BlockPos pos = new BlockPos(x + (terra$getX() << 4), y, z + (terra$getZ() << 4)); - return new ForgeBlock(pos, level); - } - - public @NotNull BlockData terra$getBlockData(int x, int y, int z) { - return terra$getBlock(x, y, z).getBlockData(); - } - - public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { - ((IChunk) this).setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false); - } - - public Object terra$getHandle() { - return this; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/WorldGenRegionMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/WorldGenRegionMixin.java deleted file mode 100644 index 7844a9637..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/WorldGenRegionMixin.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.chunk; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.forge.block.ForgeBlock; -import com.dfsek.terra.forge.block.ForgeBlockData; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.gen.WorldGenRegion; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(WorldGenRegion.class) -@Implements(@Interface(iface = Chunk.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class WorldGenRegionMixin { - @Final - @Shadow - private int x; - - @Final - @Shadow - private int z; - - public int terra$getX() { - return x; - } - - public int terra$getZ() { - return z; - } - - public World terra$getWorld() { - return (World) this; - } - - public Block terra$getBlock(int x, int y, int z) { - BlockPos pos = new BlockPos(x + (this.x << 4), y, z + (this.z << 4)); - return new ForgeBlock(pos, (WorldGenRegion) (Object) this); - } - - public @NotNull BlockData terra$getBlockData(int x, int y, int z) { - return terra$getBlock(x, y, z).getBlockData(); - } - - public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { - ((WorldGenRegion) (Object) this).setBlock(new BlockPos(x + (this.x << 4), y, z + (this.z << 4)), ((ForgeBlockData) blockData).getHandle(), 0); - } - - public Object terra$getHandle() { - return this; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/data/ChunkPrimerMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/data/ChunkPrimerMixin.java deleted file mode 100644 index 5e5404406..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/chunk/data/ChunkPrimerMixin.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.chunk.data; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.generator.ChunkData; -import com.dfsek.terra.forge.block.ForgeBlockData; -import net.minecraft.block.BlockState; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.chunk.ChunkPrimer; -import net.minecraft.world.chunk.IChunk; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(ChunkPrimer.class) -@Implements(@Interface(iface = ChunkData.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ChunkPrimerMixin { - @Shadow - public abstract BlockState getBlockState(BlockPos pos); - - public @NotNull BlockData terra$getBlockData(int x, int y, int z) { - return new ForgeBlockData(getBlockState(new BlockPos(x, y, z))); - } - - public void terra$setBlock(int x, int y, int z, @NotNull BlockData blockData) { - ((IChunk) this).setBlockState(new BlockPos(x, y, z), ((ForgeBlockData) blockData).getHandle(), false); - } - - public Object terra$getHandle() { - return this; - } - - public int terra$getMaxHeight() { - return 255; // TODO: 1.17 - Implement dynamic height. - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/CommandSourceMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/CommandSourceMixin.java deleted file mode 100644 index 83df7b48c..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/CommandSourceMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.entity; - -import com.dfsek.terra.api.platform.CommandSender; -import net.minecraft.command.CommandSource; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(CommandSource.class) -@Implements(@Interface(iface = CommandSender.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class CommandSourceMixin { - @Shadow - public abstract void sendSuccess(ITextComponent p_197030_1_, boolean p_197030_2_); - - public void terra$sendMessage(String message) { - sendSuccess(new StringTextComponent(message), true); - } - - public Object terra$getHandle() { - return this; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityMixin.java deleted file mode 100644 index 7cc684c35..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityMixin.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.entity; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.forge.ForgeAdapter; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.UUID; - -@Mixin(Entity.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.Entity.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class EntityMixin { - @Shadow - public net.minecraft.world.World level; - - @Shadow - private BlockPos blockPosition; - - @Shadow - public abstract void teleportTo(double destX, double destY, double destZ); - - - @Shadow - public abstract void sendMessage(ITextComponent p_145747_1_, UUID p_145747_2_); - - public Object terra$getHandle() { - return this; - } - - public Location terra$getLocation() { - return new Location((World) level, ForgeAdapter.adapt(blockPosition)); - } - - public void terra$setLocation(Location location) { - teleportTo(location.getX(), location.getY(), location.getZ()); - } - - public World terra$getWorld() { - return (World) level; - } - - public void terra$sendMessage(String message) { - sendMessage(new StringTextComponent(message), UUID.randomUUID()); // TODO: look into how this actually works and make it less jank - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityTypeMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityTypeMixin.java deleted file mode 100644 index e7bb15a70..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/EntityTypeMixin.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.entity; - -import net.minecraft.entity.EntityType; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(EntityType.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.entity.EntityType.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class EntityTypeMixin { - public Object terra$getHandle() { - return this; - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/PlayerEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/PlayerEntityMixin.java deleted file mode 100644 index 7ee5d6731..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/entity/PlayerEntityMixin.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.entity; - -import com.dfsek.terra.api.platform.entity.Player; -import net.minecraft.entity.player.PlayerEntity; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(PlayerEntity.class) -@Implements(@Interface(iface = Player.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class PlayerEntityMixin extends EntityMixin { - -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/LockableTileEntityMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/LockableTileEntityMixin.java deleted file mode 100644 index 06a279ed3..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/LockableTileEntityMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.inventory; - -import com.dfsek.terra.api.platform.inventory.Inventory; -import com.dfsek.terra.api.platform.inventory.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.tileentity.LockableTileEntity; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(LockableTileEntity.class) -@Implements(@Interface(iface = Inventory.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public class LockableTileEntityMixin { - public Object terra$getHandle() { - return this; - } - - public int terra$getSize() { - return ((LockableTileEntity) (Object) this).getContainerSize(); - } - - @SuppressWarnings("ConstantConditions") - public ItemStack terra$getItem(int slot) { - net.minecraft.item.ItemStack itemStack = ((LockableTileEntity) (Object) this).getItem(slot); - return itemStack.getItem() == Items.AIR ? null : (ItemStack) (Object) itemStack; - } - - @SuppressWarnings("ConstantConditions") - public void terra$setItem(int slot, ItemStack newStack) { - ((LockableTileEntity) (Object) this).setItem(slot, (net.minecraft.item.ItemStack) (Object) newStack); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemMixin.java deleted file mode 100644 index a7efd1706..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemMixin.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.inventory.item; - -import com.dfsek.terra.api.platform.inventory.ItemStack; -import net.minecraft.item.Item; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(Item.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.Item.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ItemMixin { - @Shadow - public abstract int getMaxDamage(); - - public Object terra$getHandle() { - return this; - } - - @SuppressWarnings("ConstantConditions") - public ItemStack terra$newItemStack(int amount) { - return (ItemStack) (Object) new net.minecraft.item.ItemStack((Item) (Object) this, amount); - } - - public double terra$getMaxDurability() { - return getMaxDamage(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemStackMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemStackMixin.java deleted file mode 100644 index 714dcab02..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/item/ItemStackMixin.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.inventory.item; - -import com.dfsek.terra.api.platform.inventory.Item; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(ItemStack.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.ItemStack.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ItemStackMixin { - @Shadow - public abstract int getCount(); - - @Shadow - public abstract void setCount(int count); - - @Shadow - public abstract net.minecraft.item.Item getItem(); - - - @Shadow - public abstract boolean isDamageableItem(); - - @Shadow - public abstract void setTag(@Nullable CompoundNBT p_77982_1_); - - public int terra$getAmount() { - return getCount(); - } - - public void terra$setAmount(int i) { - setCount(i); - } - - public Item terra$getType() { - return (Item) getItem(); - } - - public ItemMeta terra$getItemMeta() { - return (ItemMeta) this; - } - - @SuppressWarnings("ConstantConditions") - public void terra$setItemMeta(ItemMeta meta) { - setTag(((ItemStack) (Object) meta).getTag()); - } - - public Object terra$getHandle() { - return this; - } - - @Intrinsic - public boolean terra$isDamageable() { - return isDamageableItem(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/EnchantmentMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/EnchantmentMixin.java deleted file mode 100644 index 69bbfecaa..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/EnchantmentMixin.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.inventory.meta; - -import com.dfsek.terra.api.platform.inventory.ItemStack; -import net.minecraft.enchantment.Enchantment; -import net.minecraft.util.registry.Registry; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Objects; - -@Mixin(Enchantment.class) -@Implements(@Interface(iface = com.dfsek.terra.api.platform.inventory.item.Enchantment.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class EnchantmentMixin { - - @Shadow - public abstract boolean isCompatibleWith(Enchantment p_191560_1_); - - @Shadow - public abstract boolean canEnchant(net.minecraft.item.ItemStack p_92089_1_); - - public Object terra$getHandle() { - return this; - } - - @SuppressWarnings("ConstantConditions") - public boolean terra$canEnchantItem(ItemStack itemStack) { - return canEnchant((net.minecraft.item.ItemStack) (Object) itemStack); - } - - public String terra$getID() { - return Objects.requireNonNull(Registry.ENCHANTMENT.getId((Enchantment) (Object) this)).toString(); - } - - public boolean terra$conflictsWith(com.dfsek.terra.api.platform.inventory.item.Enchantment other) { - return !isCompatibleWith((Enchantment) other); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java deleted file mode 100644 index 8a1b438f5..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackDamageableMixin.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.inventory.meta; - -import com.dfsek.terra.api.platform.inventory.item.Damageable; -import net.minecraft.item.ItemStack; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(ItemStack.class) -@Implements(@Interface(iface = Damageable.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ItemStackDamageableMixin { - @Shadow - public abstract boolean isDamaged(); - - @Shadow - public abstract int getDamageValue(); - - @Shadow - public abstract void setDamageValue(int p_196085_1_); - - public boolean terra$hasDamage() { - return isDamaged(); - } - - @Intrinsic - public void terra$setDamage(int damage) { - setDamageValue(damage); - } - - @Intrinsic - public int terra$getDamage() { - return getDamageValue(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackMetaMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackMetaMixin.java deleted file mode 100644 index aa9b2a41b..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/inventory/meta/ItemStackMetaMixin.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.inventory.meta; - -import com.dfsek.terra.api.platform.inventory.item.Enchantment; -import com.dfsek.terra.api.platform.inventory.item.ItemMeta; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.nbt.ListNBT; -import net.minecraft.util.registry.Registry; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -@Mixin(ItemStack.class) -@Implements(@Interface(iface = ItemMeta.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ItemStackMetaMixin { - @Shadow - public abstract ListNBT getEnchantmentTags(); - - @Shadow - public abstract boolean isEnchanted(); - - @Shadow - public abstract void enchant(net.minecraft.enchantment.Enchantment p_77966_1_, int p_77966_2_); - - public Object terra$getHandle() { - return this; - } - - @Intrinsic(displace = true) - public Map terra$getEnchantments() { - if(!isEnchanted()) return Collections.emptyMap(); - Map map = new HashMap<>(); - - getEnchantmentTags().forEach(enchantment -> { - CompoundNBT eTag = (CompoundNBT) enchantment; - map.put((Enchantment) Registry.ENCHANTMENT.byId(eTag.getInt("id")), eTag.getInt("lvl")); - }); - return map; - } - - public void terra$addEnchantment(Enchantment enchantment, int level) { - enchant((net.minecraft.enchantment.Enchantment) enchantment, level); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/package-info.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/package-info.java deleted file mode 100644 index 0fae9920e..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Mixins in this package implement Terra - * interfaces in Minecraft classes. - */ -package com.dfsek.terra.forge.mixin.implementations; \ No newline at end of file diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/ServerWorldMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/ServerWorldMixin.java deleted file mode 100644 index 024b4970d..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/ServerWorldMixin.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.world; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.forge.block.ForgeBlock; -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IServerWorld; -import net.minecraft.world.server.ServerWorld; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(ServerWorld.class) -@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class ServerWorldMixin { - @Shadow - public abstract long getSeed(); - - public int terra$getMaxHeight() { - return ((ServerWorld) (Object) this).getMaxBuildHeight(); - } - - public ChunkGenerator terra$getGenerator() { - return (ChunkGenerator) ((ServerWorld) (Object) this).getChunkSource().getGenerator(); - } - - public Chunk terra$getChunkAt(int x, int z) { - return (Chunk) ((ServerWorld) (Object) this).getChunk(x, z); - } - - public Block terra$getBlockAt(int x, int y, int z) { - return new ForgeBlock(new BlockPos(x, y, z), ((ServerWorld) (Object) this)); - } - - public Entity terra$spawnEntity(Location location, EntityType entityType) { - net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(((ServerWorld) (Object) this)); - entity.setPos(location.getX(), location.getY(), location.getZ()); - ((ServerWorld) (Object) this).addFreshEntity(entity); - return (Entity) entity; - } - - @Intrinsic - public long terra$getSeed() { - return getSeed(); - } - - public int terra$getMinHeight() { - return 0; - } - - public Object terra$getHandle() { - return this; - } - - public boolean terra$isTerraWorld() { - return terra$getGenerator() instanceof GeneratorWrapper; - } - - public TerraChunkGenerator terra$getTerraGenerator() { - return ((ForgeChunkGeneratorWrapper) terra$getGenerator()).getHandle(); - } - - /** - * Overridden in the same manner as {@link WorldGenRegionMixin#hashCode()} - * - * @param other Another object - * @return Whether this world is the same as other. - * @see WorldGenRegionMixin#hashCode() - */ - @SuppressWarnings("ConstantConditions") - @Override - public boolean equals(Object other) { - if(!(other instanceof IServerWorld)) return false; - return (IServerWorld) this == (((IServerWorld) other).getLevel()); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/WorldGenRegionMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/WorldGenRegionMixin.java deleted file mode 100644 index 0b162b591..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/implementations/world/WorldGenRegionMixin.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.dfsek.terra.forge.mixin.implementations.world; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.api.platform.world.generator.GeneratorWrapper; -import com.dfsek.terra.api.world.generation.TerraChunkGenerator; -import com.dfsek.terra.forge.block.ForgeBlock; -import com.dfsek.terra.forge.generation.ForgeChunkGeneratorWrapper; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.gen.WorldGenRegion; -import net.minecraft.world.server.ServerWorld; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Implements; -import org.spongepowered.asm.mixin.Interface; -import org.spongepowered.asm.mixin.Intrinsic; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(WorldGenRegion.class) -@Implements(@Interface(iface = World.class, prefix = "terra$", remap = Interface.Remap.NONE)) -public abstract class WorldGenRegionMixin { - @Shadow - @Final - private ServerWorld level; - - @Shadow - @Final - private long seed; - - public int terra$getMaxHeight() { - return ((WorldGenRegion) (Object) this).getMaxBuildHeight(); - } - - @SuppressWarnings("deprecation") - public ChunkGenerator terra$getGenerator() { - return (ChunkGenerator) ((WorldGenRegion) (Object) this).getLevel().getChunkSource().getGenerator(); - } - - public Chunk terra$getChunkAt(int x, int z) { - return (Chunk) ((WorldGenRegion) (Object) this).getChunk(x, z); - } - - public Block terra$getBlockAt(int x, int y, int z) { - return new ForgeBlock(new BlockPos(x, y, z), ((WorldGenRegion) (Object) this)); - } - - @SuppressWarnings("deprecation") - public Entity terra$spawnEntity(Location location, EntityType entityType) { - net.minecraft.entity.Entity entity = ((net.minecraft.entity.EntityType) entityType).create(((WorldGenRegion) (Object) this).getLevel()); - entity.setPos(location.getX(), location.getY(), location.getZ()); - ((WorldGenRegion) (Object) this).addFreshEntity(entity); - return (Entity) entity; - } - - @Intrinsic - public long terra$getSeed() { - return seed; - } - - public int terra$getMinHeight() { - return 0; - } - - public Object terra$getHandle() { - return this; - } - - public boolean terra$isTerraWorld() { - return terra$getGenerator() instanceof GeneratorWrapper; - } - - public TerraChunkGenerator terra$getTerraGenerator() { - return ((ForgeChunkGeneratorWrapper) terra$getGenerator()).getHandle(); - } - - /** - * We need regions delegating to the same world - * to have the same hashcode. This - * minimizes cache misses. - *

- * This is sort of jank, but shouldn't(tm) - * break any other mods, unless they're doing - * something they really shouldn't, since - * ChunkRegions are not supposed to persist. - */ - @Override - public int hashCode() { - return level.hashCode(); - } - - /** - * Overridden in the same manner as {@link #hashCode()} - * - * @param other Another object - * @return Whether this world is the same as other. - * @see #hashCode() - */ - @Override - public boolean equals(Object other) { - if(!(other instanceof WorldGenRegion)) return false; - return level.equals(((WorldGenRegion) other).getLevel()); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftClientMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftClientMixin.java deleted file mode 100644 index 84245b37e..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftClientMixin.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.dfsek.terra.forge.mixin.init; - -import com.dfsek.terra.forge.TerraForgePlugin; -import com.dfsek.terra.forge.generation.TerraGeneratorType; -import com.dfsek.terra.forge.mixin.access.BiomeGeneratorTypeScreensAccessor; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens; -import net.minecraft.resources.ResourcePackList; -import net.minecraft.util.text.StringTextComponent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(Minecraft.class) -public abstract class MinecraftClientMixin { - @Redirect(method = "", at = @At(value = "INVOKE", - target = "Lnet/minecraft/resources/ResourcePackList;reload()V" // sorta arbitrary position, after mod init, before window opens - )) - public void injectConstructor(ResourcePackList resourcePackList) { - TerraForgePlugin.getInstance().init(); // Load during MinecraftClient construction, after other mods have registered blocks and stuff - TerraForgePlugin.getInstance().getConfigRegistry().forEach(pack -> { - final BiomeGeneratorTypeScreens generatorType = new TerraGeneratorType(pack); - //noinspection ConstantConditions - ((BiomeGeneratorTypeScreensAccessor) generatorType).setDescription(new StringTextComponent("Terra:" + pack.getTemplate().getID())); - BiomeGeneratorTypeScreensAccessor.getPresets().add(1, generatorType); - }); - resourcePackList.reload(); - } -} diff --git a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftServerMixin.java b/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftServerMixin.java deleted file mode 100644 index d8fed32cf..000000000 --- a/platforms/forge/src/main/java/com/dfsek/terra/forge/mixin/init/MinecraftServerMixin.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.forge.mixin.init; - -import com.dfsek.terra.forge.TerraForgePlugin; -import net.minecraft.server.Main; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(Main.class) -public class MinecraftServerMixin { - @Inject(method = "main([Ljava/lang/String;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/registry/DynamicRegistries;builtin()Lnet/minecraft/util/registry/DynamicRegistries$Impl;")) - private static void injectConstructor(String[] args, CallbackInfo ci) { - TerraForgePlugin.getInstance().init(); // Load during MinecraftServer construction, after other mods have registered blocks and stuff - } -} diff --git a/platforms/forge/src/main/resources/META-INF/mods.toml b/platforms/forge/src/main/resources/META-INF/mods.toml deleted file mode 100644 index a306898d9..000000000 --- a/platforms/forge/src/main/resources/META-INF/mods.toml +++ /dev/null @@ -1,17 +0,0 @@ -modLoader = "javafml" -loaderVersion = "[36,)" -license = "@LICENSE@" -issueTrackerURL = "@ISSUES@" -[[mods]] -modId = "terra" -version = "@VERSION@" -displayName = "Terra" -displayURL = "@WIKI@" -authors = "dfsek & Terra contributors" -description = "@DESCRIPTION@" -[[dependencies.terra]] -modId = "forge" -mandatory = true -versionRange = "[36,)" -ordering = "NONE" -side = "BOTH" \ No newline at end of file diff --git a/platforms/forge/src/main/resources/pack.mcmeta b/platforms/forge/src/main/resources/pack.mcmeta deleted file mode 100644 index e33bc0eb4..000000000 --- a/platforms/forge/src/main/resources/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "description": "Terra Resources", - "pack_format": 6 - } -} \ No newline at end of file diff --git a/platforms/forge/src/main/resources/terra.mixins.json b/platforms/forge/src/main/resources/terra.mixins.json deleted file mode 100644 index 5aefcf5f0..000000000 --- a/platforms/forge/src/main/resources/terra.mixins.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "required": true, - "package": "com.dfsek.terra.forge.mixin", - "compatibilityLevel": "JAVA_8", - "refmap": "terra-refmap.json", - "mixins": [ - "DimensionGeneratorSettingsMixin", - "ServerWorldMixin", - "access.AbstractSpawnerAccessor", - "access.BiomeGeneratorTypeScreensAccessor", - "implementations.BiomeMixin", - "implementations.ChunkGeneratorMixin", - "implementations.ConfiguredFeatureMixin", - "implementations.block.BlockMixin", - "implementations.block.TileEntityMixin", - "implementations.block.state.LockableLootTileEntityMixin", - "implementations.block.state.MobSpawnerTileEntityMixin", - "implementations.block.state.SignTileEntityMixin", - "implementations.chunk.ChunkMixin", - "implementations.chunk.WorldGenRegionMixin", - "implementations.chunk.data.ChunkPrimerMixin", - "implementations.entity.CommandSourceMixin", - "implementations.entity.EntityMixin", - "implementations.entity.EntityTypeMixin", - "implementations.entity.PlayerEntityMixin", - "implementations.inventory.LockableTileEntityMixin", - "implementations.inventory.item.ItemMixin", - "implementations.inventory.item.ItemStackMixin", - "implementations.inventory.meta.EnchantmentMixin", - "implementations.inventory.meta.ItemStackDamageableMixin", - "implementations.inventory.meta.ItemStackMetaMixin", - "implementations.world.ServerWorldMixin", - "implementations.world.WorldGenRegionMixin" - ], - "client": [ - "init.MinecraftClientMixin" - ], - "server": [ - "init.MinecraftServerMixin" - ], - "injectors": { - "defaultRequire": 1 - }, - "minVersion": "0.8" -} \ No newline at end of file diff --git a/platforms/forge/src/test/resources/META-INF/mods.toml b/platforms/forge/src/test/resources/META-INF/mods.toml deleted file mode 100644 index bb8120be8..000000000 --- a/platforms/forge/src/test/resources/META-INF/mods.toml +++ /dev/null @@ -1,20 +0,0 @@ -modLoader = "javafml" -loaderVersion = "[33,)" -license = "GNU General Public License, version 3.0" -issueTrackerURL = "https://github.com/PolyhedralDev/Terra/issues" -[[mods]] -modId = "terra" -version = "@VERSION@" -displayName = "Terra" -displayURL = "https://github.com/PolyhedralDev/Terra" -logoFile = "logo_text.png" -authors = "dfsek & Terra contributors" -description = ''' -Powerful data-driven world generator -''' -[[dependencies.terra]] -modId = "forge" -mandatory = true -versionRange = "[36.0.4,)" -ordering = "NONE" -side = "BOTH" \ No newline at end of file diff --git a/platforms/forge/src/test/resources/pack.mcmeta b/platforms/forge/src/test/resources/pack.mcmeta deleted file mode 100644 index 5ed246b25..000000000 --- a/platforms/forge/src/test/resources/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "description": "Terra resources", - "pack_format": 6 - } -} \ No newline at end of file diff --git a/platforms/merged/build.gradle.kts b/platforms/merged/build.gradle.kts new file mode 100644 index 000000000..2683bd74d --- /dev/null +++ b/platforms/merged/build.gradle.kts @@ -0,0 +1,37 @@ +val platformOverrides = mapOf( + "fabric" to "remapJar" + ) + +dependencies { + api(project(":common:implementation:base")) +} + +val taskSet = HashSet() +val resourcesDir = File("${project.buildDir}/resources/main/") + +val dump = tasks.create("dumpDependents") { + doFirst { + taskSet.forEach { + val resource = File(resourcesDir, it.archiveFileName.get()) + println("Including archive " + it.archiveFileName.orNull + " in directory " + resource.absolutePath) + it.archiveFile.get().asFile.copyTo(resource, true) + } + } +} + +tasks["processResources"].dependsOn(dump) + +afterEvaluate { + project(":platforms").subprojects.forEach { + if (it == this@afterEvaluate) return@forEach + + val taskName = platformOverrides.getOrDefault(it.name, "jar") + val task = it.tasks.named(taskName).get() + if (task !is AbstractArchiveTask) { + throw IllegalArgumentException("Task dependency must be Archive Task: " + task.name) + } + tasks["dumpDependents"].dependsOn(task) + taskSet.add(task) + println("Merged JAR will incorporate task ${task.name} from platform ${it.name}.") + } +} \ No newline at end of file diff --git a/platforms/region/build.gradle.kts b/platforms/region/build.gradle.kts deleted file mode 100644 index 3d467c794..000000000 --- a/platforms/region/build.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -import com.dfsek.terra.configureCommon -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar - -plugins { - `java-library` -} - -configureCommon() - -group = "com.dfsek.terra" - -repositories { - mavenCentral() - maven { url = uri("https://jitpack.io/") } -} - -dependencies { - "shadedApi"(project(":common")) - "shadedImplementation"("com.github.Querz:NBT:5.2") // Standalone NBT API - "shadedImplementation"("org.yaml:snakeyaml:1.27") - "shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1") -} - -tasks.named("shadowJar") { - relocate("net.querz", "com.dfsek.terra.libs.nbt") -} \ No newline at end of file diff --git a/platforms/region/src/main/java/com/dfsek/terra/DirectUtils.java b/platforms/region/src/main/java/com/dfsek/terra/DirectUtils.java deleted file mode 100644 index 2be2ebf6e..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/DirectUtils.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra; - -import com.dfsek.terra.api.math.MathUtil; -import net.querz.mca.MCAUtil; - -public final class DirectUtils { - - /** - * Compute long region ID from chunk coords - * - * @param x X - * @param z Z - * @return Region IS - */ - public static long regionID(int x, int z) { - return MathUtil.squash(MCAUtil.chunkToRegion(x), MCAUtil.chunkToRegion(z)); - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/RegionGenerator.java b/platforms/region/src/main/java/com/dfsek/terra/RegionGenerator.java deleted file mode 100644 index cf57a310b..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/RegionGenerator.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra; - -import com.dfsek.terra.region.Generator; - -import java.io.IOException; -import java.util.concurrent.ThreadLocalRandom; - -public class RegionGenerator { - public static void main(String[] args) throws IOException { - long seed; - if(args.length == 1) seed = Long.parseLong(args[0]); - else seed = ThreadLocalRandom.current().nextLong(); - - StandalonePlugin plugin = new StandalonePlugin(); - Generator generator = new Generator(seed, plugin); - - generator.generate(); - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java b/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java deleted file mode 100644 index ff426a5c0..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/StandalonePlugin.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.dfsek.terra; - -import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.event.EventManager; -import com.dfsek.terra.api.event.TerraEventManager; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.registry.CheckedRegistry; -import com.dfsek.terra.api.registry.LockedRegistry; -import com.dfsek.terra.api.util.logging.DebugLogger; -import com.dfsek.terra.api.util.logging.JavaLogger; -import com.dfsek.terra.config.GenericLoaders; -import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.lang.LangUtil; -import com.dfsek.terra.config.lang.Language; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.platform.RawBiome; -import com.dfsek.terra.platform.RawWorldHandle; -import com.dfsek.terra.profiler.Profiler; -import com.dfsek.terra.profiler.ProfilerImpl; -import com.dfsek.terra.registry.master.AddonRegistry; -import com.dfsek.terra.registry.master.ConfigRegistry; -import com.dfsek.terra.world.TerraWorld; - -import java.io.File; -import java.io.IOException; -import java.util.logging.Logger; - -public class StandalonePlugin implements TerraPlugin { - private final ConfigRegistry registry = new ConfigRegistry(); - private final AddonRegistry addonRegistry = new AddonRegistry(this); - - private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); - - private final PluginConfig config = new PluginConfig(); - private final RawWorldHandle worldHandle = new RawWorldHandle(); - private final EventManager eventManager = new TerraEventManager(this); - - private final Profiler profiler = new ProfilerImpl(); - - @Override - public WorldHandle getWorldHandle() { - return worldHandle; - } - - @Override - public TerraWorld getWorld(World world) { - return new TerraWorld(world, registry.get("DEFAULT"), this); - } - - @Override - public com.dfsek.terra.api.util.logging.Logger logger() { - return new JavaLogger(Logger.getLogger("Terra")); - } - - @Override - public PluginConfig getTerraConfig() { - return config; - } - - @Override - public File getDataFolder() { - return new File("."); - } - - @Override - public boolean isDebug() { - return true; - } - - @Override - public Language getLanguage() { - try { - return new Language(new File(getDataFolder(), "lang/en_us.yml")); - } catch(IOException e) { - throw new IllegalArgumentException(); - } - } - - @Override - public CheckedRegistry getConfigRegistry() { - return new CheckedRegistry<>(registry); - } - - @Override - public LockedRegistry getAddons() { - return addonLockedRegistry; - } - - @Override - public boolean reload() { - throw new UnsupportedOperationException(); - } - - @Override - public ItemHandle getItemHandle() { - return null; - } - - @Override - public void saveDefaultConfig() { - - } - - @Override - public String platformName() { - return "Standalone"; - } - - @Override - public DebugLogger getDebugLogger() { - Logger logger = Logger.getLogger("Terra"); - return new DebugLogger(new com.dfsek.terra.api.util.logging.Logger() { - @Override - public void info(String message) { - logger.info(message); - } - - @Override - public void warning(String message) { - logger.warning(message); - } - - @Override - public void severe(String message) { - logger.severe(message); - } - }); - } - - @Override - public void register(TypeRegistry registry) { - registry - .registerLoader(BlockData.class, (t, o, l) -> worldHandle.createBlockData((String) o)) - .registerLoader(Biome.class, (t, o, l) -> new RawBiome(o.toString())); - new GenericLoaders(this).register(registry); - } - - public void load() { - LangUtil.load("en_us", this); - registry.loadAll(this); - config.load(this); - } - - @Override - public EventManager getEventManager() { - return eventManager; - } - - @Override - public Profiler getProfiler() { - return profiler; - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java b/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java deleted file mode 100644 index 2267b7f91..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/Data.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.dfsek.terra.platform; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import net.querz.nbt.tag.CompoundTag; - -public class Data implements BlockData, BlockType { - private final CompoundTag data; - private final String noProp; - - public Data(String data) { - this.data = new CompoundTag(); - if(data.contains("[")) { - noProp = data.substring(0, data.indexOf('[')); // Strip properties - String properties = data.substring(data.indexOf('[') + 1, data.indexOf(']')); - String[] props = properties.split(","); - CompoundTag pTag = new CompoundTag(); - for(String property : props) { - String name = property.substring(0, property.indexOf('=')); - String val = property.substring(property.indexOf('=') + 1); - - pTag.putString(name, val); - } - this.data.put("Properties", pTag); - } else noProp = data; - this.data.putString("Name", noProp); - } - - public Data(CompoundTag tag) { - if(tag == null) { - this.data = new CompoundTag(); - data.putString("Name", "minecraft:air"); - } else { - this.data = tag; - } - noProp = data.getString("Name"); - } - - - @Override - public BlockType getBlockType() { - return this; - } - - @Override - public boolean matches(BlockData other) { - return ((Data) other).noProp.equals(noProp); - } - - @Override - public boolean isAir() { - return noProp.equals("minecraft:air"); - } - - @Override - public boolean isStructureVoid() { - return false; - } - - - @Override - public BlockData clone() { - try { - return (BlockData) super.clone(); - } catch(CloneNotSupportedException e) { - throw new Error(e); - } - } - - @Override - public String getAsString() { - return noProp; - } - - @Override - public CompoundTag getHandle() { - return data; - } - - @Override - public int hashCode() { - return noProp.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if(!(obj instanceof Data)) return false; - return ((Data) obj).noProp.equals(noProp); - } - - @Override - public BlockData getDefaultData() { - return this; - } - - @Override - public boolean isSolid() { - return false; - } - - @Override - public boolean isWater() { - return false; - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlock.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlock.java deleted file mode 100644 index 3169d0667..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlock.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.dfsek.terra.platform; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockFace; -import com.dfsek.terra.api.platform.block.BlockType; -import com.dfsek.terra.api.platform.block.state.BlockState; -import net.jafama.FastMath; - -public class DirectBlock implements Block { - private final DirectWorld world; - private final Vector3 pos; - - public DirectBlock(DirectWorld world, Vector3 pos) { - this.world = world; - this.pos = pos; - } - - @Override - public void setBlockData(BlockData data, boolean physics) { - synchronized(world) { - world.compute(FastMath.floorDiv(pos.getBlockX(), 16), FastMath.floorDiv(pos.getBlockZ(), 16)).setBlockStateAt(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), ((Data) data).getHandle(), false); - } - } - - @Override - public BlockData getBlockData() { - return new Data(world.getData(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ())); - } - - @Override - public BlockState getState() { - return new DirectBlockState(); - } - - @Override - public Block getRelative(BlockFace face) { - return world.getBlockAt(pos.getBlockX() + face.getModX(), pos.getBlockY() + face.getModY(), pos.getBlockZ() + face.getModZ()); - } - - @Override - public Block getRelative(BlockFace face, int len) { - return world.getBlockAt(pos.getBlockX() + face.getModX() * len, pos.getBlockY() + face.getModY() * len, pos.getBlockZ() + face.getModZ() * len); - } - - @Override - public boolean isEmpty() { - return getBlockData().getAsString().equals("minecraft:air"); - } - - @Override - public Location getLocation() { - return pos.toLocation(world); - } - - @Override - public BlockType getType() { - return new Data(world.getData(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ())); - } - - @Override - public int getX() { - return pos.getBlockX(); - } - - @Override - public int getZ() { - return pos.getBlockY(); - } - - @Override - public int getY() { - return pos.getBlockY(); - } - - @Override - public boolean isPassable() { - return false; - } - - @Override - public Object getHandle() { - return world; - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlockState.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlockState.java deleted file mode 100644 index db759cb44..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectBlockState.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.dfsek.terra.platform; - -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.state.BlockState; - -public class DirectBlockState implements BlockState { - @Override - public Block getBlock() { - return null; - } - - @Override - public int getX() { - return 0; - } - - @Override - public int getY() { - return 0; - } - - @Override - public int getZ() { - return 0; - } - - @Override - public BlockData getBlockData() { - return null; - } - - @Override - public boolean update(boolean applyPhysics) { - return false; - } - - @Override - public Object getHandle() { - return null; - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java deleted file mode 100644 index 4eac21cce..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectChunkData.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.dfsek.terra.platform; - -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkData; -import net.querz.mca.Chunk; -import net.querz.nbt.tag.CompoundTag; -import org.jetbrains.annotations.NotNull; - -public class DirectChunkData implements ChunkData, com.dfsek.terra.api.platform.world.Chunk { - private final Chunk delegate; - private final DirectWorld world; - private final int x; - private final int z; - - public DirectChunkData(Chunk delegate, DirectWorld world, int x, int z) { - this.delegate = delegate; - this.world = world; - this.x = x; - this.z = z; - } - - @Override - public Object getHandle() { - return delegate; - } - - @Override - public int getMaxHeight() { - return 255; - } - - @Override - public void setBlock(int x, int y, int z, @NotNull BlockData blockData) { - delegate.setBlockStateAt(x, y, z, ((Data) blockData).getHandle(), false); - } - - @Override - public @NotNull BlockData getBlockData(int x, int y, int z) { - CompoundTag tag = delegate.getBlockStateAt(x, y, z); - if(tag == null) return new Data("minecraft:air"); - return new Data(tag.getString("Name")); - } - - @Override - public int getX() { - return x; - } - - @Override - public int getZ() { - return z; - } - - @Override - public World getWorld() { - return world; - } - - @Override - public Block getBlock(int x, int y, int z) { - return new DirectBlock(world, new Vector3(x + (this.x << 4), y, z + (this.z << 4))); - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java b/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java deleted file mode 100644 index 84b90b7d8..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/DirectWorld.java +++ /dev/null @@ -1,103 +0,0 @@ -package com.dfsek.terra.platform; - -import com.dfsek.terra.DirectUtils; -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.math.vector.Vector3; -import com.dfsek.terra.api.platform.block.Block; -import com.dfsek.terra.api.platform.entity.Entity; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.world.Chunk; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import net.jafama.FastMath; -import net.querz.mca.MCAFile; -import net.querz.mca.MCAUtil; -import net.querz.nbt.tag.CompoundTag; - -import java.io.File; -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public class DirectWorld implements World { - private final long seed; - private final GenWrapper generator; - private final Map files = Collections.synchronizedMap(new HashMap<>()); - - public DirectWorld(long seed, GenWrapper generator) { - this.seed = seed; - this.generator = generator; - } - - @Override - public long getSeed() { - return seed; - } - - @Override - public int getMaxHeight() { - return 255; - } - - @Override - public ChunkGenerator getGenerator() { - return generator; - } - - @Override - public Chunk getChunkAt(int x, int z) { - MCAFile file = compute(x, z); - net.querz.mca.Chunk chunk = file.getChunk(x, z); - if(chunk == null) { - chunk = net.querz.mca.Chunk.newChunk(); - file.setChunk(x, z, chunk); - } - return new DirectChunkData(chunk, this, x, z); - } - - @Override - public Block getBlockAt(int x, int y, int z) { - return new DirectBlock(this, new Vector3(x, y, z)); - } - - @Override - public Entity spawnEntity(Location location, EntityType entityType) { - return null; - } - - @Override - public int getMinHeight() { - return 0; - } - - @Override - public Object getHandle() { - return generator; - } - - public MCAFile compute(int x, int z) { - synchronized(files) { - return files.computeIfAbsent(DirectUtils.regionID(x, z), k -> { - File test = new File("region", MCAUtil.createNameFromChunkLocation(x, z)); - if(test.exists()) { - try { - System.out.println("Re-loading " + MCAUtil.createNameFromChunkLocation(x, z)); - return MCAUtil.read(test); - } catch(IOException e) { - e.printStackTrace(); - } - } - return new MCAFile(MCAUtil.chunkToRegion(x), MCAUtil.chunkToRegion(z)); - }); - } - } - - public CompoundTag getData(int x, int y, int z) { - return compute(FastMath.floorDiv(x, 16), FastMath.floorDiv(z, 16)).getBlockStateAt(x, y, z); - } - - public Map getFiles() { - return files; - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java b/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java deleted file mode 100644 index 7de56d5bf..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/GenWrapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.platform; - -import com.dfsek.terra.api.platform.world.generator.ChunkGenerator; -import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; - -public class GenWrapper implements ChunkGenerator { - private final DefaultChunkGenerator3D generator; - - public GenWrapper(DefaultChunkGenerator3D generator) { - this.generator = generator; - } - - @Override - public Object getHandle() { - return generator; - } - -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawBiome.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawBiome.java deleted file mode 100644 index d9082aa4c..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/RawBiome.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.dfsek.terra.platform; - -import com.dfsek.terra.api.platform.world.Biome; - -public class RawBiome implements Biome { - private final String id; - - public RawBiome(String id) { - this.id = id; - } - - @Override - public Object getHandle() { - return id; - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java deleted file mode 100644 index e86172ce5..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/RawTree.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.dfsek.terra.platform; - -import com.dfsek.terra.api.math.vector.Location; -import com.dfsek.terra.api.platform.world.Tree; -import com.dfsek.terra.api.util.collections.MaterialSet; - -import java.util.Random; - -public class RawTree implements Tree { // TODO: implement - @Override - public boolean plant(Location l, Random r) { - return false; - } - - @Override - public MaterialSet getSpawnable() { - return MaterialSet.empty(); - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java b/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java deleted file mode 100644 index 2e2ce5b63..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/platform/RawWorldHandle.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.dfsek.terra.platform; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.handle.WorldHandle; - -public class RawWorldHandle implements WorldHandle { - - @Override - public BlockData createBlockData(String data) { - return new Data(data); - } - - @Override - public EntityType getEntity(String id) { - return null; - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java b/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java deleted file mode 100644 index cd6a55e66..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/region/Generator.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.dfsek.terra.region; - -import com.dfsek.terra.StandalonePlugin; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.platform.DirectChunkData; -import com.dfsek.terra.platform.DirectWorld; -import com.dfsek.terra.platform.GenWrapper; -import com.dfsek.terra.world.generation.generators.DefaultChunkGenerator3D; -import com.dfsek.terra.world.generation.math.SamplerCache; -import com.dfsek.terra.world.population.FloraPopulator; -import com.dfsek.terra.world.population.OrePopulator; -import com.dfsek.terra.world.population.StructurePopulator; -import com.dfsek.terra.world.population.TreePopulator; -import net.querz.mca.MCAFile; -import net.querz.mca.MCAUtil; - -import java.io.File; -import java.io.IOException; -import java.util.Map; - -public class Generator { - private final long seed; - FloraPopulator floraPopulator; - StructurePopulator structurePopulator; - TreePopulator treePopulator; - OrePopulator orePopulator; - DefaultChunkGenerator3D generator; - - public Generator(long seed, StandalonePlugin plugin) { - plugin.load(); - floraPopulator = new FloraPopulator(plugin); - structurePopulator = new StructurePopulator(plugin); - treePopulator = new TreePopulator(plugin); - orePopulator = new OrePopulator(plugin); - generator = new DefaultChunkGenerator3D(plugin.getConfigRegistry().get("DEFAULT"), plugin); - this.seed = seed; - } - - public void generate() throws IOException { - - int rad = 64; - System.out.println("Total mem: " + Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024 + "GB"); - - - GenWrapper wrapper = new GenWrapper(generator); - DirectWorld world = new DirectWorld(seed, wrapper); - - long l = System.nanoTime(); - int count = 0; - - for(int cx = -rad; cx <= rad; cx++) { - for(int cz = -rad; cz <= rad; cz++) { - DirectChunkData chunkData = (DirectChunkData) world.getChunkAt(cx, cz); - generator.generateChunkData(world, null, cx, cz, chunkData); - - structurePopulator.populate(world, chunkData); - orePopulator.populate(world, chunkData); - floraPopulator.populate(world, chunkData); - treePopulator.populate(world, chunkData); - count++; - - if(count % 200 == 0) { - long n = System.nanoTime(); - - System.out.println("Generated " + count + " chunks. " + 200 / ((double) (n - l) / 1000000) * 1000 + "cps."); - - l = System.nanoTime(); - - } - } - } - - - - System.out.println("Saving..."); - - for(Map.Entry entry : world.getFiles().entrySet()) { - if(entry.getValue() == null) continue; - entry.getValue().cleanupPalettesAndBlockStates(); - int x = (int) (entry.getKey() >> 32); - int z = (int) (long) entry.getKey(); - File file = new File("region", MCAUtil.createNameFromRegionLocation(x, z)); - file.getParentFile().mkdirs(); - MCAUtil.write(entry.getValue(), file); - } - - System.out.println("Done in " + (System.nanoTime() - l) / 1000000000 + "s"); - } -} diff --git a/platforms/region/src/main/java/com/dfsek/terra/region/RegionWriter.java b/platforms/region/src/main/java/com/dfsek/terra/region/RegionWriter.java deleted file mode 100644 index 7ae434669..000000000 --- a/platforms/region/src/main/java/com/dfsek/terra/region/RegionWriter.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.dfsek.terra.region; - -public class RegionWriter { - -} diff --git a/platforms/sponge/build.gradle.kts b/platforms/sponge/build.gradle.kts index 9880b8c93..9303dde3c 100644 --- a/platforms/sponge/build.gradle.kts +++ b/platforms/sponge/build.gradle.kts @@ -1,28 +1,40 @@ -import com.dfsek.terra.configureCommon - plugins { - java - id("org.spongepowered.plugin").version("0.9.0") + id("org.spongepowered.gradle.vanilla").version("0.2") } -configureCommon() - -group = "com.dfsek.terra" - repositories { - mavenCentral() - jcenter() + maven { + url = uri("https://repo-new.spongepowered.org/repository/maven-public/") + } } dependencies { - "compileOnly"("org.spongepowered:spongeapi:7.2.0") - "shadedApi"(project(":common")) - "shadedImplementation"("org.yaml:snakeyaml:1.27") - "shadedImplementation"("com.googlecode.json-simple:json-simple:1.1.1") + api(project(":common:implementation:base")) + + api("org.slf4j:slf4j-api:1.8.0-beta4") { + because("Minecraft 1.17+ includes slf4j 1.8.0-beta4, so we need to shade it for other versions.") + } + implementation("org.apache.logging.log4j", "log4j-slf4j18-impl", Versions.Libraries.log4j_slf4j_impl) { + because("Minecraft 1.17+ includes slf4j 1.8.0-beta4, so we need to shade it for other versions.") + } + + annotationProcessor("org.spongepowered", "spongeapi", Versions.Sponge.sponge) + implementation("org.spongepowered", "spongeapi", Versions.Sponge.sponge) + annotationProcessor("org.spongepowered:mixin:${Versions.Sponge.mixin}:processor") } -sponge { - plugin { - id = "terra" +minecraft { + version(Versions.Sponge.minecraft) + runs { + server() + client() + } +} + +tasks.named("jar") { + manifest { + //attributes( + // mapOf("MixinConfigs" to "terra.mixins.json") + //) } } \ No newline at end of file diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/PlatformImpl.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/PlatformImpl.java new file mode 100644 index 000000000..c04ad7244 --- /dev/null +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/PlatformImpl.java @@ -0,0 +1,64 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.sponge; + +import org.jetbrains.annotations.NotNull; +import org.spongepowered.api.Sponge; + +import java.io.File; + +import com.dfsek.terra.AbstractPlatform; +import com.dfsek.terra.api.handle.ItemHandle; +import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.sponge.handle.SpongeWorldHandle; + + +public class PlatformImpl extends AbstractPlatform { + private final TerraSpongePlugin plugin; + private final SpongeWorldHandle worldHandle = new SpongeWorldHandle(); + + public PlatformImpl(TerraSpongePlugin plugin) { + this.plugin = plugin; + load(); + } + + @Override + public boolean reload() { + return false; + } + + @Override + public @NotNull String platformName() { + return "Sponge"; + } + + @Override + public @NotNull WorldHandle getWorldHandle() { + return worldHandle; + } + + @Override + public @NotNull File getDataFolder() { + return Sponge.configManager().pluginConfig(plugin.getPluginContainer()).directory().toFile(); + } + + @Override + public @NotNull ItemHandle getItemHandle() { + return null; + } +} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeAdapter.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeAdapter.java deleted file mode 100644 index 781b5f91e..000000000 --- a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeAdapter.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.dfsek.terra.sponge; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.sponge.world.block.data.SpongeBlockData; -import org.spongepowered.api.block.BlockState; - -public final class SpongeAdapter { - public static BlockData adapt(BlockState state) { - return new SpongeBlockData(state); - } - - public static BlockState adapt(BlockData data) { - return ((SpongeBlockData) data).getHandle(); - } -} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeListener.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeListener.java new file mode 100644 index 000000000..e2373308c --- /dev/null +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeListener.java @@ -0,0 +1,38 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.sponge; + +import org.spongepowered.api.Server; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.lifecycle.StartingEngineEvent; + +import com.dfsek.terra.api.event.events.platform.PlatformInitializationEvent; + + +public class SpongeListener { + private final TerraSpongePlugin plugin; + + public SpongeListener(TerraSpongePlugin plugin) { + this.plugin = plugin; + } + + @Listener + public void initialize(StartingEngineEvent event) { + plugin.getTerraPlugin().getEventManager().callEvent(new PlatformInitializationEvent()); + } +} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeLogger.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeLogger.java deleted file mode 100644 index 1ead85e8d..000000000 --- a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/SpongeLogger.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.dfsek.terra.sponge; - -import com.dfsek.terra.api.util.logging.Logger; - -public class SpongeLogger implements Logger { - private final org.slf4j.Logger logger; - - public SpongeLogger(org.slf4j.Logger logger) { - this.logger = logger; - } - - @Override - public void info(String message) { - logger.info(message); - } - - @Override - public void warning(String message) { - logger.warn(message); - } - - @Override - public void severe(String message) { - logger.error(message); - } -} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/TerraSpongePlugin.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/TerraSpongePlugin.java index 536850875..109eb4750 100644 --- a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/TerraSpongePlugin.java +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/TerraSpongePlugin.java @@ -1,147 +1,45 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + package com.dfsek.terra.sponge; -import com.dfsek.tectonic.loading.TypeRegistry; -import com.dfsek.terra.api.TerraPlugin; -import com.dfsek.terra.api.addons.TerraAddon; -import com.dfsek.terra.api.event.EventManager; -import com.dfsek.terra.api.event.TerraEventManager; -import com.dfsek.terra.api.platform.handle.ItemHandle; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.registry.CheckedRegistry; -import com.dfsek.terra.api.registry.LockedRegistry; -import com.dfsek.terra.api.util.logging.DebugLogger; -import com.dfsek.terra.config.PluginConfig; -import com.dfsek.terra.config.lang.Language; -import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.profiler.Profiler; -import com.dfsek.terra.registry.master.AddonRegistry; -import com.dfsek.terra.registry.master.ConfigRegistry; -import com.dfsek.terra.sponge.world.SpongeWorldHandle; -import com.dfsek.terra.world.TerraWorld; import com.google.inject.Inject; -import org.slf4j.Logger; -import org.spongepowered.api.config.ConfigDir; -import org.spongepowered.api.event.Listener; -import org.spongepowered.api.event.game.state.GameStartedServerEvent; -import org.spongepowered.api.plugin.Plugin; +import org.spongepowered.api.Game; +import org.spongepowered.plugin.PluginContainer; +import org.spongepowered.plugin.builtin.jvm.Plugin; -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; - -@Plugin(id = "terra", name = "Terra-Sponge", version = "", description = "Terra") -public class TerraSpongePlugin implements TerraPlugin { - private final ConfigRegistry configRegistry = new ConfigRegistry(); - private final CheckedRegistry packCheckedRegistry = new CheckedRegistry<>(configRegistry); - private final PluginConfig config = new PluginConfig(); - private final AddonRegistry addonRegistry = new AddonRegistry(this); - private final LockedRegistry addonLockedRegistry = new LockedRegistry<>(addonRegistry); - - private final SpongeWorldHandle spongeWorldHandle = new SpongeWorldHandle(); - - private final EventManager eventManager = new TerraEventManager(this); +@Plugin("terra") +public class TerraSpongePlugin { + private final PluginContainer plugin; + private final PlatformImpl terraPlugin; + @Inject - @ConfigDir(sharedRoot = false) - private Path privateConfigDir; - - @Inject - private Logger logger; - - - @Listener - public void initialize(GameStartedServerEvent event) { - addonRegistry.loadAll(); - configRegistry.loadAll(this); + public TerraSpongePlugin(Game game) { + this.plugin = null; + this.terraPlugin = new PlatformImpl(this); + game.eventManager().registerListeners(plugin, new SpongeListener(this)); } - - @Override - public void register(TypeRegistry registry) { - + + public PluginContainer getPluginContainer() { + return plugin; } - - @Override - public WorldHandle getWorldHandle() { - return spongeWorldHandle; - } - - @Override - public TerraWorld getWorld(World world) { - return null; - } - - @Override - public com.dfsek.terra.api.util.logging.Logger logger() { - return new SpongeLogger(logger); - } - - @Override - public PluginConfig getTerraConfig() { - return config; - } - - @Override - public File getDataFolder() { - return privateConfigDir.toFile(); - } - - @Override - public boolean isDebug() { - return true; - } - - @Override - public Language getLanguage() { - try { - return new Language(new File(getDataFolder(), "lang/en_us.yml")); - } catch(IOException e) { - throw new IllegalArgumentException(); - } - } - - @Override - public CheckedRegistry getConfigRegistry() { - return packCheckedRegistry; - } - - @Override - public LockedRegistry getAddons() { - return addonLockedRegistry; - } - - @Override - public boolean reload() { - return false; - } - - @Override - public ItemHandle getItemHandle() { - return null; - } - - @Override - public void saveDefaultConfig() { - - } - - @Override - public String platformName() { - return "Sponge"; - } - - @Override - public DebugLogger getDebugLogger() { - return null; - } - - @Override - public EventManager getEventManager() { - return eventManager; - } - - @Override - public Profiler getProfiler() { - return null; + + public PlatformImpl getTerraPlugin() { + return terraPlugin; } } diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/block/SpongeBlockState.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/block/SpongeBlockState.java new file mode 100644 index 000000000..dbf1f8500 --- /dev/null +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/block/SpongeBlockState.java @@ -0,0 +1,78 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.sponge.block; + +import org.spongepowered.api.block.BlockTypes; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.block.state.properties.Property; + + +public class SpongeBlockState implements BlockState { + private final org.spongepowered.api.block.BlockState delegate; + + public SpongeBlockState(org.spongepowered.api.block.BlockState delegate) { + this.delegate = delegate; + } + + @Override + public org.spongepowered.api.block.BlockState getHandle() { + return delegate; + } + + @Override + public boolean matches(BlockState other) { + return delegate.type().equals(((SpongeBlockType) other.getBlockType()).getHandle()); + } + + @Override + public > boolean has(Property property) { + return false; + } + + @Override + public > T get(Property property) { + return null; + } + + @Override + public > BlockState set(Property property, T value) { + return this; + } + + @Override + public BlockType getBlockType() { + return new SpongeBlockType(delegate.type()); + } + + @Override + public String getAsString(boolean verbose) { + return delegate.toString(); + } + + @Override + public boolean isAir() { + return delegate.type().equals(BlockTypes.AIR.get()); + } + + @Override + public BlockState clone() { + return this; + } +} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/block/SpongeBlockType.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/block/SpongeBlockType.java new file mode 100644 index 000000000..d27aaef24 --- /dev/null +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/block/SpongeBlockType.java @@ -0,0 +1,53 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.sponge.block; + +import org.spongepowered.api.block.BlockTypes; +import org.spongepowered.api.data.Keys; + +import com.dfsek.terra.api.block.BlockType; +import com.dfsek.terra.api.block.state.BlockState; + + +public class SpongeBlockType implements BlockType { + private final org.spongepowered.api.block.BlockType delegate; + + public SpongeBlockType(org.spongepowered.api.block.BlockType delegate) { + this.delegate = delegate; + } + + @Override + public org.spongepowered.api.block.BlockType getHandle() { + return delegate; + } + + @Override + public BlockState getDefaultState() { + return new SpongeBlockState(delegate.defaultState()); + } + + @Override + public boolean isSolid() { + return !delegate.getOrElse(Keys.IS_SOLID, false); + } + + @Override + public boolean isWater() { + return delegate.equals(BlockTypes.WATER.get()); + } +} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/handle/SpongeWorldHandle.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/handle/SpongeWorldHandle.java new file mode 100644 index 000000000..84cc0a55d --- /dev/null +++ b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/handle/SpongeWorldHandle.java @@ -0,0 +1,51 @@ +/* + * This file is part of Terra. + * + * Terra is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Terra is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Terra. If not, see . + */ + +package com.dfsek.terra.sponge.handle; + +import org.jetbrains.annotations.NotNull; +import org.spongepowered.api.block.BlockTypes; + +import com.dfsek.terra.api.block.state.BlockState; +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.api.util.generic.Lazy; +import com.dfsek.terra.sponge.block.SpongeBlockState; + + +public class SpongeWorldHandle implements WorldHandle { + private final Lazy air; + + public SpongeWorldHandle() { + air = Lazy.lazy(() -> new SpongeBlockState(BlockTypes.AIR.get().defaultState())); + } + + @Override + public @NotNull BlockState createBlockState(@NotNull String data) { + return new SpongeBlockState(org.spongepowered.api.block.BlockState.fromString(data)); + } + + @Override + public @NotNull BlockState air() { + return air.value(); + } + + @Override + public @NotNull EntityType getEntity(@NotNull String id) { + throw new UnsupportedOperationException(); + } +} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/SpongeWorldHandle.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/SpongeWorldHandle.java deleted file mode 100644 index 422229ba9..000000000 --- a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/SpongeWorldHandle.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.dfsek.terra.sponge.world; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.entity.EntityType; -import com.dfsek.terra.api.platform.handle.WorldHandle; -import com.dfsek.terra.sponge.SpongeAdapter; -import org.spongepowered.api.Sponge; -import org.spongepowered.api.block.BlockState; - -public class SpongeWorldHandle implements WorldHandle { - @Override - public BlockData createBlockData(String data) { - return SpongeAdapter.adapt(Sponge.getRegistry().getType(BlockState.class, data).orElseThrow(() -> new IllegalArgumentException("Invalid block data \"" + data + "\""))); - } - - @Override - public EntityType getEntity(String id) { - return null; - } -} diff --git a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/block/data/SpongeBlockData.java b/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/block/data/SpongeBlockData.java deleted file mode 100644 index eb68b9030..000000000 --- a/platforms/sponge/src/main/java/com/dfsek/terra/sponge/world/block/data/SpongeBlockData.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.dfsek.terra.sponge.world.block.data; - -import com.dfsek.terra.api.platform.block.BlockData; -import com.dfsek.terra.api.platform.block.BlockType; -import org.spongepowered.api.block.BlockState; - -public class SpongeBlockData implements BlockData { - private final BlockState delegate; - - public SpongeBlockData(BlockState delegate) { - this.delegate = delegate; - } - - @Override - public BlockState getHandle() { - return delegate; - } - - @Override - public BlockType getBlockType() { - return null; - } - - @Override - public boolean matches(BlockData other) { - return false; - } - - @Override - public BlockData clone() { - return null; - } - - @Override - public String getAsString() { - return null; - } - - @Override - public boolean isAir() { - return false; - } - - @Override - public boolean isStructureVoid() { - return false; - } -} diff --git a/platforms/sponge/src/main/resources/META-INF/plugins.json b/platforms/sponge/src/main/resources/META-INF/plugins.json new file mode 100644 index 000000000..d0b90db10 --- /dev/null +++ b/platforms/sponge/src/main/resources/META-INF/plugins.json @@ -0,0 +1,24 @@ +{ + "plugins": [ + { + "loader": "java_plain", + "id": "terra", + "name": "Terra", + "version": "@VERSION@", + "main-class": "com.dfsek.terra.sponge.TerraSpongePlugin", + "description": "@DESCRIPTION@", + "links": { + "source": "@SOURCE@", + "issues": "@ISSUES@" + }, + "contributors": [ + ], + "dependencies": [ + { + "id": "spongeapi", + "version": "9.0.0" + } + ] + } + ] +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 8cd013d8d..f0612e154 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,19 +1,26 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * The settings file is used to specify which projects to include in your build. - * - * Detailed information about configuring a multi-project build in Gradle can be found - * in the user manual at https://docs.gradle.org/6.6.1/userguide/multi_project_builds.html - */ - rootProject.name = "Terra" -include("common") -include("platforms:bukkit") -include("platforms:fabric") -include("platforms:region") -include("platforms:sponge") -include("platforms:forge") + + +fun includeImmediateChildren(dir: File, type: String) { + dir.walkTopDown().maxDepth(1).forEach { + if (!it.isDirectory || !File(it, "build.gradle.kts").exists()) return@forEach + val addonDir = it.relativeTo(file(".")).path.replace("/", ":").replace("\\", ":") + println("Including $type directory \"$addonDir\" as subproject.") + include(addonDir) + } +} + +includeImmediateChildren(file("common/api"), "API") + +includeImmediateChildren(file("common/implementation"), "implementation") + +includeImmediateChildren(file("common/addons"), "addon") + +includeImmediateChildren(file("platforms"), "platform") + +includeImmediateChildren(file("platforms/bukkit/nms"), "Bukkit NMS") + +include(":platforms:bukkit:common") pluginManagement { repositories { @@ -23,15 +30,3 @@ pluginManagement { gradlePluginPortal() } } - -plugins { - id("com.gradle.enterprise") version "3.4.1" -} - -gradleEnterprise { - buildScan { - termsOfServiceUrl = "https://gradle.com/terms-of-service" - termsOfServiceAgree = "yes" -// publishAlwaysIf(true) - } -}