diff --git a/common/src/main/java/dev/architectury/event/events/common/ChunkEvent.java b/common/src/main/java/dev/architectury/event/events/common/ChunkEvent.java index e855038f..30115fb6 100644 --- a/common/src/main/java/dev/architectury/event/events/common/ChunkEvent.java +++ b/common/src/main/java/dev/architectury/event/events/common/ChunkEvent.java @@ -24,15 +24,16 @@ import dev.architectury.event.EventFactory; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.storage.SerializableChunkData; import org.jetbrains.annotations.Nullable; public interface ChunkEvent { /** - * @see SaveData#save(ChunkAccess, ServerLevel) + * @see SaveData#save(ChunkAccess, ServerLevel, SerializableChunkData) */ Event SAVE_DATA = EventFactory.createLoop(); /** - * @see LoadData#load(ChunkAccess, ServerLevel) + * @see LoadData#load(ChunkAccess, ServerLevel, SerializableChunkData) */ Event LOAD_DATA = EventFactory.createLoop(); @@ -44,8 +45,9 @@ public interface ChunkEvent { * * @param chunk The chunk that is saved. * @param level The level the chunk is in. + * @param data The data. */ - void save(ChunkAccess chunk, ServerLevel level); + void save(ChunkAccess chunk, ServerLevel level, SerializableChunkData data); } interface LoadData { @@ -56,7 +58,8 @@ public interface ChunkEvent { * * @param chunk The chunk that is loaded. * @param level The level the chunk is in, may be {@code null}. + * @param data The data. */ - void load(ChunkAccess chunk, @Nullable ServerLevel level); + void load(ChunkAccess chunk, @Nullable ServerLevel level, SerializableChunkData data); } } diff --git a/common/src/main/java/dev/architectury/registry/fuel/FuelRegistry.java b/common/src/main/java/dev/architectury/registry/fuel/FuelRegistry.java index 8da69a90..4e4e8d46 100644 --- a/common/src/main/java/dev/architectury/registry/fuel/FuelRegistry.java +++ b/common/src/main/java/dev/architectury/registry/fuel/FuelRegistry.java @@ -19,7 +19,12 @@ package dev.architectury.registry.fuel; +import dev.architectury.injectables.annotations.ExpectPlatform; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.entity.FuelValues; +import org.jetbrains.annotations.Nullable; public final class FuelRegistry { private FuelRegistry() { @@ -32,10 +37,10 @@ public final class FuelRegistry { * and {@code -1} to use vanilla logic * @param items the array of items to register for */ - /*@ExpectPlatform + @ExpectPlatform public static void register(int time, ItemLike... items) { throw new AssertionError(); - }*/ + } /** * Returns the burn time of an {@link ItemStack}. @@ -43,8 +48,8 @@ public final class FuelRegistry { * @param stack the stack * @return the burn time of the stack, returns {@code 0} if not a fuel */ - /*@ExpectPlatform - public static int get(ItemStack stack) { + @ExpectPlatform + public static int get(ItemStack stack, @Nullable RecipeType recipeType, FuelValues fuelValues) { throw new AssertionError(); - }*/ + } } diff --git a/common/src/main/resources/architectury.accessWidener b/common/src/main/resources/architectury.accessWidener index 3a808866..0ccb78ad 100644 --- a/common/src/main/resources/architectury.accessWidener +++ b/common/src/main/resources/architectury.accessWidener @@ -45,6 +45,7 @@ mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties em accessible field net/minecraft/world/level/block/state/BlockBehaviour$Properties dynamicShape Z mutable field net/minecraft/world/level/block/state/BlockBehaviour$Properties dynamicShape Z accessible method net/minecraft/world/level/block/state/BlockBehaviour$Properties ()V +accessible field net/minecraft/world/level/block/entity/FuelValues$Builder values Lit/unimi/dsi/fastutil/objects/Object2IntSortedMap; transitive-accessible method net/minecraft/world/entity/player/Player closeContainer ()V transitive-accessible method net/minecraft/advancements/CriteriaTriggers register (Ljava/lang/String;Lnet/minecraft/advancements/CriterionTrigger;)Lnet/minecraft/advancements/CriterionTrigger; transitive-accessible method net/minecraft/world/inventory/MenuType (Lnet/minecraft/world/inventory/MenuType$MenuSupplier;Lnet/minecraft/world/flag/FeatureFlagSet;)V @@ -237,7 +238,6 @@ transitive-accessible method net/minecraft/world/level/block/WitherWallSkullBloc transitive-accessible method net/minecraft/world/level/block/WoolCarpetBlock (Lnet/minecraft/world/item/DyeColor;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)V # RenderStateShard fields -transitive-accessible field net/minecraft/client/renderer/RenderStateShard VIEW_SCALE_Z_EPSILON F transitive-accessible field net/minecraft/client/renderer/RenderStateShard NO_TRANSPARENCY Lnet/minecraft/client/renderer/RenderStateShard$TransparencyStateShard; transitive-accessible field net/minecraft/client/renderer/RenderStateShard ADDITIVE_TRANSPARENCY Lnet/minecraft/client/renderer/RenderStateShard$TransparencyStateShard; transitive-accessible field net/minecraft/client/renderer/RenderStateShard LIGHTNING_TRANSPARENCY Lnet/minecraft/client/renderer/RenderStateShard$TransparencyStateShard; @@ -261,6 +261,7 @@ transitive-accessible field net/minecraft/client/renderer/RenderStateShard RENDE transitive-accessible field net/minecraft/client/renderer/RenderStateShard RENDERTYPE_TRANSLUCENT_SHADER Lnet/minecraft/client/renderer/RenderStateShard$ShaderStateShard; transitive-accessible field net/minecraft/client/renderer/RenderStateShard RENDERTYPE_TRANSLUCENT_MOVING_BLOCK_SHADER Lnet/minecraft/client/renderer/RenderStateShard$ShaderStateShard; transitive-accessible field net/minecraft/client/renderer/RenderStateShard RENDERTYPE_ARMOR_CUTOUT_NO_CULL_SHADER Lnet/minecraft/client/renderer/RenderStateShard$ShaderStateShard; +transitive-accessible field net/minecraft/client/renderer/RenderStateShard RENDERTYPE_ARMOR_TRANSLUCENT_SHADER Lnet/minecraft/client/renderer/RenderStateShard$ShaderStateShard; transitive-accessible field net/minecraft/client/renderer/RenderStateShard RENDERTYPE_ENTITY_SOLID_SHADER Lnet/minecraft/client/renderer/RenderStateShard$ShaderStateShard; transitive-accessible field net/minecraft/client/renderer/RenderStateShard RENDERTYPE_ENTITY_CUTOUT_SHADER Lnet/minecraft/client/renderer/RenderStateShard$ShaderStateShard; transitive-accessible field net/minecraft/client/renderer/RenderStateShard RENDERTYPE_ENTITY_CUTOUT_NO_CULL_SHADER Lnet/minecraft/client/renderer/RenderStateShard$ShaderStateShard; diff --git a/fabric/src/main/java/dev/architectury/mixin/fabric/MixinChunkMap.java b/fabric/src/main/java/dev/architectury/mixin/fabric/MixinChunkMap.java index 1a875a0e..6500f8f8 100644 --- a/fabric/src/main/java/dev/architectury/mixin/fabric/MixinChunkMap.java +++ b/fabric/src/main/java/dev/architectury/mixin/fabric/MixinChunkMap.java @@ -19,17 +19,18 @@ package dev.architectury.mixin.fabric; +import com.llamalad7.mixinextras.sugar.Local; import dev.architectury.event.events.common.ChunkEvent; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.storage.SerializableChunkData; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(ChunkMap.class) public class MixinChunkMap { @@ -39,10 +40,9 @@ public class MixinChunkMap { @Inject( method = "save", - at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap;write(Lnet/minecraft/world/level/ChunkPos;Ljava/util/function/Supplier;)Ljava/util/concurrent/CompletableFuture;", ordinal = 0), - locals = LocalCapture.CAPTURE_FAILHARD + at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkMap;write(Lnet/minecraft/world/level/ChunkPos;Ljava/util/function/Supplier;)Ljava/util/concurrent/CompletableFuture;", ordinal = 0) ) - private void save(ChunkAccess chunkAccess, CallbackInfoReturnable cir) { - ChunkEvent.SAVE_DATA.invoker().save(chunkAccess, this.level); + private void save(ChunkAccess chunkAccess, CallbackInfoReturnable cir, @Local SerializableChunkData data) { + ChunkEvent.SAVE_DATA.invoker().save(chunkAccess, this.level, data); } } diff --git a/fabric/src/main/java/dev/architectury/mixin/fabric/MixinSerializableChunkData.java b/fabric/src/main/java/dev/architectury/mixin/fabric/MixinSerializableChunkData.java index 315e2aad..f4494728 100644 --- a/fabric/src/main/java/dev/architectury/mixin/fabric/MixinSerializableChunkData.java +++ b/fabric/src/main/java/dev/architectury/mixin/fabric/MixinSerializableChunkData.java @@ -39,7 +39,6 @@ public class MixinSerializableChunkData { private void load(ServerLevel serverLevel, PoiManager poiManager, RegionStorageInfo regionStorageInfo, ChunkPos chunkPos, CallbackInfoReturnable cir, @Local ChunkAccess chunkAccess) { - // TODO: Get the CompoundTag from constructor somewhere - ChunkEvent.LOAD_DATA.invoker().load(chunkAccess, serverLevel); + ChunkEvent.LOAD_DATA.invoker().load(chunkAccess, serverLevel, (SerializableChunkData) (Object) this); } } diff --git a/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinMouseHandler.java b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinMouseHandler.java index 0fe8ee89..a5830742 100644 --- a/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinMouseHandler.java +++ b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinMouseHandler.java @@ -50,24 +50,18 @@ public class MixinMouseHandler { @Shadow private double ypos; - @Inject(method = "onScroll", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseScrolled(DDDD)Z", - ordinal = 0), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) - public void onMouseScrolled(long handle, double xOffset, double yOffset, CallbackInfo info, boolean discreteMouseScroll, double mouseWheelSensitivity, double amountX, double amountY, double x, double y) { - if (!info.isCancelled()) { - var result = ClientScreenInputEvent.MOUSE_SCROLLED_PRE.invoker().mouseScrolled(minecraft, minecraft.screen, x, y, amountX, amountY); - if (result.isPresent()) - info.cancel(); + @WrapOperation(method = "onScroll", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseScrolled(DDDD)Z", ordinal = 0)) + private boolean onGuiMouseClicked(Screen instance, double mouseX, double mouseY, double amountX, double amountY, Operation original) { + var minecraft = Minecraft.getInstance(); + var result = ClientScreenInputEvent.MOUSE_SCROLLED_PRE.invoker().mouseScrolled(minecraft, minecraft.screen, mouseX, mouseY, amountX, amountY); + if (result.isPresent()) { + return true; } - } - - @Inject(method = "onScroll", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseScrolled(DDDD)Z", - ordinal = 0, shift = At.Shift.AFTER), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) - public void onMouseScrolledPost(long handle, double xOffset, double yOffset, CallbackInfo info, boolean discreteMouseScroll, double mouseWheelSensitivity, double amountX, double amountY, double x, double y) { - if (!info.isCancelled()) { - var result = ClientScreenInputEvent.MOUSE_SCROLLED_POST.invoker().mouseScrolled(minecraft, minecraft.screen, x, y, amountX, amountY); + if (original.call(instance, mouseX, mouseY, amountX, amountY)) { + return true; } + result = ClientScreenInputEvent.MOUSE_SCROLLED_POST.invoker().mouseScrolled(minecraft, minecraft.screen, mouseX, mouseY, amountX, amountY); + return result.isPresent(); } @Inject(method = "onScroll", @@ -81,28 +75,18 @@ public class MixinMouseHandler { } } - @Inject(method = "onPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseClicked(DDI)Z", ordinal = 0), cancellable = true) - private void onGuiMouseClicked(long window, int button, int action, int mods, CallbackInfo info, - @Local(ordinal = 0) double mouseX, @Local(ordinal = 1) double mouseY, @Local(ordinal = 3) int b) { + @WrapOperation(method = "onPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseClicked(DDI)Z", ordinal = 0)) + private boolean onGuiMouseClicked(Screen instance, double mouseX, double mouseY, int b, Operation original) { var minecraft = Minecraft.getInstance(); - if (!info.isCancelled()) { - var result = ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, minecraft.screen, mouseX, mouseY, b); - if (result.isPresent()) { - info.cancel(); - } + var result = ClientScreenInputEvent.MOUSE_CLICKED_PRE.invoker().mouseClicked(minecraft, minecraft.screen, mouseX, mouseY, b); + if (result.isPresent()) { + return true; } - } - - @Inject(method = "onPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseClicked(DDI)Z", ordinal = 0, shift = At.Shift.AFTER), cancellable = true) - private void onGuiMouseClickedPost(long window, int button, int action, int mods, CallbackInfo info, - @Local(ordinal = 0) double mouseX, @Local(ordinal = 1) double mouseY, @Local(ordinal = 3) int b) { - var minecraft = Minecraft.getInstance(); - if (!info.isCancelled()) { - var result = ClientScreenInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(minecraft, minecraft.screen, mouseX, mouseY, b); - if (result.isPresent()) { - info.cancel(); - } + if (original.call(instance, mouseX, mouseY, b)) { + return true; } + result = ClientScreenInputEvent.MOUSE_CLICKED_POST.invoker().mouseClicked(minecraft, minecraft.screen, mouseX, mouseY, b); + return result.isPresent(); } @Inject(method = "onPress", at = @At(value = "INVOKE", @@ -125,28 +109,18 @@ public class MixinMouseHandler { } } - @Inject(method = "onPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseReleased(DDI)Z", ordinal = 0), cancellable = true) - private void onGuiMouseReleased(long window, int button, int action, int mods, CallbackInfo info, - @Local(ordinal = 0) double mouseX, @Local(ordinal = 1) double mouseY, @Local(ordinal = 3) int b) { + @WrapOperation(method = "onPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseReleased(DDI)Z", ordinal = 0)) + private boolean onGuiMouseReleased(Screen instance, double mouseX, double mouseY, int b, Operation original) { var minecraft = Minecraft.getInstance(); - if (!info.isCancelled()) { - var result = ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(minecraft, minecraft.screen, mouseX, mouseY, b); - if (result.isPresent()) { - info.cancel(); - } + var result = ClientScreenInputEvent.MOUSE_RELEASED_PRE.invoker().mouseReleased(minecraft, minecraft.screen, mouseX, mouseY, b); + if (result.isPresent()) { + return true; } - } - - @Inject(method = "onPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseReleased(DDI)Z", ordinal = 0, shift = At.Shift.AFTER), cancellable = true) - private void onGuiMouseReleasedPost(long window, int button, int action, int mods, CallbackInfo info, - @Local(ordinal = 0) double mouseX, @Local(ordinal = 1) double mouseY, @Local(ordinal = 3) int b) { - var minecraft = Minecraft.getInstance(); - if (!info.isCancelled()) { - var result = ClientScreenInputEvent.MOUSE_RELEASED_POST.invoker().mouseReleased(minecraft, minecraft.screen, mouseX, mouseY, b); - if (result.isPresent()) { - info.cancel(); - } + if (original.call(instance, mouseX, mouseY, b)) { + return true; } + result = ClientScreenInputEvent.MOUSE_RELEASED_POST.invoker().mouseReleased(minecraft, minecraft.screen, mouseX, mouseY, b); + return result.isPresent(); } @Inject(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseDragged(DDIDD)Z", ordinal = 0), cancellable = true) diff --git a/fabric/src/main/java/dev/architectury/registry/fuel/fabric/FuelRegistryImpl.java b/fabric/src/main/java/dev/architectury/registry/fuel/fabric/FuelRegistryImpl.java index eb0b0b19..ff720ab0 100644 --- a/fabric/src/main/java/dev/architectury/registry/fuel/fabric/FuelRegistryImpl.java +++ b/fabric/src/main/java/dev/architectury/registry/fuel/fabric/FuelRegistryImpl.java @@ -19,23 +19,51 @@ package dev.architectury.registry.fuel.fabric; +import net.fabricmc.fabric.api.registry.FuelRegistryEvents; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.entity.FuelValues; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; public class FuelRegistryImpl { + private static final List CALLBACKS = new ArrayList<>(); + private static final List EXCLUSIONS_CALLBACKS = new ArrayList<>(); + public static void register(int time, ItemLike... items) { - /*for (var item : items) { - if (time >= 0) { - FuelRegistry.INSTANCE.add(item, time); - } else { - FuelRegistry.INSTANCE.remove(item); + CALLBACKS.add((builder, context) -> { + for (var item : items) { + if (time >= 0) { + builder.add(item, time); + } } - }*/ + }); + EXCLUSIONS_CALLBACKS.add((builder, context) -> { + for (var item : items) { + if (time < 0) { + builder.values.keySet().remove(item.asItem()); + } + } + }); } - public static int get(ItemStack stack) { - /*var time = FuelRegistry.INSTANCE.get(stack.getItem()); - return time == null ? 0 : time;*/ - return 0; + public static int get(ItemStack stack, @Nullable RecipeType recipeType, FuelValues fuelValues) { + return fuelValues.burnDuration(stack); + } + + static { + FuelRegistryEvents.BUILD.register((builder, context) -> { + for (var callback : CALLBACKS) { + callback.build(builder, context); + } + }); + FuelRegistryEvents.EXCLUSIONS.register((builder, context) -> { + for (var callback : EXCLUSIONS_CALLBACKS) { + callback.buildExclusions(builder, context); + } + }); } } diff --git a/gradle.properties b/gradle.properties index 3771bde4..65f72a14 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx6G org.gradle.daemon=false -platforms=fabric +platforms=fabric,neoforge minecraft_version=1.21.2 supported_version=1.21.2 @@ -19,7 +19,7 @@ fabric_api_version=0.106.1+1.21.2 mod_menu_version=11.0.1 forge_version=51.0.0 -neoforge_version=21.0.114-beta +neoforge_version=21.2.0-beta # Set to empty if not snapshots neoforge_pr= diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 1c4223e9..ca9eb00d 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -122,7 +122,7 @@ unifiedPublishing { displayName = "[NeoForge $rootProject.supported_version] v$project.version" releaseType = "$rootProject.artifact_type" changelog = releaseChangelog() - gameVersions = ["1.21"] + gameVersions = ["1.21.2"] gameLoaders = ["neoforge"] mainPublication renameJarForPublication diff --git a/neoforge/src/main/java/dev/architectury/core/fluid/forge/imitator/ArchitecturyFlowingFluid.java b/neoforge/src/main/java/dev/architectury/core/fluid/forge/imitator/ArchitecturyFlowingFluid.java index f387c2fa..67b1502d 100644 --- a/neoforge/src/main/java/dev/architectury/core/fluid/forge/imitator/ArchitecturyFlowingFluid.java +++ b/neoforge/src/main/java/dev/architectury/core/fluid/forge/imitator/ArchitecturyFlowingFluid.java @@ -24,11 +24,11 @@ import com.google.common.base.Suppliers; import dev.architectury.core.fluid.ArchitecturyFluidAttributes; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Block; @@ -82,7 +82,7 @@ public abstract class ArchitecturyFlowingFluid extends BaseFlowingFluid { } @Override - protected boolean canConvertToSource(Level level) { + protected boolean canConvertToSource(ServerLevel level) { return attributes.canConvertToSource(); } diff --git a/neoforge/src/main/java/dev/architectury/core/fluid/forge/imitator/ArchitecturyFluidAttributesForge.java b/neoforge/src/main/java/dev/architectury/core/fluid/forge/imitator/ArchitecturyFluidAttributesForge.java index ca24d3b1..c1725e41 100644 --- a/neoforge/src/main/java/dev/architectury/core/fluid/forge/imitator/ArchitecturyFluidAttributesForge.java +++ b/neoforge/src/main/java/dev/architectury/core/fluid/forge/imitator/ArchitecturyFluidAttributesForge.java @@ -21,7 +21,10 @@ package dev.architectury.core.fluid.forge.imitator; import com.google.common.base.MoreObjects; import dev.architectury.core.fluid.ArchitecturyFluidAttributes; +import dev.architectury.hooks.client.forge.ClientExtensionsRegistryImpl; import dev.architectury.hooks.fluid.forge.FluidStackHooksForge; +import dev.architectury.platform.Platform; +import dev.architectury.utils.Env; import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.BuiltInRegistries; @@ -37,13 +40,17 @@ import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; import net.neoforged.neoforge.common.SoundAction; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import org.jetbrains.annotations.Nullable; -import java.util.function.Consumer; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Map; import static net.minecraft.sounds.SoundEvents.BUCKET_EMPTY; import static net.minecraft.sounds.SoundEvents.BUCKET_FILL; @@ -56,6 +63,9 @@ class ArchitecturyFluidAttributesForge extends FluidType { super(addArchIntoBuilder(builder, attributes)); this.attributes = attributes; this.defaultTranslationKey = Util.makeDescriptionId("fluid", BuiltInRegistries.FLUID.getKey(fluid)); + if (Platform.getEnvironment() == Env.CLIENT) { + this.registerClient(); + } } private static Properties addArchIntoBuilder(Properties builder, ArchitecturyFluidAttributes attributes) { @@ -74,9 +84,29 @@ class ArchitecturyFluidAttributesForge extends FluidType { return item == null ? super.getBucket(stack) : new ItemStack(item); } - @Override - public void initializeClient(Consumer consumer) { - consumer.accept(new IClientFluidTypeExtensions() { + @OnlyIn(Dist.CLIENT) + public void registerClient() { + ClientExtensionsRegistryImpl.register(event -> { + if (event != null) { + event.registerFluidType(initializeClient(), this); + } else { + try { + Class clazz = Class.forName("net.neoforged.neoforge.client.extensions.common.ClientExtensionsManager"); + Field field = clazz.getDeclaredField("FLUID_TYPE_EXTENSIONS"); + field.setAccessible(true); + Method method = clazz.getDeclaredMethod("register", Object.class, Map.class, Object[].class); + method.setAccessible(true); + method.invoke(null, initializeClient(), (Map) field.get(null), new Object[]{this}); + } catch (Throwable e) { + e.printStackTrace(); + } + } + }); + } + + @OnlyIn(Dist.CLIENT) + public IClientFluidTypeExtensions initializeClient() { + return new IClientFluidTypeExtensions() { @Override public int getTintColor() { return attributes.getColor(); @@ -139,7 +169,7 @@ class ArchitecturyFluidAttributesForge extends FluidType { public ResourceLocation getOverlayTexture(FluidStack stack) { return attributes.getOverlayTexture(convertSafe(stack)); } - }); + }; } @Override diff --git a/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java b/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java index ccfdbcc0..b12c30c2 100644 --- a/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java +++ b/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplClient.java @@ -26,7 +26,6 @@ import dev.architectury.event.events.client.ClientChatEvent; import dev.architectury.event.events.client.*; import dev.architectury.event.events.common.InteractionEvent; import dev.architectury.impl.ScreenAccessImpl; -import dev.architectury.impl.TooltipEventColorContextImpl; import dev.architectury.impl.TooltipEventPositionContextImpl; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; @@ -38,8 +37,8 @@ import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; -import net.neoforged.neoforge.client.event.*; import net.neoforged.neoforge.client.event.ClientTickEvent; +import net.neoforged.neoforge.client.event.*; import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; import net.neoforged.neoforge.event.level.LevelEvent; @@ -141,24 +140,24 @@ public class EventHandlerImplClient { @SubscribeEvent(priority = EventPriority.HIGH) public static void eventDrawScreenEvent(ScreenEvent.Render.Pre event) { - if (ClientGuiEvent.RENDER_PRE.invoker().render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getTimer()).isFalse()) { + if (ClientGuiEvent.RENDER_PRE.invoker().render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getDeltaTracker()).isFalse()) { event.setCanceled(true); } } @SubscribeEvent(priority = EventPriority.HIGH) public static void eventDrawScreenEvent(ScreenEvent.Render.Post event) { - ClientGuiEvent.RENDER_POST.invoker().render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getTimer()); + ClientGuiEvent.RENDER_POST.invoker().render(event.getScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getDeltaTracker()); } @SubscribeEvent(priority = EventPriority.HIGH) public static void eventContainerScreenEvent(ContainerScreenEvent.Render.Background event) { - ClientGuiEvent.RENDER_CONTAINER_BACKGROUND.invoker().render(event.getContainerScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getTimer().getRealtimeDeltaTicks()); + ClientGuiEvent.RENDER_CONTAINER_BACKGROUND.invoker().render(event.getContainerScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getDeltaTracker().getRealtimeDeltaTicks()); } @SubscribeEvent(priority = EventPriority.HIGH) public static void eventContainerScreenEvent(ContainerScreenEvent.Render.Foreground event) { - ClientGuiEvent.RENDER_CONTAINER_FOREGROUND.invoker().render(event.getContainerScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getTimer().getRealtimeDeltaTicks()); + ClientGuiEvent.RENDER_CONTAINER_FOREGROUND.invoker().render(event.getContainerScreen(), event.getGuiGraphics(), event.getMouseX(), event.getMouseY(), Minecraft.getInstance().getDeltaTracker().getRealtimeDeltaTicks()); } @SubscribeEvent(priority = EventPriority.HIGH) @@ -171,11 +170,6 @@ public class EventHandlerImplClient { InteractionEvent.CLIENT_LEFT_CLICK_AIR.invoker().click(event.getEntity(), event.getHand()); } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(RecipesUpdatedEvent event) { - ClientRecipeUpdateEvent.EVENT.invoker().update(event.getRecipeManager()); - } - private static final ThreadLocal tooltipPositionContext = ThreadLocal.withInitial(TooltipEventPositionContextImpl::new); @SubscribeEvent(priority = EventPriority.HIGH) @@ -199,26 +193,6 @@ public class EventHandlerImplClient { } } - @SubscribeEvent(priority = EventPriority.HIGH) - public static void eventRenderTooltipEvent(RenderTooltipEvent.Color event) { - GuiGraphics graphics = event.getGraphics(); - ClientTooltipEvent.additionalContexts().setItem(event.getItemStack()); - - try { - TooltipEventColorContextImpl colorContext = TooltipEventColorContextImpl.CONTEXT.get(); - colorContext.reset(); - colorContext.setBackgroundColor(event.getBackgroundStart()); - colorContext.setOutlineGradientTopColor(event.getBorderStart()); - colorContext.setOutlineGradientBottomColor(event.getBorderEnd()); - ClientTooltipEvent.RENDER_MODIFY_COLOR.invoker().renderTooltip(graphics, event.getX(), event.getY(), colorContext); - event.setBackground(colorContext.getBackgroundColor()); - event.setBorderEnd(colorContext.getOutlineGradientBottomColor()); - event.setBorderStart(colorContext.getOutlineGradientTopColor()); - } finally { - ClientTooltipEvent.additionalContexts().setItem(null); - } - } - @SubscribeEvent(priority = EventPriority.HIGH) public static void eventMouseScrollEvent(ScreenEvent.MouseScrolled.Pre event) { if (ClientScreenInputEvent.MOUSE_SCROLLED_PRE.invoker().mouseScrolled(Minecraft.getInstance(), event.getScreen(), event.getMouseX(), event.getMouseY(), event.getScrollDeltaX(), event.getScrollDeltaY()).isFalse()) { @@ -344,10 +318,5 @@ public class EventHandlerImplClient { public static void event(FMLClientSetupEvent event) { ClientLifecycleEvent.CLIENT_SETUP.invoker().stateChanged(Minecraft.getInstance()); } - - @SubscribeEvent(priority = EventPriority.HIGH) - public static void event(RegisterShadersEvent event) { - ClientReloadShadersEvent.EVENT.invoker().reload(event.getResourceProvider(), event::registerShader); - } } } diff --git a/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java b/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java index 183deb55..125a5385 100644 --- a/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java +++ b/neoforge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java @@ -19,7 +19,6 @@ package dev.architectury.event.forge; -import dev.architectury.event.CompoundEventResult; import dev.architectury.event.EventResult; import dev.architectury.event.events.common.PlayerEvent; import dev.architectury.event.events.common.*; @@ -28,7 +27,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.item.ItemStack; +import net.minecraft.world.InteractionResult; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.neoforged.bus.api.EventPriority; @@ -241,7 +240,7 @@ public class EventHandlerImplCommon { @SubscribeEvent(priority = EventPriority.HIGH) public static void event(FarmlandTrampleEvent event) { - if (event.getLevel() instanceof Level && InteractionEvent.FARMLAND_TRAMPLE.invoker().trample((Level) event.getLevel(), event.getPos(), event.getState(), event.getFallDistance(), event.getEntity()).value() != null) { + if (event.getLevel() instanceof Level && InteractionEvent.FARMLAND_TRAMPLE.invoker().trample((Level) event.getLevel(), event.getPos(), event.getState(), event.getFallDistance(), event.getEntity()) != InteractionResult.PASS) { event.setCanceled(true); } } @@ -312,19 +311,19 @@ public class EventHandlerImplCommon { @SubscribeEvent(priority = EventPriority.HIGH) public static void eventPlayerInteractEvent(PlayerInteractEvent.RightClickItem event) { - CompoundEventResult result = InteractionEvent.RIGHT_CLICK_ITEM.invoker().click(event.getEntity(), event.getHand()); - if (result.isPresent()) { + InteractionResult result = InteractionEvent.RIGHT_CLICK_ITEM.invoker().click(event.getEntity(), event.getHand()); + if (result != InteractionResult.PASS) { event.setCanceled(true); - event.setCancellationResult(result.result().asMinecraft()); + event.setCancellationResult(result); } } @SubscribeEvent(priority = EventPriority.HIGH) public static void eventPlayerInteractEvent(PlayerInteractEvent.RightClickBlock event) { - EventResult result = InteractionEvent.RIGHT_CLICK_BLOCK.invoker().click(event.getEntity(), event.getHand(), event.getPos(), event.getFace()); - if (result.isPresent()) { + InteractionResult result = InteractionEvent.RIGHT_CLICK_BLOCK.invoker().click(event.getEntity(), event.getHand(), event.getPos(), event.getFace()); + if (result != InteractionResult.PASS) { event.setCanceled(true); - event.setCancellationResult(result.asMinecraft()); + event.setCancellationResult(result); event.setUseBlock(TriState.FALSE); event.setUseItem(TriState.FALSE); } @@ -342,11 +341,11 @@ public class EventHandlerImplCommon { @SubscribeEvent(priority = EventPriority.HIGH) public static void eventPlayerInteractEvent(PlayerInteractEvent.LeftClickBlock event) { if (event.getAction() != PlayerInteractEvent.LeftClickBlock.Action.START) return; - EventResult result = InteractionEvent.LEFT_CLICK_BLOCK.invoker().click(event.getEntity(), event.getHand(), event.getPos(), event.getFace()); - if (result.isPresent()) { + InteractionResult result = InteractionEvent.LEFT_CLICK_BLOCK.invoker().click(event.getEntity(), event.getHand(), event.getPos(), event.getFace()); + if (result != InteractionResult.PASS) { event.setCanceled(true); - event.setUseBlock(result.value() ? TriState.TRUE : TriState.FALSE); - event.setUseItem(result.value() ? TriState.TRUE : TriState.FALSE); + event.setUseBlock(result.consumesAction() ? TriState.TRUE : TriState.FALSE); + event.setUseItem(result.consumesAction() ? TriState.TRUE : TriState.FALSE); } } diff --git a/neoforge/src/main/java/dev/architectury/hooks/client/forge/ClientExtensionsRegistryImpl.java b/neoforge/src/main/java/dev/architectury/hooks/client/forge/ClientExtensionsRegistryImpl.java new file mode 100644 index 00000000..7761ad1e --- /dev/null +++ b/neoforge/src/main/java/dev/architectury/hooks/client/forge/ClientExtensionsRegistryImpl.java @@ -0,0 +1,53 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.hooks.client.forge; + +import dev.architectury.utils.ArchitecturyConstants; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.extensions.common.RegisterClientExtensionsEvent; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +@EventBusSubscriber(modid = ArchitecturyConstants.MOD_ID, bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class ClientExtensionsRegistryImpl { + private static final List> CALLBACKS = new ArrayList<>(); + private static boolean called = false; + + public static void register(Consumer<@Nullable RegisterClientExtensionsEvent> callback) { + if (ClientExtensionsRegistryImpl.called) { + callback.accept(null); + } else { + CALLBACKS.add(callback); + } + } + + @SubscribeEvent + public static void onEvent(RegisterClientExtensionsEvent event) { + ClientExtensionsRegistryImpl.called = true; + for (Consumer<@Nullable RegisterClientExtensionsEvent> callback : CALLBACKS) { + callback.accept(event); + } + } +} diff --git a/neoforge/src/main/java/dev/architectury/hooks/item/food/forge/FoodPropertiesHooksImpl.java b/neoforge/src/main/java/dev/architectury/hooks/item/food/forge/FoodPropertiesHooksImpl.java deleted file mode 100644 index d10d5add..00000000 --- a/neoforge/src/main/java/dev/architectury/hooks/item/food/forge/FoodPropertiesHooksImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of architectury. - * Copyright (C) 2020, 2021, 2022 architectury - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -package dev.architectury.hooks.item.food.forge; - -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.food.FoodProperties; - -import java.util.function.Supplier; - -public class FoodPropertiesHooksImpl { - @SuppressWarnings("unchecked") - public static void effect(FoodProperties.Builder builder, - Supplier effectSupplier, float chance) { - builder.effect((Supplier) effectSupplier, chance); - } -} \ No newline at end of file diff --git a/neoforge/src/main/java/dev/architectury/hooks/item/forge/ItemStackHooksImpl.java b/neoforge/src/main/java/dev/architectury/hooks/item/forge/ItemStackHooksImpl.java index e6542bff..6e4c53de 100644 --- a/neoforge/src/main/java/dev/architectury/hooks/item/forge/ItemStackHooksImpl.java +++ b/neoforge/src/main/java/dev/architectury/hooks/item/forge/ItemStackHooksImpl.java @@ -23,10 +23,10 @@ import net.minecraft.world.item.ItemStack; public class ItemStackHooksImpl { public static boolean hasCraftingRemainingItem(ItemStack stack) { - return stack.hasCraftingRemainingItem(); + return !getCraftingRemainingItem(stack).isEmpty(); } public static ItemStack getCraftingRemainingItem(ItemStack stack) { - return stack.getCraftingRemainingItem(); + return stack.getCraftingRemainder(); } } diff --git a/neoforge/src/main/java/dev/architectury/mixin/forge/MixinClientLevel.java b/neoforge/src/main/java/dev/architectury/mixin/forge/MixinClientLevel.java index d764ab9e..a1d937a8 100644 --- a/neoforge/src/main/java/dev/architectury/mixin/forge/MixinClientLevel.java +++ b/neoforge/src/main/java/dev/architectury/mixin/forge/MixinClientLevel.java @@ -24,6 +24,7 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.Holder; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceKey; +import net.minecraft.util.profiling.Profiler; import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.level.Level; import net.minecraft.world.level.dimension.DimensionType; @@ -33,17 +34,15 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.function.Supplier; - @Mixin(ClientLevel.class) public abstract class MixinClientLevel extends Level { - protected MixinClientLevel(WritableLevelData arg, ResourceKey arg2, RegistryAccess arg3, Holder arg4, Supplier supplier, boolean bl, boolean bl2, long l, int i) { - super(arg, arg2, arg3, arg4, supplier, bl, bl2, l, i); + protected MixinClientLevel(WritableLevelData arg, ResourceKey arg2, RegistryAccess arg3, Holder arg4, boolean bl, boolean bl2, long l, int i) { + super(arg, arg2, arg3, arg4, bl, bl2, l, i); } @Inject(method = "tickEntities", at = @At("HEAD")) private void tickEntities(CallbackInfo ci) { - ProfilerFiller profiler = getProfiler(); + ProfilerFiller profiler = Profiler.get(); profiler.push("architecturyClientLevelPreTick"); ClientTickEvent.CLIENT_LEVEL_PRE.invoker().tick((ClientLevel) (Object) this); profiler.pop(); @@ -51,7 +50,7 @@ public abstract class MixinClientLevel extends Level { @Inject(method = "tickEntities", at = @At("RETURN")) private void tickEntitiesPost(CallbackInfo ci) { - ProfilerFiller profiler = getProfiler(); + ProfilerFiller profiler = Profiler.get(); profiler.push("architecturyClientLevelPostTick"); ClientTickEvent.CLIENT_LEVEL_POST.invoker().tick((ClientLevel) (Object) this); profiler.pop(); diff --git a/neoforge/src/main/java/dev/architectury/mixin/forge/MixinFallingBlockEntity.java b/neoforge/src/main/java/dev/architectury/mixin/forge/MixinFallingBlockEntity.java index 99610e6f..8ba18581 100644 --- a/neoforge/src/main/java/dev/architectury/mixin/forge/MixinFallingBlockEntity.java +++ b/neoforge/src/main/java/dev/architectury/mixin/forge/MixinFallingBlockEntity.java @@ -19,20 +19,19 @@ package dev.architectury.mixin.forge; +import com.llamalad7.mixinextras.sugar.Local; import dev.architectury.event.events.common.BlockEvent; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(FallingBlockEntity.class) public abstract class MixinFallingBlockEntity extends Entity { @@ -44,9 +43,8 @@ public abstract class MixinFallingBlockEntity extends Entity { private BlockState blockState; @Inject(method = "tick", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/Fallable;onLand(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/entity/item/FallingBlockEntity;)V"), - locals = LocalCapture.CAPTURE_FAILHARD) - public void handleLand(CallbackInfo ci, Block block, BlockPos blockPos2, boolean bl, boolean bl2, double d, BlockState blockState) { - BlockEvent.FALLING_LAND.invoker().onLand(this.level(), blockPos2, this.blockState, blockState, (FallingBlockEntity) (Object) this); + target = "Lnet/minecraft/world/level/block/Fallable;onLand(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/entity/item/FallingBlockEntity;)V")) + public void handleLand(CallbackInfo ci, @Local BlockPos blockPos, @Local BlockState blockState) { + BlockEvent.FALLING_LAND.invoker().onLand(this.level(), blockPos, this.blockState, blockState, (FallingBlockEntity) (Object) this); } } diff --git a/neoforge/src/main/java/dev/architectury/mixin/forge/client/MixinClientPacketListener.java b/neoforge/src/main/java/dev/architectury/mixin/forge/client/MixinClientPacketListener.java new file mode 100644 index 00000000..0606db8e --- /dev/null +++ b/neoforge/src/main/java/dev/architectury/mixin/forge/client/MixinClientPacketListener.java @@ -0,0 +1,70 @@ +/* + * This file is part of architectury. + * Copyright (C) 2020, 2021, 2022 architectury + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package dev.architectury.mixin.forge.client; + +import dev.architectury.event.events.client.ClientRecipeUpdateEvent; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.multiplayer.CommonListenerCookie; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.Connection; +import net.minecraft.network.protocol.game.ClientboundRecipeBookAddPacket; +import net.minecraft.network.protocol.game.ClientboundRecipeBookRemovePacket; +import net.minecraft.network.protocol.game.ClientboundUpdateRecipesPacket; +import net.minecraft.world.item.crafting.RecipeAccess; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPacketListener.class) +public abstract class MixinClientPacketListener extends ClientCommonPacketListenerImpl { + @Shadow + private ClientLevel level; + + @Shadow + public abstract RecipeAccess recipes(); + + @Unique + private LocalPlayer tmpPlayer; + + protected MixinClientPacketListener(Minecraft minecraft, Connection connection, CommonListenerCookie commonListenerCookie) { + super(minecraft, connection, commonListenerCookie); + } + + @Inject(method = "handleUpdateRecipes", at = @At("RETURN")) + private void handleUpdateRecipes(ClientboundUpdateRecipesPacket clientboundUpdateRecipesPacket, CallbackInfo ci) { + ClientRecipeUpdateEvent.EVENT.invoker().update(recipes()); + } + + @Inject(method = "handleRecipeBookAdd", at = @At("RETURN")) + private void handleRecipeBookAdd(ClientboundRecipeBookAddPacket packet, CallbackInfo ci) { + ClientRecipeUpdateEvent.ADD.invoker().add(recipes(), packet.entries()); + } + + @Inject(method = "handleRecipeBookRemove", at = @At("RETURN")) + private void handleRecipeBookRemove(ClientboundRecipeBookRemovePacket packet, CallbackInfo ci) { + ClientRecipeUpdateEvent.REMOVE.invoker().remove(recipes(), packet.recipes()); + } +} diff --git a/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/MixinBucketItem.java b/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/MixinBucketItem.java index b9231ea4..f7ef695f 100644 --- a/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/MixinBucketItem.java +++ b/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/MixinBucketItem.java @@ -21,7 +21,7 @@ package dev.architectury.mixin.forge.neoforge; import dev.architectury.event.events.common.PlayerEvent; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BucketItem; import net.minecraft.world.item.ItemStack; @@ -46,10 +46,10 @@ public class MixinBucketItem { locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true ) - public void fillBucket(Level level, Player player, InteractionHand hand, CallbackInfoReturnable> cir, ItemStack stack, BlockHitResult target) { + public void fillBucket(Level level, Player player, InteractionHand hand, CallbackInfoReturnable cir, ItemStack stack, BlockHitResult target) { var result = PlayerEvent.FILL_BUCKET.invoker().fill(player, level, stack, target); - if (result.interruptsFurtherEvaluation() && result.value() != null) { - cir.setReturnValue(result.asMinecraft()); + if (result != InteractionResult.PASS) { + cir.setReturnValue(result); cir.cancel(); } } diff --git a/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/MixinChunkSerializer.java b/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/MixinChunkMap.java similarity index 52% rename from neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/MixinChunkSerializer.java rename to neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/MixinChunkMap.java index 7fca8eef..95e7d362 100644 --- a/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/MixinChunkSerializer.java +++ b/neoforge/src/main/java/dev/architectury/mixin/forge/neoforge/MixinChunkMap.java @@ -20,46 +20,31 @@ package dev.architectury.mixin.forge.neoforge; import dev.architectury.event.forge.EventHandlerImplCommon; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.ai.village.poi.PoiManager; -import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.chunk.ProtoChunk; -import net.minecraft.world.level.chunk.storage.ChunkSerializer; -import net.minecraft.world.level.chunk.storage.RegionStorageInfo; import net.neoforged.bus.api.Event; import net.neoforged.neoforge.event.level.ChunkDataEvent; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.lang.ref.WeakReference; - -@Mixin(ChunkSerializer.class) -public class MixinChunkSerializer { - @Unique - private static ThreadLocal> level = new ThreadLocal<>(); +@Mixin(ChunkMap.class) +public class MixinChunkMap { + @Shadow + @Final + ServerLevel level; - @Inject(method = "read", at = @At("HEAD")) - private static void read(ServerLevel worldIn, PoiManager arg2, RegionStorageInfo arg3, ChunkPos arg4, CompoundTag arg5, CallbackInfoReturnable cir) { - level.set(new WeakReference<>(worldIn)); - } - - @ModifyArg(method = "read", at = @At(value = "INVOKE", - ordinal = 1, + @ModifyArg(method = {"method_43375", "lambda$scheduleChunkLoad$17"}, at = @At(value = "INVOKE", + ordinal = 0, target = "Lnet/neoforged/bus/api/IEventBus;post(Lnet/neoforged/bus/api/Event;)Lnet/neoforged/bus/api/Event;"), - index = 0) - private static Event modifyProtoChunkLevel(Event event) { - // We should get this PRed to Forge - WeakReference levelRef = level.get(); - if (levelRef != null && event instanceof ChunkDataEvent.Load) { + index = 0, remap = false) + private Event modifyProtoChunkLevel(Event event) { + if (event instanceof ChunkDataEvent.Load) { ChunkDataEvent.Load load = (ChunkDataEvent.Load) event; - ((EventHandlerImplCommon.LevelEventAttachment) load).architectury$attachLevel(levelRef.get()); + ((EventHandlerImplCommon.LevelEventAttachment) load).architectury$attachLevel(this.level); } - level.remove(); return event; } } diff --git a/neoforge/src/main/java/dev/architectury/plugin/forge/ArchitecturyMixinPlugin.java b/neoforge/src/main/java/dev/architectury/plugin/forge/ArchitecturyMixinPlugin.java index d26e3a2f..0773a95e 100644 --- a/neoforge/src/main/java/dev/architectury/plugin/forge/ArchitecturyMixinPlugin.java +++ b/neoforge/src/main/java/dev/architectury/plugin/forge/ArchitecturyMixinPlugin.java @@ -49,7 +49,7 @@ public class ArchitecturyMixinPlugin implements IMixinConfigPlugin { @Override public List getMixins() { - return List.of("neoforge.MixinChunkSerializer"); + return List.of(); } @Override diff --git a/neoforge/src/main/java/dev/architectury/registry/forge/CreativeTabRegistryImpl.java b/neoforge/src/main/java/dev/architectury/registry/forge/CreativeTabRegistryImpl.java index 7e84b80a..26b3815e 100644 --- a/neoforge/src/main/java/dev/architectury/registry/forge/CreativeTabRegistryImpl.java +++ b/neoforge/src/main/java/dev/architectury/registry/forge/CreativeTabRegistryImpl.java @@ -151,7 +151,7 @@ public class CreativeTabRegistryImpl { private void resolve() { if (this.tab == null) { - this.tab = BuiltInRegistries.CREATIVE_MODE_TAB.get(name); + this.tab = BuiltInRegistries.CREATIVE_MODE_TAB.getValue(name); } } }; diff --git a/neoforge/src/main/java/dev/architectury/registry/fuel/forge/FuelRegistryImpl.java b/neoforge/src/main/java/dev/architectury/registry/fuel/forge/FuelRegistryImpl.java index da905c72..4d456430 100644 --- a/neoforge/src/main/java/dev/architectury/registry/fuel/forge/FuelRegistryImpl.java +++ b/neoforge/src/main/java/dev/architectury/registry/fuel/forge/FuelRegistryImpl.java @@ -22,10 +22,13 @@ package dev.architectury.registry.fuel.forge; import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.entity.FuelValues; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.furnace.FurnaceFuelBurnTimeEvent; +import org.jetbrains.annotations.Nullable; public class FuelRegistryImpl { private static final Object2IntMap ITEMS = new Object2IntLinkedOpenHashMap<>(); @@ -40,8 +43,8 @@ public class FuelRegistryImpl { } } - public static int get(ItemStack stack) { - return stack.getBurnTime(null); + public static int get(ItemStack stack, @Nullable RecipeType recipeType, FuelValues fuelValues) { + return stack.getBurnTime(recipeType, fuelValues); } @SubscribeEvent diff --git a/neoforge/src/main/java/dev/architectury/registry/level/biome/forge/BiomeModificationsImpl.java b/neoforge/src/main/java/dev/architectury/registry/level/biome/forge/BiomeModificationsImpl.java index 79ba63e9..1b2a8661 100644 --- a/neoforge/src/main/java/dev/architectury/registry/level/biome/forge/BiomeModificationsImpl.java +++ b/neoforge/src/main/java/dev/architectury/registry/level/biome/forge/BiomeModificationsImpl.java @@ -142,9 +142,9 @@ public class BiomeModificationsImpl { public boolean hasTag(TagKey tag) { MinecraftServer server = GameInstance.getServer(); if (server != null) { - Optional> registry = server.registryAccess().registry(Registries.BIOME); + Optional> registry = server.registryAccess().lookup(Registries.BIOME); if (registry.isPresent()) { - Optional> holder = registry.get().getHolder(biomeResourceKey.get()); + Optional> holder = registry.get().get(biomeResourceKey.get()); if (holder.isPresent()) { return holder.get().is(tag); } @@ -208,8 +208,8 @@ public class BiomeModificationsImpl { } @Override - public Iterable>> getCarvers(GenerationStep.Carving carving) { - return generation.getCarvers(carving); + public Iterable>> getCarvers() { + return generation.getCarvers(); } @Override @@ -489,9 +489,9 @@ public class BiomeModificationsImpl { public Mutable addFeature(GenerationStep.Decoration decoration, ResourceKey feature) { MinecraftServer server = GameInstance.getServer(); if (server != null) { - Optional> registry = server.registryAccess().registry(Registries.PLACED_FEATURE); + Optional> registry = server.registryAccess().lookup(Registries.PLACED_FEATURE); if (registry.isPresent()) { - Optional> holder = registry.get().getHolder(feature); + Optional> holder = registry.get().get(feature); if (holder.isPresent()) { return addFeature(decoration, holder.get()); } else { @@ -503,20 +503,20 @@ public class BiomeModificationsImpl { } @Override - public Mutable addCarver(GenerationStep.Carving carving, Holder> feature) { - generation.addCarver(carving, feature); + public Mutable addCarver(Holder> feature) { + generation.addCarver(feature); return this; } @Override - public Mutable addCarver(GenerationStep.Carving carving, ResourceKey> feature) { + public Mutable addCarver(ResourceKey> feature) { MinecraftServer server = GameInstance.getServer(); if (server != null) { - Optional>> registry = server.registryAccess().registry(Registries.CONFIGURED_CARVER); + Optional>> registry = server.registryAccess().lookup(Registries.CONFIGURED_CARVER); if (registry.isPresent()) { - Optional>> holder = registry.get().getHolder(feature); + Optional>> holder = registry.get().get(feature); if (holder.isPresent()) { - return addCarver(carving, holder.get()); + return addCarver(holder.get()); } else { throw new IllegalArgumentException("Unknown carver: " + feature); } @@ -532,8 +532,8 @@ public class BiomeModificationsImpl { } @Override - public Mutable removeCarver(GenerationStep.Carving carving, ResourceKey> feature) { - generation.getCarvers(carving).removeIf(supplier -> supplier.is(feature)); + public Mutable removeCarver(ResourceKey> feature) { + generation.getCarvers().removeIf(supplier -> supplier.is(feature)); return this; } } diff --git a/neoforge/src/main/java/dev/architectury/registry/registries/forge/RegistrarManagerImpl.java b/neoforge/src/main/java/dev/architectury/registry/registries/forge/RegistrarManagerImpl.java index 089ba8d0..872d156d 100644 --- a/neoforge/src/main/java/dev/architectury/registry/registries/forge/RegistrarManagerImpl.java +++ b/neoforge/src/main/java/dev/architectury/registry/registries/forge/RegistrarManagerImpl.java @@ -114,7 +114,7 @@ public class RegistrarManagerImpl { @Override public Registrar get(ResourceKey> registryKey) { - Registry registry = (Registry) BuiltInRegistries.REGISTRY.get(registryKey.location()); + Registry registry = (Registry) BuiltInRegistries.REGISTRY.getValue(registryKey.location()); if (registry != null) { return get(registry); } @@ -363,7 +363,7 @@ public class RegistrarManagerImpl { @Override @Nullable public T get(ResourceLocation id) { - return delegate.get(id); + return delegate.getValue(id); } @Override @@ -399,7 +399,7 @@ public class RegistrarManagerImpl { @Override @Nullable public Holder getHolder(ResourceKey key) { - return delegate.getHolder(key).orElse(null); + return delegate.get(key).orElse(null); } @Override diff --git a/neoforge/src/main/resources/architectury.mixins.json b/neoforge/src/main/resources/architectury.mixins.json index bbff1de2..14add18e 100644 --- a/neoforge/src/main/resources/architectury.mixins.json +++ b/neoforge/src/main/resources/architectury.mixins.json @@ -5,6 +5,7 @@ "compatibilityLevel": "JAVA_16", "minVersion": "0.8", "client": [ + "client.MixinClientPacketListener", "client.MixinCommandSourceStack", "MixinClientLevel", "MixinMinecraft" @@ -13,7 +14,7 @@ "neoforge.MixinBucketItem", "neoforge.BucketItemAccessor", "neoforge.LiquidBlockAccessor", - "neoforge.MixinChunkSerializer", + "neoforge.MixinChunkMap", "MixinFallingBlockEntity", "MixinInventory", "MixinItemExtension", diff --git a/settings.gradle b/settings.gradle index 8c6bf287..2d3f37cb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -15,10 +15,10 @@ include("common") include("fabric") //include("forge") //include("minecraftforge") -//include("neoforge") +include("neoforge") include("testmod-common") include("testmod-fabric") //include("testmod-forge") -//include("testmod-neoforge") +include("testmod-neoforge") rootProject.name = "architectury" diff --git a/testmod-common/src/main/java/dev/architectury/test/events/DebugEvents.java b/testmod-common/src/main/java/dev/architectury/test/events/DebugEvents.java index 7d93fa78..e62114b1 100644 --- a/testmod-common/src/main/java/dev/architectury/test/events/DebugEvents.java +++ b/testmod-common/src/main/java/dev/architectury/test/events/DebugEvents.java @@ -229,10 +229,10 @@ public class DebugEvents { LightningEvent.STRIKE.register((bolt, level, pos, toStrike) -> { TestMod.SINK.accept(bolt.getScoreboardName() + " struck at " + toShortString(pos) + logSide(level)); }); - ChunkEvent.LOAD_DATA.register((chunk, level) -> { + ChunkEvent.LOAD_DATA.register((chunk, level, data) -> { // TestMod.SINK.accept("Chunk loaded at x=" + chunk.getPos().x + ", z=" + chunk.getPos().z + " in dimension '" + level.dimension().location() + "'"); }); - ChunkEvent.SAVE_DATA.register((chunk, level) -> { + ChunkEvent.SAVE_DATA.register((chunk, level, data) -> { // TestMod.SINK.accept("Chunk saved at x=" + chunk.getPos().x + ", z=" + chunk.getPos().z + " in dimension '" + level.dimension().location() + "'"); }); }