Merge remote-tracking branch 'architectury/1.16' into 1.17

# Conflicts:
#	fabric/src/main/resources/architectury.mixins.json
#	gradle.properties
#	settings.gradle
This commit is contained in:
shedaniel
2021-02-11 21:35:32 +08:00
111 changed files with 2971 additions and 404 deletions

261
.editorconfig Normal file
View File

@@ -0,0 +1,261 @@
# This is beautiful.
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
tab_width = 4
trim_trailing_whitespace = false
ij_continuation_indent_size = 8
[*.java]
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 = true
ij_java_align_multiline_array_initializer_expression = false
ij_java_align_multiline_assignment = false
ij_java_align_multiline_binary_operation = true
ij_java_align_multiline_chained_methods = false
ij_java_align_multiline_extends_list = false
ij_java_align_multiline_for = true
ij_java_align_multiline_method_parentheses = false
ij_java_align_multiline_parameters = false
ij_java_align_multiline_parameters_in_calls = false
ij_java_align_multiline_parenthesized_expression = false
ij_java_align_multiline_records = true
ij_java_align_multiline_resources = true
ij_java_align_multiline_ternary_operation = false
ij_java_align_multiline_text_blocks = false
ij_java_align_multiline_throws_list = false
ij_java_align_subsequent_simple_methods = false
ij_java_align_throws_keyword = false
ij_java_annotation_parameter_wrap = normal
ij_java_array_initializer_new_line_after_left_brace = false
ij_java_array_initializer_right_brace_on_new_line = false
ij_java_array_initializer_wrap = off
ij_java_assert_statement_colon_on_next_line = false
ij_java_assert_statement_wrap = off
ij_java_assignment_wrap = off
ij_java_binary_operation_sign_on_next_line = false
ij_java_binary_operation_wrap = off
ij_java_blank_lines_after_anonymous_class_header = 0
ij_java_blank_lines_after_class_header = 0
ij_java_blank_lines_after_imports = 1
ij_java_blank_lines_after_package = 1
ij_java_blank_lines_around_class = 1
ij_java_blank_lines_around_field = 0
ij_java_blank_lines_around_field_in_interface = 0
ij_java_blank_lines_around_initializer = 1
ij_java_blank_lines_around_method = 1
ij_java_blank_lines_around_method_in_interface = 1
ij_java_blank_lines_before_class_end = 0
ij_java_blank_lines_before_imports = 1
ij_java_blank_lines_before_method_body = 0
ij_java_blank_lines_before_package = 0
ij_java_block_brace_style = end_of_line
ij_java_block_comment_at_first_column = true
ij_java_call_parameters_new_line_after_left_paren = false
ij_java_call_parameters_right_paren_on_new_line = false
ij_java_call_parameters_wrap = off
ij_java_case_statement_on_separate_line = true
ij_java_catch_on_new_line = false
ij_java_class_annotation_wrap = split_into_lines
ij_java_class_brace_style = end_of_line
ij_java_class_count_to_use_import_on_demand = 5
ij_java_class_names_in_javadoc = 1
ij_java_do_not_indent_top_level_class_members = false
ij_java_do_not_wrap_after_single_annotation = false
ij_java_do_while_brace_force = never
ij_java_doc_add_blank_line_after_description = true
ij_java_doc_add_blank_line_after_param_comments = false
ij_java_doc_add_blank_line_after_return = false
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_keep_empty_lines = true
ij_java_doc_keep_empty_parameter_tag = true
ij_java_doc_keep_empty_return_tag = true
ij_java_doc_keep_empty_throws_tag = true
ij_java_doc_keep_invalid_tags = true
ij_java_doc_param_description_on_new_line = false
ij_java_doc_preserve_line_breaks = false
ij_java_doc_use_throws_not_exception_tag = true
ij_java_else_on_new_line = false
ij_java_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 = off
ij_java_extends_list_wrap = off
ij_java_field_annotation_wrap = on_every_item
ij_java_finally_on_new_line = false
ij_java_for_brace_force = never
ij_java_for_statement_new_line_after_left_paren = false
ij_java_for_statement_right_paren_on_new_line = false
ij_java_for_statement_wrap = off
ij_java_generate_final_locals = false
ij_java_generate_final_parameters = false
ij_java_if_brace_force = never
ij_java_imports_layout = *,|,javax.**,java.**,|,$*
ij_java_indent_case_from_switch = true
ij_java_insert_inner_class_imports = false
ij_java_insert_override_annotation = true
ij_java_keep_blank_lines_before_right_brace = 2
ij_java_keep_blank_lines_between_package_declaration_and_header = 2
ij_java_keep_blank_lines_in_code = 2
ij_java_keep_blank_lines_in_declarations = 2
ij_java_keep_control_statement_in_one_line = true
ij_java_keep_first_column_comment = true
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_classes_in_one_line = true
ij_java_keep_simple_lambdas_in_one_line = true
ij_java_keep_simple_methods_in_one_line = true
ij_java_label_indent_absolute = false
ij_java_label_indent_size = 0
ij_java_lambda_brace_style = end_of_line
ij_java_layout_static_imports_separately = true
ij_java_line_comment_add_space = false
ij_java_line_comment_at_first_column = true
ij_java_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_parameters_new_line_after_left_paren = false
ij_java_method_parameters_right_paren_on_new_line = false
ij_java_method_parameters_wrap = off
ij_java_modifier_list_wrap = false
ij_java_names_count_to_use_import_on_demand = 3
ij_java_new_line_after_lparen_in_record_header = false
ij_java_parameter_annotation_wrap = normal
ij_java_parentheses_expression_new_line_after_left_paren = false
ij_java_parentheses_expression_right_paren_on_new_line = false
ij_java_place_assignment_sign_on_next_line = false
ij_java_prefer_longer_names = true
ij_java_prefer_parameters_wrap = false
ij_java_record_components_wrap = normal
ij_java_repeat_synchronized = true
ij_java_replace_instanceof_and_cast = false
ij_java_replace_null_check = true
ij_java_replace_sum_lambda_with_method_ref = true
ij_java_resource_list_new_line_after_left_paren = false
ij_java_resource_list_right_paren_on_new_line = false
ij_java_resource_list_wrap = off
ij_java_rparen_on_new_line_in_record_header = false
ij_java_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
ij_java_space_after_comma_in_type_arguments = true
ij_java_space_after_for_semicolon = true
ij_java_space_after_quest = true
ij_java_space_after_type_cast = true
ij_java_space_before_annotation_array_initializer_left_brace = false
ij_java_space_before_annotation_parameter_list = false
ij_java_space_before_array_initializer_left_brace = false
ij_java_space_before_catch_keyword = true
ij_java_space_before_catch_left_brace = true
ij_java_space_before_catch_parentheses = true
ij_java_space_before_class_left_brace = true
ij_java_space_before_colon = true
ij_java_space_before_colon_in_foreach = true
ij_java_space_before_comma = false
ij_java_space_before_do_left_brace = true
ij_java_space_before_else_keyword = true
ij_java_space_before_else_left_brace = true
ij_java_space_before_finally_keyword = true
ij_java_space_before_finally_left_brace = true
ij_java_space_before_for_left_brace = true
ij_java_space_before_for_parentheses = true
ij_java_space_before_for_semicolon = false
ij_java_space_before_if_left_brace = true
ij_java_space_before_if_parentheses = true
ij_java_space_before_method_call_parentheses = false
ij_java_space_before_method_left_brace = true
ij_java_space_before_method_parentheses = false
ij_java_space_before_opening_angle_bracket_in_type_parameter = false
ij_java_space_before_quest = true
ij_java_space_before_switch_left_brace = true
ij_java_space_before_switch_parentheses = true
ij_java_space_before_synchronized_left_brace = true
ij_java_space_before_synchronized_parentheses = true
ij_java_space_before_try_left_brace = true
ij_java_space_before_try_parentheses = true
ij_java_space_before_type_parameter_list = false
ij_java_space_before_while_keyword = true
ij_java_space_before_while_left_brace = true
ij_java_space_before_while_parentheses = true
ij_java_space_inside_one_line_enum_braces = false
ij_java_space_within_empty_array_initializer_braces = false
ij_java_space_within_empty_method_call_parentheses = false
ij_java_space_within_empty_method_parentheses = false
ij_java_spaces_around_additive_operators = true
ij_java_spaces_around_assignment_operators = true
ij_java_spaces_around_bitwise_operators = true
ij_java_spaces_around_equality_operators = true
ij_java_spaces_around_lambda_arrow = true
ij_java_spaces_around_logical_operators = true
ij_java_spaces_around_method_ref_dbl_colon = false
ij_java_spaces_around_multiplicative_operators = true
ij_java_spaces_around_relational_operators = true
ij_java_spaces_around_shift_operators = true
ij_java_spaces_around_type_bounds_in_type_parameters = true
ij_java_spaces_around_unary_operator = false
ij_java_spaces_within_angle_brackets = false
ij_java_spaces_within_annotation_parentheses = false
ij_java_spaces_within_array_initializer_braces = false
ij_java_spaces_within_braces = false
ij_java_spaces_within_brackets = false
ij_java_spaces_within_cast_parentheses = false
ij_java_spaces_within_catch_parentheses = false
ij_java_spaces_within_for_parentheses = false
ij_java_spaces_within_if_parentheses = false
ij_java_spaces_within_method_call_parentheses = false
ij_java_spaces_within_method_parentheses = false
ij_java_spaces_within_parentheses = false
ij_java_spaces_within_record_header = false
ij_java_spaces_within_switch_parentheses = false
ij_java_spaces_within_synchronized_parentheses = false
ij_java_spaces_within_try_parentheses = false
ij_java_spaces_within_while_parentheses = false
ij_java_special_else_if_treatment = true
ij_java_subclass_name_suffix = Impl
ij_java_ternary_operation_signs_on_next_line = false
ij_java_ternary_operation_wrap = off
ij_java_test_name_suffix = Test
ij_java_throws_keyword_wrap = normal
ij_java_throws_list_wrap = off
ij_java_use_external_annotations = false
ij_java_use_fq_class_names = false
ij_java_use_relative_indents = false
ij_java_use_single_class_imports = true
ij_java_variable_annotation_wrap = normal
ij_java_visibility = public
ij_java_while_brace_force = never
ij_java_while_on_new_line = false
ij_java_wrap_comments = false
ij_java_wrap_first_method_in_call_chain = false
ij_java_wrap_long_lines = false

View File

@@ -2,6 +2,10 @@ name: Java CI
on:
push:
paths:
- '**.gradle'
- '**.properties'
- '**/src/**'
branches:
- "1.16"
- "1.17"
@@ -15,9 +19,10 @@ jobs:
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Upload to Bintray
run: ./gradlew bintrayUpload curseforgePublish --stacktrace
- name: Upload to Maven
run: ./gradlew publish curseforgePublish --stacktrace
if: |
!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.pull_request.title, '[ci skip]')
env:
BINTRAY_USER: shedaniel
BINTRAY_KEY: ${{ secrets.BINTRAY_KEY }}
curse_api_key: ${{ secrets.CURSE_API_KEY }}
MAVEN_PASS: ${{ secrets.MAVEN_PASS }}
curse_api_key: ${{ secrets.CURSE_API_KEY }}

28
.github/workflows/snapshot.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
name: Snapshot Compile & Release
on:
pull_request:
paths:
- '**.gradle'
- '**.properties'
- '**/src/**'
types: [ opened, synchronize, reopened ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Upload to Maven
run: ./gradlew publish --stacktrace
if: |
!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.pull_request.title, '[ci skip]')
env:
MAVEN_PASS: ${{ secrets.MAVEN_PASS }}
PR_NUM: ${{github.event.number}}

5
.gitignore vendored
View File

@@ -13,4 +13,7 @@ libs/
.project
.settings/org.eclipse.core.resources.prefs
.idea/
classes/
classes/
.vscode/
logs/

View File

@@ -1,10 +1,8 @@
plugins {
id "architectury-plugin" version "1.3.47"
id "forgified-fabric-loom" version "0.5.29" apply false
id "architectury-plugin" version "2.0.65"
id "forgified-fabric-loom" version "0.6.54" apply false
id "org.cadixdev.licenser" version "0.5.0"
id "com.jfrog.bintray" version "1.8.4"
id "com.matthewprenger.cursegradle" version "1.4.0" apply false
id "maven"
id "maven-publish"
}
@@ -15,8 +13,9 @@ architectury {
subprojects {
apply plugin: "forgified-fabric-loom"
dependencies {
testCompile sourceSets.main.output
loom {
silentMojangMappingsLicense()
useFabricMixin = true
}
}
@@ -24,13 +23,33 @@ allprojects {
apply plugin: "java"
apply plugin: "architectury-plugin"
apply plugin: "org.cadixdev.licenser"
ext {
isSnapshot = System.getenv("PR_NUM") != null
}
def runNumber = (System.getenv("GITHUB_RUN_NUMBER") == null ? "9999" : System.getenv("GITHUB_RUN_NUMBER"))
archivesBaseName = rootProject.archives_base_name
version = rootProject.mod_version + "." + (System.getenv("GITHUB_RUN_NUMBER") == null ? "9999" : System.getenv("GITHUB_RUN_NUMBER"))
if (!ext.isSnapshot) {
version = rootProject.base_version + "." + runNumber
archivesBaseName = rootProject.archives_base_name
} else {
version = rootProject.base_version + "-PR." + System.getenv("PR_NUM") + "." + runNumber
archivesBaseName = rootProject.archives_base_name_snapshot
}
group = rootProject.maven_group
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
// The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
// JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
// We'll use that if it's available, but otherwise we'll use the older option.
def targetVersion = 8
if (JavaVersion.current().isJava9Compatible()) {
options.release = targetVersion
}
}
license {
@@ -46,7 +65,7 @@ allprojects {
ignoreFailures = true
}
ext {
releaseChangelog = {
def dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm")
@@ -80,20 +99,4 @@ allprojects {
task licenseFormatAll
subprojects { p -> licenseFormatAll.dependsOn("${p.path}:licenseFormat") }
bintray {
user = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER')
key = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_KEY')
publications = ["mavenCommon", "mavenFabric", "mavenForge"]
publish = true
pkg {
repo = "cloth"
name = "architectury"
userOrg = "shedaniel"
licenses = ["Apache-2.0"]
version {
vcsUrl = "https://github.com/shedaniel/architectury.git"
}
}
}
task curseforgePublish
task curseforgePublish

View File

@@ -1,14 +1,13 @@
loom {
accessWidener = file("src/main/resources/architectury.accessWidener")
silentMojangMappingsLicense()
}
dependencies {
minecraft "com.mojang:minecraft:${rootProject.architect.minecraft}"
minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
mappings minecraft.officialMojangMappings()
// We depend on fabric loader here to use the fabric @Environment annotations
// Do NOT use other classes from fabric loader
modCompile "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
implementation "net.jodah:typetools:0.6.2"
}
@@ -43,4 +42,16 @@ publishing {
artifact javadocsJar
}
}
}
repositories {
if (System.getenv("MAVEN_PASS") != null) {
maven {
url = "https://deploy.shedaniel.me/"
credentials {
username = "shedaniel"
password = System.getenv("MAVEN_PASS")
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.core;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
/**
* The equivalent of {@link RecipeSerializer} to use in common that has forge registry entries extended.
*/
public abstract class AbstractRecipeSerializer<T extends Recipe<?>> extends RegistryEntry<RecipeSerializer<?>> implements RecipeSerializer<T> {
}

View File

@@ -0,0 +1,26 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.core;
/**
* An entry in registries, will extend {@code ForgeRegistryEntry} on forge.
*/
public class RegistryEntry<T> {
}

View File

@@ -58,6 +58,12 @@ public final class EventFactory {
return new EventImpl<>(function);
}
@SafeVarargs
public static <T> Event<T> createLoop(T... typeGetter) {
if (typeGetter.length != 0) throw new IllegalStateException("array must be empty!");
return createLoop((Class<T>) typeGetter.getClass().getComponentType());
}
@SuppressWarnings("UnstableApiUsage")
public static <T> Event<T> createLoop(Class<T> clazz) {
return of(listeners -> (T) Proxy.newProxyInstance(EventFactory.class.getClassLoader(), new Class[]{clazz}, new AbstractInvocationHandler() {
@@ -71,6 +77,12 @@ public final class EventFactory {
}));
}
@SafeVarargs
public static <T> Event<T> createInteractionResult(T... typeGetter) {
if (typeGetter.length != 0) throw new IllegalStateException("array must be empty!");
return createInteractionResult((Class<T>) typeGetter.getClass().getComponentType());
}
@SuppressWarnings("UnstableApiUsage")
public static <T> Event<T> createInteractionResult(Class<T> clazz) {
return of(listeners -> (T) Proxy.newProxyInstance(EventFactory.class.getClassLoader(), new Class[]{clazz}, new AbstractInvocationHandler() {
@@ -87,6 +99,12 @@ public final class EventFactory {
}));
}
@SafeVarargs
public static <T> Event<T> createInteractionResultHolder(T... typeGetter) {
if (typeGetter.length != 0) throw new IllegalStateException("array must be empty!");
return createInteractionResultHolder((Class<T>) typeGetter.getClass().getComponentType());
}
@SuppressWarnings("UnstableApiUsage")
public static <T> Event<T> createInteractionResultHolder(Class<T> clazz) {
return of(listeners -> (T) Proxy.newProxyInstance(EventFactory.class.getClassLoader(), new Class[]{clazz}, new AbstractInvocationHandler() {
@@ -103,6 +121,12 @@ public final class EventFactory {
}));
}
@SafeVarargs
public static <T> Event<Consumer<T>> createConsumerLoop(T... typeGetter) {
if (typeGetter.length != 0) throw new IllegalStateException("array must be empty!");
return createConsumerLoop((Class<T>) typeGetter.getClass().getComponentType());
}
@SuppressWarnings("UnstableApiUsage")
public static <T> Event<Consumer<T>> createConsumerLoop(Class<T> clazz) {
Event<Consumer<T>> event = of(listeners -> (Consumer<T>) Proxy.newProxyInstance(EventFactory.class.getClassLoader(), new Class[]{Consumer.class}, new AbstractInvocationHandler() {
@@ -124,6 +148,12 @@ public final class EventFactory {
return event;
}
@SafeVarargs
public static <T> Event<Actor<T>> createActorLoop(T... typeGetter) {
if (typeGetter.length != 0) throw new IllegalStateException("array must be empty!");
return createActorLoop((Class<T>) typeGetter.getClass().getComponentType());
}
@SuppressWarnings("UnstableApiUsage")
public static <T> Event<Actor<T>> createActorLoop(Class<T> clazz) {
Event<Actor<T>> event = of(listeners -> (Actor<T>) Proxy.newProxyInstance(EventFactory.class.getClassLoader(), new Class[]{Actor.class}, new AbstractInvocationHandler() {

View File

@@ -30,7 +30,7 @@ public interface ChatEvent {
/**
* Invoked when server receives a message, equivalent to forge's {@code ServerChatEvent}.
*/
Event<Server> SERVER = EventFactory.createInteractionResultHolder(Server.class);
Event<Server> SERVER = EventFactory.createInteractionResultHolder();
interface Server {
@NotNull

View File

@@ -31,7 +31,7 @@ public class CommandPerformEvent {
/**
* Invoked after server parses a command but before server executes it, equivalent to forge's {@code CommandEvent}.
*/
public static final Event<Actor<CommandPerformEvent>> EVENT = EventFactory.createActorLoop(CommandPerformEvent.class);
public static final Event<Actor<CommandPerformEvent>> EVENT = EventFactory.createActorLoop();
@NotNull
private ParseResults<CommandSourceStack> results;

View File

@@ -29,7 +29,7 @@ public interface CommandRegistrationEvent {
/**
* Invoked after server registers its commands, equivalent to forge's {@code RegisterCommandsEvent} and fabric's {@code CommandRegistrationCallback}.
*/
Event<CommandRegistrationEvent> EVENT = EventFactory.createLoop(CommandRegistrationEvent.class);
Event<CommandRegistrationEvent> EVENT = EventFactory.createLoop();
void register(CommandDispatcher<CommandSourceStack> dispatcher, Commands.CommandSelection selection);
}

View File

@@ -34,16 +34,16 @@ public interface EntityEvent {
/**
* Invoked before LivingEntity#die, equivalent to forge's {@code LivingDeathEvent}.
*/
Event<LivingDeath> LIVING_DEATH = EventFactory.createInteractionResult(LivingDeath.class);
Event<LivingDeath> LIVING_DEATH = EventFactory.createInteractionResult();
/**
* Invoked before LivingEntity#hurt, equivalent to forge's {@code LivingAttackEvent}.
*/
Event<LivingAttack> LIVING_ATTACK = EventFactory.createInteractionResult(LivingAttack.class);
Event<LivingAttack> LIVING_ATTACK = EventFactory.createInteractionResult();
/**
* Invoked before entity is added to a world, equivalent to forge's {@code EntityJoinWorldEvent}.
*/
Event<Add> ADD = EventFactory.createInteractionResult(Add.class);
Event<PlaceBlock> PLACE_BLOCK = EventFactory.createInteractionResult(PlaceBlock.class);
Event<Add> ADD = EventFactory.createInteractionResult();
Event<PlaceBlock> PLACE_BLOCK = EventFactory.createInteractionResult();
interface LivingDeath {
InteractionResult die(LivingEntity entity, DamageSource source);

View File

@@ -29,8 +29,8 @@ import net.minecraft.world.level.Level;
import java.util.List;
public interface ExplosionEvent {
Event<Pre> PRE = EventFactory.createInteractionResult(Pre.class);
Event<Detonate> DETONATE = EventFactory.createInteractionResult(Detonate.class);
Event<Pre> PRE = EventFactory.createInteractionResult();
Event<Detonate> DETONATE = EventFactory.createInteractionResult();
interface Pre {
InteractionResult explode(Level world, Explosion explosion);

View File

@@ -28,6 +28,7 @@ import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import java.util.List;
@@ -36,19 +37,24 @@ public interface GuiEvent {
/**
* Invoked after in-game hud is rendered, equivalent to forge's {@code RenderGameOverlayEvent.Post@ElementType#ALL} and fabric's {@code HudRenderCallback}.
*/
Event<RenderHud> RENDER_HUD = EventFactory.createLoop(RenderHud.class);
Event<DebugText> DEBUG_TEXT_LEFT = EventFactory.createLoop(DebugText.class);
Event<DebugText> DEBUG_TEXT_RIGHT = EventFactory.createLoop(DebugText.class);
Event<RenderHud> RENDER_HUD = EventFactory.createLoop();
Event<DebugText> DEBUG_TEXT_LEFT = EventFactory.createLoop();
Event<DebugText> DEBUG_TEXT_RIGHT = EventFactory.createLoop();
/**
* Invoked during Screen#init after previous widgets are cleared, equivalent to forge's {@code GuiScreenEvent.InitGuiEvent.Pre}.
*/
Event<ScreenInitPre> INIT_PRE = EventFactory.createInteractionResult(ScreenInitPre.class);
Event<ScreenInitPre> INIT_PRE = EventFactory.createInteractionResult();
/**
* Invoked after Screen#init, equivalent to forge's {@code GuiScreenEvent.InitGuiEvent.Post}.
*/
Event<ScreenInitPost> INIT_POST = EventFactory.createLoop(ScreenInitPost.class);
Event<ScreenRenderPre> RENDER_PRE = EventFactory.createInteractionResult(ScreenRenderPre.class);
Event<ScreenRenderPost> RENDER_POST = EventFactory.createInteractionResult(ScreenRenderPost.class);
Event<ScreenInitPost> INIT_POST = EventFactory.createLoop();
Event<ScreenRenderPre> RENDER_PRE = EventFactory.createInteractionResult();
Event<ScreenRenderPost> RENDER_POST = EventFactory.createInteractionResult();
/**
* Invoked during Minecraft#setScreen, equivalent to forge's {@code GuiOpenEvent}.
*/
Event<SetScreen> SET_SCREEN = EventFactory.createInteractionResultHolder();
@Environment(EnvType.CLIENT)
interface RenderHud {
@@ -79,4 +85,9 @@ public interface GuiEvent {
interface ScreenRenderPost {
void render(Screen screen, PoseStack matrices, int mouseX, int mouseY, float delta);
}
@Environment(EnvType.CLIENT)
interface SetScreen {
InteractionResultHolder<Screen> modifyScreen(Screen screen);
}
}

View File

@@ -32,12 +32,12 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
public interface InteractionEvent {
Event<LeftClickBlock> LEFT_CLICK_BLOCK = EventFactory.createInteractionResult(LeftClickBlock.class);
Event<RightClickBlock> RIGHT_CLICK_BLOCK = EventFactory.createInteractionResult(RightClickBlock.class);
Event<RightClickItem> RIGHT_CLICK_ITEM = EventFactory.createInteractionResultHolder(RightClickItem.class);
Event<ClientLeftClickAir> CLIENT_LEFT_CLICK_AIR = EventFactory.createLoop(ClientLeftClickAir.class);
Event<ClientRightClickAir> CLIENT_RIGHT_CLICK_AIR = EventFactory.createLoop(ClientRightClickAir.class);
Event<InteractEntity> INTERACT_ENTITY = EventFactory.createInteractionResult(InteractEntity.class);
Event<LeftClickBlock> LEFT_CLICK_BLOCK = EventFactory.createInteractionResult();
Event<RightClickBlock> RIGHT_CLICK_BLOCK = EventFactory.createInteractionResult();
Event<RightClickItem> RIGHT_CLICK_ITEM = EventFactory.createInteractionResultHolder();
Event<ClientLeftClickAir> CLIENT_LEFT_CLICK_AIR = EventFactory.createLoop();
Event<ClientRightClickAir> CLIENT_RIGHT_CLICK_AIR = EventFactory.createLoop();
Event<InteractEntity> INTERACT_ENTITY = EventFactory.createInteractionResult();
interface RightClickBlock {
InteractionResult click(Player player, InteractionHand hand, BlockPos pos, Direction face);

View File

@@ -29,35 +29,35 @@ public interface LifecycleEvent {
/**
* Invoked when server is starting, equivalent to forge's {@code FMLServerAboutToStartEvent} and fabric's {@code ServerLifecycleEvents#SERVER_STARTING}.
*/
Event<ServerState> SERVER_BEFORE_START = EventFactory.createLoop(ServerState.class);
Event<ServerState> SERVER_BEFORE_START = EventFactory.createLoop();
/**
* Invoked when server is starting, equivalent to forge's {@code FMLServerStartingEvent}.
*/
Event<ServerState> SERVER_STARTING = EventFactory.createLoop(ServerState.class);
Event<ServerState> SERVER_STARTING = EventFactory.createLoop();
/**
* Invoked when server has started, equivalent to forge's {@code FMLServerStartedEvent} and fabric's {@code ServerLifecycleEvents#SERVER_STARTED}.
*/
Event<ServerState> SERVER_STARTED = EventFactory.createLoop(ServerState.class);
Event<ServerState> SERVER_STARTED = EventFactory.createLoop();
/**
* Invoked when server is stopping, equivalent to forge's {@code FMLServerStoppingEvent} and fabric's {@code ServerLifecycleEvents#SERVER_STOPPING}.
*/
Event<ServerState> SERVER_STOPPING = EventFactory.createLoop(ServerState.class);
Event<ServerState> SERVER_STOPPING = EventFactory.createLoop();
/**
* Invoked when server has stopped, equivalent to forge's {@code FMLServerStoppedEvent} and fabric's {@code ServerLifecycleEvents#SERVER_STOPPED}.
*/
Event<ServerState> SERVER_STOPPED = EventFactory.createLoop(ServerState.class);
Event<ServerState> SERVER_STOPPED = EventFactory.createLoop();
/**
* Invoked after a world is loaded only on server, equivalent to forge's {@code WorldEvent.Load} and fabric's {@code ServerWorldEvents#LOAD}.
*/
Event<ServerWorldState> SERVER_WORLD_LOAD = EventFactory.createLoop(ServerWorldState.class);
Event<ServerWorldState> SERVER_WORLD_LOAD = EventFactory.createLoop();
/**
* Invoked after a world is unloaded, equivalent to forge's {@code WorldEvent.Unload} and fabric's {@code ServerWorldEvents#UNLOAD}.
*/
Event<ServerWorldState> SERVER_WORLD_UNLOAD = EventFactory.createLoop(ServerWorldState.class);
Event<ServerWorldState> SERVER_WORLD_UNLOAD = EventFactory.createLoop();
/**
* Invoked during a world is saved, equivalent to forge's {@code WorldEvent.Save}.
*/
Event<ServerWorldState> SERVER_WORLD_SAVE = EventFactory.createLoop(ServerWorldState.class);
Event<ServerWorldState> SERVER_WORLD_SAVE = EventFactory.createLoop();
interface InstanceState<T> {
void stateChanged(T instance);

View File

@@ -24,6 +24,7 @@ import me.shedaniel.architectury.event.EventFactory;
import me.shedaniel.architectury.utils.IntValue;
import net.minecraft.advancements.Advancement;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Container;
import net.minecraft.world.InteractionResult;
@@ -36,19 +37,20 @@ import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
public interface PlayerEvent {
Event<PlayerJoin> PLAYER_JOIN = EventFactory.createLoop(PlayerJoin.class);
Event<PlayerQuit> PLAYER_QUIT = EventFactory.createLoop(PlayerQuit.class);
Event<PlayerRespawn> PLAYER_RESPAWN = EventFactory.createLoop(PlayerRespawn.class);
Event<PlayerAdvancement> PLAYER_ADVANCEMENT = EventFactory.createLoop(PlayerAdvancement.class);
Event<PlayerClone> PLAYER_CLONE = EventFactory.createLoop(PlayerClone.class);
Event<CraftItem> CRAFT_ITEM = EventFactory.createLoop(CraftItem.class);
Event<SmeltItem> SMELT_ITEM = EventFactory.createLoop(SmeltItem.class);
Event<PickupItemPredicate> PICKUP_ITEM_PRE = EventFactory.createInteractionResult(PickupItemPredicate.class);
Event<PickupItem> PICKUP_ITEM_POST = EventFactory.createLoop(PickupItem.class);
Event<DropItem> DROP_ITEM = EventFactory.createLoop(DropItem.class);
Event<OpenMenu> OPEN_MENU = EventFactory.createLoop(OpenMenu.class);
Event<CloseMenu> CLOSE_MENU = EventFactory.createLoop(CloseMenu.class);
Event<BreakBlock> BREAK_BLOCK = EventFactory.createInteractionResult(BreakBlock.class);
Event<PlayerJoin> PLAYER_JOIN = EventFactory.createLoop();
Event<PlayerQuit> PLAYER_QUIT = EventFactory.createLoop();
Event<PlayerRespawn> PLAYER_RESPAWN = EventFactory.createLoop();
Event<PlayerAdvancement> PLAYER_ADVANCEMENT = EventFactory.createLoop();
Event<PlayerClone> PLAYER_CLONE = EventFactory.createLoop();
Event<CraftItem> CRAFT_ITEM = EventFactory.createLoop();
Event<SmeltItem> SMELT_ITEM = EventFactory.createLoop();
Event<PickupItemPredicate> PICKUP_ITEM_PRE = EventFactory.createInteractionResult();
Event<PickupItem> PICKUP_ITEM_POST = EventFactory.createLoop();
Event<ChangeDimension> CHANGE_DIMENSION = EventFactory.createLoop();
Event<DropItem> DROP_ITEM = EventFactory.createLoop();
Event<OpenMenu> OPEN_MENU = EventFactory.createLoop();
Event<CloseMenu> CLOSE_MENU = EventFactory.createLoop();
Event<BreakBlock> BREAK_BLOCK = EventFactory.createInteractionResult();
interface PlayerJoin {
void join(ServerPlayer player);
@@ -86,6 +88,10 @@ public interface PlayerEvent {
void pickup(Player player, ItemEntity entity, ItemStack stack);
}
interface ChangeDimension {
void change(ServerPlayer player, ResourceKey<Level> oldLevel, ResourceKey<Level> newLevel);
}
interface DropItem {
InteractionResult drop(Player player, ItemEntity entity);
}

View File

@@ -27,7 +27,7 @@ import net.minecraft.world.item.crafting.RecipeManager;
@Environment(EnvType.CLIENT)
public interface RecipeUpdateEvent {
Event<RecipeUpdateEvent> EVENT = EventFactory.createLoop(RecipeUpdateEvent.class);
Event<RecipeUpdateEvent> EVENT = EventFactory.createLoop();
void update(RecipeManager recipeManager);
}

View File

@@ -30,8 +30,8 @@ import java.util.function.Consumer;
@Environment(EnvType.CLIENT)
public interface TextureStitchEvent {
Event<Pre> PRE = EventFactory.createLoop(Pre.class);
Event<Post> POST = EventFactory.createLoop(Post.class);
Event<Pre> PRE = EventFactory.createLoop();
Event<Post> POST = EventFactory.createLoop();
@Environment(EnvType.CLIENT)
interface Pre {

View File

@@ -26,12 +26,12 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
public interface TickEvent<T> {
Event<Server> SERVER_PRE = EventFactory.createLoop(Server.class);
Event<Server> SERVER_POST = EventFactory.createLoop(Server.class);
Event<ServerWorld> SERVER_WORLD_PRE = EventFactory.createLoop(ServerWorld.class);
Event<ServerWorld> SERVER_WORLD_POST = EventFactory.createLoop(ServerWorld.class);
Event<Player> PLAYER_PRE = EventFactory.createLoop(Player.class);
Event<Player> PLAYER_POST = EventFactory.createLoop(Player.class);
Event<Server> SERVER_PRE = EventFactory.createLoop();
Event<Server> SERVER_POST = EventFactory.createLoop();
Event<ServerWorld> SERVER_WORLD_PRE = EventFactory.createLoop();
Event<ServerWorld> SERVER_WORLD_POST = EventFactory.createLoop();
Event<Player> PLAYER_PRE = EventFactory.createLoop();
Event<Player> PLAYER_POST = EventFactory.createLoop();
void tick(T instance);

View File

@@ -35,17 +35,17 @@ import java.util.List;
@Environment(EnvType.CLIENT)
public interface TooltipEvent {
Event<Item> ITEM = EventFactory.createLoop(Item.class);
Event<Item> ITEM = EventFactory.createLoop();
/**
* Render vanilla events are not invoked on the forge side.
*/
Event<RenderVanilla> RENDER_VANILLA_PRE = EventFactory.createInteractionResult(RenderVanilla.class);
Event<RenderVanilla> RENDER_VANILLA_PRE = EventFactory.createInteractionResult();
/**
* Render forge events are only invoked on the forge side.
*/
Event<RenderForge> RENDER_FORGE_PRE = EventFactory.createInteractionResult(RenderForge.class);
Event<RenderModifyPosition> RENDER_MODIFY_POSITION = EventFactory.createInteractionResult(RenderModifyPosition.class);
Event<RenderModifyColor> RENDER_MODIFY_COLOR = EventFactory.createInteractionResult(RenderModifyColor.class);
Event<RenderForge> RENDER_FORGE_PRE = EventFactory.createInteractionResult();
Event<RenderModifyPosition> RENDER_MODIFY_POSITION = EventFactory.createInteractionResult();
Event<RenderModifyColor> RENDER_MODIFY_COLOR = EventFactory.createInteractionResult();
@Environment(EnvType.CLIENT)
interface Item {

View File

@@ -36,11 +36,11 @@ public interface ClientChatEvent {
/**
* Invoked when client tries to send a message, equivalent to forge's {@code ClientChatEvent}.
*/
Event<Client> CLIENT = EventFactory.createInteractionResultHolder(Client.class);
Event<Client> CLIENT = EventFactory.createInteractionResultHolder();
/**
* Invoked when client receives a message, equivalent to forge's {@code ClientChatReceivedEvent}.
*/
Event<ClientReceived> CLIENT_RECEIVED = EventFactory.createInteractionResultHolder(ClientReceived.class);
Event<ClientReceived> CLIENT_RECEIVED = EventFactory.createInteractionResultHolder();
@Environment(EnvType.CLIENT)
interface Client {

View File

@@ -32,17 +32,17 @@ public interface ClientLifecycleEvent {
/**
* Invoked when client has been initialised, not available in forge.
*/
@Deprecated Event<ClientState> CLIENT_STARTED = EventFactory.createLoop(ClientState.class);
@Deprecated Event<ClientState> CLIENT_STARTED = EventFactory.createLoop();
/**
* Invoked when client is initialising, not available in forge.
*/
@Deprecated Event<ClientState> CLIENT_STOPPING = EventFactory.createLoop(ClientState.class);
@Deprecated Event<ClientState> CLIENT_STOPPING = EventFactory.createLoop();
/**
* Invoked after a world is loaded only on client, equivalent to forge's {@code WorldEvent.Load}.
*/
Event<ClientWorldState> CLIENT_WORLD_LOAD = EventFactory.createLoop(ClientWorldState.class);
Event<ClientWorldState> CLIENT_WORLD_LOAD = EventFactory.createLoop();
Event<ClientState> CLIENT_SETUP = EventFactory.createLoop();
@Deprecated
@Environment(EnvType.CLIENT)
interface ClientState extends LifecycleEvent.InstanceState<Minecraft> {}

View File

@@ -24,12 +24,13 @@ import me.shedaniel.architectury.event.EventFactory;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.player.LocalPlayer;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public interface ClientPlayerEvent {
Event<ClientPlayerJoin> CLIENT_PLAYER_JOIN = EventFactory.createLoop(ClientPlayerJoin.class);
Event<ClientPlayerQuit> CLIENT_PLAYER_QUIT = EventFactory.createLoop(ClientPlayerQuit.class);
Event<ClientPlayerRespawn> CLIENT_PLAYER_RESPAWN = EventFactory.createLoop(ClientPlayerRespawn.class);
Event<ClientPlayerJoin> CLIENT_PLAYER_JOIN = EventFactory.createLoop();
Event<ClientPlayerQuit> CLIENT_PLAYER_QUIT = EventFactory.createLoop();
Event<ClientPlayerRespawn> CLIENT_PLAYER_RESPAWN = EventFactory.createLoop();
@Environment(EnvType.CLIENT)
interface ClientPlayerJoin {
@@ -38,7 +39,7 @@ public interface ClientPlayerEvent {
@Environment(EnvType.CLIENT)
interface ClientPlayerQuit {
void quit(LocalPlayer player);
void quit(@Nullable LocalPlayer player);
}
@Environment(EnvType.CLIENT)

View File

@@ -0,0 +1,59 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.event.events.client;
import me.shedaniel.architectury.event.Event;
import me.shedaniel.architectury.event.EventFactory;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.world.InteractionResult;
@Environment(EnvType.CLIENT)
public interface ClientRawInputEvent {
/**
* Invoked after the mouse has scrolled, but doesn't have a screen opened, and in a world, equivalent to forge's {@code InputEvent.MouseScrollEvent}.
*/
Event<MouseScrolled> MOUSE_SCROLLED = EventFactory.createInteractionResult();
/**
* Invoked after the mouse has clicked, before the screen intercepts, equivalent to forge's {@code InputEvent.RawMouseEvent}.
*/
Event<MouseClicked> MOUSE_CLICKED_PRE = EventFactory.createInteractionResult();
/**
* Invoked after the mouse has clicked, after the screen intercepts, equivalent to forge's {@code InputEvent.MouseInputEvent}.
*/
Event<MouseClicked> MOUSE_CLICKED_POST = EventFactory.createInteractionResult();
/**
* Invoked after a key was pressed, after the screen intercepts, equivalent to forge's {@code InputEvent.KeyInputEvent}.
*/
Event<KeyPressed> KEY_PRESSED = EventFactory.createInteractionResult();
interface KeyPressed {
InteractionResult keyPressed(Minecraft client, int keyCode, int scanCode, int action, int modifiers);
}
interface MouseScrolled {
InteractionResult mouseScrolled(Minecraft client, double amount);
}
interface MouseClicked {
InteractionResult mouseClicked(Minecraft client, int button, int action, int mods);
}
}

View File

@@ -29,20 +29,20 @@ import net.minecraft.world.InteractionResult;
@Environment(EnvType.CLIENT)
public interface ClientScreenInputEvent {
Event<MouseScrolled> MOUSE_SCROLLED_PRE = EventFactory.createInteractionResult(MouseScrolled.class);
Event<MouseScrolled> MOUSE_SCROLLED_POST = EventFactory.createInteractionResult(MouseScrolled.class);
Event<MouseClicked> MOUSE_CLICKED_PRE = EventFactory.createInteractionResult(MouseClicked.class);
Event<MouseClicked> MOUSE_CLICKED_POST = EventFactory.createInteractionResult(MouseClicked.class);
Event<MouseReleased> MOUSE_RELEASED_PRE = EventFactory.createInteractionResult(MouseReleased.class);
Event<MouseReleased> MOUSE_RELEASED_POST = EventFactory.createInteractionResult(MouseReleased.class);
Event<MouseDragged> MOUSE_DRAGGED_PRE = EventFactory.createInteractionResult(MouseDragged.class);
Event<MouseDragged> MOUSE_DRAGGED_POST = EventFactory.createInteractionResult(MouseDragged.class);
Event<KeyTyped> CHAR_TYPED_PRE = EventFactory.createInteractionResult(KeyTyped.class);
Event<KeyTyped> CHAR_TYPED_POST = EventFactory.createInteractionResult(KeyTyped.class);
Event<KeyPressed> KEY_PRESSED_PRE = EventFactory.createInteractionResult(KeyPressed.class);
Event<KeyPressed> KEY_PRESSED_POST = EventFactory.createInteractionResult(KeyPressed.class);
Event<KeyReleased> KEY_RELEASED_PRE = EventFactory.createInteractionResult(KeyReleased.class);
Event<KeyReleased> KEY_RELEASED_POST = EventFactory.createInteractionResult(KeyReleased.class);
Event<MouseScrolled> MOUSE_SCROLLED_PRE = EventFactory.createInteractionResult();
Event<MouseScrolled> MOUSE_SCROLLED_POST = EventFactory.createInteractionResult();
Event<MouseClicked> MOUSE_CLICKED_PRE = EventFactory.createInteractionResult();
Event<MouseClicked> MOUSE_CLICKED_POST = EventFactory.createInteractionResult();
Event<MouseReleased> MOUSE_RELEASED_PRE = EventFactory.createInteractionResult();
Event<MouseReleased> MOUSE_RELEASED_POST = EventFactory.createInteractionResult();
Event<MouseDragged> MOUSE_DRAGGED_PRE = EventFactory.createInteractionResult();
Event<MouseDragged> MOUSE_DRAGGED_POST = EventFactory.createInteractionResult();
Event<KeyTyped> CHAR_TYPED_PRE = EventFactory.createInteractionResult();
Event<KeyTyped> CHAR_TYPED_POST = EventFactory.createInteractionResult();
Event<KeyPressed> KEY_PRESSED_PRE = EventFactory.createInteractionResult();
Event<KeyPressed> KEY_PRESSED_POST = EventFactory.createInteractionResult();
Event<KeyReleased> KEY_RELEASED_PRE = EventFactory.createInteractionResult();
Event<KeyReleased> KEY_RELEASED_POST = EventFactory.createInteractionResult();
interface KeyPressed {
InteractionResult keyPressed(Minecraft client, Screen screen, int keyCode, int scanCode, int modifiers);

View File

@@ -28,10 +28,10 @@ import net.minecraft.client.multiplayer.ClientLevel;
@Environment(EnvType.CLIENT)
public interface ClientTickEvent<T> {
Event<Client> CLIENT_PRE = EventFactory.createLoop(Client.class);
Event<Client> CLIENT_POST = EventFactory.createLoop(Client.class);
Event<ClientWorld> CLIENT_WORLD_PRE = EventFactory.createLoop(ClientWorld.class);
Event<ClientWorld> CLIENT_WORLD_POST = EventFactory.createLoop(ClientWorld.class);
Event<Client> CLIENT_PRE = EventFactory.createLoop();
Event<Client> CLIENT_POST = EventFactory.createLoop();
Event<ClientWorld> CLIENT_WORLD_PRE = EventFactory.createLoop();
Event<ClientWorld> CLIENT_WORLD_POST = EventFactory.createLoop();
void tick(T instance);

View File

@@ -0,0 +1,54 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.extensions;
import me.shedaniel.architectury.hooks.BlockEntityHooks;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* Extensions to {@link net.minecraft.world.level.block.entity.BlockEntity}, implement this on to your class.
*/
public interface BlockEntityExtension {
/**
* Handles data sent by {@link BlockEntityExtension#saveClientData(CompoundTag)} on the server.
*/
@Environment(EnvType.CLIENT)
void loadClientData(@NotNull BlockState pos, @NotNull CompoundTag tag);
/**
* Writes data to sync to the client.
*/
@NotNull
CompoundTag saveClientData(@NotNull CompoundTag tag);
/**
* Sync data to the clients by {@link BlockEntityExtension#saveClientData(CompoundTag)} and {@link BlockEntityExtension#loadClientData(BlockState, CompoundTag)}.
*/
@ApiStatus.NonExtendable
default void syncData() {
BlockEntityHooks.syncData((BlockEntity) this);
}
}

View File

@@ -0,0 +1,35 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.hooks;
import me.shedaniel.architectury.ExpectPlatform;
import net.minecraft.world.level.block.entity.BlockEntity;
public class BlockEntityHooks {
private BlockEntityHooks() {}
/**
* Sync data to the clients.
*/
@ExpectPlatform
public static void syncData(BlockEntity entity) {
throw new AssertionError();
}
}

View File

@@ -20,11 +20,8 @@
package me.shedaniel.architectury.hooks;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.world.entity.Entity;
@Environment(EnvType.CLIENT)
public final class EntityHooks {
private EntityHooks() {}

View File

@@ -20,14 +20,11 @@
package me.shedaniel.architectury.hooks;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public final class ExplosionHooks {
private ExplosionHooks() {}

View File

@@ -22,9 +22,18 @@ package me.shedaniel.architectury.hooks;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import me.shedaniel.architectury.fluid.FluidStack;
import me.shedaniel.architectury.utils.Fraction;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class FluidStackHooks {
private FluidStackHooks() {}
@@ -80,4 +89,64 @@ public class FluidStackHooks {
public static Fraction bucketAmount() {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@NotNull FluidStack stack) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@NotNull Fluid fluid) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@NotNull FluidStack stack) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@NotNull Fluid fluid) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
public static int getColor(@NotNull FluidStack stack) {
throw new AssertionError();
}
@ExpectPlatform
@Environment(EnvType.CLIENT)
public static int getColor(@NotNull Fluid fluid) {
throw new AssertionError();
}
}

View File

@@ -21,11 +21,8 @@ package me.shedaniel.architectury.hooks;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import me.shedaniel.architectury.utils.IntValue;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.world.entity.item.ItemEntity;
@Environment(EnvType.CLIENT)
public final class ItemEntityHooks {
private ItemEntityHooks() {}
@@ -38,4 +35,4 @@ public final class ItemEntityHooks {
public static IntValue lifespan(ItemEntity entity) {
throw new AssertionError();
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.hooks;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
public final class ItemStackHooks {
private ItemStackHooks() {}
public static ItemStack copyWithCount(ItemStack stack, int count) {
ItemStack copy = stack.copy();
copy.setCount(count);
return copy;
}
public static void giveItem(ServerPlayer player, ItemStack stack) {
boolean bl = player.inventory.add(stack);
if (bl && stack.isEmpty()) {
stack.setCount(1);
ItemEntity entity = player.drop(stack, false);
if (entity != null) {
entity.makeFakeItem();
}
player.level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, 0.2F, ((player.getRandom().nextFloat() - player.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F);
player.inventoryMenu.broadcastChanges();
} else {
ItemEntity entity = player.drop(stack, false);
if (entity != null) {
entity.setNoPickUpDelay();
entity.setOwner(player.getUUID());
}
}
}
}

View File

@@ -0,0 +1,30 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.hooks;
import net.minecraft.world.level.storage.LevelResource;
public class LevelResourceHooks {
private LevelResourceHooks() {}
public static LevelResource create(String id) {
return new LevelResource(id);
}
}

View File

@@ -20,11 +20,8 @@
package me.shedaniel.architectury.hooks;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.world.entity.player.Player;
@Environment(EnvType.CLIENT)
public final class PlayerHooks {
private PlayerHooks() {}

View File

@@ -19,11 +19,9 @@
package me.shedaniel.architectury.networking;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.google.common.collect.Maps;
import com.mojang.datafixers.util.Pair;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import me.shedaniel.architectury.networking.NetworkManager.PacketContext;
import me.shedaniel.architectury.platform.Platform;
import me.shedaniel.architectury.utils.Env;
@@ -34,8 +32,9 @@ import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.BiConsumer;
@@ -47,8 +46,7 @@ import java.util.function.Supplier;
*/
public final class NetworkChannel {
private final ResourceLocation id;
private final IntSet takenIds = new IntOpenHashSet();
private final Table<NetworkManager.Side, Class<?>, Pair<ResourceLocation, BiConsumer<?, FriendlyByteBuf>>> encoders = HashBasedTable.create();
private final Map<Class<?>, MessageInfo<?>> encoders = Maps.newHashMap();
private NetworkChannel(ResourceLocation id) {
this.id = id;
@@ -58,57 +56,68 @@ public final class NetworkChannel {
return new NetworkChannel(id);
}
@Deprecated
public <T> void register(NetworkManager.Side side, Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
register(Optional.ofNullable(side), type, encoder, decoder, messageConsumer);
register(type, encoder, decoder, messageConsumer);
}
@Deprecated
public <T> void register(Optional<NetworkManager.Side> side, Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
for (int i = 0; true; i++) {
if (!takenIds.contains(i)) {
register(side, i, type, encoder, decoder, messageConsumer);
break;
}
register(type, encoder, decoder, messageConsumer);
}
public <T> void register(Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
String s = StringUtils.leftPad(String.valueOf(hashCodeString(type.toString())), 10, '0');
if (s.length() > 10) s = s.substring(0, 10);
MessageInfo<T> info = new MessageInfo<>(new ResourceLocation(id + "_" + s), encoder, decoder, messageConsumer);
encoders.put(type, info);
NetworkManager.NetworkReceiver receiver = (buf, context) -> {
info.messageConsumer.accept(info.decoder.apply(buf), () -> context);
};
NetworkManager.registerReceiver(NetworkManager.clientToServer(), info.packetId, receiver);
if (Platform.getEnvironment() == Env.CLIENT) {
NetworkManager.registerReceiver(NetworkManager.serverToClient(), info.packetId, receiver);
}
}
public static long hashCodeString(String str) {
long h = 0;
int length = str.length();
for (int i = 0; i < length; i++) {
h = 31 * h + str.charAt(i);
}
return h;
}
@Deprecated
public <T> void register(int id, Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
register(type, encoder, decoder, messageConsumer);
}
@Deprecated
public <T> void register(NetworkManager.Side side, int id, Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
register(Optional.ofNullable(side), id, type, encoder, decoder, messageConsumer);
register(type, encoder, decoder, messageConsumer);
}
@Deprecated
public <T> void register(Optional<NetworkManager.Side> side, int id, Class<T> type, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
takenIds.add(id);
ResourceLocation messageId = new ResourceLocation(this.id.getNamespace(), this.id.getPath() + "_" + id);
if (!side.isPresent() || side.get() == NetworkManager.s2c()) {
if (Platform.getEnvironment() == Env.CLIENT) {
NetworkManager.registerReceiver(NetworkManager.s2c(), messageId, (buf, context) -> {
messageConsumer.accept(decoder.apply(buf), () -> context);
});
}
encoders.put(NetworkManager.s2c(), type, Pair.of(messageId, encoder));
}
if (!side.isPresent() || side.get() == NetworkManager.c2s()) {
NetworkManager.registerReceiver(NetworkManager.c2s(), messageId, (buf, context) -> {
messageConsumer.accept(decoder.apply(buf), () -> context);
});
encoders.put(NetworkManager.c2s(), type, Pair.of(messageId, encoder));
}
register(type, encoder, decoder, messageConsumer);
}
private <T> Pair<ResourceLocation, FriendlyByteBuf> encode(NetworkManager.Side side, T message) {
Pair<ResourceLocation, BiConsumer<?, FriendlyByteBuf>> pair = Objects.requireNonNull(encoders.get(side, message.getClass()));
private <T> Pair<MessageInfo<T>, FriendlyByteBuf> encode(T message) {
MessageInfo<T> messageInfo = (MessageInfo<T>) Objects.requireNonNull(encoders.get(message.getClass()));
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
((BiConsumer<T, FriendlyByteBuf>) pair.getRight()).accept(message, buf);
return Pair.of(pair.getLeft(), buf);
messageInfo.encoder.accept(message, buf);
return new Pair<>(messageInfo, buf);
}
public <T> Packet<?> toPacket(NetworkManager.Side side, T message) {
Pair<ResourceLocation, FriendlyByteBuf> encoded = encode(side, message);
return NetworkManager.toPacket(side, encoded.getLeft(), encoded.getRight());
Pair<MessageInfo<T>, FriendlyByteBuf> encoded = encode(message);
return NetworkManager.toPacket(side, encoded.getFirst().packetId, encoded.getSecond());
}
public <T> void sendToPlayer(ServerPlayer player, T message) {
Pair<ResourceLocation, FriendlyByteBuf> encoded = encode(NetworkManager.s2c(), message);
NetworkManager.sendToPlayer(player, encoded.getLeft(), encoded.getRight());
player.connection.send(toPacket(NetworkManager.s2c(), message));
}
public <T> void sendToPlayers(Iterable<ServerPlayer> players, T message) {
@@ -125,10 +134,24 @@ public final class NetworkChannel {
@Environment(EnvType.CLIENT)
public <T> boolean canServerReceive(Class<T> type) {
return NetworkManager.canServerReceive(encoders.get(NetworkManager.c2s(), type).getLeft());
return NetworkManager.canServerReceive(encoders.get(type).packetId);
}
public <T> boolean canPlayerReceive(ServerPlayer player, Class<T> type) {
return NetworkManager.canPlayerReceive(player, encoders.get(NetworkManager.s2c(), type).getLeft());
return NetworkManager.canPlayerReceive(player, encoders.get(type).packetId);
}
private static final class MessageInfo<T> {
private final ResourceLocation packetId;
private final BiConsumer<T, FriendlyByteBuf> encoder;
private final Function<FriendlyByteBuf, T> decoder;
private final BiConsumer<T, Supplier<PacketContext>> messageConsumer;
public MessageInfo(ResourceLocation packetId, BiConsumer<T, FriendlyByteBuf> encoder, Function<FriendlyByteBuf, T> decoder, BiConsumer<T, Supplier<PacketContext>> messageConsumer) {
this.packetId = packetId;
this.encoder = encoder;
this.decoder = decoder;
this.messageConsumer = messageConsumer;
}
}
}

View File

@@ -27,17 +27,40 @@ import net.minecraft.client.color.item.ItemColor;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Block;
import java.util.Objects;
import java.util.function.Supplier;
@Environment(EnvType.CLIENT)
public final class ColorHandlers {
private ColorHandlers() {}
@ExpectPlatform
public static void registerItemColors(ItemColor color, ItemLike... items) {
Supplier<ItemLike>[] array = new Supplier[items.length];
for (int i = 0; i < items.length; i++) {
ItemLike item = Objects.requireNonNull(items[i], "items[i] is null!");
array[i] = () -> item;
}
registerItemColors(color, array);
}
public static void registerBlockColors(BlockColor color, Block... blocks) {
Supplier<Block>[] array = new Supplier[blocks.length];
for (int i = 0; i < blocks.length; i++) {
Block block = Objects.requireNonNull(blocks[i], "blocks[i] is null!");
array[i] = () -> block;
}
registerBlockColors(color, array);
}
@SafeVarargs
@ExpectPlatform
public static void registerItemColors(ItemColor color, Supplier<ItemLike>... items) {
throw new AssertionError();
}
@SafeVarargs
@ExpectPlatform
public static void registerBlockColors(BlockColor color, Block... blocks) {
public static void registerBlockColors(BlockColor color, Supplier<Block>... blocks) {
throw new AssertionError();
}
}

View File

@@ -70,7 +70,7 @@ public class DeferredRegister<T> {
return create(registries::get, key);
}
public RegistrySupplier<T> register(String id, Supplier<T> supplier) {
public <R extends T> RegistrySupplier<R> register(String id, Supplier<? extends R> supplier) {
if (modId == null) {
throw new NullPointerException("You must create the deferred register with a mod id to register entries without the namespace!");
}
@@ -78,14 +78,14 @@ public class DeferredRegister<T> {
return register(new ResourceLocation(modId, id), supplier);
}
public RegistrySupplier<T> register(ResourceLocation id, Supplier<T> supplier) {
Entry<T> entry = new Entry<>(id, supplier);
public <R extends T> RegistrySupplier<R> register(ResourceLocation id, Supplier<? extends R> supplier) {
Entry<T> entry = new Entry<>(id, (Supplier<T>) supplier);
this.entries.add(entry);
if (registered) {
Registry<T> registry = registriesSupplier.get().get(key);
entry.value = registry.registerSupplied(entry.id, entry.supplier);
}
return entry;
return (RegistrySupplier<R>) entry;
}
public void register() {

View File

@@ -0,0 +1,79 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.GameRules;
import java.util.function.BiConsumer;
/**
* A utility class for creating game rule types.
*/
public final class GameRuleFactory {
private GameRuleFactory() {}
/**
* Creates a boolean rule type.
*
* @param defaultValue the rule's default value
* @return the created type
*/
@ExpectPlatform
public static GameRules.Type<GameRules.BooleanValue> createBooleanRule(boolean defaultValue) {
throw new AssertionError();
}
/**
* Creates a boolean rule type.
*
* @param defaultValue the rule's default value
* @param changedCallback a callback that is called when the rule's value is changed
* @return the created type
*/
@ExpectPlatform
public static GameRules.Type<GameRules.BooleanValue> createBooleanRule(boolean defaultValue, BiConsumer<MinecraftServer, GameRules.BooleanValue> changedCallback) {
throw new AssertionError();
}
/**
* Creates an integer rule type.
*
* @param defaultValue the rule's default value
* @return the created type
*/
@ExpectPlatform
public static GameRules.Type<GameRules.IntegerValue> createIntRule(int defaultValue) {
throw new AssertionError();
}
/**
* Creates an integer rule type.
*
* @param defaultValue the rule's default value
* @param changedCallback a callback that is called when the rule's value is changed
* @return the created type
*/
@ExpectPlatform
public static GameRules.Type<GameRules.IntegerValue> createIntRule(int defaultValue, BiConsumer<MinecraftServer, GameRules.IntegerValue> changedCallback) {
throw new AssertionError();
}
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import net.minecraft.world.level.GameRules;
/**
* A registry for registering game rules.
*/
public final class GameRuleRegistry {
private GameRuleRegistry() {}
/**
* Registers a game rule.
*
* @param name the rule's name
* @param category the rule category
* @param type the type of the rule
* @param <T> the type of the rule value
* @return a key for the registered rule
*/
@ExpectPlatform
public static <T extends GameRules.Value<T>> GameRules.Key<T> register(String name, GameRules.Category category, GameRules.Type<T> type) {
throw new AssertionError();
}
}

View File

@@ -20,9 +20,12 @@
package me.shedaniel.architectury.registry;
import me.shedaniel.architectury.annotations.ExpectPlatform;
import me.shedaniel.architectury.core.RegistryEntry;
import me.shedaniel.architectury.registry.registries.RegistryBuilder;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
@@ -36,6 +39,7 @@ public final class Registries {
private final RegistryProvider provider;
private final String modId;
@NotNull
public static Registries get(String modId) {
return REGISTRIES.computeIfAbsent(modId, Registries::new);
}
@@ -45,15 +49,24 @@ public final class Registries {
this.modId = modId;
}
@NotNull
public <T> Registry<T> get(ResourceKey<net.minecraft.core.Registry<T>> key) {
return this.provider.get(key);
}
@NotNull
@Deprecated
public <T> Registry<T> get(net.minecraft.core.Registry<T> registry) {
return this.provider.get(registry);
}
@NotNull
@SafeVarargs
public final <T extends RegistryEntry<T>> RegistryBuilder<T> builder(ResourceLocation registryId, T... typeGetter) {
if (typeGetter.length != 0) throw new IllegalStateException("array must be empty!");
return this.provider.builder((Class<T>) typeGetter.getClass().getComponentType(), registryId);
}
/**
* Forge: If the object is {@code IForgeRegistryEntry}, use `getRegistryName`, else null
* Fabric: Use registry
@@ -79,8 +92,8 @@ public final class Registries {
* Forge: If the object is {@code IForgeRegistryEntry}, use `getRegistryName`, else null
* Fabric: null
*/
@Deprecated
@Nullable
@Deprecated
public static <T> ResourceLocation getRegistryName(T object) {
return getId(object, (ResourceKey<net.minecraft.core.Registry<T>>) null);
}
@@ -90,6 +103,7 @@ public final class Registries {
throw new AssertionError();
}
@NotNull
public String getModId() {
return modId;
}
@@ -100,5 +114,7 @@ public final class Registries {
@Deprecated
<T> Registry<T> get(net.minecraft.core.Registry<T> registry);
<T extends RegistryEntry<T>> RegistryBuilder<T> builder(Class<T> type, ResourceLocation registryId);
}
}

View File

@@ -49,11 +49,16 @@ public interface Registry<T> extends Iterable<T> {
@Nullable
ResourceLocation getId(T obj);
int getRawId(T obj);
Optional<ResourceKey<T>> getKey(T obj);
@Nullable
T get(ResourceLocation id);
@Nullable
T byRawId(int rawId);
boolean contains(ResourceLocation id);
boolean containsValue(T obj);

View File

@@ -29,12 +29,21 @@ import java.util.function.Supplier;
import java.util.stream.Stream;
public interface RegistrySupplier<T> extends Supplier<T> {
/**
* @return the identifier of the registry
*/
@NotNull
ResourceLocation getRegistryId();
/**
* @return the identifier of the entry
*/
@NotNull
ResourceLocation getId();
/**
* @return whether the entry has been registered
*/
boolean isPresent();
@Nullable

View File

@@ -39,6 +39,5 @@ public final class RenderTypes {
public static void register(RenderType type, Fluid... fluids) {
throw new AssertionError();
}
}

View File

@@ -0,0 +1,42 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry.registries;
import me.shedaniel.architectury.core.RegistryEntry;
import me.shedaniel.architectury.registry.Registry;
import org.jetbrains.annotations.NotNull;
public interface RegistryBuilder<T extends RegistryEntry<T>> {
@NotNull
Registry<T> build();
@NotNull
RegistryBuilder<T> option(@NotNull RegistryOption option);
@NotNull
default RegistryBuilder<T> saveToDisc() {
return option(StandardRegistryOption.SAVE_TO_DISC);
}
@NotNull
default RegistryBuilder<T> syncToClients() {
return option(StandardRegistryOption.SYNC_TO_CLIENTS);
}
}

View File

@@ -0,0 +1,23 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry.registries;
public interface RegistryOption {
}

View File

@@ -0,0 +1,31 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry.registries;
public enum StandardRegistryOption implements RegistryOption {
/**
* Denote that the registry should save to disc and persist. Defaulted false.
*/
SAVE_TO_DISC,
/**
* Denote that the registry should sync its contents to clients. Defaulted false.
*/
SYNC_TO_CLIENTS,
}

View File

@@ -38,4 +38,5 @@ mutable field net/minecraft/world/level/biome/BiomeSpecialEffects ambientMoodSet
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects ambientAdditionsSettings Ljava/util/Optional;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects ambientAdditionsSettings Ljava/util/Optional;
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects backgroundMusic Ljava/util/Optional;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects backgroundMusic Ljava/util/Optional;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects backgroundMusic Ljava/util/Optional;
accessible method net/minecraft/world/level/storage/LevelResource <init> (Ljava/lang/String;)V

View File

@@ -1,8 +1,8 @@
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
import shadow.org.apache.tools.zip.ZipEntry
import shadow.org.codehaus.plexus.util.IOUtil
import shadow.org.apache.tools.zip.ZipOutputStream
import shadow.org.codehaus.plexus.util.IOUtil
plugins {
id "com.github.johnrengelman.shadow" version "5.0.0"
@@ -10,12 +10,16 @@ plugins {
}
loom {
accessWidener(file("src/main/resources/architectury.accessWidener"))
silentMojangMappingsLicense()
accessWidener = file("src/main/resources/architectury.accessWidener")
}
configurations {
shadow
dev
}
artifacts {
dev(jar)
}
architectury {
@@ -23,25 +27,23 @@ architectury {
}
dependencies {
minecraft("com.mojang:minecraft:${rootProject.architect.minecraft}")
mappings(minecraft.officialMojangMappings())
modCompile("net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}")
modCompile("net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}")
modCompileOnly("io.github.prospector:modmenu:${rootProject.mod_menu_version}")
minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
mappings minecraft.officialMojangMappings()
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
modCompileOnly "io.github.prospector:modmenu:${rootProject.mod_menu_version}"
implementation "net.jodah:typetools:0.6.2"
shadow "net.jodah:typetools:0.6.2"
compileOnly(project(path: ":common")) {
transitive = false
}
runtimeOnly(project(path: ":common", configuration: "transformed")) {
runtimeOnly(project(path: ":common", configuration: "transformDevelopmentFabric")) {
transitive = false
}
shadow(project(path: ":common", configuration: "transformed")) {
shadow(project(path: ":common", configuration: "transformProductionFabric")) {
transitive = false
}
testCompile project(":common").sourceSets.test.output
}
processResources {
@@ -53,9 +55,6 @@ processResources {
shadowJar {
relocate "net.jodah.typetools", "me.shedaniel.architectury.shadowed.impl.net.jodah.typetools"
transform(MergeAccessWidenersTransformer.class) {
it.resource = "architectury.accessWidener"
}
configurations = [project.configurations.shadow]
classifier "shadow"
}
@@ -75,6 +74,18 @@ publishing {
}
}
}
repositories {
if (System.getenv("MAVEN_PASS") != null) {
maven {
url = "https://deploy.shedaniel.me/"
credentials {
username = "shedaniel"
password = System.getenv("MAVEN_PASS")
}
}
}
}
}
curseforge {
@@ -87,6 +98,7 @@ curseforge {
changelog = releaseChangelog()
addGameVersion "1.16-Snapshot"
addGameVersion "1.16.4"
addGameVersion "1.16.5"
addGameVersion "Java 8"
addGameVersion "Fabric"
relations {
@@ -107,53 +119,3 @@ curseforge {
}
rootProject.tasks.getByName("curseforgePublish").dependsOn tasks.getByName("curseforge")
class MergeAccessWidenersTransformer implements Transformer {
String resource
ByteArrayOutputStream data
MergeAccessWidenersTransformer() {
data = new ByteArrayOutputStream()
data.write("accessWidener v1 named\n".bytes)
}
@Override
boolean canTransformResource(FileTreeElement element) {
def path = element.relativePath.pathString
if (resource != null && resource.equalsIgnoreCase(path)) {
return true
}
return false
}
@Override
void transform(TransformerContext context) {
def lines = context.is.readLines()
lines.removeIf { it == "accessWidener v1 named" }
IOUtil.copy(lines.join("\n"), data)
data.write('\n'.bytes)
context.is.close()
}
@Override
boolean hasTransformedResource() {
return data.size() > 0
}
void modifyOutputStream(org.apache.tools.zip.ZipOutputStream jos, boolean preserveFileTimestamps) {
throw new AbstractMethodError()
}
@Override
void modifyOutputStream(ZipOutputStream os, boolean preserveFileTimestamps) {
ZipEntry entry = new ZipEntry(resource)
entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time)
os.putNextEntry(entry)
IOUtil.copy(new ByteArrayInputStream(data.toByteArray()), os)
data.reset()
data.write('accessWidener v1 named\n'.bytes)
}
}

View File

@@ -0,0 +1,58 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.hooks.fabric;
import com.google.common.base.Preconditions;
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import java.util.Objects;
public class BlockEntityHooksImpl {
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* 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.
*/
public static void syncData(BlockEntity entity) {
if (entity instanceof BlockEntityClientSerializable) {
((BlockEntityClientSerializable) entity).sync();
} else {
Level world = Objects.requireNonNull(entity.getLevel());
if (!(world instanceof ServerLevel)) {
throw new IllegalStateException("Cannot call sync() on the logical client! Did you check world.isClient first?");
} else {
((ServerLevel) world).getChunkSource().blockChanged(entity.getBlockPos());
}
}
}
}

View File

@@ -26,14 +26,22 @@ import me.shedaniel.architectury.utils.Fraction;
import me.shedaniel.architectury.utils.NbtType;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandler;
import net.fabricmc.fabric.api.client.render.fluid.v1.FluidRenderHandlerRegistry;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
@@ -103,4 +111,86 @@ public class FluidStackHooksImpl {
public static Fraction bucketAmount() {
return Fraction.ofWhole(1);
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
TextureAtlasSprite[] sprites = FluidRenderHandlerRegistry.INSTANCE.get(state.getType()).getFluidSprites(level, pos, state);
if (sprites == null) return null;
return sprites[0];
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
TextureAtlasSprite[] sprites = FluidRenderHandlerRegistry.INSTANCE.get(stack.getFluid()).getFluidSprites(null, null, stack.getFluid().defaultFluidState());
if (sprites == null) return null;
return sprites[0];
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
TextureAtlasSprite[] sprites = FluidRenderHandlerRegistry.INSTANCE.get(fluid).getFluidSprites(null, null, fluid.defaultFluidState());
if (sprites == null) return null;
return sprites[0];
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(state.getType());
if (handler == null) return null;
TextureAtlasSprite[] sprites = handler.getFluidSprites(level, pos, state);
if (sprites == null) return null;
return sprites[1];
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(stack.getFluid());
if (handler == null) return null;
TextureAtlasSprite[] sprites = handler.getFluidSprites(null, null, stack.getFluid().defaultFluidState());
if (sprites == null) return null;
return sprites[1];
}
@Environment(EnvType.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
TextureAtlasSprite[] sprites = FluidRenderHandlerRegistry.INSTANCE.get(fluid).getFluidSprites(null, null, fluid.defaultFluidState());
if (sprites == null) return null;
return sprites[1];
}
@Environment(EnvType.CLIENT)
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
if (state.getType() == Fluids.EMPTY) return -1;
FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(state.getType());
if (handler == null) return -1;
return handler.getFluidColor(level, pos, state);
}
@Environment(EnvType.CLIENT)
public static int getColor(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return -1;
FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(stack.getFluid());
if (handler == null) return -1;
return handler.getFluidColor(null, null, stack.getFluid().defaultFluidState());
}
@Environment(EnvType.CLIENT)
public static int getColor(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return -1;
FluidRenderHandler handler = FluidRenderHandlerRegistry.INSTANCE.get(fluid);
if (handler == null) return -1;
return handler.getFluidColor(null, null, fluid.defaultFluidState());
}
}

View File

@@ -0,0 +1,29 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.init.fabric;
import me.shedaniel.architectury.event.events.client.ClientLifecycleEvent;
import net.minecraft.client.Minecraft;
public class ArchitecturyClient {
public static void init() {
ClientLifecycleEvent.CLIENT_SETUP.invoker().stateChanged(Minecraft.getInstance());
}
}

View File

@@ -0,0 +1,54 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.mixin.fabric;
import me.shedaniel.architectury.extensions.BlockEntityExtension;
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(BlockEntityExtension.class)
public interface MixinBlockEntityExtension extends BlockEntityClientSerializable {
@Shadow(remap = false)
@NotNull
CompoundTag saveClientData(@NotNull CompoundTag tag);
@Shadow(remap = false)
void loadClientData(@NotNull BlockState pos, @NotNull CompoundTag tag);
@Override
default void fromClientTag(CompoundTag tag) {
BlockEntity entity = (BlockEntity) this;
if (entity.hasLevel()) {
entity.setLevelAndPosition(entity.getLevel(), new BlockPos(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")));
loadClientData(entity.getBlockState(), tag);
}
}
@Override
default CompoundTag toClientTag(CompoundTag tag) {
return saveClientData(tag);
}
}

View File

@@ -20,6 +20,7 @@
package me.shedaniel.architectury.mixin.fabric;
import me.shedaniel.architectury.event.events.PlayerEvent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Container;
import net.minecraft.world.MenuProvider;
@@ -57,4 +58,9 @@ public class MixinServerPlayer {
private void doCloseContainer(CallbackInfo ci) {
PlayerEvent.CLOSE_MENU.invoker().close((ServerPlayer) (Object) this, ((ServerPlayer) (Object) this).containerMenu);
}
@Inject(method = "triggerDimensionChangeTriggers", at = @At("HEAD"))
private void changeDimension(ServerLevel serverLevel, CallbackInfo ci) {
PlayerEvent.CHANGE_DIMENSION.invoker().change((ServerPlayer) (Object) this, serverLevel.dimension(), ((ServerPlayer) (Object) this).level.dimension());
}
}

View File

@@ -0,0 +1,57 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.mixin.fabric.client;
import com.mojang.blaze3d.shaders.Program;
import net.minecraft.client.renderer.EffectInstance;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Unique
@Mixin(value = EffectInstance.class, priority = 950)
public class MixinEffectInstance {
@Redirect(
method = "<init>",
at = @At(value = "NEW",
target = "(Ljava/lang/String;)Lnet/minecraft/resources/ResourceLocation;",
ordinal = 0)
)
private ResourceLocation mojangPls(String _0, ResourceManager rm, String str) {
return mojangPls(new ResourceLocation(str), ".json");
}
@Redirect(
method = "getOrCreate",
at = @At(value = "NEW",
target = "(Ljava/lang/String;)Lnet/minecraft/resources/ResourceLocation;",
ordinal = 0)
)
private static ResourceLocation mojangPls(String _0, ResourceManager rm, Program.Type type, String str) {
return mojangPls(new ResourceLocation(str), type.getExtension());
}
private static ResourceLocation mojangPls(ResourceLocation rl, String ext) {
return new ResourceLocation(rl.getNamespace(), "shaders/program/" + rl.getPath() + ext);
}
}

View File

@@ -19,6 +19,7 @@
package me.shedaniel.architectury.mixin.fabric.client;
import me.shedaniel.architectury.event.events.client.ClientRawInputEvent;
import me.shedaniel.architectury.event.events.client.ClientScreenInputEvent;
import me.shedaniel.architectury.impl.fabric.ScreenInputDelegate;
import net.minecraft.client.KeyboardHandler;
@@ -111,4 +112,13 @@ public class MixinKeyboardHandler {
info.cancel();
}
}
@Inject(method = "keyPress", at = @At("RETURN"), cancellable = true)
public void onRawKey(long handle, int key, int scanCode, int action, int modifiers, CallbackInfo info) {
if (handle == this.minecraft.getWindow().getWindow()) {
InteractionResult result = ClientRawInputEvent.KEY_PRESSED.invoker().keyPressed(minecraft, key, scanCode, action, modifiers);
if (result != InteractionResult.PASS)
info.cancel();
}
}
}

View File

@@ -19,34 +19,49 @@
package me.shedaniel.architectury.mixin.fabric.client;
import me.shedaniel.architectury.event.events.GuiEvent;
import me.shedaniel.architectury.event.events.InteractionEvent;
import me.shedaniel.architectury.event.events.client.ClientPlayerEvent;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.ConnectScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.client.main.GameConfig;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.HitResult;
import org.jetbrains.annotations.Nullable;
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.Unique;
import org.spongepowered.asm.mixin.injection.*;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.io.File;
@Unique
@Mixin(Minecraft.class)
public class MixinMinecraft {
public abstract class MixinMinecraft {
// @formatter:off
@Shadow @Nullable public LocalPlayer player;
@Shadow @Nullable public HitResult hitResult;
@Shadow public abstract void setScreen(@Nullable Screen screen);
private boolean setScreenCancelled;
private String hostname;
private int port;
// @formatter:on
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/chat/NarratorChatListener;clear()V"))
private void handleLogin(Screen screen, CallbackInfo ci) {
if (player != null) {
ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player);
}
ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player);
}
@Inject(method = "startUseItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", ordinal = 1),
@@ -61,4 +76,78 @@ public class MixinMinecraft {
private void leftClickAir(CallbackInfo ci) {
InteractionEvent.CLIENT_LEFT_CLICK_AIR.invoker().click(player, InteractionHand.MAIN_HAND);
}
@ModifyVariable(
method = "setScreen",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/player/LocalPlayer;respawn()V",
shift = At.Shift.BY,
by = 2),
argsOnly = true
)
public Screen modifyScreen(Screen screen) {
Screen old = screen;
InteractionResultHolder<Screen> event = GuiEvent.SET_SCREEN.invoker().modifyScreen(screen);
switch (event.getResult()) {
case FAIL:
setScreenCancelled = true;
return old;
case SUCCESS:
screen = event.getObject();
if (old != null && screen != old) {
old.removed();
}
default:
setScreenCancelled = false;
return screen;
}
}
@Inject(
method = "setScreen",
at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/player/LocalPlayer;respawn()V",
shift = At.Shift.BY,
by = 3),
cancellable = true
)
public void cancelSetScreen(@Nullable Screen screen, CallbackInfo ci) {
if (setScreenCancelled) {
ci.cancel();
}
}
@Redirect(
method = "<init>",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V"),
slice = @Slice(
from = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;resizeDisplay()V"),
to = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/LoadingOverlay;registerTextures(Lnet/minecraft/client/Minecraft;)V")
)
)
public void minecraftWhy(Minecraft mc, Screen screen) {
}
@Inject(
method = "<init>",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;resizeDisplay()V"),
locals = LocalCapture.CAPTURE_FAILHARD
)
public void saveLocals(GameConfig gc, CallbackInfo ci, File f, String string2, int j) {
hostname = string2;
port = j;
}
@SuppressWarnings({"UnresolvedMixinReference", "ConstantConditions"})
@Inject(
method = {"method_29338", "lambda$null$1"}, // <init>.lambda$null$1
at = @At("RETURN")
)
public void registerMainScreens(CallbackInfo ci) {
if (hostname != null) {
setScreen(new ConnectScreen(new TitleScreen(), (Minecraft) ((Object) this), hostname, port));
} else {
setScreen(new TitleScreen(true));
}
}
}

View File

@@ -19,6 +19,7 @@
package me.shedaniel.architectury.mixin.fabric.client;
import me.shedaniel.architectury.event.events.client.ClientRawInputEvent;
import me.shedaniel.architectury.event.events.client.ClientScreenInputEvent;
import me.shedaniel.architectury.impl.fabric.ScreenInputDelegate;
import net.minecraft.client.Minecraft;
@@ -52,7 +53,7 @@ public class MixinMouseHandler {
@Inject(method = "onScroll",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseScrolled(DDD)Z",
ordinal = 0), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
public void onMouseScrolled(long long_1, double double_1, double double_2, CallbackInfo info, double amount, double x, double y) {
public void onMouseScrolled(long handle, double xOffset, double yOffset, CallbackInfo info, double amount, double x, double y) {
if (!info.isCancelled()) {
InteractionResult result = ClientScreenInputEvent.MOUSE_SCROLLED_PRE.invoker().mouseScrolled(minecraft, minecraft.screen, x, y, amount);
if (result != InteractionResult.PASS)
@@ -63,29 +64,62 @@ public class MixinMouseHandler {
@Inject(method = "onScroll",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseScrolled(DDD)Z",
ordinal = 0, shift = At.Shift.AFTER), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
public void onMouseScrolledPost(long long_1, double double_1, double double_2, CallbackInfo info, double amount, double x, double y) {
public void onMouseScrolledPost(long handle, double xOffset, double yOffset, CallbackInfo info, double amount, double x, double y) {
if (!info.isCancelled()) {
InteractionResult result = ClientScreenInputEvent.MOUSE_SCROLLED_POST.invoker().mouseScrolled(minecraft, minecraft.screen, x, y, amount);
}
}
@Inject(method = "onPress", at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/gui/screens/Screen;wrapScreenError(Ljava/lang/Runnable;Ljava/lang/String;Ljava/lang/String;)V",
ordinal = 0), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
public void onMouseClicked(long long_1, int button, int int_2, int int_3, CallbackInfo info, boolean bl, int i, boolean[] bls, double d, double e) {
@Inject(method = "onScroll",
at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;isSpectator()Z",
ordinal = 0), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
public void onRawMouseScrolled(long handle, double xOffset, double yOffset, CallbackInfo info, double amount) {
if (!info.isCancelled()) {
InteractionResult result = ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, minecraft.screen, d, e, button);
InteractionResult result = ClientRawInputEvent.MOUSE_SCROLLED.invoker().mouseScrolled(minecraft, amount);
if (result != InteractionResult.PASS)
info.cancel();
}
}
@Inject(method = "onPress", at = @At(value = "INVOKE",
target = "Lnet/minecraft/client/gui/screens/Screen;wrapScreenError(Ljava/lang/Runnable;Ljava/lang/String;Ljava/lang/String;)V",
ordinal = 0, shift = At.Shift.AFTER), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD)
public void onMouseClickedPost(long long_1, int button, int int_2, int int_3, CallbackInfo info, boolean bl, int i, boolean[] bls, double d, double e) {
@SuppressWarnings("UnresolvedMixinReference")
@Inject(method = {"lambda$onPress$0", "method_1611"}, at = @At("HEAD"), cancellable = true, remap = false)
public void onGuiMouseClicked(boolean[] bls, double d, double e, int button, CallbackInfo info) {
if (!info.isCancelled()) {
InteractionResult result = ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, minecraft.screen, d, e, button);
if (result != InteractionResult.PASS) {
bls[0] = true;
info.cancel();
}
}
}
@SuppressWarnings("UnresolvedMixinReference")
@Inject(method = {"lambda$onPress$0", "method_1611"}, at = @At("RETURN"), cancellable = true, remap = false)
public void onGuiMouseClickedPost(boolean[] bls, double d, double e, int button, CallbackInfo info) {
if (!info.isCancelled() && !bls[0]) {
InteractionResult result = ClientScreenInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(minecraft, minecraft.screen, d, e, button);
if (result != InteractionResult.PASS) {
bls[0] = true;
info.cancel();
}
}
}
@Inject(method = "onPress", at = @At(value = "FIELD",
target = "Lnet/minecraft/client/Minecraft;overlay:Lnet/minecraft/client/gui/screens/Overlay;",
ordinal = 0), cancellable = true)
public void onRawMouseClicked(long handle, int button, int action, int mods, CallbackInfo info) {
if (!info.isCancelled()) {
InteractionResult result = ClientRawInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, button, action, mods);
if (result != InteractionResult.PASS)
info.cancel();
}
}
@Inject(method = "onPress", at = @At("RETURN"), cancellable = true)
public void onRawMouseClickedPost(long handle, int button, int action, int mods, CallbackInfo info) {
if (handle == this.minecraft.getWindow().getWindow()) {
InteractionResult result = ClientRawInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(minecraft, button, action, mods);
if (result != InteractionResult.PASS)
info.cancel();
}

View File

@@ -0,0 +1,52 @@
package me.shedaniel.architectury.plugin.fabric;
import net.fabricmc.loader.api.FabricLoader;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.List;
import java.util.Set;
public class ArchitecturyMixinPlugin implements IMixinConfigPlugin {
@Override
public void onLoad(String mixinPackage) {
// noop
}
@Override
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
switch (mixinClassName) {
case "me.shedaniel.architectury.mixin.fabric.client.MixinEffectInstance":
return !FabricLoader.getInstance().isModLoaded("satin");
default:
return true;
}
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
// noop
}
@Override
public List<String> getMixins() {
return null;
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
// noop
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
// noop
}
}

View File

@@ -25,12 +25,35 @@ import net.minecraft.client.color.item.ItemColor;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Block;
import java.util.Objects;
import java.util.function.Supplier;
public class ColorHandlersImpl {
public static void registerItemColors(ItemColor color, ItemLike... items) {
ColorProviderRegistry.ITEM.register(color, items);
@SafeVarargs
public static void registerItemColors(ItemColor itemColor, Supplier<ItemLike>... items) {
Objects.requireNonNull(itemColor, "color is null!");
ColorProviderRegistry.ITEM.register(itemColor, unpackItems(items));
}
public static void registerBlockColors(BlockColor color, Block... blocks) {
ColorProviderRegistry.BLOCK.register(color, blocks);
@SafeVarargs
public static void registerBlockColors(BlockColor blockColor, Supplier<Block>... blocks) {
Objects.requireNonNull(blockColor, "color is null!");
ColorProviderRegistry.BLOCK.register(blockColor, unpackBlocks(blocks));
}
private static ItemLike[] unpackItems(Supplier<ItemLike>[] items) {
ItemLike[] array = new ItemLike[items.length];
for (int i = 0; i < items.length; i++) {
array[i] = Objects.requireNonNull(items[i].get());
}
return array;
}
private static Block[] unpackBlocks(Supplier<Block>[] blocks) {
Block[] array = new Block[blocks.length];
for (int i = 0; i < blocks.length; i++) {
array[i] = Objects.requireNonNull(blocks[i].get());
}
return array;
}
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry.fabric;
import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.GameRules;
import java.util.function.BiConsumer;
public class GameRuleFactoryImpl {
public static GameRules.Type<GameRules.BooleanValue> createBooleanRule(boolean defaultValue) {
return GameRuleFactory.createBooleanRule(defaultValue);
}
public static GameRules.Type<GameRules.BooleanValue> createBooleanRule(boolean defaultValue, BiConsumer<MinecraftServer, GameRules.BooleanValue> changedCallback) {
return GameRuleFactory.createBooleanRule(defaultValue, changedCallback);
}
public static GameRules.Type<GameRules.IntegerValue> createIntRule(int defaultValue) {
return GameRuleFactory.createIntRule(defaultValue);
}
public static GameRules.Type<GameRules.IntegerValue> createIntRule(int defaultValue, BiConsumer<MinecraftServer, GameRules.IntegerValue> changedCallback) {
return GameRuleFactory.createIntRule(defaultValue, changedCallback);
}
}

View File

@@ -0,0 +1,29 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry.fabric;
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
import net.minecraft.world.level.GameRules;
public class GameRuleRegistryImpl {
public static <T extends GameRules.Value<T>> GameRules.Key<T> register(String name, GameRules.Category category, GameRules.Type<T> type) {
return GameRuleRegistry.register(name, category, type);
}
}

View File

@@ -40,7 +40,7 @@ import net.minecraft.world.inventory.MenuType;
import org.jetbrains.annotations.Nullable;
public class MenuRegistryImpl {
public static void openMenu(ServerPlayer player, ExtendedMenuProvider provider) {
public static void openExtendedMenu(ServerPlayer player, ExtendedMenuProvider provider) {
player.openMenu(new ExtendedScreenHandlerFactory() {
@Override
public void writeScreenOpeningData(ServerPlayer player, FriendlyByteBuf buf) {

View File

@@ -20,9 +20,16 @@
package me.shedaniel.architectury.registry.fabric;
import com.google.common.base.Objects;
import me.shedaniel.architectury.core.RegistryEntry;
import me.shedaniel.architectury.registry.Registries;
import me.shedaniel.architectury.registry.Registry;
import me.shedaniel.architectury.registry.RegistrySupplier;
import me.shedaniel.architectury.registry.registries.RegistryBuilder;
import me.shedaniel.architectury.registry.registries.RegistryOption;
import me.shedaniel.architectury.registry.registries.StandardRegistryOption;
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
import net.minecraft.core.MappedRegistry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.LazyLoadedValue;
@@ -64,6 +71,36 @@ public class RegistriesImpl {
public <T> Registry<T> get(net.minecraft.core.Registry<T> registry) {
return new RegistryImpl<>(registry);
}
@Override
@NotNull
public <T extends RegistryEntry<T>> RegistryBuilder<T> builder(Class<T> type, ResourceLocation registryId) {
return new RegistryBuilderWrapper<>(FabricRegistryBuilder.createSimple(type, registryId));
}
}
public static class RegistryBuilderWrapper<T extends RegistryEntry<T>> implements RegistryBuilder<T> {
@NotNull
private FabricRegistryBuilder<T, MappedRegistry<T>> builder;
public RegistryBuilderWrapper(@NotNull FabricRegistryBuilder<T, MappedRegistry<T>> builder) {
this.builder = builder;
}
@Override
public @NotNull Registry<T> build() {
return RegistryProviderImpl.INSTANCE.get(builder.buildAndRegister());
}
@Override
public @NotNull RegistryBuilder<T> option(@NotNull RegistryOption option) {
if (option == StandardRegistryOption.SAVE_TO_DISC) {
this.builder.attribute(RegistryAttribute.PERSISTED);
} else if (option == StandardRegistryOption.SYNC_TO_CLIENTS) {
this.builder.attribute(RegistryAttribute.SYNCED);
}
return this;
}
}
public static class RegistryImpl<T> implements Registry<T> {
@@ -128,6 +165,11 @@ public class RegistriesImpl {
return delegate.getKey(obj);
}
@Override
public int getRawId(T obj) {
return delegate.getId(obj);
}
@Override
public Optional<ResourceKey<T>> getKey(T obj) {
return delegate.getResourceKey(obj);
@@ -138,9 +180,14 @@ public class RegistriesImpl {
return delegate.get(id);
}
@Override
public T byRawId(int rawId) {
return delegate.byId(rawId);
}
@Override
public boolean contains(ResourceLocation id) {
return delegate.containsKey(id);
return delegate.keySet().contains(id);
}
@Override

View File

@@ -39,7 +39,7 @@ public class ReloadListenersImpl {
public static void registerReloadListener(PackType type, PreparableReloadListener listener) {
byte[] bytes = new byte[8];
RANDOM.nextBytes(bytes);
ResourceLocation id = new ResourceLocation("architectury:reload_" + StringUtils.leftPad(Math.abs(Longs.fromByteArray(bytes)) + "", 19));
ResourceLocation id = new ResourceLocation("architectury:reload_" + StringUtils.leftPad(Math.abs(Longs.fromByteArray(bytes)) + "", 19, '0'));
ResourceManagerHelper.get(type).registerReloadListener(new IdentifiableResourceReloadListener() {
@Override
public ResourceLocation getFabricId() {

View File

@@ -54,4 +54,45 @@ accessible field net/minecraft/world/item/DyeColor textureDiffuseColor I
accessible method net/minecraft/world/entity/player/Player closeContainer ()V
accessible method net/minecraft/advancements/CriteriaTriggers register (Lnet/minecraft/advancements/CriterionTrigger;)Lnet/minecraft/advancements/CriterionTrigger;
accessible method net/minecraft/world/inventory/MenuType <init> (Lnet/minecraft/world/inventory/MenuType$MenuSupplier;)V
accessible class net/minecraft/world/inventory/MenuType$MenuSupplier
accessible class net/minecraft/world/inventory/MenuType$MenuSupplier
accessible method net/minecraft/world/level/block/state/BlockBehaviour$Properties <init> (Lnet/minecraft/world/level/material/Material;Ljava/util/function/Function;)V
accessible field net/minecraft/world/level/biome/Biome climateSettings Lnet/minecraft/world/level/biome/Biome$ClimateSettings;
accessible field net/minecraft/world/level/biome/Biome depth F
mutable field net/minecraft/world/level/biome/Biome depth F
accessible field net/minecraft/world/level/biome/Biome scale F
mutable field net/minecraft/world/level/biome/Biome scale F
accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecraft/world/level/biome/Biome$BiomeCategory;
mutable field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecraft/world/level/biome/Biome$BiomeCategory;
accessible field net/minecraft/world/level/biome/Biome$ClimateSettings precipitation Lnet/minecraft/world/level/biome/Biome$Precipitation;
mutable field net/minecraft/world/level/biome/Biome$ClimateSettings precipitation Lnet/minecraft/world/level/biome/Biome$Precipitation;
accessible field net/minecraft/world/level/biome/Biome$ClimateSettings temperature F
mutable field net/minecraft/world/level/biome/Biome$ClimateSettings temperature F
accessible field net/minecraft/world/level/biome/Biome$ClimateSettings temperatureModifier Lnet/minecraft/world/level/biome/Biome$TemperatureModifier;
mutable field net/minecraft/world/level/biome/Biome$ClimateSettings temperatureModifier Lnet/minecraft/world/level/biome/Biome$TemperatureModifier;
accessible field net/minecraft/world/level/biome/Biome$ClimateSettings downfall F
mutable field net/minecraft/world/level/biome/Biome$ClimateSettings downfall F
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects fogColor I
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects fogColor I
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects waterColor I
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects waterColor I
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects waterFogColor I
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects waterFogColor I
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects skyColor I
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects skyColor I
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects foliageColorOverride Ljava/util/Optional;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects foliageColorOverride Ljava/util/Optional;
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects grassColorOverride Ljava/util/Optional;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects grassColorOverride Ljava/util/Optional;
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects grassColorModifier Lnet/minecraft/world/level/biome/BiomeSpecialEffects$GrassColorModifier;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects grassColorModifier Lnet/minecraft/world/level/biome/BiomeSpecialEffects$GrassColorModifier;
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects ambientParticleSettings Ljava/util/Optional;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects ambientParticleSettings Ljava/util/Optional;
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects ambientLoopSoundEvent Ljava/util/Optional;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects ambientLoopSoundEvent Ljava/util/Optional;
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects ambientMoodSettings Ljava/util/Optional;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects ambientMoodSettings Ljava/util/Optional;
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects ambientAdditionsSettings Ljava/util/Optional;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects ambientAdditionsSettings Ljava/util/Optional;
accessible field net/minecraft/world/level/biome/BiomeSpecialEffects backgroundMusic Ljava/util/Optional;
mutable field net/minecraft/world/level/biome/BiomeSpecialEffects backgroundMusic Ljava/util/Optional;
accessible method net/minecraft/world/level/storage/LevelResource <init> (Ljava/lang/String;)V

View File

@@ -1,19 +1,45 @@
{
"required": true,
"package": "me.shedaniel.architectury.mixin.fabric",
"plugin": "me.shedaniel.architectury.plugin.fabric.ArchitecturyMixinPlugin",
"compatibilityLevel": "JAVA_8",
"minVersion": "0.7.11",
"client": [
"client.MixinClientLevel", "client.MixinClientPacketListener", "client.MixinDebugScreenOverlay", "client.MixinGameRenderer", "client.MixinIntegratedServer",
"client.MixinKeyboardHandler", "client.MixinMinecraft", "client.MixinMouseHandler", "client.MixinMultiPlayerGameMode", "client.MixinScreen",
"client.MixinClientLevel",
"client.MixinClientPacketListener",
"client.MixinDebugScreenOverlay",
"client.MixinEffectInstance",
"client.MixinGameRenderer",
"client.MixinIntegratedServer",
"client.MixinKeyboardHandler",
"client.MixinMinecraft",
"client.MixinMouseHandler",
"client.MixinMultiPlayerGameMode",
"client.MixinScreen",
"client.MixinTextureAtlas"
],
"mixins": [
"ExplosionPreInvoker", "LivingDeathInvoker", "MixinBlockItem", "MixinCommands", "MixinDedicatedServer", "MixinExplosion", "MixinFurnaceResultSlot",
"MixinItemEntity", "MixinLivingEntity", "MixinPersistentEntitySectionManager", "MixinPlayer", "MixinPlayerAdvancements", "MixinPlayerList",
"MixinResultSlot", "MixinServerGamePacketListenerImpl", "MixinServerLevel", "MixinServerPlayer", "MixinServerPlayerGameMode", "PlayerAttackInvoker"
"ExplosionPreInvoker",
"LivingDeathInvoker",
"MixinBlockEntityExtension",
"MixinBlockItem",
"MixinCommands",
"MixinDedicatedServer",
"MixinExplosion",
"MixinFurnaceResultSlot",
"MixinItemEntity",
"MixinLivingEntity",
"MixinPersistentEntitySectionManager", "MixinPlayer",
"MixinPlayerAdvancements",
"MixinPlayerList",
"MixinResultSlot",
"MixinServerGamePacketListenerImpl", "MixinServerLevel",
"MixinServerPlayer",
"MixinServerPlayerGameMode",
"PlayerAttackInvoker"
],
"injectors": {
"maxShiftBy": 5,
"defaultRequire": 1
}
}

View File

@@ -16,6 +16,9 @@
"main": [
"me.shedaniel.architectury.utils.fabric.GameInstanceImpl::init"
],
"client": [
"me.shedaniel.architectury.init.fabric.ArchitecturyClient::init"
],
"modmenu": [
"me.shedaniel.architectury.compat.fabric.ModMenuCompatibility"
]

View File

@@ -4,12 +4,16 @@ plugins {
}
loom {
silentMojangMappingsLicense()
mixinConfig = "architectury.mixins.json"
}
configurations {
shadow
dev
}
artifacts {
dev(jar)
}
architectury {
@@ -17,19 +21,19 @@ architectury {
}
dependencies {
minecraft("com.mojang:minecraft:${rootProject.architect.minecraft}")
mappings(minecraft.officialMojangMappings())
forge("net.minecraftforge:forge:${rootProject.architect.minecraft}-${rootProject.forge_version}")
minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
mappings loom.officialMojangMappings()
forge "net.minecraftforge:forge:${rootProject.architectury.minecraft}-${rootProject.forge_version}"
implementation "net.jodah:typetools:0.6.2"
shadow "net.jodah:typetools:0.6.2"
compileOnly(project(path: ":common")) {
transitive = false
}
runtimeOnly(project(path: ":common", configuration: "transformForgeFakeMod")) {
runtimeOnly(project(path: ":common", configuration: "transformDevelopmentForge")) {
transitive = false
}
shadow(project(path: ":common", configuration: "transformForge")) {
shadow(project(path: ":common", configuration: "transformProductionForge")) {
transitive = false
}
}
@@ -65,6 +69,18 @@ publishing {
}
}
}
repositories {
if (System.getenv("MAVEN_PASS") != null) {
maven {
url = "https://deploy.shedaniel.me/"
credentials {
username = "shedaniel"
password = System.getenv("MAVEN_PASS")
}
}
}
}
}
curseforge {
@@ -76,6 +92,7 @@ curseforge {
changelogType = "html"
changelog = releaseChangelog()
addGameVersion "1.16.4"
addGameVersion "1.16.5"
addGameVersion "Java 8"
addGameVersion "Forge"
mainArtifact(remapJar.archivePath) {
@@ -92,4 +109,4 @@ curseforge {
}
}
rootProject.tasks.getByName("curseforgePublish").dependsOn tasks.getByName("curseforge")
rootProject.tasks.getByName("curseforgePublish").dependsOn tasks.getByName("curseforge")

View File

@@ -27,6 +27,7 @@ import me.shedaniel.architectury.impl.TooltipEventColorContextImpl;
import me.shedaniel.architectury.impl.TooltipEventPositionContextImpl;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionResult;
@@ -38,6 +39,7 @@ import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import java.util.List;
@@ -123,6 +125,18 @@ public class EventHandlerImplClient {
}
}
@SubscribeEvent
public static void event(GuiOpenEvent event) {
InteractionResultHolder<Screen> result = GuiEvent.SET_SCREEN.invoker().modifyScreen(event.getGui());
switch (result.getResult()) {
case FAIL:
event.setCanceled(true);
return;
case SUCCESS:
event.setGui(result.getObject());
}
}
@SubscribeEvent
public static void event(GuiScreenEvent.DrawScreenEvent.Pre event) {
if (GuiEvent.RENDER_PRE.invoker().render(event.getGui(), event.getMatrixStack(), event.getMouseX(), event.getMouseY(), event.getRenderPartialTicks()) == InteractionResult.FAIL) {
@@ -264,6 +278,30 @@ public class EventHandlerImplClient {
ClientScreenInputEvent.KEY_RELEASED_POST.invoker().keyReleased(Minecraft.getInstance(), event.getGui(), event.getKeyCode(), event.getScanCode(), event.getModifiers());
}
@SubscribeEvent
public static void event(InputEvent.MouseScrollEvent event) {
if (ClientRawInputEvent.MOUSE_SCROLLED.invoker().mouseScrolled(Minecraft.getInstance(), event.getScrollDelta()) == InteractionResult.FAIL) {
event.setCanceled(true);
}
}
@SubscribeEvent
public static void event(InputEvent.RawMouseEvent event) {
if (ClientRawInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(Minecraft.getInstance(), event.getButton(), event.getAction(), event.getMods()) == InteractionResult.FAIL) {
event.setCanceled(true);
}
}
@SubscribeEvent
public static void event(InputEvent.MouseInputEvent event) {
ClientRawInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(Minecraft.getInstance(), event.getButton(), event.getAction(), event.getMods());
}
@SubscribeEvent
public static void event(InputEvent.KeyInputEvent event) {
ClientRawInputEvent.KEY_PRESSED.invoker().keyPressed(Minecraft.getInstance(), event.getKey(), event.getScanCode(), event.getAction(), event.getModifiers());
}
@OnlyIn(Dist.CLIENT)
public static class ModBasedEventHandler {
@SubscribeEvent
@@ -275,5 +313,10 @@ public class EventHandlerImplClient {
public static void event(net.minecraftforge.client.event.TextureStitchEvent.Post event) {
TextureStitchEvent.POST.invoker().stitch(event.getMap());
}
@SubscribeEvent
public static void event(FMLClientSetupEvent event) {
ClientLifecycleEvent.CLIENT_SETUP.invoker().stateChanged(event.getMinecraftSupplier().get());
}
}
}

View File

@@ -322,6 +322,13 @@ public class EventHandlerImplCommon {
LifecycleEvent.SERVER_BEFORE_START.invoker().stateChanged(event.getServer());
}
@SubscribeEvent
public static void event(PlayerChangedDimensionEvent event) {
if (event.getPlayer() instanceof ServerPlayer) {
PlayerEvent.CHANGE_DIMENSION.invoker().change((ServerPlayer) event.getPlayer(), event.getFrom(), event.getTo());
}
}
public static class ModBasedEventHandler {
}

View File

@@ -1,49 +0,0 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.event.forge;
import me.shedaniel.architectury.event.events.TextureStitchEvent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.eventbus.api.SubscribeEvent;
public class ModBasedEventHandlerImpl {
@OnlyIn(Dist.CLIENT)
public static class Client {
@SubscribeEvent
public static void event(net.minecraftforge.client.event.TextureStitchEvent.Pre event) {
TextureStitchEvent.PRE.invoker().stitch(event.getMap(), event::addSprite);
}
@SubscribeEvent
public static void event(net.minecraftforge.client.event.TextureStitchEvent.Post event) {
TextureStitchEvent.POST.invoker().stitch(event.getMap());
}
}
public static class Common {
}
@OnlyIn(Dist.DEDICATED_SERVER)
public static class Server {
}
}

View File

@@ -0,0 +1,52 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.hooks.forge;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import java.util.Objects;
public class BlockEntityHooksImpl {
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* 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.
*/
public static void syncData(BlockEntity entity) {
Level world = Objects.requireNonNull(entity.getLevel());
if (!(world instanceof ServerLevel)) {
throw new IllegalStateException("Cannot call sync() on the logical client! Did you check world.isClient first?");
} else {
((ServerLevel) world).getChunkSource().blockChanged(entity.getBlockPos());
}
}
}

View File

@@ -21,9 +21,22 @@ package me.shedaniel.architectury.hooks.forge;
import me.shedaniel.architectury.fluid.FluidStack;
import me.shedaniel.architectury.utils.Fraction;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class FluidStackHooksImpl {
public static Component getName(FluidStack stack) {
@@ -53,4 +66,70 @@ public class FluidStackHooksImpl {
public static Fraction bucketAmount() {
return Fraction.ofWhole(1000);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
ResourceLocation texture = state.getType().getAttributes().getStillTexture(level, pos);
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
ResourceLocation texture = stack.getFluid().getAttributes().getStillTexture(FluidStackHooksForge.toForge(stack));
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getStillTexture(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
ResourceLocation texture = fluid.getAttributes().getStillTexture();
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
if (state.getType() == Fluids.EMPTY) return null;
ResourceLocation texture = state.getType().getAttributes().getFlowingTexture(level, pos);
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return null;
ResourceLocation texture = stack.getFluid().getAttributes().getFlowingTexture(FluidStackHooksForge.toForge(stack));
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
@Nullable
public static TextureAtlasSprite getFlowingTexture(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return null;
ResourceLocation texture = fluid.getAttributes().getFlowingTexture();
return Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(texture);
}
@OnlyIn(Dist.CLIENT)
public static int getColor(@Nullable BlockAndTintGetter level, @Nullable BlockPos pos, @NotNull FluidState state) {
if (state.getType() == Fluids.EMPTY) return -1;
return state.getType().getAttributes().getColor(level, pos);
}
@OnlyIn(Dist.CLIENT)
public static int getColor(@NotNull FluidStack stack) {
if (stack.getFluid() == Fluids.EMPTY) return -1;
return stack.getFluid().getAttributes().getColor(FluidStackHooksForge.toForge(stack));
}
@OnlyIn(Dist.CLIENT)
public static int getColor(@NotNull Fluid fluid) {
if (fluid == Fluids.EMPTY) return -1;
return fluid.getAttributes().getColor();
}
}

View File

@@ -0,0 +1,52 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.mixin.forge;
import me.shedaniel.architectury.extensions.BlockEntityExtension;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.level.block.entity.BlockEntity;
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;
@Mixin(BlockEntity.class)
public abstract class MixinBlockEntity {
@Inject(method = "getUpdatePacket", at = @At("HEAD"), cancellable = true)
public void getUpdatePacket(CallbackInfoReturnable<ClientboundBlockEntityDataPacket> cir) {
if (this instanceof BlockEntityExtension) {
BlockEntityExtension entity = (BlockEntityExtension) this;
BlockEntity be = (BlockEntity) entity;
cir.setReturnValue(new ClientboundBlockEntityDataPacket(be.getBlockPos(), 10, be.getUpdateTag()));
cir.cancel();
}
}
@Inject(method = "getUpdateTag", at = @At("HEAD"), cancellable = true)
public void getUpdateTag(CallbackInfoReturnable<CompoundTag> cir) {
if (this instanceof BlockEntityExtension) {
BlockEntityExtension entity = (BlockEntityExtension) this;
BlockEntity be = (BlockEntity) entity;
cir.setReturnValue(entity.saveClientData(new CompoundTag()));
cir.cancel();
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.mixin.forge;
import me.shedaniel.architectury.extensions.BlockEntityExtension;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.extensions.IForgeTileEntity;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(BlockEntityExtension.class)
public interface MixinBlockEntityExtension extends IForgeTileEntity {
@Shadow(remap = false)
void loadClientData(@NotNull BlockState pos, @NotNull CompoundTag tag);
@Override
default void handleUpdateTag(BlockState state, CompoundTag tag) {
loadClientData(state, tag);
}
}

View File

@@ -0,0 +1,27 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.mixin.forge;
import me.shedaniel.architectury.core.RegistryEntry;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(RegistryEntry.class)
public class MixinRegistryEntry<T> {
}

View File

@@ -41,6 +41,8 @@ import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.event.EventNetworkChannel;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
import java.util.Map;
@@ -63,6 +65,7 @@ public class NetworkManagerImpl {
return (side == NetworkManager.Side.C2S ? NetworkDirection.PLAY_TO_SERVER : NetworkDirection.PLAY_TO_CLIENT).buildPacket(Pair.of(packetBuffer, 0), CHANNEL_ID).getThis();
}
private static final Logger LOGGER = LogManager.getLogger();
private static final ResourceLocation CHANNEL_ID = new ResourceLocation("architectury:network");
static final ResourceLocation SYNC_IDS = new ResourceLocation("architectury:sync_ids");
static final EventNetworkChannel CHANNEL = NetworkRegistry.newEventChannel(CHANNEL_ID, () -> "1", version -> true, version -> true);
@@ -94,7 +97,8 @@ public class NetworkManagerImpl {
if (event.getClass() != clazz) return;
NetworkEvent.Context context = event.getSource().get();
if (context.getPacketHandled()) return;
FriendlyByteBuf buffer = new FriendlyByteBuf(event.getPayload().copy());
FriendlyByteBuf buffer = event.getPayload();
if (buffer == null) return;
ResourceLocation type = buffer.readResourceLocation();
NetworkReceiver receiver = map.get(type);
@@ -119,7 +123,10 @@ public class NetworkManagerImpl {
return DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> ClientNetworkingManager::getClientPlayer);
}
});
} else {
LOGGER.error("Unknown message ID: " + type);
}
context.setPacketHandled(true);
};
}

View File

@@ -21,15 +21,14 @@ package me.shedaniel.architectury.platform.forge;
import net.minecraftforge.eventbus.api.IEventBus;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.function.Consumer;
public final class EventBuses {
private EventBuses() {}
private static final Map<String, IEventBus> EVENT_BUS_MAP = new HashMap<>();
private static final Map<String, List<Consumer<IEventBus>>> ON_REGISTERED = new HashMap<>();
public static void registerModEventBus(String modId, IEventBus bus) {
IEventBus previous = EVENT_BUS_MAP.put(modId, bus);
@@ -37,6 +36,20 @@ public final class EventBuses {
EVENT_BUS_MAP.put(modId, previous);
throw new IllegalStateException("Can't register event bus for mod '" + modId + "' because it was previously registered!");
}
for (Consumer<IEventBus> runnable : ON_REGISTERED.getOrDefault(modId, Collections.emptyList())) {
runnable.accept(bus);
}
}
public static void onRegistered(String modId, Consumer<IEventBus> busConsumer) {
if (EVENT_BUS_MAP.containsKey(modId)) {
busConsumer.accept(EVENT_BUS_MAP.get(modId));
} else {
synchronized (ON_REGISTERED) {
ON_REGISTERED.computeIfAbsent(modId, s -> new ArrayList<>()).add(busConsumer);
}
}
}
public static Optional<IEventBus> getModEventBus(String modId) {

View File

@@ -0,0 +1,88 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.plugin.forge;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.List;
import java.util.Objects;
import java.util.Set;
public class ArchitecturyMixinPlugin implements IMixinConfigPlugin {
@Override
public void onLoad(String mixinPackage) {
}
@Override
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return true;
}
@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
}
@Override
public List<String> getMixins() {
return null;
}
@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
// Inject our own sugar
switch (mixinClassName) {
case "me.shedaniel.architectury.mixin.forge.MixinRegistryEntry":
targetClass.superName = "net/minecraftforge/registries/ForgeRegistryEntry";
for (MethodNode method : targetClass.methods) {
if (Objects.equals(method.name, "<init>")) {
for (AbstractInsnNode insnNode : method.instructions) {
if (insnNode.getOpcode() == Opcodes.INVOKESPECIAL && insnNode instanceof MethodInsnNode) {
MethodInsnNode node = (MethodInsnNode) insnNode;
if (Objects.equals(node.name, "<init>") && Objects.equals(node.owner, "java/lang/Object")) {
node.owner = "net/minecraftforge/registries/ForgeRegistryEntry";
break;
}
}
}
}
}
targetClass.signature = "<T::Lnet/minecraftforge/registries/IForgeRegistryEntry<TT;>;>Lnet/minecraftforge/registries/ForgeRegistryEntry<TT;>;";
break;
}
}
@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
}
}

View File

@@ -20,47 +20,72 @@
package me.shedaniel.architectury.registry.forge;
import com.google.common.collect.Lists;
import me.shedaniel.architectury.forge.ArchitecturyForge;
import me.shedaniel.architectury.platform.forge.EventBuses;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockColor;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.client.event.ColorHandlerEvent;
import net.minecraftforge.common.MinecraftForge;
import org.apache.commons.lang3.tuple.Pair;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
public class ColorHandlersImpl {
private static final List<Pair<ItemColor, ItemLike[]>> ITEM_COLORS = Lists.newArrayList();
private static final List<Pair<BlockColor, Block[]>> BLOCK_COLORS = Lists.newArrayList();
private static final List<Pair<ItemColor, Supplier<ItemLike>[]>> ITEM_COLORS = Lists.newArrayList();
private static final List<Pair<BlockColor, Supplier<Block>[]>> BLOCK_COLORS = Lists.newArrayList();
static {
MinecraftForge.EVENT_BUS.<ColorHandlerEvent.Item>addListener(event -> {
for (Pair<ItemColor, ItemLike[]> pair : ITEM_COLORS) {
event.getItemColors().register(pair.getLeft(), pair.getRight());
}
});
MinecraftForge.EVENT_BUS.<ColorHandlerEvent.Block>addListener(event -> {
for (Pair<BlockColor, Block[]> pair : BLOCK_COLORS) {
event.getBlockColors().register(pair.getLeft(), pair.getRight());
}
EventBuses.onRegistered(ArchitecturyForge.MOD_ID, bus -> {
bus.<ColorHandlerEvent.Item>addListener(event -> {
for (Pair<ItemColor, Supplier<ItemLike>[]> pair : ITEM_COLORS) {
event.getItemColors().register(pair.getLeft(), unpackItems(pair.getRight()));
}
});
bus.<ColorHandlerEvent.Block>addListener(event -> {
for (Pair<BlockColor, Supplier<Block>[]> pair : BLOCK_COLORS) {
event.getBlockColors().register(pair.getLeft(), unpackBlocks(pair.getRight()));
}
});
});
}
public static void registerItemColors(ItemColor itemColor, ItemLike... items) {
@SafeVarargs
public static void registerItemColors(ItemColor itemColor, Supplier<ItemLike>... items) {
Objects.requireNonNull(itemColor, "color is null!");
if (Minecraft.getInstance().getItemColors() == null) {
ITEM_COLORS.add(Pair.of(itemColor, items));
} else {
Minecraft.getInstance().getItemColors().register(itemColor, items);
Minecraft.getInstance().getItemColors().register(itemColor, unpackItems(items));
}
}
public static void registerBlockColors(BlockColor blockColor, Block... blocks) {
@SafeVarargs
public static void registerBlockColors(BlockColor blockColor, Supplier<Block>... blocks) {
Objects.requireNonNull(blockColor, "color is null!");
if (Minecraft.getInstance().getBlockColors() == null) {
BLOCK_COLORS.add(Pair.of(blockColor, blocks));
} else {
Minecraft.getInstance().getBlockColors().register(blockColor, blocks);
Minecraft.getInstance().getBlockColors().register(blockColor, unpackBlocks(blocks));
}
}
private static ItemLike[] unpackItems(Supplier<ItemLike>[] items) {
ItemLike[] array = new ItemLike[items.length];
for (int i = 0; i < items.length; i++) {
array[i] = Objects.requireNonNull(items[i].get());
}
return array;
}
private static Block[] unpackBlocks(Supplier<Block>[] blocks) {
Block[] array = new Block[blocks.length];
for (int i = 0; i < blocks.length; i++) {
array[i] = Objects.requireNonNull(blocks[i].get());
}
return array;
}
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry.forge;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.GameRules;
import java.util.function.BiConsumer;
public class GameRuleFactoryImpl {
private GameRuleFactoryImpl() {}
public static GameRules.Type<GameRules.BooleanValue> createBooleanRule(boolean defaultValue) {
return GameRules.BooleanValue.create(defaultValue);
}
public static GameRules.Type<GameRules.BooleanValue> createBooleanRule(boolean defaultValue, BiConsumer<MinecraftServer, GameRules.BooleanValue> changedCallback) {
return GameRules.BooleanValue.create(defaultValue, changedCallback);
}
public static GameRules.Type<GameRules.IntegerValue> createIntRule(int defaultValue) {
return GameRules.IntegerValue.create(defaultValue);
}
public static GameRules.Type<GameRules.IntegerValue> createIntRule(int defaultValue, BiConsumer<MinecraftServer, GameRules.IntegerValue> changedCallback) {
return GameRules.IntegerValue.create(defaultValue, changedCallback);
}
}

View File

@@ -0,0 +1,28 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.registry.forge;
import net.minecraft.world.level.GameRules;
public class GameRuleRegistryImpl {
public static <T extends GameRules.Value<T>> GameRules.Key<T> register(String name, GameRules.Category category, GameRules.Type<T> type) {
return GameRules.register(name, category, type);
}
}

View File

@@ -35,15 +35,15 @@ import net.minecraftforge.common.extensions.IForgeContainerType;
import net.minecraftforge.fml.network.NetworkHooks;
public class MenuRegistryImpl {
public static void openMenu(ServerPlayer player, ExtendedMenuProvider provider) {
public static void openExtendedMenu(ServerPlayer player, ExtendedMenuProvider provider) {
NetworkHooks.openGui(player, provider, provider::saveExtraData);
}
public static <T extends AbstractContainerMenu> MenuType<T> registerMenuType(SimpleMenuTypeFactory<T> factory) {
public static <T extends AbstractContainerMenu> MenuType<T> of(SimpleMenuTypeFactory<T> factory) {
return new MenuType<>(factory::create);
}
public static <T extends AbstractContainerMenu> MenuType<T> registerExtendedMenuType(ExtendedMenuTypeFactory<T> factory) {
public static <T extends AbstractContainerMenu> MenuType<T> ofExtended(ExtendedMenuTypeFactory<T> factory) {
return IForgeContainerType.create(factory::create);
}

View File

@@ -22,10 +22,14 @@ package me.shedaniel.architectury.registry.forge;
import com.google.common.base.Objects;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import me.shedaniel.architectury.core.RegistryEntry;
import me.shedaniel.architectury.platform.forge.EventBuses;
import me.shedaniel.architectury.registry.Registries;
import me.shedaniel.architectury.registry.Registry;
import me.shedaniel.architectury.registry.RegistrySupplier;
import me.shedaniel.architectury.registry.registries.RegistryBuilder;
import me.shedaniel.architectury.registry.registries.RegistryOption;
import me.shedaniel.architectury.registry.registries.StandardRegistryOption;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.LazyLoadedValue;
@@ -33,6 +37,7 @@ import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.RegistryManager;
@@ -76,7 +81,11 @@ public class RegistriesImpl {
@Override
public <T> Registry<T> get(ResourceKey<net.minecraft.core.Registry<T>> registryKey) {
return new ForgeBackedRegistryImpl<>(registry, (IForgeRegistry) RegistryManager.ACTIVE.getRegistry(registryKey.location()));
return get(RegistryManager.ACTIVE.getRegistry(registryKey.location()));
}
public <T> Registry<T> get(IForgeRegistry registry) {
return new ForgeBackedRegistryImpl<>(this.registry, registry);
}
@Override
@@ -84,6 +93,13 @@ public class RegistriesImpl {
return new VanillaBackedRegistryImpl<>(registry);
}
@Override
public <T extends RegistryEntry<T>> RegistryBuilder<T> builder(Class<T> type, ResourceLocation registryId) {
return new RegistryBuilderWrapper<>(this, new net.minecraftforge.registries.RegistryBuilder<>()
.setName(registryId)
.setType((Class) type));
}
public class EventListener {
@SubscribeEvent
public void handleEvent(RegistryEvent.Register event) {
@@ -101,6 +117,37 @@ public class RegistriesImpl {
}
}
public static class RegistryBuilderWrapper<T extends RegistryEntry<T>> implements RegistryBuilder<T> {
@NotNull
private final RegistryProviderImpl provider;
@NotNull
private final net.minecraftforge.registries.RegistryBuilder<?> builder;
private boolean saveToDisk = false;
private boolean syncToClients = false;
public RegistryBuilderWrapper(@NotNull RegistryProviderImpl provider, @NotNull net.minecraftforge.registries.RegistryBuilder<?> builder) {
this.provider = provider;
this.builder = builder;
}
@Override
public @NotNull Registry<T> build() {
if (!syncToClients) builder.disableSync();
if (!saveToDisk) builder.disableSaving();
return provider.get(builder.create());
}
@Override
public @NotNull RegistryBuilder<T> option(@NotNull RegistryOption option) {
if (option == StandardRegistryOption.SAVE_TO_DISC) {
this.saveToDisk = true;
} else if (option == StandardRegistryOption.SYNC_TO_CLIENTS) {
this.syncToClients = true;
}
return this;
}
}
public static class VanillaBackedRegistryImpl<T> implements Registry<T> {
private net.minecraft.core.Registry<T> delegate;
@@ -116,27 +163,27 @@ public class RegistriesImpl {
public @NotNull ResourceLocation getRegistryId() {
return delegate.key().location();
}
@Override
public @NotNull ResourceLocation getId() {
return id;
}
@Override
public boolean isPresent() {
return contains(id);
}
@Override
public T get() {
return value.get();
}
@Override
public int hashCode() {
return Objects.hashCode(getRegistryId(), getId());
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
@@ -144,7 +191,7 @@ public class RegistriesImpl {
RegistrySupplier<?> other = (RegistrySupplier<?>) obj;
return other.getRegistryId().equals(getRegistryId()) && other.getId().equals(getId());
}
@Override
public String toString() {
return getRegistryId().toString() + "@" + id.toString();
@@ -164,6 +211,11 @@ public class RegistriesImpl {
return delegate.getKey(obj);
}
@Override
public int getRawId(T obj) {
return delegate.getId(obj);
}
@Override
public Optional<ResourceKey<T>> getKey(T t) {
return delegate.getResourceKey(t);
@@ -175,9 +227,14 @@ public class RegistriesImpl {
return delegate.get(id);
}
@Override
public T byRawId(int rawId) {
return delegate.byId(rawId);
}
@Override
public boolean contains(ResourceLocation resourceLocation) {
return delegate.containsKey(resourceLocation);
return delegate.keySet().contains(resourceLocation);
}
@Override
@@ -223,27 +280,27 @@ public class RegistriesImpl {
public @NotNull ResourceLocation getRegistryId() {
return delegate.getRegistryName();
}
@Override
public @NotNull ResourceLocation getId() {
return id;
}
@Override
public boolean isPresent() {
return contains(id);
}
@Override
public T get() {
return value.get();
}
@Override
public int hashCode() {
return Objects.hashCode(getRegistryId(), getId());
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
@@ -251,7 +308,7 @@ public class RegistriesImpl {
RegistrySupplier<?> other = (RegistrySupplier<?>) obj;
return other.getRegistryId().equals(getRegistryId()) && other.getId().equals(getId());
}
@Override
public String toString() {
return getRegistryId().toString() + "@" + id.toString();
@@ -268,27 +325,27 @@ public class RegistriesImpl {
public @NotNull ResourceLocation getRegistryId() {
return delegate.getRegistryName();
}
@Override
public @NotNull ResourceLocation getId() {
return registryObject.getId();
}
@Override
public boolean isPresent() {
return registryObject.isPresent();
}
@Override
public T get() {
return (T) registryObject.get();
}
@Override
public int hashCode() {
return Objects.hashCode(getRegistryId(), getId());
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
@@ -296,7 +353,7 @@ public class RegistriesImpl {
RegistrySupplier<?> other = (RegistrySupplier<?>) obj;
return other.getRegistryId().equals(getRegistryId()) && other.getId().equals(getId());
}
@Override
public String toString() {
return getRegistryId().toString() + "@" + id.toString();
@@ -310,6 +367,11 @@ public class RegistriesImpl {
return delegate.getKey(obj);
}
@Override
public int getRawId(T obj) {
return ((ForgeRegistry<T>) delegate).getID(obj);
}
@Override
public Optional<ResourceKey<T>> getKey(T t) {
return Optional.ofNullable(getId(t)).map(id -> ResourceKey.create(key(), id));
@@ -321,6 +383,11 @@ public class RegistriesImpl {
return delegate.getValue(id);
}
@Override
public T byRawId(int rawId) {
return ((ForgeRegistry<T>) delegate).getValue(rawId);
}
@Override
public boolean contains(ResourceLocation resourceLocation) {
return delegate.containsKey(resourceLocation);

View File

@@ -31,4 +31,9 @@ public-f net.minecraft.world.biome.BiomeAmbience field_235212_i_ # music
public-f net.minecraft.world.biome.BiomeAmbience field_242523_e # skyColor
public-f net.minecraft.world.biome.BiomeAmbience field_242524_f # foliageColor
public-f net.minecraft.world.biome.BiomeAmbience field_242525_g # grassColor
public-f net.minecraft.world.biome.BiomeAmbience field_242526_h # grassColorModifier
public-f net.minecraft.world.biome.BiomeAmbience field_242526_h # grassColorModifier
public net.minecraft.world.storage.FolderName <init>(Ljava/lang/String;)V
public net.minecraft.world.GameRules$BooleanValue func_223567_b(ZLjava/util/function/BiConsumer;)Lnet/minecraft/world/GameRules$RuleType; # create
public net.minecraft.world.GameRules$BooleanValue func_223568_b(Z)Lnet/minecraft/world/GameRules$RuleType; # create
public net.minecraft.world.GameRules$IntegerValue func_223564_a(ILjava/util/function/BiConsumer;)Lnet/minecraft/world/GameRules$RuleType; # create
public net.minecraft.world.GameRules$IntegerValue func_223559_b(I)Lnet/minecraft/world/GameRules$RuleType; # create

View File

@@ -1,11 +1,15 @@
{
"required": true,
"package": "me.shedaniel.architectury.mixin.forge",
"plugin": "me.shedaniel.architectury.plugin.forge.ArchitecturyMixinPlugin",
"compatibilityLevel": "JAVA_8",
"minVersion": "0.8",
"client": [
],
"mixins": ["BiomeGenerationSettingsBuilderAccessor", "MobSpawnSettingsBuilderAccessor"],
"mixins": [
"BiomeGenerationSettingsBuilderAccessor", "MixinRegistryEntry", "MixinBlockEntity", "MixinBlockEntityExtension",
"MobSpawnSettingsBuilderAccessor"
],
"injectors": {
"defaultRequire": 1
}

View File

@@ -7,11 +7,12 @@ supported_version=20w51a
cf_type=beta
archives_base_name=architectury
mod_version=2.0
archives_base_name_snapshot=architectury-snapshot
base_version=2.0
maven_group=me.shedaniel
fabric_loader_version=0.10.8
fabric_api_version=0.29.3+1.17
mod_menu_version=2.0.0-beta.1+build.2
#forge_version=35.1.36
#forge_version=35.1.36

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

View File

@@ -11,5 +11,8 @@ pluginManagement {
include("common")
include("fabric")
//include("forge")
include("testmod-common")
include("testmod-fabric")
//include("testmod-forge")
rootProject.name = "architectury"

View File

@@ -0,0 +1,12 @@
dependencies {
minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
mappings loom.officialMojangMappings()
// We depend on fabric loader here to use the fabric @Environment annotations
// Do NOT use other classes from fabric loader
modCompile "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
implementation project(":common")
}
architectury {
common()
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test;
import me.shedaniel.architectury.platform.Platform;
import me.shedaniel.architectury.test.debug.ConsoleMessageSink;
import me.shedaniel.architectury.test.events.DebugEvents;
import me.shedaniel.architectury.test.debug.MessageSink;
import me.shedaniel.architectury.test.debug.client.ClientOverlayMessageSink;
import me.shedaniel.architectury.test.gamerule.TestGameRules;
import me.shedaniel.architectury.test.registry.TestRegistries;
import me.shedaniel.architectury.test.registry.client.TestKeybinds;
import me.shedaniel.architectury.utils.Env;
import me.shedaniel.architectury.utils.EnvExecutor;
public class TestMod {
public static final MessageSink SINK = EnvExecutor.getEnvSpecific(() -> ClientOverlayMessageSink::new, () -> ConsoleMessageSink::new);
public static final String MOD_ID = "architectury-test";
public static void initialize() {
DebugEvents.initialize();
TestRegistries.initialize();
TestGameRules.init();
if (Platform.getEnvironment() == Env.CLIENT)
TestKeybinds.initialize();
}
}

View File

@@ -17,7 +17,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test;
package me.shedaniel.architectury.test.debug;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

View File

@@ -17,7 +17,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test;
package me.shedaniel.architectury.test.debug;
public interface MessageSink {
void accept(String message);

View File

@@ -17,13 +17,13 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test.client;
package me.shedaniel.architectury.test.debug.client;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import me.shedaniel.architectury.event.events.GuiEvent;
import me.shedaniel.architectury.test.ConsoleMessageSink;
import me.shedaniel.architectury.test.debug.ConsoleMessageSink;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.Util;
@@ -57,6 +57,8 @@ public class ClientOverlayMessageSink extends ConsoleMessageSink {
}
public void render(PoseStack matrices, float delta) {
matrices.pushPose();
matrices.scale(0.5f, 0.5f, 1f);
Minecraft minecraft = Minecraft.getInstance();
long currentMills = Util.getMillis();
int lineHeight = minecraft.font.lineHeight;
@@ -64,13 +66,13 @@ public class ClientOverlayMessageSink extends ConsoleMessageSink {
synchronized (messages) {
Iterator<Message> messageIterator = messages.iterator();
int y = 1;
RenderSystem.enableBlend();
while (messageIterator.hasNext()) {
Message message = messageIterator.next();
int timeExisted = (int) (currentMills - message.created);
if (timeExisted >= 5000) {
messageIterator.remove();
} else {
@@ -87,6 +89,7 @@ public class ClientOverlayMessageSink extends ConsoleMessageSink {
RenderSystem.disableAlphaTest();
RenderSystem.disableBlend();
matrices.popPose();
}
private static class Message {

View File

@@ -17,19 +17,14 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test;
package me.shedaniel.architectury.test.events;
import com.mojang.blaze3d.platform.InputConstants;
import me.shedaniel.architectury.event.events.*;
import me.shedaniel.architectury.event.events.client.ClientChatEvent;
import me.shedaniel.architectury.event.events.client.ClientScreenInputEvent;
import me.shedaniel.architectury.event.events.client.ClientLifecycleEvent;
import me.shedaniel.architectury.event.events.client.ClientPlayerEvent;
import me.shedaniel.architectury.event.events.client.*;
import me.shedaniel.architectury.hooks.ExplosionHooks;
import me.shedaniel.architectury.platform.Platform;
import me.shedaniel.architectury.test.client.ClientOverlayMessageSink;
import me.shedaniel.architectury.utils.Env;
import me.shedaniel.architectury.utils.EnvExecutor;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.core.Position;
@@ -44,9 +39,9 @@ import net.minecraft.world.level.Level;
import java.util.Optional;
public class TestMod {
public static final MessageSink SINK = EnvExecutor.getEnvSpecific(() -> ClientOverlayMessageSink::new, () -> ConsoleMessageSink::new);
import static me.shedaniel.architectury.test.TestMod.SINK;
public class DebugEvents {
public static void initialize() {
debugEvents();
if (Platform.getEnvironment() == Env.CLIENT)
@@ -170,6 +165,9 @@ public class TestMod {
PlayerEvent.CLOSE_MENU.register((player, menu) -> {
SINK.accept(player.getScoreboardName() + " closes " + toSimpleName(menu) + logSide(player.level));
});
PlayerEvent.CHANGE_DIMENSION.register((player, oldLevel, newLevel) -> {
SINK.accept(player.getScoreboardName() + " switched from " + oldLevel.location() + " to " + newLevel.location() + logSide(player.level));
});
}
public static String toShortString(Vec3i pos) {
@@ -203,11 +201,17 @@ public class TestMod {
SINK.accept(player.getScoreboardName() + " joined (client)");
});
ClientPlayerEvent.CLIENT_PLAYER_QUIT.register(player -> {
SINK.accept(player.getScoreboardName() + " quit (client)");
if (player != null) {
SINK.accept(player.getScoreboardName() + " quit (client)");
}
});
ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.register((oldPlayer, newPlayer) -> {
SINK.accept(newPlayer.getScoreboardName() + " respawned (client)");
});
GuiEvent.SET_SCREEN.register((screen -> {
SINK.accept("Screen has been changed to " + toSimpleName(screen));
return InteractionResultHolder.pass(screen);
}));
GuiEvent.INIT_PRE.register((screen, widgets, children) -> {
SINK.accept(toSimpleName(screen) + " initializes");
return InteractionResult.PASS;
@@ -225,7 +229,7 @@ public class TestMod {
SINK.accept("Client texture stitched: " + atlas.location());
});
ClientScreenInputEvent.MOUSE_SCROLLED_PRE.register((client, screen, mouseX, mouseY, amount) -> {
SINK.accept("Screen Mouse amount: %.2f distance", amount);
SINK.accept("Screen Mouse scrolled: %.2f distance", amount);
return InteractionResult.PASS;
});
ClientScreenInputEvent.MOUSE_CLICKED_PRE.register((client, screen, mouseX, mouseY, button) -> {
@@ -252,9 +256,21 @@ public class TestMod {
SINK.accept("Screen Key released: " + InputConstants.getKey(keyCode, scanCode).getDisplayName().getString());
return InteractionResult.PASS;
});
ClientRawInputEvent.MOUSE_SCROLLED.register((client, amount) -> {
SINK.accept("Raw Mouse scrolled: %.2f distance", amount);
return InteractionResult.PASS;
});
ClientRawInputEvent.MOUSE_CLICKED_PRE.register((client, button, action, mods) -> {
SINK.accept("Raw Mouse clicked: " + button);
return InteractionResult.PASS;
});
ClientRawInputEvent.KEY_PRESSED.register((client, keyCode, scanCode, action, modifiers) -> {
SINK.accept("Raw Key pressed: " + InputConstants.getKey(keyCode, scanCode).getDisplayName().getString());
return InteractionResult.PASS;
});
}
private static String toSimpleName(Object o) {
return o.getClass().getSimpleName() + "@" + Integer.toHexString(o.hashCode());
return o == null ? "null" : o.getClass().getSimpleName() + "@" + Integer.toHexString(o.hashCode());
}
}

View File

@@ -0,0 +1,38 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test.gamerule;
import me.shedaniel.architectury.registry.GameRuleFactory;
import net.minecraft.world.level.GameRules;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import static me.shedaniel.architectury.registry.GameRuleRegistry.register;
public class TestGameRules {
private static final Logger LOGGER = LogManager.getLogger();
public static final GameRules.Key<GameRules.BooleanValue> SIMPLE_BOOL = register("simpleBool", GameRules.Category.MISC, GameRuleFactory.createBooleanRule(true));
public static final GameRules.Key<GameRules.IntegerValue> SIMPLE_INT = register("simpleInt", GameRules.Category.MISC, GameRuleFactory.createIntRule(10));
public static final GameRules.Key<GameRules.BooleanValue> CALLBACK_BOOL = register("callbackBool", GameRules.Category.MISC, GameRuleFactory.createBooleanRule(true, (server, value) -> LOGGER.info("changed to {}", value.get())));
public static final GameRules.Key<GameRules.IntegerValue> CALLBACK_INT = register("callbackInt", GameRules.Category.MISC, GameRuleFactory.createIntRule(10, (server, value) -> LOGGER.info("changed to {}", value.get())));
public static void init() {}
}

Some files were not shown because too many files have changed in this diff Show More