From 01d9a51c610eb9f28fa22767839c6609acda1275 Mon Sep 17 00:00:00 2001
From: fishshi <2855691008@qq.com>
Date: Wed, 13 Nov 2024 02:16:14 +0800
Subject: [PATCH] Add AFTER_CLIENT_WORLD_CHANGE (#4173)

* add AFTER_CLIENT_WORLD_CHANGE

* fix

* move

* add description to README and change class to final with a private constructor

* revert the event name
---
 fabric-lifecycle-events-v1/README.md          |  5 ++
 .../event/lifecycle/v1/ClientWorldEvents.java | 48 +++++++++++++++++++
 .../client/MinecraftClientMixin.java          | 10 ++++
 .../client/ClientLifecycleTests.java          |  9 ++++
 4 files changed, 72 insertions(+)
 create mode 100644 fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/api/client/event/lifecycle/v1/ClientWorldEvents.java

diff --git a/fabric-lifecycle-events-v1/README.md b/fabric-lifecycle-events-v1/README.md
index 3911c28ee..979ff365e 100644
--- a/fabric-lifecycle-events-v1/README.md
+++ b/fabric-lifecycle-events-v1/README.md
@@ -62,6 +62,11 @@ Currently, this contains events related to when the Minecraft Client is starting
 Events related to ticking of a Minecraft client.
 There are events that indicate the beginning and end of the tick for the client and the `ClientWorld` if in game.
 
+## `ClientWorldEvents`
+
+Events related to the lifecycle a `ClientWorld`.
+Currently, this contains an event which is called after `ClientWorld` has been changed.
+
 ## `ClientChunkEvents`
 
 Events related to the lifecycle of chunks on a Minecraft client.
diff --git a/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/api/client/event/lifecycle/v1/ClientWorldEvents.java b/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/api/client/event/lifecycle/v1/ClientWorldEvents.java
new file mode 100644
index 000000000..332058177
--- /dev/null
+++ b/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/api/client/event/lifecycle/v1/ClientWorldEvents.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.api.client.event.lifecycle.v1;
+
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.world.ClientWorld;
+
+import net.fabricmc.fabric.api.event.Event;
+import net.fabricmc.fabric.api.event.EventFactory;
+
+public final class ClientWorldEvents {
+	private ClientWorldEvents() {
+	}
+
+	/**
+	 * An event which is called after the client world has been changed.
+	 */
+	public static final Event<AfterClientWorldChange> AFTER_CLIENT_WORLD_CHANGE = EventFactory.createArrayBacked(AfterClientWorldChange.class, callbacks -> (client, world) -> {
+		for (AfterClientWorldChange callback : callbacks) {
+			callback.afterWorldChange(client, world);
+		}
+	});
+
+	@FunctionalInterface
+	public interface AfterClientWorldChange {
+		/**
+		 * Called after the client world has been changed.
+		 *
+		 * @param client the client instance
+		 * @param world the new world instance
+		 */
+		void afterWorldChange(MinecraftClient client, ClientWorld world);
+	}
+}
diff --git a/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/mixin/event/lifecycle/client/MinecraftClientMixin.java b/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/mixin/event/lifecycle/client/MinecraftClientMixin.java
index e0277d6b5..f0e4a73f3 100644
--- a/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/mixin/event/lifecycle/client/MinecraftClientMixin.java
+++ b/fabric-lifecycle-events-v1/src/client/java/net/fabricmc/fabric/mixin/event/lifecycle/client/MinecraftClientMixin.java
@@ -22,9 +22,11 @@ import org.spongepowered.asm.mixin.injection.Inject;
 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
 
 import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.world.ClientWorld;
 
 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.event.lifecycle.v1.ClientWorldEvents;
 
 @Mixin(MinecraftClient.class)
 public abstract class MinecraftClientMixin {
@@ -48,4 +50,12 @@ public abstract class MinecraftClientMixin {
 	private void onStart(CallbackInfo ci) {
 		ClientLifecycleEvents.CLIENT_STARTED.invoker().onClientStarted((MinecraftClient) (Object) this);
 	}
+
+	@Inject(method = "setWorld", at = @At("TAIL"))
+	private void afterClientWorldChange(ClientWorld world, CallbackInfo ci) {
+		if (world != null) {
+			MinecraftClient client = (MinecraftClient) (Object) this;
+			ClientWorldEvents.AFTER_CLIENT_WORLD_CHANGE.invoker().afterWorldChange(client, world);
+		}
+	}
 }
diff --git a/fabric-lifecycle-events-v1/src/testmodClient/java/net/fabricmc/fabric/test/event/lifecycle/client/ClientLifecycleTests.java b/fabric-lifecycle-events-v1/src/testmodClient/java/net/fabricmc/fabric/test/event/lifecycle/client/ClientLifecycleTests.java
index 5d1f3f8eb..04d8cc728 100644
--- a/fabric-lifecycle-events-v1/src/testmodClient/java/net/fabricmc/fabric/test/event/lifecycle/client/ClientLifecycleTests.java
+++ b/fabric-lifecycle-events-v1/src/testmodClient/java/net/fabricmc/fabric/test/event/lifecycle/client/ClientLifecycleTests.java
@@ -16,10 +16,15 @@
 
 package net.fabricmc.fabric.test.event.lifecycle.client;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import net.fabricmc.api.ClientModInitializer;
 import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
+import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientWorldEvents;
 
 public final class ClientLifecycleTests implements ClientModInitializer {
+	private static final Logger LOGGER = LoggerFactory.getLogger(ClientLifecycleTests.class);
 	private boolean startCalled;
 	private boolean stopCalled;
 
@@ -44,5 +49,9 @@ public final class ClientLifecycleTests implements ClientModInitializer {
 			stopCalled = true;
 			System.out.println("Client has started stopping!");
 		});
+
+		ClientWorldEvents.AFTER_CLIENT_WORLD_CHANGE.register((client, world) -> {
+			LOGGER.info("Client world changed to {}", world.getRegistryKey().getValue());
+		});
 	}
 }