diff --git a/common/src/main/java/dev/architectury/event/events/client/ClientLifecycleEvent.java b/common/src/main/java/dev/architectury/event/events/client/ClientLifecycleEvent.java index 92971e73..346d6ce5 100644 --- a/common/src/main/java/dev/architectury/event/events/client/ClientLifecycleEvent.java +++ b/common/src/main/java/dev/architectury/event/events/client/ClientLifecycleEvent.java @@ -30,14 +30,14 @@ import net.minecraft.client.multiplayer.ClientLevel; @Environment(EnvType.CLIENT) public interface ClientLifecycleEvent { /** - * Invoked when client has been initialised, not available in forge. + * Invoked when client has been initialised. + * Equivalent to Fabric's {@code ClientLifecycleEvents.CLIENT_STARTING}. */ - @Deprecated Event CLIENT_STARTED = EventFactory.createLoop(); /** - * Invoked when client is stopping, not available in forge. + * Invoked when client is stopping. + * Equivalent to Fabric's {@code ClientLifecycleEvents.CLIENT_STOPPING}. */ - @Deprecated Event CLIENT_STOPPING = EventFactory.createLoop(); /** * Invoked after a level is loaded only on the client-side. diff --git a/common/src/main/java/dev/architectury/hooks/level/biome/BiomeHooks.java b/common/src/main/java/dev/architectury/hooks/level/biome/BiomeHooks.java index 9c7f612a..2c792f58 100644 --- a/common/src/main/java/dev/architectury/hooks/level/biome/BiomeHooks.java +++ b/common/src/main/java/dev/architectury/hooks/level/biome/BiomeHooks.java @@ -362,6 +362,11 @@ public final class BiomeHooks { return settings.getCarvers(carving); } + @Override + public List> getFeatures(GenerationStep.Decoration decoration) { + return settings.features().get(decoration.ordinal()); + } + @Override public List>> getFeatures() { return settings.features(); diff --git a/common/src/main/java/dev/architectury/hooks/level/biome/GenerationProperties.java b/common/src/main/java/dev/architectury/hooks/level/biome/GenerationProperties.java index 73625b74..98eb7155 100644 --- a/common/src/main/java/dev/architectury/hooks/level/biome/GenerationProperties.java +++ b/common/src/main/java/dev/architectury/hooks/level/biome/GenerationProperties.java @@ -30,6 +30,8 @@ import java.util.function.Supplier; public interface GenerationProperties { List>> getCarvers(GenerationStep.Carving carving); + List> getFeatures(GenerationStep.Decoration decoration); + List>> getFeatures(); interface Mutable extends GenerationProperties { diff --git a/common/src/main/java/dev/architectury/registry/level/biome/BiomeModifications.java b/common/src/main/java/dev/architectury/registry/level/biome/BiomeModifications.java index 661d2267..4f0c2fcf 100644 --- a/common/src/main/java/dev/architectury/registry/level/biome/BiomeModifications.java +++ b/common/src/main/java/dev/architectury/registry/level/biome/BiomeModifications.java @@ -27,6 +27,27 @@ import net.minecraft.resources.ResourceLocation; import java.util.function.BiConsumer; import java.util.function.Predicate; +/** + * This class provides a cross-platform API to modify Biome features and properties. + * + *

Changes to the biomes are hereby done in four distinct "phases", akin to Fabric API's + * {@link net.fabricmc.fabric.api.biome.v1.ModificationPhase} enum. + * + *

The order in which these phases get processed is as follows, + * with the corresponding Forge EventPriority shown in brackets: + * + *

    + *
  1. {@linkplain #addProperties(Predicate, BiConsumer) Adding} new features to biomes. [HIGH]
  2. + *
  3. {@linkplain #removeProperties(Predicate, BiConsumer) Removing} existing features from biomes. [NORMAL]
  4. + *
  5. {@linkplain #replaceProperties(Predicate, BiConsumer) Replacing} existing features with new ones. [LOW]
  6. + *
  7. Generic {@linkplain #postProcessProperties(Predicate, BiConsumer) Post-Processing} of already modified biome features. [LOWEST]
  8. + *
+ * + * Keep in mind that it isn't strictly required that you use these phases accordingly + * (i.e., you may also add features during Post-Processing, for example); they mostly serve to + * add a predictable order to biome modifications. + */ +@SuppressWarnings("JavadocReference") public final class BiomeModifications { public static void addProperties(BiConsumer modifier) { BiomeModifications.addProperties(Predicates.alwaysTrue(), modifier); diff --git a/fabric/src/main/java/dev/architectury/hooks/tags/fabric/TagHooksImpl.java b/fabric/src/main/java/dev/architectury/hooks/tags/fabric/TagHooksImpl.java index f5bbaced..f190d388 100644 --- a/fabric/src/main/java/dev/architectury/hooks/tags/fabric/TagHooksImpl.java +++ b/fabric/src/main/java/dev/architectury/hooks/tags/fabric/TagHooksImpl.java @@ -19,7 +19,7 @@ package dev.architectury.hooks.tags.fabric; -import net.fabricmc.fabric.api.tag.TagRegistry; +import net.fabricmc.fabric.api.tag.TagFactory; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.Tag; import net.minecraft.tags.TagCollection; @@ -28,6 +28,6 @@ import java.util.function.Supplier; public class TagHooksImpl { public static Tag.Named optional(ResourceLocation id, Supplier> collection) { - return TagRegistry.create(id, collection); + return TagFactory.of(collection).create(id); } } diff --git a/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer013.java b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer013.java new file mode 100644 index 00000000..0499aa56 --- /dev/null +++ b/fabric/src/main/java/dev/architectury/mixin/fabric/client/MixinGameRenderer013.java @@ -0,0 +1,73 @@ +/* + * 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.fabric.client; + +import com.mojang.blaze3d.platform.Window; +import com.mojang.blaze3d.shaders.Program; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.datafixers.util.Pair; +import com.mojang.math.Matrix4f; +import dev.architectury.event.events.client.ClientGuiEvent; +import dev.architectury.event.events.client.ClientReloadShadersEvent; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.ShaderInstance; +import net.minecraft.server.packs.resources.ResourceManager; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.List; +import java.util.function.Consumer; + +@Mixin(value = GameRenderer.class, priority = 1100) +public abstract class MixinGameRenderer013 { + @Shadow + @Final + private Minecraft minecraft; + + @Inject(method = "render(FJZ)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V", + ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true) + public void renderScreenPre(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, Window window, Matrix4f matrix, PoseStack matrices) { + if (ClientGuiEvent.RENDER_PRE.invoker().render(minecraft.screen, matrices, mouseX, mouseY, minecraft.getDeltaFrameTime()).isFalse()) { + ci.cancel(); + } + } + + @Inject(method = "render(FJZ)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;render(Lcom/mojang/blaze3d/vertex/PoseStack;IIF)V", + shift = At.Shift.AFTER, ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION) + public void renderScreenPost(float tickDelta, long startTime, boolean tick, CallbackInfo ci, int mouseX, int mouseY, Window window, Matrix4f matrix, PoseStack matrices) { + ClientGuiEvent.RENDER_POST.invoker().render(minecraft.screen, matrices, mouseX, mouseY, minecraft.getDeltaFrameTime()); + } + + @Inject(method = "reloadShaders", + at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 0), locals = LocalCapture.CAPTURE_FAILEXCEPTION) + public void reloadShaders(ResourceManager resourceManager, CallbackInfo ci, List programs, List>> shaders) { + ClientReloadShadersEvent.EVENT.invoker().reload(resourceManager, (shader, callback) -> { + shaders.add(Pair.of(shader, callback)); + }); + } +} \ No newline at end of file diff --git a/fabric/src/main/java/dev/architectury/networking/fabric/NetworkManagerImpl.java b/fabric/src/main/java/dev/architectury/networking/fabric/NetworkManagerImpl.java index 35921b59..b0684e34 100644 --- a/fabric/src/main/java/dev/architectury/networking/fabric/NetworkManagerImpl.java +++ b/fabric/src/main/java/dev/architectury/networking/fabric/NetworkManagerImpl.java @@ -26,13 +26,16 @@ import dev.architectury.networking.transformers.PacketTransformer; import dev.architectury.utils.Env; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; -import net.fabricmc.fabric.api.network.PacketContext; -import net.fabricmc.fabric.api.network.ServerSidePacketRegistry; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.networking.v1.PacketSender; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.Packet; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.thread.BlockableEventLoop; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; @@ -57,8 +60,8 @@ public class NetworkManagerImpl { private static void registerC2SReceiver(ResourceLocation id, List packetTransformers, NetworkReceiver receiver) { C2S_RECEIVER.put(id, receiver); PacketTransformer transformer = PacketTransformer.concat(packetTransformers); - ServerSidePacketRegistry.INSTANCE.register(id, (packetContext, buf) -> { - NetworkManager.PacketContext context = to(packetContext); + ServerPlayNetworking.registerGlobalReceiver(id, (server, player, handler, buf, sender) -> { + var context = context(player, server, false); transformer.inbound(NetworkManager.Side.C2S, id, buf, context, (side, id1, buf1) -> { NetworkReceiver networkReceiver = side == NetworkManager.Side.C2S ? C2S_RECEIVER.get(id1) : S2C_RECEIVER.get(id1); if (networkReceiver == null) { @@ -70,38 +73,42 @@ public class NetworkManagerImpl { C2S_TRANSFORMERS.put(id, transformer); } + @SuppressWarnings("Convert2Lambda") @Environment(EnvType.CLIENT) private static void registerS2CReceiver(ResourceLocation id, List packetTransformers, NetworkReceiver receiver) { S2C_RECEIVER.put(id, receiver); PacketTransformer transformer = PacketTransformer.concat(packetTransformers); - ClientSidePacketRegistry.INSTANCE.register(id, (packetContext, buf) -> { - NetworkManager.PacketContext context = to(packetContext); - transformer.inbound(NetworkManager.Side.S2C, id, buf, context, (side, id1, buf1) -> { - NetworkReceiver networkReceiver = side == NetworkManager.Side.C2S ? C2S_RECEIVER.get(id1) : S2C_RECEIVER.get(id1); - if (networkReceiver == null) { - throw new IllegalArgumentException("Network Receiver not found! " + id1); - } - networkReceiver.receive(buf1, context); - }); + ClientPlayNetworking.registerGlobalReceiver(id, new ClientPlayNetworking.PlayChannelHandler() { + @Override + public void receive(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender sender) { + var context = context(client.player, client, true); + transformer.inbound(NetworkManager.Side.S2C, id, buf, context, (side, id1, buf1) -> { + NetworkReceiver networkReceiver = side == NetworkManager.Side.C2S ? C2S_RECEIVER.get(id1) : S2C_RECEIVER.get(id1); + if (networkReceiver == null) { + throw new IllegalArgumentException("Network Receiver not found! " + id1); + } + networkReceiver.receive(buf1, context); + }); + } }); S2C_TRANSFORMERS.put(id, transformer); } - private static NetworkManager.PacketContext to(PacketContext context) { + private static NetworkManager.PacketContext context(Player player, BlockableEventLoop taskQueue, boolean client) { return new NetworkManager.PacketContext() { @Override public Player getPlayer() { - return context.getPlayer(); + return player; } @Override public void queue(Runnable runnable) { - context.getTaskQueue().execute(runnable); + taskQueue.execute(runnable); } @Override public Env getEnvironment() { - return Env.fromPlatform(context.getPacketEnvironment()); + return client ? Env.CLIENT : Env.SERVER; } }; } @@ -129,11 +136,11 @@ public class NetworkManagerImpl { @Environment(EnvType.CLIENT) public static boolean canServerReceive(ResourceLocation id) { - return ClientSidePacketRegistry.INSTANCE.canServerReceive(id); + return ClientPlayNetworking.canSend(id); } public static boolean canPlayerReceive(ServerPlayer player, ResourceLocation id) { - return ServerSidePacketRegistry.INSTANCE.canPlayerReceive(player, id); + return ServerPlayNetworking.canSend(player, id); } public static Packet createAddEntityPacket(Entity entity) { @@ -142,10 +149,10 @@ public class NetworkManagerImpl { @Environment(EnvType.CLIENT) private static Packet toC2SPacket(ResourceLocation id, FriendlyByteBuf buf) { - return ClientSidePacketRegistry.INSTANCE.toPacket(id, buf); + return ClientPlayNetworking.createC2SPacket(id, buf); } private static Packet toS2CPacket(ResourceLocation id, FriendlyByteBuf buf) { - return ServerSidePacketRegistry.INSTANCE.toPacket(id, buf); + return ServerPlayNetworking.createS2CPacket(id, buf); } } diff --git a/fabric/src/main/java/dev/architectury/plugin/fabric/ArchitecturyMixinPlugin.java b/fabric/src/main/java/dev/architectury/plugin/fabric/ArchitecturyMixinPlugin.java index 279bbc64..c267a07c 100644 --- a/fabric/src/main/java/dev/architectury/plugin/fabric/ArchitecturyMixinPlugin.java +++ b/fabric/src/main/java/dev/architectury/plugin/fabric/ArchitecturyMixinPlugin.java @@ -19,7 +19,7 @@ package dev.architectury.plugin.fabric; -import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.*; import net.fabricmc.loader.api.SemanticVersion; import net.fabricmc.loader.api.Version; import net.fabricmc.loader.api.VersionParsingException; @@ -41,10 +41,29 @@ public class ArchitecturyMixinPlugin implements IMixinConfigPlugin { return null; } + private boolean isLoader013() { + ModContainer fabricLoader = FabricLoader.getInstance().getModContainer("fabricloader") + .orElseThrow(() -> new IllegalStateException("Where is fabricloader?")); + Version version = fabricLoader.getMetadata().getVersion(); + if (version instanceof SemanticVersion) { + try { + return version.compareTo(SemanticVersion.parse("0.13-")) >= 0; + } catch (VersionParsingException e) { + throw new IllegalStateException("Failed to parse version", e); + } + } + System.err.println("FabricLoader is not a SemanticVersion, cannot determine if it is >= 0.13"); + return true; + } + @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { if ("dev.architectury.mixin.fabric.client.MixinEffectInstance".equals(mixinClassName)) { return !FabricLoader.getInstance().isModLoaded("satin"); + } else if ("dev.architectury.mixin.fabric.client.MixinGameRenderer".equals(mixinClassName)) { + return !isLoader013(); + } else if ("dev.architectury.mixin.fabric.client.MixinGameRenderer013".equals(mixinClassName)) { + return isLoader013(); } else if ("dev.architectury.mixin.fabric.client.MixinMinecraft118".equals(mixinClassName)) { Version minecraft = FabricLoader.getInstance().getModContainer("minecraft").get().getMetadata().getVersion(); // is below 1.18.2 diff --git a/fabric/src/main/java/dev/architectury/registry/client/rendering/fabric/BlockEntityRendererRegistryImpl.java b/fabric/src/main/java/dev/architectury/registry/client/rendering/fabric/BlockEntityRendererRegistryImpl.java index 869f0d80..bd2f7f1e 100644 --- a/fabric/src/main/java/dev/architectury/registry/client/rendering/fabric/BlockEntityRendererRegistryImpl.java +++ b/fabric/src/main/java/dev/architectury/registry/client/rendering/fabric/BlockEntityRendererRegistryImpl.java @@ -19,13 +19,13 @@ package dev.architectury.registry.client.rendering.fabric; -import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry; +import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry; import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; public class BlockEntityRendererRegistryImpl { public static void register(BlockEntityType type, BlockEntityRendererProvider provider) { - BlockEntityRendererRegistry.INSTANCE.register(type, provider); + BlockEntityRendererRegistry.register(type, provider); } } diff --git a/fabric/src/main/resources/architectury.mixins.json b/fabric/src/main/resources/architectury.mixins.json index 2d42a43a..8acbe4c4 100644 --- a/fabric/src/main/resources/architectury.mixins.json +++ b/fabric/src/main/resources/architectury.mixins.json @@ -10,6 +10,7 @@ "client.MixinDebugScreenOverlay", "client.MixinEffectInstance", "client.MixinGameRenderer", + "client.MixinGameRenderer013", "client.MixinIntegratedServer", "client.MixinKeyboardHandler", "client.MixinMinecraft", diff --git a/forge/src/main/java/dev/architectury/mixin/forge/MixinMinecraft.java b/forge/src/main/java/dev/architectury/mixin/forge/MixinMinecraft.java new file mode 100644 index 00000000..562414b1 --- /dev/null +++ b/forge/src/main/java/dev/architectury/mixin/forge/MixinMinecraft.java @@ -0,0 +1,42 @@ +/* + * 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; + +import dev.architectury.event.events.client.ClientLifecycleEvent; +import net.minecraft.client.Minecraft; +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; + +// adopted from fabric +@Mixin(Minecraft.class) +public abstract class MixinMinecraft { + @Inject(at = @At(value = "FIELD", target = "Lnet/minecraft/client/Minecraft;gameThread:Ljava/lang/Thread;", shift = At.Shift.AFTER, ordinal = 0), method = "run") + private void onStart(CallbackInfo ci) { + ClientLifecycleEvent.CLIENT_STARTED.invoker().stateChanged((Minecraft) (Object) this); + } + + // using {1} rather than Log4j directly for 1.18.2+ support + @Inject(at = @At(value = "INVOKE", target = "{1}(Ljava/lang/String;)V" /* Logger.info */, shift = At.Shift.AFTER, remap = false), method = "destroy") + private void onStopping(CallbackInfo ci) { + ClientLifecycleEvent.CLIENT_STOPPING.invoker().stateChanged((Minecraft) (Object) this); + } +} diff --git a/forge/src/main/java/dev/architectury/registry/level/biome/forge/BiomeModificationsImpl.java b/forge/src/main/java/dev/architectury/registry/level/biome/forge/BiomeModificationsImpl.java index db534e40..59a465e5 100644 --- a/forge/src/main/java/dev/architectury/registry/level/biome/forge/BiomeModificationsImpl.java +++ b/forge/src/main/java/dev/architectury/registry/level/biome/forge/BiomeModificationsImpl.java @@ -34,6 +34,7 @@ import net.minecraft.world.level.levelgen.placement.PlacedFeature; import net.minecraftforge.common.world.BiomeGenerationSettingsBuilder; import net.minecraftforge.common.world.MobSpawnSettingsBuilder; import net.minecraftforge.event.world.BiomeLoadingEvent; +import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import org.apache.commons.lang3.tuple.Pair; @@ -48,22 +49,25 @@ import java.util.function.Supplier; @Mod.EventBusSubscriber(modid = ArchitecturyForge.MOD_ID) public class BiomeModificationsImpl { - private static final List, BiConsumer>> MODIFICATIONS = Lists.newArrayList(); + private static final List, BiConsumer>> ADDITIONS = Lists.newArrayList(); + private static final List, BiConsumer>> POST_PROCESSING = Lists.newArrayList(); + private static final List, BiConsumer>> REMOVALS = Lists.newArrayList(); + private static final List, BiConsumer>> REPLACEMENTS = Lists.newArrayList(); public static void addProperties(Predicate predicate, BiConsumer modifier) { - MODIFICATIONS.add(Pair.of(predicate, modifier)); + ADDITIONS.add(Pair.of(predicate, modifier)); } public static void postProcessProperties(Predicate predicate, BiConsumer modifier) { - MODIFICATIONS.add(Pair.of(predicate, modifier)); + POST_PROCESSING.add(Pair.of(predicate, modifier)); } public static void removeProperties(Predicate predicate, BiConsumer modifier) { - MODIFICATIONS.add(Pair.of(predicate, modifier)); + REMOVALS.add(Pair.of(predicate, modifier)); } public static void replaceProperties(Predicate predicate, BiConsumer modifier) { - MODIFICATIONS.add(Pair.of(predicate, modifier)); + REPLACEMENTS.add(Pair.of(predicate, modifier)); } private static BiomeContext wrapSelectionContext(BiomeLoadingEvent event) { @@ -149,7 +153,12 @@ public class BiomeModificationsImpl { public @NotNull List>> getCarvers(GenerationStep.Carving carving) { return generation.getCarvers(carving); } - + + @Override + public List> getFeatures(GenerationStep.Decoration decoration) { + return generation.getFeatures(decoration); + } + @Override public @NotNull List>> getFeatures() { return generation.features; @@ -367,11 +376,30 @@ public class BiomeModificationsImpl { } } - @SubscribeEvent - public static void onBiomeLoading(BiomeLoadingEvent event) { + @SubscribeEvent(priority = EventPriority.HIGH) + public static void processAdditions(BiomeLoadingEvent event) { + modifyBiome(event, ADDITIONS); + } + + @SubscribeEvent(priority = EventPriority.NORMAL) + public static void processRemovals(BiomeLoadingEvent event) { + modifyBiome(event, REMOVALS); + } + + @SubscribeEvent(priority = EventPriority.LOW) + public static void processReplacements(BiomeLoadingEvent event) { + modifyBiome(event, REPLACEMENTS); + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void postProcessBiomes(BiomeLoadingEvent event) { + modifyBiome(event, POST_PROCESSING); + } + + private static void modifyBiome(BiomeLoadingEvent event, List, BiConsumer>> list) { BiomeContext biomeContext = wrapSelectionContext(event); BiomeProperties.Mutable mutableBiome = new MutableBiomeWrapped(event); - for (Pair, BiConsumer> pair : MODIFICATIONS) { + for (var pair : list) { if (pair.getLeft().test(biomeContext)) { pair.getRight().accept(biomeContext, mutableBiome); } diff --git a/forge/src/main/resources/architectury.mixins.json b/forge/src/main/resources/architectury.mixins.json index 114c00a6..ceb99d84 100644 --- a/forge/src/main/resources/architectury.mixins.json +++ b/forge/src/main/resources/architectury.mixins.json @@ -5,7 +5,8 @@ "compatibilityLevel": "JAVA_16", "minVersion": "0.8", "client": [ - "MixinClientLevel" + "MixinClientLevel", + "MixinMinecraft" ], "mixins": [ "MixinChunkSerializer", diff --git a/gradle.properties b/gradle.properties index f92fd7de..0ffca31b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ cf_type=release archives_base_name=architectury archives_base_name_snapshot=architectury-snapshot -base_version=3.4 +base_version=3.6 maven_group=dev.architectury fabric_loader_version=0.12.12 diff --git a/testmod-common/src/main/java/dev/architectury/test/TestMod.java b/testmod-common/src/main/java/dev/architectury/test/TestMod.java index 9c17bdef..b18c93be 100644 --- a/testmod-common/src/main/java/dev/architectury/test/TestMod.java +++ b/testmod-common/src/main/java/dev/architectury/test/TestMod.java @@ -19,7 +19,8 @@ package dev.architectury.test; -import dev.architectury.registry.level.entity.EntityRendererRegistry; +import dev.architectury.event.events.client.ClientLifecycleEvent; +import dev.architectury.registry.client.level.entity.EntityRendererRegistry; import dev.architectury.test.debug.ConsoleMessageSink; import dev.architectury.test.debug.MessageSink; import dev.architectury.test.debug.client.ClientOverlayMessageSink; @@ -60,6 +61,8 @@ public class TestMod { public static class Client { @Environment(EnvType.CLIENT) public static void initializeClient() { + ClientLifecycleEvent.CLIENT_STARTED.register((client) -> SINK.accept("Client started!")); + ClientLifecycleEvent.CLIENT_STOPPING.register((client) -> SINK.accept("Client stopping!")); TestKeybinds.initialize(); TestModNet.initializeClient(); EntityRendererRegistry.register(() -> TestEntity.TYPE, context ->