aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/moe/nea
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/moe/nea')
-rw-r--r--src/main/java/moe/nea/firmament/gui/config/storage/ArrayIndexedJsonPointer.kt17
-rw-r--r--src/main/java/moe/nea/firmament/gui/config/storage/ConfigEditor.kt104
-rw-r--r--src/main/java/moe/nea/firmament/gui/config/storage/ConfigFixEvent.kt38
-rw-r--r--src/main/java/moe/nea/firmament/gui/config/storage/JsonPointer.kt8
-rw-r--r--src/main/java/moe/nea/firmament/gui/config/storage/ObjectIndexedJsonPointer.kt17
-rw-r--r--src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java38
-rw-r--r--src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java75
-rw-r--r--src/main/java/moe/nea/firmament/init/EarlyRiser.java1
-rw-r--r--src/main/java/moe/nea/firmament/init/HandledScreenRiser.java113
-rw-r--r--src/main/java/moe/nea/firmament/init/Intermediary.java115
-rw-r--r--src/main/java/moe/nea/firmament/init/MixinPlugin.java103
-rw-r--r--src/main/java/moe/nea/firmament/init/RiserUtils.java7
-rw-r--r--src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java181
-rw-r--r--src/main/java/moe/nea/firmament/mixins/AppendRepoAsResourcePack.java26
-rw-r--r--src/main/java/moe/nea/firmament/mixins/BandAidResourcePackPatch.java10
-rw-r--r--src/main/java/moe/nea/firmament/mixins/ChatPeekScrollPatch.java27
-rw-r--r--src/main/java/moe/nea/firmament/mixins/ChatPeekingPatch.java6
-rw-r--r--src/main/java/moe/nea/firmament/mixins/CopyChatPatch.java45
-rw-r--r--src/main/java/moe/nea/firmament/mixins/CustomDurabilityBarPatch.java30
-rw-r--r--src/main/java/moe/nea/firmament/mixins/DFUEntityIdFixPatch.java8
-rw-r--r--src/main/java/moe/nea/firmament/mixins/DisableHurtCam.java18
-rw-r--r--src/main/java/moe/nea/firmament/mixins/DispatchMouseInputEventsPatch.java17
-rw-r--r--src/main/java/moe/nea/firmament/mixins/EarlyResourceReloadPatch.java14
-rw-r--r--src/main/java/moe/nea/firmament/mixins/EntityDespawnPatch.java6
-rw-r--r--src/main/java/moe/nea/firmament/mixins/EntityInteractEventPatch.java28
-rw-r--r--src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java58
-rw-r--r--src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java33
-rw-r--r--src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java26
-rw-r--r--src/main/java/moe/nea/firmament/mixins/HudRenderEventsPatch.java26
-rw-r--r--src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java24
-rw-r--r--src/main/java/moe/nea/firmament/mixins/KeyPressInWorldEventPatch.java21
-rw-r--r--src/main/java/moe/nea/firmament/mixins/LenientProfileComponentPatch.java25
-rw-r--r--src/main/java/moe/nea/firmament/mixins/MainWindowFirstLoadPatch.java10
-rw-r--r--src/main/java/moe/nea/firmament/mixins/MaintainKeyboardStatePatch.java17
-rw-r--r--src/main/java/moe/nea/firmament/mixins/MinecraftInitLevelListener.java26
-rw-r--r--src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java87
-rw-r--r--src/main/java/moe/nea/firmament/mixins/MixinPlayerScreenHandler.java31
-rw-r--r--src/main/java/moe/nea/firmament/mixins/MixinRecipeBookScreen.java16
-rw-r--r--src/main/java/moe/nea/firmament/mixins/MousePressInWorldEventPatch.java22
-rw-r--r--src/main/java/moe/nea/firmament/mixins/OutgoingPacketEventPatch.java8
-rw-r--r--src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java32
-rw-r--r--src/main/java/moe/nea/firmament/mixins/PropertySignatureIgnorePatch.java36
-rw-r--r--src/main/java/moe/nea/firmament/mixins/ResourceReloaderRegistrationPatch.java14
-rw-r--r--src/main/java/moe/nea/firmament/mixins/SaveCursorPositionPatch.java50
-rw-r--r--src/main/java/moe/nea/firmament/mixins/SaveOriginalCommandTreePacket.java10
-rw-r--r--src/main/java/moe/nea/firmament/mixins/ScreenChangeEventPatch.java10
-rw-r--r--src/main/java/moe/nea/firmament/mixins/ScreenInputEvents.java34
-rw-r--r--src/main/java/moe/nea/firmament/mixins/SlotClickEventPatch.java23
-rw-r--r--src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java48
-rw-r--r--src/main/java/moe/nea/firmament/mixins/SoundReceiveEventPatch.java36
-rw-r--r--src/main/java/moe/nea/firmament/mixins/ToggleSprintPatch.java8
-rw-r--r--src/main/java/moe/nea/firmament/mixins/TolerateFirmamentTolerateRegistryOwners.java8
-rw-r--r--src/main/java/moe/nea/firmament/mixins/WorldReadyEventPatch.java7
-rw-r--r--src/main/java/moe/nea/firmament/mixins/WorldRenderLastEventPatch.java42
-rw-r--r--src/main/java/moe/nea/firmament/mixins/accessor/AccessorAbstractClientPlayerEntity.java10
-rw-r--r--src/main/java/moe/nea/firmament/mixins/accessor/AccessorChatHud.java20
-rw-r--r--src/main/java/moe/nea/firmament/mixins/accessor/AccessorHandledScreen.java28
-rw-r--r--src/main/java/moe/nea/firmament/mixins/accessor/AccessorNbtComponent.java12
-rw-r--r--src/main/java/moe/nea/firmament/mixins/accessor/AccessorPlayerListHud.java31
-rw-r--r--src/main/java/moe/nea/firmament/mixins/accessor/AccessorScreenHandler.java12
-rw-r--r--src/main/java/moe/nea/firmament/mixins/accessor/AccessorWorldRenderer.java17
-rw-r--r--src/main/java/moe/nea/firmament/mixins/customgui/OriginalSlotCoords.java2
-rw-r--r--src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java114
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/DisableCommonPacketWarnings.java20
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/DisableInvalidFishingHook.java6
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java8
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/IdentifyCloser.java2
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/IdentifyStopperPatch.java17
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/MixinKeyboard.java10
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/MixinScoreboard.java4
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/WarnForUnknownCustomPayloadSends.java8
-rw-r--r--src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java14
-rw-r--r--src/main/java/moe/nea/firmament/mixins/feature/DisableSlotHighlights.java25
-rw-r--r--src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeFeatureRenderer.java49
-rw-r--r--src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeStorage.java23
-rw-r--r--src/main/java/moe/nea/firmament/mixins/render/IncreaseStackLimitSizeInDrawContext.java20
-rw-r--r--src/main/java/moe/nea/firmament/mixins/render/entitytints/ChangeColorOfLivingEntities.java65
-rw-r--r--src/main/java/moe/nea/firmament/mixins/render/entitytints/EntityRenderStateTint.java55
-rw-r--r--src/main/java/moe/nea/firmament/mixins/render/entitytints/InjectIntoRenderState.java30
-rw-r--r--src/main/java/moe/nea/firmament/mixins/render/entitytints/ReplaceOverlayTexture.java24
-rw-r--r--src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableEquipmentRenderer.java34
-rw-r--r--src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableHeadFeatureRenderer.java26
-rw-r--r--src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableItemRenderer.java26
-rw-r--r--src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableSkullBlockEntityRenderer.java25
-rw-r--r--src/main/java/moe/nea/firmament/mixins/render/renderer/MultipleSpecialGuiRenderStates.java68
-rw-r--r--src/main/java/moe/nea/firmament/repo/EnchantedBookCache.kt16
-rw-r--r--src/main/java/moe/nea/firmament/util/data/ManagedConfig.kt292
87 files changed, 2108 insertions, 845 deletions
diff --git a/src/main/java/moe/nea/firmament/gui/config/storage/ArrayIndexedJsonPointer.kt b/src/main/java/moe/nea/firmament/gui/config/storage/ArrayIndexedJsonPointer.kt
new file mode 100644
index 0000000..1e204d6
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/gui/config/storage/ArrayIndexedJsonPointer.kt
@@ -0,0 +1,17 @@
+package moe.nea.firmament.gui.config.storage
+
+import com.google.gson.JsonArray
+import com.google.gson.JsonElement
+
+data class ArrayIndexedJsonPointer(
+ val owner: JsonArray,
+ val index: Int
+) : JsonPointer {
+ override fun get(): JsonElement {
+ return owner.get(index)
+ }
+
+ override fun set(value: JsonElement) {
+ owner.set(index, value)
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/gui/config/storage/ConfigEditor.kt b/src/main/java/moe/nea/firmament/gui/config/storage/ConfigEditor.kt
new file mode 100644
index 0000000..df1ed33
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/gui/config/storage/ConfigEditor.kt
@@ -0,0 +1,104 @@
+package moe.nea.firmament.gui.config.storage
+
+import com.google.gson.JsonArray
+import com.google.gson.JsonObject
+import kotlinx.serialization.json.JsonElement
+import moe.nea.firmament.util.json.intoGson
+import moe.nea.firmament.util.json.intoKotlinJson
+
+data class ConfigEditor(
+ val roots: List<JsonPointer>,
+) {
+ fun transform(transform: (JsonElement) -> JsonElement) {
+ roots.forEach { root ->
+ root.set(transform(root.get().intoKotlinJson()).intoGson())
+ }
+ }
+
+ fun move(fromPath: String, toPath: String) {
+ if (fromPath == toPath) return
+ val fromSegments = fromPath.split(".").filter { it.isNotEmpty() }
+ val toSegments = toPath.split(".").filter { it.isNotEmpty() }
+ roots.forEach { root ->
+ var fp = root.get()
+ if (fromSegments.isEmpty()) {
+ root.set(JsonObject())
+ } else {
+ fromSegments.dropLast(1).forEach {
+ fp = (fp as JsonObject)[it] ?: return@forEach // todo warn if we dont find the object maybe
+ }
+ fp as JsonObject
+ fp = fp.remove(fromSegments.last())?.deepCopy() ?: return@forEach // in theory i don't need to deepcopy but fuck theory
+ }
+ if (toSegments.isEmpty()) {
+ root.set(fp)
+ } else {
+ var lp = root.get()
+ toSegments.dropLast(1).forEach { name ->
+ val parent = lp as JsonObject
+ var child = parent[name]
+ if (child == null) {
+ child = JsonObject()
+ parent.add(name, child)
+ }
+ lp = child
+ }
+ lp as JsonObject
+ if (lp.has(toSegments.last())) {
+ error("Cannot overwrite $lp.${toSegments.last()} with $fp")
+ }
+ lp.add(toSegments.last(), fp)
+ }
+ }
+ }
+
+ fun at(path: String, block: ConfigEditor.() -> Unit) {
+ block(at(path))
+ }
+
+ fun at(path: String): ConfigEditor {
+ var lastRoots = roots
+ for (segment in path.split(".")) {
+ if (segment.isEmpty()) {
+ continue
+ } else if (segment == "*") {
+ lastRoots = lastRoots.flatMap { root ->
+ when (val ele = root.get()) {
+ is JsonObject -> {
+ ele.entrySet().map {
+ (ObjectIndexedJsonPointer(ele, it.key))
+ }
+ }
+
+ is JsonArray -> {
+ (0..<ele.size()).map {
+ (ArrayIndexedJsonPointer(ele, it))
+ }
+ }
+
+ else -> {
+ error("Cannot expand a json primitive $ele at $path")
+ }
+ }
+ }
+ } else {
+ lastRoots = lastRoots.map { root ->
+ when (val ele = root.get()) {
+ is JsonObject -> {
+ ObjectIndexedJsonPointer(ele, segment)
+ }
+
+ is JsonArray -> {
+ ArrayIndexedJsonPointer(ele, segment.toInt())
+ }
+
+ else -> {
+ error("Cannot expand a json primitive $ele at $path")
+ }
+ }
+ }
+ }
+ }
+ return ConfigEditor(lastRoots)
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/gui/config/storage/ConfigFixEvent.kt b/src/main/java/moe/nea/firmament/gui/config/storage/ConfigFixEvent.kt
new file mode 100644
index 0000000..07148d5
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/gui/config/storage/ConfigFixEvent.kt
@@ -0,0 +1,38 @@
+package moe.nea.firmament.gui.config.storage
+
+import com.google.gson.JsonElement
+import com.google.gson.JsonObject
+import moe.nea.firmament.events.FirmamentEvent
+import moe.nea.firmament.events.FirmamentEventBus
+
+data class ConfigFixEvent(
+ val storageClass: ConfigStorageClass,
+ val toVersion: Int,
+ var data: JsonObject,
+) : FirmamentEvent() {
+ companion object : FirmamentEventBus<ConfigFixEvent>() {
+
+ }
+ fun on(
+ toVersion: Int,
+ storageClass: ConfigStorageClass,
+ block: ConfigEditor.() -> Unit
+ ) {
+ require(toVersion <= FirmamentConfigLoader.currentConfigVersion)
+ if (this.toVersion == toVersion && this.storageClass == storageClass) {
+ block(ConfigEditor(listOf(object : JsonPointer {
+ override fun get(): JsonObject {
+ return data
+ }
+
+ override fun set(value: JsonElement) {
+ data = value as JsonObject
+ }
+
+ override fun toString(): String {
+ return "ConfigRoot($storageClass)"
+ }
+ })))
+ }
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/gui/config/storage/JsonPointer.kt b/src/main/java/moe/nea/firmament/gui/config/storage/JsonPointer.kt
new file mode 100644
index 0000000..e34c312
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/gui/config/storage/JsonPointer.kt
@@ -0,0 +1,8 @@
+package moe.nea.firmament.gui.config.storage
+
+import com.google.gson.JsonElement
+
+interface JsonPointer {
+ fun get(): JsonElement
+ fun set(value: JsonElement)
+}
diff --git a/src/main/java/moe/nea/firmament/gui/config/storage/ObjectIndexedJsonPointer.kt b/src/main/java/moe/nea/firmament/gui/config/storage/ObjectIndexedJsonPointer.kt
new file mode 100644
index 0000000..091275d
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/gui/config/storage/ObjectIndexedJsonPointer.kt
@@ -0,0 +1,17 @@
+package moe.nea.firmament.gui.config.storage
+
+import com.google.gson.JsonElement
+import com.google.gson.JsonObject
+
+data class ObjectIndexedJsonPointer(
+ val owner: JsonObject,
+ val name: String
+) : JsonPointer {
+ override fun get(): JsonElement {
+ return owner.get(name)
+ }
+
+ override fun set(value: JsonElement) {
+ owner.add(name, value)
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java b/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java
index 0713068..07e4549 100644
--- a/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java
+++ b/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java
@@ -1,6 +1,9 @@
package moe.nea.firmament.init;
+import moe.nea.firmament.util.ErrorUtil;
+import moe.nea.firmament.util.compatloader.ICompatMeta;
+
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
@@ -24,6 +27,8 @@ public class AutoDiscoveryPlugin {
return mixins.stream().map(it -> defaultName + "." + it).toList();
}
+ // TODO: remove println
+
private static final List<AutoDiscoveryPlugin> mixinPlugins = new ArrayList<>();
public static List<AutoDiscoveryPlugin> getMixinPlugins() {
@@ -94,7 +99,7 @@ public class AutoDiscoveryPlugin {
String norm = (className.substring(0, className.length() - ".class".length()))
.replace("\\", "/")
.replace("/", ".");
- if (norm.startsWith(getMixinPackage() + ".") && !norm.endsWith(".")) {
+ if (norm.startsWith(getMixinPackage() + ".") && !norm.endsWith(".") && ICompatMeta.Companion.shouldLoad(norm)) {
mixins.add(norm.substring(getMixinPackage().length() + 1));
}
}
@@ -125,24 +130,25 @@ public class AutoDiscoveryPlugin {
*/
public List<String> getMixins() {
if (mixins != null) return mixins;
- System.out.println("Trying to discover mixins");
- mixins = new ArrayList<>();
- URL classUrl = getClass().getProtectionDomain().getCodeSource().getLocation();
- System.out.println("Found classes at " + classUrl);
- tryDiscoverFromContentFile(classUrl);
- var classRoots = System.getProperty("firmament.classroots");
- if (classRoots != null && !classRoots.isBlank()) {
- System.out.println("Found firmament class roots: " + classRoots);
- for (String s : classRoots.split(File.pathSeparator)) {
- if (s.isBlank()) {
- continue;
- }
- try {
+ try {
+ System.out.println("Trying to discover mixins");
+ mixins = new ArrayList<>();
+ URL classUrl = getClass().getProtectionDomain().getCodeSource().getLocation();
+ System.out.println("Found classes at " + classUrl);
+ tryDiscoverFromContentFile(classUrl);
+ var classRoots = System.getProperty("firmament.classroots");
+ if (classRoots != null && !classRoots.isBlank()) {
+ System.out.println("Found firmament class roots: " + classRoots);
+ for (String s : classRoots.split(File.pathSeparator)) {
+ if (s.isBlank()) {
+ continue;
+ }
tryDiscoverFromContentFile(new File(s).toURI().toURL());
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
}
}
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(1);
}
return mixins;
}
diff --git a/src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java b/src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java
deleted file mode 100644
index d60e3e7..0000000
--- a/src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package moe.nea.firmament.init;
-
-import me.shedaniel.mm.api.ClassTinkerers;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.tree.ClassNode;
-import org.objectweb.asm.tree.InsnNode;
-import org.objectweb.asm.tree.MethodInsnNode;
-import org.objectweb.asm.tree.MethodNode;
-import org.objectweb.asm.tree.VarInsnNode;
-
-import java.lang.reflect.Modifier;
-import java.util.Objects;
-
-public class ClientPlayerRiser extends RiserUtils {
- @IntermediaryName(net.minecraft.entity.player.PlayerEntity.class)
- String PlayerEntity;
- @IntermediaryName(net.minecraft.world.World.class)
- String World;
- String GameProfile = "com.mojang.authlib.GameProfile";
- @IntermediaryName(net.minecraft.util.math.BlockPos.class)
- String BlockPos;
- @IntermediaryName(net.minecraft.client.network.AbstractClientPlayerEntity.class)
- String AbstractClientPlayerEntity;
- String GuiPlayer = "moe.nea.firmament.gui.entity.GuiPlayer";
- // World world, BlockPos pos, float yaw, GameProfile gameProfile
- Type constructorDescriptor = Type.getMethodType(Type.VOID_TYPE, getTypeForClassName(World), getTypeForClassName(BlockPos), Type.FLOAT_TYPE, getTypeForClassName(GameProfile));
-
-
- private void mapClassNode(ClassNode classNode, Type superClass) {
- for (MethodNode method : classNode.methods) {
- if (Objects.equals(method.name, "<init>") && Type.getMethodType(method.desc).equals(constructorDescriptor)) {
- modifyConstructor(method, superClass);
- return;
- }
- }
- var node = new MethodNode(Opcodes.ASM9, "<init>", constructorDescriptor.getDescriptor(), null, null);
- classNode.methods.add(node);
- modifyConstructor(node, superClass);
- }
-
-
- private void modifyConstructor(MethodNode method, Type superClass) {
- method.access = (method.access | Modifier.PUBLIC) & ~Modifier.PRIVATE & ~Modifier.PROTECTED;
- if (method.instructions.size() != 0) return; // Some other mod has already made a constructor here
-
- // World world, BlockPos pos, float yaw, GameProfile gameProfile
- // ALOAD this
- method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
-
- // ALOAD World
- method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
-
- // ALOAD BlockPos
- method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2));
-
- // ALOAD yaw
- method.instructions.add(new VarInsnNode(Opcodes.FLOAD, 3));
-
- // ALOAD gameProfile
- method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 4));
-
- // Call super
- method.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, superClass.getInternalName(), "<init>", constructorDescriptor.getDescriptor(), false));
-
- // Return
- method.instructions.add(new InsnNode(Opcodes.RETURN));
- }
-
- @Override
- public void addTinkerers() {
- ClassTinkerers.addTransformation(AbstractClientPlayerEntity, it -> mapClassNode(it, getTypeForClassName(PlayerEntity)), true);
- ClassTinkerers.addTransformation(GuiPlayer, it -> mapClassNode(it, getTypeForClassName(AbstractClientPlayerEntity)), true);
- }
-}
diff --git a/src/main/java/moe/nea/firmament/init/EarlyRiser.java b/src/main/java/moe/nea/firmament/init/EarlyRiser.java
index 5441255..ae26bd7 100644
--- a/src/main/java/moe/nea/firmament/init/EarlyRiser.java
+++ b/src/main/java/moe/nea/firmament/init/EarlyRiser.java
@@ -4,7 +4,6 @@ package moe.nea.firmament.init;
public class EarlyRiser implements Runnable {
@Override
public void run() {
- new ClientPlayerRiser().addTinkerers();
new HandledScreenRiser().addTinkerers();
new SectionBuilderRiser().addTinkerers();
// TODO: new ItemColorsSodiumRiser().addTinkerers();
diff --git a/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java b/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java
index f7db18c..98be517 100644
--- a/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java
+++ b/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java
@@ -2,7 +2,13 @@
package moe.nea.firmament.init;
import me.shedaniel.mm.api.ClassTinkerers;
-import net.minecraft.client.gui.Element;
+import net.minecraft.client.gui.components.events.AbstractContainerEventHandler;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
+import net.minecraft.client.input.CharacterEvent;
+import net.minecraft.client.input.KeyEvent;
+import net.minecraft.client.input.MouseButtonEvent;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
@@ -19,30 +25,46 @@ import java.lang.reflect.Modifier;
import java.util.function.Consumer;
public class HandledScreenRiser extends RiserUtils {
- @IntermediaryName(net.minecraft.client.gui.screen.Screen.class)
- String Screen;
- @IntermediaryName(net.minecraft.client.gui.screen.ingame.HandledScreen.class)
- String HandledScreen;
- Type mouseScrolledDesc = Type.getMethodType(Type.BOOLEAN_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE);
- String mouseScrolled = remapper.mapMethodName("intermediary", "net.minecraft.class_364", "method_25401",
- mouseScrolledDesc.getDescriptor());
- // boolean keyReleased(int keyCode, int scanCode, int modifiers)
- Type keyReleasedDesc = Type.getMethodType(Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.INT_TYPE);
- String keyReleased = remapper.mapMethodName("intermediary", Intermediary.<Element>className(),
- Intermediary.methodName(Element::keyReleased),
- keyReleasedDesc.getDescriptor());
- // public boolean charTyped(char chr, int modifiers)
- Type charTypedDesc = Type.getMethodType(Type.BOOLEAN_TYPE, Type.CHAR_TYPE, Type.INT_TYPE);
- String charTyped = remapper.mapMethodName("intermediary", Intermediary.<Element>className(),
- Intermediary.methodName(Element::charTyped),
- charTypedDesc.getDescriptor());
+ Intermediary.InterClass Screen = Intermediary.<Screen>intermediaryClass();
+ Intermediary.InterClass KeyInput = Intermediary.<KeyEvent>intermediaryClass();
+ Intermediary.InterClass CharInput = Intermediary.<CharacterEvent>intermediaryClass();
+ Intermediary.InterClass HandledScreen = Intermediary.<AbstractContainerScreen>intermediaryClass();
+ Intermediary.InterClass AbstractContainerEventHandler = Intermediary.<AbstractContainerEventHandler>intermediaryClass();
+ Intermediary.InterClass MouseButtonEvent = Intermediary.<MouseButtonEvent>intermediaryClass();
+ Intermediary.InterMethod mouseScrolled = Intermediary.intermediaryMethod(
+ GuiEventListener::mouseScrolled,
+ Intermediary.ofClass(boolean.class),
+ Intermediary.ofClass(double.class),
+ Intermediary.ofClass(double.class),
+ Intermediary.ofClass(double.class),
+ Intermediary.ofClass(double.class)
+ );
+ Intermediary.InterMethod mouseClickedScreen = Intermediary.intermediaryMethod(
+ //onMouseClicked$firmament
+ GuiEventListener::mouseClicked,
+ Intermediary.ofClass(boolean.class),
+ MouseButtonEvent,
+ Intermediary.ofClass(boolean.class)
+ );
+ ;
+ Intermediary.InterMethod keyReleased = Intermediary.intermediaryMethod(
+ GuiEventListener::keyReleased,
+ Intermediary.ofClass(boolean.class),
+ KeyInput
+ );
+ Intermediary.InterMethod charTyped = Intermediary.intermediaryMethod(
+ GuiEventListener::charTyped,
+ Intermediary.ofClass(boolean.class),
+ CharInput
+ );
@Override
public void addTinkerers() {
- ClassTinkerers.addTransformation(HandledScreen, this::addMouseScroll, true);
- ClassTinkerers.addTransformation(HandledScreen, this::addKeyReleased, true);
- ClassTinkerers.addTransformation(HandledScreen, this::addCharTyped, true);
+ addTransformation(HandledScreen, this::addMouseScroll, true);
+ addTransformation(HandledScreen, this::addKeyReleased, true);
+ addTransformation(HandledScreen, this::addCharTyped, true);
+ addTransformation(Screen, this::addMouseClicked, true);
}
/**
@@ -56,8 +78,8 @@ public class HandledScreenRiser extends RiserUtils {
* @param insertInvoke insert the invokevirtual/invokestatic call
*/
void insertTrueHandler(MethodNode node,
- Consumer<InsnList> insertLoads,
- Consumer<InsnList> insertInvoke) {
+ Consumer<InsnList> insertLoads,
+ Consumer<InsnList> insertInvoke) {
var insns = new InsnList();
insertLoads.accept(insns);
@@ -76,26 +98,39 @@ public class HandledScreenRiser extends RiserUtils {
void addKeyReleased(ClassNode classNode) {
addSuperInjector(
- classNode, keyReleased, keyReleasedDesc, "keyReleased_firmament",
+ classNode, keyReleased.mapped(), keyReleased.mappedDesc(), HandledScreen, Screen, "keyReleased_firmament",
insns -> {
// ALOAD 0, load this
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
- // ILOAD 1-3, load args
- insns.add(new VarInsnNode(Opcodes.ILOAD, 1));
- insns.add(new VarInsnNode(Opcodes.ILOAD, 2));
- insns.add(new VarInsnNode(Opcodes.ILOAD, 3));
+ // ALOAD 1, load args
+ insns.add(new VarInsnNode(Opcodes.ALOAD, 1));
});
}
+ void addMouseClicked(ClassNode classNode) {
+ addSuperInjector(
+ classNode, mouseClickedScreen.mapped(), mouseClickedScreen.mappedDesc(),
+ Screen, AbstractContainerEventHandler, "onMouseClicked$firmament",
+ insns -> {
+ // load this
+ insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
+ // load mouse event
+ insns.add(new VarInsnNode(Opcodes.ALOAD, 1));
+ // load doubled
+ insns.add(new VarInsnNode(Opcodes.ILOAD, 2));
+ }
+ );
+ }
+
void addCharTyped(ClassNode classNode) {
addSuperInjector(
- classNode, charTyped, charTypedDesc, "charTyped_firmament",
+ classNode, charTyped.mapped(), charTyped.mappedDesc(),
+ HandledScreen, Screen, "charTyped_firmament",
insns -> {
// ALOAD 0, load this
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
- // ILOAD 1-2, load args. chars = ints
- insns.add(new VarInsnNode(Opcodes.ILOAD, 1));
- insns.add(new VarInsnNode(Opcodes.ILOAD, 2));
+ // ALOAD 1, load args
+ insns.add(new VarInsnNode(Opcodes.ALOAD, 1));
});
}
@@ -103,6 +138,8 @@ public class HandledScreenRiser extends RiserUtils {
ClassNode classNode,
String name,
Type desc,
+ Intermediary.InterClass currentClass,
+ Intermediary.InterClass parentClass,
String firmamentName,
Consumer<InsnList> loadArgs
) {
@@ -118,8 +155,8 @@ public class HandledScreenRiser extends RiserUtils {
var insns = keyReleasedNode.instructions;
loadArgs.accept(insns);
// INVOKESPECIAL call super method
- insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, getTypeForClassName(Screen).getInternalName(),
- name, desc.getDescriptor()));
+ insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, parentClass.mapped().getInternalName(),
+ name, desc.getDescriptor()));
// IRETURN return int on stack (booleans are int at runtime)
insns.add(new InsnNode(Opcodes.IRETURN));
classNode.methods.add(keyReleasedNode);
@@ -127,16 +164,16 @@ public class HandledScreenRiser extends RiserUtils {
insertTrueHandler(keyReleasedNode, loadArgs, insns -> {
// INVOKEVIRTUAL call custom handler
insns.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
- getTypeForClassName(HandledScreen).getInternalName(),
- firmamentName,
- desc.getDescriptor()));
+ currentClass.mapped().getInternalName(),
+ firmamentName,
+ desc.getDescriptor()));
});
}
void addMouseScroll(ClassNode classNode) {
addSuperInjector(
- classNode, mouseScrolled, mouseScrolledDesc, "mouseScrolled_firmament",
+ classNode, mouseScrolled.mapped(), mouseScrolled.mappedDesc(), HandledScreen, Screen, "mouseScrolled_firmament",
insns -> {
// ALOAD 0, load this
insns.add(new VarInsnNode(Opcodes.ALOAD, 0));
diff --git a/src/main/java/moe/nea/firmament/init/Intermediary.java b/src/main/java/moe/nea/firmament/init/Intermediary.java
index 61494d7..3513a6b 100644
--- a/src/main/java/moe/nea/firmament/init/Intermediary.java
+++ b/src/main/java/moe/nea/firmament/init/Intermediary.java
@@ -7,57 +7,66 @@ import org.objectweb.asm.Type;
import java.util.List;
public class Intermediary {
- private static final MappingResolver RESOLVER = FabricLoader.getInstance().getMappingResolver();
-
- static String methodName(Object object) {
- throw new AssertionError("Cannot be called at runtime");
- }
-
- static <T> String className() {
- throw new AssertionError("Cannot be called at runtime");
- }
-
- static String id(String source) {
- return source;
- }
-
-// public record Class(
-// Type intermediaryClass
-// ) {
-// public Class(String intermediaryClass) {
-// this(Type.getObjectType(intermediaryClass.replace('.', '/')));
-// }
-//
-// public String getMappedName() {
-// return RESOLVER.mapClassName("intermediary", intermediaryClass.getInternalName()
-// .replace('/', '.'));
-// }
-// }
-//
-// public record Method(
-// Type intermediaryClassName,
-// String intermediaryMethodName,
-// Type intermediaryReturnType,
-// List<Type> intermediaryArgumentTypes
-// ) {
-// public Method(
-// String intermediaryClassName,
-// String intermediaryMethodName,
-// String intermediaryReturnType,
-// String... intermediaryArgumentTypes
-// ) {
-// this(intermediaryClassName, intermediaryMethodName, intermediaryReturnType, List.of(intermediaryArgumentTypes));
-// }
-//
-// public String getMappedMethodName() {
-// return RESOLVER.mapMethodName("intermediary",
-// intermediaryClassName.getInternalName().replace('/', '.'));
-// }
-//
-// public Type getIntermediaryDescriptor() {
-// return Type.getMethodType(intermediaryReturnType, intermediaryArgumentTypes.toArray(Type[]::new));
-// }
-//
-//
-// }
+ private static final MappingResolver RESOLVER = FabricLoader.getInstance().getMappingResolver();
+
+ static InterMethod intermediaryMethod(Object object, InterClass returnType, InterClass... args) {
+ throw new AssertionError("Cannot be called at runtime");
+ }
+
+ static <T> InterClass intermediaryClass() {
+ throw new AssertionError("Cannot be called at runtime");
+ }
+
+ public static InterClass ofIntermediaryClass(String interClass) {
+ return new InterClass(Type.getObjectType(interClass.replace('.', '/')));
+ }
+
+ public static InterClass ofClass(Class<?> unmappedClass) {
+ return new InterClass(Type.getType(unmappedClass));
+ }
+
+ public static InterMethod ofMethod(String intermediary, String ownerType, InterClass returnType, InterClass... argTypes) {
+ return new InterMethod(intermediary, ofIntermediaryClass(ownerType), returnType, List.of(argTypes));
+ }
+
+ public record InterClass(
+ Type intermediary
+ ) {
+ public Type mapped() {
+ if (intermediary().getSort() != Type.OBJECT)
+ return intermediary();
+ return Type.getObjectType(RESOLVER.mapClassName("intermediary", intermediary().getClassName())
+ .replace('.', '/'));
+ }
+ }
+
+ public record InterMethod(
+ String intermediary,
+ InterClass ownerType,
+ InterClass returnType,
+ List<InterClass> argumentTypes
+ ) {
+ public Type intermediaryDesc() {
+ return Type.getMethodType(
+ returnType.intermediary(),
+ argumentTypes().stream().map(InterClass::intermediary).toArray(Type[]::new)
+ );
+ }
+
+ public Type mappedDesc() {
+ return Type.getMethodType(
+ returnType.mapped(),
+ argumentTypes().stream().map(InterClass::mapped).toArray(Type[]::new)
+ );
+ }
+
+ public String mapped() {
+ return RESOLVER.mapMethodName(
+ "intermediary",
+ ownerType.intermediary().getClassName(),
+ intermediary(),
+ intermediaryDesc().getDescriptor()
+ );
+ }
+ }
}
diff --git a/src/main/java/moe/nea/firmament/init/MixinPlugin.java b/src/main/java/moe/nea/firmament/init/MixinPlugin.java
index 61e8f14..d48139b 100644
--- a/src/main/java/moe/nea/firmament/init/MixinPlugin.java
+++ b/src/main/java/moe/nea/firmament/init/MixinPlugin.java
@@ -8,54 +8,69 @@ import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class MixinPlugin implements IMixinConfigPlugin {
- AutoDiscoveryPlugin autoDiscoveryPlugin = new AutoDiscoveryPlugin();
- public static String mixinPackage;
- @Override
- public void onLoad(String mixinPackage) {
- MixinExtrasBootstrap.init();
- MixinPlugin.mixinPackage = mixinPackage;
- autoDiscoveryPlugin.setMixinPackage(mixinPackage);
- }
-
- @Override
- public String getRefMapperConfig() {
- return null;
- }
-
- @Override
- public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
- if (!Boolean.getBoolean("firmament.debug") && mixinClassName.contains("devenv.")) {
- return false;
- }
- return true;
- }
-
- @Override
- public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
-
- }
-
- @Override
- public List<String> getMixins() {
- return autoDiscoveryPlugin.getMixins().stream().filter(it -> this.shouldApplyMixin(null, it))
- .toList();
- }
-
- @Override
- public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
-
- }
-
- public static List<String> appliedMixins = new ArrayList<>();
-
- @Override
- public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
- appliedMixins.add(mixinClassName);
- }
+ AutoDiscoveryPlugin autoDiscoveryPlugin = new AutoDiscoveryPlugin();
+ public static List<MixinPlugin> instances = new ArrayList<>();
+ public String mixinPackage;
+
+ @Override
+ public void onLoad(String mixinPackage) {
+ MixinExtrasBootstrap.init();
+ instances.add(this);
+ this.mixinPackage = mixinPackage;
+ autoDiscoveryPlugin.setMixinPackage(mixinPackage);
+ }
+
+ @Override
+ public String getRefMapperConfig() {
+ return null;
+ }
+
+ @Override
+ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
+ if (!Boolean.getBoolean("firmament.debug") && mixinClassName.contains("devenv.")) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
+
+ }
+
+ @Override
+ public List<String> getMixins() {
+ return autoDiscoveryPlugin.getMixins().stream().filter(it -> this.shouldApplyMixin(null, it))
+ .toList();
+ }
+
+ @Override
+ public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
+
+ }
+
+ public Set<String> getAppliedFullPathMixins() {
+ return new HashSet<>(appliedMixins);
+ }
+
+ public Set<String> getExpectedFullPathMixins() {
+ return getMixins()
+ .stream()
+ .map(it -> mixinPackage + "." + it)
+ .collect(Collectors.toSet());
+ }
+
+ public List<String> appliedMixins = new ArrayList<>();
+
+ @Override
+ public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
+ appliedMixins.add(mixinClassName);
+ }
}
diff --git a/src/main/java/moe/nea/firmament/init/RiserUtils.java b/src/main/java/moe/nea/firmament/init/RiserUtils.java
index c1c8fd1..ad4ac8f 100644
--- a/src/main/java/moe/nea/firmament/init/RiserUtils.java
+++ b/src/main/java/moe/nea/firmament/init/RiserUtils.java
@@ -1,12 +1,15 @@
package moe.nea.firmament.init;
+import me.shedaniel.mm.api.ClassTinkerers;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.MappingResolver;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
+import java.util.function.Consumer;
+
public abstract class RiserUtils {
protected Type getTypeForClassName(String className) {
return Type.getObjectType(className.replace('.', '/'));
@@ -24,4 +27,8 @@ public abstract class RiserUtils {
return null;
}
+ public void addTransformation(Intermediary.InterClass interClass, Consumer<ClassNode> transformer, boolean post) {
+ ClassTinkerers.addTransformation(interClass.mapped().getClassName(), transformer, post);
+ }
+
}
diff --git a/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java b/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java
index f2c6c53..a5d5c1d 100644
--- a/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java
+++ b/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java
@@ -1,13 +1,11 @@
package moe.nea.firmament.init;
-import me.shedaniel.mm.api.ClassTinkerers;
import net.fabricmc.loader.api.FabricLoader;
-import net.minecraft.block.BlockState;
-import net.minecraft.client.render.block.BlockModels;
-import net.minecraft.client.render.block.BlockRenderManager;
-import net.minecraft.client.render.chunk.SectionBuilder;
-import net.minecraft.client.render.model.BakedModel;
-import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.client.renderer.block.BlockRenderDispatcher;
+import net.minecraft.client.renderer.chunk.SectionCompiler;
+import net.minecraft.client.renderer.block.model.BlockStateModel;
+import net.minecraft.core.BlockPos;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
@@ -20,98 +18,89 @@ import org.objectweb.asm.tree.VarInsnNode;
public class SectionBuilderRiser extends RiserUtils {
- @IntermediaryName(SectionBuilder.class)
- String SectionBuilder;
- @IntermediaryName(BlockPos.class)
- String BlockPos;
- @IntermediaryName(BlockRenderManager.class)
- String BlockRenderManager;
- @IntermediaryName(BlockState.class)
- String BlockState;
- @IntermediaryName(BakedModel.class)
- String BakedModel;
- String CustomBlockTextures = "moe.nea.firmament.features.texturepack.CustomBlockTextures";
+ Intermediary.InterClass SectionBuilder = Intermediary.<SectionCompiler>intermediaryClass();
+ Intermediary.InterClass BlockPos = Intermediary.<BlockPos>intermediaryClass();
+ Intermediary.InterClass BlockRenderManager = Intermediary.<BlockRenderDispatcher>intermediaryClass();
+ Intermediary.InterClass BlockState = Intermediary.<BlockState>intermediaryClass();
+ Intermediary.InterClass BlockStateModel = Intermediary.<BlockStateModel>intermediaryClass();
+ String CustomBlockTextures = "moe.nea.firmament.features.texturepack.CustomBlockTextures";
- Type getModelDesc = Type.getMethodType(
- getTypeForClassName(BlockRenderManager),
- getTypeForClassName(BlockState)
- );
- String getModel = remapper.mapMethodName(
- "intermediary",
- Intermediary.<BlockRenderManager>className(),
- Intermediary.methodName(net.minecraft.client.render.block.BlockRenderManager::getModel),
- Type.getMethodDescriptor(
- getTypeForClassName(Intermediary.<BakedModel>className()),
- getTypeForClassName(Intermediary.<BlockState>className())
- )
- );
+ Intermediary.InterMethod getModel =
+ Intermediary.intermediaryMethod(
+ net.minecraft.client.renderer.block.BlockRenderDispatcher::getBlockModel,
+ BlockStateModel,
+ BlockState
+ );
- @Override
- public void addTinkerers() {
- if (FabricLoader.getInstance().isModLoaded("fabric-renderer-indigo"))
- ClassTinkerers.addTransformation(SectionBuilder, this::handle, true);
- }
+ @Override
+ public void addTinkerers() {
+ if (FabricLoader.getInstance().isModLoaded("fabric-renderer-indigo"))
+ addTransformation(SectionBuilder, this::handle, true);
+ }
- private void handle(ClassNode classNode) {
- for (MethodNode method : classNode.methods) {
- if ((method.name.endsWith("$fabric-renderer-indigo$hookBuildRenderBlock")
- || method.name.endsWith("$fabric-renderer-indigo$hookChunkBuildTessellate")) &&
- method.name.startsWith("redirect$")) {
- handleIndigo(method);
- return;
- }
- }
- System.err.println("Could not inject indigo rendering hook. Is a custom renderer installed (e.g. sodium)?");
- }
+ private void handle(ClassNode classNode) {
+ System.out.println("AVAST! "+ getModel);
+ for (MethodNode method : classNode.methods) {
+ if ((method.name.endsWith("$fabric-renderer-indigo$hookBuildRenderBlock")
+ || method.name.endsWith("$fabric-renderer-indigo$hookChunkBuildTessellate")) &&
+ method.name.startsWith("redirect$")) {
+ handleIndigo(method);
+ return;
+ }
+ }
+ System.err.println("Could not inject indigo rendering hook. Is a custom renderer installed (e.g. sodium)?");
+ }
- private void handleIndigo(MethodNode method) {
- LocalVariableNode blockPosVar = null, blockStateVar = null;
- for (LocalVariableNode localVariable : method.localVariables) {
- if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockPos))) {
- blockPosVar = localVariable;
- }
- if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockState))) {
- blockStateVar = localVariable;
- }
- }
- if (blockPosVar == null || blockStateVar == null) {
- System.err.println("Firmament could inject into indigo: missing either block pos or blockstate");
- return;
- }
- for (AbstractInsnNode instruction : method.instructions) {
- if (instruction.getOpcode() != Opcodes.INVOKEVIRTUAL) continue;
- var methodInsn = (MethodInsnNode) instruction;
- if (!(methodInsn.name.equals(getModel) && Type.getObjectType(methodInsn.owner).equals(getTypeForClassName(BlockRenderManager))))
- continue;
- method.instructions.insertBefore(
- methodInsn,
- new MethodInsnNode(
- Opcodes.INVOKESTATIC,
- getTypeForClassName(CustomBlockTextures).getInternalName(),
- "enterFallbackCall",
- Type.getMethodDescriptor(Type.VOID_TYPE)
- ));
+ private void handleIndigo(MethodNode method) {
+ LocalVariableNode blockPosVar = null, blockStateVar = null;
+ for (LocalVariableNode localVariable : method.localVariables) {
+ if (Type.getType(localVariable.desc).equals(BlockPos.mapped())) {
+ blockPosVar = localVariable;
+ }
+ if (Type.getType(localVariable.desc).equals(BlockState.mapped())) {
+ blockStateVar = localVariable;
+ }
+ }
+ if (blockPosVar == null || blockStateVar == null) {
+ System.err.println("Firmament could inject into indigo: missing either block pos or blockstate");
+ return;
+ }
+ for (AbstractInsnNode instruction : method.instructions) {
+ if (instruction.getOpcode() != Opcodes.INVOKEVIRTUAL) continue;
+ var methodInsn = (MethodInsnNode) instruction;
+ if (!(methodInsn.name.equals(getModel.mapped()) &&
+ Type.getObjectType(methodInsn.owner).equals(BlockRenderManager.mapped())))
+ continue;
+ method.instructions.insertBefore(
+ methodInsn,
+ new MethodInsnNode(
+ Opcodes.INVOKESTATIC,
+ getTypeForClassName(CustomBlockTextures).getInternalName(),
+ "enterFallbackCall",
+ Type.getMethodDescriptor(Type.VOID_TYPE)
+ ));
- var insnList = new InsnList();
- insnList.add(new MethodInsnNode(
- Opcodes.INVOKESTATIC,
- getTypeForClassName(CustomBlockTextures).getInternalName(),
- "exitFallbackCall",
- Type.getMethodDescriptor(Type.VOID_TYPE)
- ));
- insnList.add(new VarInsnNode(Opcodes.ALOAD, blockPosVar.index));
- insnList.add(new VarInsnNode(Opcodes.ALOAD, blockStateVar.index));
- insnList.add(new MethodInsnNode(
- Opcodes.INVOKESTATIC,
- getTypeForClassName(CustomBlockTextures).getInternalName(),
- "patchIndigo",
- Type.getMethodDescriptor(getTypeForClassName(BakedModel),
- getTypeForClassName(BakedModel),
- getTypeForClassName(BlockPos),
- getTypeForClassName(BlockState)),
- false
- ));
- method.instructions.insert(methodInsn, insnList);
- }
- }
+ var insnList = new InsnList();
+ insnList.add(new MethodInsnNode(
+ Opcodes.INVOKESTATIC,
+ getTypeForClassName(CustomBlockTextures).getInternalName(),
+ "exitFallbackCall",
+ Type.getMethodDescriptor(Type.VOID_TYPE)
+ ));
+ insnList.add(new VarInsnNode(Opcodes.ALOAD, blockPosVar.index));
+ insnList.add(new VarInsnNode(Opcodes.ALOAD, blockStateVar.index));
+ insnList.add(new MethodInsnNode(
+ Opcodes.INVOKESTATIC,
+ getTypeForClassName(CustomBlockTextures).getInternalName(),
+ "patchIndigo",
+ Type.getMethodDescriptor(
+ (BlockStateModel).mapped(),
+ (BlockStateModel).mapped(),
+ (BlockPos).mapped(),
+ (BlockState).mapped()),
+ false
+ ));
+ method.instructions.insert(methodInsn, insnList);
+ }
+ }
}
diff --git a/src/main/java/moe/nea/firmament/mixins/AppendRepoAsResourcePack.java b/src/main/java/moe/nea/firmament/mixins/AppendRepoAsResourcePack.java
index 22ce991..30b5020 100644
--- a/src/main/java/moe/nea/firmament/mixins/AppendRepoAsResourcePack.java
+++ b/src/main/java/moe/nea/firmament/mixins/AppendRepoAsResourcePack.java
@@ -1,28 +1,34 @@
package moe.nea.firmament.mixins;
+import com.llamalad7.mixinextras.sugar.Local;
import moe.nea.firmament.repo.RepoModResourcePack;
import net.fabricmc.fabric.api.resource.ModResourcePack;
+import net.fabricmc.fabric.impl.resource.loader.ModResourcePackSorter;
import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil;
-import net.minecraft.resource.ResourceType;
+import net.fabricmc.loader.api.FabricLoader;
+import net.minecraft.server.packs.PackType;
import org.jetbrains.annotations.Nullable;
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;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.List;
@Mixin(ModResourcePackUtil.class)
public class AppendRepoAsResourcePack {
- @Inject(method = "appendModResourcePacks", at = @At("TAIL"))
- private static void onAppendModResourcePack(
- List<ModResourcePack> packs,
- ResourceType type,
- @Nullable String subPath,
- CallbackInfo ci
- ) {
- RepoModResourcePack.Companion.append(packs);
- }
+ @Inject(
+ method = "getModResourcePacks",
+ at = @At(value = "INVOKE", target = "Lnet/fabricmc/fabric/impl/resource/loader/ModResourcePackSorter;getPacks()Ljava/util/List;"),
+ require = 0
+ )
+ private static void onAppendModResourcePack(
+ FabricLoader fabricLoader, PackType type, @Nullable String subPath, CallbackInfoReturnable<List<ModResourcePack>> cir,
+ @Local ModResourcePackSorter sorter
+ ) {
+ RepoModResourcePack.Companion.append(sorter);
+ }
}
diff --git a/src/main/java/moe/nea/firmament/mixins/BandAidResourcePackPatch.java b/src/main/java/moe/nea/firmament/mixins/BandAidResourcePackPatch.java
index d898c44..8e591bd 100644
--- a/src/main/java/moe/nea/firmament/mixins/BandAidResourcePackPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/BandAidResourcePackPatch.java
@@ -4,22 +4,22 @@ package moe.nea.firmament.mixins;
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import com.llamalad7.mixinextras.sugar.Local;
import moe.nea.firmament.repo.RepoModResourcePack;
-import net.minecraft.resource.ReloadableResourceManagerImpl;
-import net.minecraft.resource.Resource;
-import net.minecraft.util.Identifier;
+import net.minecraft.server.packs.resources.ReloadableResourceManager;
+import net.minecraft.server.packs.resources.Resource;
+import net.minecraft.resources.ResourceLocation;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import java.util.Optional;
-@Mixin(ReloadableResourceManagerImpl.class)
+@Mixin(ReloadableResourceManager.class)
public class BandAidResourcePackPatch {
@ModifyReturnValue(
method = "getResource",
at = @At("RETURN")
)
- private Optional<Resource> injectOurCustomResourcesInCaseExistingMethodsFailed(Optional<Resource> original, @Local Identifier identifier) {
+ private Optional<Resource> injectOurCustomResourcesInCaseExistingMethodsFailed(Optional<Resource> original, @Local ResourceLocation identifier) {
return original.or(() -> RepoModResourcePack.Companion.createResourceDirectly(identifier));
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/ChatPeekScrollPatch.java b/src/main/java/moe/nea/firmament/mixins/ChatPeekScrollPatch.java
new file mode 100644
index 0000000..c795908
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/ChatPeekScrollPatch.java
@@ -0,0 +1,27 @@
+package moe.nea.firmament.mixins;
+
+import moe.nea.firmament.features.fixes.Fixes;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.MouseHandler;
+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.ModifyVariable;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(MouseHandler.class)
+public class ChatPeekScrollPatch {
+
+ @Inject(method = "onScroll", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Inventory;getSelectedSlot()I"), cancellable = true)
+ public void onHotbarScrollWhilePeeking(long window, double horizontal, double vertical, CallbackInfo ci) {
+ if (Fixes.INSTANCE.shouldPeekChat() && Fixes.INSTANCE.shouldScrollPeekedChat()) ci.cancel();
+ }
+
+ @ModifyVariable(method = "onScroll", at = @At(value = "STORE"), ordinal = 0)
+ public int onGetChatHud(int i) {
+ if (Fixes.INSTANCE.shouldPeekChat() && Fixes.INSTANCE.shouldScrollPeekedChat())
+ Minecraft.getInstance().gui.getChat().scrollChat(i);
+ return i;
+ }
+
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/ChatPeekingPatch.java b/src/main/java/moe/nea/firmament/mixins/ChatPeekingPatch.java
index 9f6fb4d..2bc1374 100644
--- a/src/main/java/moe/nea/firmament/mixins/ChatPeekingPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/ChatPeekingPatch.java
@@ -4,12 +4,12 @@ package moe.nea.firmament.mixins;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import moe.nea.firmament.features.fixes.Fixes;
-import net.minecraft.client.gui.hud.ChatHud;
+import net.minecraft.client.gui.components.ChatComponent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
-@Mixin(ChatHud.class)
+@Mixin(ChatComponent.class)
public class ChatPeekingPatch {
@ModifyVariable(method = "render", at = @At(value = "HEAD"), index = 5, argsOnly = true)
@@ -17,7 +17,7 @@ public class ChatPeekingPatch {
return old || Fixes.INSTANCE.shouldPeekChat();
}
- @ModifyExpressionValue(method = "getHeight()I", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;isChatFocused()Z"))
+ @ModifyExpressionValue(method = "getHeight()I", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/ChatComponent;isChatFocused()Z"))
public boolean onGetChatHudHeight(boolean old) {
return old || Fixes.INSTANCE.shouldPeekChat();
}
diff --git a/src/main/java/moe/nea/firmament/mixins/CopyChatPatch.java b/src/main/java/moe/nea/firmament/mixins/CopyChatPatch.java
new file mode 100644
index 0000000..9079fc9
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/CopyChatPatch.java
@@ -0,0 +1,45 @@
+package moe.nea.firmament.mixins;
+
+import moe.nea.firmament.features.chat.CopyChat;
+import moe.nea.firmament.mixins.accessor.AccessorChatHud;
+import moe.nea.firmament.util.ClipboardUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.input.MouseButtonEvent;
+import net.minecraft.client.gui.components.ChatComponent;
+import net.minecraft.client.GuiMessage;
+import net.minecraft.client.gui.screens.ChatScreen;
+import net.minecraft.network.chat.Component;
+import net.minecraft.ChatFormatting;
+import net.minecraft.util.Mth;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Unique;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+import java.util.List;
+
+@Mixin(ChatScreen.class)
+public class CopyChatPatch {
+ @Inject(method = "mouseClicked", at = @At("HEAD"), cancellable = true)
+ private void onRightClick(MouseButtonEvent click, boolean doubled, CallbackInfoReturnable<Boolean> cir) throws NoSuchFieldException, IllegalAccessException {
+ if (click.button() != 1 || !CopyChat.TConfig.INSTANCE.getCopyChat()) return;
+ Minecraft client = Minecraft.getInstance();
+ ChatComponent chatHud = client.gui.getChat();
+ int lineIndex = getChatLineIndex(chatHud, click.y());
+ if (lineIndex < 0) return;
+ List<GuiMessage.Line> visible = ((AccessorChatHud) chatHud).getVisibleMessages_firmament();
+ if (lineIndex >= visible.size()) return;
+ GuiMessage.Line line = visible.get(lineIndex);
+ String text = CopyChat.INSTANCE.orderedTextToString(line.content());
+ ClipboardUtils.INSTANCE.setTextContent(text);
+ chatHud.addMessage(Component.literal("Copied: ").append(text).withStyle(ChatFormatting.GRAY));
+ cir.setReturnValue(true);
+ cir.cancel();
+ }
+
+ @Unique
+ private int getChatLineIndex(ChatComponent chatHud, double mouseY) {
+ double chatLineY = ((AccessorChatHud) chatHud).toChatLineY_firmament(mouseY);
+ return Mth.floor(chatLineY + ((AccessorChatHud) chatHud).getScrolledLines_firmament());
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/CustomDurabilityBarPatch.java b/src/main/java/moe/nea/firmament/mixins/CustomDurabilityBarPatch.java
index fde3580..2299068 100644
--- a/src/main/java/moe/nea/firmament/mixins/CustomDurabilityBarPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/CustomDurabilityBarPatch.java
@@ -6,20 +6,20 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
import moe.nea.firmament.util.DurabilityBarEvent;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.item.ItemStack;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
-@Mixin(DrawContext.class)
+@Mixin(GuiGraphics.class)
public class CustomDurabilityBarPatch {
@WrapOperation(
- method = "drawItemBar",
- at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isItemBarVisible()Z")
+ method = "renderItemBar",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isBarVisible()Z")
)
private boolean onIsItemBarVisible(
- ItemStack instance, Operation<Boolean> original,
- @Share("barOverride") LocalRef<DurabilityBarEvent.DurabilityBar> barOverride
+ ItemStack instance, Operation<Boolean> original,
+ @Share("barOverride") LocalRef<DurabilityBarEvent.DurabilityBar> barOverride
) {
if (original.call(instance))
return true;
@@ -29,22 +29,22 @@ public class CustomDurabilityBarPatch {
return barOverride.get() != null;
}
- @WrapOperation(method = "drawItemBar",
- at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getItemBarStep()I"))
+ @WrapOperation(method = "renderItemBar",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;getBarWidth()I"))
private int overrideItemStep(
- ItemStack instance, Operation<Integer> original,
- @Share("barOverride") LocalRef<DurabilityBarEvent.DurabilityBar> barOverride
+ ItemStack instance, Operation<Integer> original,
+ @Share("barOverride") LocalRef<DurabilityBarEvent.DurabilityBar> barOverride
) {
if (barOverride.get() != null)
return Math.round(barOverride.get().getPercentage() * 13);
return original.call(instance);
}
- @WrapOperation(method = "drawItemBar",
- at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getItemBarColor()I"))
+ @WrapOperation(method = "renderItemBar",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;getBarColor()I"))
private int overrideItemColor(
- ItemStack instance, Operation<Integer> original,
- @Share("barOverride") LocalRef<DurabilityBarEvent.DurabilityBar> barOverride
+ ItemStack instance, Operation<Integer> original,
+ @Share("barOverride") LocalRef<DurabilityBarEvent.DurabilityBar> barOverride
) {
if (barOverride.get() != null)
return barOverride.get().getColor().getColor();
diff --git a/src/main/java/moe/nea/firmament/mixins/DFUEntityIdFixPatch.java b/src/main/java/moe/nea/firmament/mixins/DFUEntityIdFixPatch.java
index 717d404..8503411 100644
--- a/src/main/java/moe/nea/firmament/mixins/DFUEntityIdFixPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/DFUEntityIdFixPatch.java
@@ -6,8 +6,8 @@ import com.mojang.datafixers.DataFix;
import com.mojang.datafixers.TypeRewriteRule;
import com.mojang.datafixers.schemas.Schema;
import com.mojang.datafixers.util.Pair;
-import net.minecraft.datafixer.TypeReferences;
-import net.minecraft.datafixer.fix.EntityIdFix;
+import net.minecraft.util.datafix.fixes.References;
+import net.minecraft.util.datafix.fixes.EntityIdFix;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -22,7 +22,7 @@ import java.util.Map;
public abstract class DFUEntityIdFixPatch extends DataFix {
@Shadow
@Final
- private static Map<String, String> RENAMED_ENTITIES;
+ private static Map<String, String> ID_MAP;
public DFUEntityIdFixPatch(Schema outputSchema, boolean changesType) {
super(outputSchema, changesType);
@@ -30,6 +30,6 @@ public abstract class DFUEntityIdFixPatch extends DataFix {
@Inject(method = "makeRule", at = @At("RETURN"), cancellable = true)
public void onMakeRule(CallbackInfoReturnable<TypeRewriteRule> cir) {
- cir.setReturnValue(TypeRewriteRule.seq(fixTypeEverywhere("EntityIdFix", getInputSchema().findChoiceType(TypeReferences.ENTITY), getOutputSchema().findChoiceType(TypeReferences.ENTITY), dynamicOps -> pair -> ((Pair) pair).mapFirst(string -> RENAMED_ENTITIES.getOrDefault(string, (String) string))), convertUnchecked("Fix Type", getInputSchema().getType(TypeReferences.ITEM_STACK), getOutputSchema().getType(TypeReferences.ITEM_STACK))));
+ cir.setReturnValue(TypeRewriteRule.seq(fixTypeEverywhere("EntityIdFix", getInputSchema().findChoiceType(References.ENTITY), getOutputSchema().findChoiceType(References.ENTITY), dynamicOps -> pair -> ((Pair) pair).mapFirst(string -> ID_MAP.getOrDefault(string, (String) string))), convertUnchecked("Fix Type", getInputSchema().getType(References.ITEM_STACK), getOutputSchema().getType(References.ITEM_STACK))));
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/DisableHurtCam.java b/src/main/java/moe/nea/firmament/mixins/DisableHurtCam.java
new file mode 100644
index 0000000..3a53ab1
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/DisableHurtCam.java
@@ -0,0 +1,18 @@
+package moe.nea.firmament.mixins;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import moe.nea.firmament.features.fixes.Fixes;
+import net.minecraft.client.renderer.GameRenderer;
+import org.objectweb.asm.Opcodes;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(GameRenderer.class)
+public class DisableHurtCam {
+ @ModifyExpressionValue(method = "bobHurt", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;hurtTime:I", opcode = Opcodes.GETFIELD))
+ private int replaceHurtTime(int original) {
+ if (Fixes.TConfig.INSTANCE.getNoHurtCam())
+ return 0;
+ return original;
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/DispatchMouseInputEventsPatch.java b/src/main/java/moe/nea/firmament/mixins/DispatchMouseInputEventsPatch.java
new file mode 100644
index 0000000..ecd361d
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/DispatchMouseInputEventsPatch.java
@@ -0,0 +1,17 @@
+package moe.nea.firmament.mixins;
+
+import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
+import moe.nea.firmament.events.WorldMouseMoveEvent;
+import net.minecraft.client.MouseHandler;
+import net.minecraft.client.player.LocalPlayer;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(MouseHandler.class)
+public class DispatchMouseInputEventsPatch {
+ @WrapWithCondition(method = "turnPlayer", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;turn(DD)V"))
+ public boolean onRotatePlayer(LocalPlayer instance, double deltaX, double deltaY) {
+ var event = WorldMouseMoveEvent.Companion.publish(new WorldMouseMoveEvent(deltaX, deltaY));
+ return !event.getCancelled();
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/EarlyResourceReloadPatch.java b/src/main/java/moe/nea/firmament/mixins/EarlyResourceReloadPatch.java
index e98faf6..b8460a7 100644
--- a/src/main/java/moe/nea/firmament/mixins/EarlyResourceReloadPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/EarlyResourceReloadPatch.java
@@ -2,10 +2,10 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.events.EarlyResourceReloadEvent;
-import net.minecraft.resource.ReloadableResourceManagerImpl;
-import net.minecraft.resource.ResourceManager;
-import net.minecraft.resource.ResourcePack;
-import net.minecraft.resource.ResourceReload;
+import net.minecraft.server.packs.resources.ReloadableResourceManager;
+import net.minecraft.server.packs.resources.ResourceManager;
+import net.minecraft.server.packs.PackResources;
+import net.minecraft.server.packs.resources.ReloadInstance;
import net.minecraft.util.Unit;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -16,10 +16,10 @@ import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
-@Mixin(ReloadableResourceManagerImpl.class)
+@Mixin(ReloadableResourceManager.class)
public abstract class EarlyResourceReloadPatch implements ResourceManager {
- @Inject(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/SimpleResourceReload;start(Lnet/minecraft/resource/ResourceManager;Ljava/util/List;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Z)Lnet/minecraft/resource/ResourceReload;", shift = At.Shift.BEFORE))
- public void onResourceReload(Executor prepareExecutor, Executor applyExecutor, CompletableFuture<Unit> initialStage, List<ResourcePack> packs, CallbackInfoReturnable<ResourceReload> cir) {
+ @Inject(method = "createReload", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/SimpleReloadInstance;create(Lnet/minecraft/server/packs/resources/ResourceManager;Ljava/util/List;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Z)Lnet/minecraft/server/packs/resources/ReloadInstance;", shift = At.Shift.BEFORE))
+ public void onResourceReload(Executor prepareExecutor, Executor applyExecutor, CompletableFuture<Unit> initialStage, List<PackResources> packs, CallbackInfoReturnable<ReloadInstance> cir) {
EarlyResourceReloadEvent.Companion.publish(new EarlyResourceReloadEvent(this, prepareExecutor));
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/EntityDespawnPatch.java b/src/main/java/moe/nea/firmament/mixins/EntityDespawnPatch.java
index 22bebec..c286226 100644
--- a/src/main/java/moe/nea/firmament/mixins/EntityDespawnPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/EntityDespawnPatch.java
@@ -3,15 +3,15 @@ package moe.nea.firmament.mixins;
import com.llamalad7.mixinextras.sugar.Local;
import moe.nea.firmament.events.EntityDespawnEvent;
-import net.minecraft.client.world.ClientWorld;
-import net.minecraft.entity.Entity;
+import net.minecraft.client.multiplayer.ClientLevel;
+import net.minecraft.world.entity.Entity;
import org.jetbrains.annotations.Nullable;
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;
-@Mixin(ClientWorld.class)
+@Mixin(ClientLevel.class)
public class EntityDespawnPatch {
@Inject(method = "removeEntity", at = @At(value = "TAIL"))
private void onRemoved(int entityId, Entity.RemovalReason removalReason, CallbackInfo ci, @Local @Nullable Entity entity) {
diff --git a/src/main/java/moe/nea/firmament/mixins/EntityInteractEventPatch.java b/src/main/java/moe/nea/firmament/mixins/EntityInteractEventPatch.java
index 8ade59b..4138389 100644
--- a/src/main/java/moe/nea/firmament/mixins/EntityInteractEventPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/EntityInteractEventPatch.java
@@ -2,32 +2,32 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.events.EntityInteractionEvent;
-import net.minecraft.client.network.ClientPlayerInteractionManager;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.player.PlayerEntity;
-import net.minecraft.util.ActionResult;
-import net.minecraft.util.Hand;
-import net.minecraft.util.hit.EntityHitResult;
+import net.minecraft.client.multiplayer.MultiPlayerGameMode;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.InteractionResult;
+import net.minecraft.world.InteractionHand;
+import net.minecraft.world.phys.EntityHitResult;
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;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-@Mixin(ClientPlayerInteractionManager.class)
+@Mixin(MultiPlayerGameMode.class)
public class EntityInteractEventPatch {
- @Inject(method = "attackEntity", at = @At("HEAD"))
- private void onAttack(PlayerEntity player, Entity target, CallbackInfo ci) {
- EntityInteractionEvent.Companion.publish(new EntityInteractionEvent(EntityInteractionEvent.InteractionKind.ATTACK, target, Hand.MAIN_HAND));
+ @Inject(method = "attack", at = @At("HEAD"))
+ private void onAttack(Player player, Entity target, CallbackInfo ci) {
+ EntityInteractionEvent.Companion.publish(new EntityInteractionEvent(EntityInteractionEvent.InteractionKind.ATTACK, target, InteractionHand.MAIN_HAND));
}
- @Inject(method = "interactEntity", at = @At("HEAD"))
- private void onInteract(PlayerEntity player, Entity entity, Hand hand, CallbackInfoReturnable<ActionResult> cir) {
+ @Inject(method = "interact", at = @At("HEAD"))
+ private void onInteract(Player player, Entity entity, InteractionHand hand, CallbackInfoReturnable<InteractionResult> cir) {
EntityInteractionEvent.Companion.publish(new EntityInteractionEvent(EntityInteractionEvent.InteractionKind.INTERACT, entity, hand));
}
- @Inject(method = "interactEntityAtLocation", at = @At("HEAD"))
- private void onInteractAtLocation(PlayerEntity player, Entity entity, EntityHitResult hitResult, Hand hand, CallbackInfoReturnable<ActionResult> cir) {
+ @Inject(method = "interactAt", at = @At("HEAD"))
+ private void onInteractAtLocation(Player player, Entity entity, EntityHitResult hitResult, InteractionHand hand, CallbackInfoReturnable<InteractionResult> cir) {
EntityInteractionEvent.Companion.publish(new EntityInteractionEvent(EntityInteractionEvent.InteractionKind.INTERACT_AT_LOCATION, entity, hand));
}
diff --git a/src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java b/src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java
index c2d6e46..0021099 100644
--- a/src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java
+++ b/src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java
@@ -3,40 +3,46 @@ package moe.nea.firmament.mixins;
import com.llamalad7.mixinextras.sugar.Local;
import moe.nea.firmament.events.EntityUpdateEvent;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.network.ClientCommonNetworkHandler;
-import net.minecraft.client.network.ClientConnectionState;
-import net.minecraft.client.network.ClientPlayNetworkHandler;
-import net.minecraft.client.world.ClientWorld;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.LivingEntity;
-import net.minecraft.network.ClientConnection;
-import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket;
-import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl;
+import net.minecraft.client.multiplayer.CommonListenerCookie;
+import net.minecraft.client.multiplayer.ClientPacketListener;
+import net.minecraft.client.multiplayer.ClientLevel;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.LivingEntity;
+import net.minecraft.network.Connection;
+import net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket;
+import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;
+import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
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;
-@Mixin(ClientPlayNetworkHandler.class)
-public abstract class EntityUpdateEventListener extends ClientCommonNetworkHandler {
+@Mixin(ClientPacketListener.class)
+public abstract class EntityUpdateEventListener extends ClientCommonPacketListenerImpl {
- @Shadow
- private ClientWorld world;
+ @Shadow
+ private ClientLevel level;
- protected EntityUpdateEventListener(MinecraftClient client, ClientConnection connection, ClientConnectionState connectionState) {
- super(client, connection, connectionState);
- }
+ protected EntityUpdateEventListener(Minecraft client, Connection connection, CommonListenerCookie connectionState) {
+ super(client, connection, connectionState);
+ }
- @Inject(method = "onEntityAttributes", at = @At("TAIL"))
- private void onAttributeUpdate(EntityAttributesS2CPacket packet, CallbackInfo ci) {
- EntityUpdateEvent.Companion.publish(new EntityUpdateEvent.AttributeUpdate(
- (LivingEntity) world.getEntityById(packet.getEntityId()), packet.getEntries()));
- }
+ @Inject(method = "handleSetEquipment", at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", shift = At.Shift.AFTER))
+ private void onEquipmentUpdate(ClientboundSetEquipmentPacket packet, CallbackInfo ci, @Local LivingEntity entity) {
+ EntityUpdateEvent.Companion.publish(new EntityUpdateEvent.EquipmentUpdate(entity, packet.getSlots()));
+ }
- @Inject(method = "onEntityTrackerUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/data/DataTracker;writeUpdatedEntries(Ljava/util/List;)V", shift = At.Shift.AFTER))
- private void onEntityTracker(EntityTrackerUpdateS2CPacket packet, CallbackInfo ci, @Local Entity entity) {
- EntityUpdateEvent.Companion.publish(new EntityUpdateEvent.TrackedDataUpdate(entity, packet.trackedValues()));
- }
+ @Inject(method = "handleUpdateAttributes", at = @At("TAIL"))
+ private void onAttributeUpdate(ClientboundUpdateAttributesPacket packet, CallbackInfo ci) {
+ EntityUpdateEvent.Companion.publish(new EntityUpdateEvent.AttributeUpdate(
+ (LivingEntity) level.getEntity(packet.getEntityId()), packet.getValues()));
+ }
+
+ @Inject(method = "handleSetEntityData", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/syncher/SynchedEntityData;assignValues(Ljava/util/List;)V", shift = At.Shift.AFTER))
+ private void onEntityTracker(ClientboundSetEntityDataPacket packet, CallbackInfo ci, @Local Entity entity) {
+ EntityUpdateEvent.Companion.publish(new EntityUpdateEvent.TrackedDataUpdate(entity, packet.packedItems()));
+ }
}
diff --git a/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java b/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java
index 699d5b7..5d8484f 100644
--- a/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java
@@ -3,13 +3,12 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.gui.config.KeyBindingHandler;
-import moe.nea.firmament.gui.config.ManagedConfig;
import moe.nea.firmament.keybindings.FirmamentKeyBindings;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gui.screen.option.ControlsListWidget;
-import net.minecraft.client.gui.widget.ButtonWidget;
-import net.minecraft.client.option.KeyBinding;
-import net.minecraft.text.Text;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.screens.options.controls.KeyBindsList;
+import net.minecraft.client.gui.components.Button;
+import net.minecraft.client.KeyMapping;
+import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
@@ -19,39 +18,39 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-@Mixin(ControlsListWidget.KeyBindingEntry.class)
+@Mixin(KeyBindsList.KeyEntry.class)
public class FirmKeybindsInVanillaControlsPatch {
@Mutable
@Shadow
@Final
- private ButtonWidget editButton;
+ private Button changeButton;
@Shadow
@Final
- private KeyBinding binding;
+ private KeyMapping key;
@Shadow
@Final
- private ButtonWidget resetButton;
+ private Button resetButton;
- @ModifyArg(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/ButtonWidget;builder(Lnet/minecraft/text/Text;Lnet/minecraft/client/gui/widget/ButtonWidget$PressAction;)Lnet/minecraft/client/gui/widget/ButtonWidget$Builder;"))
- public ButtonWidget.PressAction onInit(ButtonWidget.PressAction action) {
- var config = FirmamentKeyBindings.INSTANCE.getKeyBindings().get(binding);
+ @ModifyArg(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/components/Button;builder(Lnet/minecraft/network/chat/Component;Lnet/minecraft/client/gui/components/Button$OnPress;)Lnet/minecraft/client/gui/components/Button$Builder;"))
+ public Button.OnPress onInit(Button.OnPress action) {
+ var config = FirmamentKeyBindings.INSTANCE.getKeyBindings().get(key);
if (config == null) return action;
return button -> {
((KeyBindingHandler) config.getHandler())
.getManagedConfig()
- .showConfigEditor(MinecraftClient.getInstance().currentScreen);
+ .showConfigEditor(Minecraft.getInstance().screen);
};
}
- @Inject(method = "update", at = @At("HEAD"), cancellable = true)
+ @Inject(method = "refreshEntry", at = @At("HEAD"), cancellable = true)
public void onUpdate(CallbackInfo ci) {
- var config = FirmamentKeyBindings.INSTANCE.getKeyBindings().get(binding);
+ var config = FirmamentKeyBindings.INSTANCE.getKeyBindings().get(key);
if (config == null) return;
resetButton.active = false;
- editButton.setMessage(Text.translatable("firmament.keybinding.external", config.getValue().format()));
+ changeButton.setMessage(Component.translatable("firmament.keybinding.external", config.getValue().format()));
ci.cancel();
}
diff --git a/src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java b/src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java
index c5af8b6..b2884cd 100644
--- a/src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java
@@ -1,29 +1,33 @@
package moe.nea.firmament.mixins;
-import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import moe.nea.firmament.features.fixes.Fixes;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.gui.screen.ingame.InventoryScreen;
-import net.minecraft.client.gui.screen.ingame.StatusEffectsDisplay;
+import moe.nea.firmament.util.SBData;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.screens.inventory.EffectsInInventory;
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.CallbackInfoReturnable;
-@Mixin(InventoryScreen.class)
+@Mixin(EffectsInInventory.class)
public abstract class HideStatusEffectsPatch {
@Shadow
- public abstract boolean shouldHideStatusEffectHud();
+ public abstract boolean canSeeEffects();
- @Inject(method = "shouldHideStatusEffectHud", at = @At("HEAD"), cancellable = true)
+ @Inject(method = "canSeeEffects", at = @At("HEAD"), cancellable = true)
private void hideStatusEffects(CallbackInfoReturnable<Boolean> cir) {
- cir.setReturnValue(!Fixes.TConfig.INSTANCE.getHidePotionEffects());
+ if (Fixes.TConfig.INSTANCE.getHidePotionEffects()) {
+ cir.setReturnValue(false);
+ }
}
- @WrapWithCondition(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/StatusEffectsDisplay;drawStatusEffects(Lnet/minecraft/client/gui/DrawContext;IIF)V"))
- private boolean conditionalRenderStatuses(StatusEffectsDisplay instance, DrawContext context, int mouseX, int mouseY, float tickDelta) {
- return shouldHideStatusEffectHud() || !Fixes.TConfig.INSTANCE.getHidePotionEffects();
+ @Inject(method = "renderEffects", at = @At("HEAD"), cancellable = true)
+ private void conditionalRenderStatuses(GuiGraphics context, int mouseX, int mouseY, CallbackInfo ci) {
+ if (Fixes.TConfig.INSTANCE.getHidePotionEffects()) {
+ ci.cancel();
+ }
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/HudRenderEventsPatch.java b/src/main/java/moe/nea/firmament/mixins/HudRenderEventsPatch.java
index 85c0462..1f7e07a 100644
--- a/src/main/java/moe/nea/firmament/mixins/HudRenderEventsPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/HudRenderEventsPatch.java
@@ -4,26 +4,34 @@ package moe.nea.firmament.mixins;
import moe.nea.firmament.events.HotbarItemRenderEvent;
import moe.nea.firmament.events.HudRenderEvent;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.gui.hud.InGameHud;
-import net.minecraft.client.render.RenderTickCounter;
-import net.minecraft.entity.player.PlayerEntity;
-import net.minecraft.item.ItemStack;
+import moe.nea.firmament.features.fixes.Fixes;
+import moe.nea.firmament.util.SBData;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.DeltaTracker;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.item.ItemStack;
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;
-@Mixin(InGameHud.class)
+@Mixin(Gui.class)
public class HudRenderEventsPatch {
@Inject(method = "renderSleepOverlay", at = @At(value = "HEAD"))
- public void renderCallBack(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) {
+ public void renderCallBack(GuiGraphics context, DeltaTracker tickCounter, CallbackInfo ci) {
HudRenderEvent.Companion.publish(new HudRenderEvent(context, tickCounter));
}
- @Inject(method = "renderHotbarItem", at = @At("HEAD"))
- public void onRenderHotbarItem(DrawContext context, int x, int y, RenderTickCounter tickCounter, PlayerEntity player, ItemStack stack, int seed, CallbackInfo ci) {
+ @Inject(method = "renderSlot", at = @At("HEAD"))
+ public void onRenderHotbarItem(GuiGraphics context, int x, int y, DeltaTracker tickCounter, Player player, ItemStack stack, int seed, CallbackInfo ci) {
if (stack != null && !stack.isEmpty())
HotbarItemRenderEvent.Companion.publish(new HotbarItemRenderEvent(stack, context, x, y, tickCounter));
}
+
+ @Inject(method = "renderEffects", at = @At("HEAD"), cancellable = true)
+ public void hideStatusEffects(CallbackInfo ci) {
+ if (Fixes.TConfig.INSTANCE.getHidePotionEffectsHud() && SBData.INSTANCE.isOnSkyblock()) ci.cancel();
+ }
+
}
diff --git a/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java b/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java
index a7c3875..9f338f5 100644
--- a/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java
+++ b/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java
@@ -6,33 +6,33 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.mojang.brigadier.CommandDispatcher;
import moe.nea.firmament.events.MaskCommands;
import moe.nea.firmament.events.ParticleSpawnEvent;
-import net.minecraft.client.network.ClientPlayNetworkHandler;
-import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
-import net.minecraft.util.math.Vec3d;
+import net.minecraft.client.multiplayer.ClientPacketListener;
+import net.minecraft.network.protocol.game.ClientboundLevelParticlesPacket;
+import net.minecraft.world.phys.Vec3;
import org.joml.Vector3f;
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;
-@Mixin(ClientPlayNetworkHandler.class)
+@Mixin(ClientPacketListener.class)
public abstract class IncomingPacketListenerPatches {
- @ModifyExpressionValue(method = "onCommandTree", at = @At(value = "NEW", target = "(Lcom/mojang/brigadier/tree/RootCommandNode;)Lcom/mojang/brigadier/CommandDispatcher;", remap = false))
+ @ModifyExpressionValue(method = "handleCommands", at = @At(value = "NEW", target = "(Lcom/mojang/brigadier/tree/RootCommandNode;)Lcom/mojang/brigadier/CommandDispatcher;", remap = false))
public CommandDispatcher onOnCommandTree(CommandDispatcher dispatcher) {
MaskCommands.Companion.publish(new MaskCommands(dispatcher));
return dispatcher;
}
- @Inject(method = "onParticle", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkThreadUtils;forceMainThread(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;Lnet/minecraft/util/thread/ThreadExecutor;)V", shift = At.Shift.AFTER), cancellable = true)
- public void onParticleSpawn(ParticleS2CPacket packet, CallbackInfo ci) {
+ @Inject(method = "handleParticleEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/network/PacketProcessor;)V", shift = At.Shift.AFTER), cancellable = true)
+ public void onParticleSpawn(ClientboundLevelParticlesPacket packet, CallbackInfo ci) {
var event = new ParticleSpawnEvent(
- packet.getParameters(),
- new Vec3d(packet.getX(), packet.getY(), packet.getZ()),
- new Vector3f(packet.getOffsetX(), packet.getOffsetY(), packet.getOffsetZ()),
- packet.isImportant(),
+ packet.getParticle(),
+ new Vec3(packet.getX(), packet.getY(), packet.getZ()),
+ new Vector3f(packet.getXDist(), packet.getYDist(), packet.getZDist()),
+ packet.alwaysShow(),
packet.getCount(),
- packet.getSpeed()
+ packet.getMaxSpeed()
);
ParticleSpawnEvent.Companion.publish(event);
if (event.getCancelled())
diff --git a/src/main/java/moe/nea/firmament/mixins/KeyPressInWorldEventPatch.java b/src/main/java/moe/nea/firmament/mixins/KeyPressInWorldEventPatch.java
index 48f3c23..ee7f570 100644
--- a/src/main/java/moe/nea/firmament/mixins/KeyPressInWorldEventPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/KeyPressInWorldEventPatch.java
@@ -2,18 +2,23 @@
package moe.nea.firmament.mixins;
+import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
+import com.llamalad7.mixinextras.sugar.Local;
import moe.nea.firmament.events.WorldKeyboardEvent;
-import net.minecraft.client.Keyboard;
+import moe.nea.firmament.keybindings.GenericInputAction;
+import moe.nea.firmament.keybindings.InputModifiers;
+import net.minecraft.client.KeyboardHandler;
+import net.minecraft.client.input.KeyEvent;
+import com.mojang.blaze3d.platform.InputConstants;
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;
-@Mixin(Keyboard.class)
+@Mixin(KeyboardHandler.class)
public class KeyPressInWorldEventPatch {
- @Inject(method = "onKey", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/KeyBinding;onKeyPressed(Lnet/minecraft/client/util/InputUtil$Key;)V"))
- public void onKeyBoardInWorld(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) {
- WorldKeyboardEvent.Companion.publish(new WorldKeyboardEvent(key, scancode, modifiers));
- }
+ @WrapWithCondition(method = "keyPress", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyMapping;click(Lcom/mojang/blaze3d/platform/InputConstants$Key;)V"))
+ public boolean onKeyBoardInWorld(InputConstants.Key key, @Local(argsOnly = true) KeyEvent keyInput) {
+ var event = WorldKeyboardEvent.Companion.publish(new WorldKeyboardEvent(GenericInputAction.of(keyInput), InputModifiers.of(keyInput)));
+ return !event.getCancelled();
+ }
}
diff --git a/src/main/java/moe/nea/firmament/mixins/LenientProfileComponentPatch.java b/src/main/java/moe/nea/firmament/mixins/LenientProfileComponentPatch.java
deleted file mode 100644
index 76b34ba..0000000
--- a/src/main/java/moe/nea/firmament/mixins/LenientProfileComponentPatch.java
+++ /dev/null
@@ -1,25 +0,0 @@
-
-package moe.nea.firmament.mixins;
-
-import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
-import com.mojang.serialization.Codec;
-import com.mojang.serialization.DataResult;
-import com.mojang.serialization.Lifecycle;
-import com.mojang.util.UndashedUuid;
-import moe.nea.firmament.util.json.FirmCodecs;
-import net.minecraft.component.type.ProfileComponent;
-import net.minecraft.util.Uuids;
-import org.objectweb.asm.Opcodes;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-
-import java.util.UUID;
-
-@Mixin(ProfileComponent.class)
-public class LenientProfileComponentPatch {
- // lambda in RecordCodecBuilder.create for BASE_CODEC
- @ModifyExpressionValue(method = "method_57508", at = @At(value = "FIELD", opcode = Opcodes.GETSTATIC, target = "Lnet/minecraft/util/Uuids;INT_STREAM_CODEC:Lcom/mojang/serialization/Codec;"))
- private static Codec<UUID> onStaticInit(Codec<UUID> original) {
- return FirmCodecs.UUID_LENIENT_PREFER_INT_STREAM;
- }
-}
diff --git a/src/main/java/moe/nea/firmament/mixins/MainWindowFirstLoadPatch.java b/src/main/java/moe/nea/firmament/mixins/MainWindowFirstLoadPatch.java
index 0a90b35..2f82fd9 100644
--- a/src/main/java/moe/nea/firmament/mixins/MainWindowFirstLoadPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/MainWindowFirstLoadPatch.java
@@ -2,8 +2,8 @@ package moe.nea.firmament.mixins;
import moe.nea.firmament.Firmament;
import moe.nea.firmament.events.DebugInstantiateEvent;
-import net.minecraft.client.gui.LogoDrawer;
-import net.minecraft.client.gui.screen.TitleScreen;
+import net.minecraft.client.gui.components.LogoRenderer;
+import net.minecraft.client.gui.screens.TitleScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@@ -15,9 +15,9 @@ public class MainWindowFirstLoadPatch {
@Unique
private static boolean hasInited = false;
- @Inject(method = "<init>(ZLnet/minecraft/client/gui/LogoDrawer;)V", at = @At("RETURN"))
- private void onCreate(boolean doBackgroundFade, LogoDrawer logoDrawer, CallbackInfo ci) {
- if (!hasInited) {
+ @Inject(method = "<init>(ZLnet/minecraft/client/gui/components/LogoRenderer;)V", at = @At("RETURN"))
+ private void onCreate(boolean doBackgroundFade, LogoRenderer logoDrawer, CallbackInfo ci) {
+ if (!hasInited && Firmament.INSTANCE.getDEBUG()) {
try {
DebugInstantiateEvent.Companion.publish(new DebugInstantiateEvent());
} catch (Throwable t) {
diff --git a/src/main/java/moe/nea/firmament/mixins/MaintainKeyboardStatePatch.java b/src/main/java/moe/nea/firmament/mixins/MaintainKeyboardStatePatch.java
new file mode 100644
index 0000000..97d524a
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/MaintainKeyboardStatePatch.java
@@ -0,0 +1,17 @@
+package moe.nea.firmament.mixins;
+
+import moe.nea.firmament.keybindings.FirmamentKeyboardState;
+import net.minecraft.client.KeyboardHandler;
+import net.minecraft.client.input.KeyEvent;
+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;
+
+@Mixin(KeyboardHandler.class)
+public class MaintainKeyboardStatePatch {
+ @Inject(method = "keyPress", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/FramerateLimitTracker;onInputReceived()V"))
+ private void onKeyInput(long window, int action, KeyEvent input, CallbackInfo ci) {
+ FirmamentKeyboardState.INSTANCE.maintainState(input, action);
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/MinecraftInitLevelListener.java b/src/main/java/moe/nea/firmament/mixins/MinecraftInitLevelListener.java
new file mode 100644
index 0000000..7c1189b
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/MinecraftInitLevelListener.java
@@ -0,0 +1,26 @@
+package moe.nea.firmament.mixins;
+
+import moe.nea.firmament.util.mc.InitLevel;
+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;
+
+@Mixin(Minecraft.class)
+public class MinecraftInitLevelListener {
+ @Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;initBackendSystem()Lnet/minecraft/util/TimeSource$NanoTimeSource;"))
+ private void onInitRenderBackend(CallbackInfo ci) {
+ InitLevel.bump(InitLevel.RENDER_INIT);
+ }
+
+ @Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;initRenderer(JIZLjava/util/function/BiFunction;Z)V"))
+ private void onInitRender(CallbackInfo ci) {
+ InitLevel.bump(InitLevel.RENDER);
+ }
+
+ @Inject(method = "<init>", at = @At(value = "TAIL"))
+ private void onFinishedLoading(CallbackInfo ci) {
+ InitLevel.bump(InitLevel.MAIN_MENU);
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java b/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java
index e607ba3..c7555fb 100644
--- a/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java
+++ b/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java
@@ -4,16 +4,20 @@ package moe.nea.firmament.mixins;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
-import com.llamalad7.mixinextras.sugar.Local;
import moe.nea.firmament.events.*;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.gui.screen.ingame.HandledScreen;
-import net.minecraft.entity.player.PlayerInventory;
-import net.minecraft.item.ItemStack;
-import net.minecraft.screen.ScreenHandler;
-import net.minecraft.screen.slot.Slot;
-import net.minecraft.screen.slot.SlotActionType;
-import net.minecraft.text.Text;
+import moe.nea.firmament.events.HandledScreenClickEvent;
+import moe.nea.firmament.keybindings.GenericInputAction;
+import moe.nea.firmament.keybindings.InputModifiers;
+import net.minecraft.client.input.MouseButtonEvent;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
+import net.minecraft.client.input.KeyEvent;
+import net.minecraft.world.entity.player.Inventory;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.inventory.AbstractContainerMenu;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.inventory.ClickType;
+import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -22,77 +26,68 @@ 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.CallbackInfoReturnable;
-import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
-import java.util.Iterator;
-
-@Mixin(value = HandledScreen.class, priority = 990)
-public abstract class MixinHandledScreen<T extends ScreenHandler> {
+@Mixin(value = AbstractContainerScreen.class, priority = 990)
+public abstract class MixinHandledScreen<T extends AbstractContainerMenu> {
@Shadow
@Final
- protected T handler;
+ protected T menu;
@Shadow
- public abstract T getScreenHandler();
+ public abstract T getMenu();
@Shadow
- protected int y;
+ protected int topPos;
@Shadow
- protected int x;
+ protected int leftPos;
@Unique
- PlayerInventory playerInventory;
+ Inventory playerInventory;
@Inject(method = "<init>", at = @At("TAIL"))
- public void savePlayerInventory(ScreenHandler handler, PlayerInventory inventory, Text title, CallbackInfo ci) {
+ public void savePlayerInventory(AbstractContainerMenu handler, Inventory inventory, Component title, CallbackInfo ci) {
this.playerInventory = inventory;
}
- @Inject(method = "keyPressed", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;handleHotbarKeyPressed(II)Z", shift = At.Shift.BEFORE), cancellable = true)
- public void onKeyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable<Boolean> cir) {
- if (HandledScreenKeyPressedEvent.Companion.publish(new HandledScreenKeyPressedEvent((HandledScreen<?>) (Object) this, keyCode, scanCode, modifiers)).getCancelled()) {
- cir.setReturnValue(true);
- }
- }
-
- @Inject(method = "mouseClicked", at = @At("HEAD"), cancellable = true)
- public void onMouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable<Boolean> cir) {
- if (HandledScreenClickEvent.Companion.publish(new HandledScreenClickEvent((HandledScreen<?>) (Object) this, mouseX, mouseY, button)).getCancelled()) {
+ @Inject(method = "mouseReleased", at = @At("HEAD"), cancellable = true)
+ private void onMouseReleased(MouseButtonEvent click, CallbackInfoReturnable<Boolean> cir) {
+ var self = (AbstractContainerScreen<?>) (Object) this;
+ var clickEvent = new HandledScreenClickEvent(self, click.x(), click.y(), click.button());
+ var keyEvent = new HandledScreenKeyReleasedEvent(self, GenericInputAction.mouse(click), InputModifiers.current());
+ if (HandledScreenClickEvent.Companion.publish(clickEvent).getCancelled()
+ || HandledScreenKeyReleasedEvent.Companion.publish(keyEvent).getCancelled()) {
cir.setReturnValue(true);
}
}
- @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawForeground(Lnet/minecraft/client/gui/DrawContext;II)V", shift = At.Shift.AFTER))
- public void onAfterRenderForeground(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
- context.getMatrices().push();
- context.getMatrices().translate(-x, -y, 0);
- HandledScreenForegroundEvent.Companion.publish(new HandledScreenForegroundEvent((HandledScreen<?>) (Object) this, context, mouseX, mouseY, delta));
- context.getMatrices().pop();
+ @Inject(method = "renderContents", at = @At("HEAD"))
+ public void onAfterRenderForeground(GuiGraphics context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
+ HandledScreenForegroundEvent.Companion.publish(new HandledScreenForegroundEvent((AbstractContainerScreen<?>) (Object) this, context, mouseX, mouseY, delta));
}
- @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true)
- public void onMouseClickedSlot(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) {
- if (slotId == -999 && getScreenHandler() != null && actionType == SlotActionType.PICKUP) { // -999 is code for "clicked outside the main window"
- ItemStack cursorStack = getScreenHandler().getCursorStack();
- if (cursorStack != null && IsSlotProtectedEvent.shouldBlockInteraction(slot, SlotActionType.THROW, cursorStack)) {
+ @Inject(method = "slotClicked(Lnet/minecraft/world/inventory/Slot;IILnet/minecraft/world/inventory/ClickType;)V", at = @At("HEAD"), cancellable = true)
+ public void onMouseClickedSlot(Slot slot, int slotId, int button, ClickType actionType, CallbackInfo ci) {
+ if (slotId == -999 && getMenu() != null && actionType == ClickType.PICKUP) { // -999 is code for "clicked outside the main window"
+ ItemStack cursorStack = getMenu().getCarried();
+ if (cursorStack != null && IsSlotProtectedEvent.shouldBlockInteraction(slot, ClickType.THROW, IsSlotProtectedEvent.MoveOrigin.INVENTORY_MOVE, cursorStack)) {
ci.cancel();
return;
}
}
- if (IsSlotProtectedEvent.shouldBlockInteraction(slot, actionType)) {
+ if (IsSlotProtectedEvent.shouldBlockInteraction(slot, actionType, IsSlotProtectedEvent.MoveOrigin.INVENTORY_MOVE)) {
ci.cancel();
return;
}
- if (actionType == SlotActionType.SWAP && 0 <= button && button < 9) {
- if (IsSlotProtectedEvent.shouldBlockInteraction(new Slot(playerInventory, button, 0, 0), actionType)) {
+ if (actionType == ClickType.SWAP && 0 <= button && button < 9) {
+ if (IsSlotProtectedEvent.shouldBlockInteraction(new Slot(playerInventory, button, 0, 0), actionType, IsSlotProtectedEvent.MoveOrigin.INVENTORY_MOVE)) {
ci.cancel();
}
}
}
- @WrapOperation(method = "drawSlots", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawSlot(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/screen/slot/Slot;)V"))
- public void onDrawSlots(HandledScreen instance, DrawContext context, Slot slot, Operation<Void> original) {
+ @WrapOperation(method = "renderSlots", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;renderSlot(Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/world/inventory/Slot;)V"))
+ public void onDrawSlots(AbstractContainerScreen instance, GuiGraphics context, Slot slot, Operation<Void> original) {
var before = new SlotRenderEvents.Before(context, slot);
SlotRenderEvents.Before.Companion.publish(before);
original.call(instance, context, slot);
diff --git a/src/main/java/moe/nea/firmament/mixins/MixinPlayerScreenHandler.java b/src/main/java/moe/nea/firmament/mixins/MixinPlayerScreenHandler.java
new file mode 100644
index 0000000..2210c9e
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/MixinPlayerScreenHandler.java
@@ -0,0 +1,31 @@
+package moe.nea.firmament.mixins;
+
+import moe.nea.firmament.features.fixes.Fixes;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.entity.player.Inventory;
+import net.minecraft.world.inventory.InventoryMenu;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Unique;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(InventoryMenu.class)
+public class MixinPlayerScreenHandler {
+
+ @Unique
+ private static final int OFF_HAND_SLOT = 40;
+
+ @Inject(method = "<init>", at = @At("TAIL"))
+ private void moveOffHandSlot(Inventory inventory, boolean onServer, Player owner, CallbackInfo ci) {
+ if (Fixes.TConfig.INSTANCE.getHideOffHand()) {
+ InventoryMenu self = (InventoryMenu) (Object) this;
+ self.slots.stream()
+ .filter(slot -> slot.getContainerSlot() == OFF_HAND_SLOT)
+ .forEach(slot -> {
+ slot.x = -1000;
+ slot.y = -1000;
+ });
+ }
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/MixinRecipeBookScreen.java b/src/main/java/moe/nea/firmament/mixins/MixinRecipeBookScreen.java
new file mode 100644
index 0000000..d0ec17c
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/MixinRecipeBookScreen.java
@@ -0,0 +1,16 @@
+package moe.nea.firmament.mixins;
+
+import moe.nea.firmament.features.fixes.Fixes;
+import net.minecraft.client.gui.screens.inventory.AbstractRecipeBookScreen;
+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;
+
+@Mixin(value = AbstractRecipeBookScreen.class, priority = 999)
+public class MixinRecipeBookScreen {
+ @Inject(method = "initButton", at = @At("HEAD"), cancellable = true)
+ public void addRecipeBook(CallbackInfo ci) {
+ if (Fixes.TConfig.INSTANCE.getHideRecipeBook()) ci.cancel();
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/MousePressInWorldEventPatch.java b/src/main/java/moe/nea/firmament/mixins/MousePressInWorldEventPatch.java
new file mode 100644
index 0000000..e0ae61b
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/MousePressInWorldEventPatch.java
@@ -0,0 +1,22 @@
+package moe.nea.firmament.mixins;
+
+import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
+import com.llamalad7.mixinextras.sugar.Local;
+import moe.nea.firmament.events.WorldKeyboardEvent;
+import moe.nea.firmament.keybindings.GenericInputAction;
+import moe.nea.firmament.keybindings.InputModifiers;
+import net.minecraft.client.MouseHandler;
+import net.minecraft.client.input.MouseButtonInfo;
+import com.mojang.blaze3d.platform.InputConstants;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(MouseHandler.class)
+public class MousePressInWorldEventPatch {
+ @WrapWithCondition(method = "onButton", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyMapping;click(Lcom/mojang/blaze3d/platform/InputConstants$Key;)V"))
+ public boolean onKeyBoardInWorld(InputConstants.Key key, @Local(argsOnly = true) MouseButtonInfo input) { // TODO: handle modified mouse click instead
+ var event = WorldKeyboardEvent.Companion.publish(new WorldKeyboardEvent(GenericInputAction.of(input),
+ InputModifiers.of(input)));
+ return !event.getCancelled();
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/OutgoingPacketEventPatch.java b/src/main/java/moe/nea/firmament/mixins/OutgoingPacketEventPatch.java
index 25505b7..fd6869c 100644
--- a/src/main/java/moe/nea/firmament/mixins/OutgoingPacketEventPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/OutgoingPacketEventPatch.java
@@ -3,16 +3,16 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.events.OutgoingPacketEvent;
-import net.minecraft.client.network.ClientCommonNetworkHandler;
-import net.minecraft.network.packet.Packet;
+import net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl;
+import net.minecraft.network.protocol.Packet;
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;
-@Mixin(ClientCommonNetworkHandler.class)
+@Mixin(ClientCommonPacketListenerImpl.class)
public class OutgoingPacketEventPatch {
- @Inject(method = "sendPacket(Lnet/minecraft/network/packet/Packet;)V", at = @At("HEAD"), cancellable = true)
+ @Inject(method = "send(Lnet/minecraft/network/protocol/Packet;)V", at = @At("HEAD"), cancellable = true)
public void onSendPacket(Packet<?> packet, CallbackInfo ci) {
if (OutgoingPacketEvent.Companion.publish(new OutgoingPacketEvent(packet)).getCancelled()) {
ci.cancel();
diff --git a/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java b/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java
index 9a4626f..9ee271d 100644
--- a/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java
@@ -3,26 +3,26 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.events.IsSlotProtectedEvent;
-import net.minecraft.client.network.ClientPlayerEntity;
-import net.minecraft.entity.player.PlayerEntity;
-import net.minecraft.screen.slot.Slot;
-import net.minecraft.screen.slot.SlotActionType;
+import net.minecraft.client.player.LocalPlayer;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.world.inventory.ClickType;
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.CallbackInfoReturnable;
-@Mixin(ClientPlayerEntity.class)
-public abstract class PlayerDropEventPatch extends PlayerEntity {
- public PlayerDropEventPatch() {
- super(null, null, 0, null);
- }
+@Mixin(LocalPlayer.class)
+public abstract class PlayerDropEventPatch extends Player {
+ public PlayerDropEventPatch() {
+ super(null, null);
+ }
- @Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true)
- public void onDropSelectedItem(boolean entireStack, CallbackInfoReturnable<Boolean> cir) {
- Slot fakeSlot = new Slot(getInventory(), getInventory().selectedSlot, 0, 0);
- if (IsSlotProtectedEvent.shouldBlockInteraction(fakeSlot, SlotActionType.THROW)) {
- cir.setReturnValue(false);
- }
- }
+ @Inject(method = "drop", at = @At("HEAD"), cancellable = true)
+ public void onDropSelectedItem(boolean entireStack, CallbackInfoReturnable<Boolean> cir) {
+ Slot fakeSlot = new Slot(getInventory(), getInventory().getSelectedSlot(), 0, 0);
+ if (IsSlotProtectedEvent.shouldBlockInteraction(fakeSlot, ClickType.THROW, IsSlotProtectedEvent.MoveOrigin.DROP_FROM_HOTBAR)) {
+ cir.setReturnValue(false);
+ }
+ }
}
diff --git a/src/main/java/moe/nea/firmament/mixins/PropertySignatureIgnorePatch.java b/src/main/java/moe/nea/firmament/mixins/PropertySignatureIgnorePatch.java
deleted file mode 100644
index e7331c5..0000000
--- a/src/main/java/moe/nea/firmament/mixins/PropertySignatureIgnorePatch.java
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-package moe.nea.firmament.mixins;
-
-import com.mojang.authlib.properties.Property;
-import moe.nea.firmament.features.fixes.Fixes;
-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.CallbackInfoReturnable;
-
-import java.security.PublicKey;
-
-@Mixin(value = Property.class, remap = false)
-public class PropertySignatureIgnorePatch {
- @Inject(method = "isSignatureValid", cancellable = true, at = @At("HEAD"), remap = false)
- public void onValidateSignature(PublicKey publicKey, CallbackInfoReturnable<Boolean> cir) {
- if (Fixes.TConfig.INSTANCE.getFixUnsignedPlayerSkins()) {
- cir.setReturnValue(true);
- }
- }
-
- @Inject(method = "signature", cancellable = true, at = @At("HEAD"), remap = false)
- public void returnEmptySignatureInsteadOfNull(CallbackInfoReturnable<String> cir) {
- if (Fixes.TConfig.INSTANCE.getFixUnsignedPlayerSkins()) {
- cir.setReturnValue("");
- }
- }
-
- @Inject(method = "hasSignature", cancellable = true, at = @At("HEAD"), remap = false)
- public void onHasSignature(CallbackInfoReturnable<Boolean> cir) {
- if (Fixes.TConfig.INSTANCE.getFixUnsignedPlayerSkins()) {
- cir.setReturnValue(true);
- }
- }
-}
diff --git a/src/main/java/moe/nea/firmament/mixins/ResourceReloaderRegistrationPatch.java b/src/main/java/moe/nea/firmament/mixins/ResourceReloaderRegistrationPatch.java
index 28fe3d9..a29cdc0 100644
--- a/src/main/java/moe/nea/firmament/mixins/ResourceReloaderRegistrationPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/ResourceReloaderRegistrationPatch.java
@@ -2,9 +2,9 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.events.FinalizeResourceManagerEvent;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.RunArgs;
-import net.minecraft.resource.ReloadableResourceManagerImpl;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.main.GameConfig;
+import net.minecraft.server.packs.resources.ReloadableResourceManager;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -12,14 +12,14 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-@Mixin(MinecraftClient.class)
+@Mixin(Minecraft.class)
public class ResourceReloaderRegistrationPatch {
@Shadow
@Final
- private ReloadableResourceManagerImpl resourceManager;
+ private ReloadableResourceManager resourceManager;
- @Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePackManager;createResourcePacks()Ljava/util/List;", shift = At.Shift.BEFORE))
- private void onBeforeResourcePackCreation(RunArgs args, CallbackInfo ci) {
+ @Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/repository/PackRepository;openAllSelected()Ljava/util/List;", shift = At.Shift.BEFORE))
+ private void onBeforeResourcePackCreation(GameConfig args, CallbackInfo ci) {
FinalizeResourceManagerEvent.Companion.publish(new FinalizeResourceManagerEvent(this.resourceManager));
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/SaveCursorPositionPatch.java b/src/main/java/moe/nea/firmament/mixins/SaveCursorPositionPatch.java
index fd3adca..3cfd0d6 100644
--- a/src/main/java/moe/nea/firmament/mixins/SaveCursorPositionPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/SaveCursorPositionPatch.java
@@ -4,7 +4,7 @@ package moe.nea.firmament.mixins;
import kotlin.Pair;
import moe.nea.firmament.features.inventory.SaveCursorPosition;
-import net.minecraft.client.Mouse;
+import net.minecraft.client.MouseHandler;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -12,29 +12,29 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-@Mixin(Mouse.class)
+@Mixin(MouseHandler.class)
public class SaveCursorPositionPatch {
- @Shadow
- private double x;
-
- @Shadow
- private double y;
-
- @Inject(method = "lockCursor", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/Mouse;cursorLocked:Z"))
- public void onLockCursor(CallbackInfo ci) {
- SaveCursorPosition.saveCursorOriginal(x, y);
- }
-
- @Inject(method = "lockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/Window;getHandle()J"))
- public void onLockCursorAfter(CallbackInfo ci) {
- SaveCursorPosition.saveCursorMiddle(x, y);
- }
-
- @Inject(method = "unlockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/Window;getHandle()J"))
- public void onUnlockCursor(CallbackInfo ci) {
- Pair<Double, Double> cursorPosition = SaveCursorPosition.loadCursor(this.x, this.y);
- if (cursorPosition == null) return;
- this.x = cursorPosition.getFirst();
- this.y = cursorPosition.getSecond();
- }
+ @Shadow
+ private double xpos;
+
+ @Shadow
+ private double ypos;
+
+ @Inject(method = "grabMouse", at = @At(value = "HEAD"))
+ public void onLockCursor(CallbackInfo ci) {
+ SaveCursorPosition.saveCursorOriginal(xpos, ypos);
+ }
+
+ @Inject(method = "grabMouse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getWindow()Lcom/mojang/blaze3d/platform/Window;", ordinal = 2))
+ public void onLockCursorAfter(CallbackInfo ci) {
+ SaveCursorPosition.saveCursorMiddle(xpos, ypos);
+ }
+
+ @Inject(method = "releaseMouse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getWindow()Lcom/mojang/blaze3d/platform/Window;", ordinal = 2))
+ public void onUnlockCursor(CallbackInfo ci) {
+ Pair<Double, Double> cursorPosition = SaveCursorPosition.loadCursor(this.xpos, this.ypos);
+ if (cursorPosition == null) return;
+ this.xpos = cursorPosition.getFirst();
+ this.ypos = cursorPosition.getSecond();
+ }
}
diff --git a/src/main/java/moe/nea/firmament/mixins/SaveOriginalCommandTreePacket.java b/src/main/java/moe/nea/firmament/mixins/SaveOriginalCommandTreePacket.java
index 2f2f188..5974277 100644
--- a/src/main/java/moe/nea/firmament/mixins/SaveOriginalCommandTreePacket.java
+++ b/src/main/java/moe/nea/firmament/mixins/SaveOriginalCommandTreePacket.java
@@ -1,17 +1,17 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.features.chat.QuickCommands;
-import net.minecraft.client.network.ClientPlayNetworkHandler;
-import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket;
+import net.minecraft.client.multiplayer.ClientPacketListener;
+import net.minecraft.network.protocol.game.ClientboundCommandsPacket;
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;
-@Mixin(ClientPlayNetworkHandler.class)
+@Mixin(ClientPacketListener.class)
public class SaveOriginalCommandTreePacket {
- @Inject(method = "onCommandTree", at = @At(value = "RETURN"))
- private void saveUnmodifiedCommandTree(CommandTreeS2CPacket packet, CallbackInfo ci) {
+ @Inject(method = "handleCommands", at = @At(value = "RETURN"))
+ private void saveUnmodifiedCommandTree(ClientboundCommandsPacket packet, CallbackInfo ci) {
QuickCommands.INSTANCE.setLastReceivedTreePacket(packet);
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/ScreenChangeEventPatch.java b/src/main/java/moe/nea/firmament/mixins/ScreenChangeEventPatch.java
index 6d19405..37423f0 100644
--- a/src/main/java/moe/nea/firmament/mixins/ScreenChangeEventPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/ScreenChangeEventPatch.java
@@ -5,8 +5,8 @@ package moe.nea.firmament.mixins;
import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
import moe.nea.firmament.events.ScreenChangeEvent;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.screens.Screen;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -14,15 +14,15 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-@Mixin(MinecraftClient.class)
+@Mixin(Minecraft.class)
public abstract class ScreenChangeEventPatch {
@Shadow
@Nullable
- public Screen currentScreen;
+ public Screen screen;
@Inject(method = "setScreen", at = @At("HEAD"), cancellable = true)
public void onScreenChange(Screen screen, CallbackInfo ci, @Local(argsOnly = true) LocalRef<Screen> screenLocalRef) {
- var event = new ScreenChangeEvent(currentScreen, screen);
+ var event = new ScreenChangeEvent(screen, screen);
if (ScreenChangeEvent.Companion.publish(event).getCancelled()) {
ci.cancel();
} else if (event.getOverrideScreen() != null) {
diff --git a/src/main/java/moe/nea/firmament/mixins/ScreenInputEvents.java b/src/main/java/moe/nea/firmament/mixins/ScreenInputEvents.java
new file mode 100644
index 0000000..edc8fd6
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/ScreenInputEvents.java
@@ -0,0 +1,34 @@
+package moe.nea.firmament.mixins;
+
+import moe.nea.firmament.events.HandledScreenKeyPressedEvent;
+import moe.nea.firmament.keybindings.GenericInputAction;
+import moe.nea.firmament.keybindings.InputModifiers;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
+import net.minecraft.client.input.KeyEvent;
+import net.minecraft.client.input.MouseButtonEvent;
+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.CallbackInfoReturnable;
+
+@Mixin(Screen.class)
+public class ScreenInputEvents {
+ @Inject(method = "keyPressed", at = @At("HEAD"), cancellable = true)
+ public void onKeyPressed(KeyEvent input, CallbackInfoReturnable<Boolean> cir) {
+ if (HandledScreenKeyPressedEvent.Companion.publish(new HandledScreenKeyPressedEvent(
+ (Screen) (Object) this,
+ GenericInputAction.of(input),
+ InputModifiers.of(input))).getCancelled()) {
+ cir.setReturnValue(true);
+ }
+ }
+
+ public boolean onMouseClicked$firmament(MouseButtonEvent click, boolean doubled) {
+ return HandledScreenKeyPressedEvent.Companion.publish(
+ new HandledScreenKeyPressedEvent((Screen) (Object) this,
+ GenericInputAction.mouse(click), InputModifiers.current())).getCancelled();
+ }
+
+
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/SlotClickEventPatch.java b/src/main/java/moe/nea/firmament/mixins/SlotClickEventPatch.java
index 21e7899..db87f37 100644
--- a/src/main/java/moe/nea/firmament/mixins/SlotClickEventPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/SlotClickEventPatch.java
@@ -5,11 +5,11 @@ import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
import moe.nea.firmament.events.SlotClickEvent;
-import net.minecraft.client.network.ClientPlayerInteractionManager;
-import net.minecraft.entity.player.PlayerEntity;
-import net.minecraft.item.ItemStack;
-import net.minecraft.screen.ScreenHandler;
-import net.minecraft.screen.slot.SlotActionType;
+import net.minecraft.client.multiplayer.MultiPlayerGameMode;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.inventory.AbstractContainerMenu;
+import net.minecraft.world.inventory.ClickType;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -17,18 +17,19 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-@Mixin(ClientPlayerInteractionManager.class)
+@Mixin(MultiPlayerGameMode.class)
public class SlotClickEventPatch {
- @Inject(method = "clickSlot", at = @At(value = "FIELD", target = "Lnet/minecraft/screen/ScreenHandler;slots:Lnet/minecraft/util/collection/DefaultedList;", opcode = Opcodes.GETFIELD))
- private void onSlotClickSaveSlot(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci, @Local ScreenHandler handler, @Share("slotContent") LocalRef<ItemStack> slotContent) {
+ @Inject(method = "handleInventoryMouseClick", at = @At(value = "FIELD", target =
+ "Lnet/minecraft/world/inventory/AbstractContainerMenu;slots:Lnet/minecraft/core/NonNullList;", opcode = Opcodes.GETFIELD))
+ private void onSlotClickSaveSlot(int containerId, int slotId, int mouseButton, ClickType clickType, Player player, CallbackInfo ci, @Local AbstractContainerMenu handler, @Share("slotContent") LocalRef<ItemStack> slotContent) {
if (0 <= slotId && slotId < handler.slots.size()) {
- slotContent.set(handler.getSlot(slotId).getStack().copy());
+ slotContent.set(handler.getSlot(slotId).getItem().copy());
}
}
- @Inject(method = "clickSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V"))
- private void onSlotClick(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci, @Local ScreenHandler handler, @Share("slotContent") LocalRef<ItemStack> slotContent) {
+ @Inject(method = "handleInventoryMouseClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V"))
+ private void onSlotClick(int syncId, int slotId, int button, ClickType actionType, Player player, CallbackInfo ci, @Local AbstractContainerMenu handler, @Share("slotContent") LocalRef<ItemStack> slotContent) {
if (0 <= slotId && slotId < handler.slots.size()) {
SlotClickEvent.Companion.publish(new SlotClickEvent(
handler.getSlot(slotId),
diff --git a/src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java b/src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java
index 06ecbd4..49661d0 100644
--- a/src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java
+++ b/src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java
@@ -3,51 +3,51 @@ package moe.nea.firmament.mixins;
import moe.nea.firmament.events.ChestInventoryUpdateEvent;
import moe.nea.firmament.events.PlayerInventoryUpdate;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.network.ClientCommonNetworkHandler;
-import net.minecraft.client.network.ClientConnectionState;
-import net.minecraft.client.network.ClientPlayNetworkHandler;
-import net.minecraft.network.ClientConnection;
-import net.minecraft.network.packet.s2c.play.InventoryS2CPacket;
-import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl;
+import net.minecraft.client.multiplayer.CommonListenerCookie;
+import net.minecraft.client.multiplayer.ClientPacketListener;
+import net.minecraft.network.Connection;
+import net.minecraft.network.protocol.game.ClientboundContainerSetContentPacket;
+import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
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;
-@Mixin(ClientPlayNetworkHandler.class)
-public abstract class SlotUpdateListener extends ClientCommonNetworkHandler {
- protected SlotUpdateListener(MinecraftClient client, ClientConnection connection, ClientConnectionState connectionState) {
+@Mixin(ClientPacketListener.class)
+public abstract class SlotUpdateListener extends ClientCommonPacketListenerImpl {
+ protected SlotUpdateListener(Minecraft client, Connection connection, CommonListenerCookie connectionState) {
super(client, connection, connectionState);
}
@Inject(
- method = "onScreenHandlerSlotUpdate",
+ method = "handleContainerSetSlot",
at = @At(value = "TAIL"))
private void onSingleSlotUpdate(
- ScreenHandlerSlotUpdateS2CPacket packet,
+ ClientboundContainerSetSlotPacket packet,
CallbackInfo ci) {
- var player = this.client.player;
+ var player = this.minecraft.player;
assert player != null;
- if (packet.getSyncId() == 0) {
- PlayerInventoryUpdate.Companion.publish(new PlayerInventoryUpdate.Single(packet.getSlot(), packet.getStack()));
- } else if (packet.getSyncId() == player.currentScreenHandler.syncId) {
+ if (packet.getContainerId() == 0) {
+ PlayerInventoryUpdate.Companion.publish(new PlayerInventoryUpdate.Single(packet.getSlot(), packet.getItem()));
+ } else if (packet.getContainerId() == player.containerMenu.containerId) {
ChestInventoryUpdateEvent.Companion.publish(
- new ChestInventoryUpdateEvent.Single(packet.getSlot(), packet.getStack())
+ new ChestInventoryUpdateEvent.Single(packet.getSlot(), packet.getItem())
);
}
}
- @Inject(method = "onInventory",
+ @Inject(method = "handleContainerContent",
at = @At("TAIL"))
- private void onMultiSlotUpdate(InventoryS2CPacket packet, CallbackInfo ci) {
- var player = this.client.player;
+ private void onMultiSlotUpdate(ClientboundContainerSetContentPacket packet, CallbackInfo ci) {
+ var player = this.minecraft.player;
assert player != null;
- if (packet.getSyncId() == 0) {
- PlayerInventoryUpdate.Companion.publish(new PlayerInventoryUpdate.Multi(packet.getContents()));
- } else if (packet.getSyncId() == player.currentScreenHandler.syncId) {
+ if (packet.containerId() == 0) {
+ PlayerInventoryUpdate.Companion.publish(new PlayerInventoryUpdate.Multi(packet.items()));
+ } else if (packet.containerId() == player.containerMenu.containerId) {
ChestInventoryUpdateEvent.Companion.publish(
- new ChestInventoryUpdateEvent.Multi(packet.getContents())
+ new ChestInventoryUpdateEvent.Multi(packet.items())
);
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/SoundReceiveEventPatch.java b/src/main/java/moe/nea/firmament/mixins/SoundReceiveEventPatch.java
index 5c52d70..e685b0c 100644
--- a/src/main/java/moe/nea/firmament/mixins/SoundReceiveEventPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/SoundReceiveEventPatch.java
@@ -1,30 +1,32 @@
package moe.nea.firmament.mixins;
+import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import moe.nea.firmament.events.SoundReceiveEvent;
-import net.minecraft.client.network.ClientPlayNetworkHandler;
-import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket;
-import net.minecraft.util.math.Vec3d;
+import net.minecraft.client.multiplayer.ClientPacketListener;
+import net.minecraft.client.multiplayer.ClientLevel;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.core.Holder;
+import net.minecraft.sounds.SoundSource;
+import net.minecraft.sounds.SoundEvent;
+import net.minecraft.world.phys.Vec3;
+import org.jetbrains.annotations.Nullable;
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;
-@Mixin(ClientPlayNetworkHandler.class)
+@Mixin(ClientPacketListener.class)
public class SoundReceiveEventPatch {
- @Inject(method = "onPlaySound", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;playSound(Lnet/minecraft/entity/player/PlayerEntity;DDDLnet/minecraft/registry/entry/RegistryEntry;Lnet/minecraft/sound/SoundCategory;FFJ)V"), cancellable = true)
- private void postEventWhenSoundIsPlayed(PlaySoundS2CPacket packet, CallbackInfo ci) {
+ @WrapWithCondition(method = "handleSoundEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;playSeededSound(Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/core/Holder;Lnet/minecraft/sounds/SoundSource;FFJ)V"))
+ private boolean postEventWhenSoundIsPlayed(ClientLevel instance, @Nullable Entity source, double x, double y, double z, Holder<SoundEvent> sound, SoundSource category, float volume, float pitch, long seed) {
var event = new SoundReceiveEvent(
- packet.getSound(),
- packet.getCategory(),
- new Vec3d(packet.getX(), packet.getY(), packet.getZ()),
- packet.getPitch(),
- packet.getVolume(),
- packet.getSeed()
+ sound,
+ category,
+ new Vec3(x,y,z),
+ pitch,
+ volume,
+ seed
);
SoundReceiveEvent.Companion.publish(event);
- if (event.getCancelled()) {
- ci.cancel();
- }
+ return !event.getCancelled();
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/ToggleSprintPatch.java b/src/main/java/moe/nea/firmament/mixins/ToggleSprintPatch.java
index 1acbf20..96d03bd 100644
--- a/src/main/java/moe/nea/firmament/mixins/ToggleSprintPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/ToggleSprintPatch.java
@@ -3,16 +3,16 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.features.fixes.Fixes;
-import net.minecraft.client.option.KeyBinding;
+import net.minecraft.client.KeyMapping;
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.CallbackInfoReturnable;
-@Mixin(KeyBinding.class)
+@Mixin(KeyMapping.class)
public class ToggleSprintPatch {
- @Inject(method = "isPressed", at = @At("HEAD"), cancellable = true)
+ @Inject(method = "isDown", at = @At("HEAD"), cancellable = true)
public void onIsPressed(CallbackInfoReturnable<Boolean> cir) {
- Fixes.INSTANCE.handleIsPressed((KeyBinding) (Object) this, cir);
+ Fixes.INSTANCE.handleIsPressed((KeyMapping) (Object) this, cir);
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/TolerateFirmamentTolerateRegistryOwners.java b/src/main/java/moe/nea/firmament/mixins/TolerateFirmamentTolerateRegistryOwners.java
index ac6f614..bc0ece5 100644
--- a/src/main/java/moe/nea/firmament/mixins/TolerateFirmamentTolerateRegistryOwners.java
+++ b/src/main/java/moe/nea/firmament/mixins/TolerateFirmamentTolerateRegistryOwners.java
@@ -1,16 +1,16 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.util.mc.TolerantRegistriesOps;
-import net.minecraft.registry.entry.RegistryEntryOwner;
+import net.minecraft.core.HolderOwner;
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.CallbackInfoReturnable;
-@Mixin(RegistryEntryOwner.class)
+@Mixin(HolderOwner.class)
public interface TolerateFirmamentTolerateRegistryOwners<T> {
- @Inject(method = "ownerEquals", at = @At("HEAD"), cancellable = true)
- private void equalTolerantRegistryOwners(RegistryEntryOwner<T> other, CallbackInfoReturnable<Boolean> cir) {
+ @Inject(method = "canSerializeIn", at = @At("HEAD"), cancellable = true)
+ private void equalTolerantRegistryOwners(HolderOwner<T> other, CallbackInfoReturnable<Boolean> cir) {
if (other instanceof TolerantRegistriesOps.TolerantOwner<?>) {
cir.setReturnValue(true);
}
diff --git a/src/main/java/moe/nea/firmament/mixins/WorldReadyEventPatch.java b/src/main/java/moe/nea/firmament/mixins/WorldReadyEventPatch.java
index d4b8c9e..70ef9cb 100644
--- a/src/main/java/moe/nea/firmament/mixins/WorldReadyEventPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/WorldReadyEventPatch.java
@@ -3,16 +3,15 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.events.WorldReadyEvent;
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
+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;
-@Mixin(MinecraftClient.class)
+@Mixin(Minecraft.class)
public class WorldReadyEventPatch {
- @Inject(method = "joinWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;setWorld(Lnet/minecraft/client/world/ClientWorld;)V", shift = At.Shift.AFTER))
+ @Inject(method = "setLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;updateLevelInEngines(Lnet/minecraft/client/multiplayer/ClientLevel;)V", shift = At.Shift.AFTER))
public void onClose(CallbackInfo ci) {
WorldReadyEvent.Companion.publish(new WorldReadyEvent());
}
diff --git a/src/main/java/moe/nea/firmament/mixins/WorldRenderLastEventPatch.java b/src/main/java/moe/nea/firmament/mixins/WorldRenderLastEventPatch.java
index 847fb4d..a875bcf 100644
--- a/src/main/java/moe/nea/firmament/mixins/WorldRenderLastEventPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/WorldRenderLastEventPatch.java
@@ -2,13 +2,18 @@
package moe.nea.firmament.mixins;
-import com.llamalad7.mixinextras.sugar.Local;
+import com.mojang.blaze3d.buffers.GpuBufferSlice;
import moe.nea.firmament.events.WorldRenderLastEvent;
-import net.minecraft.client.render.*;
-import net.minecraft.client.util.Handle;
-import net.minecraft.client.util.ObjectAllocator;
-import net.minecraft.client.util.math.MatrixStack;
-import net.minecraft.util.profiler.Profiler;
+import net.minecraft.client.renderer.LevelRenderer;
+import net.minecraft.client.renderer.LevelTargetBundle;
+import net.minecraft.client.renderer.RenderBuffers;
+import net.minecraft.client.renderer.culling.Frustum;
+import net.minecraft.client.renderer.state.LevelRenderState;
+import com.mojang.blaze3d.resource.ResourceHandle;
+import com.mojang.blaze3d.vertex.PoseStack;
+import net.minecraft.client.multiplayer.ClientLevel;
+import net.minecraft.util.profiling.ProfilerFiller;
+import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -17,31 +22,30 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-@Mixin(WorldRenderer.class)
+@Mixin(LevelRenderer.class)
public abstract class WorldRenderLastEventPatch {
@Shadow
@Final
- private BufferBuilderStorage bufferBuilders;
+ private RenderBuffers renderBuffers;
@Shadow
- @Final
- private DefaultFramebufferSet framebufferSet;
+ protected abstract void checkPoseStack(PoseStack matrices);
@Shadow
- protected abstract void checkEmpty(MatrixStack matrices);
+ private int ticks;
- @Inject(method = "method_62214", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;pop()V", shift = At.Shift.AFTER))
- public void onWorldRenderLast(Fog fog, RenderTickCounter tickCounter, Camera camera, Profiler profiler, Matrix4f matrix4f, Matrix4f matrix4f2, Handle handle, Handle handle2, Handle handle3, Handle handle4, boolean bl, Frustum frustum, Handle handle5, CallbackInfo ci) {
- var imm = this.bufferBuilders.getEntityVertexConsumers();
- var stack = new MatrixStack();
+ @Inject(method = "method_62214", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/ProfilerFiller;pop()V", shift = At.Shift.AFTER))
+ public void onWorldRenderLast(GpuBufferSlice gpuBufferSlice, LevelRenderState worldRenderState, ProfilerFiller profiler, Matrix4f matrix4f, ResourceHandle handle, ResourceHandle handle2, boolean bl, Frustum frustum, ResourceHandle handle3, ResourceHandle handle4, CallbackInfo ci) {
+ var imm = this.renderBuffers.bufferSource();
+ var stack = new PoseStack();
// TODO: pre-cancel this event if F1 is active
var event = new WorldRenderLastEvent(
- stack, tickCounter,
- camera,
+ stack, ticks,
+ worldRenderState.cameraRenderState,
imm
);
WorldRenderLastEvent.Companion.publish(event);
- imm.draw();
- checkEmpty(stack);
+ imm.endBatch();
+ checkPoseStack(stack);
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorAbstractClientPlayerEntity.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorAbstractClientPlayerEntity.java
index 0a10046..cbd143d 100644
--- a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorAbstractClientPlayerEntity.java
+++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorAbstractClientPlayerEntity.java
@@ -1,13 +1,13 @@
package moe.nea.firmament.mixins.accessor;
-import net.minecraft.client.network.AbstractClientPlayerEntity;
-import net.minecraft.client.network.PlayerListEntry;
+import net.minecraft.client.player.AbstractClientPlayer;
+import net.minecraft.client.multiplayer.PlayerInfo;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
-@Mixin(AbstractClientPlayerEntity.class)
+@Mixin(AbstractClientPlayer.class)
public interface AccessorAbstractClientPlayerEntity {
- @Accessor("playerListEntry")
- void setPlayerListEntry_firmament(PlayerListEntry playerListEntry);
+ @Accessor("playerInfo")
+ void setPlayerListEntry_firmament(PlayerInfo playerListEntry);
}
diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorChatHud.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorChatHud.java
index 72a72f0..0b986ef 100644
--- a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorChatHud.java
+++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorChatHud.java
@@ -1,14 +1,24 @@
package moe.nea.firmament.mixins.accessor;
-import net.minecraft.client.gui.hud.ChatHud;
-import net.minecraft.client.gui.hud.ChatHudLine;
+import net.minecraft.client.gui.components.ChatComponent;
+import net.minecraft.client.GuiMessage;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
+import org.spongepowered.asm.mixin.gen.Invoker;
import java.util.List;
-@Mixin(ChatHud.class)
+@Mixin(ChatComponent.class)
public interface AccessorChatHud {
- @Accessor("messages")
- List<ChatHudLine> getMessages_firmament();
+ @Accessor("allMessages")
+ List<GuiMessage> getMessages_firmament();
+
+ @Accessor("trimmedMessages")
+ List<GuiMessage.Line> getVisibleMessages_firmament();
+
+ @Accessor("chatScrollbarPos")
+ int getScrolledLines_firmament();
+
+ @Invoker("screenToChatY")
+ double toChatLineY_firmament(double y);
}
diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorHandledScreen.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorHandledScreen.java
index 7ed04b1..5e0c669 100644
--- a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorHandledScreen.java
+++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorHandledScreen.java
@@ -1,41 +1,39 @@
-
-
package moe.nea.firmament.mixins.accessor;
-import net.minecraft.client.gui.screen.ingame.HandledScreen;
-import net.minecraft.screen.slot.Slot;
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
+import net.minecraft.world.inventory.Slot;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
-@Mixin(HandledScreen.class)
+@Mixin(AbstractContainerScreen.class)
public interface AccessorHandledScreen {
- @Accessor("focusedSlot")
+ @Accessor("hoveredSlot")
@Nullable
- Slot getFocusedSlot_Firmament();
+ Slot getFocusedSlot_Firmament();
- @Accessor("backgroundWidth")
+ @Accessor("imageWidth")
int getBackgroundWidth_Firmament();
- @Accessor("backgroundWidth")
+ @Accessor("imageWidth")
void setBackgroundWidth_Firmament(int newBackgroundWidth);
- @Accessor("backgroundHeight")
+ @Accessor("imageHeight")
int getBackgroundHeight_Firmament();
- @Accessor("backgroundHeight")
+ @Accessor("imageHeight")
void setBackgroundHeight_Firmament(int newBackgroundHeight);
- @Accessor("x")
+ @Accessor("leftPos")
int getX_Firmament();
- @Accessor("x")
+ @Accessor("leftPos")
void setX_Firmament(int newX);
- @Accessor("y")
+ @Accessor("topPos")
int getY_Firmament();
- @Accessor("y")
+ @Accessor("topPos")
void setY_Firmament(int newY);
}
diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorNbtComponent.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorNbtComponent.java
new file mode 100644
index 0000000..672badf
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorNbtComponent.java
@@ -0,0 +1,12 @@
+package moe.nea.firmament.mixins.accessor;
+
+import net.minecraft.world.item.component.CustomData;
+import net.minecraft.nbt.CompoundTag;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(CustomData.class)
+public interface AccessorNbtComponent {
+ @Accessor("tag")
+ CompoundTag getUnsafeNbt_firmament();
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorPlayerListHud.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorPlayerListHud.java
new file mode 100644
index 0000000..58c9ad9
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorPlayerListHud.java
@@ -0,0 +1,31 @@
+package moe.nea.firmament.mixins.accessor;
+
+import net.minecraft.client.gui.components.PlayerTabOverlay;
+import net.minecraft.client.multiplayer.PlayerInfo;
+import net.minecraft.network.chat.Component;
+import org.jetbrains.annotations.Nullable;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+import java.util.Comparator;
+import java.util.List;
+
+@Mixin(PlayerTabOverlay.class)
+public interface AccessorPlayerListHud {
+
+ @Accessor("PLAYER_COMPARATOR")
+ static Comparator<PlayerInfo> getEntryOrdering() {
+ throw new AssertionError();
+ }
+
+ @Invoker("getPlayerInfos")
+ List<PlayerInfo> collectPlayerEntries_firmament();
+
+ @Accessor("footer")
+ @Nullable Component getFooter_firmament();
+
+ @Accessor("header")
+ @Nullable Component getHeader_firmament();
+
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorScreenHandler.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorScreenHandler.java
new file mode 100644
index 0000000..0a75ea1
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorScreenHandler.java
@@ -0,0 +1,12 @@
+package moe.nea.firmament.mixins.accessor;
+
+import net.minecraft.world.inventory.AbstractContainerMenu;
+import net.minecraft.world.inventory.MenuType;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(AbstractContainerMenu.class)
+public interface AccessorScreenHandler {
+ @Accessor("menuType")
+ MenuType<?> getType_firmament();
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorWorldRenderer.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorWorldRenderer.java
new file mode 100644
index 0000000..9164af0
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorWorldRenderer.java
@@ -0,0 +1,17 @@
+package moe.nea.firmament.mixins.accessor;
+
+import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
+import net.minecraft.client.renderer.LevelRenderer;
+import net.minecraft.server.level.BlockDestructionProgress;
+import org.jetbrains.annotations.NotNull;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.SortedSet;
+
+@Mixin(LevelRenderer.class)
+public interface AccessorWorldRenderer {
+ @Accessor("destructionProgress")
+ @NotNull
+ Long2ObjectMap<SortedSet<BlockDestructionProgress>> getBlockBreakingProgressions_firmament();
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/customgui/OriginalSlotCoords.java b/src/main/java/moe/nea/firmament/mixins/customgui/OriginalSlotCoords.java
index c705625..203b87e 100644
--- a/src/main/java/moe/nea/firmament/mixins/customgui/OriginalSlotCoords.java
+++ b/src/main/java/moe/nea/firmament/mixins/customgui/OriginalSlotCoords.java
@@ -2,7 +2,7 @@
package moe.nea.firmament.mixins.customgui;
import moe.nea.firmament.util.customgui.CoordRememberingSlot;
-import net.minecraft.screen.slot.Slot;
+import net.minecraft.world.inventory.Slot;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
diff --git a/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java b/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java
index 6e1090a..b0fbbe1 100644
--- a/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java
+++ b/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java
@@ -4,17 +4,21 @@ package moe.nea.firmament.mixins.customgui;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
-import com.llamalad7.mixinextras.sugar.Local;
import moe.nea.firmament.events.HandledScreenKeyReleasedEvent;
+import moe.nea.firmament.keybindings.GenericInputAction;
+import moe.nea.firmament.keybindings.InputModifiers;
import moe.nea.firmament.util.customgui.CoordRememberingSlot;
import moe.nea.firmament.util.customgui.CustomGui;
import moe.nea.firmament.util.customgui.HasCustomGui;
-import net.minecraft.client.gui.DrawContext;
-import net.minecraft.client.gui.screen.Screen;
-import net.minecraft.client.gui.screen.ingame.HandledScreen;
-import net.minecraft.screen.ScreenHandler;
-import net.minecraft.screen.slot.Slot;
-import net.minecraft.text.Text;
+import net.minecraft.client.input.MouseButtonEvent;
+import net.minecraft.client.gui.GuiGraphics;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
+import net.minecraft.client.input.CharacterEvent;
+import net.minecraft.client.input.KeyEvent;
+import net.minecraft.world.inventory.AbstractContainerMenu;
+import net.minecraft.world.inventory.Slot;
+import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -25,19 +29,19 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-@Mixin(HandledScreen.class)
-public class PatchHandledScreen<T extends ScreenHandler> extends Screen implements HasCustomGui {
+@Mixin(AbstractContainerScreen.class)
+public class PatchHandledScreen<T extends AbstractContainerMenu> extends Screen implements HasCustomGui {
@Shadow
@Final
- protected T handler;
+ protected T menu;
@Shadow
- protected int x;
+ protected int leftPos;
@Shadow
- protected int y;
+ protected int topPos;
@Shadow
- protected int backgroundHeight;
+ protected int imageHeight;
@Shadow
- protected int backgroundWidth;
+ protected int imageWidth;
@Unique
public CustomGui override;
@Unique
@@ -47,7 +51,7 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
@Unique
private int originalBackgroundHeight;
- protected PatchHandledScreen(Text title) {
+ protected PatchHandledScreen(Component title) {
super(title);
}
@@ -60,12 +64,12 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
@Override
public void setCustomGui_Firmament(@Nullable CustomGui gui) {
if (this.override != null) {
- backgroundHeight = originalBackgroundHeight;
- backgroundWidth = originalBackgroundWidth;
+ imageHeight = originalBackgroundHeight;
+ imageWidth = originalBackgroundWidth;
}
if (gui != null) {
- originalBackgroundHeight = backgroundHeight;
- originalBackgroundWidth = backgroundWidth;
+ originalBackgroundHeight = imageHeight;
+ originalBackgroundWidth = imageWidth;
}
this.override = gui;
}
@@ -74,14 +78,17 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
return override != null && override.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
}
- public boolean keyReleased_firmament(int keyCode, int scanCode, int modifiers) {
- if (HandledScreenKeyReleasedEvent.Companion.publish(new HandledScreenKeyReleasedEvent((HandledScreen<?>) (Object) this, keyCode, scanCode, modifiers)).getCancelled())
+ public boolean keyReleased_firmament(KeyEvent input) {
+ if (HandledScreenKeyReleasedEvent.Companion.publish(new HandledScreenKeyReleasedEvent(
+ (AbstractContainerScreen<?>) (Object) this,
+ GenericInputAction.of(input),
+ InputModifiers.of(input))).getCancelled())
return true;
- return override != null && override.keyReleased(keyCode, scanCode, modifiers);
+ return override != null && override.keyReleased(input);
}
- public boolean charTyped_firmament(char chr, int modifiers) {
- return override != null && override.charTyped(chr, modifiers);
+ public boolean charTyped_firmament(CharacterEvent input) {
+ return override != null && override.charTyped(input);
}
@Inject(method = "init", at = @At("TAIL"))
@@ -91,19 +98,19 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
}
}
- @Inject(method = "drawForeground", at = @At("HEAD"), cancellable = true)
- private void onDrawForeground(DrawContext context, int mouseX, int mouseY, CallbackInfo ci) {
+ @Inject(method = "renderLabels", at = @At("HEAD"), cancellable = true)
+ private void onDrawForeground(GuiGraphics context, int mouseX, int mouseY, CallbackInfo ci) {
if (override != null && !override.shouldDrawForeground())
ci.cancel();
}
@WrapOperation(
- method = "drawSlots",
+ method = "renderSlots",
at = @At(
value = "INVOKE",
- target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawSlot(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/screen/slot/Slot;)V"))
- private void beforeSlotRender(HandledScreen instance, DrawContext context, Slot slot, Operation<Void> original) {
+ target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;renderSlot(Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/world/inventory/Slot;)V"))
+ private void beforeSlotRender(AbstractContainerScreen instance, GuiGraphics context, Slot slot, Operation<Void> original) {
if (override != null) {
override.beforeSlotRender(context, slot);
}
@@ -113,31 +120,33 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
}
}
- @Inject(method = "isClickOutsideBounds", at = @At("HEAD"), cancellable = true)
- public void onIsClickOutsideBounds(double mouseX, double mouseY, int left, int top, int button, CallbackInfoReturnable<Boolean> cir) {
+ @Inject(method = "hasClickedOutside", at = @At("HEAD"), cancellable = true)
+ public void onIsClickOutsideBounds(
+ double mouseX, double mouseY, int left, int top,
+ CallbackInfoReturnable<Boolean> cir) {
if (override != null) {
cir.setReturnValue(override.isClickOutsideBounds(mouseX, mouseY));
}
}
- @Inject(method = "isPointWithinBounds", at = @At("HEAD"), cancellable = true)
+ @Inject(method = "isHovering(IIIIDD)Z", at = @At("HEAD"), cancellable = true)
public void onIsPointWithinBounds(int x, int y, int width, int height, double pointX, double pointY, CallbackInfoReturnable<Boolean> cir) {
if (override != null) {
- cir.setReturnValue(override.isPointWithinBounds(x + this.x, y + this.y, width, height, pointX, pointY));
+ cir.setReturnValue(override.isPointWithinBounds(x + this.leftPos, y + this.topPos, width, height, pointX, pointY));
}
}
- @Inject(method = "isPointOverSlot", at = @At("HEAD"), cancellable = true)
+ @Inject(method = "isHovering(Lnet/minecraft/world/inventory/Slot;DD)Z", at = @At("HEAD"), cancellable = true)
public void onIsPointOverSlot(Slot slot, double pointX, double pointY, CallbackInfoReturnable<Boolean> cir) {
if (override != null) {
- cir.setReturnValue(override.isPointOverSlot(slot, this.x, this.y, pointX, pointY));
+ cir.setReturnValue(override.isPointOverSlot(slot, this.leftPos, this.topPos, pointX, pointY));
}
}
- @Inject(method = "render", at = @At("HEAD"))
- public void moveSlots(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
+ @Inject(method = "renderBackground", at = @At("HEAD"))
+ public void moveSlots(GuiGraphics context, int mouseX, int mouseY, float delta, CallbackInfo ci) {
if (override != null) {
- for (Slot slot : handler.slots) {
+ for (Slot slot : menu.slots) {
if (!hasRememberedSlots) {
((CoordRememberingSlot) slot).rememberCoords_firmament();
}
@@ -146,7 +155,7 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
hasRememberedSlots = true;
} else {
if (hasRememberedSlots) {
- for (Slot slot : handler.slots) {
+ for (Slot slot : menu.slots) {
((CoordRememberingSlot) slot).restoreCoords_firmament();
}
hasRememberedSlots = false;
@@ -154,7 +163,7 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
}
}
- @Inject(at = @At("HEAD"), method = "close", cancellable = true)
+ @Inject(at = @At("HEAD"), method = "onClose", cancellable = true)
private void onVoluntaryExit(CallbackInfo ci) {
if (override != null) {
if (!override.onVoluntaryExit())
@@ -162,8 +171,8 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
}
}
- @WrapWithCondition(method = "renderBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawBackground(Lnet/minecraft/client/gui/DrawContext;FII)V"))
- public boolean preventDrawingBackground(HandledScreen instance, DrawContext drawContext, float delta, int mouseX, int mouseY) {
+ @WrapWithCondition(method = "renderBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/inventory/AbstractContainerScreen;renderBg(Lnet/minecraft/client/gui/GuiGraphics;FII)V"))
+ public boolean preventDrawingBackground(AbstractContainerScreen instance, GuiGraphics drawContext, float delta, int mouseX, int mouseY) {
if (override != null) {
override.render(drawContext, delta, mouseX, mouseY);
}
@@ -172,28 +181,27 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
@WrapOperation(
method = "mouseClicked",
- at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;mouseClicked(DDI)Z"))
- public boolean overrideMouseClicks(HandledScreen instance, double mouseX, double mouseY, int button,
- Operation<Boolean> original) {
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/Screen;mouseClicked(Lnet/minecraft/client/input/MouseButtonEvent;Z)Z"))
+ public boolean overrideMouseClicks(AbstractContainerScreen instance, MouseButtonEvent click, boolean doubled, Operation<Boolean> original) {
if (override != null) {
- if (override.mouseClick(mouseX, mouseY, button))
+ if (override.mouseClick(click, doubled))
return true;
}
- return original.call(instance, mouseX, mouseY, button);
+ return original.call(instance, click, doubled);
}
@Inject(method = "mouseDragged", at = @At("HEAD"), cancellable = true)
- public void overrideMouseDrags(double mouseX, double mouseY, int button, double deltaX, double deltaY, CallbackInfoReturnable<Boolean> cir) {
+ public void overrideMouseDrags(MouseButtonEvent click, double offsetX, double offsetY, CallbackInfoReturnable<Boolean> cir) {
if (override != null) {
- if (override.mouseDragged(mouseX, mouseY, button, deltaX, deltaY))
+ if (override.mouseDragged(click, offsetX, offsetY))
cir.setReturnValue(true);
}
}
@Inject(method = "keyPressed", at = @At("HEAD"), cancellable = true)
- private void overrideKeyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable<Boolean> cir) {
+ private void overrideKeyPressed(KeyEvent input, CallbackInfoReturnable<Boolean> cir) {
if (override != null) {
- if (override.keyPressed(keyCode, scanCode, modifiers)) {
+ if (override.keyPressed(input)) {
cir.setReturnValue(true);
}
}
@@ -203,9 +211,9 @@ public class PatchHandledScreen<T extends ScreenHandler> extends Screen implemen
@Inject(
method = "mouseReleased",
at = @At("HEAD"), cancellable = true)
- public void overrideMouseReleases(double mouseX, double mouseY, int button, CallbackInfoReturnable<Boolean> cir) {
+ public void overrideMouseReleases(MouseButtonEvent click, CallbackInfoReturnable<Boolean> cir) {
if (override != null) {
- if (override.mouseReleased(mouseX, mouseY, button))
+ if (override.mouseReleased(click))
cir.setReturnValue(true);
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/DisableCommonPacketWarnings.java b/src/main/java/moe/nea/firmament/mixins/devenv/DisableCommonPacketWarnings.java
index a15d825..2744fb4 100644
--- a/src/main/java/moe/nea/firmament/mixins/devenv/DisableCommonPacketWarnings.java
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/DisableCommonPacketWarnings.java
@@ -2,9 +2,9 @@
package moe.nea.firmament.mixins.devenv;
-import net.minecraft.client.network.ClientPlayNetworkHandler;
-import net.minecraft.network.packet.CustomPayload;
-import net.minecraft.util.Identifier;
+import net.minecraft.client.multiplayer.ClientPacketListener;
+import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
+import net.minecraft.resources.ResourceLocation;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -14,27 +14,27 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Objects;
-@Mixin(ClientPlayNetworkHandler.class)
+@Mixin(ClientPacketListener.class)
public class DisableCommonPacketWarnings {
- @Inject(method = "warnOnUnknownPayload", at = @At("HEAD"), cancellable = true)
- public void onCustomPacketError(CustomPayload customPayload, CallbackInfo ci) {
- if (Objects.equals(customPayload.getId(), Identifier.of("badlion", "mods"))) {
+ @Inject(method = "handleUnknownCustomPayload", at = @At("HEAD"), cancellable = true)
+ public void onCustomPacketError(CustomPacketPayload customPayload, CallbackInfo ci) {
+ if (Objects.equals(customPayload.type(), ResourceLocation.fromNamespaceAndPath("badlion", "mods"))) {
ci.cancel();
}
}
- @Redirect(method = "onEntityPassengersSet", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;)V", remap = false))
+ @Redirect(method = "handleSetEntityPassengersPacket", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;)V", remap = false))
public void onUnknownPassenger(Logger instance, String s) {
// Ignore passenger data for unknown entities, since HyPixel just sends a lot of those.
}
- @Redirect(method = "onTeam", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;[Ljava/lang/Object;)V", remap = false))
+ @Redirect(method = "handleSetPlayerTeamPacket", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;[Ljava/lang/Object;)V", remap = false))
public void onOnTeam(Logger instance, String s, Object[] objects) {
// Ignore data for unknown teams, since HyPixel just sends a lot of invalid team data.
}
- @Redirect(method = "onPlayerList", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false))
+ @Redirect(method = "handlePlayerInfoUpdate", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false))
public void onOnPlayerList(Logger instance, String s, Object o, Object o2) {
// Ignore invalid player info, since HyPixel just sends a lot of invalid player info
}
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/DisableInvalidFishingHook.java b/src/main/java/moe/nea/firmament/mixins/devenv/DisableInvalidFishingHook.java
index 689a757..ffcfefa 100644
--- a/src/main/java/moe/nea/firmament/mixins/devenv/DisableInvalidFishingHook.java
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/DisableInvalidFishingHook.java
@@ -2,15 +2,15 @@
package moe.nea.firmament.mixins.devenv;
-import net.minecraft.entity.projectile.FishingBobberEntity;
+import net.minecraft.world.entity.projectile.FishingHook;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
-@Mixin(FishingBobberEntity.class)
+@Mixin(FishingHook.class)
public class DisableInvalidFishingHook {
- @Redirect(method = "onSpawnPacket", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false))
+ @Redirect(method = "recreateFromPacket", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false))
public void onOnSpawnPacket(Logger instance, String s, Object o, Object o1) {
// Don't warn for broken fishing hooks, since HyPixel sends a bunch of those
}
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java b/src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java
index ef8c9eb..849525f 100644
--- a/src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java
@@ -1,19 +1,19 @@
package moe.nea.firmament.mixins.devenv;
-import net.minecraft.text.TranslatableTextContent;
+import net.minecraft.network.chat.contents.TranslatableContents;
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;
-@Mixin(TranslatableTextContent.class)
+@Mixin(TranslatableContents.class)
public abstract class EarlyInstantiateTranslations {
@Shadow
- protected abstract void updateTranslations();
+ protected abstract void decompose();
@Inject(method = "<init>", at = @At("TAIL"))
private void onInit(String key, String fallback, Object[] args, CallbackInfo ci) {
- updateTranslations();
+ decompose();
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyCloser.java b/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyCloser.java
index 6620b47..c71f337 100644
--- a/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyCloser.java
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyCloser.java
@@ -1,7 +1,7 @@
package moe.nea.firmament.mixins.devenv;
-import net.minecraft.client.util.Window;
+import com.mojang.blaze3d.platform.Window;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyStopperPatch.java b/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyStopperPatch.java
index fac0688..cc04493 100644
--- a/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyStopperPatch.java
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyStopperPatch.java
@@ -1,16 +1,21 @@
package moe.nea.firmament.mixins.devenv;
-import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.Minecraft;
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;
-@Mixin(MinecraftClient.class)
+@Mixin(Minecraft.class)
public class IdentifyStopperPatch {
- @Inject(method = "scheduleStop", at = @At("HEAD"))
- private void onStop(CallbackInfo ci) {
- Thread.dumpStack();
- }
+ @Shadow
+ private volatile boolean running;
+
+ @Inject(method = "stop", at = @At("HEAD"))
+ private void onStop(CallbackInfo ci) {
+ if (this.running)
+ Thread.dumpStack();
+ }
}
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/MixinKeyboard.java b/src/main/java/moe/nea/firmament/mixins/devenv/MixinKeyboard.java
index d7b6cc3..7d5fc80 100644
--- a/src/main/java/moe/nea/firmament/mixins/devenv/MixinKeyboard.java
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/MixinKeyboard.java
@@ -3,18 +3,18 @@
package moe.nea.firmament.mixins.devenv;
import moe.nea.firmament.features.debug.DeveloperFeatures;
-import net.minecraft.client.Keyboard;
-import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.KeyboardHandler;
+import net.minecraft.client.Minecraft;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import java.util.concurrent.CompletableFuture;
-@Mixin(Keyboard.class)
+@Mixin(KeyboardHandler.class)
public class MixinKeyboard {
- @Redirect(method = "processF3", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;reloadResources()Ljava/util/concurrent/CompletableFuture;"))
- public CompletableFuture<Void> redirectReloadResources(MinecraftClient instance) {
+ @Redirect(method = "handleDebugKeys", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;reloadResourcePacks()Ljava/util/concurrent/CompletableFuture;"))
+ public CompletableFuture<Void> redirectReloadResources(Minecraft instance) {
return DeveloperFeatures.hookOnBeforeResourceReload(instance);
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/MixinScoreboard.java b/src/main/java/moe/nea/firmament/mixins/devenv/MixinScoreboard.java
index 34a733c..e39fe35 100644
--- a/src/main/java/moe/nea/firmament/mixins/devenv/MixinScoreboard.java
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/MixinScoreboard.java
@@ -2,7 +2,7 @@
package moe.nea.firmament.mixins.devenv;
-import net.minecraft.scoreboard.Scoreboard;
+import net.minecraft.world.scores.Scoreboard;
import org.slf4j.Logger;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(Scoreboard.class)
public class MixinScoreboard {
- @Redirect(method = "addTeam", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V", remap = false))
+ @Redirect(method = {"addPlayerTeam", "addPlayerToTeam"}, at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V", remap = false))
public void onExistingteam(Logger instance, String s, Object o) {
// Ignore creations of existing teams
}
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/WarnForUnknownCustomPayloadSends.java b/src/main/java/moe/nea/firmament/mixins/devenv/WarnForUnknownCustomPayloadSends.java
index 6d44e29..9a96df2 100644
--- a/src/main/java/moe/nea/firmament/mixins/devenv/WarnForUnknownCustomPayloadSends.java
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/WarnForUnknownCustomPayloadSends.java
@@ -2,17 +2,17 @@
package moe.nea.firmament.mixins.devenv;
import moe.nea.firmament.Firmament;
-import net.minecraft.network.PacketByteBuf;
-import net.minecraft.network.packet.UnknownCustomPayload;
+import net.minecraft.network.FriendlyByteBuf;
+import net.minecraft.network.protocol.common.custom.DiscardedPayload;
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;
-@Mixin(UnknownCustomPayload.class)
+@Mixin(DiscardedPayload.class)
public class WarnForUnknownCustomPayloadSends {
@Inject(method = "method_56493", at = @At("HEAD"))
- private static void warn(UnknownCustomPayload value, PacketByteBuf buf, CallbackInfo ci) {
+ private static void warn(DiscardedPayload value, FriendlyByteBuf buf, CallbackInfo ci) {
Firmament.INSTANCE.getLogger().warn("Unknown custom payload is being sent: {}", value);
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java b/src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java
index 33840c1..e513a97 100644
--- a/src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java
+++ b/src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java
@@ -2,8 +2,8 @@ package moe.nea.firmament.mixins.devenv;
import moe.nea.firmament.features.debug.DeveloperFeatures;
import moe.nea.firmament.util.MC;
-import net.minecraft.client.resource.language.TranslationStorage;
-import net.minecraft.text.Text;
+import net.minecraft.client.resources.language.ClientLanguage;
+import net.minecraft.network.chat.Component;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@@ -14,15 +14,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Set;
import java.util.TreeSet;
-@Mixin(TranslationStorage.class)
+@Mixin(ClientLanguage.class)
public abstract class WarnOnMissingTranslations {
@Shadow
- public abstract boolean hasTranslation(String key);
+ public abstract boolean has(String key);
@Unique
private final Set<String> missingTranslations = new TreeSet<>();
- @Inject(method = "get", at = @At("HEAD"))
+ @Inject(method = "getOrDefault", at = @At("HEAD"))
private void onGetTranslationKey(String key, String fallback, CallbackInfoReturnable<String> cir) {
warnForMissingTranslation(key);
}
@@ -30,9 +30,9 @@ public abstract class WarnOnMissingTranslations {
@Unique
private void warnForMissingTranslation(String key) {
if (!key.contains("firmament")) return;
- if (hasTranslation(key)) return;
+ if (has(key)) return;
if (!missingTranslations.add(key)) return;
- MC.INSTANCE.sendChat(Text.literal("Missing firmament translation: " + key));
+ MC.INSTANCE.sendChat(Component.literal("Missing firmament translation: " + key));
DeveloperFeatures.hookMissingTranslations(missingTranslations);
}
}
diff --git a/src/main/java/moe/nea/firmament/mixins/feature/DisableSlotHighlights.java b/src/main/java/moe/nea/firmament/mixins/feature/DisableSlotHighlights.java
new file mode 100644
index 0000000..475a5bf
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/feature/DisableSlotHighlights.java
@@ -0,0 +1,25 @@
+package moe.nea.firmament.mixins.feature;
+
+import moe.nea.firmament.features.fixes.Fixes;
+import net.minecraft.core.component.DataComponents;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.inventory.Slot;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+@Mixin(Slot.class)
+public abstract class DisableSlotHighlights {
+ @Shadow
+ public abstract ItemStack getItem();
+
+ @Inject(method = "isHighlightable", at = @At("HEAD"), cancellable = true)
+ private void dontHighlight(CallbackInfoReturnable<Boolean> cir) {
+ if (!Fixes.TConfig.INSTANCE.getHideSlotHighlights()) return;
+ var display = getItem().get(DataComponents.TOOLTIP_DISPLAY);
+ if (display != null && display.hideTooltip())
+ cir.setReturnValue(false);
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeFeatureRenderer.java b/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeFeatureRenderer.java
new file mode 100644
index 0000000..7852fc3
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeFeatureRenderer.java
@@ -0,0 +1,49 @@
+package moe.nea.firmament.mixins.feature.devcosmetics;
+
+import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
+import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
+import com.llamalad7.mixinextras.sugar.Local;
+import kotlin.Unit;
+import moe.nea.firmament.features.misc.CustomCapes;
+import net.minecraft.client.model.Model;
+import net.minecraft.client.renderer.RenderType;
+import com.mojang.blaze3d.vertex.VertexConsumer;
+import net.minecraft.client.renderer.MultiBufferSource;
+import net.minecraft.client.renderer.feature.ModelFeatureRenderer;
+import net.minecraft.client.renderer.SubmitNodeCollector;
+import net.minecraft.client.renderer.entity.layers.CapeLayer;
+import net.minecraft.client.renderer.entity.layers.RenderLayer;
+import net.minecraft.client.renderer.entity.RenderLayerParent;
+import net.minecraft.client.model.HumanoidModel;
+import net.minecraft.client.model.PlayerModel;
+import net.minecraft.client.renderer.entity.state.AvatarRenderState;
+import com.mojang.blaze3d.vertex.PoseStack;
+import net.minecraft.world.entity.player.PlayerSkin;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(CapeLayer.class)
+public abstract class CustomCapeFeatureRenderer extends RenderLayer<AvatarRenderState, PlayerModel> {
+ public CustomCapeFeatureRenderer(RenderLayerParent<AvatarRenderState, PlayerModel> context) {
+ super(context);
+ }
+
+ @WrapOperation(
+ method = "submit(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/client/renderer/entity/state/AvatarRenderState;FF)V",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitModel(Lnet/minecraft/client/model/Model;Ljava/lang/Object;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/RenderType;IIILnet/minecraft/client/renderer/feature/ModelFeatureRenderer$CrumblingOverlay;)V")
+ )
+ private void onRender(SubmitNodeCollector instance, Model model, Object o, PoseStack matrixStack, RenderType renderLayer, int light, int overlay, int outlineColor, ModelFeatureRenderer.CrumblingOverlay crumblingOverlayCommand, Operation<Void> original,
+ @Local(argsOnly = true) AvatarRenderState playerEntityRenderState, @Local PlayerSkin skinTextures) {
+ // TODO: 1.21.10 custom capes by pre rendering the texture id. this is more viable on this version i am fairly sure, without clogging up all of the cached image render layers
+// CustomCapes.render(
+// playerEntityRenderState,
+// vertexConsumer,
+// RenderLayer.getEntitySolid(skinTextures.cape().id()),
+// vertexConsumerProvider,
+// matrixStack,
+// updatedConsumer -> {
+// original.call(instance, matrixStack, updatedConsumer, light, overlay, outlineColor);
+// return Unit.INSTANCE;
+// });
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeStorage.java b/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeStorage.java
new file mode 100644
index 0000000..dc933ce
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeStorage.java
@@ -0,0 +1,23 @@
+package moe.nea.firmament.mixins.feature.devcosmetics;
+
+import moe.nea.firmament.features.misc.CustomCapes;
+import net.minecraft.client.renderer.entity.state.AvatarRenderState;
+import org.jetbrains.annotations.Nullable;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Unique;
+
+@Mixin(AvatarRenderState.class)
+public class CustomCapeStorage implements CustomCapes.CapeStorage {
+ @Unique
+ CustomCapes.CustomCape customCape;
+
+ @Override
+ public CustomCapes.@Nullable CustomCape getCape_firmament() {
+ return customCape;
+ }
+
+ @Override
+ public void setCape_firmament(CustomCapes.@Nullable CustomCape customCape) {
+ this.customCape = customCape;
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/render/IncreaseStackLimitSizeInDrawContext.java b/src/main/java/moe/nea/firmament/mixins/render/IncreaseStackLimitSizeInDrawContext.java
new file mode 100644
index 0000000..2352dfa
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/render/IncreaseStackLimitSizeInDrawContext.java
@@ -0,0 +1,20 @@
+package moe.nea.firmament.mixins.render;
+
+import net.minecraft.client.gui.GuiGraphics;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.ModifyArg;
+
+@Mixin(GuiGraphics.class)
+public class IncreaseStackLimitSizeInDrawContext {
+ // [22:00:57] [Render thread/ERROR] (Minecraft) Couldn't compile program for pipeline firmament:gui_textured_overlay_tris_circle:
+ // net.minecraft.client.gl.ShaderLoader$LoadException: Error encountered when linking program containing
+ // VS minecraft:core/position_tex_color and FS firmament:circle_discard_color.
+ // Log output: error: declarations for uniform `ColorModulator` are inside block `DynamicTransforms` and outside a block
+ @ModifyArg(
+ method = "<init>(Lnet/minecraft/client/Minecraft;Lnet/minecraft/client/gui/render/state/GuiRenderState;)V",
+ at = @At(value = "INVOKE", target = "Lorg/joml/Matrix3x2fStack;<init>(I)V"))
+ private static int increaseStackSize(int stackSize) {
+ return Math.max(stackSize, 48);
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/ChangeColorOfLivingEntities.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/ChangeColorOfLivingEntities.java
new file mode 100644
index 0000000..53353e2
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/ChangeColorOfLivingEntities.java
@@ -0,0 +1,65 @@
+package moe.nea.firmament.mixins.render.entitytints;
+
+import com.llamalad7.mixinextras.injector.ModifyReturnValue;
+import com.llamalad7.mixinextras.sugar.Local;
+import moe.nea.firmament.events.EntityRenderTintEvent;
+import net.minecraft.client.renderer.MultiBufferSource;
+import net.minecraft.client.renderer.SubmitNodeCollector;
+import net.minecraft.client.renderer.entity.LivingEntityRenderer;
+import net.minecraft.client.model.EntityModel;
+import net.minecraft.client.renderer.entity.state.LivingEntityRenderState;
+import net.minecraft.client.renderer.state.CameraRenderState;
+import com.mojang.blaze3d.vertex.PoseStack;
+import net.minecraft.world.entity.LivingEntity;
+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.ModifyArg;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+/**
+ * Applies various rendering modifications from {@link EntityRenderTintEvent}
+ */
+@Mixin(LivingEntityRenderer.class)
+public class ChangeColorOfLivingEntities<T extends LivingEntity, S extends LivingEntityRenderState, M extends EntityModel<? super S>> {
+ @ModifyReturnValue(method = "getModelTint", at = @At("RETURN"))
+ private int changeColor(int original, @Local(argsOnly = true) S state) {
+ var tintState = EntityRenderTintEvent.HasTintRenderState.cast(state);
+ if (tintState.getHasTintOverride_firmament())
+ return tintState.getTint_firmament();
+ return original;
+ }
+
+ @ModifyArg(
+ method = "getOverlayCoords",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/texture/OverlayTexture;u(F)I"),
+ allow = 1
+ )
+ private static float modifyLightOverlay(float originalWhiteOffset, @Local(argsOnly = true) LivingEntityRenderState state) {
+ var tintState = EntityRenderTintEvent.HasTintRenderState.cast(state);
+ if (tintState.getHasTintOverride_firmament() || tintState.getOverlayTexture_firmament() != null) {
+ return 1F; // TODO: add interpolation percentage to render state extension
+ }
+ return originalWhiteOffset;
+ }
+
+ @Inject(method = "submit(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;popPose()V"))
+ private void afterRender(S livingEntityRenderState, PoseStack matrixStack, SubmitNodeCollector orderedRenderCommandQueue, CameraRenderState cameraRenderState, CallbackInfo ci) {
+// var tintState = EntityRenderTintEvent.HasTintRenderState.cast(livingEntityRenderState);
+// var overlayTexture = tintState.getOverlayTexture_firmament();
+// if (overlayTexture != null && vertexConsumerProvider instanceof VertexConsumerProvider.Immediate imm) {
+// imm.drawCurrentLayer();
+// }
+// EntityRenderTintEvent.overlayOverride = null;
+ // TODO: 1.21.10
+ }
+
+ @Inject(method = "submit(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V"))
+ private void beforeRender(S livingEntityRenderState, PoseStack matrixStack, SubmitNodeCollector orderedRenderCommandQueue, CameraRenderState cameraRenderState, CallbackInfo ci) {
+ var tintState = EntityRenderTintEvent.HasTintRenderState.cast(livingEntityRenderState);
+ var overlayTexture = tintState.getOverlayTexture_firmament();
+ if (overlayTexture != null) {
+ EntityRenderTintEvent.overlayOverride = overlayTexture;
+ }
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/EntityRenderStateTint.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/EntityRenderStateTint.java
new file mode 100644
index 0000000..1745fc9
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/EntityRenderStateTint.java
@@ -0,0 +1,55 @@
+package moe.nea.firmament.mixins.render.entitytints;
+
+import moe.nea.firmament.events.EntityRenderTintEvent;
+import moe.nea.firmament.util.render.TintedOverlayTexture;
+import net.minecraft.client.renderer.entity.state.EntityRenderState;
+import org.jetbrains.annotations.Nullable;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Unique;
+
+@Mixin(EntityRenderState.class)
+public class EntityRenderStateTint implements EntityRenderTintEvent.HasTintRenderState {
+ @Unique
+ int tint = -1;
+ @Unique
+ TintedOverlayTexture overlayTexture;
+ @Unique
+ boolean hasTintOverride = false;
+
+ @Override
+ public int getTint_firmament() {
+ return tint;
+ }
+
+ @Override
+ public void setTint_firmament(int i) {
+ tint = i;
+ hasTintOverride = true;
+ }
+
+ @Override
+ public boolean getHasTintOverride_firmament() {
+ return hasTintOverride;
+ }
+
+ @Override
+ public void setHasTintOverride_firmament(boolean b) {
+ hasTintOverride = b;
+ }
+
+ @Override
+ public void reset_firmament() {
+ hasTintOverride = false;
+ overlayTexture = null;
+ }
+
+ @Override
+ public @Nullable TintedOverlayTexture getOverlayTexture_firmament() {
+ return overlayTexture;
+ }
+
+ @Override
+ public void setOverlayTexture_firmament(@Nullable TintedOverlayTexture tintedOverlayTexture) {
+ this.overlayTexture = tintedOverlayTexture;
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/InjectIntoRenderState.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/InjectIntoRenderState.java
new file mode 100644
index 0000000..c84dbb6
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/InjectIntoRenderState.java
@@ -0,0 +1,30 @@
+package moe.nea.firmament.mixins.render.entitytints;
+
+import moe.nea.firmament.events.EntityRenderTintEvent;
+import net.minecraft.client.renderer.entity.EntityRenderer;
+import net.minecraft.client.renderer.entity.state.EntityRenderState;
+import net.minecraft.world.entity.Entity;
+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;
+
+/**
+ * Dispatches {@link EntityRenderTintEvent} to collect additional render state used by {@link ChangeColorOfLivingEntities}
+ */
+@Mixin(EntityRenderer.class)
+public class InjectIntoRenderState<T extends Entity, S extends EntityRenderState> {
+
+ @Inject(
+ method = "extractRenderState",
+ at = @At("RETURN"))
+ private void onUpdateRenderState(T entity, S state, float tickDelta, CallbackInfo ci) {
+ var renderState = EntityRenderTintEvent.HasTintRenderState.cast(state);
+ renderState.reset_firmament();
+ var tintEvent = new EntityRenderTintEvent(
+ entity,
+ renderState
+ );
+ EntityRenderTintEvent.Companion.publish(tintEvent);
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/ReplaceOverlayTexture.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/ReplaceOverlayTexture.java
new file mode 100644
index 0000000..ef8b371
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/ReplaceOverlayTexture.java
@@ -0,0 +1,24 @@
+package moe.nea.firmament.mixins.render.entitytints;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import moe.nea.firmament.events.EntityRenderTintEvent;
+import net.minecraft.client.renderer.texture.OverlayTexture;
+import net.minecraft.client.renderer.RenderType;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+/**
+ * Replaces the overlay texture used by rendering with the override specified in {@link EntityRenderTintEvent#overlayOverride}
+ */
+@Mixin(RenderType.OverlayStateShard.class)
+public class ReplaceOverlayTexture {
+ @ModifyExpressionValue(
+ method = {"method_23555", "method_23556"},
+ expect = 2,
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;overlayTexture()Lnet/minecraft/client/renderer/texture/OverlayTexture;"))
+ private static OverlayTexture replaceOverlayTexture(OverlayTexture original) {
+ if (EntityRenderTintEvent.overlayOverride != null)
+ return EntityRenderTintEvent.overlayOverride;
+ return original;
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableEquipmentRenderer.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableEquipmentRenderer.java
new file mode 100644
index 0000000..0cceea3
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableEquipmentRenderer.java
@@ -0,0 +1,34 @@
+package moe.nea.firmament.mixins.render.entitytints;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
+import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
+import moe.nea.firmament.events.EntityRenderTintEvent;
+import net.minecraft.client.renderer.texture.OverlayTexture;
+import net.minecraft.client.renderer.RenderType;
+import net.minecraft.client.renderer.entity.layers.EquipmentLayerRenderer;
+import net.minecraft.resources.ResourceLocation;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+/**
+ * Patch to make {@link EquipmentLayerRenderer} use a {@link RenderType} that allows uses Minecraft's overlay texture, if a {@link EntityRenderTintEvent#overlayOverride} is specified.
+ */
+@Mixin(EquipmentLayerRenderer.class)
+public class UseOverlayableEquipmentRenderer {
+ @WrapOperation(method = "renderLayers(Lnet/minecraft/client/resources/model/EquipmentClientInfo$LayerType;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/client/model/Model;Ljava/lang/Object;Lnet/minecraft/world/item/ItemStack;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/resources/ResourceLocation;II)V",
+ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderType;armorCutoutNoCull(Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/client/renderer/RenderType;"))
+ private RenderType replace(ResourceLocation texture, Operation<RenderType> original) {
+ if (EntityRenderTintEvent.overlayOverride != null)
+ return RenderType.entityTranslucent(texture);
+ return original.call(texture);
+ }
+
+ @ModifyExpressionValue(method = "renderLayers(Lnet/minecraft/client/resources/model/EquipmentClientInfo$LayerType;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/client/model/Model;Ljava/lang/Object;Lnet/minecraft/world/item/ItemStack;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/resources/ResourceLocation;II)V",
+ at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/OverlayTexture;NO_OVERLAY:I"))
+ private int replaceUvIndex(int original) {
+ if (EntityRenderTintEvent.overlayOverride != null)
+ return OverlayTexture.pack(15, 10); // TODO: store this info in a global alongside overlayOverride
+ return original;
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableHeadFeatureRenderer.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableHeadFeatureRenderer.java
new file mode 100644
index 0000000..a867c81
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableHeadFeatureRenderer.java
@@ -0,0 +1,26 @@
+package moe.nea.firmament.mixins.render.entitytints;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import moe.nea.firmament.events.EntityRenderTintEvent;
+import net.minecraft.client.renderer.texture.OverlayTexture;
+import net.minecraft.client.renderer.RenderType;
+import net.minecraft.client.renderer.entity.layers.CustomHeadLayer;
+import org.objectweb.asm.Opcodes;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+/**
+ * Patch to make {@link CustomHeadLayer} use a {@link RenderType} that allows uses Minecraft's overlay texture, if a {@link EntityRenderTintEvent#overlayOverride} is specified.
+ * @see UseOverlayableItemRenderer
+ */
+@Mixin(CustomHeadLayer.class)
+public class UseOverlayableHeadFeatureRenderer {
+
+ @ModifyExpressionValue(method = "submit(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;FF)V",
+ at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/OverlayTexture;NO_OVERLAY:I", opcode = Opcodes.GETSTATIC))
+ private int replaceUvIndex(int original) {
+ if (EntityRenderTintEvent.overlayOverride != null)
+ return OverlayTexture.pack(15, 10); // TODO: store this info in a global alongside overlayOverride
+ return original;
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableItemRenderer.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableItemRenderer.java
new file mode 100644
index 0000000..dcac77c
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableItemRenderer.java
@@ -0,0 +1,26 @@
+package moe.nea.firmament.mixins.render.entitytints;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import moe.nea.firmament.events.EntityRenderTintEvent;
+import net.minecraft.client.renderer.texture.OverlayTexture;
+import net.minecraft.client.renderer.RenderType;
+import net.minecraft.client.renderer.RenderStateShard;
+import net.minecraft.client.renderer.item.ItemStackRenderState;
+import org.objectweb.asm.Opcodes;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+/**
+ * Patch to make {@link ItemStackRenderState} use a {@link RenderType} that allows uses Minecraft's overlay texture.
+ *
+ * @see UseOverlayableHeadFeatureRenderer
+ */
+@Mixin(ItemStackRenderState.LayerRenderState.class)
+public class UseOverlayableItemRenderer {
+ @ModifyExpressionValue(method = "submit", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/item/ItemStackRenderState$LayerRenderState;renderType:Lnet/minecraft/client/renderer/RenderType;", opcode = Opcodes.GETFIELD))
+ private RenderType replace(RenderType original) {
+ if (EntityRenderTintEvent.overlayOverride != null && original instanceof RenderType.CompositeRenderType multiPhase && multiPhase.state.textureState instanceof RenderStateShard.TextureStateShard texture && texture.cutoutTexture().isPresent())
+ return RenderType.entityTranslucent(texture.cutoutTexture().get());
+ return original;
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableSkullBlockEntityRenderer.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableSkullBlockEntityRenderer.java
new file mode 100644
index 0000000..ac102ed
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableSkullBlockEntityRenderer.java
@@ -0,0 +1,25 @@
+package moe.nea.firmament.mixins.render.entitytints;
+
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import moe.nea.firmament.events.EntityRenderTintEvent;
+import net.minecraft.client.renderer.texture.OverlayTexture;
+import net.minecraft.client.renderer.RenderType;
+import net.minecraft.client.renderer.blockentity.SkullBlockRenderer;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+/**
+ * Patch to make {@link SkullBlockRenderer} use a {@link RenderType} that allows uses Minecraft's overlay texture, if a {@link EntityRenderTintEvent#overlayOverride} is specified.
+ */
+
+@Mixin(SkullBlockRenderer.class)
+public class UseOverlayableSkullBlockEntityRenderer {
+ @ModifyExpressionValue(method = "submitSkull(Lnet/minecraft/core/Direction;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;ILnet/minecraft/client/model/SkullModelBase;Lnet/minecraft/client/renderer/RenderType;ILnet/minecraft/client/renderer/feature/ModelFeatureRenderer$CrumblingOverlay;)V",
+ at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/texture/OverlayTexture;NO_OVERLAY:I"))
+ private static int replaceUvIndex(int original) {
+ if (EntityRenderTintEvent.overlayOverride != null)
+ return OverlayTexture.pack(15, 10); // TODO: store this info in a global alongside overlayOverride
+ return original;
+ }
+
+}
diff --git a/src/main/java/moe/nea/firmament/mixins/render/renderer/MultipleSpecialGuiRenderStates.java b/src/main/java/moe/nea/firmament/mixins/render/renderer/MultipleSpecialGuiRenderStates.java
new file mode 100644
index 0000000..7c37684
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/mixins/render/renderer/MultipleSpecialGuiRenderStates.java
@@ -0,0 +1,68 @@
+/*
+ * SPDX-License-Identifier: LGPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2025 azureaaron via Skyblocker
+ */
+
+package moe.nea.firmament.mixins.render.renderer;
+
+import com.mojang.blaze3d.buffers.GpuBufferSlice;
+import moe.nea.firmament.util.render.MultiSpecialGuiRenderState;
+import moe.nea.firmament.util.render.MultiSpecialGuiRenderer;
+import net.minecraft.client.gui.render.GuiRenderer;
+import net.minecraft.client.gui.render.pip.PictureInPictureRenderer;
+import net.minecraft.client.gui.render.state.GuiRenderState;
+import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState;
+import net.minecraft.client.renderer.MultiBufferSource;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The structure of this class was roughly taken from SkyBlocker, retrieved 29.07.2025
+ */
+@Mixin(GuiRenderer.class)
+public class MultipleSpecialGuiRenderStates {
+ @Shadow
+ @Final
+ private MultiBufferSource.BufferSource bufferSource;
+ @Shadow
+ @Final
+ GuiRenderState renderState;
+ @Unique
+ Map<MultiSpecialGuiRenderState, MultiSpecialGuiRenderer<?>> multiRenderers = new HashMap<>();
+
+ @Inject(method = "preparePictureInPictureState", at = @At("HEAD"), cancellable = true)
+ private <T extends PictureInPictureRenderState> void onPrepareElement(T elementState, int windowScaleFactor, CallbackInfo ci) {
+ if (elementState instanceof MultiSpecialGuiRenderState multiState) {
+ @SuppressWarnings({"resource", "unchecked"})
+ var renderer = (PictureInPictureRenderer<T>) multiRenderers
+ .computeIfAbsent(multiState, elementState$ -> elementState$.createRenderer(this.bufferSource));
+ renderer.prepare(elementState, renderState, windowScaleFactor);
+ ci.cancel();
+ }
+ }
+
+ @Inject(method = "close", at = @At("TAIL"))
+ private void onClose(CallbackInfo ci) {
+ multiRenderers.values().forEach(PictureInPictureRenderer::close);
+ }
+
+ @Inject(method = "render(Lcom/mojang/blaze3d/buffers/GpuBufferSlice;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/render/GuiRenderer;clearUnusedOversizedItemRenderers()V"))
+ private void onAfterRender(GpuBufferSlice fogBuffer, CallbackInfo ci) {
+ multiRenderers.values().removeIf(it -> {
+ if (it.consumeRender()) {
+ return false;
+ } else {
+ it.close();
+ return true;
+ }
+ });
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/repo/EnchantedBookCache.kt b/src/main/java/moe/nea/firmament/repo/EnchantedBookCache.kt
new file mode 100644
index 0000000..0e276ce
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/repo/EnchantedBookCache.kt
@@ -0,0 +1,16 @@
+package moe.nea.firmament.repo
+
+import io.github.moulberry.repo.IReloadable
+import io.github.moulberry.repo.NEURepository
+import moe.nea.firmament.util.SkyblockId
+import moe.nea.firmament.util.removeColorCodes
+import moe.nea.firmament.util.skyblockId
+
+class EnchantedBookCache : IReloadable {
+ var byName: Map<String, SkyblockId> = mapOf()
+ override fun reload(repo: NEURepository) {
+ byName = repo.items.items.values
+ .filter { it.displayName.endsWith("Enchanted Book") }
+ .associate { it.lore.first().removeColorCodes() to it.skyblockId }
+ }
+}
diff --git a/src/main/java/moe/nea/firmament/util/data/ManagedConfig.kt b/src/main/java/moe/nea/firmament/util/data/ManagedConfig.kt
new file mode 100644
index 0000000..29c7f15
--- /dev/null
+++ b/src/main/java/moe/nea/firmament/util/data/ManagedConfig.kt
@@ -0,0 +1,292 @@
+package moe.nea.firmament.util.data
+
+import com.mojang.serialization.Codec
+import io.github.notenoughupdates.moulconfig.ChromaColour
+import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
+import io.github.notenoughupdates.moulconfig.gui.GuiContext
+import io.github.notenoughupdates.moulconfig.gui.component.CenterComponent
+import io.github.notenoughupdates.moulconfig.gui.component.ColumnComponent
+import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent
+import io.github.notenoughupdates.moulconfig.gui.component.RowComponent
+import io.github.notenoughupdates.moulconfig.gui.component.ScrollPanelComponent
+import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
+import io.github.notenoughupdates.moulconfig.platform.MoulConfigScreenComponent
+import kotlinx.serialization.json.JsonElement
+import kotlinx.serialization.json.JsonObject
+import moe.nea.firmament.Firmament
+import moe.nea.firmament.gui.FirmButtonComponent
+import moe.nea.firmament.gui.config.AllConfigsGui
+import moe.nea.firmament.gui.config.BooleanHandler
+import moe.nea.firmament.gui.config.ChoiceHandler
+import moe.nea.firmament.gui.config.ClickHandler
+import moe.nea.firmament.gui.config.ColourHandler
+import moe.nea.firmament.gui.config.DurationHandler
+import moe.nea.firmament.gui.config.GuiAppender
+import moe.nea.firmament.gui.config.HudMeta
+import moe.nea.firmament.gui.config.HudMetaHandler
+import moe.nea.firmament.gui.config.HudPosition
+import moe.nea.firmament.gui.config.IntegerHandler
+import moe.nea.firmament.gui.config.KeyBindingHandler
+import moe.nea.firmament.gui.config.ManagedOption
+import moe.nea.firmament.gui.config.StringHandler
+import moe.nea.firmament.keybindings.SavedKeyBinding
+import moe.nea.firmament.util.ScreenUtil
+import moe.nea.firmament.util.collections.InstanceList
+import net.minecraft.client.gui.screens.Screen
+import net.minecraft.network.chat.Component
+import net.minecraft.util.StringRepresentable
+import org.joml.Vector2i
+import kotlinx.serialization.json.buildJsonObject
+import kotlinx.serialization.json.jsonObject
+import kotlinx.serialization.json.putJsonObject
+import kotlin.io.path.createDirectories
+import kotlin.io.path.readText
+import kotlin.io.path.writeText
+import kotlin.time.Duration
+import moe.nea.firmament.gui.config.storage.ConfigStorageClass
+
+abstract class ManagedConfig(
+ val name: String,
+ val category: Category,
+) : IDataHolder<Unit>() {
+ enum class Category {
+ // Böse Kategorie, nicht benutzten lol
+ MISC,
+ CHAT,
+ INVENTORY,
+ ITEMS,
+ MINING,
+ GARDEN,
+ EVENTS,
+ INTEGRATIONS,
+ META,
+ DEV,
+ ;
+
+ val labelText: Component = Component.translatable("firmament.config.category.${name.lowercase()}")
+ val description: Component = Component.translatable("firmament.config.category.${name.lowercase()}.description")
+ val configs: MutableList<ManagedConfig> = mutableListOf()
+ }
+
+ companion object {
+ val allManagedConfigs = InstanceList<ManagedConfig>("ManagedConfig")
+ }
+
+ interface OptionHandler<T : Any> {
+ fun initOption(opt: ManagedOption<T>) {}
+ fun toJson(element: T): JsonElement?
+ fun fromJson(element: JsonElement): T
+ fun emitGuiElements(opt: ManagedOption<T>, guiAppender: GuiAppender)
+ }
+
+ init {
+ allManagedConfigs.getAll().forEach {
+ require(it.name != name) { "Duplicate name '$name' used for config" }
+ }
+ allManagedConfigs.add(this)
+ category.configs.add(this)
+ }
+
+ override fun keys(): Collection<Unit> {
+ return listOf(Unit)
+ }
+
+ override fun clear() {
+ sortedOptions.forEach {
+ it._actualValue = null
+ }
+ }
+
+ override val storageClass: ConfigStorageClass
+ get() = ConfigStorageClass.CONFIG
+
+ override fun saveTo(key: Unit): JsonObject {
+ return buildJsonObject {
+ putJsonObject(name) {
+ sortedOptions.forEach {
+ put(it.propertyName, it.toJson() ?: return@forEach)
+ }
+ }
+ }
+ }
+
+ override fun explicitDefaultLoad() {
+ val empty = JsonObject(mapOf())
+ sortedOptions.forEach { it.load(empty) }
+ }
+
+ override fun loadFrom(key: Unit, jsonObject: JsonObject) {
+ val unprefixed = jsonObject[name]?.jsonObject ?: JsonObject(mapOf())
+ sortedOptions.forEach {
+ it.load(unprefixed)
+ }
+ }
+
+ val allOptions = mutableMapOf<String, ManagedOption<*>>()
+ val sortedOptions = mutableListOf<ManagedOption<*>>()
+
+ private var latestGuiAppender: GuiAppender? = null
+
+ protected fun <T : Any> option(
+ propertyName: String,
+ default: () -> T,
+ handler: OptionHandler<T>
+ ): ManagedOption<T> {
+ if (propertyName in allOptions) error("Cannot register the same name twice")
+ return ManagedOption(this, propertyName, default, handler).also {
+ it.handler.initOption(it)
+ allOptions[propertyName] = it
+ sortedOptions.add(it)
+ }
+ }
+
+ protected fun toggle(propertyName: String, default: () -> Boolean): ManagedOption<Boolean> {
+ return option(propertyName, default, BooleanHandler(this))
+ }
+
+ protected fun colour(propertyName: String, default: () -> ChromaColour): ManagedOption<ChromaColour> {
+ return option(propertyName, default, ColourHandler(this))
+ }
+
+ protected fun <E> choice(
+ propertyName: String,
+ enumClass: Class<E>,
+ default: () -> E
+ ): ManagedOption<E> where E : Enum<E>, E : StringRepresentable {
+ return option(propertyName, default, ChoiceHandler(enumClass, enumClass.enumConstants.toList()))
+ }
+
+ protected inline fun <reified E> choice(
+ propertyName: String,
+ noinline default: () -> E
+ ): ManagedOption<E> where E : Enum<E>, E : StringRepresentable {
+ return choice(propertyName, E::class.java, default)
+ }
+
+ private fun <E> createStringIdentifiable(x: () -> Array<out E>): Codec<E> where E : Enum<E>, E : StringRepresentable {
+ return StringRepresentable.fromEnum { x() }
+ }
+
+ // TODO: wait on https://youtrack.jetbrains.com/issue/KT-73434
+// protected inline fun <reified E> choice(
+// propertyName: String,
+// noinline default: () -> E
+// ): ManagedOption<E> where E : Enum<E>, E : StringIdentifiable {
+// return choice(
+// propertyName,
+// enumEntries<E>().toList(),
+// StringIdentifiable.createCodec { enumValues<E>() },
+// EnumRenderer.default(),
+// default
+// )
+// }
+ open fun onChange(option: ManagedOption<*>) {
+ }
+
+ protected fun duration(
+ propertyName: String,
+ min: Duration,
+ max: Duration,
+ default: () -> Duration,
+ ): ManagedOption<Duration> {
+ return option(propertyName, default, DurationHandler(this, min, max))
+ }
+
+
+ protected fun position(
+ propertyName: String,
+ width: Int,
+ height: Int,
+ default: () -> Vector2i,
+ ): ManagedOption<HudMeta> {
+ val label = Component.translatable("firmament.config.${name}.${propertyName}")
+ return option(propertyName, {
+ val p = default()
+ HudMeta(HudPosition(p.x(), p.y(), 1F), Firmament.identifier(propertyName), label, width, height)
+ }, HudMetaHandler(this, propertyName, label, width, height))
+ }
+
+ protected fun keyBinding(
+ propertyName: String,
+ default: () -> Int,
+ ): ManagedOption<SavedKeyBinding> = keyBindingWithOutDefaultModifiers(propertyName) {
+ SavedKeyBinding.Companion.keyWithoutMods(default())
+ }
+
+ protected fun keyBindingWithOutDefaultModifiers(
+ propertyName: String,
+ default: () -> SavedKeyBinding,
+ ): ManagedOption<SavedKeyBinding> {
+ return option(propertyName, default, KeyBindingHandler("firmament.config.${name}.${propertyName}", this))
+ }
+
+ protected fun keyBindingWithDefaultUnbound(
+ propertyName: String,
+ ): ManagedOption<SavedKeyBinding> {
+ return keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding.Companion.unbound() }
+ }
+
+ protected fun integer(
+ propertyName: String,
+ min: Int,
+ max: Int,
+ default: () -> Int,
+ ): ManagedOption<Int> {
+ return option(propertyName, default, IntegerHandler(this, min, max))
+ }
+
+ protected fun button(propertyName: String, runnable: () -> Unit): ManagedOption<Unit> {
+ return option(propertyName, { }, ClickHandler(this, runnable))
+ }
+
+ protected fun string(propertyName: String, default: () -> String): ManagedOption<String> {
+ return option(propertyName, default, StringHandler(this))
+ }
+
+
+ fun reloadGui() {
+ latestGuiAppender?.reloadables?.forEach { it() }
+ }
+
+ val translationKey get() = "firmament.config.${name}"
+ val labelText: Component = Component.translatable(translationKey)
+
+ fun getConfigEditor(parent: Screen? = null): Screen {
+ var screen: Screen? = null
+ val guiapp = GuiAppender(400) { requireNotNull(screen) { "Screen Accessor called too early" } }
+ latestGuiAppender = guiapp
+ guiapp.appendFullRow(
+ RowComponent(
+ FirmButtonComponent(TextComponent("←")) {
+ if (parent != null) {
+ markDirty()
+ ScreenUtil.setScreenLater(parent)
+ } else {
+ AllConfigsGui.showAllGuis()
+ }
+ }
+ ))
+ sortedOptions.forEach { it.appendToGui(guiapp) }
+ guiapp.reloadables.forEach { it() }
+ val component = CenterComponent(
+ PanelComponent(
+ ScrollPanelComponent(400, 300, ColumnComponent(guiapp.panel)),
+ 10,
+ PanelComponent.DefaultBackgroundRenderer.VANILLA
+ )
+ )
+ screen = object : MoulConfigScreenComponent(Component.empty(), GuiContext(component), parent) {
+ override fun onClose() {
+ if (guiContext.onBeforeClose() == CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE) {
+ minecraft!!.setScreen(parent)
+ }
+ }
+ }
+ return screen
+ }
+
+ fun showConfigEditor(parent: Screen? = null) {
+ ScreenUtil.setScreenLater(getConfigEditor(parent))
+ }
+
+}