Sfoglia il codice sorgente

Fix client events, bump version to 1.1, fix FluidStackHooks for fabric.

shedaniel 4 anni fa
parent
commit
eaba509f2b
21 ha cambiato i file con 437 aggiunte e 122 eliminazioni
  1. 1 1
      build.gradle
  2. 0 26
      common/src/main/java/me/shedaniel/architectury/event/events/ChatEvent.java
  3. 0 24
      common/src/main/java/me/shedaniel/architectury/event/events/LifecycleEvent.java
  4. 0 21
      common/src/main/java/me/shedaniel/architectury/event/events/PlayerEvent.java
  5. 0 14
      common/src/main/java/me/shedaniel/architectury/event/events/TickEvent.java
  6. 56 0
      common/src/main/java/me/shedaniel/architectury/event/events/client/ClientChatEvent.java
  7. 51 0
      common/src/main/java/me/shedaniel/architectury/event/events/client/ClientLifecycleEvent.java
  8. 48 0
      common/src/main/java/me/shedaniel/architectury/event/events/client/ClientPlayerEvent.java
  9. 43 0
      common/src/main/java/me/shedaniel/architectury/event/events/client/ClientTickEvent.java
  10. 13 0
      common/src/main/java/me/shedaniel/architectury/fluid/FluidStack.java
  11. 5 1
      common/src/main/java/me/shedaniel/architectury/platform/Platform.java
  12. 52 0
      common/src/main/java/me/shedaniel/architectury/utils/EnvExecutor.java
  13. 12 6
      fabric/src/main/java/me/shedaniel/architectury/event/fabric/EventHandlerImpl.java
  14. 105 0
      fabric/src/main/java/me/shedaniel/architectury/hooks/fabric/FluidStackHooksImpl.java
  15. 2 2
      fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinClientLevel.java
  16. 5 5
      fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinClientPacketListener.java
  17. 2 2
      fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinMinecraft.java
  18. 2 2
      fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinScreen.java
  19. 14 12
      forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImplClient.java
  20. 25 4
      forge/src/main/java/me/shedaniel/architectury/hooks/forge/FluidStackHooksImpl.java
  21. 1 2
      gradle.properties

+ 1 - 1
build.gradle

@@ -17,7 +17,7 @@ allprojects {
     apply plugin: "org.cadixdev.licenser"
 
     archivesBaseName = rootProject.archives_base_name
-    version = rootProject.mod_version + "." + (System.getenv("GITHUB_RUN_NUMBER") == null ? "9999" : (System.getenv("GITHUB_RUN_NUMBER").toInteger() - Integer.parseInt(rootProject.last_minor_build)).toString())
+    version = rootProject.mod_version + "." + (System.getenv("GITHUB_RUN_NUMBER") == null ? "9999" : System.getenv("GITHUB_RUN_NUMBER"))
     group = rootProject.maven_group
 
     tasks.withType(JavaCompile) {

+ 0 - 26
common/src/main/java/me/shedaniel/architectury/event/events/ChatEvent.java

@@ -21,43 +21,17 @@ package me.shedaniel.architectury.event.events;
 
 import me.shedaniel.architectury.event.Event;
 import me.shedaniel.architectury.event.EventFactory;
-import net.fabricmc.api.EnvType;
-import net.fabricmc.api.Environment;
-import net.minecraft.network.chat.ChatType;
 import net.minecraft.network.chat.Component;
 import net.minecraft.server.level.ServerPlayer;
 import net.minecraft.world.InteractionResultHolder;
 import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.UUID;
 
 public interface ChatEvent {
-    /**
-     * Invoked when client tries to send a message, equivalent to forge's {@code ClientChatEvent}.
-     */
-    @Environment(EnvType.CLIENT) Event<Client> CLIENT = EventFactory.createInteractionResultHolder(Client.class);
-    /**
-     * Invoked when client receives a message, equivalent to forge's {@code ClientChatReceivedEvent}.
-     */
-    @Environment(EnvType.CLIENT) Event<ClientReceived> CLIENT_RECEIVED = EventFactory.createInteractionResultHolder(ClientReceived.class);
     /**
      * Invoked when server receives a message, equivalent to forge's {@code ServerChatEvent}.
      */
     Event<Server> SERVER = EventFactory.createInteractionResultHolder(Server.class);
     
-    @Environment(EnvType.CLIENT)
-    interface Client {
-        @NotNull
-        InteractionResultHolder<String> process(String message);
-    }
-    
-    @Environment(EnvType.CLIENT)
-    interface ClientReceived {
-        @NotNull
-        InteractionResultHolder<Component> process(ChatType type, Component message, @Nullable UUID sender);
-    }
-    
     interface Server {
         @NotNull
         InteractionResultHolder<Component> process(ServerPlayer player, String message, Component component);

+ 0 - 24
common/src/main/java/me/shedaniel/architectury/event/events/LifecycleEvent.java

@@ -21,24 +21,11 @@ package me.shedaniel.architectury.event.events;
 
 import me.shedaniel.architectury.event.Event;
 import me.shedaniel.architectury.event.EventFactory;
-import net.fabricmc.api.EnvType;
-import net.fabricmc.api.Environment;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.multiplayer.ClientLevel;
 import net.minecraft.server.MinecraftServer;
 import net.minecraft.server.level.ServerLevel;
 import net.minecraft.world.level.Level;
 
-
 public interface LifecycleEvent {
-    /**
-     * Invoked when client has been initialised, not available in forge.
-     */
-    @Deprecated @Environment(EnvType.CLIENT) Event<ClientState> CLIENT_STARTED = EventFactory.createLoop(ClientState.class);
-    /**
-     * Invoked when client is initialising, not available in forge.
-     */
-    @Deprecated @Environment(EnvType.CLIENT) Event<ClientState> CLIENT_STOPPING = EventFactory.createLoop(ClientState.class);
     /**
      * Invoked when server is starting, equivalent to forge's {@code FMLServerStartingEvent} and fabric's {@code ServerLifecycleEvents#SERVER_STARTING}.
      */
@@ -67,27 +54,16 @@ public interface LifecycleEvent {
      * Invoked during a world is saved, equivalent to forge's {@code WorldEvent.Save}.
      */
     Event<ServerWorldState> SERVER_WORLD_SAVE = EventFactory.createLoop(ServerWorldState.class);
-    /**
-     * Invoked after a world is loaded only on client, equivalent to forge's {@code WorldEvent.Load}.
-     */
-    @Environment(EnvType.CLIENT) Event<ClientWorldState> CLIENT_WORLD_LOAD = EventFactory.createLoop(ClientWorldState.class);
     
     interface InstanceState<T> {
         void stateChanged(T instance);
     }
     
-    @Deprecated
-    @Environment(EnvType.CLIENT)
-    interface ClientState extends InstanceState<Minecraft> {}
-    
     interface ServerState extends InstanceState<MinecraftServer> {}
     
     interface WorldState<T extends Level> {
         void act(T world);
     }
     
-    @Environment(EnvType.CLIENT)
-    interface ClientWorldState extends WorldState<ClientLevel> {}
-    
     interface ServerWorldState extends WorldState<ServerLevel> {}
 }

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

@@ -22,10 +22,7 @@ package me.shedaniel.architectury.event.events;
 import me.shedaniel.architectury.event.Event;
 import me.shedaniel.architectury.event.EventFactory;
 import me.shedaniel.architectury.utils.IntValue;
-import net.fabricmc.api.EnvType;
-import net.fabricmc.api.Environment;
 import net.minecraft.advancements.Advancement;
-import net.minecraft.client.player.LocalPlayer;
 import net.minecraft.core.BlockPos;
 import net.minecraft.server.level.ServerPlayer;
 import net.minecraft.world.Container;
@@ -42,9 +39,6 @@ public interface PlayerEvent {
     Event<PlayerJoin> PLAYER_JOIN = EventFactory.createLoop(PlayerJoin.class);
     Event<PlayerQuit> PLAYER_QUIT = EventFactory.createLoop(PlayerQuit.class);
     Event<PlayerRespawn> PLAYER_RESPAWN = EventFactory.createLoop(PlayerRespawn.class);
-    @Environment(EnvType.CLIENT) Event<ClientPlayerJoin> CLIENT_PLAYER_JOIN = EventFactory.createLoop(ClientPlayerJoin.class);
-    @Environment(EnvType.CLIENT) Event<ClientPlayerQuit> CLIENT_PLAYER_QUIT = EventFactory.createLoop(ClientPlayerQuit.class);
-    @Environment(EnvType.CLIENT) Event<ClientPlayerRespawn> CLIENT_PLAYER_RESPAWN = EventFactory.createLoop(ClientPlayerRespawn.class);
     Event<PlayerAdvancement> PLAYER_ADVANCEMENT = EventFactory.createLoop(PlayerAdvancement.class);
     Event<PlayerClone> PLAYER_CLONE = EventFactory.createLoop(PlayerClone.class);
     Event<CraftItem> CRAFT_ITEM = EventFactory.createLoop(CraftItem.class);
@@ -107,19 +101,4 @@ public interface PlayerEvent {
     interface CloseMenu {
         void close(Player player, AbstractContainerMenu menu);
     }
-    
-    @Environment(EnvType.CLIENT)
-    interface ClientPlayerJoin {
-        void join(LocalPlayer player);
-    }
-    
-    @Environment(EnvType.CLIENT)
-    interface ClientPlayerQuit {
-        void quit(LocalPlayer player);
-    }
-    
-    @Environment(EnvType.CLIENT)
-    interface ClientPlayerRespawn {
-        void respawn(LocalPlayer oldPlayer, LocalPlayer newPlayer);
-    }
 }

+ 0 - 14
common/src/main/java/me/shedaniel/architectury/event/events/TickEvent.java

@@ -21,21 +21,13 @@ package me.shedaniel.architectury.event.events;
 
 import me.shedaniel.architectury.event.Event;
 import me.shedaniel.architectury.event.EventFactory;
-import net.fabricmc.api.EnvType;
-import net.fabricmc.api.Environment;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.multiplayer.ClientLevel;
 import net.minecraft.server.MinecraftServer;
 import net.minecraft.server.level.ServerLevel;
 import net.minecraft.world.level.Level;
 
 public interface TickEvent<T> {
-    @Environment(EnvType.CLIENT) Event<Client> CLIENT_PRE = EventFactory.createLoop(Client.class);
-    @Environment(EnvType.CLIENT) Event<Client> CLIENT_POST = EventFactory.createLoop(Client.class);
     Event<Server> SERVER_PRE = EventFactory.createLoop(Server.class);
     Event<Server> SERVER_POST = EventFactory.createLoop(Server.class);
-    @Environment(EnvType.CLIENT) Event<ClientWorld> CLIENT_WORLD_PRE = EventFactory.createLoop(ClientWorld.class);
-    @Environment(EnvType.CLIENT) Event<ClientWorld> CLIENT_WORLD_POST = EventFactory.createLoop(ClientWorld.class);
     Event<ServerWorld> SERVER_WORLD_PRE = EventFactory.createLoop(ServerWorld.class);
     Event<ServerWorld> SERVER_WORLD_POST = EventFactory.createLoop(ServerWorld.class);
     Event<Player> PLAYER_PRE = EventFactory.createLoop(Player.class);
@@ -43,16 +35,10 @@ public interface TickEvent<T> {
     
     void tick(T instance);
     
-    @Environment(EnvType.CLIENT)
-    interface Client extends TickEvent<Minecraft> {}
-    
     interface Server extends TickEvent<MinecraftServer> {}
     
     interface WorldTick<T extends Level> extends TickEvent<T> {}
     
-    @Environment(EnvType.CLIENT)
-    interface ClientWorld extends WorldTick<ClientLevel> {}
-    
     interface ServerWorld extends WorldTick<ServerLevel> {}
     
     interface Player extends TickEvent<net.minecraft.world.entity.player.Player> {}

+ 56 - 0
common/src/main/java/me/shedaniel/architectury/event/events/client/ClientChatEvent.java

@@ -0,0 +1,56 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.event.events.client;
+
+import me.shedaniel.architectury.event.Event;
+import me.shedaniel.architectury.event.EventFactory;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.network.chat.ChatType;
+import net.minecraft.network.chat.Component;
+import net.minecraft.world.InteractionResultHolder;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+
+@Environment(EnvType.CLIENT)
+public interface ClientChatEvent {
+    /**
+     * Invoked when client tries to send a message, equivalent to forge's {@code ClientChatEvent}.
+     */
+    Event<Client> CLIENT = EventFactory.createInteractionResultHolder(Client.class);
+    /**
+     * Invoked when client receives a message, equivalent to forge's {@code ClientChatReceivedEvent}.
+     */
+    Event<ClientReceived> CLIENT_RECEIVED = EventFactory.createInteractionResultHolder(ClientReceived.class);
+    
+    @Environment(EnvType.CLIENT)
+    interface Client {
+        @NotNull
+        InteractionResultHolder<String> process(String message);
+    }
+    
+    @Environment(EnvType.CLIENT)
+    interface ClientReceived {
+        @NotNull
+        InteractionResultHolder<Component> process(ChatType type, Component message, @Nullable UUID sender);
+    }
+}

+ 51 - 0
common/src/main/java/me/shedaniel/architectury/event/events/client/ClientLifecycleEvent.java

@@ -0,0 +1,51 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.event.events.client;
+
+import me.shedaniel.architectury.event.Event;
+import me.shedaniel.architectury.event.EventFactory;
+import me.shedaniel.architectury.event.events.LifecycleEvent;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.multiplayer.ClientLevel;
+
+@Environment(EnvType.CLIENT)
+public interface ClientLifecycleEvent {
+    /**
+     * Invoked when client has been initialised, not available in forge.
+     */
+    @Deprecated Event<ClientState> CLIENT_STARTED = EventFactory.createLoop(ClientState.class);
+    /**
+     * Invoked when client is initialising, not available in forge.
+     */
+    @Deprecated Event<ClientState> CLIENT_STOPPING = EventFactory.createLoop(ClientState.class);
+    /**
+     * Invoked after a world is loaded only on client, equivalent to forge's {@code WorldEvent.Load}.
+     */
+    Event<ClientWorldState> CLIENT_WORLD_LOAD = EventFactory.createLoop(ClientWorldState.class);
+    
+    @Deprecated
+    @Environment(EnvType.CLIENT)
+    interface ClientState extends LifecycleEvent.InstanceState<Minecraft> {}
+    
+    @Environment(EnvType.CLIENT)
+    interface ClientWorldState extends LifecycleEvent.WorldState<ClientLevel> {}
+}

+ 48 - 0
common/src/main/java/me/shedaniel/architectury/event/events/client/ClientPlayerEvent.java

@@ -0,0 +1,48 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.event.events.client;
+
+import me.shedaniel.architectury.event.Event;
+import me.shedaniel.architectury.event.EventFactory;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.player.LocalPlayer;
+
+@Environment(EnvType.CLIENT)
+public interface ClientPlayerEvent {
+    Event<ClientPlayerJoin> CLIENT_PLAYER_JOIN = EventFactory.createLoop(ClientPlayerJoin.class);
+    Event<ClientPlayerQuit> CLIENT_PLAYER_QUIT = EventFactory.createLoop(ClientPlayerQuit.class);
+    Event<ClientPlayerRespawn> CLIENT_PLAYER_RESPAWN = EventFactory.createLoop(ClientPlayerRespawn.class);
+    
+    @Environment(EnvType.CLIENT)
+    interface ClientPlayerJoin {
+        void join(LocalPlayer player);
+    }
+    
+    @Environment(EnvType.CLIENT)
+    interface ClientPlayerQuit {
+        void quit(LocalPlayer player);
+    }
+    
+    @Environment(EnvType.CLIENT)
+    interface ClientPlayerRespawn {
+        void respawn(LocalPlayer oldPlayer, LocalPlayer newPlayer);
+    }
+}

+ 43 - 0
common/src/main/java/me/shedaniel/architectury/event/events/client/ClientTickEvent.java

@@ -0,0 +1,43 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.event.events.client;
+
+import me.shedaniel.architectury.event.Event;
+import me.shedaniel.architectury.event.EventFactory;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.multiplayer.ClientLevel;
+
+@Environment(EnvType.CLIENT)
+public interface ClientTickEvent<T> {
+    Event<Client> CLIENT_PRE = EventFactory.createLoop(Client.class);
+    Event<Client> CLIENT_POST = EventFactory.createLoop(Client.class);
+    Event<ClientWorld> CLIENT_WORLD_PRE = EventFactory.createLoop(ClientWorld.class);
+    Event<ClientWorld> CLIENT_WORLD_POST = EventFactory.createLoop(ClientWorld.class);
+    
+    void tick(T instance);
+    
+    @Environment(EnvType.CLIENT)
+    interface Client extends ClientTickEvent<Minecraft> {}
+    
+    @Environment(EnvType.CLIENT)
+    interface ClientWorld extends ClientTickEvent<ClientLevel> {}
+}

+ 13 - 0
common/src/main/java/me/shedaniel/architectury/fluid/FluidStack.java

@@ -33,6 +33,7 @@ import java.util.Objects;
 import java.util.function.Supplier;
 
 public final class FluidStack {
+    private static final FluidStack EMPTY = create(Fluids.EMPTY, Fraction.zero());
     private Fraction amount;
     @Nullable
     private CompoundTag tag;
@@ -44,6 +45,18 @@ public final class FluidStack {
         this.tag = tag == null ? null : tag.copy();
     }
     
+    public static FluidStack empty() {
+        return EMPTY;
+    }
+    
+    public static FluidStack create(Fluid fluid, Fraction amount, @Nullable CompoundTag tag) {
+        return create(() -> fluid, amount, tag);
+    }
+    
+    public static FluidStack create(Fluid fluid, Fraction amount) {
+        return create(fluid, amount, null);
+    }
+    
     public static FluidStack create(Supplier<Fluid> fluid, Fraction amount, @Nullable CompoundTag tag) {
         return new FluidStack(fluid, amount, tag);
     }

+ 5 - 1
common/src/main/java/me/shedaniel/architectury/platform/Platform.java

@@ -23,7 +23,6 @@ import me.shedaniel.architectury.Architectury;
 import me.shedaniel.architectury.ExpectPlatform;
 import net.fabricmc.api.EnvType;
 import net.minecraft.SharedConstants;
-import net.minecraft.util.LazyLoadedValue;
 import org.jetbrains.annotations.NotNull;
 
 import java.nio.file.Path;
@@ -32,6 +31,7 @@ import java.util.Optional;
 
 public final class Platform {
     private Platform() {}
+    
     private static int simpleLoaderCache = -1;
     
     /**
@@ -53,6 +53,10 @@ public final class Platform {
     }
     
     private static void updateLoaderCache() {
+        if (simpleLoaderCache != -1) {
+            return;
+        }
+        
         switch (getModLoader()) {
             case "fabric":
                 simpleLoaderCache = 0;

+ 52 - 0
common/src/main/java/me/shedaniel/architectury/utils/EnvExecutor.java

@@ -0,0 +1,52 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020 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.utils;
+
+import me.shedaniel.architectury.platform.Platform;
+import net.fabricmc.api.EnvType;
+
+import java.util.Optional;
+import java.util.function.Supplier;
+
+public final class EnvExecutor {
+    public static void runInEnv(EnvType type, Supplier<Runnable> runnableSupplier) {
+        if (Platform.getEnv() == type) {
+            runnableSupplier.get().run();
+        }
+    }
+    
+    public static <T> Optional<T> getInEnv(EnvType type, Supplier<Supplier<T>> runnableSupplier) {
+        if (Platform.getEnv() == type) {
+            return Optional.ofNullable(runnableSupplier.get().get());
+        }
+        
+        return Optional.empty();
+    }
+    
+    public static <T> T getEnvSpecific(Supplier<Supplier<T>> client, Supplier<Supplier<T>> server) {
+        if (Platform.getEnv() == EnvType.CLIENT) {
+            return client.get().get();
+        } else {
+            return server.get().get();
+        }
+    }
+    
+    private EnvExecutor() {}
+}

+ 12 - 6
fabric/src/main/java/me/shedaniel/architectury/event/fabric/EventHandlerImpl.java

@@ -20,6 +20,10 @@
 package me.shedaniel.architectury.event.fabric;
 
 import me.shedaniel.architectury.event.events.*;
+import me.shedaniel.architectury.event.events.client.ClientLifecycleEvent;
+import me.shedaniel.architectury.event.events.client.ClientTickEvent;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
 import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
 import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
 import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback;
@@ -34,14 +38,15 @@ import net.fabricmc.fabric.api.event.player.UseItemCallback;
 import net.minecraft.commands.Commands;
 
 public class EventHandlerImpl {
+    @Environment(EnvType.CLIENT)
     public static void registerClient() {
-        ClientLifecycleEvents.CLIENT_STARTED.register(LifecycleEvent.CLIENT_STARTED.invoker()::stateChanged);
-        ClientLifecycleEvents.CLIENT_STOPPING.register(LifecycleEvent.CLIENT_STOPPING.invoker()::stateChanged);
+        ClientLifecycleEvents.CLIENT_STARTED.register(ClientLifecycleEvent.CLIENT_STARTED.invoker()::stateChanged);
+        ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvent.CLIENT_STOPPING.invoker()::stateChanged);
         
-        ClientTickEvents.START_CLIENT_TICK.register(TickEvent.CLIENT_PRE.invoker()::tick);
-        ClientTickEvents.END_CLIENT_TICK.register(TickEvent.CLIENT_POST.invoker()::tick);
-        ClientTickEvents.START_WORLD_TICK.register(TickEvent.CLIENT_WORLD_PRE.invoker()::tick);
-        ClientTickEvents.END_WORLD_TICK.register(TickEvent.CLIENT_WORLD_POST.invoker()::tick);
+        ClientTickEvents.START_CLIENT_TICK.register(ClientTickEvent.CLIENT_PRE.invoker()::tick);
+        ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvent.CLIENT_POST.invoker()::tick);
+        ClientTickEvents.START_WORLD_TICK.register(ClientTickEvent.CLIENT_WORLD_PRE.invoker()::tick);
+        ClientTickEvents.END_WORLD_TICK.register(ClientTickEvent.CLIENT_WORLD_POST.invoker()::tick);
         
         ItemTooltipCallback.EVENT.register((itemStack, tooltipFlag, list) -> TooltipEvent.ITEM.invoker().append(itemStack, list, tooltipFlag));
         HudRenderCallback.EVENT.register(GuiEvent.RENDER_HUD.invoker()::renderHud);
@@ -68,6 +73,7 @@ public class EventHandlerImpl {
         AttackBlockCallback.EVENT.register((player, world, hand, pos, face) -> InteractionEvent.LEFT_CLICK_BLOCK.invoker().click(player, hand, pos, face));
     }
     
+    @Environment(EnvType.SERVER)
     public static void registerServer() {
         
     }

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

@@ -0,0 +1,105 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.hooks.fabric;
+
+import me.shedaniel.architectury.fluid.FluidStack;
+import me.shedaniel.architectury.platform.Platform;
+import me.shedaniel.architectury.utils.Fraction;
+import me.shedaniel.architectury.utils.NbtType;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.core.Registry;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TranslatableComponent;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.level.material.Fluid;
+import net.minecraft.world.level.material.Fluids;
+
+import java.util.Objects;
+
+public class FluidStackHooksImpl {
+    public static Component getName(FluidStack stack) {
+        if (Platform.getEnv() == EnvType.CLIENT) {
+            return getNameClient(stack);
+        }
+        
+        return new TranslatableComponent(getTranslationKey(stack));
+    }
+    
+    @Environment(EnvType.CLIENT)
+    private static Component getNameClient(FluidStack stack) {
+        return stack.getFluid().defaultFluidState().createLegacyBlock().getBlock().getName();
+    }
+    
+    public static String getTranslationKey(FluidStack stack) {
+        ResourceLocation id = Registry.FLUID.getKey(stack.getFluid());
+        return "block." + id.getNamespace() + "." + id.getPath();
+    }
+    
+    public static FluidStack read(FriendlyByteBuf buf) {
+        Fluid fluid = Objects.requireNonNull(Registry.FLUID.get(buf.readResourceLocation()));
+        Fraction amount = Fraction.of(buf.readVarLong(), buf.readVarLong());
+        CompoundTag tag = buf.readNbt();
+        if (fluid == Fluids.EMPTY) return FluidStack.empty();
+        return FluidStack.create(fluid, amount, tag);
+    }
+    
+    public static void write(FluidStack stack, FriendlyByteBuf buf) {
+        buf.writeResourceLocation(Registry.FLUID.getKey(stack.getFluid()));
+        buf.writeVarLong(stack.getAmount().getNumerator());
+        buf.writeVarLong(stack.getAmount().getDenominator());
+        buf.writeNbt(stack.getTag());
+    }
+    
+    public static FluidStack read(CompoundTag tag) {
+        if (tag == null || !tag.contains("id", NbtType.STRING)) {
+            return FluidStack.empty();
+        }
+        
+        Fluid fluid = Registry.FLUID.get(new ResourceLocation(tag.getString("id")));
+        if (fluid == null || fluid == Fluids.EMPTY) {
+            return FluidStack.empty();
+        }
+        long numerator = tag.getLong("numerator");
+        long denominator = tag.getLong("denominator");
+        FluidStack stack = FluidStack.create(fluid, Fraction.of(numerator, denominator));
+        
+        if (tag.contains("tag", NbtType.COMPOUND)) {
+            stack.setTag(tag.getCompound("tag"));
+        }
+        return stack;
+    }
+    
+    public static CompoundTag write(FluidStack stack, CompoundTag tag) {
+        tag.putString("id", Registry.FLUID.getKey(stack.getFluid()).toString());
+        tag.putLong("numerator", stack.getAmount().getNumerator());
+        tag.putLong("denominator", stack.getAmount().getDenominator());
+        if (stack.hasTag()) {
+            tag.put("tag", stack.getTag());
+        }
+        return tag;
+    }
+    
+    public static Fraction bucketAmount() {
+        return Fraction.ofWhole(1);
+    }
+}

+ 2 - 2
fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinClientLevel.java

@@ -20,7 +20,7 @@
 package me.shedaniel.architectury.mixin.fabric.client;
 
 import me.shedaniel.architectury.event.events.EntityEvent;
-import me.shedaniel.architectury.event.events.LifecycleEvent;
+import me.shedaniel.architectury.event.events.client.ClientLifecycleEvent;
 import net.minecraft.client.multiplayer.ClientLevel;
 import net.minecraft.client.multiplayer.ClientPacketListener;
 import net.minecraft.client.renderer.LevelRenderer;
@@ -41,7 +41,7 @@ import java.util.function.Supplier;
 public class MixinClientLevel {
     @Inject(method = "<init>", at = @At("RETURN"))
     private void construct(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey<Level> resourceKey, DimensionType dimensionType, int i, Supplier<ProfilerFiller> supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) {
-        LifecycleEvent.CLIENT_WORLD_LOAD.invoker().act((ClientLevel) (Object) this);
+        ClientLifecycleEvent.CLIENT_WORLD_LOAD.invoker().act((ClientLevel) (Object) this);
     }
     
     @Inject(method = "addEntity", at = @At("HEAD"), cancellable = true)

+ 5 - 5
fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinClientPacketListener.java

@@ -19,9 +19,9 @@
 
 package me.shedaniel.architectury.mixin.fabric.client;
 
-import me.shedaniel.architectury.event.events.ChatEvent;
-import me.shedaniel.architectury.event.events.PlayerEvent;
 import me.shedaniel.architectury.event.events.RecipeUpdateEvent;
+import me.shedaniel.architectury.event.events.client.ClientChatEvent;
+import me.shedaniel.architectury.event.events.client.ClientPlayerEvent;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.multiplayer.ClientPacketListener;
 import net.minecraft.client.player.LocalPlayer;
@@ -49,7 +49,7 @@ public class MixinClientPacketListener {
     
     @Inject(method = "handleLogin", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Options;broadcastOptions()V"))
     private void handleLogin(ClientboundLoginPacket packet, CallbackInfo ci) {
-        PlayerEvent.CLIENT_PLAYER_JOIN.invoker().join(minecraft.player);
+        ClientPlayerEvent.CLIENT_PLAYER_JOIN.invoker().join(minecraft.player);
     }
     
     @Inject(method = "handleRespawn", at = @At("HEAD"))
@@ -60,7 +60,7 @@ public class MixinClientPacketListener {
     @Inject(method = "handleRespawn", at = @At(value = "INVOKE",
                                                target = "Lnet/minecraft/client/multiplayer/ClientLevel;addPlayer(ILnet/minecraft/client/player/AbstractClientPlayer;)V"))
     private void handleRespawn(ClientboundRespawnPacket packet, CallbackInfo ci) {
-        PlayerEvent.CLIENT_PLAYER_RESPAWN.invoker().respawn(tmpPlayer, minecraft.player);
+        ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.invoker().respawn(tmpPlayer, minecraft.player);
         this.tmpPlayer = null;
     }
     
@@ -68,7 +68,7 @@ public class MixinClientPacketListener {
                                             target = "Lnet/minecraft/client/gui/Gui;handleChat(Lnet/minecraft/network/chat/ChatType;Lnet/minecraft/network/chat/Component;Ljava/util/UUID;)V"),
             cancellable = true)
     private void handleChat(ClientboundChatPacket packet, CallbackInfo ci) {
-        InteractionResultHolder<Component> process = ChatEvent.CLIENT_RECEIVED.invoker().process(packet.getType(), packet.getMessage(), packet.getSender());
+        InteractionResultHolder<Component> process = ClientChatEvent.CLIENT_RECEIVED.invoker().process(packet.getType(), packet.getMessage(), packet.getSender());
         if (process.getResult() == InteractionResult.FAIL)
             ci.cancel();
         else if (process.getObject() != null && !process.getObject().equals(packet.getMessage())) {

+ 2 - 2
fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinMinecraft.java

@@ -20,7 +20,7 @@
 package me.shedaniel.architectury.mixin.fabric.client;
 
 import me.shedaniel.architectury.event.events.InteractionEvent;
-import me.shedaniel.architectury.event.events.PlayerEvent;
+import me.shedaniel.architectury.event.events.client.ClientPlayerEvent;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.screens.Screen;
 import net.minecraft.client.player.LocalPlayer;
@@ -44,7 +44,7 @@ public class MixinMinecraft {
     @Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V",
             at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/chat/NarratorChatListener;clear()V"))
     private void handleLogin(Screen screen, CallbackInfo ci) {
-        PlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player);
+        ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player);
     }
     
     @Inject(method = "startUseItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", ordinal = 1),

+ 2 - 2
fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinScreen.java

@@ -19,8 +19,8 @@
 
 package me.shedaniel.architectury.mixin.fabric.client;
 
-import me.shedaniel.architectury.event.events.ChatEvent;
 import me.shedaniel.architectury.event.events.GuiEvent;
+import me.shedaniel.architectury.event.events.client.ClientChatEvent;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.components.AbstractWidget;
 import net.minecraft.client.gui.components.events.GuiEventListener;
@@ -59,7 +59,7 @@ public abstract class MixinScreen {
     
     @ModifyVariable(method = "sendMessage(Ljava/lang/String;Z)V", at = @At("HEAD"), argsOnly = true, ordinal = 0)
     private String modifyMessage(String message) {
-        InteractionResultHolder<String> process = ChatEvent.CLIENT.invoker().process(message);
+        InteractionResultHolder<String> process = ClientChatEvent.CLIENT.invoker().process(message);
         if (process.getResult() == InteractionResult.FAIL)
             return "";
         if (process.getObject() != null)

+ 14 - 12
forge/src/main/java/me/shedaniel/architectury/event/forge/EventHandlerImplClient.java

@@ -21,17 +21,19 @@ package me.shedaniel.architectury.event.forge;
 
 import me.shedaniel.architectury.event.events.TextureStitchEvent;
 import me.shedaniel.architectury.event.events.*;
+import me.shedaniel.architectury.event.events.client.ClientChatEvent;
+import me.shedaniel.architectury.event.events.client.ClientLifecycleEvent;
+import me.shedaniel.architectury.event.events.client.ClientPlayerEvent;
+import me.shedaniel.architectury.event.events.client.ClientTickEvent;
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.IGuiEventListener;
 import net.minecraft.client.world.ClientWorld;
-import net.minecraft.network.play.server.SUpdateRecipesPacket;
 import net.minecraft.util.ActionResult;
 import net.minecraft.util.ActionResultType;
 import net.minecraft.util.text.ITextComponent;
 import net.minecraftforge.api.distmarker.Dist;
 import net.minecraftforge.api.distmarker.OnlyIn;
 import net.minecraftforge.client.event.*;
-import net.minecraftforge.event.TickEvent.ClientTickEvent;
 import net.minecraftforge.event.entity.player.ItemTooltipEvent;
 import net.minecraftforge.event.entity.player.PlayerInteractEvent;
 import net.minecraftforge.event.world.WorldEvent;
@@ -47,11 +49,11 @@ public class EventHandlerImplClient {
     }
     
     @SubscribeEvent
-    public static void event(ClientTickEvent event) {
+    public static void event(net.minecraftforge.event.TickEvent.ClientTickEvent event) {
         if (event.phase == net.minecraftforge.event.TickEvent.Phase.START)
-            TickEvent.CLIENT_PRE.invoker().tick(Minecraft.getInstance());
+            ClientTickEvent.CLIENT_PRE.invoker().tick(Minecraft.getInstance());
         else if (event.phase == net.minecraftforge.event.TickEvent.Phase.END)
-            TickEvent.CLIENT_POST.invoker().tick(Minecraft.getInstance());
+            ClientTickEvent.CLIENT_POST.invoker().tick(Minecraft.getInstance());
     }
     
     @SubscribeEvent
@@ -62,17 +64,17 @@ public class EventHandlerImplClient {
     
     @SubscribeEvent
     public static void event(ClientPlayerNetworkEvent.LoggedInEvent event) {
-        PlayerEvent.CLIENT_PLAYER_JOIN.invoker().join(event.getPlayer());
+        ClientPlayerEvent.CLIENT_PLAYER_JOIN.invoker().join(event.getPlayer());
     }
     
     @SubscribeEvent
     public static void event(ClientPlayerNetworkEvent.LoggedOutEvent event) {
-        PlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(event.getPlayer());
+        ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(event.getPlayer());
     }
     
     @SubscribeEvent
     public static void event(ClientPlayerNetworkEvent.RespawnEvent event) {
-        PlayerEvent.CLIENT_PLAYER_RESPAWN.invoker().respawn(event.getOldPlayer(), event.getNewPlayer());
+        ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.invoker().respawn(event.getOldPlayer(), event.getNewPlayer());
     }
     
     @SubscribeEvent
@@ -94,8 +96,8 @@ public class EventHandlerImplClient {
     }
     
     @SubscribeEvent
-    public static void event(ClientChatEvent event) {
-        ActionResult<String> process = ChatEvent.CLIENT.invoker().process(event.getMessage());
+    public static void event(net.minecraftforge.client.event.ClientChatEvent event) {
+        ActionResult<String> process = ClientChatEvent.CLIENT.invoker().process(event.getMessage());
         if (process.getObject() != null)
             event.setMessage(process.getObject());
         if (process.getResult() == ActionResultType.FAIL)
@@ -104,7 +106,7 @@ public class EventHandlerImplClient {
     
     @SubscribeEvent
     public static void event(ClientChatReceivedEvent event) {
-        ActionResult<ITextComponent> process = ChatEvent.CLIENT_RECEIVED.invoker().process(event.getType(), event.getMessage(), event.getSenderUUID());
+        ActionResult<ITextComponent> process = ClientChatEvent.CLIENT_RECEIVED.invoker().process(event.getType(), event.getMessage(), event.getSenderUUID());
         if (process.getObject() != null)
             event.setMessage(process.getObject());
         if (process.getResult() == ActionResultType.FAIL)
@@ -115,7 +117,7 @@ public class EventHandlerImplClient {
     public static void event(WorldEvent.Save event) {
         if (event.getWorld() instanceof ClientWorld) {
             ClientWorld world = (ClientWorld) event.getWorld();
-            LifecycleEvent.CLIENT_WORLD_LOAD.invoker().act(world);
+            ClientLifecycleEvent.CLIENT_WORLD_LOAD.invoker().act(world);
         }
     }
     

+ 25 - 4
forge/src/main/java/me/shedaniel/architectury/hooks/forge/FluidStackHooksImpl.java

@@ -1,3 +1,22 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
 package me.shedaniel.architectury.hooks.forge;
 
 import me.shedaniel.architectury.fluid.FluidStack;
@@ -8,11 +27,13 @@ import net.minecraft.util.text.ITextComponent;
 
 public class FluidStackHooksImpl {
     public static ITextComponent getName(FluidStack stack) {
-        return stack.getName();
+        return stack.getFluid().getAttributes().getDisplayName(
+                new net.minecraftforge.fluids.FluidStack(stack.getRawFluid(), stack.getAmount().intValue(), stack.getTag()));
     }
     
     public static String getTranslationKey(FluidStack stack) {
-        return stack.getTranslationKey();
+        return stack.getFluid().getAttributes().getTranslationKey(
+                new net.minecraftforge.fluids.FluidStack(stack.getRawFluid(), stack.getAmount().intValue(), stack.getTag()));
     }
     
     public static FluidStack read(PacketBuffer buf) {
@@ -21,7 +42,7 @@ public class FluidStackHooksImpl {
     }
     
     public static void write(FluidStack stack, PacketBuffer buf) {
-        stack.write(buf);
+        new net.minecraftforge.fluids.FluidStack(stack.getRawFluid(), stack.getAmount().intValue(), stack.getTag()).writeToPacket(buf);
     }
     
     public static FluidStack read(CompoundNBT tag) {
@@ -30,7 +51,7 @@ public class FluidStackHooksImpl {
     }
     
     public static CompoundNBT write(FluidStack stack, CompoundNBT tag) {
-        return stack.write(tag);
+        return new net.minecraftforge.fluids.FluidStack(stack.getRawFluid(), stack.getAmount().intValue(), stack.getTag()).writeToNBT(tag);
     }
     
     public static Fraction bucketAmount() {

+ 1 - 2
gradle.properties

@@ -5,8 +5,7 @@ minecraft_version=1.16.4
 supported_version=1.16.4
 
 archives_base_name=architectury
-mod_version=1.0
-last_minor_build=3
+mod_version=1.1
 maven_group=me.shedaniel
 
 fabric_loader_version=0.10.6+build.214