diff --git a/.editorconfig b/.editorconfig index 998bd73f..d1a1ff05 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,7 +11,7 @@ ij_formatter_off_tag = off ij_formatter_on_tag = on ij_formatter_tags_enabled = false ij_smart_tabs = false -ij_visual_guides = +ij_visual_guides = ij_wrap_on_typing = false [*.css] @@ -89,7 +89,7 @@ ij_java_blank_lines_before_package = 0 ij_java_block_brace_style = end_of_line ij_java_block_comment_add_space = false ij_java_block_comment_at_first_column = true -ij_java_builder_methods = +ij_java_builder_methods = ij_java_call_parameters_new_line_after_left_paren = true ij_java_call_parameters_right_paren_on_new_line = false ij_java_call_parameters_wrap = on_every_item @@ -123,31 +123,31 @@ 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_prefix = +ij_java_entity_dd_prefix = ij_java_entity_dd_suffix = EJB -ij_java_entity_eb_prefix = +ij_java_entity_eb_prefix = ij_java_entity_eb_suffix = Bean -ij_java_entity_hi_prefix = +ij_java_entity_hi_prefix = 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_li_suffix = +ij_java_entity_li_suffix = ij_java_entity_pk_class = java.lang.String -ij_java_entity_ri_prefix = -ij_java_entity_ri_suffix = -ij_java_entity_vo_prefix = +ij_java_entity_ri_prefix = +ij_java_entity_ri_suffix = +ij_java_entity_vo_prefix = ij_java_entity_vo_suffix = VO ij_java_enum_constants_wrap = on_every_item ij_java_extends_keyword_wrap = off ij_java_extends_list_wrap = off ij_java_field_annotation_wrap = split_into_lines -ij_java_field_name_prefix = -ij_java_field_name_suffix = -ij_java_filter_class_prefix = -ij_java_filter_class_suffix = -ij_java_filter_dd_prefix = -ij_java_filter_dd_suffix = +ij_java_field_name_prefix = +ij_java_field_name_suffix = +ij_java_filter_class_prefix = +ij_java_filter_class_suffix = +ij_java_filter_dd_prefix = +ij_java_filter_dd_suffix = ij_java_finally_on_new_line = false ij_java_for_brace_force = never ij_java_for_statement_new_line_after_left_paren = true @@ -181,13 +181,13 @@ ij_java_layout_static_imports_separately = true ij_java_line_comment_add_space = false ij_java_line_comment_add_space_on_reformat = false ij_java_line_comment_at_first_column = true -ij_java_listener_class_prefix = -ij_java_listener_class_suffix = -ij_java_local_variable_name_prefix = -ij_java_local_variable_name_suffix = -ij_java_message_dd_prefix = +ij_java_listener_class_prefix = +ij_java_listener_class_suffix = +ij_java_local_variable_name_prefix = +ij_java_local_variable_name_suffix = +ij_java_message_dd_prefix = ij_java_message_dd_suffix = EJB -ij_java_message_eb_prefix = +ij_java_message_eb_prefix = ij_java_message_eb_suffix = Bean ij_java_method_annotation_wrap = split_into_lines ij_java_method_brace_style = end_of_line @@ -203,15 +203,15 @@ ij_java_new_line_after_lparen_in_deconstruction_pattern = true ij_java_new_line_after_lparen_in_record_header = true ij_java_packages_to_use_import_on_demand = java.awt.*,javax.swing.* ij_java_parameter_annotation_wrap = off -ij_java_parameter_name_prefix = -ij_java_parameter_name_suffix = +ij_java_parameter_name_prefix = +ij_java_parameter_name_suffix = ij_java_parentheses_expression_new_line_after_left_paren = true 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 = true ij_java_record_components_wrap = on_every_item -ij_java_repeat_annotations = +ij_java_repeat_annotations = ij_java_repeat_synchronized = true ij_java_replace_instanceof_and_cast = false ij_java_replace_null_check = true @@ -222,23 +222,23 @@ ij_java_resource_list_wrap = off ij_java_rparen_on_new_line_in_annotation = false ij_java_rparen_on_new_line_in_deconstruction_pattern = false ij_java_rparen_on_new_line_in_record_header = false -ij_java_servlet_class_prefix = -ij_java_servlet_class_suffix = -ij_java_servlet_dd_prefix = -ij_java_servlet_dd_suffix = -ij_java_session_dd_prefix = +ij_java_servlet_class_prefix = +ij_java_servlet_class_suffix = +ij_java_servlet_dd_prefix = +ij_java_servlet_dd_suffix = +ij_java_session_dd_prefix = ij_java_session_dd_suffix = EJB -ij_java_session_eb_prefix = +ij_java_session_eb_prefix = ij_java_session_eb_suffix = Bean -ij_java_session_hi_prefix = +ij_java_session_hi_prefix = 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_li_suffix = -ij_java_session_ri_prefix = -ij_java_session_ri_suffix = -ij_java_session_si_prefix = +ij_java_session_li_suffix = +ij_java_session_ri_prefix = +ij_java_session_ri_suffix = +ij_java_session_si_prefix = ij_java_session_si_suffix = Service ij_java_space_after_closing_angle_bracket_in_type_argument = false ij_java_space_after_colon = true @@ -319,13 +319,13 @@ 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_static_field_name_prefix = -ij_java_static_field_name_suffix = -ij_java_subclass_name_prefix = +ij_java_static_field_name_prefix = +ij_java_static_field_name_suffix = +ij_java_subclass_name_prefix = ij_java_subclass_name_suffix = Impl ij_java_ternary_operation_signs_on_next_line = false ij_java_ternary_operation_wrap = on_every_item -ij_java_test_name_prefix = +ij_java_test_name_prefix = ij_java_test_name_suffix = Test ij_java_throws_keyword_wrap = off ij_java_throws_list_wrap = off @@ -561,7 +561,7 @@ ij_typescript_prefer_explicit_types_function_expression_returns = false ij_typescript_prefer_explicit_types_function_returns = false ij_typescript_prefer_explicit_types_vars_fields = false ij_typescript_prefer_parameters_wrap = false -ij_typescript_property_prefix = +ij_typescript_property_prefix = ij_typescript_reformat_c_style_comments = false ij_typescript_space_after_colon = true ij_typescript_space_after_comma = true @@ -742,7 +742,7 @@ ij_javascript_prefer_explicit_types_function_expression_returns = false ij_javascript_prefer_explicit_types_function_returns = false ij_javascript_prefer_explicit_types_vars_fields = false ij_javascript_prefer_parameters_wrap = false -ij_javascript_property_prefix = +ij_javascript_property_prefix = ij_javascript_reformat_c_style_comments = false ij_javascript_space_after_colon = true ij_javascript_space_after_comma = true @@ -1107,6 +1107,7 @@ ij_kotlin_wrap_first_method_in_call_chain = false [{*.har,*.jsb2,*.jsb3,*.json,*.jsonc,*.png.mcmeta,*.postman_collection,*.postman_collection.json,*.postman_environment,*.postman_environment.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config,mcmod.info,pack.mcmeta}] indent_style = tab +indent_size = 2 ij_json_array_wrapping = split_into_lines ij_json_keep_blank_lines_in_code = 0 ij_json_keep_indents_on_empty_lines = false @@ -1220,4 +1221,4 @@ ij_yaml_keep_line_breaks = true ij_yaml_sequence_on_new_line = false ij_yaml_space_before_colon = false ij_yaml_spaces_within_braces = true -ij_yaml_spaces_within_brackets = true +ij_yaml_spaces_within_brackets = true \ No newline at end of file diff --git a/annotation/src/main/java/snownee/kiwi/KiwiModule.java b/annotation/src/main/java/snownee/kiwi/KiwiModule.java index dc518a28..5a39cb53 100644 --- a/annotation/src/main/java/snownee/kiwi/KiwiModule.java +++ b/annotation/src/main/java/snownee/kiwi/KiwiModule.java @@ -14,6 +14,11 @@ */ String value() default "core"; + /** + * Let it determine your namespace during the phase. + */ + String modId() default ""; + /** * Module will be registered only if dependent mods or modules are loaded. * You can use ";" to separate multiple mod ids. @@ -69,7 +74,7 @@ * Set group of this item/block to null * * @author Snownee - * @see KiwiModule.Category + * @see Category */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @@ -90,7 +95,6 @@ @Target({ElementType.TYPE, ElementType.FIELD}) @interface RenderLayer { RenderLayerEnum value(); - } /** @@ -99,7 +103,7 @@ * @author Snownee */ @Retention(RetentionPolicy.RUNTIME) - @Target(ElementType.FIELD) + @Target({ElementType.TYPE, ElementType.FIELD}) @interface Skip { } diff --git a/annotation/src/main/java/snownee/kiwi/config/KiwiConfig.java b/annotation/src/main/java/snownee/kiwi/config/KiwiConfig.java index f607be08..3a34fac0 100644 --- a/annotation/src/main/java/snownee/kiwi/config/KiwiConfig.java +++ b/annotation/src/main/java/snownee/kiwi/config/KiwiConfig.java @@ -26,6 +26,10 @@ public String extension() { } } + enum PerformanceType { + NONE, LOW, MEDIUM, HIGH + } + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @interface Translation { @@ -50,6 +54,12 @@ public String extension() { @interface GameRestart { } + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + @interface PerformanceImpact { + PerformanceType value(); + } + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE}) @interface Path { diff --git a/build.gradle b/build.gradle index 3fa41a5c..32961271 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "io.github.goooler.shadow" version "8.1.7" - id 'fabric-loom' version '1.6.+' + id 'fabric-loom' version '1.11-SNAPSHOT' id 'maven-publish' id "me.shedaniel.unified-publishing" version "0.1.+" } @@ -65,7 +65,11 @@ dependencies { // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings loom.officialMojangMappings() + mappings loom.layered() { + officialMojangMappings() + parchment("org.parchmentmc.data:parchment-${project.parchment_minecraft_version}:${project.parchment_mappings_version}@zip") + } + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" // Fabric API. This is technically optional, but you probably want it anyway. diff --git a/gradle.properties b/gradle.properties index 5c9332e5..adda052f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,13 +1,13 @@ # Sets default memory used for gradle commands. Can be overridden by user or command line properties. # This is required to provide enough memory for the Minecraft decompilation process. -org.gradle.jvmargs=-Xmx3G -Xms3G -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1079 -Duser.language=en +org.gradle.jvmargs=-Xmx3G -Xms3G -Duser.language=en org.gradle.daemon=false # Fabric Properties # check these on https://fabricmc.net/versions.html -minecraft_version=1.21 -supported_version=1.21 -loader_version=0.15.11 +minecraft_version=1.21.8 +supported_version=1.21.8 +loader_version=0.16.14 # Mod Properties mod_version=15.1.4 @@ -17,8 +17,12 @@ maven_group=snownee.kiwi archives_base_name=Kiwi # Dependencies -fabric_version=0.100.1+1.21 -cloth_config_version=15.0.127 -modmenu_version=11.0.0-beta.1 +fabric_version=0.130.0+1.21.8 +cloth_config_version=19.0.147 +modmenu_version=15.0.0-beta.3 snakeyaml_version=2.0 evalex_version=3.4.0 + +# you can also find the latest versions at: https://parchmentmc.org/docs/getting-started +parchment_minecraft_version=1.21.8 +parchment_mappings_version=2025.07.20 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd491..e6441136 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23a..ca025c83 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f..25da30db 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/src/main/java/snownee/kiwi/AbstractModule.java b/src/main/java/snownee/kiwi/AbstractModule.java index 3c31ce58..c9548159 100644 --- a/src/main/java/snownee/kiwi/AbstractModule.java +++ b/src/main/java/snownee/kiwi/AbstractModule.java @@ -1,18 +1,20 @@ package snownee.kiwi; import java.util.Map; +import java.util.Objects; import java.util.function.BiConsumer; +import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collectors; import java.util.stream.Stream; +import org.jetbrains.annotations.Nullable; + import com.google.common.collect.Maps; -import com.mojang.datafixers.types.Type; -import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; -import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; +import net.fabricmc.fabric.impl.object.builder.ExtendedBlockEntityType; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; -import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; @@ -28,6 +30,7 @@ import snownee.kiwi.block.entity.InheritanceBlockEntityType; import snownee.kiwi.loader.event.InitEvent; import snownee.kiwi.loader.event.PostInitEvent; +import snownee.kiwi.util.KiwiTabBuilder; /** * All your modules should extend {@code AbstractModule} @@ -35,17 +38,38 @@ * @author Snownee */ public abstract class AbstractModule { - protected final Map>, BiConsumer>> decorators = Maps.newHashMap(); - public ResourceLocation uid; + private static final StackWalker STACK_WALKER = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + protected final Map>, BiConsumer>> decorators = Maps.newIdentityHashMap(); + public @Nullable ResourceLocation uid; protected static KiwiGO go(Supplier factory) { + //noinspection unchecked return new KiwiGO<>((Supplier) factory); } protected static KiwiGO go(Supplier factory, ResourceKey> registryKey) { + //noinspection unchecked return new KiwiGO.RegistrySpecified<>((Supplier) factory, registryKey); } + protected static ItemObject item(Function factory) { + return new ItemObject<>(factory); + } + + protected static BlockObject block(Function factory) { + return block(factory, null); + } + + protected static BlockObject block( + Function factory, + @Nullable Supplier copyFrom) { + return new BlockObject<>(factory, copyFrom); + } + + protected static KiwiGO ref(ResourceKey> registryKey) { + return new KiwiGO.Ref<>(registryKey); + } + /// helper methods: protected static Item.Properties itemProp() { return new Item.Properties(); @@ -61,22 +85,34 @@ protected static BlockBehaviour.Properties blockProp(BlockBehaviour block) { @SafeVarargs public static KiwiGO> blockEntity( - FabricBlockEntityTypeBuilder.Factory factory, - Type datafixer, + BlockEntityType.BlockEntitySupplier factory, + Supplier... blocks) { + return blockEntity(factory, false, blocks); + } + + @SafeVarargs + public static KiwiGO> blockEntity( + BlockEntityType.BlockEntitySupplier factory, + boolean onlyOpCanSetNbt, Supplier... blocks) { - return go(() -> FabricBlockEntityTypeBuilder.create(factory, Stream.of(blocks).map(Supplier::get).toArray(Block[]::new)) - .build(datafixer)); + return go(() -> new ExtendedBlockEntityType<>(factory, Stream.of(blocks).map(Supplier::get).collect(Collectors.toSet()), onlyOpCanSetNbt)); } public static KiwiGO> blockEntity( - FabricBlockEntityTypeBuilder.Factory factory, - Type datafixer, + BlockEntityType.BlockEntitySupplier factory, Class blockClass) { - return go(() -> new InheritanceBlockEntityType<>(factory, blockClass, datafixer)); + return blockEntity(factory, false, blockClass); } - public static CreativeModeTab.Builder itemCategory(String namespace, String path, Supplier icon) { - return FabricItemGroup.builder().title(Component.translatable("itemGroup.%s.%s".formatted(namespace, path))).icon(icon); + public static KiwiGO> blockEntity( + BlockEntityType.BlockEntitySupplier factory, + boolean onlyOpCanSetNbt, + Class blockClass) { + return go(() -> new InheritanceBlockEntityType<>(factory, blockClass, onlyOpCanSetNbt)); + } + + public static CreativeModeTab.Builder itemCategory(ResourceLocation id, Supplier icon) { + return new KiwiTabBuilder(id).icon(icon); } public static TagKey itemTag(String namespace, String path) { @@ -99,6 +135,44 @@ public static TagKey tag(ResourceKey> registryKey, return TagKey.create(registryKey, ResourceLocation.fromNamespaceAndPath(namespace, path)); } + public static TagKey itemTag(String id) { + return tag(Registries.ITEM, id); + } + + public static TagKey> entityTag(String id) { + return tag(Registries.ENTITY_TYPE, id); + } + + public static TagKey blockTag(String id) { + return tag(Registries.BLOCK, id); + } + + public static TagKey fluidTag(String id) { + return tag(Registries.FLUID, id); + } + + public static TagKey tag(ResourceKey> registryKey, String id) { + ResourceLocation location; + if (id.contains(":")) { + location = ResourceLocation.parse(id); + } else { + Class callerClass = STACK_WALKER.walk(stream -> stream + .map(StackWalker.StackFrame::getDeclaringClass) + .filter(cls -> cls != AbstractModule.class) + .findFirst() + ).orElse(null); + if (callerClass == null) { + throw new IllegalStateException("No caller class found"); + } + KiwiModule annotation = callerClass.getDeclaredAnnotation(KiwiModule.class); + if (annotation == null || annotation.modId().isEmpty()) { + throw new IllegalStateException("No KiwiModule modId found on " + callerClass.getName()); + } + location = ResourceLocation.fromNamespaceAndPath(annotation.modId(), id); + } + return TagKey.create(registryKey, location); + } + public void addRegistries() { } @@ -115,10 +189,10 @@ protected void postInit(PostInitEvent event) { } public ResourceLocation id(String path) { - return ResourceLocation.fromNamespaceAndPath(uid.getNamespace(), path); + return ResourceLocation.fromNamespaceAndPath(Objects.requireNonNull(uid).getNamespace(), path); } public KiwiModuleContainer container() { - return KiwiModules.get(uid); + return KiwiModules.get(Objects.requireNonNull(uid)); } } diff --git a/src/main/java/snownee/kiwi/BlockObject.java b/src/main/java/snownee/kiwi/BlockObject.java new file mode 100644 index 00000000..984b3474 --- /dev/null +++ b/src/main/java/snownee/kiwi/BlockObject.java @@ -0,0 +1,63 @@ +package snownee.kiwi; + +import java.util.Objects; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockBehaviour; + +public class BlockObject extends KiwiGO implements ItemLike { + private Function factory; + private @Nullable Supplier copyFrom; + + public BlockObject(Function factory, @Nullable Supplier copyFrom) { + super(null); + this.factory = Objects.requireNonNull(factory); + this.copyFrom = copyFrom; + } + + @Override + public T preRegister(ResourceLocation id) { + //noinspection unchecked + setKey((ResourceKey) ResourceKey.create(Registries.BLOCK, id)); + return getOrCreate(); + } + + @Override + public T getOrCreate() { + if (value == null) { + Objects.requireNonNull(factory); + BlockBehaviour.Properties properties; + if (copyFrom != null) { + properties = BlockBehaviour.Properties.ofFullCopy(copyFrom.get()); + } else { + properties = BlockBehaviour.Properties.of(); + } + //noinspection unchecked + properties.setId((ResourceKey) resourceKey()); + value = Objects.requireNonNull(factory.apply(properties)); + factory = null; + copyFrom = null; + } + return get(); + } + + @Override + public Item asItem() { + return get().asItem(); + } + + @Override + public ResourceKey> findRegistry() { + return Registries.BLOCK; + } +} diff --git a/src/main/java/snownee/kiwi/GroupSetting.java b/src/main/java/snownee/kiwi/GroupSetting.java index 5606e299..bf4dea19 100644 --- a/src/main/java/snownee/kiwi/GroupSetting.java +++ b/src/main/java/snownee/kiwi/GroupSetting.java @@ -62,20 +62,23 @@ public void postApply() { .toList(); for (ResourceKey tabKey : tabKeys) { ItemGroupEvents.modifyEntriesEvent(tabKey).register(entries -> { - Set afterItems = Stream.of(after) - .map(ResourceLocation::tryParse) - .filter(Objects::nonNull) - .map(BuiltInRegistries.ITEM::get) - .filter(Predicate.not(Items.AIR::equals)) - .collect(Collectors.toSet()); List items = Lists.newArrayList(); for (ItemCategoryFiller filler : fillers) { - CreativeModeTab tab = BuiltInRegistries.CREATIVE_MODE_TAB.get(tabKey); + CreativeModeTab tab = BuiltInRegistries.CREATIVE_MODE_TAB.getValue(tabKey); filler.fillItemCategory(tab, entries.getEnabledFeatures(), entries.shouldShowOpRestrictedItems(), items); } items = getEnabledStacks(items, entries.getEnabledFeatures()); - addAfter(items, entries.getDisplayStacks(), afterItems); - addAfter(items, entries.getSearchTabStacks(), afterItems); + + if (after != null) { + Set afterItems = Stream.of(after) + .map(ResourceLocation::tryParse) + .filter(Objects::nonNull) + .map(BuiltInRegistries.ITEM::getValue) + .filter(Predicate.not(Items.AIR::equals)) + .collect(Collectors.toSet()); + addAfter(items, entries.getDisplayStacks(), afterItems); + addAfter(items, entries.getSearchTabStacks(), afterItems); + } }); } } diff --git a/src/main/java/snownee/kiwi/ItemObject.java b/src/main/java/snownee/kiwi/ItemObject.java new file mode 100644 index 00000000..5319bf36 --- /dev/null +++ b/src/main/java/snownee/kiwi/ItemObject.java @@ -0,0 +1,48 @@ +package snownee.kiwi; + +import java.util.Objects; +import java.util.function.Function; + +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.ItemLike; + +public class ItemObject extends KiwiGO implements ItemLike { + private Function factory; + + public ItemObject(Function factory) { + super(null); + this.factory = Objects.requireNonNull(factory); + } + + @Override + public T preRegister(ResourceLocation id) { + //noinspection unchecked + setKey((ResourceKey) ResourceKey.create(Registries.ITEM, id)); + return getOrCreate(); + } + + @Override + public T getOrCreate() { + if (value == null) { + Objects.requireNonNull(factory); + //noinspection unchecked + value = Objects.requireNonNull(factory.apply(new Item.Properties().setId((ResourceKey) resourceKey()))); + factory = null; + } + return get(); + } + + @Override + public Item asItem() { + return get(); + } + + @Override + public ResourceKey> findRegistry() { + return Registries.ITEM; + } +} diff --git a/src/main/java/snownee/kiwi/Kiwi.java b/src/main/java/snownee/kiwi/Kiwi.java index 0ac0a1ee..81cd9a1e 100644 --- a/src/main/java/snownee/kiwi/Kiwi.java +++ b/src/main/java/snownee/kiwi/Kiwi.java @@ -41,75 +41,15 @@ import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.metadata.ModMetadata; -import net.minecraft.advancements.critereon.ItemSubPredicate; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.commands.synchronization.ArgumentTypeInfo; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.core.Registry; -import net.minecraft.core.component.DataComponentType; -import net.minecraft.core.particles.ParticleType; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.stats.StatType; -import net.minecraft.util.valueproviders.FloatProviderType; -import net.minecraft.util.valueproviders.IntProviderType; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.ai.attributes.Attribute; -import net.minecraft.world.entity.ai.memory.MemoryModuleType; -import net.minecraft.world.entity.ai.sensing.SensorType; -import net.minecraft.world.entity.ai.village.poi.PoiType; -import net.minecraft.world.entity.animal.CatVariant; -import net.minecraft.world.entity.animal.FrogVariant; -import net.minecraft.world.entity.decoration.PaintingVariant; -import net.minecraft.world.entity.npc.VillagerProfession; -import net.minecraft.world.entity.npc.VillagerType; -import net.minecraft.world.entity.schedule.Activity; -import net.minecraft.world.entity.schedule.Schedule; -import net.minecraft.world.inventory.MenuType; -import net.minecraft.world.item.ArmorMaterial; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTabs; -import net.minecraft.world.item.Instrument; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.alchemy.Potion; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.chunk.status.ChunkStatus; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.level.gameevent.PositionSourceType; -import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicateType; -import net.minecraft.world.level.levelgen.carver.WorldCarver; -import net.minecraft.world.level.levelgen.feature.Feature; -import net.minecraft.world.level.levelgen.feature.featuresize.FeatureSizeType; -import net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacerType; -import net.minecraft.world.level.levelgen.feature.rootplacers.RootPlacerType; -import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProviderType; -import net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecoratorType; -import net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacerType; -import net.minecraft.world.level.levelgen.heightproviders.HeightProviderType; -import net.minecraft.world.level.levelgen.placement.PlacementModifierType; -import net.minecraft.world.level.levelgen.structure.StructureType; -import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; -import net.minecraft.world.level.levelgen.structure.placement.StructurePlacementType; -import net.minecraft.world.level.levelgen.structure.pools.StructurePoolElementType; -import net.minecraft.world.level.levelgen.structure.templatesystem.PosRuleTestType; -import net.minecraft.world.level.levelgen.structure.templatesystem.RuleTestType; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; -import net.minecraft.world.level.material.Fluid; -import net.minecraft.world.level.storage.loot.entries.LootPoolEntryType; -import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; -import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; -import net.minecraft.world.level.storage.loot.providers.nbt.LootNbtProviderType; -import net.minecraft.world.level.storage.loot.providers.number.LootNumberProviderType; -import net.minecraft.world.level.storage.loot.providers.score.LootScoreProviderType; -import snownee.kiwi.block.def.BlockDefinition; -import snownee.kiwi.block.def.SimpleBlockDefinition; import snownee.kiwi.build.KiwiMetadata; import snownee.kiwi.build.KiwiMetadataParser; import snownee.kiwi.command.KiwiClientCommand; @@ -122,6 +62,7 @@ import snownee.kiwi.loader.event.InitEvent; import snownee.kiwi.loader.event.PostInitEvent; import snownee.kiwi.network.KNetworking; +import snownee.kiwi.util.ClientProxy; import snownee.kiwi.util.KUtil; @Mod(Kiwi.ID) @@ -135,7 +76,6 @@ public class Kiwi implements ClientModInitializer, DedicatedServerModInitializer public static MinecraftServer currentServer; private static Multimap moduleData = ArrayListMultimap.create(); private static Map conditions = Maps.newHashMap(); - private static boolean tagsUpdated; public static boolean enableDataModule; private static boolean initialized; @@ -209,66 +149,85 @@ private static void registerRegistries() throws Exception { // } // System.out.println(sb); - registerRegistry(Registries.GAME_EVENT, GameEvent.class); - registerRegistry(Registries.SOUND_EVENT, SoundEvent.class); - registerRegistry(Registries.FLUID, Fluid.class); - registerRegistry(Registries.MOB_EFFECT, MobEffect.class); - registerRegistry(Registries.BLOCK, Block.class); - registerRegistry(Registries.ENTITY_TYPE, EntityType.class); - registerRegistry(Registries.ITEM, Item.class); - registerRegistry(Registries.POTION, Potion.class); - registerRegistry(Registries.PARTICLE_TYPE, ParticleType.class); - registerRegistry(Registries.BLOCK_ENTITY_TYPE, BlockEntityType.class); - registerRegistry(Registries.PAINTING_VARIANT, PaintingVariant.class); - //registerRegistry(Registries.CUSTOM_STAT, ResourceLocation.class); - registerRegistry(Registries.CHUNK_STATUS, ChunkStatus.class); - registerRegistry(Registries.RULE_TEST, RuleTestType.class); - registerRegistry(Registries.POS_RULE_TEST, PosRuleTestType.class); - registerRegistry(Registries.MENU, MenuType.class); - registerRegistry(Registries.RECIPE_TYPE, RecipeType.class); - registerRegistry(Registries.RECIPE_SERIALIZER, RecipeSerializer.class); - registerRegistry(Registries.ATTRIBUTE, Attribute.class); - registerRegistry(Registries.POSITION_SOURCE_TYPE, PositionSourceType.class); - registerRegistry(Registries.COMMAND_ARGUMENT_TYPE, ArgumentTypeInfo.class); - registerRegistry(Registries.STAT_TYPE, StatType.class); - registerRegistry(Registries.VILLAGER_TYPE, VillagerType.class); - registerRegistry(Registries.VILLAGER_PROFESSION, VillagerProfession.class); - registerRegistry(Registries.POINT_OF_INTEREST_TYPE, PoiType.class); - registerRegistry(Registries.MEMORY_MODULE_TYPE, MemoryModuleType.class); - registerRegistry(Registries.SENSOR_TYPE, SensorType.class); - registerRegistry(Registries.SCHEDULE, Schedule.class); - registerRegistry(Registries.ACTIVITY, Activity.class); - registerRegistry(Registries.LOOT_POOL_ENTRY_TYPE, LootPoolEntryType.class); - registerRegistry(Registries.LOOT_FUNCTION_TYPE, LootItemFunctionType.class); - registerRegistry(Registries.LOOT_CONDITION_TYPE, LootItemConditionType.class); - registerRegistry(Registries.LOOT_NUMBER_PROVIDER_TYPE, LootNumberProviderType.class); - registerRegistry(Registries.LOOT_NBT_PROVIDER_TYPE, LootNbtProviderType.class); - registerRegistry(Registries.LOOT_SCORE_PROVIDER_TYPE, LootScoreProviderType.class); - registerRegistry(Registries.FLOAT_PROVIDER_TYPE, FloatProviderType.class); - registerRegistry(Registries.INT_PROVIDER_TYPE, IntProviderType.class); - registerRegistry(Registries.HEIGHT_PROVIDER_TYPE, HeightProviderType.class); - registerRegistry(Registries.BLOCK_PREDICATE_TYPE, BlockPredicateType.class); - registerRegistry(Registries.CARVER, WorldCarver.class); - registerRegistry(Registries.FEATURE, Feature.class); - registerRegistry(Registries.STRUCTURE_PLACEMENT, StructurePlacementType.class); - registerRegistry(Registries.STRUCTURE_PIECE, StructurePieceType.class); - registerRegistry(Registries.STRUCTURE_TYPE, StructureType.class); - registerRegistry(Registries.PLACEMENT_MODIFIER_TYPE, PlacementModifierType.class); - registerRegistry(Registries.BLOCK_STATE_PROVIDER_TYPE, BlockStateProviderType.class); - registerRegistry(Registries.FOLIAGE_PLACER_TYPE, FoliagePlacerType.class); - registerRegistry(Registries.TRUNK_PLACER_TYPE, TrunkPlacerType.class); - registerRegistry(Registries.ROOT_PLACER_TYPE, RootPlacerType.class); - registerRegistry(Registries.TREE_DECORATOR_TYPE, TreeDecoratorType.class); - registerRegistry(Registries.FEATURE_SIZE_TYPE, FeatureSizeType.class); - registerRegistry(Registries.STRUCTURE_PROCESSOR, StructureProcessorType.class); - registerRegistry(Registries.STRUCTURE_POOL_ELEMENT, StructurePoolElementType.class); - registerRegistry(Registries.CAT_VARIANT, CatVariant.class); - registerRegistry(Registries.FROG_VARIANT, FrogVariant.class); - registerRegistry(Registries.INSTRUMENT, Instrument.class); - registerRegistry(Registries.CREATIVE_MODE_TAB, CreativeModeTab.class); - registerRegistry(Registries.ARMOR_MATERIAL, ArmorMaterial.class); - registerRegistry(Registries.DATA_COMPONENT_TYPE, DataComponentType.class); - registerRegistry(Registries.ITEM_SUB_PREDICATE_TYPE, ItemSubPredicate.Type.class); + registerRegistry(Registries.GAME_EVENT, net.minecraft.world.level.gameevent.GameEvent.class); + registerRegistry(Registries.SOUND_EVENT, net.minecraft.sounds.SoundEvent.class); + registerRegistry(Registries.FLUID, net.minecraft.world.level.material.Fluid.class); + registerRegistry(Registries.MOB_EFFECT, net.minecraft.world.effect.MobEffect.class); + registerRegistry(Registries.BLOCK, net.minecraft.world.level.block.Block.class); + registerRegistry(Registries.ENTITY_TYPE, net.minecraft.world.entity.EntityType.class); + registerRegistry(Registries.ITEM, net.minecraft.world.item.Item.class); + registerRegistry(Registries.POTION, net.minecraft.world.item.alchemy.Potion.class); + registerRegistry(Registries.PARTICLE_TYPE, net.minecraft.core.particles.ParticleType.class); + registerRegistry(Registries.BLOCK_ENTITY_TYPE, net.minecraft.world.level.block.entity.BlockEntityType.class); + registerRegistry(Registries.CHUNK_STATUS, net.minecraft.world.level.chunk.status.ChunkStatus.class); + registerRegistry(Registries.RULE_TEST, net.minecraft.world.level.levelgen.structure.templatesystem.RuleTestType.class); + registerRegistry( + Registries.RULE_BLOCK_ENTITY_MODIFIER, + net.minecraft.world.level.levelgen.structure.templatesystem.rule.blockentity.RuleBlockEntityModifierType.class); + registerRegistry(Registries.POS_RULE_TEST, net.minecraft.world.level.levelgen.structure.templatesystem.PosRuleTestType.class); + registerRegistry(Registries.MENU, net.minecraft.world.inventory.MenuType.class); + registerRegistry(Registries.RECIPE_TYPE, net.minecraft.world.item.crafting.RecipeType.class); + registerRegistry(Registries.RECIPE_SERIALIZER, net.minecraft.world.item.crafting.RecipeSerializer.class); + registerRegistry(Registries.ATTRIBUTE, net.minecraft.world.entity.ai.attributes.Attribute.class); + registerRegistry(Registries.POSITION_SOURCE_TYPE, net.minecraft.world.level.gameevent.PositionSourceType.class); + registerRegistry(Registries.COMMAND_ARGUMENT_TYPE, net.minecraft.commands.synchronization.ArgumentTypeInfo.class); + registerRegistry(Registries.STAT_TYPE, net.minecraft.stats.StatType.class); + registerRegistry(Registries.VILLAGER_TYPE, net.minecraft.world.entity.npc.VillagerType.class); + registerRegistry(Registries.VILLAGER_PROFESSION, net.minecraft.world.entity.npc.VillagerProfession.class); + registerRegistry(Registries.POINT_OF_INTEREST_TYPE, net.minecraft.world.entity.ai.village.poi.PoiType.class); + registerRegistry(Registries.MEMORY_MODULE_TYPE, net.minecraft.world.entity.ai.memory.MemoryModuleType.class); + registerRegistry(Registries.SENSOR_TYPE, net.minecraft.world.entity.ai.sensing.SensorType.class); + registerRegistry(Registries.SCHEDULE, net.minecraft.world.entity.schedule.Schedule.class); + registerRegistry(Registries.ACTIVITY, net.minecraft.world.entity.schedule.Activity.class); + registerRegistry(Registries.LOOT_POOL_ENTRY_TYPE, net.minecraft.world.level.storage.loot.entries.LootPoolEntryType.class); + registerRegistry(Registries.LOOT_FUNCTION_TYPE, net.minecraft.world.level.storage.loot.functions.LootItemFunctionType.class); + registerRegistry(Registries.LOOT_CONDITION_TYPE, net.minecraft.world.level.storage.loot.predicates.LootItemConditionType.class); + registerRegistry( + Registries.LOOT_NUMBER_PROVIDER_TYPE, + net.minecraft.world.level.storage.loot.providers.number.LootNumberProviderType.class); + registerRegistry(Registries.LOOT_NBT_PROVIDER_TYPE, net.minecraft.world.level.storage.loot.providers.nbt.LootNbtProviderType.class); + registerRegistry( + Registries.LOOT_SCORE_PROVIDER_TYPE, + net.minecraft.world.level.storage.loot.providers.score.LootScoreProviderType.class); + registerRegistry(Registries.FLOAT_PROVIDER_TYPE, net.minecraft.util.valueproviders.FloatProviderType.class); + registerRegistry(Registries.INT_PROVIDER_TYPE, net.minecraft.util.valueproviders.IntProviderType.class); + registerRegistry(Registries.HEIGHT_PROVIDER_TYPE, net.minecraft.world.level.levelgen.heightproviders.HeightProviderType.class); + registerRegistry(Registries.BLOCK_PREDICATE_TYPE, net.minecraft.world.level.levelgen.blockpredicates.BlockPredicateType.class); + registerRegistry(Registries.CARVER, net.minecraft.world.level.levelgen.carver.WorldCarver.class); + registerRegistry(Registries.FEATURE, net.minecraft.world.level.levelgen.feature.Feature.class); + registerRegistry( + Registries.STRUCTURE_PLACEMENT, + net.minecraft.world.level.levelgen.structure.placement.StructurePlacementType.class); + registerRegistry(Registries.STRUCTURE_PIECE, net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType.class); + registerRegistry(Registries.STRUCTURE_TYPE, net.minecraft.world.level.levelgen.structure.StructureType.class); + registerRegistry(Registries.PLACEMENT_MODIFIER_TYPE, net.minecraft.world.level.levelgen.placement.PlacementModifierType.class); + registerRegistry( + Registries.BLOCK_STATE_PROVIDER_TYPE, + net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProviderType.class); + registerRegistry(Registries.FOLIAGE_PLACER_TYPE, net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacerType.class); + registerRegistry(Registries.TRUNK_PLACER_TYPE, net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacerType.class); + registerRegistry(Registries.ROOT_PLACER_TYPE, net.minecraft.world.level.levelgen.feature.rootplacers.RootPlacerType.class); + registerRegistry(Registries.TREE_DECORATOR_TYPE, net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecoratorType.class); + registerRegistry(Registries.FEATURE_SIZE_TYPE, net.minecraft.world.level.levelgen.feature.featuresize.FeatureSizeType.class); + registerRegistry( + Registries.STRUCTURE_PROCESSOR, + net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType.class); + registerRegistry( + Registries.STRUCTURE_POOL_ELEMENT, + net.minecraft.world.level.levelgen.structure.pools.StructurePoolElementType.class); + registerRegistry(Registries.DECORATED_POT_PATTERN, net.minecraft.world.level.block.entity.DecoratedPotPattern.class); + registerRegistry(Registries.CREATIVE_MODE_TAB, net.minecraft.world.item.CreativeModeTab.class); + registerRegistry(Registries.TRIGGER_TYPE, net.minecraft.advancements.CriterionTrigger.class); + registerRegistry(Registries.NUMBER_FORMAT_TYPE, net.minecraft.network.chat.numbers.NumberFormatType.class); + registerRegistry( + Registries.DATA_COMPONENT_PREDICATE_TYPE, + net.minecraft.core.component.predicates.DataComponentPredicate.Type.class); + registerRegistry(Registries.MAP_DECORATION_TYPE, net.minecraft.world.level.saveddata.maps.MapDecorationType.class); + registerRegistry(Registries.CONSUME_EFFECT_TYPE, net.minecraft.world.item.consume_effects.ConsumeEffect.Type.class); + registerRegistry(Registries.RECIPE_DISPLAY, net.minecraft.world.item.crafting.display.RecipeDisplay.Type.class); + registerRegistry(Registries.SLOT_DISPLAY, net.minecraft.world.item.crafting.display.SlotDisplay.Type.class); + registerRegistry(Registries.RECIPE_BOOK_CATEGORY, net.minecraft.world.item.crafting.RecipeBookCategory.class); + registerRegistry(Registries.TICKET_TYPE, net.minecraft.server.level.TicketType.class); } public static void registerTab(String id, ResourceKey tab) { @@ -299,14 +258,6 @@ public static boolean isLoaded(ResourceLocation module) { return KiwiModules.isLoaded(module); } - public static void onTagsUpdated() { - tagsUpdated = true; - } - - public static boolean areTagsUpdated() { - return tagsUpdated; - } - public static void enableDataModule() { enableDataModule = true; } @@ -316,6 +267,7 @@ public static void enableDataModule() { @Override public void onInitializeClient() { onInitialize(); + ClientProxy.init(); } @Override @@ -433,14 +385,14 @@ public static void onInitialize() { } KiwiConfigManager.init(); - CommandRegistrationCallback.EVENT.register(KiwiCommand::register); + CommandRegistrationCallback.EVENT.register((dispatcher, context, environment) -> KiwiCommand.register(dispatcher)); ServerLifecycleEvents.SERVER_STARTING.register(Kiwi::serverInit); ServerLifecycleEvents.SERVER_STOPPED.register($ -> currentServer = null); AttackEntityCallback.EVENT.register(KUtil::onAttackEntity); if (Platform.isPhysicalClient()) { - RenderLayerEnum.CUTOUT.value = RenderType.cutout(); - RenderLayerEnum.CUTOUT_MIPPED.value = RenderType.cutoutMipped(); - RenderLayerEnum.TRANSLUCENT.value = RenderType.translucent(); + RenderLayerEnum.CUTOUT.value = ChunkSectionLayer.CUTOUT; + RenderLayerEnum.CUTOUT_MIPPED.value = ChunkSectionLayer.CUTOUT_MIPPED; + RenderLayerEnum.TRANSLUCENT.value = ChunkSectionLayer.TRANSLUCENT; ClientCommandRegistrationCallback.EVENT.register(KiwiClientCommand::register); ClientLifecycleEvents.CLIENT_STARTED.register(Kiwi::clientInit); @@ -580,7 +532,7 @@ private static void preInit() { KiwiModules.fire(KiwiModuleContainer::addRegistries); for (KiwiModuleContainer container : KiwiModules.get()) { - container.loadGameObjects(registryLookup); + container.loadGameObjects(); } KiwiModules.ALL_USED_REGISTRIES.add(Registries.CREATIVE_MODE_TAB); @@ -618,7 +570,6 @@ private static void init() { KiwiConfigManager.refresh(); InitEvent e = new InitEvent(); KiwiModules.fire(m -> m.init(e)); - BlockDefinition.registerFactory(SimpleBlockDefinition.Factory.INSTANCE); } private static void clientInit(Minecraft mc) { diff --git a/src/main/java/snownee/kiwi/KiwiClientConfig.java b/src/main/java/snownee/kiwi/KiwiClientConfig.java index 3f36f7d6..2a47a1fc 100644 --- a/src/main/java/snownee/kiwi/KiwiClientConfig.java +++ b/src/main/java/snownee/kiwi/KiwiClientConfig.java @@ -32,6 +32,9 @@ public final class KiwiClientConfig { @KiwiConfig.Path("debug.tagsTooltip") public static boolean tagsTooltip = true; + @KiwiConfig.Path("debug.F3CopyInInventory") + public static boolean f3CopyInInventory = true; + @KiwiConfig.Path("debug.showTranslatedTagsByDefault") public static boolean showTranslatedTagsByDefault = false; @@ -45,4 +48,7 @@ public final class KiwiClientConfig { @ConfigUI.Hide @KiwiConfig.Path("debug.debugTooltipMsg") public static boolean debugTooltipMsg = true; + + @KiwiModule.Skip + public static boolean exportBlocksMore; } diff --git a/src/main/java/snownee/kiwi/KiwiCommonConfig.java b/src/main/java/snownee/kiwi/KiwiCommonConfig.java index cac27829..fa233d69 100644 --- a/src/main/java/snownee/kiwi/KiwiCommonConfig.java +++ b/src/main/java/snownee/kiwi/KiwiCommonConfig.java @@ -13,4 +13,9 @@ public static boolean getBooleanVar(String key) { return vars.get(key) instanceof Boolean && (Boolean) vars.get(key); } + @KiwiConfig.Path("eval.printExpression") + public static boolean evalPrintExpression = false; + + @KiwiConfig.Path("kSwitch.creativeOnly") + public static boolean kSwitchCreativeOnly; } diff --git a/src/main/java/snownee/kiwi/KiwiGO.java b/src/main/java/snownee/kiwi/KiwiGO.java index 681f6da9..3daa0656 100644 --- a/src/main/java/snownee/kiwi/KiwiGO.java +++ b/src/main/java/snownee/kiwi/KiwiGO.java @@ -1,9 +1,11 @@ package snownee.kiwi; +import java.lang.reflect.Field; import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; +import org.apache.commons.lang3.builder.ToStringBuilder; import org.jetbrains.annotations.Nullable; import net.minecraft.core.Holder; @@ -18,11 +20,16 @@ public class KiwiGO implements Supplier { - private Supplier factory; - private ResourceKey key; - private T value; + @Nullable + protected Supplier factory; + @Nullable + protected ResourceKey key; + @Nullable + protected T value; + @Nullable Field field; + @Nullable GroupSetting groupSetting; - public KiwiGO(Supplier factory) { + public KiwiGO(@Nullable Supplier factory) { this.factory = factory; } @@ -34,12 +41,24 @@ public T get() { public T getOrCreate() { if (value == null) { - value = factory.get(); + Objects.requireNonNull(factory); + value = Objects.requireNonNull(factory.get()); factory = null; } return get(); } + @Nullable + public T preRegister(ResourceLocation id) { + getOrCreate(); + ResourceKey> registryKey = findRegistry(); + //noinspection unchecked,rawtypes + ResourceKey resourceKey = ResourceKey.create((ResourceKey) registryKey, id); + //noinspection unchecked + setKey(resourceKey); + return get(); + } + public void setKey(ResourceKey key) { Objects.requireNonNull(key); if (this.key != null) { @@ -59,18 +78,18 @@ public boolean is(ItemStack stack) { if (key == null || stack.isEmpty()) { return false; } - return stack.is(((ItemLike) value).asItem()); + return stack.is(((ItemLike) get()).asItem()); } public boolean is(BlockState state) { if (key == null) { return false; } - return state.is((Block) value); + return state.is((Block) get()); } public BlockState defaultBlockState() { - return ((Block) value).defaultBlockState(); + return ((Block) get()).defaultBlockState(); } public ItemStack itemStack() { @@ -78,7 +97,7 @@ public ItemStack itemStack() { } public ItemStack itemStack(int amount) { - ItemStack stack = ((ItemLike) value).asItem().getDefaultInstance(); + ItemStack stack = ((ItemLike) get()).asItem().getDefaultInstance(); if (!stack.isEmpty()) { stack.setCount(amount); } @@ -86,16 +105,32 @@ public ItemStack itemStack(int amount) { } public ResourceLocation key() { - return key.location(); + return resourceKey().location(); } public ResourceKey resourceKey() { - return key; + return Objects.requireNonNull(key); + } + + @Nullable + public Field field() { + return field; + } + + @Nullable + public GroupSetting groupSetting() { + return groupSetting; + } + + void register() { + //noinspection unchecked + Registry registry = (Registry) Objects.requireNonNull(BuiltInRegistries.REGISTRY.getValue(resourceKey().registry())); + Registry.register(registry, key(), get()); } @Nullable public ResourceKey> findRegistry() { - return Kiwi.registryLookup.findRegistry(value); + return Kiwi.registryLookup.findRegistry(get()); } public Optional> holder() { @@ -103,15 +138,21 @@ public Optional> holder() { return Optional.empty(); } //noinspection unchecked - Registry registry = (Registry) BuiltInRegistries.REGISTRY.get(key.registry()); + Registry registry = (Registry) BuiltInRegistries.REGISTRY.getValue(key.registry()); if (registry == null) { return Optional.empty(); } - return registry.getHolder(key); + return registry.get(key); } - public static class RegistrySpecified extends KiwiGO { + @Override + public String toString() { + return new ToStringBuilder(this).append("key", key).append("value", value).append("field", field).append( + "groupSetting", + groupSetting).toString(); + } + public static class RegistrySpecified extends KiwiGO { final ResourceKey> registryKey; public RegistrySpecified(Supplier factory, ResourceKey> registryKey) { @@ -125,4 +166,48 @@ public ResourceKey> findRegistry() { } } + public static class Direct extends KiwiGO { + public Direct(T value) { + super(null); + this.value = Objects.requireNonNull(value); + } + } + + public static class Ref extends KiwiGO { + final ResourceKey> registryKey; + + public Ref(ResourceKey> registryKey) { + super(null); + this.registryKey = registryKey; + } + + @Override + @Nullable + public T preRegister(ResourceLocation id) { + //noinspection unchecked + setKey(ResourceKey.create((ResourceKey>) registryKey, id)); + return null; + } + + @Override + public ResourceKey> findRegistry() { + return registryKey; + } + + @Override + public T get() { + if (value == null) { + //noinspection unchecked + Registry registry = (Registry) Objects.requireNonNull(BuiltInRegistries.REGISTRY.getValue(resourceKey().registry())); + value = registry.getValueOrThrow(resourceKey()); + } + return value; + } + + @Override + public T getOrCreate() { + return get(); + } + } + } diff --git a/src/main/java/snownee/kiwi/KiwiGOHolder.java b/src/main/java/snownee/kiwi/KiwiGOHolder.java deleted file mode 100644 index e27428e6..00000000 --- a/src/main/java/snownee/kiwi/KiwiGOHolder.java +++ /dev/null @@ -1,31 +0,0 @@ -package snownee.kiwi; - -import java.lang.reflect.Field; -import java.util.Objects; - -import org.jetbrains.annotations.Nullable; - -import net.minecraft.core.Registry; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceKey; - -public class KiwiGOHolder { - public final T value; - public final ResourceKey key; - @Nullable - public final Field field; - @Nullable - public GroupSetting groupSetting; - - public KiwiGOHolder(T value, ResourceKey key, @Nullable Field field) { - this.value = value; - this.key = key; - this.field = field; - } - - public void register() { - //noinspection unchecked - Registry registry = (Registry) Objects.requireNonNull(BuiltInRegistries.REGISTRY.get(key.registry())); - Registry.register(registry, key, value); - } -} diff --git a/src/main/java/snownee/kiwi/KiwiModuleContainer.java b/src/main/java/snownee/kiwi/KiwiModuleContainer.java index c6f30959..748eb0a3 100644 --- a/src/main/java/snownee/kiwi/KiwiModuleContainer.java +++ b/src/main/java/snownee/kiwi/KiwiModuleContainer.java @@ -19,7 +19,7 @@ import com.google.common.collect.MultimapBuilder.ListMultimapBuilder; import com.google.common.collect.Sets; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; @@ -40,59 +40,59 @@ public final class KiwiModuleContainer { public static final class RegistryEntryStore { - final Multimap> registries = ListMultimapBuilder.linkedHashKeys().linkedListValues().build(); + final Multimap> registries = ListMultimapBuilder.linkedHashKeys().linkedListValues().build(); - void put(KiwiGOHolder entry) { - registries.put(entry.key.registry(), entry); + void put(KiwiGO entry) { + registries.put(entry.resourceKey().registry(), entry); } @SuppressWarnings("unchecked") - Collection> get(ResourceKey> registry) { - return (Collection>) (Object) registries.get(registry.location()); + Collection> get(ResourceKey> registry) { + return (Collection>) (Object) registries.get(registry.location()); } } public final AbstractModule module; public final ModContext context; - public GroupSetting groupSetting; + public @Nullable GroupSetting groupSetting; final RegistryEntryStore registries = new RegistryEntryStore(); Map blockItemBuilders = Maps.newHashMap(); Set noCategories = Sets.newHashSet(); Set noItems = Sets.newHashSet(); - public KiwiModuleContainer(ResourceLocation rl, AbstractModule module, ModContext context) { + public KiwiModuleContainer(ResourceLocation id, AbstractModule module, ModContext context) { this.module = module; this.context = context; - module.uid = rl; + module.uid = id; } - public KiwiGOHolder register(T object, ResourceKey key, @Nullable Field field) { - KiwiGOHolder entry = new KiwiGOHolder<>(object, key, field); - registries.put(entry); - if (field != null) { - KiwiModule.Category group = field.getAnnotation(KiwiModule.Category.class); + public void register(KiwiGO go) { + registries.put(go); + if (go.field != null) { + KiwiModule.Category group = go.field.getAnnotation(KiwiModule.Category.class); if (group != null) { - entry.groupSetting = GroupSetting.of(group, groupSetting); + go.groupSetting = GroupSetting.of(group, groupSetting); } } - return entry; } - public void loadGameObjects(RegistryLookup registryLookup) { + public void loadGameObjects() { context.setActiveContainer(); - boolean useOwnGroup = groupSetting == null; - if (useOwnGroup) { + final boolean useOwnGroup; + if (groupSetting == null) { KiwiModule.Category group = module.getClass().getDeclaredAnnotation(KiwiModule.Category.class); - if (group != null) { - if (group.value().length > 0) { - useOwnGroup = false; - groupSetting = GroupSetting.of(group, null); - } + if (group != null && group.value().length > 0) { + useOwnGroup = false; + groupSetting = GroupSetting.of(group, null); + } else { + useOwnGroup = true; } + } else { + useOwnGroup = false; } - String modid = module.uid.getNamespace(); + String modId = Objects.requireNonNull(module.uid).getNamespace(); Item.Properties tmpBuilder = null; Field tmpBuilderField = null; for (Field field : module.getClass().getFields()) { @@ -108,13 +108,13 @@ public void loadGameObjects(RegistryLookup registryLookup) { ResourceLocation id; KiwiModule.Name nameAnnotation = field.getAnnotation(KiwiModule.Name.class); if (nameAnnotation != null) { - id = KUtil.RL(nameAnnotation.value(), modid); + id = KUtil.RL(nameAnnotation.value(), modId); } else { - id = KUtil.RL(field.getName().toLowerCase(Locale.ENGLISH), modid); + id = KUtil.RL(field.getName().toLowerCase(Locale.ENGLISH), modId); } Objects.requireNonNull(id); - if (field.getType() == module.getClass() && "instance".equals(id.getPath()) && id.getNamespace().equals(modid)) { + if (field.getType() == module.getClass() && "instance".equals(id.getPath()) && id.getNamespace().equals(modId)) { try { field.set(null, module); } catch (IllegalArgumentException | IllegalAccessException e) { @@ -138,56 +138,53 @@ public void loadGameObjects(RegistryLookup registryLookup) { continue; } - ResourceKey> registryKey; - //noinspection rawtypes - ResourceKey resourceKey; - if (o instanceof KiwiGO kiwiGO) { - o = kiwiGO.getOrCreate(); - registryKey = kiwiGO.findRegistry(); - //noinspection unchecked,rawtypes - resourceKey = ResourceKey.create((ResourceKey) registryKey, id); - //noinspection unchecked - kiwiGO.setKey(resourceKey); - } else { - registryKey = registryLookup.findRegistry(o); - if (registryKey == null) { - tmpBuilder = null; - tmpBuilderField = null; + if (!(o instanceof KiwiGO go)) { + continue; + } + try { + go.field = field; + o = go.preRegister(id); + if (go instanceof KiwiGO.Ref) { continue; } - //noinspection unchecked,rawtypes - resourceKey = ResourceKey.create((ResourceKey) registryKey, id); - } - if (o instanceof Block) { - if (field.getAnnotation(KiwiModule.NoItem.class) != null) { - noItems.add((Block) o); + switch (Objects.requireNonNull(o)) { + case Block block -> { + if (field.getAnnotation(KiwiModule.NoItem.class) != null) { + noItems.add(block); + } + checkNoGroup(field, o); + if (tmpBuilder != null) { + blockItemBuilders.put(block, tmpBuilder); + try { + tmpBuilderField.set(module, null); + } catch (Exception e) { + Kiwi.LOGGER.error("Mod %s failed to clean used item builder: %s".formatted(modId, go), e); + } + } + } + case Item item -> checkNoGroup(field, item); + case CreativeModeTab ignored when useOwnGroup && groupSetting == null -> + groupSetting = new GroupSetting(new String[]{id.toString()}, null); + default -> { + } } - checkNoGroup(field, o); - if (tmpBuilder != null) { - blockItemBuilders.put((Block) o, tmpBuilder); - try { - tmpBuilderField.set(module, null); - } catch (Exception e) { - Kiwi.LOGGER.error("Kiwi failed to clean used item builder: %s".formatted(tmpBuilderField), e); + register(go); + if (go.resourceKey().isFor(Registries.MOB_EFFECT)) { + BiConsumer> decorator = module.decorators.get(go.resourceKey().registryKey()); + if (decorator != null) { + decorator.accept(this, go); } + go.register(); } - } else if (o instanceof Item) { - checkNoGroup(field, o); - } else if (useOwnGroup && groupSetting == null && o instanceof CreativeModeTab) { - groupSetting = new GroupSetting(new String[]{id.toString()}, new String[0]); - } - //noinspection unchecked - KiwiGOHolder entry = register(o, resourceKey, field); - if (Registries.MOB_EFFECT == registryKey) { - BiConsumer> decorator = module.decorators.getOrDefault(registryKey, (a, b) -> { - }); - decorator.accept(this, entry); - entry.register(); - } - tmpBuilder = null; - tmpBuilderField = null; + tmpBuilder = null; + tmpBuilderField = null; + } catch (Throwable e) { + String message = "Mod %s failed to register game object: %s".formatted(modId, go); + Kiwi.LOGGER.error(message, e); + throw new IllegalStateException(message, e); + } } } @@ -203,28 +200,30 @@ public void registerGameObjects(ResourceKey> registryKey) return; } context.setActiveContainer(); - Collection> entries = registries.registries.get(registryKey.location()); - BiConsumer> decorator = module.decorators.getOrDefault(registryKey, (a, b) -> { - }); + Collection> entries = registries.registries.get(registryKey.location()); + BiConsumer> decorator = module.decorators.getOrDefault( + registryKey, (a, b) -> { + }); if (Registries.ITEM == registryKey) { registries.get(Registries.BLOCK).forEach(e -> { - if (noItems.contains(e.value)) { + if (noItems.contains(e.get())) { return; } - Item.Properties builder = blockItemBuilders.get(e.value); + Item.Properties builder = blockItemBuilders.get(e.get()); if (builder == null) { builder = new Item.Properties(); } BlockItem item; - if (e.value instanceof IKiwiBlock kiwiBlock) { + if (e.get() instanceof IKiwiBlock kiwiBlock) { item = kiwiBlock.createItem(builder); } else { - item = new ModBlockItem(e.value, builder); + item = new ModBlockItem(e.get(), builder); } - if (noCategories.contains(e.value)) { + if (noCategories.contains(e.get())) { noCategories.add(item); } - KiwiGOHolder itemEntry = new KiwiGOHolder<>(item, ResourceKey.create(Registries.ITEM, e.key.location()), null); + KiwiGO itemEntry = new KiwiGO.Direct<>(item); + itemEntry.preRegister(e.key()); itemEntry.groupSetting = e.groupSetting; entries.add(itemEntry); }); @@ -235,7 +234,7 @@ public void registerGameObjects(ResourceKey> registryKey) groupSettings.add(groupSetting); } entries.forEach(e -> { - Item item = (Item) e.value; + Item item = (Item) e.get(); if (noCategories.contains(item)) { prevSetting.setValue(groupSetting); return; @@ -265,14 +264,14 @@ public void registerGameObjects(ResourceKey> registryKey) noCategories = null; noItems = null; } else if (Registries.BLOCK == registryKey && Platform.isPhysicalClient() && !Platform.isDataGen()) { - final RenderType solid = RenderType.solid(); - Map, RenderType> cache = Maps.newHashMap(); + final ChunkSectionLayer solid = ChunkSectionLayer.SOLID; + Map, ChunkSectionLayer> cache = Maps.newHashMap(); entries.forEach(e -> { - Block block = (Block) e.value; + Block block = (Block) e.get(); if (e.field != null) { KiwiModule.RenderLayer layer = e.field.getAnnotation(KiwiModule.RenderLayer.class); if (layer != null) { - RenderType type = (RenderType) layer.value().value; + ChunkSectionLayer type = (ChunkSectionLayer) layer.value().value; if (type != solid && type != null) { ClientPlatform.setRenderType(block, type); return; @@ -280,17 +279,18 @@ public void registerGameObjects(ResourceKey> registryKey) } } Class klass = block.getClass(); - RenderType type = cache.computeIfAbsent(klass, k -> { - KiwiModule.RenderLayer layer; - while (k != Block.class) { - layer = k.getDeclaredAnnotation(KiwiModule.RenderLayer.class); - if (layer != null) { - return (RenderType) layer.value().value; - } - k = k.getSuperclass(); - } - return solid; - }); + ChunkSectionLayer type = cache.computeIfAbsent( + klass, k -> { + KiwiModule.RenderLayer layer; + while (k != Block.class) { + layer = k.getDeclaredAnnotation(KiwiModule.RenderLayer.class); + if (layer != null) { + return (ChunkSectionLayer) layer.value().value; + } + k = k.getSuperclass(); + } + return solid; + }); if (type != solid && type != null) { ClientPlatform.setRenderType(block, type); } @@ -323,10 +323,10 @@ public void postInit(PostInitEvent event) { } public List getRegistries(ResourceKey> registry) { - return getRegistryEntries(registry).map($ -> $.value).toList(); + return getRegistryEntries(registry).map(KiwiGO::get).toList(); } - public Stream> getRegistryEntries(ResourceKey> registry) { + public Stream> getRegistryEntries(ResourceKey> registry) { return registries.get(registry).stream(); } diff --git a/src/main/java/snownee/kiwi/ModContext.java b/src/main/java/snownee/kiwi/ModContext.java index 3fc95f2d..d0aabf10 100644 --- a/src/main/java/snownee/kiwi/ModContext.java +++ b/src/main/java/snownee/kiwi/ModContext.java @@ -6,10 +6,10 @@ import com.google.common.collect.Maps; public class ModContext { - public static final Map ALL = Maps.newHashMap(); + public static final Map ALL_CONTEXTS = Maps.newHashMap(); public static ModContext get(String modid) { - return ALL.computeIfAbsent(modid, ModContext::new); + return ALL_CONTEXTS.computeIfAbsent(modid, ModContext::new); } private ModContext(String modid) { diff --git a/src/main/java/snownee/kiwi/block/IKiwiBlock.java b/src/main/java/snownee/kiwi/block/IKiwiBlock.java index 3ce13eba..5799b66d 100644 --- a/src/main/java/snownee/kiwi/block/IKiwiBlock.java +++ b/src/main/java/snownee/kiwi/block/IKiwiBlock.java @@ -1,43 +1,20 @@ package snownee.kiwi.block; -import org.jetbrains.annotations.Nullable; - -import net.fabricmc.fabric.api.block.BlockPickInteractionAware; -import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.HitResult; import snownee.kiwi.item.ModBlockItem; -public interface IKiwiBlock extends BlockPickInteractionAware { - - default MutableComponent getName(ItemStack stack) { - return Component.translatable(stack.getDescriptionId()); +public interface IKiwiBlock { + default Component getName(ItemStack stack) { + return stack.getComponents().getOrDefault(DataComponents.ITEM_NAME, CommonComponents.EMPTY); } default BlockItem createItem(Item.Properties builder) { return new ModBlockItem((Block) this, builder); } - - default ItemStack getCloneItemStack( - LevelReader level, - BlockPos blockPos, - BlockState blockState, - @Nullable Player player, - @Nullable HitResult hit) { - return ModBlock.pickBlockEntityData(level, blockPos, blockState, blockState.getBlock().getCloneItemStack(level, blockPos, blockState)); - } - - @Override - default ItemStack getPickedStack(BlockState state, BlockGetter view, BlockPos pos, Player player, HitResult result) { - return getCloneItemStack(player.level(), pos, state, player, result); - } } diff --git a/src/main/java/snownee/kiwi/block/ModBlock.java b/src/main/java/snownee/kiwi/block/ModBlock.java index 9d71ae8a..218a227e 100644 --- a/src/main/java/snownee/kiwi/block/ModBlock.java +++ b/src/main/java/snownee/kiwi/block/ModBlock.java @@ -1,12 +1,14 @@ package snownee.kiwi.block; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.TagValueOutput; +import snownee.kiwi.Kiwi; import snownee.kiwi.block.entity.ModBlockEntity; /** @@ -14,17 +16,19 @@ */ public class ModBlock extends Block implements IKiwiBlock { - public ModBlock(Block.Properties builder) { + public ModBlock(Properties builder) { super(builder); } public static ItemStack pickBlockEntityData(LevelReader level, BlockPos pos, BlockState blockState, ItemStack itemStack) { if (blockState.hasBlockEntity() && level.getBlockEntity(pos) instanceof ModBlockEntity be && be.persistData) { - CompoundTag data = be.saveWithFullMetadata(level.registryAccess()); - data.remove("x"); - data.remove("y"); - data.remove("z"); - BlockItem.setBlockEntityData(itemStack, be.getType(), data); + try (ProblemReporter.ScopedCollector collector = new ProblemReporter.ScopedCollector(be.problemPath(), Kiwi.LOGGER)) { + TagValueOutput tagValueOutput = TagValueOutput.createWithContext(collector, level.registryAccess()); + be.saveCustomOnly(tagValueOutput); + be.removeComponentsFromTag(tagValueOutput); + BlockItem.setBlockEntityData(itemStack, be.getType(), tagValueOutput); + itemStack.applyComponents(be.collectComponents()); + } } return itemStack; } diff --git a/src/main/java/snownee/kiwi/block/def/BlockDefinition.java b/src/main/java/snownee/kiwi/block/def/BlockDefinition.java deleted file mode 100644 index 49e264ae..00000000 --- a/src/main/java/snownee/kiwi/block/def/BlockDefinition.java +++ /dev/null @@ -1,138 +0,0 @@ -package snownee.kiwi.block.def; - -import java.util.List; -import java.util.Map; - -import org.jetbrains.annotations.Nullable; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.Material; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.HitResult; - -public interface BlockDefinition { - - Map> MAP = Maps.newConcurrentMap(); - List> FACTORIES = Lists.newLinkedList(); - - static void registerFactory(Factory factory) { - MAP.put(factory.getId(), factory); - if (SimpleBlockDefinition.TYPE.equals(factory.getId())) { - FACTORIES.add(factory); - } else { - FACTORIES.add(0, factory); - } - } - - static BlockDefinition fromNBT(CompoundTag tag) { - Factory factory = MAP.get(tag.getString("Type")); - if (factory == null) { - return null; - } - return factory.fromNBT(tag); - } - - static BlockDefinition fromBlock(BlockState state, BlockEntity blockEntity, LevelReader level, BlockPos pos) { - for (Factory factory : FACTORIES) { - BlockDefinition supplier = factory.fromBlock(state, blockEntity, level, pos); - if (supplier != null) { - return supplier; - } - } - return null; - } - - static BlockDefinition fromItem(ItemStack stack, @Nullable BlockPlaceContext context) { - if (!stack.isEmpty()) { - for (Factory factory : FACTORIES) { - BlockDefinition supplier = factory.fromItem(stack, context); - if (supplier != null) { - return supplier; - } - } - } - return null; - } - - Factory getFactory(); - - @Environment(EnvType.CLIENT) - BakedModel model(); - - // @Environment(EnvType.CLIENT) - // default IModelData modelData() { - // return EmptyModelData.INSTANCE; - // } - - @Environment(EnvType.CLIENT) - Material renderMaterial(@Nullable Direction direction); - - void save(CompoundTag tag); - - @Environment(EnvType.CLIENT) - boolean canRenderInLayer(RenderType layer); - - boolean canOcclude(); - - @Environment(EnvType.CLIENT) - int getColor(BlockState blockState, BlockAndTintGetter level, BlockPos pos, int index); - - Component getDescription(); - - void place(Level level, BlockPos pos); - - ItemStack createItem(HitResult target, LevelReader world, @Nullable BlockPos pos, @Nullable Player player); - - BlockState getBlockState(); - - default BlockDefinition getCamoDefinition() { - return null; - } - - static BlockDefinition getCamo(BlockDefinition definition) { - BlockDefinition camo = definition.getCamoDefinition(); - while (camo != null && camo != definition) { - definition = camo; - camo = definition.getCamoDefinition(); - } - return definition; - } - - default int getLightEmission(BlockGetter level, BlockPos pos) { - return getBlockState().getLightEmission(); - } - - SoundType getSoundType(); - - interface Factory { - T fromNBT(CompoundTag tag); - - String getId(); - - @Nullable - T fromBlock(BlockState state, BlockEntity blockEntity, LevelReader level, BlockPos pos); - - @Nullable - T fromItem(ItemStack stack, @Nullable BlockPlaceContext context); - } - -} diff --git a/src/main/java/snownee/kiwi/block/def/SimpleBlockDefinition.java b/src/main/java/snownee/kiwi/block/def/SimpleBlockDefinition.java deleted file mode 100644 index 62b82c4b..00000000 --- a/src/main/java/snownee/kiwi/block/def/SimpleBlockDefinition.java +++ /dev/null @@ -1,248 +0,0 @@ -package snownee.kiwi.block.def; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.jetbrains.annotations.Nullable; - -import com.google.common.collect.Maps; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.block.BlockPickInteractionAware; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.ItemBlockRenderTypes; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.texture.TextureAtlas; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.Material; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.phys.HitResult; -import snownee.kiwi.loader.Platform; - -public class SimpleBlockDefinition implements BlockDefinition { - - public static final MethodHandle GET_STATE_FOR_PLACEMENT; - - static { - MethodHandle m = null; - try { - // getPlacementState - String methodName = FabricLoader.getInstance().getMappingResolver().mapMethodName( - "intermediary", - "net.minecraft.class_1747", - "method_7707", - "(Lnet/minecraft/class_1750;)Lnet/minecraft/class_2680;"); - m = MethodHandles.lookup().unreflect(BlockItem.class.getDeclaredMethod(methodName, BlockPlaceContext.class)); - } catch (Exception e) { - throw new RuntimeException("Report this to author", e); - } - GET_STATE_FOR_PLACEMENT = m; - } - - @Nullable - private static BlockState getStateForPlacement(BlockItem blockItem, BlockPlaceContext context) { - try { - return (BlockState) GET_STATE_FOR_PLACEMENT.invokeExact(blockItem, context); - } catch (Throwable e) { - return null; - } - } - - public enum Factory implements BlockDefinition.Factory { - INSTANCE; - - @Override - public SimpleBlockDefinition fromNBT(CompoundTag tag) { - BlockState state = NbtUtils.readBlockState(BuiltInRegistries.BLOCK.asLookup(), tag.getCompound(TYPE)); - if (state.isAir()) { - return null; - } - return of(state); - } - - @Override - public SimpleBlockDefinition fromBlock(BlockState state, BlockEntity blockEntity, LevelReader level, BlockPos pos) { - return of(state); - } - - @Override - public SimpleBlockDefinition fromItem(ItemStack stack, BlockPlaceContext context) { - if (!(stack.getItem() instanceof BlockItem)) { - return null; - } - BlockItem blockItem = (BlockItem) stack.getItem(); - if (context == null) { - return of(blockItem.getBlock().defaultBlockState()); - } - context = blockItem.updatePlacementContext(context); - if (context == null) { - return null; - } - BlockState state = getStateForPlacement(blockItem, context); - if (state == null) { - return null; - } - return of(state); - } - - @Override - public String getId() { - return TYPE; - } - - } - - public static final String TYPE = "Block"; - private static final Map MAP = Maps.newIdentityHashMap(); - - public static SimpleBlockDefinition of(BlockState state) { - if (state.getBlock() == Blocks.GRASS_BLOCK) { - state = state.setValue(BlockStateProperties.SNOWY, false); - } - return MAP.computeIfAbsent(state, SimpleBlockDefinition::new); - } - - public final BlockState state; - @Environment(EnvType.CLIENT) - private Material[] materials; - - private SimpleBlockDefinition(BlockState state) { - this.state = state; - if (Platform.isPhysicalClient()) { - materials = new Material[7]; - } - } - - @Override - public BlockDefinition.Factory getFactory() { - return Factory.INSTANCE; - } - - @Override - @Environment(EnvType.CLIENT) - public BakedModel model() { - return Minecraft.getInstance().getBlockRenderer().getBlockModelShaper().getBlockModel(state); - } - - @SuppressWarnings("deprecation") - @Override - @Environment(EnvType.CLIENT) - public Material renderMaterial(Direction direction) { - int index = direction == null ? 0 : direction.ordinal() + 1; - if (materials[index] == null) { - BakedModel model = model(); - RandomSource random = RandomSource.create(); - random.setSeed(42L); - ResourceLocation particleIcon = model.getParticleIcon().contents().name(); - ResourceLocation sprite = particleIcon; - if (state.getBlock() == Blocks.GRASS_BLOCK) { - direction = Direction.UP; - } - if (direction != null) { - List quads = model.getQuads(state, direction, random); - if (quads.isEmpty()) { - quads = model.getQuads(state, null, random); - } - for (BakedQuad quad : quads) { - sprite = quad.getSprite().contents().name(); - if (sprite.equals(particleIcon)) { - break; - } - } - } - materials[index] = new Material(TextureAtlas.LOCATION_BLOCKS, sprite); - } - return materials[index]; - } - - @Override - @Environment(EnvType.CLIENT) - public boolean canRenderInLayer(RenderType layer) { - return ItemBlockRenderTypes.getRenderType(state, false) == layer; - } - - @Override - public boolean canOcclude() { - return state.canOcclude(); - } - - @Override - public void save(CompoundTag tag) { - tag.put(TYPE, NbtUtils.writeBlockState(state)); - } - - @Override - public String toString() { - return state.toString(); - } - - @Override - @Environment(EnvType.CLIENT) - public int getColor(BlockState blockState, BlockAndTintGetter level, BlockPos worldPosition, int index) { - return Minecraft.getInstance().getBlockColors().getColor(state, level, worldPosition, index); - } - - @Override - public Component getDescription() { - return state.getBlock().getName(); - } - - @Override - public void place(Level level, BlockPos pos) { - BlockState state = this.state; - if (state.hasProperty(BlockStateProperties.LIT)) { - state = state.setValue(BlockStateProperties.LIT, false); - } - level.setBlockAndUpdate(pos, state); - } - - @Override - public ItemStack createItem(HitResult target, LevelReader world, BlockPos pos, Player player) { - if (state.getBlock() instanceof BlockPickInteractionAware) { - return (((BlockPickInteractionAware) state.getBlock()).getPickedStack(state, world, pos, player, target)); - } - return state.getBlock().getCloneItemStack(world, pos, state); - } - - @Override - public BlockState getBlockState() { - return state; - } - - @Override - public SoundType getSoundType() { - return state.getSoundType(); - } - - public static void reload() { - for (SimpleBlockDefinition supplier : MAP.values()) { - Arrays.fill(supplier.materials, null); - } - } - -} diff --git a/src/main/java/snownee/kiwi/block/entity/InheritanceBlockEntityType.java b/src/main/java/snownee/kiwi/block/entity/InheritanceBlockEntityType.java index 17ee8304..64016934 100644 --- a/src/main/java/snownee/kiwi/block/entity/InheritanceBlockEntityType.java +++ b/src/main/java/snownee/kiwi/block/entity/InheritanceBlockEntityType.java @@ -2,23 +2,21 @@ import java.util.Set; -import com.mojang.datafixers.types.Type; - -import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; +import net.fabricmc.fabric.impl.object.builder.ExtendedBlockEntityType; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -public class InheritanceBlockEntityType extends BlockEntityType { +public class InheritanceBlockEntityType extends ExtendedBlockEntityType { private final Class clazz; public InheritanceBlockEntityType( - FabricBlockEntityTypeBuilder.Factory factory, + BlockEntityType.BlockEntitySupplier factory, Class clazz, - Type datafixer) { - super(factory::create, Set.of(), datafixer); + boolean onlyOpCanSetNbt) { + super(factory, Set.of(), onlyOpCanSetNbt); this.clazz = clazz; } diff --git a/src/main/java/snownee/kiwi/block/entity/ModBlockEntity.java b/src/main/java/snownee/kiwi/block/entity/ModBlockEntity.java index 57e1e6ab..de034993 100644 --- a/src/main/java/snownee/kiwi/block/entity/ModBlockEntity.java +++ b/src/main/java/snownee/kiwi/block/entity/ModBlockEntity.java @@ -7,9 +7,13 @@ import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientGamePacketListener; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.TagValueOutput; +import net.minecraft.world.level.storage.ValueInput; +import net.minecraft.world.level.storage.ValueOutput; import snownee.kiwi.util.NotNullByDefault; /** @@ -29,30 +33,31 @@ public Packet getUpdatePacket() { return ClientboundBlockEntityDataPacket.create(this); } - public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { - readPacketData(pkt.getTag()); + public void onDataPacket(Connection net, ValueInput valueInput) { + readPacketData(valueInput); } // Used for syncing data at the time when the chunk is loaded @Override public CompoundTag getUpdateTag(HolderLookup.Provider provider) { - return writePacketData(new CompoundTag(), provider); + TagValueOutput valueOutput = TagValueOutput.createWithContext(ProblemReporter.DISCARDING, provider); + writePacketData(valueOutput); + return valueOutput.buildResult(); } /** * Read data for server-client syncing. * - * @param data the data source + * @param valueInput the data source */ - protected abstract void readPacketData(CompoundTag data); + protected abstract void readPacketData(ValueInput valueInput); /** * Write data for server-client syncing. ONLY write the necessary data! * - * @param data the data sink - * @return the parameter, or delegate to super method + * @param valueOutput the data sink */ - protected abstract CompoundTag writePacketData(CompoundTag data, HolderLookup.Provider provider); + protected abstract void writePacketData(ValueOutput valueOutput); public void refresh() { if (hasLevel() && !level.isClientSide) { diff --git a/src/main/java/snownee/kiwi/block/entity/RetextureBlockEntity.java b/src/main/java/snownee/kiwi/block/entity/RetextureBlockEntity.java deleted file mode 100644 index 134acf80..00000000 --- a/src/main/java/snownee/kiwi/block/entity/RetextureBlockEntity.java +++ /dev/null @@ -1,169 +0,0 @@ -package snownee.kiwi.block.entity; - -import java.util.Map; -import java.util.Objects; - -import org.jetbrains.annotations.Nullable; - -import com.google.common.base.Predicate; -import com.google.common.collect.Maps; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import snownee.kiwi.block.def.BlockDefinition; -import snownee.kiwi.block.def.SimpleBlockDefinition; -import snownee.kiwi.util.NBTHelper; -import snownee.kiwi.util.NotNullByDefault; - -@NotNullByDefault -public abstract class RetextureBlockEntity extends ModBlockEntity { - @Nullable - protected Map textures; - // /** Do not get modelData directly, use getModelData() */ - // protected IModelData modelData = EmptyModelData.INSTANCE; - - public RetextureBlockEntity(BlockEntityType tileEntityTypeIn, BlockPos level, BlockState state, String... textureKeys) { - super(tileEntityTypeIn, level, state); - persistData = true; - textures = textureKeys.length == 0 ? null : Maps.newHashMapWithExpectedSize(textureKeys.length); - for (String key : textureKeys) { - textures.put(key, null); - } - } - - public static void setTexture(Map textures, String key, String path) { - if (!textures.containsKey(key)) { - return; - } - textures.put(key, path); - } - - public void setTexture(String key, @Nullable BlockDefinition modelSupplier) { - if (modelSupplier == null || !isValidTexture(modelSupplier)) { - return; - } - setTexture(textures, key, modelSupplier); - } - - public boolean isValidTexture(BlockDefinition modelSupplier) { - return true; - } - - public static void setTexture(@Nullable Map textures, String key, BlockDefinition modelSupplier) { - if (textures == null || !textures.containsKey(key)) { - return; - } - textures.put(key, modelSupplier); - } - - public static void setTexture(Map textures, String key, Item item) { - Block block = Block.byItem(item); - if (block != Blocks.AIR) { - setTexture(textures, key, SimpleBlockDefinition.of(block.defaultBlockState())); - } - } - - @Override - public void refresh() { - if (level != null && level.isClientSide) { - // requestModelDataUpdate(); - } else { - super.refresh(); - } - } - - // @Override - // public void onLoad() { - // super.requestModelDataUpdate(); - // } - - // @Override - // public void requestModelDataUpdate() { - // if (textures == null) { - // return; - // } - // super.requestModelDataUpdate(); - // if (!remove && level != null && level.isClientSide) { - // level.sendBlockUpdated(worldPosition, getBlockState(), getBlockState(), 8); - // } - // } - - @Override - protected void readPacketData(CompoundTag data) { - if (!data.contains("Overrides", Tag.TAG_COMPOUND)) { - return; - } - boolean shouldRefresh = readTextures(textures, data.getCompound("Overrides"), this::isValidTexture); - if (shouldRefresh) { - refresh(); - } - } - - public static boolean readTextures( - @Nullable Map textures, - CompoundTag data, - Predicate validator) { - if (textures == null) { - return false; - } - boolean shouldRefresh = false; - NBTHelper helper = NBTHelper.of(data); - for (String k : textures.keySet()) { - CompoundTag v = helper.getTag(k); - if (v == null) { - continue; - } - BlockDefinition supplier = BlockDefinition.fromNBT(v); - if (supplier != null && !validator.test(supplier)) { - continue; - } - if (!Objects.equals(textures.get(k), supplier)) { - shouldRefresh = true; - textures.put(k, supplier); - } - } - return shouldRefresh; - } - - @Override - protected CompoundTag writePacketData(CompoundTag data, HolderLookup.Provider provider) { - writeTextures(textures, data); - return data; - } - - public static CompoundTag writeTextures(@Nullable Map textures, CompoundTag data) { - if (textures != null) { - NBTHelper tag = NBTHelper.of(data); - textures.forEach((k, v) -> { - if (v == null) { - return; - } - CompoundTag compound = new CompoundTag(); - v.save(compound); - compound.putString("Type", v.getFactory().getId()); - tag.setTag("Overrides." + k, compound); - }); - } - return data; - } - - // @Override - // public IModelData getModelData() { - // if (textures != null && modelData == EmptyModelData.INSTANCE) { - // modelData = new ModelDataMap.Builder().withInitial(RetextureModel.TEXTURES, textures).build(); - // } - // return modelData; - // } - - // @Environment(EnvType.CLIENT) - // public int getColor(BlockAndTintGetter level, int index) { - // return RetextureModel.getColor(textures, getBlockState(), level, worldPosition, index); - // } -} diff --git a/src/main/java/snownee/kiwi/client/TooltipEvents.java b/src/main/java/snownee/kiwi/client/TooltipEvents.java index e4c0bc16..67a15182 100644 --- a/src/main/java/snownee/kiwi/client/TooltipEvents.java +++ b/src/main/java/snownee/kiwi/client/TooltipEvents.java @@ -2,6 +2,7 @@ import java.util.Comparator; import java.util.List; +import java.util.Optional; import java.util.function.IntConsumer; import java.util.stream.Stream; @@ -12,16 +13,16 @@ import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.resources.language.I18n; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.ClickEvent; -import net.minecraft.network.chat.ClickEvent.Action; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.contents.TranslatableContents; +import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.BucketItem; @@ -36,9 +37,10 @@ import snownee.kiwi.config.KiwiConfigManager; import snownee.kiwi.item.ModItem; import snownee.kiwi.loader.Platform; +import snownee.kiwi.util.KUtil; public final class TooltipEvents { - public static final String disableDebugTooltipCommand = "@kiwi disable debugTooltip"; + public static final ResourceLocation DISABLE_DEBUG_TOOLTIP = Kiwi.id("disable_debug_tooltip"); private static final DebugTooltipCache cache = new DebugTooltipCache(); private static boolean firstSeenDebugTooltip = true; private static long latestPressF3; @@ -56,23 +58,18 @@ public static void globalTooltip(ItemStack stack, List tooltip, Toolt } public static void debugTooltip(ItemStack itemStack, List tooltip, TooltipFlag flag) { - if (!Kiwi.areTagsUpdated() || !flag.isAdvanced()) { + if (!flag.isAdvanced()) { return; } Minecraft mc = Minecraft.getInstance(); long millis = Util.getMillis(); - if (mc.player != null && millis - latestPressF3 > 500 && InputConstants.isKeyDown( - Minecraft.getInstance().getWindow().getWindow(), - InputConstants.KEY_F3)) { + if (KiwiClientConfig.f3CopyInInventory && mc.player != null && millis - latestPressF3 > 500 && + InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), InputConstants.KEY_F3)) { latestPressF3 = millis; MutableComponent component = Component.literal(BuiltInRegistries.ITEM.getKey(itemStack.getItem()).toString()); mc.keyboardHandler.setClipboard(component.getString()); - component.withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, component.getString())) - .withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Component.translatable("chat.copy.click"))) - .withInsertion(component.getString())); - mc.player.displayClientMessage(component, false); - mc.gui.getDebugOverlay().toggleOverlay(); + mc.player.displayClientMessage(KUtil.clickToCopy(component), false); } if (KiwiClientConfig.hideDataComponentsTooltip) { @@ -108,10 +105,11 @@ private static void trySendTipMsg(Minecraft mc) { if (firstSeenDebugTooltip && mc.player != null) { firstSeenDebugTooltip = false; if (KiwiClientConfig.debugTooltipMsg) { - MutableComponent clickHere = Component.translatable("tip.kiwi.click_here").withStyle($ -> $.withClickEvent(new ClickEvent( - Action.COPY_TO_CLIPBOARD, - disableDebugTooltipCommand))); - mc.player.sendSystemMessage(Component.translatable("tip.kiwi.debug_tooltip", clickHere.withStyle(ChatFormatting.AQUA))); + MutableComponent clickHere = Component.translatable("tip.kiwi.click_here") + .withStyle($ -> $.withClickEvent(new ClickEvent.Custom(DISABLE_DEBUG_TOOLTIP, Optional.empty()))); + mc.player.displayClientMessage( + Component.translatable("tip.kiwi.debug_tooltip", clickHere.withStyle(ChatFormatting.AQUA)), + false); KiwiClientConfig.debugTooltipMsg = false; KiwiConfigManager.getHandler(KiwiClientConfig.class).save(); } @@ -144,8 +142,9 @@ public void maybeUpdateTags(ItemStack itemStack) { if (block != Blocks.AIR) { addPages("block", getTags(BuiltInRegistries.BLOCK, block)); } - if (item instanceof SpawnEggItem spawnEggItem) { - EntityType type = spawnEggItem.getType(itemStack); + ClientLevel level = Minecraft.getInstance().level; + if (level != null && item instanceof SpawnEggItem spawnEggItem) { + EntityType type = spawnEggItem.getType(level.registryAccess(), itemStack); addPages("entity_type", getTags(BuiltInRegistries.ENTITY_TYPE, type)); } else if (item instanceof BucketItem bucketItem) { addPages("fluid", getTags(BuiltInRegistries.FLUID, Platform.getFluidFromBucket(bucketItem))); @@ -159,10 +158,7 @@ public void maybeUpdateTags(ItemStack itemStack) { } private static Stream> getTags(Registry registry, T object) { - return registry.getResourceKey(object) - .flatMap(registry::getHolder) - .stream() - .flatMap(Holder::tags); + return registry.getResourceKey(object).flatMap(registry::get).stream().flatMap(Holder::tags); } public void addPages(String type, Stream> stream) { @@ -222,10 +218,11 @@ public void appendTagsTooltip(List tooltip) { for (String tag : page) { sub.add(Component.literal(tag).withStyle(ChatFormatting.DARK_GRAY)); } - int index = findIdLine(tooltip, i -> { - String type = pageTypes.get(pageNow); - tooltip.set(i, tooltip.get(i).copy().append(" (%s/%s...%s)".formatted(pageNow + 1, pages.size(), type))); - }); + int index = findIdLine( + tooltip, i -> { + String type = pageTypes.get(pageNow); + tooltip.set(i, tooltip.get(i).copy().append(" (%s/%s...%s)".formatted(pageNow + 1, pages.size(), type))); + }); index = index == -1 ? tooltip.size() : index + 1; tooltip.addAll(index, sub); } diff --git a/src/main/java/snownee/kiwi/client/model/RetextureModel.java b/src/main/java/snownee/kiwi/client/model/RetextureModel.java deleted file mode 100644 index 8ec09dd2..00000000 --- a/src/main/java/snownee/kiwi/client/model/RetextureModel.java +++ /dev/null @@ -1,350 +0,0 @@ -/* -package snownee.kiwi.client.model; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; - -import org.apache.commons.lang3.StringUtils; - -import com.google.common.base.Predicates; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonObject; - -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.block.model.BlockModel; -import net.minecraft.client.renderer.block.model.ItemOverrides; -import net.minecraft.client.renderer.block.model.ItemTransforms; -import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.resources.model.BakedModel; -import net.minecraft.client.resources.model.Material; -import net.minecraft.client.resources.model.ModelBakery; -import net.minecraft.client.resources.model.ModelState; -import net.minecraft.client.resources.model.UnbakedModel; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockAndTintGetter; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.MinecraftForgeClient; -import net.minecraftforge.client.model.BlockModelConfiguration; -import net.minecraftforge.client.model.ForgeModelBakery; -import net.minecraftforge.client.model.IModelConfiguration; -import net.minecraftforge.client.model.IModelLoader; -import net.minecraftforge.client.model.data.IDynamicBakedModel; -import net.minecraftforge.client.model.data.IModelData; -import net.minecraftforge.client.model.data.ModelProperty; -import net.minecraftforge.client.model.geometry.IModelGeometry; -import net.minecraftforge.common.util.Lazy; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import snownee.kiwi.KiwiModule.Subscriber.Bus; -import snownee.kiwi.block.def.BlockDefinition; -import snownee.kiwi.block.entity.RetextureBlockEntity; -import snownee.kiwi.util.NBTHelper; - -@EventBusSubscriber(bus = Bus.MOD, value = Dist.CLIENT) -@Environment(EnvType.CLIENT) -public class RetextureModel implements IDynamicBakedModel { - public static ModelProperty> TEXTURES = new ModelProperty<>(); - - public static class ModelConfiguration implements IModelConfiguration { - - private final IModelConfiguration baseConfiguration; - private final Map overrides; - - public ModelConfiguration(IModelConfiguration baseConfiguration, Map overrides) { - this.baseConfiguration = baseConfiguration; - this.overrides = overrides; - } - - @Override - public UnbakedModel getOwnerModel() { - return baseConfiguration.getOwnerModel(); - } - - @Override - public String getModelName() { - return baseConfiguration.getModelName(); - } - - @Override - public boolean isTexturePresent(String name) { - return baseConfiguration.isTexturePresent(name); - } - - @Override - public Material resolveTexture(String name) { - if (name.charAt(0) == '#') { - String ref = name.substring(1); - int i = ref.lastIndexOf('_'); - if (i != -1) { - String ref0 = ref.substring(0, i); - BlockDefinition supplier = overrides.get(ref0); - if (supplier != null) { - Direction direction = Direction.byName(ref.substring(i + 1)); - return supplier.renderMaterial(direction); - } - } - BlockDefinition supplier = overrides.get(ref); - if (supplier != null) { - return supplier.renderMaterial(null); - } - } - return baseConfiguration.resolveTexture(name); - } - - @Override - public boolean isShadedInGui() { - return baseConfiguration.isShadedInGui(); - } - - @Override - public boolean isSideLit() { - return baseConfiguration.isSideLit(); - } - - @Override - public boolean useSmoothLighting() { - return baseConfiguration.useSmoothLighting(); - } - - @Override - public ItemTransforms getCameraTransforms() { - return baseConfiguration.getCameraTransforms(); - } - - @Override - public ModelState getCombinedTransform() { - return baseConfiguration.getCombinedTransform(); - } - - } - - public static class Geometry implements IModelGeometry { - - private final ResourceLocation loaderId; - private final Lazy blockModel; - private final String particle; - private final boolean inventory; - - public Geometry(Lazy blockModel, ResourceLocation loaderId, String particle, boolean inventory) { - this.blockModel = blockModel; - this.loaderId = loaderId; - this.particle = particle; - this.inventory = inventory; - } - - @Override - public BakedModel bake(IModelConfiguration owner, ModelBakery bakery, Function spriteGetter, ModelState modelTransform, ItemOverrides overrides, ResourceLocation modelLocation) { - return new RetextureModel(bakery, modelTransform, loaderId, blockModel.get().customData, particle, inventory); - } - - @Override - public Collection getTextures(IModelConfiguration owner, Function modelGetter, Set> missingTextureErrors) { - return blockModel.get().getMaterials(modelGetter, missingTextureErrors); - } - - } - - public static class Loader implements IModelLoader { - - public static final Loader INSTANCE = new Loader(); - - private Loader() { - } - - @Override - public void onResourceManagerReload(ResourceManager resourceManager) { - } - - @Override - public Geometry read(JsonDeserializationContext deserializationContext, JsonObject modelContents) { - ResourceLocation loaderId = new ResourceLocation(GsonHelper.getAsString(modelContents, "base_loader", "elements")); - Lazy blockModel = Lazy.of(() -> (BlockModel) ForgeModelBakery.instance().getModel(new ResourceLocation(GsonHelper.getAsString(modelContents, "base")))); - return new Geometry(blockModel, loaderId, GsonHelper.getAsString(modelContents, "particle", "0"), GsonHelper.getAsBoolean(modelContents, "inventory", true)); - } - - } - - private final ModelBakery modelLoader; - private final ModelState variant; - private final ResourceLocation loaderId; - private ItemOverrides overrideList; - private final Cache baked = CacheBuilder.newBuilder().expireAfterAccess(500L, TimeUnit.SECONDS).build(); - private final BlockModelConfiguration baseConfiguration; - private final String particleKey; - - public RetextureModel(ModelBakery modelLoader, ModelState variant, ResourceLocation loaderId, BlockModelConfiguration baseConfiguration, String particleKey, boolean inventory) { - this.modelLoader = modelLoader; - this.variant = variant; - this.loaderId = loaderId; - this.baseConfiguration = baseConfiguration; - overrideList = inventory ? new Overrides(this) : ItemOverrides.EMPTY; - this.particleKey = particleKey; - } - - @Override - public boolean useAmbientOcclusion() { - return baseConfiguration.useSmoothLighting(); - } - - @Override - public boolean isGui3d() { - return baseConfiguration.isShadedInGui(); - } - - @Override - public boolean isCustomRenderer() { - return false; - } - - @Override - public TextureAtlasSprite getParticleIcon(IModelData data) { - if (data.getData(TEXTURES) != null) { - BlockDefinition supplier = data.getData(TEXTURES).get(particleKey); - if (supplier != null) { - Material material = supplier.renderMaterial(null); - TextureAtlasSprite particle = ForgeModelBakery.defaultTextureGetter().apply(material); - if (particle.getClass() != MissingTextureAtlasSprite.class) { - return particle; - } - } - } - return getParticleIcon(); - } - - @Override - public TextureAtlasSprite getParticleIcon() { - return modelLoader.getSpriteMap().getSprite(baseConfiguration.resolveTexture("particle")); - } - - @Override - public ItemOverrides getOverrides() { - return overrideList; - } - - @Override - public ItemTransforms getTransforms() { - return baseConfiguration.getCameraTransforms(); - } - - @Override - public List getQuads(BlockState state, Direction side, Random rand, IModelData extraData) { - Map overrides = extraData.getData(TEXTURES); - if (overrides == null) - overrides = Collections.EMPTY_MAP; - RenderType layer = MinecraftForgeClient.getRenderType(); - boolean noSupplier = true; - if (layer != null) { - for (BlockDefinition supplier : overrides.values()) { - if (supplier != null) { - noSupplier = false; - if (supplier.canRenderInLayer(layer)) { - BakedModel model = getModel(overrides); - return model.getQuads(state, side, rand, extraData); - } - } - } - } - if (layer == null || (noSupplier && layer == RenderType.solid())) { - BakedModel model = getModel(overrides); - return model.getQuads(state, side, rand, extraData); - } - return Collections.EMPTY_LIST; - } - - public BakedModel getModel(Map overrides) { - String key = generateKey(overrides); - try { - return baked.get(key, () -> { - ModelConfiguration configuration = new ModelConfiguration(baseConfiguration, overrides); - return baseConfiguration.getCustomGeometry().bake(configuration, modelLoader, ForgeModelBakery.defaultTextureGetter(), variant, overrideList, loaderId); - }); - } catch (Exception e) { - e.printStackTrace(); - } - return Minecraft.getInstance().getModelManager().getMissingModel(); - } - - private static String generateKey(Map overrides) { - if (overrides == null) { - return ""; - } else { - return StringUtils.join(overrides.entrySet(), ','); - } - } - - public static class Overrides extends ItemOverrides { - private final RetextureModel baked; - private final Cache cache = CacheBuilder.newBuilder().maximumSize(100L).expireAfterWrite(300L, TimeUnit.SECONDS).weakKeys().build(); - - public Overrides(RetextureModel model) { - baked = model; - } - - @Override - public BakedModel resolve(BakedModel model, ItemStack stack, ClientLevel worldIn, LivingEntity entityIn, int seed) { - if (model instanceof RetextureModel) { - try { - model = cache.get(stack, () -> { - return baked.getModel(overridesFromItem(stack)); - }); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } - return model; - } - - public static Map overridesFromItem(ItemStack stack) { - CompoundTag data = NBTHelper.of(stack).getTag("BlockEntityTag.Overrides"); - if (data == null) - data = new CompoundTag(); - Set keySet = data.getAllKeys(); - Map overrides = Maps.newHashMapWithExpectedSize(keySet.size()); - keySet.forEach(k -> overrides.put(k, null)); - RetextureBlockEntity.readTextures(overrides, data, Predicates.alwaysTrue()); - return overrides; - } - - @Override - public ImmutableList getOverrides() { - return ImmutableList.of(); - } - } - - @Override - public boolean usesBlockLight() { - return baseConfiguration.isSideLit(); - } - - public static int getColor(Map textures, BlockState state, BlockAndTintGetter level, BlockPos pos, int index) { - BlockDefinition supplier = textures.get(Integer.toString(index)); - if (supplier != null) - return supplier.getColor(state, level, pos, index); - return -1; - } -} -*/ \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/command/KiwiClientCommand.java b/src/main/java/snownee/kiwi/command/KiwiClientCommand.java index 1b7f07a2..6fcbefe5 100644 --- a/src/main/java/snownee/kiwi/command/KiwiClientCommand.java +++ b/src/main/java/snownee/kiwi/command/KiwiClientCommand.java @@ -58,7 +58,7 @@ private static void putMods( ctx.getSource().sendFeedback(Component.translatable("commands.kiwi.configure.failed")); return 0; } - Minecraft.getInstance().tell(() -> { + Minecraft.getInstance().schedule(() -> { Minecraft.getInstance().setScreen(screen); }); return 1; diff --git a/src/main/java/snownee/kiwi/command/KiwiCommand.java b/src/main/java/snownee/kiwi/command/KiwiCommand.java index 7f41d60d..9e6af346 100644 --- a/src/main/java/snownee/kiwi/command/KiwiCommand.java +++ b/src/main/java/snownee/kiwi/command/KiwiCommand.java @@ -1,7 +1,10 @@ package snownee.kiwi.command; +import java.net.URI; +import java.text.DecimalFormat; import java.util.List; import java.util.Objects; +import java.util.function.BiConsumer; import com.ezylang.evalex.Expression; import com.ezylang.evalex.data.EvaluationValue; @@ -9,21 +12,21 @@ import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import net.minecraft.commands.CommandBuildContext; +import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; +import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Component; import snownee.kiwi.Kiwi; +import snownee.kiwi.KiwiCommonConfig; import snownee.kiwi.config.KiwiConfigManager; import snownee.kiwi.loader.Platform; import snownee.kiwi.util.KEval; +import snownee.kiwi.util.KUtil; public class KiwiCommand { - public static void register( - CommandDispatcher dispatcher, - CommandBuildContext registryAccess, - Commands.CommandSelection environment) { + public static void register(CommandDispatcher dispatcher) { LiteralArgumentBuilder builder = Commands.literal(Kiwi.ID); /* off */ builder.then(Commands @@ -35,9 +38,9 @@ public static void register( builder.then(Commands .literal("reload") .requires(ctx -> ctx.hasPermission(2)) - .then(Commands.argument("configFile", StringArgumentType.greedyString()) + .then(Commands.argument("fileName", StringArgumentType.greedyString()) .executes(ctx -> { - String fileName = StringArgumentType.getString(ctx, "configFile"); + String fileName = StringArgumentType.getString(ctx, "fileName"); if (KiwiConfigManager.refresh(fileName)) { ctx.getSource().sendSuccess(() -> Component.translatable("commands.kiwi.reload.success", fileName), true); return 1; @@ -52,8 +55,15 @@ public static void register( builder.then(Commands .literal("eval") .requires(ctx -> ctx.hasPermission(2)) + .executes(ctx -> evalHelp(ctx.getSource(), CommandSourceStack::sendFailure)) .then(Commands.argument("expression", StringArgumentType.greedyString()) - .executes(ctx -> eval(ctx.getSource(), StringArgumentType.getString(ctx, "expression"))) + .executes(ctx -> eval( + StringArgumentType.getString(ctx, "expression"), + KiwiCommonConfig.evalPrintExpression, + ctx.getSource(), + (source, msg) -> source.sendSuccess(() -> msg, false), + CommandSourceStack::sendFailure) + ) ) ); /* on */ @@ -82,22 +92,41 @@ private static int debugRules(CommandSourceStack commandSourceStack) { return 1; } - private static int eval(CommandSourceStack source, String expString) { + public static int evalHelp(T ctx, BiConsumer send) { + String url = "https://github.com/Snownee/Kiwi/wiki/Eval-Guide"; + send.accept( + ctx, + Component.literal(url) + .withStyle(s -> s.withUnderlined(true).withClickEvent(new ClickEvent.OpenUrl(URI.create(url))))); + return 0; + } + + public static int eval( + String expString, + boolean print, + T source, + BiConsumer sendSuccess, + BiConsumer sendFailure) { try { + if (print) { + sendSuccess.accept(source, Component.literal(">>> " + expString).withStyle(ChatFormatting.GREEN)); + } EvaluationValue value = new Expression(expString, KEval.config()).evaluate(); String s; if (value.isNumberValue()) { - s = value.getNumberValue().toPlainString(); + s = new DecimalFormat("###,###.#####").format(value.getNumberValue()); + } else if (value.isExpressionNode() || value.isBinaryValue()) { + s = "[%s]".formatted(value.getDataType()); } else { s = Objects.toString(value.getValue()); } - source.sendSuccess(() -> Component.literal(s), false); + sendSuccess.accept(source, KUtil.clickToCopy(Component.literal(s))); return value.isNullValue() ? 0 : value.getNumberValue().intValue(); } catch (Throwable e) { if (!Platform.isProduction()) { Kiwi.LOGGER.error(expString, e); } - source.sendFailure(Component.literal(e.getLocalizedMessage())); + sendFailure.accept(source, Component.literal("%s - %s".formatted(e, e.getLocalizedMessage()))); return 0; } } diff --git a/src/main/java/snownee/kiwi/contributor/Contributors.java b/src/main/java/snownee/kiwi/contributor/Contributors.java index 6e083df5..4f1fb97d 100644 --- a/src/main/java/snownee/kiwi/contributor/Contributors.java +++ b/src/main/java/snownee/kiwi/contributor/Contributors.java @@ -2,14 +2,17 @@ import java.util.Calendar; import java.util.Collections; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; -import com.google.common.collect.ImmutableMap; +import org.jetbrains.annotations.Nullable; + import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -30,15 +33,17 @@ public class Contributors extends AbstractModule { public static final Map REWARD_PROVIDERS = Maps.newConcurrentMap(); - public static final Map PLAYER_COSMETICS = Maps.newConcurrentMap(); - private static final Set RENDERABLES = Sets.newLinkedHashSet(); + public static final Map PLAYER_COSMETICS = Maps.newConcurrentMap(); + private static final Set COSMETIC_IDS = Sets.newLinkedHashSet(); private static int DAY = Calendar.getInstance().get(Calendar.DAY_OF_MONTH); public static boolean isContributor(String author, String playerName) { + if (!Platform.isProduction()) return true; return REWARD_PROVIDERS.getOrDefault(author.toLowerCase(Locale.ENGLISH), ITierProvider.Empty.INSTANCE).isContributor(playerName); } public static boolean isContributor(String author, String playerName, String tier) { + if (!Platform.isProduction()) return true; return REWARD_PROVIDERS.getOrDefault(author.toLowerCase(Locale.ENGLISH), ITierProvider.Empty.INSTANCE).isContributor( playerName, tier); @@ -74,49 +79,52 @@ public static void registerTierProvider(ITierProvider rewardProvider) { String namespace = rewardProvider.getAuthor().toLowerCase(Locale.ENGLISH); REWARD_PROVIDERS.put(namespace, rewardProvider); for (String tier : rewardProvider.getRenderableTiers()) { - RENDERABLES.add(ResourceLocation.fromNamespaceAndPath(namespace, tier)); + COSMETIC_IDS.add(ResourceLocation.fromNamespaceAndPath(namespace, tier)); } } - public static void changeCosmetic(ServerPlayer player, ResourceLocation cosmetic) { - String playerName = player.getGameProfile().getName(); - canPlayerUseCosmetic(playerName, cosmetic).thenAccept(bl -> { + public static void changeCosmetic(ServerPlayer player, @Nullable ResourceLocation cosmetic) { + canPlayerUseCosmetic(player.getGameProfile().getName(), cosmetic).thenAccept(bl -> { if (bl) { + UUID uuid = player.getUUID(); + SSyncCosmeticPacket packet; if (cosmetic == null) { - PLAYER_COSMETICS.remove(playerName); + PLAYER_COSMETICS.remove(uuid); + packet = new SSyncCosmeticPacket(Map.of(), List.of(uuid)); } else { - PLAYER_COSMETICS.put(playerName, cosmetic); + PLAYER_COSMETICS.put(uuid, cosmetic); + packet = new SSyncCosmeticPacket(Map.of(uuid, cosmetic), List.of()); } - KPacketSender.sendToAll(new SSyncCosmeticPacket(ImmutableMap.of(playerName, cosmetic)), player.server); + KPacketSender.sendToAll(packet, player.level().getServer()); } }); } public static boolean isRenderable(ResourceLocation id) { refreshRenderables(); - return RENDERABLES.contains(id); + return COSMETIC_IDS.contains(id); } public static Set getRenderableTiers() { refreshRenderables(); - return Collections.unmodifiableSet(RENDERABLES); + return Collections.unmodifiableSet(COSMETIC_IDS); } private static void refreshRenderables() { int current = Calendar.getInstance().get(Calendar.DAY_OF_MONTH); if (current != DAY) { DAY = current; - RENDERABLES.clear(); + COSMETIC_IDS.clear(); for (Entry entry : REWARD_PROVIDERS.entrySet()) { String namespace = entry.getKey(); for (String tier : entry.getValue().getRenderableTiers()) { - RENDERABLES.add(ResourceLocation.fromNamespaceAndPath(namespace, tier)); + COSMETIC_IDS.add(ResourceLocation.fromNamespaceAndPath(namespace, tier)); } } } } - public static CompletableFuture canPlayerUseCosmetic(String playerName, ResourceLocation cosmetic) { + public static CompletableFuture canPlayerUseCosmetic(String playerName, @Nullable ResourceLocation cosmetic) { if (cosmetic == null || cosmetic.getPath().isEmpty()) { // Set to empty return CompletableFuture.completedFuture(Boolean.TRUE); } @@ -141,14 +149,13 @@ protected void init(InitEvent event) { registerTierProvider(new KiwiTierProvider()); ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { if (!(server.isSingleplayerOwner(handler.player.getGameProfile()))) { - KPacketSender.send(new SSyncCosmeticPacket(ImmutableMap.copyOf(PLAYER_COSMETICS)), handler.player); + KPacketSender.send(new SSyncCosmeticPacket(Map.copyOf(PLAYER_COSMETICS), List.of()), handler.player); } }); if (!Platform.isPhysicalClient()) { ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> { - PLAYER_COSMETICS.remove(handler.player.getGameProfile().getName()); + PLAYER_COSMETICS.remove(handler.player.getUUID()); }); } } - -} +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/contributor/ContributorsClient.java b/src/main/java/snownee/kiwi/contributor/ContributorsClient.java index a2835f1b..7a1b2b57 100644 --- a/src/main/java/snownee/kiwi/contributor/ContributorsClient.java +++ b/src/main/java/snownee/kiwi/contributor/ContributorsClient.java @@ -1,15 +1,15 @@ package snownee.kiwi.contributor; -import java.util.Map; +import java.util.UUID; +import java.util.function.Function; import com.mojang.blaze3d.platform.InputConstants; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; -import net.fabricmc.fabric.api.client.rendering.v1.LivingEntityFeatureRendererRegistrationCallback; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.renderer.entity.player.PlayerRenderer; +import net.minecraft.client.model.PlayerModel; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.state.PlayerRenderState; import net.minecraft.resources.ResourceLocation; import snownee.kiwi.AbstractModule; import snownee.kiwi.Kiwi; @@ -18,7 +18,12 @@ import snownee.kiwi.config.KiwiConfigManager; import snownee.kiwi.contributor.client.CosmeticLayer; import snownee.kiwi.contributor.client.gui.CosmeticScreen; +import snownee.kiwi.contributor.impl.client.layer.FoxTailLayer; +import snownee.kiwi.contributor.impl.client.layer.PlanetLayer; +import snownee.kiwi.contributor.impl.client.layer.SantaHatLayer; +import snownee.kiwi.contributor.impl.client.layer.SunnyMilkLayer; import snownee.kiwi.contributor.network.CSetCosmeticPacket; +import snownee.kiwi.contributor.network.SSyncCosmeticPacket; import snownee.kiwi.loader.event.InitEvent; import snownee.kiwi.network.KPacketSender; import snownee.kiwi.util.KUtil; @@ -27,23 +32,14 @@ public class ContributorsClient extends AbstractModule { @Override protected void init(InitEvent event) { - event.enqueueWork(() -> { - LivingEntityFeatureRendererRegistrationCallback.EVENT.register((entityType, entityRenderer, registrationHelper, context) -> { - if (entityRenderer instanceof PlayerRenderer) { - CosmeticLayer layer = new CosmeticLayer((PlayerRenderer) entityRenderer); - CosmeticLayer.ALL_LAYERS.add(layer); - registrationHelper.register(layer); - } - }); - ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> { - ContributorsClient.changeCosmetic(); - }); - ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> { - Contributors.PLAYER_COSMETICS.clear(); - CosmeticLayer.ALL_LAYERS.forEach(l -> l.getCache().invalidateAll()); - }); - ClientTickEvents.END_CLIENT_TICK.register(ContributorsClient::onKeyInput); - }); + registerRenderer("2020q3", PlanetLayer::new); + registerRenderer("2020q4", FoxTailLayer::new); + registerRenderer("xmas", SantaHatLayer::new); + registerRenderer("sunny_milk", SunnyMilkLayer::new); + } + + private static void registerRenderer(String id, Function, CosmeticLayer> creator) { + CosmeticLayer.registerRenderer(ResourceLocation.fromNamespaceAndPath("snownee", id), creator); } private static int hold; @@ -69,7 +65,7 @@ public static void changeCosmetic() { id = null; } ResourceLocation cosmetic = id; - Contributors.canPlayerUseCosmetic(getPlayerName(), cosmetic).thenAccept(bl -> { + Contributors.canPlayerUseCosmetic(getSelfName(), cosmetic).thenAccept(bl -> { if (!bl) { ConfigHandler cfg = KiwiConfigManager.getHandler(KiwiClientConfig.class); KiwiClientConfig.contributorCosmetic = ""; @@ -78,27 +74,38 @@ public static void changeCosmetic() { } KPacketSender.sendToServer(new CSetCosmeticPacket(cosmetic)); if (cosmetic == null) { - Contributors.PLAYER_COSMETICS.remove(getPlayerName()); + Contributors.PLAYER_COSMETICS.remove(getSelfUUID()); } else { - Contributors.PLAYER_COSMETICS.put(getPlayerName(), cosmetic); + Contributors.PLAYER_COSMETICS.put(getSelfUUID(), cosmetic); Kiwi.LOGGER.info("Enabled contributor effect: {}", cosmetic); } - CosmeticLayer.ALL_LAYERS.forEach(l -> l.getCache().invalidate(getPlayerName())); + CosmeticLayer.getCache().remove(getSelfUUID()); }); } - public static void changeCosmetic(Map changes) { - changes.forEach((k, v) -> { - if (v == null) { - Contributors.PLAYER_COSMETICS.remove(k); - } else { - Contributors.PLAYER_COSMETICS.put(k, v); - } - }); - CosmeticLayer.ALL_LAYERS.forEach(l -> l.getCache().invalidateAll(changes.keySet())); + public static void changeCosmetic(SSyncCosmeticPacket changes) { + if (changes.add().isEmpty() && changes.remove().isEmpty()) { + clear(); + return; + } + Contributors.PLAYER_COSMETICS.putAll(changes.add()); + for (UUID s : changes.remove()) { + Contributors.PLAYER_COSMETICS.remove(s); + } + changes.add().keySet().forEach(CosmeticLayer.getCache()::remove); + changes.remove().forEach(CosmeticLayer.getCache()::remove); + } + + public static void clear() { + Contributors.PLAYER_COSMETICS.clear(); + CosmeticLayer.getCache().clear(); + } + + public static UUID getSelfUUID() { + return Minecraft.getInstance().getUser().getProfileId(); } - private static String getPlayerName() { + public static String getSelfName() { return Minecraft.getInstance().getUser().getName(); } diff --git a/src/main/java/snownee/kiwi/contributor/CosmeticRenderState.java b/src/main/java/snownee/kiwi/contributor/CosmeticRenderState.java new file mode 100644 index 00000000..7f438365 --- /dev/null +++ b/src/main/java/snownee/kiwi/contributor/CosmeticRenderState.java @@ -0,0 +1,8 @@ +package snownee.kiwi.contributor; + +import snownee.kiwi.contributor.client.CosmeticLayer; + +public interface CosmeticRenderState { + CosmeticLayer kiwi$getCosmeticLayer(); + void kiwi$setCosmeticLayer(CosmeticLayer layer); +} diff --git a/src/main/java/snownee/kiwi/contributor/ITierProvider.java b/src/main/java/snownee/kiwi/contributor/ITierProvider.java index 5d21fa3b..92fbd171 100644 --- a/src/main/java/snownee/kiwi/contributor/ITierProvider.java +++ b/src/main/java/snownee/kiwi/contributor/ITierProvider.java @@ -4,13 +4,6 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.model.PlayerModel; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.renderer.entity.RenderLayerParent; -import snownee.kiwi.contributor.client.CosmeticLayer; - public interface ITierProvider { String getAuthor(); @@ -24,9 +17,6 @@ default CompletableFuture refresh() { return CompletableFuture.completedFuture(null); } - @Environment(EnvType.CLIENT) - CosmeticLayer createRenderer(RenderLayerParent> entityRenderer, String tier); - default boolean isContributor(String playerName) { return !getPlayerTiers(playerName).isEmpty(); } @@ -35,7 +25,7 @@ default boolean isContributor(String playerName, String tier) { return getPlayerTiers(playerName).contains(tier); } - public enum Empty implements ITierProvider { + enum Empty implements ITierProvider { INSTANCE; @Override @@ -57,14 +47,5 @@ public Set getPlayerTiers(String playerName) { public List getRenderableTiers() { return List.of(); } - - @Environment(EnvType.CLIENT) - @Override - public CosmeticLayer createRenderer( - RenderLayerParent> entityRenderer, - String tier) { - return null; - } - } } diff --git a/src/main/java/snownee/kiwi/contributor/client/CosmeticLayer.java b/src/main/java/snownee/kiwi/contributor/client/CosmeticLayer.java index 9f592d31..e6acb1e1 100644 --- a/src/main/java/snownee/kiwi/contributor/client/CosmeticLayer.java +++ b/src/main/java/snownee/kiwi/contributor/client/CosmeticLayer.java @@ -1,11 +1,12 @@ package snownee.kiwi.contributor.client; -import java.util.Collection; -import java.util.Locale; +import java.util.Map; +import java.util.UUID; +import java.util.function.Function; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.collect.Lists; +import org.jetbrains.annotations.Nullable; + +import com.google.common.collect.Maps; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.model.PlayerModel; @@ -13,24 +14,55 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.RenderLayerParent; import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.client.renderer.entity.state.PlayerRenderState; +import net.minecraft.client.resources.PlayerSkin; import net.minecraft.resources.ResourceLocation; import snownee.kiwi.contributor.Contributors; -import snownee.kiwi.contributor.ITierProvider; +import snownee.kiwi.contributor.CosmeticRenderState; +import snownee.kiwi.mixin.client.RenderLayerAccess; -public class CosmeticLayer extends RenderLayer> { +public class CosmeticLayer extends RenderLayer { - public static final Collection ALL_LAYERS = Lists.newLinkedList(); - private final Cache>> player2renderer; - public final RenderLayerParent> renderer; + public static Map ALL_LAYERS = Maps.newHashMap(); + private static final Map PLAYER_CACHE = Maps.newHashMap(); + private static final Map, CosmeticLayer>> LAYER_CREATORS = Maps.newHashMap(); + private final Map renderers = Maps.newHashMap(); - public CosmeticLayer(RenderLayerParent> entityRendererIn) { + public CosmeticLayer(RenderLayerParent entityRendererIn) { super(entityRendererIn); - this.renderer = entityRendererIn; - if (getClass() == CosmeticLayer.class) { - player2renderer = CacheBuilder.newBuilder().build(); - } else { - player2renderer = null; - } + } + + @Nullable + public static CosmeticLayer getRendererOf(AbstractClientPlayer player) { + return PLAYER_CACHE.computeIfAbsent( + player.getUUID(), uuid -> { + CosmeticLayer parent = ALL_LAYERS.get(player.getSkin().model()); + ResourceLocation id = Contributors.PLAYER_COSMETICS.get(uuid); + if (parent == null || id == null) { + return null; + } + return createRenderer(id, parent); + }); + } + + @Nullable + public static CosmeticLayer createRenderer(ResourceLocation id, CosmeticLayer parent) { + return parent.renderers.computeIfAbsent( + id, key -> { + Function, CosmeticLayer> creator = LAYER_CREATORS.get(key); + if (creator != null) { + //noinspection unchecked,rawtypes + RenderLayerParent layerParent = ((RenderLayerAccess) parent).getRenderer(); + return creator.apply(layerParent); + } + return null; + }); + } + + public synchronized static void registerRenderer( + ResourceLocation id, + Function, CosmeticLayer> creator) { + LAYER_CREATORS.put(id, creator); } @Override @@ -38,50 +70,19 @@ public void render( PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, - AbstractClientPlayer entitylivingbaseIn, - float limbSwing, - float limbSwingAmount, - float partialTicks, - float ageInTicks, - float netHeadYaw, - float headPitch) { - if (player2renderer == null) { + PlayerRenderState renderState, + float yRot, + float xRot) { + if (renderState.isInvisible) { return; } - RenderLayer> renderer = player2renderer.getIfPresent(entitylivingbaseIn.getGameProfile() - .getName()); - if (renderer == null) { - String name = entitylivingbaseIn.getGameProfile().getName(); - ResourceLocation id = Contributors.PLAYER_COSMETICS.get(name); - if (id != null) { - ITierProvider provider = Contributors.REWARD_PROVIDERS.get(id.getNamespace().toLowerCase(Locale.ENGLISH)); - if (provider == null) { - Contributors.PLAYER_COSMETICS.remove(name); - } else { - renderer = provider.createRenderer(this.renderer, id.getPath()); - if (renderer != null) { - player2renderer.put(name, renderer); - } - } - } - } + CosmeticLayer renderer = ((CosmeticRenderState) renderState).kiwi$getCosmeticLayer(); if (renderer != null) { - renderer.render( - matrixStackIn, - bufferIn, - packedLightIn, - entitylivingbaseIn, - limbSwing, - limbSwingAmount, - partialTicks, - ageInTicks, - netHeadYaw, - headPitch); + renderer.render(matrixStackIn, bufferIn, packedLightIn, renderState, yRot, xRot); } } - public Cache>> getCache() { - return player2renderer; + public static Map getCache() { + return PLAYER_CACHE; } - -} +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/contributor/client/gui/CosmeticScreen.java b/src/main/java/snownee/kiwi/contributor/client/gui/CosmeticScreen.java index 964d9020..9367d95c 100644 --- a/src/main/java/snownee/kiwi/contributor/client/gui/CosmeticScreen.java +++ b/src/main/java/snownee/kiwi/contributor/client/gui/CosmeticScreen.java @@ -9,6 +9,7 @@ import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.ObjectSelectionList; +import net.minecraft.client.gui.components.StringWidget; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; @@ -30,17 +31,13 @@ public CosmeticScreen() { super(Component.translatable("gui.kiwi.cosmetic")); } - private static String getPlayerName() { - return Minecraft.getInstance().getUser().getName(); - } - @Override protected void init() { - currentCosmetic = Contributors.PLAYER_COSMETICS.get(getPlayerName()); + currentCosmetic = Contributors.PLAYER_COSMETICS.get(ContributorsClient.getSelfUUID()); list = new List(minecraft, 150, height, 0, 20); list.setX(20); list.addEntry(selectedEntry = new Entry(this, null)); - String playerName = getPlayerName(); + String playerName = ContributorsClient.getSelfName(); boolean added = false; for (ResourceLocation tier : Contributors.getRenderableTiers()) { if (Contributors.isContributor(tier.getNamespace(), playerName, tier.getPath())) { @@ -55,6 +52,10 @@ protected void init() { if (!added) { minecraft.setScreen(null); } + StringWidget stringWidget = new StringWidget(title, minecraft.font); + stringWidget.setPosition(180, 10); + addRenderableWidget(stringWidget); + addRenderableWidget(list); addRenderableWidget(Button.builder( Component.translatable(KiwiClientConfig.cosmeticScreenKeybind ? "gui.kiwi.cosmetic.enabled" : "gui.kiwi.cosmetic.disabled"), b -> { @@ -66,14 +67,6 @@ protected void init() { }).pos(180, 30).build()); } - @Override - public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float pTicks) { - renderBackground(guiGraphics, mouseX, mouseY, pTicks); - super.render(guiGraphics, mouseX, mouseY, pTicks); - list.render(guiGraphics, mouseX, mouseY, pTicks); - guiGraphics.drawString(minecraft.font, title, 180, 10, 0xFFFFFF); - } - @Override public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) { list.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_); @@ -132,7 +125,7 @@ public List(Minecraft mcIn, int widthIn, int heightIn, int topIn, int slotHeight } @Override - public int addEntry(snownee.kiwi.contributor.client.gui.CosmeticScreen.Entry p_93487_) { + public int addEntry(CosmeticScreen.Entry p_93487_) { return super.addEntry(p_93487_); } @@ -145,7 +138,7 @@ private static class Entry extends ObjectSelectionList.Entry { private final ResourceLocation id; private final String name; - public Entry(CosmeticScreen parent, ResourceLocation id) { + public Entry(CosmeticScreen parent, @Nullable ResourceLocation id) { this.parent = parent; this.id = id; name = id == null ? "-" : I18n.get(Util.makeDescriptionId("cosmetic", id)); @@ -163,9 +156,9 @@ public void render( int mouseY, boolean hover, float partialTicks) { - int color = hover ? 0xFFFFAA : 0xFFFFFF; + int color = hover ? 0xFFFFFFAA : 0xFFFFFFFF; if (this == parent.selectedEntry) { - color = 0xFFFF77; + color = 0xFFFFFF77; } guiGraphics.drawString(parent.font, name, left + 43, top + 2, color); } diff --git a/src/main/java/snownee/kiwi/contributor/impl/JsonTierProvider.java b/src/main/java/snownee/kiwi/contributor/impl/JsonTierProvider.java index 419873a5..4b0f6352 100644 --- a/src/main/java/snownee/kiwi/contributor/impl/JsonTierProvider.java +++ b/src/main/java/snownee/kiwi/contributor/impl/JsonTierProvider.java @@ -14,20 +14,15 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; +import com.google.gson.Strictness; import com.mojang.serialization.Codec; import com.mojang.serialization.JsonOps; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.model.PlayerModel; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.renderer.entity.RenderLayerParent; import snownee.kiwi.Kiwi; import snownee.kiwi.contributor.ITierProvider; -import snownee.kiwi.contributor.client.CosmeticLayer; public class JsonTierProvider implements ITierProvider { - public static final Gson GSON = new GsonBuilder().setLenient().create(); + public static final Gson GSON = new GsonBuilder().setStrictness(Strictness.LENIENT).create(); public static final Codec>> CODEC = Codec.unboundedMap(Codec.STRING, Codec.STRING.listOf()); private final String author; @@ -44,7 +39,7 @@ public JsonTierProvider(String author, Supplier> urlProvider) { public boolean load(String url) { try (InputStreamReader reader = new InputStreamReader(URI.create(url).toURL().openStream())) { JsonElement json = GSON.fromJson(reader, JsonElement.class); - Map> map = CODEC.parse(JsonOps.INSTANCE, json).getOrThrow(); + Map> map = CODEC.parse(JsonOps.INSTANCE, json).result().orElseThrow(); ImmutableSet.Builder superusers = ImmutableSet.builder(); if (map.containsKey("*")) { superusers.addAll(map.get("*")); @@ -102,13 +97,4 @@ public Set getTiers() { public List getRenderableTiers() { return List.of(); } - - @Environment(EnvType.CLIENT) - @Override - public CosmeticLayer createRenderer( - RenderLayerParent> entityRenderer, - String tier) { - return null; - } - } diff --git a/src/main/java/snownee/kiwi/contributor/impl/KiwiTierProvider.java b/src/main/java/snownee/kiwi/contributor/impl/KiwiTierProvider.java index dc747e52..8cef4d09 100644 --- a/src/main/java/snownee/kiwi/contributor/impl/KiwiTierProvider.java +++ b/src/main/java/snownee/kiwi/contributor/impl/KiwiTierProvider.java @@ -6,17 +6,6 @@ import com.google.common.collect.Sets; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.model.PlayerModel; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.renderer.entity.RenderLayerParent; -import snownee.kiwi.contributor.client.CosmeticLayer; -import snownee.kiwi.contributor.impl.client.layer.FoxTailLayer; -import snownee.kiwi.contributor.impl.client.layer.PlanetLayer; -import snownee.kiwi.contributor.impl.client.layer.SantaHatLayer; -import snownee.kiwi.contributor.impl.client.layer.SunnyMilkLayer; - public class KiwiTierProvider extends JsonTierProvider { private final List renderableTiers = List.of("2020q3", "2020q4"/*, "2021q1"*/, "sunny_milk", "xmas"); @@ -55,19 +44,4 @@ public List getRenderableTiers() { return renderableTiers; } - @Override - @Environment(EnvType.CLIENT) - public CosmeticLayer createRenderer( - RenderLayerParent> entityRenderer, - String tier) { - return switch (tier) { - case "2020q3" -> new PlanetLayer(entityRenderer); - case "2020q4" -> new FoxTailLayer(entityRenderer); - // case "2021q1" -> new ElectronicatLayer(entityRenderer); - case "xmas" -> new SantaHatLayer(entityRenderer); - case "sunny_milk" -> new SunnyMilkLayer(entityRenderer); - default -> null; - }; - } - } diff --git a/src/main/java/snownee/kiwi/contributor/impl/client/layer/FoxTailLayer.java b/src/main/java/snownee/kiwi/contributor/impl/client/layer/FoxTailLayer.java index c1a6d075..0be044f9 100644 --- a/src/main/java/snownee/kiwi/contributor/impl/client/layer/FoxTailLayer.java +++ b/src/main/java/snownee/kiwi/contributor/impl/client/layer/FoxTailLayer.java @@ -9,16 +9,14 @@ import net.minecraft.client.model.PlayerModel; import net.minecraft.client.model.geom.builders.LayerDefinition; -import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.state.PlayerRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.ElytraItem; -import net.minecraft.world.item.ItemStack; import snownee.kiwi.contributor.client.CosmeticLayer; import snownee.kiwi.contributor.impl.client.model.FoxTailModel; @@ -26,11 +24,11 @@ public class FoxTailLayer extends CosmeticLayer { private static final ResourceLocation FOX = ResourceLocation.withDefaultNamespace("textures/entity/fox/fox.png"); private static final ResourceLocation SNOW_FOX = ResourceLocation.withDefaultNamespace("textures/entity/fox/snow_fox.png"); private static final Supplier definition = Suppliers.memoize(FoxTailModel::create); - private final FoxTailModel modelFoxTail; + private final FoxTailModel modelFoxTail; - public FoxTailLayer(RenderLayerParent> entityRendererIn) { + public FoxTailLayer(RenderLayerParent entityRendererIn) { super(entityRendererIn); - modelFoxTail = new FoxTailModel<>(entityRendererIn.getModel(), definition.get()); + modelFoxTail = new FoxTailModel<>(entityRendererIn.getModel(), definition.get().bakeRoot()); } @Override @@ -38,27 +36,18 @@ public void render( PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, - AbstractClientPlayer entitylivingbaseIn, - float limbSwing, - float limbSwingAmount, - float partialTicks, - float ageInTicks, - float netHeadYaw, - float headPitch) { - if (entitylivingbaseIn.isInvisible() || entitylivingbaseIn.isSleeping()) { + PlayerRenderState renderState, + float yRot, + float xRot) { + if (renderState.showCape && renderState.chestEquipment.get(DataComponents.GLIDER) != null) { return; } - ItemStack itemstack = entitylivingbaseIn.getItemBySlot(EquipmentSlot.CHEST); - if (itemstack.getItem() instanceof ElytraItem) { - return; - } - String name = entitylivingbaseIn.getName().getString().toLowerCase(Locale.ENGLISH); + String name = renderState.name.toLowerCase(Locale.ENGLISH); ResourceLocation texture = name.contains("snow") || name.contains("xue") || name.contains("yuki") ? SNOW_FOX : FOX; matrixStackIn.pushPose(); - modelFoxTail.young = entitylivingbaseIn.isBaby(); - modelFoxTail.setupAnim(entitylivingbaseIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); - VertexConsumer ivertexbuilder = ItemRenderer.getFoilBuffer(bufferIn, RenderType.entitySolid(texture), false, false); - modelFoxTail.renderToBuffer(matrixStackIn, ivertexbuilder, packedLightIn, OverlayTexture.NO_OVERLAY); + modelFoxTail.setupAnim(renderState); + VertexConsumer vertexConsumer = ItemRenderer.getFoilBuffer(bufferIn, RenderType.entitySolid(texture), false, false); + modelFoxTail.renderToBuffer(matrixStackIn, vertexConsumer, packedLightIn, OverlayTexture.NO_OVERLAY); matrixStackIn.popPose(); } diff --git a/src/main/java/snownee/kiwi/contributor/impl/client/layer/PlanetLayer.java b/src/main/java/snownee/kiwi/contributor/impl/client/layer/PlanetLayer.java index c149a69f..9f664091 100644 --- a/src/main/java/snownee/kiwi/contributor/impl/client/layer/PlanetLayer.java +++ b/src/main/java/snownee/kiwi/contributor/impl/client/layer/PlanetLayer.java @@ -6,30 +6,27 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Axis; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.minecraft.client.model.PlayerModel; import net.minecraft.client.model.geom.builders.LayerDefinition; -import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.state.PlayerRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.resources.ResourceLocation; import snownee.kiwi.Kiwi; import snownee.kiwi.contributor.client.CosmeticLayer; import snownee.kiwi.contributor.impl.client.model.PlanetModel; -@Environment(EnvType.CLIENT) public class PlanetLayer extends CosmeticLayer { private static final ResourceLocation TEXTURE = Kiwi.id("textures/reward/planet.png"); private static final Supplier definition = Suppliers.memoize(PlanetModel::create); - private final PlanetModel modelPlanet; + private final PlanetModel modelPlanet; - public PlanetLayer(RenderLayerParent> entityRendererIn) { + public PlanetLayer(RenderLayerParent entityRendererIn) { super(entityRendererIn); - modelPlanet = new PlanetModel<>(definition.get()); + modelPlanet = new PlanetModel<>(definition.get().bakeRoot()); } @Override @@ -37,21 +34,14 @@ public void render( PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, - AbstractClientPlayer entitylivingbaseIn, - float limbSwing, - float limbSwingAmount, - float partialTicks, - float ageInTicks, - float netHeadYaw, - float headPitch) { - if (entitylivingbaseIn.isInvisible()) { - return; - } + PlayerRenderState renderState, + float yRot, + float xRot) { matrixStackIn.pushPose(); - matrixStackIn.translate(0, -0.6, 0); - matrixStackIn.mulPose(Axis.YP.rotationDegrees(-ageInTicks)); - matrixStackIn.scale(1.2f, 1.2f, 1.2f); - modelPlanet.setupAnim(entitylivingbaseIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); + matrixStackIn.mulPose(Axis.YP.rotationDegrees(-renderState.ageInTicks)); + float scale = 0.7f; + matrixStackIn.scale(scale, scale, scale); + modelPlanet.setupAnim(renderState); VertexConsumer ivertexbuilder = ItemRenderer.getFoilBuffer(bufferIn, RenderType.entityTranslucent(TEXTURE), false, false); modelPlanet.renderToBuffer(matrixStackIn, ivertexbuilder, packedLightIn, OverlayTexture.NO_OVERLAY); matrixStackIn.popPose(); diff --git a/src/main/java/snownee/kiwi/contributor/impl/client/layer/SantaHatLayer.java b/src/main/java/snownee/kiwi/contributor/impl/client/layer/SantaHatLayer.java index e63c3075..7b3acb19 100644 --- a/src/main/java/snownee/kiwi/contributor/impl/client/layer/SantaHatLayer.java +++ b/src/main/java/snownee/kiwi/contributor/impl/client/layer/SantaHatLayer.java @@ -7,15 +7,13 @@ import net.minecraft.client.model.PlayerModel; import net.minecraft.client.model.geom.builders.LayerDefinition; -import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.state.PlayerRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.ItemStack; import snownee.kiwi.Kiwi; import snownee.kiwi.contributor.client.CosmeticLayer; import snownee.kiwi.contributor.impl.client.model.SantaHatModel; @@ -23,11 +21,11 @@ public class SantaHatLayer extends CosmeticLayer { private static final ResourceLocation TEXTURE = Kiwi.id("textures/reward/santa.png"); private static final Supplier definition = Suppliers.memoize(SantaHatModel::create); - private final SantaHatModel modelSantaHat; + private final SantaHatModel modelSantaHat; - public SantaHatLayer(RenderLayerParent> entityRendererIn) { + public SantaHatLayer(RenderLayerParent entityRendererIn) { super(entityRendererIn); - modelSantaHat = new SantaHatModel<>(entityRendererIn.getModel(), definition.get()); + modelSantaHat = new SantaHatModel<>(entityRendererIn.getModel(), definition.get().bakeRoot()); } @Override @@ -35,23 +33,14 @@ public void render( PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, - AbstractClientPlayer entitylivingbaseIn, - float limbSwing, - float limbSwingAmount, - float partialTicks, - float ageInTicks, - float netHeadYaw, - float headPitch) { - if (entitylivingbaseIn.isInvisible()) { - return; - } - ItemStack itemstack = entitylivingbaseIn.getItemBySlot(EquipmentSlot.HEAD); - if (!itemstack.isEmpty()) { + PlayerRenderState renderState, + float yRot, + float xRot) { + if (!renderState.headEquipment.isEmpty()) { return; } matrixStackIn.pushPose(); - modelSantaHat.young = entitylivingbaseIn.isBaby(); - modelSantaHat.setupAnim(entitylivingbaseIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); + modelSantaHat.setupAnim(renderState); VertexConsumer ivertexbuilder = ItemRenderer.getFoilBuffer(bufferIn, RenderType.entitySolid(TEXTURE), false, false); modelSantaHat.renderToBuffer(matrixStackIn, ivertexbuilder, packedLightIn, OverlayTexture.NO_OVERLAY); matrixStackIn.popPose(); diff --git a/src/main/java/snownee/kiwi/contributor/impl/client/layer/SunnyMilkLayer.java b/src/main/java/snownee/kiwi/contributor/impl/client/layer/SunnyMilkLayer.java index e14a97ed..0fa217f1 100644 --- a/src/main/java/snownee/kiwi/contributor/impl/client/layer/SunnyMilkLayer.java +++ b/src/main/java/snownee/kiwi/contributor/impl/client/layer/SunnyMilkLayer.java @@ -7,16 +7,15 @@ import net.minecraft.client.model.PlayerModel; import net.minecraft.client.model.geom.builders.LayerDefinition; -import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.state.PlayerRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.item.ElytraItem; -import net.minecraft.world.item.ItemStack; +import net.minecraft.world.entity.Pose; import snownee.kiwi.Kiwi; import snownee.kiwi.contributor.client.CosmeticLayer; import snownee.kiwi.contributor.impl.client.model.SunnyMilkModel; @@ -24,11 +23,11 @@ public class SunnyMilkLayer extends CosmeticLayer { private static final ResourceLocation TEXTURE = Kiwi.id("textures/reward/sunny_milk.png"); private static final Supplier definition = Suppliers.memoize(SunnyMilkModel::create); - private final SunnyMilkModel model; + private final SunnyMilkModel model; - public SunnyMilkLayer(RenderLayerParent> entityRendererIn) { + public SunnyMilkLayer(RenderLayerParent entityRendererIn) { super(entityRendererIn); - model = new SunnyMilkModel<>(definition.get()); + model = new SunnyMilkModel<>(definition.get().bakeRoot()); } @Override @@ -36,25 +35,20 @@ public void render( PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, - AbstractClientPlayer entitylivingbaseIn, - float limbSwing, - float limbSwingAmount, - float partialTicks, - float ageInTicks, - float netHeadYaw, - float headPitch) { - if (entitylivingbaseIn.isInvisible() || entitylivingbaseIn.isSleeping()) { + PlayerRenderState renderState, + float yRot, + float xRot) { + if (renderState.pose == Pose.SLEEPING) { return; } - ItemStack itemstack = entitylivingbaseIn.getItemBySlot(EquipmentSlot.CHEST); - if (itemstack.getItem() instanceof ElytraItem) { + if (renderState.showCape && renderState.chestEquipment.get(DataComponents.GLIDER) != null) { return; } matrixStackIn.pushPose(); - model.young = entitylivingbaseIn.isBaby(); - model.setupAnim(entitylivingbaseIn, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch); +// model.young = renderState.isBaby; + model.setupAnim(renderState); VertexConsumer ivertexbuilder = ItemRenderer.getFoilBuffer(bufferIn, RenderType.entityTranslucent(TEXTURE), false, false); - renderer.getModel().body.translateAndRotate(matrixStackIn); + getParentModel().body.translateAndRotate(matrixStackIn); model.renderToBuffer(matrixStackIn, ivertexbuilder, packedLightIn, OverlayTexture.NO_OVERLAY); matrixStackIn.popPose(); } diff --git a/src/main/java/snownee/kiwi/contributor/impl/client/model/FoxTailModel.java b/src/main/java/snownee/kiwi/contributor/impl/client/model/FoxTailModel.java index 06bd2b35..3aa96a58 100644 --- a/src/main/java/snownee/kiwi/contributor/impl/client/model/FoxTailModel.java +++ b/src/main/java/snownee/kiwi/contributor/impl/client/model/FoxTailModel.java @@ -1,38 +1,43 @@ package snownee.kiwi.contributor.impl.client.model; -import com.google.common.collect.ImmutableList; - -import net.minecraft.client.model.AgeableListModel; +import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.PlayerModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; import net.minecraft.client.model.geom.builders.CubeListBuilder; import net.minecraft.client.model.geom.builders.LayerDefinition; import net.minecraft.client.model.geom.builders.MeshDefinition; import net.minecraft.client.model.geom.builders.PartDefinition; -import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.entity.state.HumanoidRenderState; import net.minecraft.util.Mth; -import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Pose; -public class FoxTailModel extends AgeableListModel { +public class FoxTailModel extends HumanoidModel { - private PlayerModel playerModel; + private PlayerModel playerModel; private ModelPart tail; private ModelPart ear1; private ModelPart ear2; - public FoxTailModel(PlayerModel playerModel, LayerDefinition definition) { + public FoxTailModel(PlayerModel playerModel, ModelPart root) { + super(root); this.playerModel = playerModel; - - ModelPart root = definition.bakeRoot(); - this.ear1 = root.getChild("right_ear"); - this.ear2 = root.getChild("left_ear"); + this.ear1 = root.getChild("head").getChild("right_ear"); + this.ear2 = root.getChild("head").getChild("left_ear"); this.tail = root.getChild("tail"); } public static LayerDefinition create() { - MeshDefinition meshdefinition = new MeshDefinition(); + MeshDefinition meshdefinition = HumanoidModel.createMesh(CubeDeformation.NONE, 0.0F); PartDefinition root = meshdefinition.getRoot(); + PartDefinition head = root.clearChild("head"); + head.clearChild("hat"); + root.clearChild("body"); + root.clearChild("left_arm"); + root.clearChild("right_arm"); + root.clearChild("left_leg"); + root.clearChild("right_leg"); // this.ear1 = new ModelPart(this, 8, 1); // this.ear1.addBox(-4.0F, -10.0F, -4.0F, 2.0F, 2.0F, 1.0F); @@ -42,11 +47,11 @@ public static LayerDefinition create() { // this.tail.addBox(0F, 0F, 0F, 4.0F, 9.0F, 5.0F); //PartDefinition partdefinition1 = root.addOrReplaceChild("head", CubeListBuilder.create().texOffs(1, 5).addBox(-3.0F, -2.0F, -5.0F, 8.0F, 6.0F, 6.0F), PartPose.offset(-1.0F, 16.5F, -3.0F)); - root.addOrReplaceChild( + head.addOrReplaceChild( "right_ear", CubeListBuilder.create().texOffs(8, 1).addBox(-4.0F, -10.0F, -4.0F, 2.0F, 2.0F, 1.0F), PartPose.ZERO); - root.addOrReplaceChild( + head.addOrReplaceChild( "left_ear", CubeListBuilder.create().texOffs(15, 1).addBox(2.0F, -10.0F, -4.0F, 2.0F, 2.0F, 1.0F), PartPose.ZERO); @@ -58,32 +63,20 @@ public static LayerDefinition create() { } @Override - protected Iterable headParts() { - return ImmutableList.of(ear1, ear2); - } - - @Override - protected Iterable bodyParts() { - return ImmutableList.of(tail); - } - - @Override - public void setupAnim(T entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { - ear1.copyFrom(playerModel.head); - ear2.copyFrom(playerModel.head); - if (ageInTicks % 60 < 2) { + public void setupAnim(T renderState) { + super.setupAnim(renderState); + if (renderState.ageInTicks % 60 < 2) { ear1.yRot += 0.05f; ear2.yRot -= 0.05f; } - float delta = Mth.cos(ageInTicks * 0.09F) * 0.05F + 0.05F; - if (entityIn.isCrouching()) { - this.tail.setPos(-2.0F, 14.0F, 5.5F); - this.tail.xRot = 1.25F + delta; + float delta = Mth.cos(renderState.ageInTicks * 0.09F) * 0.05F + 0.05F; + tail.visible = renderState.pose != Pose.SLEEPING; + if (renderState.isCrouching) { + tail.setPos(-2.0F, 14.0F, 5.5F); + tail.xRot = 1.25F + delta; } else { - this.tail.setPos(-2.0F, 10.0F, .5F); - this.tail.xRot = 0.85F + delta; + tail.setPos(-2.0F, 10.0F, .5F); + tail.xRot = 0.85F + delta; } - } - -} +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/contributor/impl/client/model/PlanetModel.java b/src/main/java/snownee/kiwi/contributor/impl/client/model/PlanetModel.java index 29feea6d..e076869b 100644 --- a/src/main/java/snownee/kiwi/contributor/impl/client/model/PlanetModel.java +++ b/src/main/java/snownee/kiwi/contributor/impl/client/model/PlanetModel.java @@ -1,57 +1,56 @@ package snownee.kiwi.contributor.impl.client.model; -import com.google.common.collect.ImmutableList; - -import net.minecraft.client.model.AgeableListModel; +import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; import net.minecraft.client.model.geom.builders.CubeListBuilder; import net.minecraft.client.model.geom.builders.LayerDefinition; import net.minecraft.client.model.geom.builders.MeshDefinition; import net.minecraft.client.model.geom.builders.PartDefinition; -import net.minecraft.world.entity.LivingEntity; +import net.minecraft.client.renderer.entity.state.HumanoidRenderState; -public class PlanetModel extends AgeableListModel { +public class PlanetModel extends HumanoidModel { private final ModelPart largePlanet; private final ModelPart smallPlanet; - public PlanetModel(LayerDefinition definition) { - ModelPart root = definition.bakeRoot(); - this.largePlanet = root.getChild("large"); - this.smallPlanet = root.getChild("small"); + public PlanetModel(ModelPart root) { + super(root); + this.largePlanet = root.getChild("planet_large"); + this.smallPlanet = root.getChild("planet_small"); } public static LayerDefinition create() { - MeshDefinition meshdefinition = new MeshDefinition(); + MeshDefinition meshdefinition = HumanoidModel.createMesh(CubeDeformation.NONE, 0.0F); PartDefinition root = meshdefinition.getRoot(); - root.addOrReplaceChild("large", CubeListBuilder.create() - .texOffs(0, 0) - .addBox(-2.0F, -36.0F, -2.0F, 4.0F, 4.0F, 4.0F) - .texOffs(-9, 8) - .addBox(-4.5F, -34.0F, -4.5F, 9.0F, 0.0F, 9.0F), PartPose.offset(0.0F, 20.0F, -20.0F)); + root.clearChild("body"); + PartDefinition head = root.clearChild("head"); + head.clearChild("hat"); + root.clearChild("left_arm"); + root.clearChild("right_arm"); + root.clearChild("left_leg"); + root.clearChild("right_leg"); + root.addOrReplaceChild( + "planet_large", CubeListBuilder.create() + .texOffs(0, 0) + .addBox(-2.0F, 0, -2.0F, 4.0F, 4.0F, 4.0F) + .texOffs(-9, 8) + .addBox(-4.5F, 2f, -4.5F, 9.0F, 0.0F, 9.0F), + PartPose.offset(0.0F, -6.0F, -20.0F)); root.addOrReplaceChild( - "small", - CubeListBuilder.create().texOffs(16, 0).addBox(-1.5F, -35.0F, -1.5F, 3.0F, 3.0F, 3.0F), - PartPose.offset(0.0F, 20.0F, 16.0F)); + "planet_small", + CubeListBuilder.create().texOffs(16, 0).addBox(-1.5F, 1f, -1.5F, 3.0F, 3.0F, 3.0F), + PartPose.offset(0.0F, -6.0F, 16.0F)); return LayerDefinition.create(meshdefinition, 32, 32); } @Override - protected Iterable headParts() { - return ImmutableList.of(); - } - - @Override - protected Iterable bodyParts() { - return ImmutableList.of(largePlanet, smallPlanet); - } - - @Override - public void setupAnim(T entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { - largePlanet.yRot = -ageInTicks / 10; - smallPlanet.yRot = -ageInTicks / 6; + public void setupAnim(T renderState) { + super.setupAnim(renderState); + largePlanet.yRot = -renderState.ageInTicks / 10; + smallPlanet.yRot = -renderState.ageInTicks / 6; } -} +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/contributor/impl/client/model/SantaHatModel.java b/src/main/java/snownee/kiwi/contributor/impl/client/model/SantaHatModel.java index c757ea75..835110d5 100644 --- a/src/main/java/snownee/kiwi/contributor/impl/client/model/SantaHatModel.java +++ b/src/main/java/snownee/kiwi/contributor/impl/client/model/SantaHatModel.java @@ -1,54 +1,50 @@ package snownee.kiwi.contributor.impl.client.model; -import com.google.common.collect.ImmutableList; - -import net.minecraft.client.model.AgeableListModel; +import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.PlayerModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; import net.minecraft.client.model.geom.builders.CubeListBuilder; import net.minecraft.client.model.geom.builders.LayerDefinition; import net.minecraft.client.model.geom.builders.MeshDefinition; import net.minecraft.client.model.geom.builders.PartDefinition; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.world.entity.LivingEntity; +import net.minecraft.client.renderer.entity.state.HumanoidRenderState; -public class SantaHatModel extends AgeableListModel { +public class SantaHatModel extends HumanoidModel { - private PlayerModel playerModel; + private PlayerModel playerModel; private ModelPart main; - public SantaHatModel(PlayerModel playerModel, LayerDefinition definition) { + public SantaHatModel(PlayerModel playerModel, ModelPart root) { + super(root); this.playerModel = playerModel; - ModelPart root = definition.bakeRoot(); - main = root.getChild("main"); + main = root.getChild("santa"); } public static LayerDefinition create() { - MeshDefinition meshdefinition = new MeshDefinition(); + MeshDefinition meshdefinition = HumanoidModel.createMesh(CubeDeformation.NONE, 0.0F); PartDefinition root = meshdefinition.getRoot(); + root.clearChild("body"); + root.clearChild("left_arm"); + root.clearChild("right_arm"); + root.clearChild("left_leg"); + root.clearChild("right_leg"); + PartDefinition head = root.clearChild("head"); + head.clearChild("hat"); CubeListBuilder builder = CubeListBuilder.create(); builder.texOffs(0, 8).addBox(-0.5F, -10.0F, -3.0F, 5.0F, 2.0F, 5.0F); builder.texOffs(0, 0).addBox(0.0F, -12.0F, -2.5F, 4.0F, 3.0F, 4.0F); builder.texOffs(16, 4).addBox(4.0F, -12.5F, -1.5F, 2.0F, 4.0F, 2.0F); builder.texOffs(12, 0).addBox(5.0F, -9.0F, -1.0F, 2.0F, 2.0F, 2.0F); - root.addOrReplaceChild("main", builder, PartPose.ZERO); + root.addOrReplaceChild("santa", builder, PartPose.ZERO); return LayerDefinition.create(meshdefinition, 32, 32); } @Override - protected Iterable headParts() { - return ImmutableList.of(main); - } - - @Override - protected Iterable bodyParts() { - return ImmutableList.of(); - } - - @Override - public void setupAnim(T entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) { + public void setupAnim(T renderState) { + super.setupAnim(renderState); main.copyFrom(playerModel.head); } -} +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/contributor/impl/client/model/SunnyMilkModel.java b/src/main/java/snownee/kiwi/contributor/impl/client/model/SunnyMilkModel.java index 13f16fc8..27a89248 100644 --- a/src/main/java/snownee/kiwi/contributor/impl/client/model/SunnyMilkModel.java +++ b/src/main/java/snownee/kiwi/contributor/impl/client/model/SunnyMilkModel.java @@ -1,33 +1,39 @@ package snownee.kiwi.contributor.impl.client.model; -import com.google.common.collect.ImmutableList; - import net.minecraft.client.Minecraft; -import net.minecraft.client.model.AgeableListModel; +import net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.geom.ModelPart; import net.minecraft.client.model.geom.PartPose; +import net.minecraft.client.model.geom.builders.CubeDeformation; import net.minecraft.client.model.geom.builders.CubeListBuilder; import net.minecraft.client.model.geom.builders.LayerDefinition; import net.minecraft.client.model.geom.builders.MeshDefinition; import net.minecraft.client.model.geom.builders.PartDefinition; +import net.minecraft.client.renderer.entity.state.HumanoidRenderState; import net.minecraft.util.Mth; -import net.minecraft.world.entity.LivingEntity; -public class SunnyMilkModel extends AgeableListModel { +public class SunnyMilkModel extends HumanoidModel { private float ticks; - private ModelPart wingRight; - private ModelPart wingLeft; + private final ModelPart wingRight; + private final ModelPart wingLeft; - public SunnyMilkModel(LayerDefinition definition) { - ModelPart root = definition.bakeRoot(); + public SunnyMilkModel(ModelPart root) { + super(root); wingLeft = root.getChild("wingLeft"); wingRight = root.getChild("wingRight"); } public static LayerDefinition create() { - MeshDefinition meshdefinition = new MeshDefinition(); + MeshDefinition meshdefinition = HumanoidModel.createMesh(CubeDeformation.NONE, 0.0F); PartDefinition root = meshdefinition.getRoot(); + root.clearChild("body"); + PartDefinition head = root.clearChild("head"); + head.clearChild("hat"); + root.clearChild("left_arm"); + root.clearChild("right_arm"); + root.clearChild("left_leg"); + root.clearChild("right_leg"); CubeListBuilder wingLeft = CubeListBuilder.create(); wingLeft.texOffs(0, 12).addBox(0.5F, -5.5F, 0.0F, 0.0F, 12.0F, 20.0F); @@ -44,21 +50,14 @@ public static LayerDefinition create() { } @Override - protected Iterable headParts() { - return ImmutableList.of(); - } - - @Override - protected Iterable bodyParts() { - return ImmutableList.of(wingLeft, wingRight); - } + public void setupAnim(T renderState) { + super.setupAnim(renderState); - @Override - public void setupAnim(T entityIn, float limbSwing, float limbSwingAmount, float partialTicks, float netHeadYaw, float headPitch) { - float f = ((float) entityIn.getDeltaMovement().length()) * 10; - ticks += Minecraft.getInstance().getTimer().getGameTimeDeltaTicks() * (1 + Math.min(9, f * f * f)) * 0.1f; + float f = renderState.speedValue * 10; + ticks += Minecraft.getInstance().getDeltaTracker() + .getGameTimeDeltaPartialTick(!renderState.isFullyFrozen) * (1 + Math.min(9, f * f * f)) * 0.1f; wingLeft.yRot = -1.0472F + Mth.sin(ticks) * 0.25f; wingRight.yRot = -wingLeft.yRot; } -} +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/contributor/network/CSetCosmeticPacket.java b/src/main/java/snownee/kiwi/contributor/network/CSetCosmeticPacket.java index c867f3e3..a96f4636 100644 --- a/src/main/java/snownee/kiwi/contributor/network/CSetCosmeticPacket.java +++ b/src/main/java/snownee/kiwi/contributor/network/CSetCosmeticPacket.java @@ -1,6 +1,5 @@ package snownee.kiwi.contributor.network; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import net.minecraft.network.RegistryFriendlyByteBuf; @@ -17,10 +16,10 @@ @KiwiPacket public record CSetCosmeticPacket(@Nullable ResourceLocation id) implements CustomPacketPayload { - public static final Type TYPE = new CustomPacketPayload.Type<>(Kiwi.id("set_cosmetic")); + public static final Type TYPE = new Type<>(Kiwi.id("set_cosmetic")); @Override - public @NotNull Type type() { + public Type type() { return TYPE; } diff --git a/src/main/java/snownee/kiwi/contributor/network/SSyncCosmeticPacket.java b/src/main/java/snownee/kiwi/contributor/network/SSyncCosmeticPacket.java index bbb9e424..b3e17477 100644 --- a/src/main/java/snownee/kiwi/contributor/network/SSyncCosmeticPacket.java +++ b/src/main/java/snownee/kiwi/contributor/network/SSyncCosmeticPacket.java @@ -1,8 +1,13 @@ package snownee.kiwi.contributor.network; +import java.util.List; +import java.util.Map; +import java.util.UUID; + import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; +import net.minecraft.core.UUIDUtil; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; @@ -15,8 +20,8 @@ import snownee.kiwi.network.PlayPacketHandler; @KiwiPacket -public record SSyncCosmeticPacket(ImmutableMap data) implements CustomPacketPayload { - public static final Type TYPE = new CustomPacketPayload.Type<>(Kiwi.id("sync_cosmetic")); +public record SSyncCosmeticPacket(Map add, List remove) implements CustomPacketPayload { + public static final Type TYPE = new Type<>(Kiwi.id("sync_cosmetic")); @Override public Type type() { @@ -25,9 +30,14 @@ public Type type() { public static class Handler implements PlayPacketHandler { public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ByteBufCodecs.map(Maps::newHashMapWithExpectedSize, ByteBufCodecs.STRING_UTF8, ResourceLocation.STREAM_CODEC) + ByteBufCodecs.map( + Maps::newHashMapWithExpectedSize, + UUIDUtil.STREAM_CODEC, + ResourceLocation.STREAM_CODEC) .map(ImmutableMap::copyOf, Maps::newHashMap), - SSyncCosmeticPacket::data, + SSyncCosmeticPacket::add, + UUIDUtil.STREAM_CODEC.apply(ByteBufCodecs.list()), + SSyncCosmeticPacket::remove, SSyncCosmeticPacket::new ); @@ -38,7 +48,7 @@ public StreamCodec streamCodec() { @Override public void handle(SSyncCosmeticPacket packet, PayloadContext context) { - context.execute(() -> ContributorsClient.changeCosmetic(packet.data())); + context.execute(() -> ContributorsClient.changeCosmetic(packet)); } } } diff --git a/src/main/java/snownee/kiwi/data/DataModule.java b/src/main/java/snownee/kiwi/data/DataModule.java index 9c52190a..75113d45 100644 --- a/src/main/java/snownee/kiwi/data/DataModule.java +++ b/src/main/java/snownee/kiwi/data/DataModule.java @@ -2,7 +2,7 @@ import net.fabricmc.fabric.api.recipe.v1.ingredient.CustomIngredientSerializer; import net.fabricmc.fabric.api.resource.conditions.v1.ResourceConditions; -import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.display.SlotDisplay; import snownee.kiwi.AbstractModule; import snownee.kiwi.Kiwi; import snownee.kiwi.KiwiCommonConfig; @@ -12,14 +12,17 @@ import snownee.kiwi.recipe.AlternativesIngredient; import snownee.kiwi.recipe.EvalCondition; import snownee.kiwi.recipe.ModuleLoadedCondition; -import snownee.kiwi.recipe.crafting.KiwiShapelessRecipe; -import snownee.kiwi.recipe.crafting.NoContainersShapedRecipe; +import snownee.kiwi.recipe.SizedIngredient; @KiwiModule("data") public final class DataModule extends AbstractModule { - public static final KiwiGO> SHAPED_NO_CONTAINERS = go(NoContainersShapedRecipe.Serializer::new); - public static final KiwiGO> SHAPELESS = go(KiwiShapelessRecipe.Serializer::new); +// public static final KiwiGO> SHAPED_NO_CONTAINERS = go(NoContainersShapedRecipe.Serializer::new); +// public static final KiwiGO> SHAPELESS = go(KiwiShapelessRecipe.Serializer::new); + + public static final KiwiGO> SIZED = go(() -> new SlotDisplay.Type<>( + SizedIngredient.SizedSlotDisplay.MAP_CODEC, + SizedIngredient.SizedSlotDisplay.STREAM_CODEC)); @Override protected void addEntries() { diff --git a/src/main/java/snownee/kiwi/datagen/KiwiBlockLoot.java b/src/main/java/snownee/kiwi/datagen/KiwiBlockLoot.java index e4922fcb..cd1512e4 100644 --- a/src/main/java/snownee/kiwi/datagen/KiwiBlockLoot.java +++ b/src/main/java/snownee/kiwi/datagen/KiwiBlockLoot.java @@ -1,3 +1,4 @@ +/* package snownee.kiwi.datagen; import java.util.List; @@ -81,3 +82,4 @@ public String getName() { return super.getName() + " - " + moduleId; } } + */ \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/datagen/KiwiDataGen.java b/src/main/java/snownee/kiwi/datagen/KiwiDataGen.java index 842a94fd..2efd6ccf 100644 --- a/src/main/java/snownee/kiwi/datagen/KiwiDataGen.java +++ b/src/main/java/snownee/kiwi/datagen/KiwiDataGen.java @@ -1,3 +1,4 @@ +/* package snownee.kiwi.datagen; import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; @@ -10,3 +11,4 @@ public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) { pack.addProvider(KiwiLanguageProvider::new); } } + */ \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/datagen/KiwiLanguageProvider.java b/src/main/java/snownee/kiwi/datagen/KiwiLanguageProvider.java index 516cb159..2da96cde 100644 --- a/src/main/java/snownee/kiwi/datagen/KiwiLanguageProvider.java +++ b/src/main/java/snownee/kiwi/datagen/KiwiLanguageProvider.java @@ -1,3 +1,4 @@ +/* package snownee.kiwi.datagen; import java.io.Reader; @@ -218,3 +219,4 @@ private Path getLangFilePath(String code) { .json(ResourceLocation.fromNamespaceAndPath(dataOutput.getModId(), code)); } } + */ \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/item/ModBlockItem.java b/src/main/java/snownee/kiwi/item/ModBlockItem.java index 9c2b971b..e1d3709a 100644 --- a/src/main/java/snownee/kiwi/item/ModBlockItem.java +++ b/src/main/java/snownee/kiwi/item/ModBlockItem.java @@ -10,53 +10,53 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; +import net.minecraft.util.ProblemReporter; import net.minecraft.world.entity.player.Player; import net.minecraft.world.flag.FeatureFlagSet; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.CreativeModeTab; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.component.CustomData; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import snownee.kiwi.KiwiClientConfig; +import net.minecraft.world.level.storage.TagValueInput; +import snownee.kiwi.Kiwi; import snownee.kiwi.block.IKiwiBlock; import snownee.kiwi.loader.Platform; -import snownee.kiwi.util.NotNullByDefault; -@NotNullByDefault public class ModBlockItem extends BlockItem implements ItemCategoryFiller { public static final Set> INSTANT_UPDATE_TILES = Platform.isPhysicalClient() ? Sets.newHashSet() : null; - public ModBlockItem(Block block, Item.Properties builder) { + public ModBlockItem(Block block, Properties builder) { super(block, builder); } @Override - protected boolean updateCustomBlockEntityTag(BlockPos pos, Level worldIn, @Nullable Player player, ItemStack stack, BlockState state) { + protected boolean updateCustomBlockEntityTag( + BlockPos pos, + Level worldIn, + @Nullable Player player, + ItemStack itemStack, + BlockState state) { if (worldIn.isClientSide) { - BlockEntity tile = worldIn.getBlockEntity(pos); - if (tile != null && INSTANT_UPDATE_TILES.contains(tile.getType())) { - CustomData data = stack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); + BlockEntity be = worldIn.getBlockEntity(pos); + if (be != null && INSTANT_UPDATE_TILES.contains(be.getType())) { + CustomData data = itemStack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); if (!data.isEmpty()) { - tile.loadWithComponents(data.copyTag(), worldIn.registryAccess()); - tile.setChanged(); + try ( + ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector( + be.problemPath(), + Kiwi.LOGGER)) { + be.loadWithComponents(TagValueInput.create(scopedCollector, worldIn.registryAccess(), data.copyTag())); + be.setChanged(); + } } } } - return super.updateCustomBlockEntityTag(pos, worldIn, player, stack, state); - } - - @Override - public void appendHoverText(ItemStack itemStack, TooltipContext tooltipContext, List tooltip, TooltipFlag tooltipFlag) { - super.appendHoverText(itemStack, tooltipContext, tooltip, tooltipFlag); - if (Platform.isPhysicalClient() && !KiwiClientConfig.globalTooltip) { - ModItem.addTip(itemStack, tooltip, tooltipFlag); - } + return super.updateCustomBlockEntityTag(pos, worldIn, player, itemStack, state); } @Override diff --git a/src/main/java/snownee/kiwi/item/ModItem.java b/src/main/java/snownee/kiwi/item/ModItem.java index 99ad038d..ae71560a 100644 --- a/src/main/java/snownee/kiwi/item/ModItem.java +++ b/src/main/java/snownee/kiwi/item/ModItem.java @@ -13,24 +13,12 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; -import snownee.kiwi.KiwiClientConfig; -import snownee.kiwi.loader.Platform; -import snownee.kiwi.util.NotNullByDefault; -@NotNullByDefault public class ModItem extends Item { - public ModItem(Item.Properties builder) { + public ModItem(Properties builder) { super(builder); } - @Override - public void appendHoverText(ItemStack itemStack, TooltipContext tooltipContext, List tooltip, TooltipFlag tooltipFlag) { - super.appendHoverText(itemStack, tooltipContext, tooltip, tooltipFlag); - if (Platform.isPhysicalClient() && !KiwiClientConfig.globalTooltip) { - ModItem.addTip(itemStack, tooltip, tooltipFlag); - } - } - @Environment(EnvType.CLIENT) public static void addTip(ItemStack stack, List tooltip, TooltipFlag flagIn) { if (tooltip.isEmpty()) { @@ -39,12 +27,13 @@ public static void addTip(ItemStack stack, List tooltip, TooltipFlag String key; boolean shift = Screen.hasShiftDown(); boolean ctrl = Screen.hasControlDown(); + String descriptionId = stack.getItem().getDescriptionId(); if (shift == ctrl) { - key = stack.getDescriptionId() + ".tip"; + key = descriptionId + ".tip"; } else if (shift) { - key = stack.getDescriptionId() + ".tip.shift"; + key = descriptionId + ".tip.shift"; } else { // ctrl - key = stack.getDescriptionId() + ".tip.ctrl"; + key = descriptionId + ".tip.ctrl"; } boolean hasKey = I18n.exists(key); if (!hasKey && (shift != ctrl)) { diff --git a/src/main/java/snownee/kiwi/loader/ClientPlatform.java b/src/main/java/snownee/kiwi/loader/ClientPlatform.java index 09b17700..3d390c0b 100644 --- a/src/main/java/snownee/kiwi/loader/ClientPlatform.java +++ b/src/main/java/snownee/kiwi/loader/ClientPlatform.java @@ -1,28 +1,18 @@ package snownee.kiwi.loader; -import java.util.List; import java.util.Locale; -import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; -import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; -import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry; -import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; -import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; import net.minecraft.client.Minecraft; -import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; import net.minecraft.client.particle.ParticleProvider; -import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.ItemBlockRenderTypes; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; +import net.minecraft.client.renderer.chunk.ChunkSectionLayer; import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -31,18 +21,10 @@ public final class ClientPlatform { private ClientPlatform() { } - public static BakedModel getModel(ResourceLocation id) { - return Minecraft.getInstance().getModelManager().getModel(id); - } - - public static void addExtraModels(List ids) { - ModelLoadingPlugin.register(ctx -> ctx.addModels(ids)); - } - public static void registerEntityRenderer( EntityType entityType, EntityRendererProvider entityRendererFactory) { - EntityRendererRegistry.register(entityType, entityRendererFactory); +// EntityRendererRegistry.register(entityType, entityRendererFactory); } public static void registerBlockEntityRenderer( @@ -52,22 +34,15 @@ public static void registerBlockEntityRenderer( } public static void registerParticleType(ParticleType type, ParticleProvider factory) { - ParticleFactoryRegistry.getInstance().register(type, factory); - } - - public static void registerItemColor(ItemColor itemColor, ItemLike... items) { - ColorProviderRegistry.ITEM.register(itemColor, items); - } - - public static void registerBlockColor(BlockColor blockColor, Block... blocks) { - ColorProviderRegistry.BLOCK.register(blockColor, blocks); +// ParticleFactoryRegistry.getInstance().register(type, factory); } - public static void setRenderType(Block block, RenderType renderType) { - BlockRenderLayerMap.INSTANCE.putBlock(block, renderType); + public static void setRenderType(Block block, ChunkSectionLayer layer) { + ItemBlockRenderTypes.TYPE_BY_BLOCK.put(block, layer); } public static Locale getLocale() { - return Locale.getDefault(); + String[] langSplit = Minecraft.getInstance().getLanguageManager().getSelected().split("_", 2); + return langSplit.length == 1 ? new Locale(langSplit[0]) : new Locale(langSplit[0], langSplit[1]); } } diff --git a/src/main/java/snownee/kiwi/loader/KiwiMetadataLoader.java b/src/main/java/snownee/kiwi/loader/KiwiMetadataLoader.java index 372ef528..34d83766 100644 --- a/src/main/java/snownee/kiwi/loader/KiwiMetadataLoader.java +++ b/src/main/java/snownee/kiwi/loader/KiwiMetadataLoader.java @@ -2,8 +2,10 @@ import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; import java.util.function.Function; +import net.fabricmc.loader.api.FabricLoader; import snownee.kiwi.build.KiwiMetadata; import snownee.kiwi.build.KiwiMetadataParser; @@ -11,14 +13,13 @@ public record KiwiMetadataLoader(String modId) implements Function mod.findPath(name)).map(path -> { + try (InputStream is = Files.newInputStream(path)) { + return parser.load(is); + } catch (IOException e) { return null; } - return parser.load(is); - } catch (IOException e) { - return null; - } + }).orElse(null); } } diff --git a/src/main/java/snownee/kiwi/loader/Platform.java b/src/main/java/snownee/kiwi/loader/Platform.java index d4605c56..0ed0e7f5 100644 --- a/src/main/java/snownee/kiwi/loader/Platform.java +++ b/src/main/java/snownee/kiwi/loader/Platform.java @@ -2,11 +2,21 @@ import java.nio.file.Path; import java.text.MessageFormat; +import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.mojang.datafixers.util.Pair; + import net.fabricmc.api.EnvType; import net.fabricmc.fabric.api.entity.FakePlayer; +import net.fabricmc.fabric.api.registry.CompostingChanceRegistry; +import net.fabricmc.fabric.api.registry.FlammableBlockRegistry; +import net.fabricmc.fabric.api.registry.FlattenableBlockRegistry; +import net.fabricmc.fabric.api.registry.StrippableBlockRegistry; +import net.fabricmc.fabric.api.registry.TillableBlockRegistry; +import net.fabricmc.fabric.api.registry.VillagerInteractionRegistries; import net.fabricmc.fabric.api.tag.convention.v2.ConventionalItemTags; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; @@ -24,6 +34,10 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BucketItem; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; import snownee.kiwi.Kiwi; @@ -126,6 +140,38 @@ public static Platform.Type getPlatformSeries() { return Type.Fabric; } + public static void setFireInfo(Block blockIn, int spread, int burn) { + FlammableBlockRegistry.getDefaultInstance().add(blockIn, burn, spread); + } + + public static void registerHoeConversion(Block k, Pair, Consumer> v) { + TillableBlockRegistry.register(k, v.getFirst(), v.getSecond()); + } + + public static void registerAxeConversion(Block k, Block v) { + StrippableBlockRegistry.register(k, v); + } + + public static void registerShovelConversion(Block k, BlockState v) { + FlattenableBlockRegistry.register(k, v); + } + + public static void registerCompostable(float chance, ItemLike itemIn) { + CompostingChanceRegistry.INSTANCE.add(itemIn, chance); + } + + public static void registerVillagerCollectable(ItemLike item) { + VillagerInteractionRegistries.registerCollectable(item); + } + + public static void registerVillagerCompostable(ItemLike item) { + VillagerInteractionRegistries.registerCompostable(item); + } + + public static void registerVillagerFood(ItemLike item, int value) { + VillagerInteractionRegistries.registerFood(item, value); + } + public enum Type { Vanilla, Fabric, Quilt, Forge, NeoForge } diff --git a/src/main/java/snownee/kiwi/mixin/IngredientAccess.java b/src/main/java/snownee/kiwi/mixin/IngredientAccess.java new file mode 100644 index 00000000..189f20a0 --- /dev/null +++ b/src/main/java/snownee/kiwi/mixin/IngredientAccess.java @@ -0,0 +1,14 @@ +package snownee.kiwi.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.core.HolderSet; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.crafting.Ingredient; + +@Mixin(Ingredient.class) +public interface IngredientAccess { + @Accessor + HolderSet getValues(); +} diff --git a/src/main/java/snownee/kiwi/mixin/MixinPlugin.java b/src/main/java/snownee/kiwi/mixin/MixinPlugin.java index debead6b..de99139a 100644 --- a/src/main/java/snownee/kiwi/mixin/MixinPlugin.java +++ b/src/main/java/snownee/kiwi/mixin/MixinPlugin.java @@ -40,17 +40,12 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { if (mixinClassName.startsWith("snownee.kiwi.mixin.customization.")) { return customization; } - if (mixinClassName.equals("snownee.kiwi.mixin.client.CreativeModeInventoryScreenMixin")) { - return persistentCreativeInventory; - } - if (mixinClassName.equals("snownee.kiwi.mixin.client.OptionInstanceMixin")) { - return fastScrolling; - } - if (mixinClassName.equals("snownee.kiwi.mixin.client.FogRendererMixin") || mixinClassName.equals( - "snownee.kiwi.mixin.client.ScreenEffectRendererMixin")) { - return lavaClearView; - } - return true; + return switch (mixinClassName) { + case "snownee.kiwi.mixin.client.CreativeModeInventoryScreenMixin" -> persistentCreativeInventory; + case "snownee.kiwi.mixin.client.OptionInstanceMixin" -> fastScrolling; + case "snownee.kiwi.mixin.client.FogRendererMixin", "snownee.kiwi.mixin.client.ScreenEffectRendererMixin" -> lavaClearView; + default -> true; + }; } @Override diff --git a/src/main/java/snownee/kiwi/mixin/RecipeManagerMixin.java b/src/main/java/snownee/kiwi/mixin/RecipeManagerMixin.java deleted file mode 100644 index b2f4657b..00000000 --- a/src/main/java/snownee/kiwi/mixin/RecipeManagerMixin.java +++ /dev/null @@ -1,38 +0,0 @@ -package snownee.kiwi.mixin; - -import java.util.Map; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.google.gson.JsonElement; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeManager; -import snownee.kiwi.util.KUtil; - -@Mixin(value = RecipeManager.class, priority = 9) -public class RecipeManagerMixin { - - @Inject( - at = @At("HEAD"), - method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V") - private void kiwi_apply( - Map pObject, - ResourceManager pResourceManager, - ProfilerFiller pProfiler, - CallbackInfo ci) { - KUtil.setRecipeManager((RecipeManager) (Object) this); - } - - @Inject(at = @At("HEAD"), method = "replaceRecipes") - private void kiwi_replaceRecipes(Iterable> pRecipes, CallbackInfo ci) { - KUtil.setRecipeManager((RecipeManager) (Object) this); - } - -} diff --git a/src/main/java/snownee/kiwi/mixin/ReloadableServerResourcesMixin.java b/src/main/java/snownee/kiwi/mixin/ReloadableServerResourcesMixin.java deleted file mode 100644 index 01cf085a..00000000 --- a/src/main/java/snownee/kiwi/mixin/ReloadableServerResourcesMixin.java +++ /dev/null @@ -1,19 +0,0 @@ -package snownee.kiwi.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import net.minecraft.server.ReloadableServerResources; -import snownee.kiwi.Kiwi; - -@Mixin(ReloadableServerResources.class) -public class ReloadableServerResourcesMixin { - - @Inject(method = "updateRegistryTags()V", at = @At("RETURN")) - private void kiwi$updateRegistryTags(CallbackInfo ci) { - Kiwi.onTagsUpdated(); - } - -} diff --git a/src/main/java/snownee/kiwi/mixin/client/ClientPacketListenerMixin.java b/src/main/java/snownee/kiwi/mixin/client/ClientPacketListenerMixin.java index 0c848e10..97bfcbc3 100644 --- a/src/main/java/snownee/kiwi/mixin/client/ClientPacketListenerMixin.java +++ b/src/main/java/snownee/kiwi/mixin/client/ClientPacketListenerMixin.java @@ -2,33 +2,34 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.storage.ValueInput; import snownee.kiwi.block.entity.ModBlockEntity; @Mixin(ClientPacketListener.class) public class ClientPacketListenerMixin { - @Inject( + @WrapOperation( + method = {"method_38542", "lambda$handleBlockEntityData$5"}, + remap = false, at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/BlockEntity;loadWithComponents(Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/core/HolderLookup$Provider;)V", + target = "Lnet/minecraft/world/level/block/entity/BlockEntity;loadWithComponents(Lnet/minecraft/world/level/storage/ValueInput;)V", remap = true - ), method = {"method_38542", "lambda$handleBlockEntityData$5"}, cancellable = true, remap = false + ) ) private void kiwi$handleBlockEntityData( - ClientboundBlockEntityDataPacket clientboundBlockEntityDataPacket, - BlockEntity blockEntity, - CallbackInfo ci) { + final BlockEntity blockEntity, final ValueInput valueInput, final Operation original) { if (blockEntity instanceof ModBlockEntity) { ClientPacketListener listener = (ClientPacketListener) (Object) this; - ((ModBlockEntity) blockEntity).onDataPacket(listener.getConnection(), clientboundBlockEntityDataPacket); - ci.cancel(); + ((ModBlockEntity) blockEntity).onDataPacket(listener.getConnection(), valueInput); + } else { + original.call(blockEntity, valueInput); } } - } diff --git a/src/main/java/snownee/kiwi/mixin/client/CreativeModeInventoryScreenMixin.java b/src/main/java/snownee/kiwi/mixin/client/CreativeModeInventoryScreenMixin.java index 34aa2c97..bc1c660f 100644 --- a/src/main/java/snownee/kiwi/mixin/client/CreativeModeInventoryScreenMixin.java +++ b/src/main/java/snownee/kiwi/mixin/client/CreativeModeInventoryScreenMixin.java @@ -10,15 +10,15 @@ import com.llamalad7.mixinextras.sugar.Local; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; -import net.minecraft.client.gui.screens.inventory.EffectRenderingInventoryScreen; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTabs; @Mixin(CreativeModeInventoryScreen.class) -public abstract class CreativeModeInventoryScreenMixin extends EffectRenderingInventoryScreen { +public abstract class CreativeModeInventoryScreenMixin extends AbstractContainerScreen { @Shadow private float scrollOffs; diff --git a/src/main/java/snownee/kiwi/mixin/client/EntityRenderDispatcherAccess.java b/src/main/java/snownee/kiwi/mixin/client/EntityRenderDispatcherAccess.java new file mode 100644 index 00000000..5fa5fc78 --- /dev/null +++ b/src/main/java/snownee/kiwi/mixin/client/EntityRenderDispatcherAccess.java @@ -0,0 +1,17 @@ +package snownee.kiwi.mixin.client; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.resources.PlayerSkin; +import net.minecraft.world.entity.player.Player; + +@Mixin(EntityRenderDispatcher.class) +public interface EntityRenderDispatcherAccess { + @Accessor + Map> getPlayerRenderers(); +} diff --git a/src/main/java/snownee/kiwi/mixin/client/EntityRendererMixin.java b/src/main/java/snownee/kiwi/mixin/client/EntityRendererMixin.java new file mode 100644 index 00000000..c21a10e8 --- /dev/null +++ b/src/main/java/snownee/kiwi/mixin/client/EntityRendererMixin.java @@ -0,0 +1,28 @@ +package snownee.kiwi.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; + +import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.player.PlayerRenderer; +import net.minecraft.client.renderer.entity.state.EntityRenderState; +import net.minecraft.world.entity.Entity; +import snownee.kiwi.contributor.CosmeticRenderState; +import snownee.kiwi.contributor.client.CosmeticLayer; + +@Mixin(EntityRenderer.class) +public class EntityRendererMixin { + @ModifyReturnValue( + method = "createRenderState(Lnet/minecraft/world/entity/Entity;F)Lnet/minecraft/client/renderer/entity/state/EntityRenderState;", + at = @At("RETURN")) + private EntityRenderState kiwi$appendState(final EntityRenderState state, Entity player) { + if (!((Object) this instanceof PlayerRenderer)) { + return state; + } + ((CosmeticRenderState) state).kiwi$setCosmeticLayer(CosmeticLayer.getRendererOf((AbstractClientPlayer) player)); + return state; + } +} diff --git a/src/main/java/snownee/kiwi/mixin/client/FogRendererMixin.java b/src/main/java/snownee/kiwi/mixin/client/LavaFogEnvironmentMixin.java similarity index 56% rename from src/main/java/snownee/kiwi/mixin/client/FogRendererMixin.java rename to src/main/java/snownee/kiwi/mixin/client/LavaFogEnvironmentMixin.java index 1e9bd8a9..88fe6996 100644 --- a/src/main/java/snownee/kiwi/mixin/client/FogRendererMixin.java +++ b/src/main/java/snownee/kiwi/mixin/client/LavaFogEnvironmentMixin.java @@ -6,20 +6,24 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.client.renderer.FogRenderer; +import net.minecraft.client.renderer.fog.environment.LavaFogEnvironment; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; -@Mixin(FogRenderer.class) -public class FogRendererMixin { +@Mixin(LavaFogEnvironment.class) +public class LavaFogEnvironmentMixin { @WrapOperation( method = "setupFog", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;isSpectator()Z", ordinal = 0)) - private static boolean kiwi$setupFog(Entity entity, Operation original) { - if (entity instanceof Player player) { - if (player.isCreative() || player.fireImmune() || player.hasEffect(MobEffects.FIRE_RESISTANCE)) { + private boolean kiwi$setupFog(Entity entity, Operation original) { + if (entity instanceof Player player && player.isCreative()) { + return true; + } + if (entity instanceof LivingEntity living) { + if (living.fireImmune() || living.hasEffect(MobEffects.FIRE_RESISTANCE)) { return true; } } diff --git a/src/main/java/snownee/kiwi/mixin/client/LoadingOverlayMixin.java b/src/main/java/snownee/kiwi/mixin/client/LoadingOverlayMixin.java index 2c6c2f84..9ad70dc1 100644 --- a/src/main/java/snownee/kiwi/mixin/client/LoadingOverlayMixin.java +++ b/src/main/java/snownee/kiwi/mixin/client/LoadingOverlayMixin.java @@ -18,7 +18,7 @@ public class LoadingOverlayMixin { @Inject(method = "render", at = @At("TAIL")) private void kiwi$render(GuiGraphics guiGraphics, int i, int j, float f, CallbackInfo ci) { if (KiwiClientConfig.loadingOverlayNoFade && fadeOutStart > 0L) { - fadeOutStart = 0; + fadeOutStart = 0L; } } } diff --git a/src/main/java/snownee/kiwi/mixin/client/OptionInstanceMixin.java b/src/main/java/snownee/kiwi/mixin/client/OptionInstanceMixin.java index 2b72f375..457c32d9 100644 --- a/src/main/java/snownee/kiwi/mixin/client/OptionInstanceMixin.java +++ b/src/main/java/snownee/kiwi/mixin/client/OptionInstanceMixin.java @@ -23,7 +23,7 @@ public class OptionInstanceMixin { return; } //noinspection ConstantValue - if (mc.options != null && this == (Object) mc.options.mouseWheelSensitivity() && Screen.hasControlDown()) { + if (mc.getWindow() != null && mc.options != null && this == (Object) mc.options.mouseWheelSensitivity() && Screen.hasControlDown()) { ci.setReturnValue((Double) value * 4); } } diff --git a/src/main/java/snownee/kiwi/mixin/client/PlayerRenderStateMixin.java b/src/main/java/snownee/kiwi/mixin/client/PlayerRenderStateMixin.java new file mode 100644 index 00000000..41f66324 --- /dev/null +++ b/src/main/java/snownee/kiwi/mixin/client/PlayerRenderStateMixin.java @@ -0,0 +1,22 @@ +package snownee.kiwi.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; + +import net.minecraft.client.renderer.entity.state.PlayerRenderState; +import snownee.kiwi.contributor.CosmeticRenderState; +import snownee.kiwi.contributor.client.CosmeticLayer; + +@Mixin(PlayerRenderState.class) +public class PlayerRenderStateMixin implements CosmeticRenderState { + private CosmeticLayer kiwi$cosmeticLayer; + + @Override + public CosmeticLayer kiwi$getCosmeticLayer() { + return kiwi$cosmeticLayer; + } + + @Override + public void kiwi$setCosmeticLayer(CosmeticLayer layer) { + kiwi$cosmeticLayer = layer; + } +} diff --git a/src/main/java/snownee/kiwi/mixin/client/RenderLayerAccess.java b/src/main/java/snownee/kiwi/mixin/client/RenderLayerAccess.java new file mode 100644 index 00000000..15ec8040 --- /dev/null +++ b/src/main/java/snownee/kiwi/mixin/client/RenderLayerAccess.java @@ -0,0 +1,15 @@ +package snownee.kiwi.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import net.minecraft.client.model.EntityModel; +import net.minecraft.client.renderer.entity.RenderLayerParent; +import net.minecraft.client.renderer.entity.layers.RenderLayer; +import net.minecraft.client.renderer.entity.state.EntityRenderState; + +@Mixin(RenderLayer.class) +public interface RenderLayerAccess> { + @Accessor + RenderLayerParent getRenderer(); +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/mixin/client/ScreenEffectRendererMixin.java b/src/main/java/snownee/kiwi/mixin/client/ScreenEffectRendererMixin.java index bdd8523d..7faa3e74 100644 --- a/src/main/java/snownee/kiwi/mixin/client/ScreenEffectRendererMixin.java +++ b/src/main/java/snownee/kiwi/mixin/client/ScreenEffectRendererMixin.java @@ -1,32 +1,35 @@ package snownee.kiwi.mixin.client; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.ScreenEffectRenderer; -import net.minecraft.tags.FluidTags; import net.minecraft.world.effect.MobEffects; @Mixin(ScreenEffectRenderer.class) public class ScreenEffectRendererMixin { - @Inject(at = @At("HEAD"), method = "renderFire", cancellable = true) - private static void kiwi$renderFire(Minecraft minecraft, PoseStack poseStack, CallbackInfo ci) { + @WrapMethod(method = "renderFire") + private static void kiwi$renderFire(PoseStack poseStack, MultiBufferSource bufferSource, Operation original) { LocalPlayer player = Minecraft.getInstance().player; if (player == null) { + original.call(poseStack, bufferSource); return; } if (player.isCreative()) { - ci.cancel(); + return; } - if (player.isEyeInFluid(FluidTags.LAVA) && (player.fireImmune() || player.hasEffect(MobEffects.FIRE_RESISTANCE))) { + if (player.fireImmune() || player.hasEffect(MobEffects.FIRE_RESISTANCE)) { + poseStack.pushPose(); poseStack.translate(0, -0.25, 0); + original.call(poseStack, bufferSource); + poseStack.popPose(); } } diff --git a/src/main/java/snownee/kiwi/mixin/client/ScreenMixin.java b/src/main/java/snownee/kiwi/mixin/client/ScreenMixin.java index 4478125c..9e1113ac 100644 --- a/src/main/java/snownee/kiwi/mixin/client/ScreenMixin.java +++ b/src/main/java/snownee/kiwi/mixin/client/ScreenMixin.java @@ -3,15 +3,13 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.player.LocalPlayer; import net.minecraft.network.chat.ClickEvent; -import net.minecraft.network.chat.ClickEvent.Action; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.Style; import snownee.kiwi.KiwiClientConfig; import snownee.kiwi.client.TooltipEvents; import snownee.kiwi.config.KiwiConfigManager; @@ -19,26 +17,21 @@ @Mixin(Screen.class) public class ScreenMixin { - @Inject( - method = "handleComponentClicked", at = @At( - value = "INVOKE", target = "Lnet/minecraft/client/KeyboardHandler;setClipboard(Ljava/lang/String;)V" - ), cancellable = true - ) - private void kiwi$handleComponentClicked(Style style, CallbackInfoReturnable ci) { - ClickEvent clickEvent = style.getClickEvent(); - if (clickEvent == null || clickEvent.getAction() != Action.COPY_TO_CLIPBOARD || !TooltipEvents.disableDebugTooltipCommand.equals( - clickEvent.getValue())) { - return; + @Inject(method = "defaultHandleGameClickEvent", at = @At("HEAD"), cancellable = true) + private static void kiwi$defaultHandleGameClickEvent(ClickEvent clickEvent, Minecraft mc, Screen screen, CallbackInfo ci) { + if (clickEvent instanceof ClickEvent.Custom custom) { + if (custom.id().equals(TooltipEvents.DISABLE_DEBUG_TOOLTIP)) { + if (KiwiClientConfig.tagsTooltip) { + KiwiClientConfig.tagsTooltip = false; + KiwiConfigManager.getHandler(KiwiClientConfig.class).save(); + } + LocalPlayer player = mc.player; + if (player != null) { + player.displayClientMessage(Component.translatable("tip.kiwi.debug_tooltip.success"), false); + } + ci.cancel(); + } } - if (KiwiClientConfig.tagsTooltip) { - KiwiClientConfig.tagsTooltip = false; - KiwiConfigManager.getHandler(KiwiClientConfig.class).save(); - } - LocalPlayer player = Minecraft.getInstance().player; - if (player != null) { - player.displayClientMessage(Component.translatable("tip.kiwi.debug_tooltip.success"), false); - } - ci.setReturnValue(true); } } diff --git a/src/main/java/snownee/kiwi/network/KPacketSender.java b/src/main/java/snownee/kiwi/network/KPacketSender.java index 38620e90..d7f726b5 100644 --- a/src/main/java/snownee/kiwi/network/KPacketSender.java +++ b/src/main/java/snownee/kiwi/network/KPacketSender.java @@ -49,11 +49,6 @@ public static void sendToAll(CustomPacketPayload payload, MinecraftServer server send(payload, PlayerLookup.all(server).stream()); } - @Deprecated - public static void sendToAllExcept(CustomPacketPayload payload, ServerPlayer player) { - send(payload, PlayerLookup.all(player.server).stream().filter(p -> p != player)); - } - public static void sendToAround( CustomPacketPayload payload, ServerLevel world, diff --git a/src/main/java/snownee/kiwi/recipe/AlternativesIngredient.java b/src/main/java/snownee/kiwi/recipe/AlternativesIngredient.java index e205e90b..62428888 100644 --- a/src/main/java/snownee/kiwi/recipe/AlternativesIngredient.java +++ b/src/main/java/snownee/kiwi/recipe/AlternativesIngredient.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Objects; +import java.util.stream.Stream; import org.jetbrains.annotations.Nullable; @@ -11,10 +12,12 @@ import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.Holder; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ExtraCodecs; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import snownee.kiwi.Kiwi; @@ -35,8 +38,8 @@ public boolean test(ItemStack stack) { } @Override - public List getMatchingStacks() { - return List.of(internal().getItems()); + public Stream> getMatchingItems() { + return internal().items(); } @Override @@ -47,7 +50,7 @@ public boolean requiresTesting() { public Ingredient internal() { if (cached == null) { Objects.requireNonNull(options); - cached = Ingredient.EMPTY; + cached = RecipeUtil.emptyIngredient(); for (JsonElement option : options) { Ingredient ingredient; try { @@ -55,7 +58,7 @@ public Ingredient internal() { } catch (Exception e) { continue; } - if (ingredient.getItems().length == 0) { + if (ingredient.isEmpty()) { continue; } cached = ingredient; @@ -86,6 +89,11 @@ public ResourceLocation getIdentifier() { return ID; } + @Override + public MapCodec getCodec() { + return CODEC; + } + public static AlternativesIngredient read(RegistryFriendlyByteBuf buf) { Ingredient internal = Ingredient.CONTENTS_STREAM_CODEC.decode(buf); AlternativesIngredient ingredient = new AlternativesIngredient(null); @@ -97,11 +105,6 @@ public static void write(RegistryFriendlyByteBuf buf, AlternativesIngredient ing Ingredient.CONTENTS_STREAM_CODEC.encode(buf, ingredient.internal()); } - @Override - public MapCodec getCodec(boolean allowEmpty) { - return CODEC; - } - @Override public StreamCodec getPacketCodec() { return STREAM_CODEC; diff --git a/src/main/java/snownee/kiwi/recipe/AlternativesIngredientBuilder.java b/src/main/java/snownee/kiwi/recipe/AlternativesIngredientBuilder.java index 10cf6008..e88b7a11 100644 --- a/src/main/java/snownee/kiwi/recipe/AlternativesIngredientBuilder.java +++ b/src/main/java/snownee/kiwi/recipe/AlternativesIngredientBuilder.java @@ -35,7 +35,7 @@ public AlternativesIngredientBuilder add(ItemLike itemLike) { } public AlternativesIngredientBuilder add(TagKey tag) { - ingredients.add(Ingredient.of(tag)); + ingredients.add(RecipeUtil.tagIngredient(tag)); return this; } @@ -48,7 +48,7 @@ public AlternativesIngredientBuilder add(String tagOrItem) { if (tagOrItem.startsWith("#")) { add(TagKey.create(Registries.ITEM, ResourceLocation.parse(tagOrItem.substring(1)))); } else { - Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(tagOrItem)); + Item item = BuiltInRegistries.ITEM.getValue(ResourceLocation.parse(tagOrItem)); Preconditions.checkState(item != Items.AIR); add(item); } diff --git a/src/main/java/snownee/kiwi/recipe/EvalCondition.java b/src/main/java/snownee/kiwi/recipe/EvalCondition.java index d3d3ef99..1d4ddd68 100644 --- a/src/main/java/snownee/kiwi/recipe/EvalCondition.java +++ b/src/main/java/snownee/kiwi/recipe/EvalCondition.java @@ -10,7 +10,7 @@ import net.fabricmc.fabric.api.resource.conditions.v1.ResourceCondition; import net.fabricmc.fabric.api.resource.conditions.v1.ResourceConditionType; -import net.minecraft.core.HolderLookup; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceLocation; import snownee.kiwi.Kiwi; import snownee.kiwi.util.KEval; @@ -30,7 +30,7 @@ public ResourceConditionType getType() { } @Override - public boolean test(@Nullable HolderLookup.Provider registryLookup) { + public boolean test(RegistryOps.@Nullable RegistryInfoLookup registryInfo) { try { return new Expression(expression, KEval.config()).evaluate().getBooleanValue(); } catch (EvaluationException | ParseException e) { diff --git a/src/main/java/snownee/kiwi/recipe/ModuleLoadedCondition.java b/src/main/java/snownee/kiwi/recipe/ModuleLoadedCondition.java index b2b18b96..aed920eb 100644 --- a/src/main/java/snownee/kiwi/recipe/ModuleLoadedCondition.java +++ b/src/main/java/snownee/kiwi/recipe/ModuleLoadedCondition.java @@ -6,7 +6,7 @@ import net.fabricmc.fabric.api.resource.conditions.v1.ResourceCondition; import net.fabricmc.fabric.api.resource.conditions.v1.ResourceConditionType; -import net.minecraft.core.HolderLookup; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceLocation; import snownee.kiwi.Kiwi; @@ -24,7 +24,7 @@ public ResourceConditionType getType() { } @Override - public boolean test(@Nullable HolderLookup.Provider registryLookup) { + public boolean test(RegistryOps.@Nullable RegistryInfoLookup registryInfo) { return Kiwi.isLoaded(module); } } diff --git a/src/main/java/snownee/kiwi/recipe/RecipeUtil.java b/src/main/java/snownee/kiwi/recipe/RecipeUtil.java new file mode 100644 index 00000000..2a61c7d9 --- /dev/null +++ b/src/main/java/snownee/kiwi/recipe/RecipeUtil.java @@ -0,0 +1,24 @@ +package snownee.kiwi.recipe; + +import java.util.stream.Stream; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.tags.TagKey; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.crafting.Ingredient; + +public final class RecipeUtil { + private static final Ingredient EMPTY_INGREDIENT = Ingredient.of(Stream.empty()); + + private RecipeUtil() { + // Utility class + } + + public static Ingredient tagIngredient(TagKey tag) { + return Ingredient.of(BuiltInRegistries.ITEM.get(tag).orElseThrow()); + } + + public static Ingredient emptyIngredient() { + return EMPTY_INGREDIENT; + } +} diff --git a/src/main/java/snownee/kiwi/recipe/SimpleRecipe.java b/src/main/java/snownee/kiwi/recipe/SimpleRecipe.java index 696dfcb4..de395eb2 100644 --- a/src/main/java/snownee/kiwi/recipe/SimpleRecipe.java +++ b/src/main/java/snownee/kiwi/recipe/SimpleRecipe.java @@ -2,16 +2,16 @@ import net.minecraft.core.HolderLookup; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.PlacementInfo; import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeBookCategories; +import net.minecraft.world.item.crafting.RecipeBookCategory; import net.minecraft.world.item.crafting.RecipeInput; -import snownee.kiwi.util.NotNullByDefault; -@NotNullByDefault public abstract class SimpleRecipe implements Recipe { - @Override - public boolean canCraftInDimensions(int width, int height) { - return true; + public PlacementInfo placementInfo() { + return PlacementInfo.NOT_PLACEABLE; } @Override @@ -20,8 +20,7 @@ public ItemStack assemble(T input, HolderLookup.Provider registryAccess) { } @Override - public ItemStack getResultItem(HolderLookup.Provider registryAccess) { - return ItemStack.EMPTY; + public RecipeBookCategory recipeBookCategory() { + return RecipeBookCategories.CRAFTING_MISC; } - } diff --git a/src/main/java/snownee/kiwi/recipe/SizedIngredient.java b/src/main/java/snownee/kiwi/recipe/SizedIngredient.java new file mode 100644 index 00000000..1553facd --- /dev/null +++ b/src/main/java/snownee/kiwi/recipe/SizedIngredient.java @@ -0,0 +1,148 @@ +package snownee.kiwi.recipe; + +import java.util.Objects; +import java.util.stream.Stream; + +import com.google.common.base.Preconditions; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.tags.TagKey; +import net.minecraft.util.ExtraCodecs; +import net.minecraft.util.context.ContextMap; +import net.minecraft.world.flag.FeatureFlagSet; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.display.DisplayContentsFactory; +import net.minecraft.world.item.crafting.display.SlotDisplay; +import net.minecraft.world.level.ItemLike; +import snownee.kiwi.data.DataModule; +import snownee.kiwi.mixin.IngredientAccess; + +public final class SizedIngredient { + public static final SizedIngredient EMPTY = new SizedIngredient(RecipeUtil.emptyIngredient(), 1); + + private static final Codec FLAT_CODEC = RecordCodecBuilder.create(instance -> instance.group( + Ingredient.NON_AIR_HOLDER_SET_CODEC.xmap(Ingredient::of, it -> ((IngredientAccess) (Object) it).getValues()) + .fieldOf("ingredient") + .forGetter(SizedIngredient::ingredient), + ExtraCodecs.POSITIVE_INT.fieldOf("count").forGetter(SizedIngredient::count) + ).apply(instance, SizedIngredient::new)); + + public static final Codec CODEC = Codec.withAlternative( + RecordCodecBuilder.create(instance -> instance.group( + Ingredient.CODEC.fieldOf("ingredient").forGetter(SizedIngredient::ingredient), + ExtraCodecs.POSITIVE_INT.optionalFieldOf("count", 1).forGetter(SizedIngredient::count) + ).apply(instance, SizedIngredient::new)), FLAT_CODEC); + + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + Ingredient.CONTENTS_STREAM_CODEC, + SizedIngredient::ingredient, + ByteBufCodecs.VAR_INT, + SizedIngredient::count, + SizedIngredient::new); + + public static SizedIngredient of(ItemLike item, int count) { + return new SizedIngredient(Ingredient.of(item), count); + } + + public static SizedIngredient of(TagKey tag, int count) { + return new SizedIngredient(RecipeUtil.tagIngredient(tag), count); + } + + private final Ingredient ingredient; + private final int count; + + public SizedIngredient(Ingredient ingredient, int count) { + Preconditions.checkArgument(count > 0, "Count must be positive"); + this.ingredient = ingredient; + this.count = count; + } + + public Ingredient ingredient() { + return ingredient; + } + + public int count() { + return count; + } + + public boolean test(ItemStack stack) { + return ingredient.test(stack) && (stack.isEmpty() || stack.getCount() >= count); + } + + public SlotDisplay display() { + if (count == 1) { + return ingredient.display(); + } + return new SizedSlotDisplay(ingredient.display(), count); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SizedIngredient other)) { + return false; + } + return count == other.count && ingredient.equals(other.ingredient); + } + + @Override + public int hashCode() { + return Objects.hash(ingredient, count); + } + + @Override + public String toString() { + return count + "x " + ingredient; + } + + public record SizedSlotDisplay(SlotDisplay display, int count) implements SlotDisplay { + public static final MapCodec MAP_CODEC = RecordCodecBuilder.mapCodec(i -> i.group( + SlotDisplay.CODEC.fieldOf( + "display").forGetter(SizedSlotDisplay::display), + ExtraCodecs.POSITIVE_INT.fieldOf("count").forGetter(SizedSlotDisplay::count)).apply(i, SizedSlotDisplay::new)); + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + SlotDisplay.STREAM_CODEC, + SizedSlotDisplay::display, + ByteBufCodecs.VAR_INT, + SizedSlotDisplay::count, + SizedSlotDisplay::new); + + @Override + public String toString() { + return count + "x " + display; + } + + @Override + public Stream resolve(ContextMap context, DisplayContentsFactory output) { + return display.resolve(context, output).peek($ -> { + if ($ instanceof ItemStack itemStack) { + itemStack.setCount(count); + } + }); + } + + @Override + public ItemStack resolveForFirstStack(ContextMap context) { + return display.resolveForFirstStack(context).copyWithCount(count); + } + + @Override + public boolean isEnabled(FeatureFlagSet enabledFeatures) { + return display.isEnabled(enabledFeatures); + } + + @Override + public Type type() { + return DataModule.SIZED.getOrCreate(); + } + } +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/recipe/crafting/DynamicShapedRecipe.java b/src/main/java/snownee/kiwi/recipe/crafting/DynamicShapedRecipe.java index 07346deb..83a30f7d 100644 --- a/src/main/java/snownee/kiwi/recipe/crafting/DynamicShapedRecipe.java +++ b/src/main/java/snownee/kiwi/recipe/crafting/DynamicShapedRecipe.java @@ -1,3 +1,4 @@ +/* package snownee.kiwi.recipe.crafting; import java.util.List; @@ -215,3 +216,4 @@ public static void toNetwork(RegistryFriendlyByt } } } +*/ \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/recipe/crafting/KiwiShapelessRecipe.java b/src/main/java/snownee/kiwi/recipe/crafting/KiwiShapelessRecipe.java index a4c7494c..f13e952d 100644 --- a/src/main/java/snownee/kiwi/recipe/crafting/KiwiShapelessRecipe.java +++ b/src/main/java/snownee/kiwi/recipe/crafting/KiwiShapelessRecipe.java @@ -1,3 +1,4 @@ +/* package snownee.kiwi.recipe.crafting; import com.mojang.serialization.Codec; @@ -121,3 +122,4 @@ public static void toNetwork(RegistryFriendlyByteBuf buffer, KiwiShapelessRecipe } } } + */ \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/recipe/crafting/KiwiShapelessRecipeBuilder.java b/src/main/java/snownee/kiwi/recipe/crafting/KiwiShapelessRecipeBuilder.java index 4c2590b6..6e31cd50 100644 --- a/src/main/java/snownee/kiwi/recipe/crafting/KiwiShapelessRecipeBuilder.java +++ b/src/main/java/snownee/kiwi/recipe/crafting/KiwiShapelessRecipeBuilder.java @@ -1,3 +1,4 @@ +/* package snownee.kiwi.recipe.crafting; import java.util.Objects; @@ -57,4 +58,4 @@ public void save(RecipeOutput recipeOutput, ResourceLocation resourceLocation) { builder.build(resourceLocation.withPrefix("recipes/" + category.getFolderName() + "/"))); } } - +*/ \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/recipe/crafting/NoContainersShapedRecipe.java b/src/main/java/snownee/kiwi/recipe/crafting/NoContainersShapedRecipe.java index f40953e0..6f07297d 100644 --- a/src/main/java/snownee/kiwi/recipe/crafting/NoContainersShapedRecipe.java +++ b/src/main/java/snownee/kiwi/recipe/crafting/NoContainersShapedRecipe.java @@ -1,3 +1,4 @@ +/* package snownee.kiwi.recipe.crafting; import com.mojang.serialization.Codec; @@ -86,3 +87,4 @@ public static void toNetwork(RegistryFriendlyByteBuf buffer, NoContainersShapedR } } } +*/ \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/schedule/ITicker.java b/src/main/java/snownee/kiwi/schedule/ITicker.java deleted file mode 100644 index af08fb64..00000000 --- a/src/main/java/snownee/kiwi/schedule/ITicker.java +++ /dev/null @@ -1,6 +0,0 @@ -package snownee.kiwi.schedule; - -public interface ITicker { - default void destroy() { - } -} diff --git a/src/main/java/snownee/kiwi/schedule/Scheduler.java b/src/main/java/snownee/kiwi/schedule/Scheduler.java deleted file mode 100644 index 1e28e6bf..00000000 --- a/src/main/java/snownee/kiwi/schedule/Scheduler.java +++ /dev/null @@ -1,148 +0,0 @@ -//package snownee.kiwi.schedule; -// -//import java.util.Iterator; -// -//import com.google.common.collect.BiMap; -//import com.google.common.collect.HashBiMap; -//import com.google.common.collect.LinkedListMultimap; -//import com.google.common.collect.Multimap; -// -//import net.fabricmc.api.EnvType; -//import net.fabricmc.api.Environment; -//import net.minecraft.nbt.CompoundTag; -//import net.minecraft.nbt.ListTag; -//import net.minecraft.nbt.Tag; -//import net.minecraft.resources.ResourceLocation; -//import net.minecraft.world.level.saveddata.SavedData; -//import net.minecraftforge.client.event.ClientPlayerNetworkEvent; -//import net.minecraftforge.common.util.INBTSerializable; -//import net.minecraftforge.event.server.ServerStoppedEvent; -//import net.minecraftforge.eventbus.api.SubscribeEvent; -//import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -//import snownee.kiwi.Kiwi; -// -///** -// * @since 2.4 -// */ -//@EventBusSubscriber -//@SuppressWarnings("rawtypes") -//public final class Scheduler extends SavedData { -// public static final String ID = Kiwi.MODID + "-schedule"; -// public static final Scheduler INSTANCE = new Scheduler(); -// -// private static final BiMap> idMap = HashBiMap.create(); -// -// protected static final Multimap taskMap = LinkedListMultimap.create(); -// -// private Scheduler() { -// } -// -// public static void register(ResourceLocation id, Class clazz) { -// if (idMap.containsKey(id)) { -// Kiwi.logger.error("Duplicate task id: " + id); -// } else if (idMap.containsValue(clazz)) { -// Kiwi.logger.error("Duplicate task class: " + clazz); -// } else if (!INBTSerializable.class.isAssignableFrom(clazz)) { -// Kiwi.logger.error("task " + id + " should implement INBTSerializable"); -// } else { -// idMap.put(id, (Class) clazz); -// } -// } -// -// public static Task deserialize(CompoundTag data) { -// try { -// ResourceLocation type = new ResourceLocation(data.getString("type")); -// Class clazz = idMap.get(type); -// if (clazz != null) { -// Task task = clazz.getDeclaredConstructor().newInstance(); -// ((INBTSerializable) task).deserializeNBT(data); -// return task; -// } -// } catch (Exception e) { -// Kiwi.logger.catching(e); -// } -// return null; -// } -// -// public CompoundTag serialize(Task task) { -// if (task.shouldSave()) { -// try { -// ResourceLocation type = idMap.inverse().get(task.getClass()); -// CompoundTag data = ((INBTSerializable) task).serializeNBT(); -// data.putString("type", type.toString()); -// return data; -// } catch (Exception e) { -// Kiwi.logger.catching(e); -// } -// } -// return null; -// } -// -// public static void add(Task task) { -// ITicker ticker = task.ticker(); -// if (ticker != null) { -// taskMap.put(ticker, task); -// } -// } -// -// public static void remove(Task task) { -// taskMap.values().remove(task); -// } -// -// public static void tick(T ticker) { -// Iterator itr = taskMap.get(ticker).iterator(); -// while (itr.hasNext()) { -// Task task = itr.next(); -// if (task.tick(ticker)) { -// itr.remove(); -// } -// } -// } -// -// @Override -// public boolean isDirty() { -// return !taskMap.isEmpty(); -// } -// -// public static Scheduler load(CompoundTag nbt) { -// ListTag list = nbt.getList("tasks", Tag.TAG_COMPOUND); -// for (int i = 0; i < list.size(); i++) { -// Task task = deserialize(list.getCompound(i)); -// if (task != null) { -// add(task); -// } -// } -// return INSTANCE; -// } -// -// @Override -// public CompoundTag save(CompoundTag data) { -// ListTag list = new ListTag(); -// for (Task task : taskMap.values()) { -// CompoundTag nbt = serialize(task); -// if (nbt != null) { -// list.add(nbt); -// } -// } -// if (!list.isEmpty()) { -// data.put("tasks", list); -// } -// return data; -// } -// -// public static void clear() { -// taskMap.keySet().forEach(ITicker::destroy); -// taskMap.clear(); -// } -// -// @Environment(EnvType.CLIENT) -// @SubscribeEvent -// public static void clientLoggedOut(ClientPlayerNetworkEvent.LoggedOutEvent event) { -// clear(); -// } -// -// @SubscribeEvent -// public static void serverStopped(ServerStoppedEvent event) { -// clear(); -// } -//} diff --git a/src/main/java/snownee/kiwi/schedule/Task.java b/src/main/java/snownee/kiwi/schedule/Task.java deleted file mode 100644 index 26d09634..00000000 --- a/src/main/java/snownee/kiwi/schedule/Task.java +++ /dev/null @@ -1,17 +0,0 @@ -package snownee.kiwi.schedule; - -import org.jetbrains.annotations.Nullable; - -public abstract class Task { - public Task() { - } - - abstract public boolean tick(T ticker); - - @Nullable - abstract public T ticker(); - - public boolean shouldSave() { - return true; - } -} diff --git a/src/main/java/snownee/kiwi/schedule/impl/GlobalTicker.java b/src/main/java/snownee/kiwi/schedule/impl/GlobalTicker.java deleted file mode 100644 index 56687324..00000000 --- a/src/main/java/snownee/kiwi/schedule/impl/GlobalTicker.java +++ /dev/null @@ -1,35 +0,0 @@ -//package snownee.kiwi.schedule.impl; -// -//import org.spongepowered.asm.mixin.MixinEnvironment.Phase; -// -//import net.fabricmc.api.EnvType; -//import net.fabricmc.api.Environment; -//import net.minecraftforge.common.MinecraftForge; -//import net.minecraftforge.event.TickEvent; -//import net.minecraftforge.eventbus.api.SubscribeEvent; -//import net.minecraftforge.fml.LogicalSide; -//import snownee.kiwi.schedule.ITicker; -//import snownee.kiwi.schedule.Scheduler; -// -//public enum GlobalTicker implements ITicker { -// PRE_SERVER, POST_SERVER, PRE_CLIENT, POST_CLIENT; -// -// static { -// MinecraftForge.EVENT_BUS.register(GlobalTicker.class); -// } -// -// @SubscribeEvent -// public static void onTickServer(TickEvent.ServerTickEvent event) { -// Scheduler.tick(event.phase == Phase.START ? PRE_SERVER : POST_SERVER); -// } -// -// @SubscribeEvent -// @Environment(EnvType.CLIENT) -// public static void onTickClient(TickEvent.ClientTickEvent event) { -// Scheduler.tick(event.phase == Phase.START ? PRE_CLIENT : POST_CLIENT); -// } -// -// public static GlobalTicker get(LogicalSide side, Phase phase) { -// return side == LogicalSide.SERVER ? (phase == Phase.START ? PRE_SERVER : POST_SERVER) : (phase == Phase.START ? PRE_CLIENT : POST_CLIENT); -// } -//} diff --git a/src/main/java/snownee/kiwi/schedule/impl/LevelTicker.java b/src/main/java/snownee/kiwi/schedule/impl/LevelTicker.java deleted file mode 100644 index 1120038b..00000000 --- a/src/main/java/snownee/kiwi/schedule/impl/LevelTicker.java +++ /dev/null @@ -1,96 +0,0 @@ -//package snownee.kiwi.schedule.impl; -// -//import java.util.Map; -// -//import org.jetbrains.annotations.Nullable; -// -//import com.google.common.collect.Maps; -// -//import net.minecraft.resources.ResourceKey; -//import net.minecraft.world.level.Level; -//import net.minecraftforge.common.MinecraftForge; -//import net.minecraftforge.event.TickEvent; -//import net.minecraftforge.event.world.WorldEvent; -//import net.minecraftforge.eventbus.api.SubscribeEvent; -//import snownee.kiwi.schedule.ITicker; -//import snownee.kiwi.schedule.Scheduler; -// -//public class LevelTicker implements ITicker { -// private static final Map, LevelTicker[]> tickers = Maps.newHashMap(); -// -// public static LevelTicker get(Level level, TickEvent.Phase phase) { -// return get(level.dimension(), phase); -// } -// -// public static LevelTicker get(ResourceKey dimension, TickEvent.Phase phase) { -// LevelTicker[] pair = tickers.computeIfAbsent(dimension, $ -> new LevelTicker[2]); -// LevelTicker ticker = pair[phase.ordinal()]; -// if (ticker == null) { -// ticker = new LevelTicker(dimension); -// pair[phase.ordinal()] = ticker; -// } -// return ticker; -// } -// -// static { -// MinecraftForge.EVENT_BUS.register(LevelTicker.class); -// } -// -// @SubscribeEvent -// public static void onTick(TickEvent.WorldTickEvent event) { -// LevelTicker[] pair = tickers.get(event.world.dimension()); -// if (pair == null) { -// return; -// } -// LevelTicker ticker = pair[event.phase.ordinal()]; -// if (ticker == null) { -// return; -// } -// ticker.level = event.world; -// Scheduler.tick(ticker); -// } -// -// @SubscribeEvent -// public static void unloadLevel(WorldEvent.Unload event) { -// if (!(event.getWorld() instanceof Level)) { -// return; -// } -// LevelTicker[] pair = tickers.get(((Level) event.getWorld()).dimension()); -// if (pair == null) { -// return; -// } -// if (pair[0] != null) { -// pair[0].level = null; -// } -// if (pair[1] != null) { -// pair[1].level = null; -// } -// } -// -// @Nullable -// private Level level; -// private final ResourceKey dimension; -// -// private LevelTicker(ResourceKey dimension) { -// this.dimension = dimension; -// } -// -// @Nullable -// public Level getLevel() { -// return level; -// } -// -// @Override -// public void destroy() { -// LevelTicker[] pair = tickers.get(dimension); -// if (pair != null) { -// if (pair[0] == this) { -// pair[0] = null; -// } -// if (pair[1] == this) { -// pair[1] = null; -// } -// } -// level = null; -// } -//} diff --git a/src/main/java/snownee/kiwi/schedule/impl/SimpleGlobalTask.java b/src/main/java/snownee/kiwi/schedule/impl/SimpleGlobalTask.java deleted file mode 100644 index c2fc2500..00000000 --- a/src/main/java/snownee/kiwi/schedule/impl/SimpleGlobalTask.java +++ /dev/null @@ -1,59 +0,0 @@ -//package snownee.kiwi.schedule.impl; -// -//import java.util.function.IntPredicate; -// -//import org.spongepowered.asm.mixin.MixinEnvironment.Phase; -// -//import net.minecraft.nbt.CompoundTag; -//import net.minecraftforge.common.util.INBTSerializable; -//import net.minecraftforge.fml.LogicalSide; -//import snownee.kiwi.schedule.Task; -// -//public class SimpleGlobalTask extends Task implements INBTSerializable { -// -// protected int tick = 0; -// protected LogicalSide side; -// protected Phase phase; -// protected IntPredicate function; -// -// public SimpleGlobalTask() { -// } -// -// public SimpleGlobalTask(LogicalSide side, Phase phase, IntPredicate function) { -// this.side = side; -// this.phase = phase; -// this.function = function; -// } -// -// @Override -// public boolean tick(GlobalTicker ticker) { -// return function.test(++tick); -// } -// -// @Override -// public GlobalTicker ticker() { -// return GlobalTicker.get(side, phase); -// } -// -// @Override -// public boolean shouldSave() { -// return getClass() != SimpleGlobalTask.class; -// } -// -// @Override -// public CompoundTag serializeNBT() { -// CompoundTag data = new CompoundTag(); -// data.putInt("tick", tick); -// data.putBoolean("client", side.isClient()); -// data.putBoolean("start", phase == Phase.START); -// return data; -// } -// -// @Override -// public void deserializeNBT(CompoundTag nbt) { -// tick = nbt.getInt("tick"); -// side = nbt.getBoolean("client") ? LogicalSide.CLIENT : LogicalSide.SERVER; -// phase = nbt.getBoolean("start") ? Phase.START : Phase.END; -// } -// -//} diff --git a/src/main/java/snownee/kiwi/schedule/impl/SimpleLevelTask.java b/src/main/java/snownee/kiwi/schedule/impl/SimpleLevelTask.java deleted file mode 100644 index 4045dce2..00000000 --- a/src/main/java/snownee/kiwi/schedule/impl/SimpleLevelTask.java +++ /dev/null @@ -1,69 +0,0 @@ -//package snownee.kiwi.schedule.impl; -// -//import java.util.function.IntPredicate; -// -//import org.spongepowered.asm.mixin.MixinEnvironment.Phase; -// -//import net.minecraft.nbt.CompoundTag; -//import net.minecraft.nbt.NbtOps; -//import net.minecraft.resources.ResourceKey; -//import net.minecraft.world.level.Level; -//import net.minecraftforge.common.util.INBTSerializable; -//import net.minecraftforge.event.TickEvent; -//import snownee.kiwi.Kiwi; -//import snownee.kiwi.schedule.Task; -// -//public class SimpleLevelTask extends Task implements INBTSerializable { -// -// protected int tick = 0; -// protected ResourceKey dimension; -// protected TickEvent.Phase phase; -// protected IntPredicate function; -// -// public SimpleLevelTask() { -// } -// -// public SimpleLevelTask(Level world, TickEvent.Phase phase, IntPredicate function) { -// this(world.dimension(), phase, function); -// } -// -// public SimpleLevelTask(ResourceKey dimensionType, TickEvent.Phase phase, IntPredicate function) { -// dimension = dimensionType; -// this.phase = phase; -// this.function = function; -// } -// -// @Override -// public boolean tick(LevelTicker ticker) { -// return function.test(++tick); -// } -// -// @Override -// public LevelTicker ticker() { -// return LevelTicker.get(dimension, phase); -// } -// -// @Override -// public boolean shouldSave() { -// return getClass() != SimpleLevelTask.class; -// } -// -// @Override -// public CompoundTag serializeNBT() { -// CompoundTag data = new CompoundTag(); -// data.putInt("tick", tick); -// Level.RESOURCE_KEY_CODEC.encodeStart(NbtOps.INSTANCE, dimension).resultOrPartial(Kiwi.logger::error).ifPresent(nbt -> { -// data.put("world", nbt); -// }); -// data.putBoolean("start", phase == Phase.START); -// return data; -// } -// -// @Override -// public void deserializeNBT(CompoundTag nbt) { -// dimension = Level.RESOURCE_KEY_CODEC.parse(NbtOps.INSTANCE, nbt.get("world")).resultOrPartial(Kiwi.logger::error).orElse(Level.OVERWORLD); -// tick = nbt.getInt("tick"); -// phase = nbt.getBoolean("start") ? Phase.START : Phase.END; -// } -// -//} diff --git a/src/main/java/snownee/kiwi/test/MyBlockEntity.java b/src/main/java/snownee/kiwi/test/MyBlockEntity.java deleted file mode 100644 index 16c0defe..00000000 --- a/src/main/java/snownee/kiwi/test/MyBlockEntity.java +++ /dev/null @@ -1,38 +0,0 @@ -package snownee.kiwi.test; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.state.BlockState; -import snownee.kiwi.block.entity.ModBlockEntity; -import snownee.kiwi.util.NotNullByDefault; - -@NotNullByDefault -public class MyBlockEntity extends ModBlockEntity { - - public MyBlockEntity(BlockPos pos, BlockState state) { - super(TestModule.FIRST_TILE.get(), pos, state); - persistData = true; - } - - @Override - protected void readPacketData(CompoundTag data) { - } - - @Override - protected CompoundTag writePacketData(CompoundTag data, HolderLookup.Provider provider) { - return data; - } - - @Override - protected void loadAdditional(CompoundTag compoundTag, HolderLookup.Provider provider) { - readPacketData(compoundTag); - super.loadAdditional(compoundTag, provider); - } - - @Override - protected void saveAdditional(CompoundTag compoundTag, HolderLookup.Provider provider) { - writePacketData(compoundTag, provider); - super.saveAdditional(compoundTag, provider); - } -} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/test/MyModule.java b/src/main/java/snownee/kiwi/test/MyModule.java index f36af11b..67ad57d7 100644 --- a/src/main/java/snownee/kiwi/test/MyModule.java +++ b/src/main/java/snownee/kiwi/test/MyModule.java @@ -2,23 +2,14 @@ import net.minecraft.world.level.block.Blocks; import snownee.kiwi.AbstractModule; +import snownee.kiwi.loader.Platform; import snownee.kiwi.loader.event.InitEvent; -import snownee.kiwi.loader.event.PostInitEvent; -import snownee.kiwi.util.VanillaActions; public class MyModule extends AbstractModule { - @Override - protected void addEntries() { - } - @Override protected void init(InitEvent event) { - event.enqueueWork(() -> VanillaActions.registerAxeConversion(Blocks.DIAMOND_BLOCK, Blocks.REDSTONE_BLOCK)); - } - - @Override - protected void postInit(PostInitEvent event) { + event.enqueueWork(() -> Platform.registerAxeConversion(Blocks.DIAMOND_BLOCK, Blocks.REDSTONE_BLOCK)); } } diff --git a/src/main/java/snownee/kiwi/test/MyTask.java b/src/main/java/snownee/kiwi/test/MyTask.java deleted file mode 100644 index 2dd29465..00000000 --- a/src/main/java/snownee/kiwi/test/MyTask.java +++ /dev/null @@ -1,52 +0,0 @@ -//package snownee.kiwi.test; -// -//import net.minecraft.Util; -//import net.minecraft.nbt.CompoundTag; -//import net.minecraft.network.chat.ChatType; -//import net.minecraft.network.chat.TextComponent; -//import net.minecraft.resources.ResourceLocation; -//import net.minecraft.server.MinecraftServer; -//import net.minecraft.world.level.Level; -//import net.minecraftforge.event.TickEvent; -//import snownee.kiwi.schedule.impl.LevelTicker; -//import snownee.kiwi.schedule.impl.SimpleLevelTask; -// -//public class MyTask extends SimpleLevelTask { -// public static final ResourceLocation ID = new ResourceLocation("my_mod", "test"); -// private String words; -// -// public MyTask() { -// } -// -// public MyTask(Level world, TickEvent.Phase phase, String words) { -// super(world, phase, null); -// this.words = words; -// } -// -// @Override -// public boolean tick(LevelTicker ticker) { -// if (++tick >= 50) { -// MinecraftServer server = ticker.getLevel().getServer(); -// if (server != null) { -// TextComponent text = new TextComponent(words); -// server.getPlayerList().broadcastMessage(text, ChatType.SYSTEM, Util.NIL_UUID); -// } -// return true; -// } else { -// return false; -// } -// } -// -// @Override -// public void deserializeNBT(CompoundTag data) { -// super.deserializeNBT(data); -// words = data.getString("words"); -// } -// -// @Override -// public CompoundTag serializeNBT() { -// CompoundTag data = super.serializeNBT(); -// data.putString("words", words); -// return data; -// } -//} diff --git a/src/main/java/snownee/kiwi/test/SMyPacket.java b/src/main/java/snownee/kiwi/test/SMyPacket.java index cd5e1a2b..f13151d9 100644 --- a/src/main/java/snownee/kiwi/test/SMyPacket.java +++ b/src/main/java/snownee/kiwi/test/SMyPacket.java @@ -13,7 +13,7 @@ @KiwiPacket public record SMyPacket(int number) implements CustomPacketPayload { - public static final Type TYPE = new CustomPacketPayload.Type<>(Kiwi.id("my")); + public static final Type TYPE = new Type<>(Kiwi.id("my")); @Override public Type type() { diff --git a/src/main/java/snownee/kiwi/test/TestBlock.java b/src/main/java/snownee/kiwi/test/TestBlock.java deleted file mode 100644 index 81fdd023..00000000 --- a/src/main/java/snownee/kiwi/test/TestBlock.java +++ /dev/null @@ -1,75 +0,0 @@ -package snownee.kiwi.test; - -import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.ItemInteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.StairBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import snownee.kiwi.block.IKiwiBlock; -import snownee.kiwi.block.def.SimpleBlockDefinition; -import snownee.kiwi.block.entity.RetextureBlockEntity; - -// fill ~-40 ~ ~-40 ~40 ~ ~40 kiwi:tex_block -public class TestBlock extends StairBlock implements EntityBlock, IKiwiBlock { - - public TestBlock(Properties builder) { - super(Blocks.STONE.defaultBlockState(), builder); - } - - @Override - protected ItemInteractionResult useItemOn( - ItemStack itemStack, - BlockState blockState, - Level worldIn, - BlockPos pos, - Player player, - InteractionHand handIn, - BlockHitResult blockHitResult) { - if (worldIn.isClientSide) { - return ItemInteractionResult.sidedSuccess(true); - } - BlockEntity tile = worldIn.getBlockEntity(pos); - ItemStack stack = player.getItemInHand(handIn); - if (tile instanceof RetextureBlockEntity && !stack.isEmpty()) { -// if (FullBlockIngredient.isFullBlock(stack)) { - RetextureBlockEntity textureTile = (RetextureBlockEntity) tile; - BlockState state2 = ((BlockItem) stack.getItem()).getBlock().defaultBlockState(); - textureTile.setTexture("0", SimpleBlockDefinition.of(state2)); - textureTile.refresh(); -// } - } - return ItemInteractionResult.sidedSuccess(false); - } - - @Override - public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean isMoving) { - if (pState.hasBlockEntity() && (!pState.is(pNewState.getBlock()) || !pNewState.hasBlockEntity())) { - pLevel.removeBlockEntity(pPos); - } - super.onRemove(pState, pLevel, pPos, pNewState, isMoving); - } - - // @Override - // public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos, Player player) { - // return ModBlock.pick(state, target, world, pos, player); - // } - - @Override - public BlockEntity newBlockEntity(BlockPos p_153215_, BlockState p_153216_) { - return new TestBlockEntity(p_153215_, p_153216_); - } - - @Override - public MutableComponent getName(ItemStack stack) { - return IKiwiBlock.super.getName(stack).append(" " + stack.getCount()); - } -} diff --git a/src/main/java/snownee/kiwi/test/TestBlock2.java b/src/main/java/snownee/kiwi/test/TestBlock2.java deleted file mode 100644 index f3a4c446..00000000 --- a/src/main/java/snownee/kiwi/test/TestBlock2.java +++ /dev/null @@ -1,9 +0,0 @@ -package snownee.kiwi.test; - -public class TestBlock2 extends TestBlock { - - public TestBlock2(Properties builder) { - super(builder); - } - -} diff --git a/src/main/java/snownee/kiwi/test/TestBlockEntity.java b/src/main/java/snownee/kiwi/test/TestBlockEntity.java deleted file mode 100644 index e6792ccc..00000000 --- a/src/main/java/snownee/kiwi/test/TestBlockEntity.java +++ /dev/null @@ -1,27 +0,0 @@ -package snownee.kiwi.test; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.state.BlockState; -import snownee.kiwi.block.entity.RetextureBlockEntity; - -public class TestBlockEntity extends RetextureBlockEntity { - - public TestBlockEntity(BlockPos pos, BlockState state) { - super(TestModule.FIRST_TILE.get(), pos, state, "0"); - } - - @Override - protected void loadAdditional(CompoundTag compoundTag, HolderLookup.Provider provider) { - readPacketData(compoundTag); - super.loadAdditional(compoundTag, provider); - } - - @Override - protected void saveAdditional(CompoundTag compoundTag, HolderLookup.Provider provider) { - writePacketData(compoundTag, provider); - super.saveAdditional(compoundTag, provider); - } - -} diff --git a/src/main/java/snownee/kiwi/test/TestConfig.java b/src/main/java/snownee/kiwi/test/TestConfig.java index ff19967f..b5bcf83b 100644 --- a/src/main/java/snownee/kiwi/test/TestConfig.java +++ b/src/main/java/snownee/kiwi/test/TestConfig.java @@ -1,6 +1,5 @@ package snownee.kiwi.test; -import java.util.Arrays; import java.util.List; import java.util.Map; @@ -15,6 +14,7 @@ @KiwiConfig(value = "test", type = ConfigType.COMMON) public class TestConfig { + @KiwiConfig.PerformanceImpact(KiwiConfig.PerformanceType.HIGH) public static int intValue = 5; @Range(min = 0, max = 114514) @@ -30,7 +30,7 @@ public class TestConfig { @Typed(String.class) @TextDescription(value = "1\n2\n3", after = true) - public static List listValue = Arrays.asList("test"); + public static List listValue = List.of("test"); @TextDescription("Test2") public static String emptyStr; diff --git a/src/main/java/snownee/kiwi/test/TestItem.java b/src/main/java/snownee/kiwi/test/TestItem.java index 8a38d9c2..e53602b3 100644 --- a/src/main/java/snownee/kiwi/test/TestItem.java +++ b/src/main/java/snownee/kiwi/test/TestItem.java @@ -2,19 +2,22 @@ import java.util.List; +import com.google.common.collect.Lists; + import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import snownee.kiwi.item.ModItem; -import snownee.kiwi.network.KPacketSender; +import snownee.kiwi.util.MathUtil; // Your class don't have to extend ModItem or ModBlock to be registered +@SuppressWarnings("deprecation") public class TestItem extends ModItem { public static List posList; public static Vec3 start; @@ -24,34 +27,22 @@ public TestItem(Item.Properties builder) { super(builder); } - // @Override - // public InteractionResult useOn(UseOnContext context) { - // if (!context.getLevel().isClientSide) { - // Scheduler.add(new MyTask(context.getLevel(), Phase.END, "?")); - // } - // Level world = context.getLevel(); - // Scheduler.add(new SimpleLevelTask(world, Phase.END, tick -> { - // if (tick >= 50) { - // System.out.println("五十已到"); - // return true; - // } else { - // return false; - // } - // })); - // System.out.println(TestModule.FIRST_ITEM == TestModule2.FIRST_ITEM); - // return InteractionResult.SUCCESS; - // // Level world = context.getLevel(); - // // Hand hand = context.getHand(); - // // Player player = context.getPlayer(); - // // BlockPos pos = context.getPos(); - // // Direction face = context.getFace(); - // // BlockState state = Blocks.CARVED_PUMPKIN.getDefaultState().with(CarvedPumpkinBlock.FACING, player.getHorizontalFacing().getOpposite()); - // // BlockPos result = PlayerUtil.tryPlace(world, pos, face, player, hand, state, null, true, true); - // // return result == null ? InteractionResult.PASS : InteractionResult.SUCCESS; - // } + @Override + public InteractionResult useOn(UseOnContext context) { + System.out.println(TestModule.FIRST_ITEM == TestModule2.FIRST_ITEM); + return InteractionResult.SUCCESS; + // Level world = context.getLevel(); + // Hand hand = context.getHand(); + // Player player = context.getPlayer(); + // BlockPos pos = context.getPos(); + // Direction face = context.getFace(); + // BlockState state = Blocks.CARVED_PUMPKIN.getDefaultState().with(CarvedPumpkinBlock.FACING, player.getHorizontalFacing().getOpposite()); + // BlockPos result = PlayerUtil.tryPlace(world, pos, face, player, hand, state, null, true, true); + // return result == null ? InteractionResult.PASS : InteractionResult.SUCCESS; + } @Override - public InteractionResultHolder use(Level worldIn, Player playerIn, InteractionHand handIn) { + public InteractionResult use(Level worldIn, Player playerIn, InteractionHand handIn) { // if (worldIn.isRemote) // { // Vec3 start = playerIn.getEyePosition(1).add(playerIn.getLookVec().scale(3)); @@ -63,75 +54,23 @@ public InteractionResultHolder use(Level worldIn, Player playerIn, In // } ItemStack stack = playerIn.getItemInHand(handIn); -// // NBTHelper data = NBTHelper.of(stack); -// // HitResult result = rayTrace(worldIn, playerIn, FluidMode.ANY); -// // if (result != null && result.getType() == Type.BLOCK) -// // { -// // BlockPos pos = ((BlockHitResult) result).getPos(); -// // data.setPos("pos", pos); -// // } -// // else -// // { -// // data.remove("pos"); -// // } -// List list = Lists.newLinkedList(); -// start = playerIn.getEyePosition(1); -// end = start.add(playerIn.getLookAngle().scale(15)); -// MathUtil.posOnLine(start, end, list); -// posList = list; - - -// try { -// RetextureRecipe recipe = new RetextureRecipe(CraftingBookCategory.MISC); -// recipe.result = Items.DIAMOND.getDefaultInstance(); -// recipe.pattern = ShapedRecipePattern.of(Map.of('A', Ingredient.of(Items.DIAMOND)), List.of("A")); -// recipe.textureKeys = Char2ObjectMaps.singleton('A', new String[]{"0"}); -// JsonElement e = DataModule.RETEXTURE.get().codec().encodeStart(JsonOps.INSTANCE, recipe).getOrThrow(false, Kiwi.LOGGER::error); -// System.out.println(e); -// } catch (Exception e) { -// e.printStackTrace(); -// } - - if (!worldIn.isClientSide) { - KPacketSender.send(new SMyPacket(5), playerIn); - } + // NBTHelper data = NBTHelper.of(stack); + // HitResult result = rayTrace(worldIn, playerIn, FluidMode.ANY); + // if (result != null && result.getType() == Type.BLOCK) + // { + // BlockPos pos = ((BlockHitResult) result).getPos(); + // data.setPos("pos", pos); + // } + // else + // { + // data.remove("pos"); + // } + List list = Lists.newLinkedList(); + start = playerIn.getEyePosition(1); + end = start.add(playerIn.getLookAngle().scale(15)); + MathUtil.posOnLine(start, end, list); + posList = list; - return new InteractionResultHolder<>(InteractionResult.SUCCESS, stack); + return InteractionResult.SUCCESS; } - - // @Environment(EnvType.CLIENT) - // public void render(RenderLevelLastEvent event) { - // Screen.fill(0, 0, 20, 20, 20); - // Minecraft mc = Minecraft.getInstance(); - // Player player = mc.player; - // ItemStack stack = player.getHeldItemMainhand(); - // if (posList == null || stack.getItem() != TestModule.FIRST_ITEM) { - // return; - // } - // - // RenderUtil.beginLevel(); - // GlStateManager.disableDepthTest(); - // GlStateManager.disableTexture(); - // GlStateManager.lineWidth(5); - // - // Tessellator tessellator = Tessellator.getInstance(); - // BufferBuilder buffer = tessellator.getBuffer(); - // buffer.begin(3, DefaultVertexFormats.POSITION_COLOR); - // if (start != null) { - // buffer.pos(start.x, start.y, start.z).color(0.5f, 0, 0, 0.5f).endVertex(); - // } - // if (end != null) { - // buffer.pos(end.x, end.y, end.z).color(0.5f, 0, 0, 0.5f).endVertex(); - // } - // for (BlockPos pos : posList) { - // AABB box = new AABB(pos); - // LevelRenderer.drawBoundingBox(buffer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, 0, 0, 0.5f, 0.5f); - // } - // tessellator.draw(); - // RenderUtil.endLevel(); - // - // GlStateManager.enableTexture(); - // GlStateManager.enableDepthTest(); - // //RenderUtil.drawPos(pos); - // } } diff --git a/src/main/java/snownee/kiwi/test/TestModule.java b/src/main/java/snownee/kiwi/test/TestModule.java index 59fa0f30..4ddc7def 100644 --- a/src/main/java/snownee/kiwi/test/TestModule.java +++ b/src/main/java/snownee/kiwi/test/TestModule.java @@ -8,9 +8,9 @@ import net.minecraft.world.item.Rarity; import net.minecraft.world.item.alchemy.Potion; import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.level.block.entity.BlockEntityType; import snownee.kiwi.AbstractModule; import snownee.kiwi.Categories; +import snownee.kiwi.ItemObject; import snownee.kiwi.KiwiGO; import snownee.kiwi.KiwiModule; import snownee.kiwi.KiwiModule.Category; @@ -24,37 +24,36 @@ public class TestModule extends AbstractModule { // Register a simple item @Category(value = Categories.FOOD_AND_DRINKS, after = "apple") - public static final KiwiGO FIRST_ITEM = go(() -> new TestItem(itemProp().rarity(Rarity.EPIC))); - public static final KiwiGO ITEM2 = go(() -> new TestItem(itemProp())); + public static final ItemObject FIRST_ITEM = item(p -> new TestItem(p.rarity(Rarity.EPIC))); + public static final ItemObject ITEM2 = item(TestItem::new); @Category(value = Categories.FOOD_AND_DRINKS, after = "kiwi:item2") - public static final KiwiGO ITEM3 = go(() -> new TestItem(itemProp())); - public static final KiwiGO ITEM4 = go(() -> new TestItem(itemProp())); + public static final ItemObject ITEM3 = item(TestItem::new); + public static final ItemObject ITEM4 = item(TestItem::new); // The next block will use this builder to build its BlockItem. After that this field will be null public static Item.Properties FIRST_BLOCK_ITEM_BUILDER = itemProp().rarity(Rarity.RARE); // Register a simple block and its BlockItem //@RenderLayer(Layer.CUTOUT) - @Category - public static final KiwiGO FIRST_BLOCK = go(() -> new TestBlock2(blockProp())); +// @Category +// public static final KiwiGO FIRST_BLOCK = go(() -> new TestBlock2(blockProp())); // Register a simple effect public static final KiwiGO FIRST_EFFECT = go(() -> new InstantenousMobEffect(MobEffectCategory.BENEFICIAL, 0xFF0000)); // And its potion - public static final KiwiGO FIRST_POTION = go(() -> new Potion(new MobEffectInstance( - FIRST_EFFECT.holder().orElseThrow(), - 1800))); + public static final KiwiGO FIRST_POTION = go(() -> new Potion( + "kiwi:first_potion", + new MobEffectInstance(FIRST_EFFECT.holder().orElseThrow(), 1800))); - public static final KiwiGO> FIRST_TILE = blockEntity(TestBlockEntity::new, null, FIRST_BLOCK); +// public static final KiwiGO> FIRST_TILE = blockEntity(TestBlockEntity::new, null, FIRST_BLOCK); - public static final KiwiGO TEX_BLOCK = go(() -> new TestBlock(blockProp())); - public static final KiwiGO> TEX_TILE = blockEntity(TexBlockEntity::new, null, TEX_BLOCK); +// public static final KiwiGO TEX_BLOCK = go(() -> new TestBlock(blockProp())); +// public static final KiwiGO> TEX_TILE = blockEntity(TexBlockEntity::new, null, TEX_BLOCK); public static TestModule INSTANCE; public static final KiwiGO> RECIPE_TYPE = go(() -> { - return new RecipeType<>() { - }; + return new RecipeType<>() {}; }); // @Override diff --git a/src/main/java/snownee/kiwi/test/TestModule2.java b/src/main/java/snownee/kiwi/test/TestModule2.java index 162b15c1..4474fb27 100644 --- a/src/main/java/snownee/kiwi/test/TestModule2.java +++ b/src/main/java/snownee/kiwi/test/TestModule2.java @@ -1,40 +1,49 @@ package snownee.kiwi.test; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.entity.EntityType; import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.Rarity; import net.minecraft.world.level.block.Blocks; import snownee.kiwi.AbstractModule; +import snownee.kiwi.ItemObject; import snownee.kiwi.Kiwi; import snownee.kiwi.KiwiGO; import snownee.kiwi.KiwiModule; import snownee.kiwi.KiwiModule.Name; +import snownee.kiwi.loader.Platform; import snownee.kiwi.loader.event.InitEvent; -import snownee.kiwi.util.VanillaActions; -@KiwiModule(value = "test2") +@KiwiModule(modId = Kiwi.ID, value = "test2", dependencies = "minecraft;@kiwi:test") @KiwiModule.Optional(defaultEnabled = false) public class TestModule2 extends AbstractModule { public static final KiwiGO TAB = go(() -> itemCategory( - "my_mod", - "items", + ResourceLocation.fromNamespaceAndPath("my_mod", "items"), () -> new ItemStack(Items.DANDELION)).build()); - public static final TagKey> BAT = entityTag(Kiwi.ID, "bat"); + public static final TagKey> BAT = entityTag("bat"); @Name("kiwi:test_item") - public static final KiwiGO FIRST_ITEM = go(() -> new TestItem(itemProp().rarity(Rarity.EPIC)) { + public static final ItemObject FIRST_ITEM = item(p -> new TestItem(p.rarity(Rarity.EPIC)) { @Override public boolean isFoil(ItemStack stack) { return true; } }); + @Name("minecraft:dandelion") + public static final KiwiGO DANDELION = ref(Registries.ITEM); + @Override protected void init(InitEvent event) { - event.enqueueWork(() -> VanillaActions.registerShovelConversion(Blocks.DIAMOND_BLOCK, Blocks.REDSTONE_BLOCK.defaultBlockState())); + event.enqueueWork(() -> { + Platform.registerAxeConversion(Blocks.QUARTZ_PILLAR, Blocks.PURPUR_PILLAR); + Kiwi.LOGGER.info("{}", DANDELION.get()); + }); } } diff --git a/src/main/java/snownee/kiwi/test/TestRecipe.java b/src/main/java/snownee/kiwi/test/TestRecipe.java index 106b201b..5d1e93a1 100644 --- a/src/main/java/snownee/kiwi/test/TestRecipe.java +++ b/src/main/java/snownee/kiwi/test/TestRecipe.java @@ -1,3 +1,4 @@ +/* package snownee.kiwi.test; import com.mojang.serialization.Codec; @@ -97,3 +98,4 @@ public static void toNetwork(RegistryFriendlyByteBuf pBuffer, TestRecipe pRecipe } } } + */ \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/test/TexBlockEntity.java b/src/main/java/snownee/kiwi/test/TexBlockEntity.java deleted file mode 100644 index c432d8ea..00000000 --- a/src/main/java/snownee/kiwi/test/TexBlockEntity.java +++ /dev/null @@ -1,27 +0,0 @@ -package snownee.kiwi.test; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.HolderLookup; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.level.block.state.BlockState; -import snownee.kiwi.block.entity.RetextureBlockEntity; - -public class TexBlockEntity extends RetextureBlockEntity { - - public TexBlockEntity(BlockPos pos, BlockState state) { - super(TestModule.TEX_TILE.get(), pos, state, "0"); - } - - @Override - protected void loadAdditional(CompoundTag compoundTag, HolderLookup.Provider provider) { - readPacketData(compoundTag); - super.loadAdditional(compoundTag, provider); - } - - @Override - protected void saveAdditional(CompoundTag compoundTag, HolderLookup.Provider provider) { - writePacketData(compoundTag, provider); - super.saveAdditional(compoundTag, provider); - } - -} diff --git a/src/main/java/snownee/kiwi/util/BlockPredicateHelper.java b/src/main/java/snownee/kiwi/util/BlockPredicateHelper.java new file mode 100644 index 00000000..bc68e555 --- /dev/null +++ b/src/main/java/snownee/kiwi/util/BlockPredicateHelper.java @@ -0,0 +1,42 @@ +package snownee.kiwi.util; + +import java.util.Optional; +import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.advancements.critereon.BlockPredicate; +import net.minecraft.advancements.critereon.DataComponentMatchers; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +public class BlockPredicateHelper { + + public static final BlockPredicate ANY = new BlockPredicate( + Optional.empty(), + Optional.empty(), + Optional.empty(), + DataComponentMatchers.ANY); + + public static boolean fastMatch(BlockPredicate predicate, BlockState blockstate, Supplier<@Nullable BlockEntity> beGetter) { + if (predicate == ANY) { + return true; + } + if (predicate.blocks().isPresent() && !predicate.blocks().get().contains(blockstate.getBlockHolder())) { + return false; + } + if (!predicate.properties().map(propPredicate -> propPredicate.matches(blockstate)).orElse(Boolean.TRUE)) { + return false; + } + BlockEntity be = predicate.nbt().isPresent() || !predicate.components().isEmpty() ? beGetter.get() : null; + if (predicate.nbt().isPresent()) { + if (be == null || be.getLevel() == null || BlockPredicate.matchesBlockEntity( + be.getLevel(), + be, + predicate.nbt().orElseThrow())) { + return false; + } + } + return predicate.components().isEmpty() || BlockPredicate.matchesComponents(be, predicate.components()); + } +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/util/CachedSupplier.java b/src/main/java/snownee/kiwi/util/CachedSupplier.java index 7f888c2b..c50a9e3f 100644 --- a/src/main/java/snownee/kiwi/util/CachedSupplier.java +++ b/src/main/java/snownee/kiwi/util/CachedSupplier.java @@ -21,6 +21,7 @@ public CachedSupplier(Supplier delegate, @Nullable T fallback) { this.fallback = fallback; } + @Nullable @Override public T get() { if (value != null) { diff --git a/src/main/java/snownee/kiwi/util/ClientProxy.java b/src/main/java/snownee/kiwi/util/ClientProxy.java new file mode 100644 index 00000000..7a8df686 --- /dev/null +++ b/src/main/java/snownee/kiwi/util/ClientProxy.java @@ -0,0 +1,57 @@ +package snownee.kiwi.util; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +import org.jetbrains.annotations.NotNull; + +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents; +import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener; +import net.fabricmc.fabric.api.resource.ResourceManagerHelper; +import net.fabricmc.fabric.mixin.client.rendering.LivingEntityRendererAccessor; +import net.minecraft.client.Minecraft; +import net.minecraft.client.model.PlayerModel; +import net.minecraft.client.renderer.entity.player.PlayerRenderer; +import net.minecraft.client.renderer.entity.state.PlayerRenderState; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.PackType; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.Unit; +import snownee.kiwi.Kiwi; +import snownee.kiwi.contributor.ContributorsClient; +import snownee.kiwi.contributor.client.CosmeticLayer; +import snownee.kiwi.mixin.client.EntityRenderDispatcherAccess; + +public final class ClientProxy { + public static void init() { + ResourceManagerHelper.get(PackType.CLIENT_RESOURCES).registerReloadListener(new IdentifiableResourceReloadListener() { + private static final ResourceLocation ID = Kiwi.id("contributors"); + + @Override + public ResourceLocation getFabricId() { + return ID; + } + + @Override + public @NotNull CompletableFuture reload( + PreparationBarrier barrier, + ResourceManager manager, + Executor backgroundExecutor, + Executor gameExecutor) { + return barrier.wait(Unit.INSTANCE).thenRunAsync( + () -> ((EntityRenderDispatcherAccess) Minecraft.getInstance().getEntityRenderDispatcher()) + .getPlayerRenderers() + .forEach((skin, renderer) -> { + CosmeticLayer layer = new CosmeticLayer((PlayerRenderer) renderer); + CosmeticLayer.ALL_LAYERS.put(skin, layer); + ((LivingEntityRendererAccessor) renderer).callAddFeature(layer); + }), backgroundExecutor); + } + }); + + ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> ContributorsClient.changeCosmetic()); + ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> ContributorsClient.clear()); + ClientTickEvents.END_CLIENT_TICK.register(ContributorsClient::onKeyInput); + } +} diff --git a/src/main/java/snownee/kiwi/util/Color.java b/src/main/java/snownee/kiwi/util/Color.java index a6e0d990..3d1f973a 100644 --- a/src/main/java/snownee/kiwi/util/Color.java +++ b/src/main/java/snownee/kiwi/util/Color.java @@ -2,7 +2,6 @@ import java.util.function.UnaryOperator; -import org.jetbrains.annotations.NotNull; import org.joml.Vector3f; import com.google.common.hash.Hashing; @@ -251,7 +250,7 @@ protected Color setValueUnchecked(int value) { // ********* // - public static Color mixColors(@NotNull Color c1, @NotNull Color c2, float w) { + public static Color mixColors(Color c1, Color c2, float w) { return new Color( (int) (c1.getRed() + (c2.getRed() - c1.getRed()) * w), (int) (c1.getGreen() + (c2.getGreen() - c1.getGreen()) * w), diff --git a/src/main/java/snownee/kiwi/util/GameObjectLookup.java b/src/main/java/snownee/kiwi/util/GameObjectLookup.java index e07af799..5d7cd15a 100644 --- a/src/main/java/snownee/kiwi/util/GameObjectLookup.java +++ b/src/main/java/snownee/kiwi/util/GameObjectLookup.java @@ -8,7 +8,7 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import snownee.kiwi.KiwiGOHolder; +import snownee.kiwi.KiwiGO; import snownee.kiwi.KiwiModule; import snownee.kiwi.KiwiModules; @@ -20,8 +20,8 @@ static Stream all(ResourceKey> registryKey, String modId) { @SuppressWarnings("unchecked") static Stream> allHolders(ResourceKey> registryKey, String modId) { - Registry registry = (Registry) Objects.requireNonNull(BuiltInRegistries.REGISTRY.get(registryKey.location())); - return registry.holders().filter($ -> $.key().location().getNamespace().equals(modId)); + Registry registry = (Registry) Objects.requireNonNull(BuiltInRegistries.REGISTRY.getValue(registryKey.location())); + return registry.listElements().filter($ -> $.key().location().getNamespace().equals(modId)); } static Stream> fromModules(ResourceKey> registryKey, String... ids) { @@ -37,7 +37,7 @@ static Stream> fromModules(ResourceKey> registr }); } - record OptionalEntry(KiwiGOHolder holder, boolean optional) { + record OptionalEntry(KiwiGO holder, boolean optional) { } } diff --git a/src/main/java/snownee/kiwi/util/KEval.java b/src/main/java/snownee/kiwi/util/KEval.java index c9013107..d4502ca0 100644 --- a/src/main/java/snownee/kiwi/util/KEval.java +++ b/src/main/java/snownee/kiwi/util/KEval.java @@ -1,10 +1,10 @@ package snownee.kiwi.util; -import java.math.BigDecimal; +import java.util.List; import java.util.Map; import java.util.TreeMap; -import java.util.function.ToIntFunction; +import com.ezylang.evalex.EvaluationException; import com.ezylang.evalex.Expression; import com.ezylang.evalex.config.ExpressionConfiguration; import com.ezylang.evalex.data.DataAccessorIfc; @@ -14,10 +14,12 @@ import com.ezylang.evalex.operators.AbstractOperator; import com.ezylang.evalex.operators.InfixOperator; import com.ezylang.evalex.operators.OperatorIfc; +import com.ezylang.evalex.parser.ASTNode; import com.ezylang.evalex.parser.Token; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; -import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.ints.IntList; import net.minecraft.resources.ResourceLocation; import snownee.kiwi.KiwiCommonConfig; import snownee.kiwi.KiwiModules; @@ -27,21 +29,23 @@ public class KEval { private static final ExpressionConfiguration CONFIG = ExpressionConfiguration.builder() .defaultConstants(generateConstants()) - .dataAccessorSupplier(DataAccessor::new) + .dataAccessorSupplier(() -> DataAccessor.INSTANCE) .singleQuoteStringLiteralsAllowed(true) .build(); static { config().getFunctionDictionary().addFunction("HAS", new HasFunction()); config().getFunctionDictionary().addFunction("VER", new VerFunction()); + config().getFunctionDictionary().addFunction("RESET", new ResetFunction()); + config().getOperatorDictionary().addOperator("=", new AssignmentOperator()); config().getOperatorDictionary().addOperator("??", new NullishCoalescingOperator()); } private static Map generateConstants() { Map map = new TreeMap<>(ExpressionConfiguration.StandardConstants); - map.put("MC", EvaluationValue.numberValue(new BigDecimal(Platform.getVersionNumber("minecraft")))); - map.put("FORGELIKE", EvaluationValue.booleanValue(Platform.getPlatformSeries() == Platform.Type.Forge)); - map.put("FABRICLIKE", EvaluationValue.booleanValue(Platform.getPlatformSeries() == Platform.Type.Fabric)); + map.put("MC", EvaluationValue.arrayValue(IntList.of(Platform.getVersionNumber(ResourceLocation.DEFAULT_NAMESPACE)))); + map.put("DEVENV", EvaluationValue.booleanValue(!Platform.isProduction())); + map.put("ISCLIENT", EvaluationValue.booleanValue(Platform.isPhysicalClient())); map.put("MODLOADER", EvaluationValue.stringValue(Platform.getPlatform().name())); return map; } @@ -53,10 +57,7 @@ public static ExpressionConfiguration config() { @FunctionParameter(name = "id") private static class HasFunction extends AbstractFunction { @Override - public EvaluationValue evaluate( - Expression expression, - Token functionToken, - EvaluationValue... parameterValues) { + public EvaluationValue evaluate(Expression expression, Token functionToken, EvaluationValue... parameterValues) { String string = parameterValues[0].getStringValue(); if (string.startsWith("@")) { return EvaluationValue.booleanValue(KiwiModules.isLoaded(ResourceLocation.parse(string.substring(1)))); @@ -68,40 +69,79 @@ public EvaluationValue evaluate( @FunctionParameter(name = "id") private static class VerFunction extends AbstractFunction { - private final Object2IntMap cache = new Object2IntAVLTreeMap<>(); + private final Map cache = Maps.newHashMap(); @Override - public EvaluationValue evaluate( - Expression expression, - Token functionToken, - EvaluationValue... parameterValues) { - String string = parameterValues[0].getStringValue(); - return EvaluationValue.numberValue(new BigDecimal(cache.computeIfAbsent( - string, - (ToIntFunction) Platform::getVersionNumber))); + public EvaluationValue evaluate(Expression expression, Token functionToken, EvaluationValue... parameterValues) { + String s = parameterValues[0].getStringValue(); + if (!Platform.isModLoaded(s)) { + return EvaluationValue.NULL_VALUE; + } + return EvaluationValue.arrayValue(cache.computeIfAbsent(s, id -> IntList.of(Platform.getVersionNumber(id)))); + } + } + + private static class ResetFunction extends AbstractFunction { + @Override + public EvaluationValue evaluate(Expression expression, Token functionToken, EvaluationValue... parameterValues) { + ((DataAccessor) expression.getDataAccessor()).variables.clear(); + return EvaluationValue.stringValue("Variables reset"); } } private static class DataAccessor implements DataAccessorIfc { + static final DataAccessor INSTANCE = new DataAccessor(); + private final Map variables = new TreeMap<>(); + @Override public EvaluationValue getData(String variable) { - Object o = KiwiCommonConfig.vars.get(variable); - return EvaluationValue.of(o, config()); + if (KiwiCommonConfig.vars.containsKey(variable)) { + return EvaluationValue.of(KiwiCommonConfig.vars.get(variable), config()); + } + return variables.get(variable); } @Override public void setData(String variable, EvaluationValue value) { + if (KiwiCommonConfig.vars.containsKey(variable)) { + throw new IllegalArgumentException("Cannot assign to constant"); + } + variables.put(variable, value); } } - @InfixOperator(precedence = OperatorIfc.OPERATOR_PRECEDENCE_OR) - private static class NullishCoalescingOperator extends AbstractOperator { - + @InfixOperator(precedence = -1, operandsLazy = true) + private static class AssignmentOperator extends AbstractOperator { @Override public EvaluationValue evaluate( Expression expression, Token operatorToken, - EvaluationValue... operands) { + EvaluationValue... operands) throws EvaluationException { + List parameters; + try { + parameters = expression.getAbstractSyntaxTree().getParameters(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + Preconditions.checkArgument(parameters.size() == 2, "Assignment operator must have exactly two operands"); + ASTNode left = parameters.getFirst(); + Preconditions.checkArgument( + left.getToken().getType() == Token.TokenType.VARIABLE_OR_CONSTANT, + "Left side of assignment must be a variable"); + String varName = left.getToken().getValue(); + if (expression.getConstants().containsKey(varName)) { + throw new IllegalArgumentException("Cannot assign to constant"); + } + EvaluationValue value = expression.evaluateSubtree(operands[1].getExpressionNode()); + expression.getDataAccessor().setData(varName, value); + return value; + } + } + + @InfixOperator(precedence = OperatorIfc.OPERATOR_PRECEDENCE_OR, operandsLazy = true) + private static class NullishCoalescingOperator extends AbstractOperator { + @Override + public EvaluationValue evaluate(Expression expression, Token operatorToken, EvaluationValue... operands) { if (operands[0].isNullValue()) { return operands[1]; } else { diff --git a/src/main/java/snownee/kiwi/util/KEvent.java b/src/main/java/snownee/kiwi/util/KEvent.java index b64e7c52..ffe88513 100644 --- a/src/main/java/snownee/kiwi/util/KEvent.java +++ b/src/main/java/snownee/kiwi/util/KEvent.java @@ -44,4 +44,4 @@ public void register(ResourceLocation phase, T listener) { public void addPhaseOrdering(ResourceLocation firstPhase, ResourceLocation secondPhase) { wrapped.addPhaseOrdering(firstPhase, secondPhase); } -} +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/util/KUtil.java b/src/main/java/snownee/kiwi/util/KUtil.java index 4c3caba1..0c447a4e 100644 --- a/src/main/java/snownee/kiwi/util/KUtil.java +++ b/src/main/java/snownee/kiwi/util/KUtil.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import org.apache.commons.lang3.mutable.MutableBoolean; import org.jetbrains.annotations.Nullable; @@ -22,11 +23,14 @@ import org.yaml.snakeyaml.nodes.SequenceNode; import org.yaml.snakeyaml.representer.Representer; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientPacketListener; +import com.google.gson.JsonElement; + import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; import net.minecraft.world.InteractionHand; @@ -36,23 +40,15 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.RecipeInput; -import net.minecraft.world.item.crafting.RecipeManager; -import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.EntityHitResult; -import snownee.kiwi.loader.Platform; public final class KUtil { - public static final MessageFormat MESSAGE_FORMAT = new MessageFormat("{0,number,0.#}"); + public static final MessageFormat MESSAGE_FORMAT = new MessageFormat("{0,number,#.#}"); private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("###,###"); private static final Yaml YAML; - private static RecipeManager recipeManager; public static final List DIRECTIONS = Direction.stream().toList(); - public static final List HORIZONTAL_DIRECTIONS = Direction.Plane.HORIZONTAL.stream().toList(); static { DumperOptions dumperOptions = new DumperOptions(); @@ -108,6 +104,9 @@ public static String trimRL(String rl, String defaultNamespace) { @Nullable public static ResourceLocation RL(@Nullable String string) { + if (string == null) { + return null; + } try { return ResourceLocation.tryParse(string); } catch (Exception e) { @@ -126,30 +125,6 @@ public static ResourceLocation RL(@Nullable String string, String defaultNamespa return RL(string); } - @Nullable - public static RecipeManager getRecipeManager() { - if (recipeManager == null && Platform.isPhysicalClient()) { - ClientPacketListener connection = Minecraft.getInstance().getConnection(); - if (connection != null) { - return connection.getRecipeManager(); - } - } - return recipeManager; - } - - public static void setRecipeManager(RecipeManager recipeManager) { - KUtil.recipeManager = recipeManager; - } - - public static > List> getRecipes(RecipeType recipeTypeIn) { - RecipeManager manager = getRecipeManager(); - if (manager == null) { - return List.of(); - } else { - return getRecipeManager().getAllRecipesFor(recipeTypeIn); - } - } - public static int friendlyCompare(String a, String b) { int aLength = a.length(); int bLength = b.length(); @@ -182,9 +157,7 @@ public static int friendlyCompare(String a, String b) { } } else if (aNumber && bNumber) { asNumeric = true; - if (lastNumericCompare == 0) { - lastNumericCompare = aChar - bChar; - } + lastNumericCompare = aChar - bChar; } else if (aChar != bChar) { return aChar - bChar; } @@ -240,7 +213,7 @@ public static boolean canPlayerBreak(Player player, BlockState state, BlockPos p return false; } // BreakEvent event = new BreakEvent(player.level, pos, state, player); - // if (MinecraftForge.EVENT_BUS.post(event)) { + // if (NeoForge.EVENT_BUS.post(event)) { // return false; // } return true; @@ -259,6 +232,12 @@ public static int applyAlpha(int color, float alpha) { return (color & 0xFFFFFF) | alphaChannel << 24; } + // GameRenderer.pick + public static float getPickRange(Player player) { + float attrib = 5; + return player.isCreative() ? attrib : attrib - 0.5F; + } + public static void displayClientMessage(@Nullable Player player, boolean client, String key, Object... args) { if (player == null) { return; @@ -266,15 +245,21 @@ public static void displayClientMessage(@Nullable Player player, boolean client, if (client != player.level().isClientSide) { return; } - player.sendSystemMessage(Component.translatable(key, args)); + player.displayClientMessage(Component.translatable(key, args), false); + } + + public static void jsonList(JsonElement json, Consumer collector) { + if (json.isJsonArray()) { + for (JsonElement e : json.getAsJsonArray()) { + collector.accept(e); + } + } else { + collector.accept(json); + } } public static InteractionResult onAttackEntity( - Player player, - Level world, - InteractionHand hand, - Entity entity, - @Nullable EntityHitResult hitResult) { + Player player, Level world, InteractionHand hand, Entity entity, @Nullable EntityHitResult hitResult) { if (entity instanceof ItemFrame frame && !frame.getItem().isEmpty() && !frame.isNoGravity() && !frame.isInvulnerable()) { ItemStack stack = player.getItemInHand(hand); if (stack.is(Items.END_PORTAL_FRAME)) { @@ -285,6 +270,13 @@ public static InteractionResult onAttackEntity( return InteractionResult.PASS; } + public static MutableComponent clickToCopy(MutableComponent component) { + String str = component.getString(); + return component.withStyle(s -> s.withClickEvent(new ClickEvent.CopyToClipboard(str)) + .withHoverEvent(new HoverEvent.ShowText(Component.translatable("chat.copy.click"))) + .withInsertion(str)); + } + public static T loadYaml(String yaml, Class type) { return YAML.loadAs(yaml, type); } @@ -306,6 +298,7 @@ public ResafeConstructor(LoaderOptions loaderOptions) { } private class ConstructSafeMapping extends ConstructMapping { + @Override public Object construct(Node node) { MappingNode mnode = (MappingNode) node; if (node.isTwoStepsConstruction()) { @@ -315,6 +308,7 @@ public Object construct(Node node) { } } + @Override @SuppressWarnings("unchecked") public void construct2ndStep(Node node, Object object) { constructMapping2ndStep((MappingNode) node, (Map) object); diff --git a/src/main/java/snownee/kiwi/util/KiwiEntityTypeBuilder.java b/src/main/java/snownee/kiwi/util/KiwiEntityTypeBuilder.java index 95cc1ca6..0efd84c1 100644 --- a/src/main/java/snownee/kiwi/util/KiwiEntityTypeBuilder.java +++ b/src/main/java/snownee/kiwi/util/KiwiEntityTypeBuilder.java @@ -1,3 +1,4 @@ +/* package snownee.kiwi.util; import java.util.Objects; @@ -194,3 +195,4 @@ public EntityType build() { return builder.build(); } } + */ \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/util/KiwiTabBuilder.java b/src/main/java/snownee/kiwi/util/KiwiTabBuilder.java new file mode 100644 index 00000000..d10f6c56 --- /dev/null +++ b/src/main/java/snownee/kiwi/util/KiwiTabBuilder.java @@ -0,0 +1,17 @@ +package snownee.kiwi.util; + +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.CreativeModeTab; + +public class KiwiTabBuilder extends CreativeModeTab.Builder { + + public final ResourceLocation id; + + public KiwiTabBuilder(ResourceLocation id) { + super(CreativeModeTab.Row.TOP, 0); + this.id = id; + title(Component.translatable("itemGroup.%s.%s".formatted(id.getNamespace(), id.getPath()))); + } + +} diff --git a/src/main/java/snownee/kiwi/util/MultilineTooltip.java b/src/main/java/snownee/kiwi/util/MultilineTooltip.java new file mode 100644 index 00000000..a145fe4d --- /dev/null +++ b/src/main/java/snownee/kiwi/util/MultilineTooltip.java @@ -0,0 +1,32 @@ +package snownee.kiwi.util; + +import java.util.List; + +import org.jetbrains.annotations.Nullable; + +import net.minecraft.client.gui.components.Tooltip; +import net.minecraft.network.chat.Component; + +public class MultilineTooltip { + public static Tooltip create(List components) { + return create(components, components); + } + + public static Tooltip create(List components, @Nullable List narration) { + return Tooltip.create(compose(components), narration == null ? null : compose(narration)); + } + + private static Component compose(List components) { + if (components.isEmpty()) { + return Component.empty(); + } + if (components.size() == 1) { + return components.get(0); + } + Component linebreak = Component.literal("\n"); + return components.stream().skip(1).reduce( + components.get(0).copy(), + (a, b) -> a.append(linebreak).append(b), + (a, b) -> a.append(linebreak).append(b)); + } +} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/util/NBTHelper.java b/src/main/java/snownee/kiwi/util/NBTHelper.java deleted file mode 100644 index 50edb962..00000000 --- a/src/main/java/snownee/kiwi/util/NBTHelper.java +++ /dev/null @@ -1,426 +0,0 @@ -package snownee.kiwi.util; - -import java.util.Collections; -import java.util.Set; -import java.util.UUID; - -import org.jetbrains.annotations.Nullable; - -import com.google.common.base.Preconditions; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.component.DataComponentType; -import net.minecraft.core.component.DataComponents; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.nbt.Tag; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.component.CustomData; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; - -/** - * Simple NBT helper. Use 'a.b.c' to access to values - * - * @author Snownee - */ -public class NBTHelper { - - @Nullable - private ItemStack stack; - @Nullable - private CompoundTag tag; - - private NBTHelper(@Nullable CompoundTag tag, @Nullable ItemStack stack) { - this.stack = stack; - this.tag = tag; - } - - @Nullable - public CompoundTag getTag(String key) { - return getTag(key, false); - } - - public CompoundTag getTag(String key, boolean createIfNull) { - return getTagInternal(key, createIfNull, false); - } - - private CompoundTag getTagInternal(String key, boolean createIfNull, boolean ignoreLastNode) { - if (tag == null) { - if (createIfNull) { - tag = new CompoundTag(); - } else { - return null; - } - } - if (key.isEmpty()) { - return tag; - } - CompoundTag subTag = tag; - String[] parts = key.split("\\."); - int length = parts.length; - if (ignoreLastNode) { - --length; - } - for (int i = 0; i < length; ++i) { - // TODO: list support. e.g. a.b[2].c.d - if (!subTag.contains(parts[i], Tag.TAG_COMPOUND)) { - if (createIfNull) { - subTag.put(parts[i], new CompoundTag()); - } else { - return null; - } - } - subTag = (CompoundTag) subTag.get(parts[i]); - } - return subTag; - } - - private CompoundTag getTagInternal(String key) { - return getTagInternal(key, true, true); - } - - private String getLastNode(String key) { - int index = key.lastIndexOf("."); - if (index < 0) { - return key; - } else { - return key.substring(index + 1); - } - } - - public NBTHelper setTag(String key, Tag value) { - getTagInternal(key).put(getLastNode(key), value); - return this; - } - - public NBTHelper setInt(String key, int value) { - getTagInternal(key).putInt(getLastNode(key), value); - return this; - } - - public int getInt(String key) { - return getInt(key, 0); - } - - public int getInt(String key, int defaultValue) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_INT)) { - return subTag.getInt(actualKey); - } - } - return defaultValue; - } - - public NBTHelper setLong(String key, long value) { - getTagInternal(key).putLong(getLastNode(key), value); - return this; - } - - public long getLong(String key) { - return getLong(key, 0); - } - - public long getLong(String key, long defaultValue) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_LONG)) { - return subTag.getLong(actualKey); - } - } - return defaultValue; - } - - public NBTHelper setShort(String key, short value) { - getTagInternal(key).putShort(getLastNode(key), value); - return this; - } - - public short getShort(String key) { - return getShort(key, (short) 0); - } - - public short getShort(String key, short defaultValue) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_SHORT)) { - return subTag.getShort(actualKey); - } - } - return defaultValue; - } - - public NBTHelper setDouble(String key, double value) { - getTagInternal(key).putDouble(getLastNode(key), value); - return this; - } - - public double getDouble(String key) { - return getDouble(key, 0); - } - - public double getDouble(String key, double defaultValue) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_DOUBLE)) { - return subTag.getDouble(actualKey); - } - } - return defaultValue; - } - - public NBTHelper setFloat(String key, float value) { - getTagInternal(key).putFloat(getLastNode(key), value); - return this; - } - - public float getFloat(String key) { - return getFloat(key, 0); - } - - public float getFloat(String key, float defaultValue) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_FLOAT)) { - return subTag.getFloat(actualKey); - } - } - return defaultValue; - } - - public NBTHelper setByte(String key, byte value) { - getTagInternal(key).putFloat(getLastNode(key), value); - return this; - } - - public byte getByte(String key) { - return getByte(key, (byte) 0); - } - - public byte getByte(String key, byte defaultValue) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_BYTE)) { - return subTag.getByte(actualKey); - } - } - return defaultValue; - } - - public NBTHelper setBoolean(String key, boolean value) { - getTagInternal(key).putBoolean(getLastNode(key), value); - return this; - } - - public boolean getBoolean(String key) { - return getBoolean(key, false); - } - - public boolean getBoolean(String key, boolean defaultValue) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_BYTE)) { - return subTag.getBoolean(actualKey); - } - } - return defaultValue; - } - - public NBTHelper setPos(String key, BlockPos value) { - getTagInternal(key).put(getLastNode(key), NbtUtils.writeBlockPos(value)); - return this; - } - - @Nullable - public BlockPos getPos(String key) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - return NbtUtils.readBlockPos(subTag, actualKey).orElse(null); - } - return null; - } - - // public NBTHelper setGlobalPos(String key, GlobalPos value) { - // getTagInternal(key).put(getLastNode(key), GlobalPos.field_239645_a_.encodeStart(NBTDynamicOps.INSTANCE, value).getOrThrow(allowPartial, onError)); - // return this; - // } - // - // @Nullable - // public GlobalPos getGlobalPos(String key) { - // CompoundTag subTag = getTagInternal(key, false, true); - // if (subTag != null) { - // String actualKey = getLastNode(key); - // if (subTag.contains(actualKey, NBT.COMPOUND)) { - // return GlobalPos.deserialize(new Dynamic<>(NBTDynamicOps.INSTANCE, getTag(actualKey))); - // } - // } - // return null; - // } - - public NBTHelper setBlockState(String key, BlockState value) { - return setTag(key, NbtUtils.writeBlockState(value)); - } - - public BlockState getBlockState(String key) { - CompoundTag subTag = getTagInternal(key, false, false); - if (subTag != null) { - return NbtUtils.readBlockState(BuiltInRegistries.BLOCK.asLookup(), subTag); - } - return Blocks.AIR.defaultBlockState(); - } - - public NBTHelper setString(String key, String value) { - getTagInternal(key).putString(getLastNode(key), value); - return this; - } - - @Nullable - public String getString(String key) { - return getString(key, null); - } - - public String getString(String key, String defaultValue) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_STRING)) { - return subTag.getString(actualKey); - } - } - return defaultValue; - } - - public NBTHelper setIntArray(String key, int[] value) { - getTagInternal(key).putIntArray(getLastNode(key), value); - return this; - } - - public int[] getIntArray(String key) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_INT_ARRAY)) { - return subTag.getIntArray(actualKey); - } - } - return new int[0]; - } - - public NBTHelper setByteArray(String key, byte[] value) { - getTagInternal(key).putByteArray(getLastNode(key), value); - return this; - } - - public byte[] getByteArray(String key) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_BYTE_ARRAY)) { - return subTag.getByteArray(actualKey); - } - } - return new byte[0]; - } - - public NBTHelper setUUID(String key, UUID value) { - getTagInternal(key).putUUID(getLastNode(key), value); - return this; - } - - @Nullable - public UUID getUUID(String key) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.hasUUID(actualKey)) { - return subTag.getUUID(actualKey); - } - } - return null; - } - - public ListTag getTagList(String key, int type) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - if (subTag.contains(actualKey, Tag.TAG_LIST)) { - return subTag.getList(actualKey, type); - } - } - return null; - } - - public boolean hasTag(String key, int type) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - if (key.isEmpty()) { - return true; - } - String actualKey = getLastNode(key); - return subTag.contains(actualKey, type); - } - return false; - } - - public Set keySet(String key) { - return hasTag(key, Tag.TAG_COMPOUND) ? getTag(key).getAllKeys() : Collections.EMPTY_SET; - } - - // TODO: remove parent if empty? - public NBTHelper remove(String key) { - CompoundTag subTag = getTagInternal(key, false, true); - if (subTag != null) { - String actualKey = getLastNode(key); - subTag.remove(actualKey); - } - return this; - } - - @Nullable - public CompoundTag get() { - return tag; - } - - public ItemStack getItem() { - return stack == null ? ItemStack.EMPTY : stack; - } - - public NBTHelper updateItemData() { - return updateItemData(DataComponents.CUSTOM_DATA); - } - - public NBTHelper updateItemData(DataComponentType componentType) { - Preconditions.checkNotNull(stack); - if (tag == null) { - stack.remove(componentType); - } else { - CustomData.set(componentType, stack, tag); - } - return this; - } - - public static NBTHelper of(ItemStack stack) { - Preconditions.checkState(!stack.isEmpty()); - return new NBTHelper(stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(), stack); - } - - public static NBTHelper of(CompoundTag tag) { - return new NBTHelper(tag, null); - } - - public static NBTHelper create() { - return of(new CompoundTag()); - } - -} diff --git a/src/main/java/snownee/kiwi/util/SimulationBlockGetter.java b/src/main/java/snownee/kiwi/util/SimulationBlockGetter.java index 45236ae4..f741b265 100644 --- a/src/main/java/snownee/kiwi/util/SimulationBlockGetter.java +++ b/src/main/java/snownee/kiwi/util/SimulationBlockGetter.java @@ -1,5 +1,7 @@ package snownee.kiwi.util; +import org.jetbrains.annotations.Nullable; + import net.minecraft.core.BlockPos; import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.block.Blocks; @@ -22,6 +24,7 @@ public void setPos(BlockPos pos) { } @Override + @Nullable public BlockEntity getBlockEntity(BlockPos pos) { if (simulatedBlockEntity != null && pos.equals(simulatedPos)) { return simulatedBlockEntity; diff --git a/src/main/java/snownee/kiwi/util/TriState.java b/src/main/java/snownee/kiwi/util/TriState.java deleted file mode 100644 index 645bc50f..00000000 --- a/src/main/java/snownee/kiwi/util/TriState.java +++ /dev/null @@ -1,126 +0,0 @@ -package snownee.kiwi.util; - -import java.util.Objects; -import java.util.Optional; -import java.util.function.BooleanSupplier; -import java.util.function.Supplier; - -import org.jetbrains.annotations.Nullable; - -import it.unimi.dsi.fastutil.booleans.Boolean2ObjectFunction; - -/** - * Represents a boolean value which can be true, false or refer to a default value. - */ -public enum TriState { - /** - * Represents the boolean value of {@code false}. - */ - FALSE, - /** - * Represents a value that refers to a "default" value, often as a fallback. - */ - DEFAULT, - /** - * Represents the boolean value of {@code true}. - */ - TRUE; - - /** - * Gets the corresponding tri-state from a boolean value. - * - * @param bool the boolean value - * @return {@link TriState#TRUE} or {@link TriState#FALSE} depending on the value of the boolean. - */ - public static TriState of(boolean bool) { - return bool ? TRUE : FALSE; - } - - /** - * Gets a tri-state from a nullable boxed boolean. - * - * @param bool the boolean value - * @return {@link TriState#DEFAULT} if {@code null}. - * Otherwise {@link TriState#TRUE} or {@link TriState#FALSE} depending on the value of the boolean. - */ - public static TriState of(@Nullable Boolean bool) { - return bool == null ? DEFAULT : of(bool.booleanValue()); - } - - /** - * Gets the value of the tri-state. - * - * @return true if the tri-state is {@link TriState#TRUE}, - * otherwise false. - */ - public boolean get() { - return this == TRUE; - } - - /** - * Gets the value of the tri-state as a boxed, nullable boolean. - * - * @return {@code null} if {@link TriState#DEFAULT}. - * Otherwise {@code true} if {@link TriState#TRUE} or {@code false} if {@link TriState#FALSE}. - */ - @Nullable - public Boolean getBoxed() { - return this == DEFAULT ? null : this.get(); - } - - /** - * Gets the value of this tri-state. - * If the value is {@link TriState#DEFAULT} then use the supplied value. - * - * @param value the value to fall back to - * @return the value of the tri-state or the supplied value if {@link TriState#DEFAULT}. - */ - public boolean orElse(boolean value) { - return this == DEFAULT ? value : this.get(); - } - - /** - * Gets the value of this tri-state. - * If the value is {@link TriState#DEFAULT} then use the supplied value. - * - * @param supplier the supplier used to get the value to fall back to - * @return the value of the tri-state or the value of the supplier if the tri-state is {@link TriState#DEFAULT}. - */ - public boolean orElseGet(BooleanSupplier supplier) { - return this == DEFAULT ? supplier.getAsBoolean() : this.get(); - } - - /** - * Maps the boolean value of this tri-state if it is {@link TriState#TRUE} or {@link TriState#FALSE}. - * - * @param mapper the mapper to use - * @param the type of object being supplier by the mapper - * @return an optional containing the mapped value; {@link Optional#empty()} if the tri-state is - * {@link TriState#DEFAULT} or the value provided by the mapper is {@code null}. - */ - public Optional map(Boolean2ObjectFunction mapper) { - Objects.requireNonNull(mapper, "Mapper function cannot be null"); - - if (this == DEFAULT) { - return Optional.empty(); - } - - return Optional.ofNullable(mapper.apply(this.get())); - } - - /** - * Gets the value of this tri-state, or throws an exception if this tri-state's value is {@link TriState#DEFAULT}. - * - * @param exceptionSupplier the supplying function that produces an exception to be thrown - * @param Type of the exception to be thrown - * @return the value - * @throws X if the value is {@link TriState#DEFAULT} - */ - public boolean orElseThrow(Supplier exceptionSupplier) throws X { - if (this != DEFAULT) { - return this.get(); - } - - throw exceptionSupplier.get(); - } -} \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/util/VanillaActions.java b/src/main/java/snownee/kiwi/util/VanillaActions.java deleted file mode 100644 index 2746b8ca..00000000 --- a/src/main/java/snownee/kiwi/util/VanillaActions.java +++ /dev/null @@ -1,58 +0,0 @@ -package snownee.kiwi.util; - -import java.util.function.Consumer; -import java.util.function.Predicate; - -import com.mojang.datafixers.util.Pair; - -import net.fabricmc.fabric.api.registry.CompostingChanceRegistry; -import net.fabricmc.fabric.api.registry.FlammableBlockRegistry; -import net.fabricmc.fabric.api.registry.FlattenableBlockRegistry; -import net.fabricmc.fabric.api.registry.StrippableBlockRegistry; -import net.fabricmc.fabric.api.registry.TillableBlockRegistry; -import net.fabricmc.fabric.api.registry.VillagerInteractionRegistries; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.ItemLike; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; - -/** - * @since 5.0.0 - */ -public final class VanillaActions { //TODO brewing - private VanillaActions() { - } - - public static void setFireInfo(Block blockIn, int spread, int burn) { - FlammableBlockRegistry.getDefaultInstance().add(blockIn, burn, spread); - } - - public static void registerHoeConversion(Block k, Pair, Consumer> v) { - TillableBlockRegistry.register(k, v.getFirst(), v.getSecond()); - } - - public static void registerAxeConversion(Block k, Block v) { - StrippableBlockRegistry.register(k, v); - } - - public static void registerShovelConversion(Block k, BlockState v) { - FlattenableBlockRegistry.register(k, v); - } - - public static void registerCompostable(float chance, ItemLike itemIn) { - CompostingChanceRegistry.INSTANCE.add(itemIn, chance); - } - - public static void registerVillagerCollectable(ItemLike item) { - VillagerInteractionRegistries.registerCollectable(item); - } - - public static void registerVillagerCompostable(ItemLike item) { - VillagerInteractionRegistries.registerCompostable(item); - } - - public static void registerVillagerFood(ItemLike item, int value) { - VillagerInteractionRegistries.registerFood(item, value); - } - -} diff --git a/src/main/java/snownee/kiwi/util/VoxelUtil.java b/src/main/java/snownee/kiwi/util/VoxelUtil.java index 3c9f7a92..7bde5b55 100644 --- a/src/main/java/snownee/kiwi/util/VoxelUtil.java +++ b/src/main/java/snownee/kiwi/util/VoxelUtil.java @@ -24,7 +24,8 @@ public final class VoxelUtil { * Prints out an easy to copy-paste string representing the cuboid of a shape */ public static void print(double x1, double y1, double z1, double x2, double y2, double z2) { - Kiwi.LOGGER.info("box({}, {}, {}, {}, {}, {}),", Math.min(x1, x2), Math.min(y1, y2), Math.min(z1, z2), + Kiwi.LOGGER.info( + "box({}, {}, {}, {}, {}, {}),", Math.min(x1, x2), Math.min(y1, y2), Math.min(z1, z2), Math.max(x1, x2), Math.max(y1, y2), Math.max(z1, z2)); } @@ -237,7 +238,7 @@ public static void setShape(VoxelShape shape, VoxelShape[] dest, boolean vertica } public static void setShape(VoxelShape shape, VoxelShape[] dest, boolean verticalAxis, boolean invert) { - List dirs = verticalAxis ? KUtil.DIRECTIONS : KUtil.HORIZONTAL_DIRECTIONS; + Iterable dirs = verticalAxis ? KUtil.DIRECTIONS : Direction.Plane.HORIZONTAL; for (Direction side : dirs) { dest[verticalAxis ? side.ordinal() : side.ordinal() - 2] = verticalAxis ? VoxelUtil.rotate( shape, diff --git a/src/main/java/snownee/kiwi/util/WrappedBlockGetter.java b/src/main/java/snownee/kiwi/util/WrappedBlockGetter.java index 35864475..2284fab2 100644 --- a/src/main/java/snownee/kiwi/util/WrappedBlockGetter.java +++ b/src/main/java/snownee/kiwi/util/WrappedBlockGetter.java @@ -1,5 +1,7 @@ package snownee.kiwi.util; +import org.jetbrains.annotations.Nullable; + import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.BlockAndTintGetter; @@ -18,6 +20,7 @@ public void setLevel(BlockAndTintGetter level) { } @Override + @Nullable public BlockEntity getBlockEntity(BlockPos pos) { return delegate.getBlockEntity(pos); } @@ -53,8 +56,7 @@ public int getHeight() { } @Override - public int getMinBuildHeight() { - return delegate.getMinBuildHeight(); + public int getMinY() { + return delegate.getMinY(); } - } diff --git a/src/main/java/snownee/kiwi/util/client/ColorProviderUtil.java b/src/main/java/snownee/kiwi/util/client/ColorProviderUtil.java index e4663120..bc7431d3 100644 --- a/src/main/java/snownee/kiwi/util/client/ColorProviderUtil.java +++ b/src/main/java/snownee/kiwi/util/client/ColorProviderUtil.java @@ -1,15 +1,13 @@ package snownee.kiwi.util.client; +import java.util.Objects; import java.util.function.Supplier; import org.jetbrains.annotations.Nullable; import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; import net.minecraft.client.color.block.BlockColor; -import net.minecraft.client.color.item.ItemColor; import net.minecraft.core.BlockPos; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; @@ -20,33 +18,13 @@ public static BlockColor delegate(Block block) { return new BlockDelegate(() -> ColorProviderRegistry.BLOCK.get(block)); } - public static ItemColor delegate(Item item) { - return new ItemDelegate(() -> ColorProviderRegistry.ITEM.get(item)); - } - - public static ItemColor delegateItemFallback(Block block) { - return new ItemDelegate(() -> { - BlockColor blockColor = ColorProviderRegistry.BLOCK.get(block); - if (blockColor == null) { - return null; - } else { - return (stack, i) -> blockColor.getColor(block.defaultBlockState(), null, null, i); - } - }); - } - - public static class Dummy implements ItemColor, BlockColor { + public static class Dummy implements BlockColor { public static final Dummy INSTANCE = new Dummy(); @Override public int getColor(BlockState blockState, @Nullable BlockAndTintGetter blockAndTintGetter, @Nullable BlockPos blockPos, int i) { return -1; } - - @Override - public int getColor(ItemStack itemStack, int i) { - return -1; - } } private static class BlockDelegate extends CachedSupplier implements BlockColor { @@ -56,18 +34,7 @@ public BlockDelegate(Supplier getter) { @Override public int getColor(BlockState blockState, @Nullable BlockAndTintGetter blockAndTintGetter, @Nullable BlockPos blockPos, int i) { - return this.get().getColor(blockState, blockAndTintGetter, blockPos, i); - } - } - - private static class ItemDelegate extends CachedSupplier implements ItemColor { - public ItemDelegate(Supplier getter) { - super(getter, Dummy.INSTANCE); - } - - @Override - public int getColor(ItemStack itemStack, int i) { - return this.get().getColor(itemStack, i); + return Objects.requireNonNull(this.get()).getColor(blockState, blockAndTintGetter, blockPos, i); } } } \ No newline at end of file diff --git a/src/main/java/snownee/kiwi/util/resource/OneTimeLoader.java b/src/main/java/snownee/kiwi/util/resource/OneTimeLoader.java index d3220a9b..09d6f3aa 100644 --- a/src/main/java/snownee/kiwi/util/resource/OneTimeLoader.java +++ b/src/main/java/snownee/kiwi/util/resource/OneTimeLoader.java @@ -3,14 +3,19 @@ import java.io.BufferedReader; import java.util.Map; import java.util.Optional; -import java.util.function.Predicate; +import java.util.Set; +import org.jetbrains.annotations.Nullable; + +import com.ezylang.evalex.Expression; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; +import com.mojang.serialization.Dynamic; import com.mojang.serialization.JavaOps; import com.mojang.serialization.JsonOps; @@ -18,45 +23,50 @@ import net.minecraft.server.packs.resources.Resource; import net.minecraft.server.packs.resources.ResourceManager; import snownee.kiwi.Kiwi; +import snownee.kiwi.util.KEval; import snownee.kiwi.util.KUtil; public class OneTimeLoader { private static final Gson GSON = new GsonBuilder().setLenient().create(); - public static Map load( - ResourceManager resourceManager, - String directory, - Codec codec) { - return load(resourceManager, directory, codec, $ -> true); - } - - public static Map load( - ResourceManager resourceManager, - String directory, - Codec codec, - Predicate listFilter) { - var fileToIdConverter = AlternativesFileToIdConverter.yamlOrJson(directory).setListFilter(listFilter); + public static Map load(ResourceManager resourceManager, String directory, Codec codec, Context context) { + var fileToIdConverter = AlternativesFileToIdConverter.yamlOrJson(directory); Map results = Maps.newHashMap(); for (Map.Entry entry : fileToIdConverter.listMatchingResources(resourceManager).entrySet()) { - DataResult result = parseFile(entry.getKey(), entry.getValue(), codec); + ResourceLocation key = entry.getKey(); + if (context.isNamespaceDisabled(key.getNamespace())) { + continue; + } + DataResult result = parseFile(key, entry.getValue(), codec, context); + if (result == null) { + continue; + } if (result.error().isPresent()) { - Kiwi.LOGGER.error("Failed to parse " + entry.getKey() + ": " + result.error().get()); + Kiwi.LOGGER.error("Failed to parse " + key + ": " + result.error().get()); continue; } - ResourceLocation id = fileToIdConverter.fileToId(entry.getKey()); + ResourceLocation id = fileToIdConverter.fileToId(key); results.put(id, result.result().orElseThrow()); } return results; } - public static T loadFile(ResourceManager resourceManager, String directory, ResourceLocation id, Codec codec) { + public static @Nullable T loadFile( + ResourceManager resourceManager, + String directory, + ResourceLocation id, + Codec codec, + @Nullable Context context) { var fileToIdConverter = AlternativesFileToIdConverter.yamlOrJson(directory); ResourceLocation file = fileToIdConverter.idToFile(id); Optional resource = resourceManager.getResource(file); if (resource.isEmpty()) { return null; } - DataResult result = parseFile(file, resource.get(), codec); + DataResult result = parseFile(file, resource.get(), codec, context); + if (result == null) { + return null; + } if (result.error().isPresent()) { Kiwi.LOGGER.error("Failed to parse " + file + ": " + result.error().get()); return null; @@ -64,20 +74,62 @@ public static T loadFile(ResourceManager resourceManager, String directory, return result.result().orElseThrow(); } - public static DataResult parseFile(ResourceLocation file, Resource resource, Codec codec) { + public static @Nullable DataResult parseFile( + ResourceLocation file, + Resource resource, + Codec codec, + @Nullable Context context) { String ext = file.getPath().substring(file.getPath().length() - 5); try (BufferedReader reader = resource.openAsReader()) { - DataResult result; + Dynamic dynamic; if (ext.equals(".json")) { - result = codec.parse(JsonOps.INSTANCE, GSON.fromJson(reader, JsonElement.class)); + JsonElement value = GSON.fromJson(reader, JsonElement.class); + dynamic = new Dynamic<>(JsonOps.INSTANCE, value); } else if (ext.equals(".yaml")) { - result = codec.parse(JavaOps.INSTANCE, KUtil.loadYaml(reader, Object.class)); + Object value = KUtil.loadYaml(reader, Object.class); + dynamic = new Dynamic<>(JavaOps.INSTANCE, value); } else { return DataResult.error(() -> "Unknown extension: " + ext); } - return result; + if (context != null) { + Optional condition = dynamic.get("condition").asString().result(); + if (condition.isPresent()) { + try { + Expression expression = context.getExpression(condition.get()); + if (expression.evaluate().getBooleanValue() != Boolean.FALSE) { + return null; + } + } catch (Exception e) { + Kiwi.LOGGER.error("Failed to parse condition in " + file + ": " + e); + } + } + } + return codec.parse(dynamic); } catch (Exception e) { return DataResult.error(() -> "Failed to load " + file + ": " + e); } } + + public static class Context { + private Map cachedExpressions; + private Set disabledNamespaces; + + public Expression getExpression(String expression) { + if (cachedExpressions == null) { + cachedExpressions = Maps.newHashMap(); + } + return cachedExpressions.computeIfAbsent(expression, $ -> new Expression($, KEval.config())); + } + + public void addDisabledNamespace(String namespace) { + if (disabledNamespaces == null) { + disabledNamespaces = Sets.newHashSet(); + } + disabledNamespaces.add(namespace); + } + + public boolean isNamespaceDisabled(String namespace) { + return disabledNamespaces != null && disabledNamespaces.contains(namespace); + } + } } \ No newline at end of file diff --git a/src/main/resources/kiwi.accesswidener b/src/main/resources/kiwi.accesswidener index bfe7d3d4..5a890aff 100644 --- a/src/main/resources/kiwi.accesswidener +++ b/src/main/resources/kiwi.accesswidener @@ -20,11 +20,10 @@ accessible field net/minecraft/world/item/CreativeModeTabs TOOLS_AND_UTILITIES L accessible field net/minecraft/data/recipes/ShapelessRecipeBuilder criteria Ljava/util/Map; accessible field net/minecraft/data/recipes/ShapelessRecipeBuilder group Ljava/lang/String; -accessible field net/minecraft/data/recipes/ShapelessRecipeBuilder ingredients Lnet/minecraft/core/NonNullList; -accessible field net/minecraft/data/recipes/ShapelessRecipeBuilder result Lnet/minecraft/world/item/Item; -accessible field net/minecraft/data/recipes/ShapelessRecipeBuilder count I +accessible field net/minecraft/data/recipes/ShapelessRecipeBuilder ingredients Ljava/util/List; +accessible field net/minecraft/data/recipes/ShapelessRecipeBuilder result Lnet/minecraft/world/item/ItemStack; accessible field net/minecraft/data/recipes/ShapelessRecipeBuilder category Lnet/minecraft/data/recipes/RecipeCategory; -accessible method net/minecraft/data/recipes/ShapelessRecipeBuilder ensureValid (Lnet/minecraft/resources/ResourceLocation;)V +accessible method net/minecraft/data/recipes/ShapelessRecipeBuilder ensureValid (Lnet/minecraft/resources/ResourceKey;)V accessible field net/minecraft/world/item/BucketItem content Lnet/minecraft/world/level/material/Fluid; @@ -32,3 +31,10 @@ accessible field net/minecraft/server/packs/repository/FolderRepositorySource fo accessible field net/minecraft/server/packs/repository/FolderRepositorySource validator Lnet/minecraft/world/level/validation/DirectoryValidator; accessible field net/minecraft/server/packs/repository/FolderRepositorySource packType Lnet/minecraft/server/packs/PackType; accessible method net/minecraft/server/packs/repository/FolderRepositorySource createDiscoveredFilePackInfo (Ljava/nio/file/Path;)Lnet/minecraft/server/packs/PackLocationInfo; + +accessible method net/minecraft/world/level/block/entity/BlockEntityType (Lnet/minecraft/world/level/block/entity/BlockEntityType$BlockEntitySupplier;Ljava/util/Set;)V + +accessible field net/minecraft/client/renderer/ItemBlockRenderTypes TYPE_BY_BLOCK Ljava/util/Map; + +accessible method net/minecraft/advancements/critereon/BlockPredicate matchesBlockEntity (Lnet/minecraft/world/level/LevelReader;Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/advancements/critereon/NbtPredicate;)Z +accessible method net/minecraft/advancements/critereon/BlockPredicate matchesComponents (Lnet/minecraft/world/level/block/entity/BlockEntity;Lnet/minecraft/advancements/critereon/DataComponentMatchers;)Z \ No newline at end of file diff --git a/src/main/resources/kiwi.mixins.json b/src/main/resources/kiwi.mixins.json index 16b09b76..275e4678 100644 --- a/src/main/resources/kiwi.mixins.json +++ b/src/main/resources/kiwi.mixins.json @@ -6,16 +6,19 @@ "compatibilityLevel": "JAVA_16", "refmap": "kiwi.refmap.json", "mixins": [ - "RecipeManagerMixin", - "ReloadableServerResourcesMixin" + "IngredientAccess" ], "client": [ "client.ClientPacketListenerMixin", "client.ClientTelemetryManagerMixin", "client.CreativeModeInventoryScreenMixin", - "client.FogRendererMixin", + "client.EntityRenderDispatcherAccess", + "client.EntityRendererMixin", + "client.LavaFogEnvironmentMixin", "client.LoadingOverlayMixin", "client.OptionInstanceMixin", + "client.PlayerRenderStateMixin", + "client.RenderLayerAccess", "client.ScreenEffectRendererMixin", "client.ScreenMixin", "client.TitleScreenMixin",