Ver código fonte

Merge branch '1.16' into feature/screen-open-event

Max 4 anos atrás
pai
commit
8d1f10205c

+ 6 - 0
.github/workflows/publish.yml

@@ -2,6 +2,10 @@ name: Java CI
 
 
 on:
 on:
   push:
   push:
+    paths:
+      - '**.gradle'
+      - '**.properties'
+      - '**/src/**'
     branches:
     branches:
       - "1.16"
       - "1.16"
       - "1.17"
       - "1.17"
@@ -17,6 +21,8 @@ jobs:
           java-version: 1.8
           java-version: 1.8
       - name: Upload to Bintray
       - name: Upload to Bintray
         run: ./gradlew bintrayUpload curseforgePublish --stacktrace
         run: ./gradlew bintrayUpload curseforgePublish --stacktrace
+        if: |
+          !contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.pull_request.title, '[ci skip]')
         env:
         env:
           BINTRAY_USER: shedaniel
           BINTRAY_USER: shedaniel
           BINTRAY_KEY: ${{ secrets.BINTRAY_KEY }}
           BINTRAY_KEY: ${{ secrets.BINTRAY_KEY }}

+ 29 - 0
.github/workflows/snapshot.yml

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

+ 17 - 5
build.gradle

@@ -1,6 +1,6 @@
 plugins {
 plugins {
-    id "architectury-plugin" version "2.0.57"
-    id "forgified-fabric-loom" version "0.6.49" apply false
+    id "architectury-plugin" version "2.0.64"
+    id "forgified-fabric-loom" version "0.6.53" apply false
     id "org.cadixdev.licenser" version "0.5.0"
     id "org.cadixdev.licenser" version "0.5.0"
     id "com.jfrog.bintray" version "1.8.4"
     id "com.jfrog.bintray" version "1.8.4"
     id "com.matthewprenger.cursegradle" version "1.4.0" apply false
     id "com.matthewprenger.cursegradle" version "1.4.0" apply false
@@ -25,9 +25,21 @@ allprojects {
     apply plugin: "java"
     apply plugin: "java"
     apply plugin: "architectury-plugin"
     apply plugin: "architectury-plugin"
     apply plugin: "org.cadixdev.licenser"
     apply plugin: "org.cadixdev.licenser"
+    
+    ext {
+        isSnapshot = System.getenv("PR_NUM") != null
+    }
+    
+    def runNumber = (System.getenv("GITHUB_RUN_NUMBER") == null ? "9999" : System.getenv("GITHUB_RUN_NUMBER"))
 
 
-    archivesBaseName = rootProject.archives_base_name
-    version = rootProject.mod_version + "." + (System.getenv("GITHUB_RUN_NUMBER") == null ? "9999" : System.getenv("GITHUB_RUN_NUMBER"))
+    if (!ext.isSnapshot) {
+        version = rootProject.base_version + "." + runNumber
+        archivesBaseName = rootProject.archives_base_name
+    } else {
+        version = rootProject.base_version + "-PR." + System.getenv("PR_NUM") + "." + runNumber
+        archivesBaseName = rootProject.archives_base_name_snapshot
+    }
+    
     group = rootProject.maven_group
     group = rootProject.maven_group
 
 
     tasks.withType(JavaCompile) {
     tasks.withType(JavaCompile) {
@@ -55,7 +67,7 @@ allprojects {
 
 
         ignoreFailures = true
         ignoreFailures = true
     }
     }
-    
+
     ext {
     ext {
         releaseChangelog = {
         releaseChangelog = {
             def dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm")
             def dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm")

+ 6 - 0
common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java

@@ -24,6 +24,7 @@ import me.shedaniel.architectury.event.EventFactory;
 import me.shedaniel.architectury.utils.IntValue;
 import me.shedaniel.architectury.utils.IntValue;
 import net.minecraft.advancements.Advancement;
 import net.minecraft.advancements.Advancement;
 import net.minecraft.core.BlockPos;
 import net.minecraft.core.BlockPos;
+import net.minecraft.resources.ResourceKey;
 import net.minecraft.server.level.ServerPlayer;
 import net.minecraft.server.level.ServerPlayer;
 import net.minecraft.world.Container;
 import net.minecraft.world.Container;
 import net.minecraft.world.InteractionResult;
 import net.minecraft.world.InteractionResult;
@@ -45,6 +46,7 @@ public interface PlayerEvent {
     Event<SmeltItem> SMELT_ITEM = EventFactory.createLoop();
     Event<SmeltItem> SMELT_ITEM = EventFactory.createLoop();
     Event<PickupItemPredicate> PICKUP_ITEM_PRE = EventFactory.createInteractionResult();
     Event<PickupItemPredicate> PICKUP_ITEM_PRE = EventFactory.createInteractionResult();
     Event<PickupItem> PICKUP_ITEM_POST = EventFactory.createLoop();
     Event<PickupItem> PICKUP_ITEM_POST = EventFactory.createLoop();
+    Event<ChangeDimension> CHANGE_DIMENSION = EventFactory.createLoop();
     Event<DropItem> DROP_ITEM = EventFactory.createLoop();
     Event<DropItem> DROP_ITEM = EventFactory.createLoop();
     Event<OpenMenu> OPEN_MENU = EventFactory.createLoop();
     Event<OpenMenu> OPEN_MENU = EventFactory.createLoop();
     Event<CloseMenu> CLOSE_MENU = EventFactory.createLoop();
     Event<CloseMenu> CLOSE_MENU = EventFactory.createLoop();
@@ -86,6 +88,10 @@ public interface PlayerEvent {
         void pickup(Player player, ItemEntity entity, ItemStack stack);
         void pickup(Player player, ItemEntity entity, ItemStack stack);
     }
     }
     
     
+    interface ChangeDimension {
+        void change(ServerPlayer player, ResourceKey<Level> oldLevel, ResourceKey<Level> newLevel);
+    }
+    
     interface DropItem {
     interface DropItem {
         InteractionResult drop(Player player, ItemEntity entity);
         InteractionResult drop(Player player, ItemEntity entity);
     }
     }

+ 69 - 0
common/src/main/java/me/shedaniel/architectury/hooks/FluidStackHooks.java

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

+ 56 - 0
common/src/main/java/me/shedaniel/architectury/hooks/ItemStackHooks.java

@@ -0,0 +1,56 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.hooks;
+
+import net.minecraft.server.level.ServerPlayer;
+import net.minecraft.sounds.SoundEvents;
+import net.minecraft.sounds.SoundSource;
+import net.minecraft.world.entity.item.ItemEntity;
+import net.minecraft.world.item.ItemStack;
+
+public final class ItemStackHooks {
+    private ItemStackHooks() {}
+    
+    public static ItemStack copyWithCount(ItemStack stack, int count) {
+        ItemStack copy = stack.copy();
+        copy.setCount(count);
+        return copy;
+    }
+    
+    public static void giveItem(ServerPlayer player, ItemStack stack) {
+        boolean bl = player.inventory.add(stack);
+        if (bl && stack.isEmpty()) {
+            stack.setCount(1);
+            ItemEntity entity = player.drop(stack, false);
+            if (entity != null) {
+                entity.makeFakeItem();
+            }
+            
+            player.level.playSound(null, player.getX(), player.getY(), player.getZ(), SoundEvents.ITEM_PICKUP, SoundSource.PLAYERS, 0.2F, ((player.getRandom().nextFloat() - player.getRandom().nextFloat()) * 0.7F + 1.0F) * 2.0F);
+            player.inventoryMenu.broadcastChanges();
+        } else {
+            ItemEntity entity = player.drop(stack, false);
+            if (entity != null) {
+                entity.setNoPickUpDelay();
+                entity.setOwner(player.getUUID());
+            }
+        }
+    }
+}

+ 90 - 0
fabric/src/main/java/me/shedaniel/architectury/hooks/fabric/FluidStackHooksImpl.java

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

+ 6 - 0
fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/MixinServerPlayer.java

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

+ 22 - 3
fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinEffectInstance.java

@@ -1,3 +1,22 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
 package me.shedaniel.architectury.mixin.fabric.client;
 package me.shedaniel.architectury.mixin.fabric.client;
 
 
 import com.mojang.blaze3d.shaders.Program;
 import com.mojang.blaze3d.shaders.Program;
@@ -10,7 +29,7 @@ import org.spongepowered.asm.mixin.injection.At;
 import org.spongepowered.asm.mixin.injection.Redirect;
 import org.spongepowered.asm.mixin.injection.Redirect;
 
 
 @Unique
 @Unique
-@Mixin(EffectInstance.class)
+@Mixin(value = EffectInstance.class, priority = 950)
 public class MixinEffectInstance {
 public class MixinEffectInstance {
     @Redirect(
     @Redirect(
             method = "<init>",
             method = "<init>",
@@ -21,7 +40,7 @@ public class MixinEffectInstance {
     private ResourceLocation mojangPls(String _0, ResourceManager rm, String str) {
     private ResourceLocation mojangPls(String _0, ResourceManager rm, String str) {
         return mojangPls(new ResourceLocation(str), ".json");
         return mojangPls(new ResourceLocation(str), ".json");
     }
     }
-
+    
     @Redirect(
     @Redirect(
             method = "getOrCreate",
             method = "getOrCreate",
             at = @At(value = "NEW",
             at = @At(value = "NEW",
@@ -31,7 +50,7 @@ public class MixinEffectInstance {
     private static ResourceLocation mojangPls(String _0, ResourceManager rm, Program.Type type, String str) {
     private static ResourceLocation mojangPls(String _0, ResourceManager rm, Program.Type type, String str) {
         return mojangPls(new ResourceLocation(str), type.getExtension());
         return mojangPls(new ResourceLocation(str), type.getExtension());
     }
     }
-
+    
     private static ResourceLocation mojangPls(ResourceLocation rl, String ext) {
     private static ResourceLocation mojangPls(ResourceLocation rl, String ext) {
         return new ResourceLocation(rl.getNamespace(), "shaders/program/" + rl.getPath() + ext);
         return new ResourceLocation(rl.getNamespace(), "shaders/program/" + rl.getPath() + ext);
     }
     }

+ 52 - 0
fabric/src/main/java/me/shedaniel/architectury/plugin/fabric/ArchitecturyMixinPlugin.java

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

+ 3 - 2
fabric/src/main/resources/architectury.mixins.json

@@ -1,12 +1,14 @@
 {
 {
   "required": true,
   "required": true,
   "package": "me.shedaniel.architectury.mixin.fabric",
   "package": "me.shedaniel.architectury.mixin.fabric",
+  "plugin": "me.shedaniel.architectury.plugin.fabric.ArchitecturyMixinPlugin",
   "compatibilityLevel": "JAVA_8",
   "compatibilityLevel": "JAVA_8",
   "minVersion": "0.7.11",
   "minVersion": "0.7.11",
   "client": [
   "client": [
     "client.MixinClientLevel",
     "client.MixinClientLevel",
     "client.MixinClientPacketListener",
     "client.MixinClientPacketListener",
     "client.MixinDebugScreenOverlay",
     "client.MixinDebugScreenOverlay",
+    "client.MixinEffectInstance",
     "client.MixinGameRenderer",
     "client.MixinGameRenderer",
     "client.MixinIntegratedServer",
     "client.MixinIntegratedServer",
     "client.MixinKeyboardHandler",
     "client.MixinKeyboardHandler",
@@ -14,8 +16,7 @@
     "client.MixinMouseHandler",
     "client.MixinMouseHandler",
     "client.MixinMultiPlayerGameMode",
     "client.MixinMultiPlayerGameMode",
     "client.MixinScreen",
     "client.MixinScreen",
-    "client.MixinTextureAtlas",
-    "client.MixinEffectInstance"
+    "client.MixinTextureAtlas"
   ],
   ],
   "mixins": [
   "mixins": [
     "ExplosionPreInvoker",
     "ExplosionPreInvoker",

+ 7 - 0
forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImplCommon.java

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

+ 79 - 0
forge/src/main/java/me/shedaniel/architectury/hooks/forge/FluidStackHooksImpl.java

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

+ 2 - 1
gradle.properties

@@ -5,7 +5,8 @@ minecraft_version=1.16.4
 supported_version=1.16.4/5
 supported_version=1.16.4/5
 
 
 archives_base_name=architectury
 archives_base_name=architectury
-mod_version=1.4
+archives_base_name_snapshot=architectury-snapshot
+base_version=1.4
 maven_group=me.shedaniel
 maven_group=me.shedaniel
 
 
 fabric_loader_version=0.10.8
 fabric_loader_version=0.10.8

+ 3 - 0
testmod-common/src/main/java/me/shedaniel/architectury/test/events/DebugEvents.java

@@ -165,6 +165,9 @@ public class DebugEvents {
         PlayerEvent.CLOSE_MENU.register((player, menu) -> {
         PlayerEvent.CLOSE_MENU.register((player, menu) -> {
             SINK.accept(player.getScoreboardName() + " closes " + toSimpleName(menu) + logSide(player.level));
             SINK.accept(player.getScoreboardName() + " closes " + toSimpleName(menu) + logSide(player.level));
         });
         });
+        PlayerEvent.CHANGE_DIMENSION.register((player, oldLevel, newLevel) -> {
+            SINK.accept(player.getScoreboardName() + " switched from " + oldLevel.location() + " to " + newLevel.location() + logSide(player.level));
+        });
     }
     }
     
     
     public static String toShortString(Vec3i pos) {
     public static String toShortString(Vec3i pos) {