This commit is contained in:
2026-01-09 21:48:48 +01:00
parent c89433c8dd
commit a711ba501d
28 changed files with 1343 additions and 123 deletions

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.mixin.screen;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.minecraft.class_332;
import net.minecraft.class_437;
import net.minecraft.class_757;
@Mixin(class_757.class)
abstract class GameRendererMixin {
@WrapOperation(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;renderWithTooltip(Lnet/minecraft/client/gui/DrawContext;IIF)V"))
private void onRenderScreen(class_437 currentScreen, class_332 drawContext, int mouseX, int mouseY, float tickDelta, Operation<Void> operation) {
ScreenEvents.beforeRender(currentScreen).invoker().beforeRender(currentScreen, drawContext, mouseX, mouseY, tickDelta);
operation.call(currentScreen, drawContext, mouseX, mouseY, tickDelta);
ScreenEvents.afterRender(currentScreen).invoker().afterRender(currentScreen, drawContext, mouseX, mouseY, tickDelta);
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.mixin.screen;
import net.minecraft.class_2561;
import net.minecraft.class_437;
import net.minecraft.class_465;
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(class_465.class)
public abstract class HandledScreenMixin extends class_437 {
private HandledScreenMixin(class_2561 title) {
super(title);
}
@Inject(method = "mouseReleased", at = @At("HEAD"), cancellable = true)
private void callSuperMouseReleased(double mouseX, double mouseY, int button, CallbackInfoReturnable<Boolean> cir) {
if (super.method_25406(mouseX, mouseY, button)) {
cir.setReturnValue(true);
}
}
@Inject(method = "mouseDragged", at = @At("HEAD"), cancellable = true)
private void callSuperMouseReleased(double mouseX, double mouseY, int button, double deltaX, double deltaY, CallbackInfoReturnable<Boolean> cir) {
if (super.method_25403(mouseX, mouseY, button, deltaX, deltaY)) {
cir.setReturnValue(true);
}
}
}

View File

@@ -0,0 +1,280 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.fabricmc.fabric.mixin.screen;
import java.util.List;
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 net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.fabricmc.fabric.api.client.screen.v1.ScreenKeyboardEvents;
import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.impl.client.screen.ButtonList;
import net.fabricmc.fabric.impl.client.screen.ScreenEventFactory;
import net.fabricmc.fabric.impl.client.screen.ScreenExtensions;
import net.minecraft.class_310;
import net.minecraft.class_339;
import net.minecraft.class_364;
import net.minecraft.class_4068;
import net.minecraft.class_437;
import net.minecraft.class_6379;
@Mixin(class_437.class)
abstract class ScreenMixin implements ScreenExtensions {
@Shadow
@Final
protected List<class_6379> selectables;
@Shadow
@Final
protected List<class_364> children;
@Shadow
@Final
protected List<class_4068> drawables;
@Unique
private ButtonList fabricButtons;
@Unique
private Event<ScreenEvents.Remove> removeEvent;
@Unique
private Event<ScreenEvents.BeforeTick> beforeTickEvent;
@Unique
private Event<ScreenEvents.AfterTick> afterTickEvent;
@Unique
private Event<ScreenEvents.BeforeRender> beforeRenderEvent;
@Unique
private Event<ScreenEvents.AfterRender> afterRenderEvent;
// Keyboard
@Unique
private Event<ScreenKeyboardEvents.AllowKeyPress> allowKeyPressEvent;
@Unique
private Event<ScreenKeyboardEvents.BeforeKeyPress> beforeKeyPressEvent;
@Unique
private Event<ScreenKeyboardEvents.AfterKeyPress> afterKeyPressEvent;
@Unique
private Event<ScreenKeyboardEvents.AllowKeyRelease> allowKeyReleaseEvent;
@Unique
private Event<ScreenKeyboardEvents.BeforeKeyRelease> beforeKeyReleaseEvent;
@Unique
private Event<ScreenKeyboardEvents.AfterKeyRelease> afterKeyReleaseEvent;
// Mouse
@Unique
private Event<ScreenMouseEvents.AllowMouseClick> allowMouseClickEvent;
@Unique
private Event<ScreenMouseEvents.BeforeMouseClick> beforeMouseClickEvent;
@Unique
private Event<ScreenMouseEvents.AfterMouseClick> afterMouseClickEvent;
@Unique
private Event<ScreenMouseEvents.AllowMouseRelease> allowMouseReleaseEvent;
@Unique
private Event<ScreenMouseEvents.BeforeMouseRelease> beforeMouseReleaseEvent;
@Unique
private Event<ScreenMouseEvents.AfterMouseRelease> afterMouseReleaseEvent;
@Unique
private Event<ScreenMouseEvents.AllowMouseScroll> allowMouseScrollEvent;
@Unique
private Event<ScreenMouseEvents.BeforeMouseScroll> beforeMouseScrollEvent;
@Unique
private Event<ScreenMouseEvents.AfterMouseScroll> afterMouseScrollEvent;
@Inject(method = "init(Lnet/minecraft/client/MinecraftClient;II)V", at = @At("HEAD"))
private void beforeInitScreen(class_310 client, int width, int height, CallbackInfo ci) {
beforeInit(client, width, height);
}
@Inject(method = "init(Lnet/minecraft/client/MinecraftClient;II)V", at = @At("TAIL"))
private void afterInitScreen(class_310 client, int width, int height, CallbackInfo ci) {
afterInit(client, width, height);
}
@Inject(method = "resize", at = @At("HEAD"))
private void beforeResizeScreen(class_310 client, int width, int height, CallbackInfo ci) {
beforeInit(client, width, height);
}
@Inject(method = "resize", at = @At("TAIL"))
private void afterResizeScreen(class_310 client, int width, int height, CallbackInfo ci) {
afterInit(client, width, height);
}
@Unique
private void beforeInit(class_310 client, int width, int height) {
// All elements are repopulated on the screen, so we need to reinitialize all events
this.fabricButtons = null;
this.removeEvent = ScreenEventFactory.createRemoveEvent();
this.beforeRenderEvent = ScreenEventFactory.createBeforeRenderEvent();
this.afterRenderEvent = ScreenEventFactory.createAfterRenderEvent();
this.beforeTickEvent = ScreenEventFactory.createBeforeTickEvent();
this.afterTickEvent = ScreenEventFactory.createAfterTickEvent();
// Keyboard
this.allowKeyPressEvent = ScreenEventFactory.createAllowKeyPressEvent();
this.beforeKeyPressEvent = ScreenEventFactory.createBeforeKeyPressEvent();
this.afterKeyPressEvent = ScreenEventFactory.createAfterKeyPressEvent();
this.allowKeyReleaseEvent = ScreenEventFactory.createAllowKeyReleaseEvent();
this.beforeKeyReleaseEvent = ScreenEventFactory.createBeforeKeyReleaseEvent();
this.afterKeyReleaseEvent = ScreenEventFactory.createAfterKeyReleaseEvent();
// Mouse
this.allowMouseClickEvent = ScreenEventFactory.createAllowMouseClickEvent();
this.beforeMouseClickEvent = ScreenEventFactory.createBeforeMouseClickEvent();
this.afterMouseClickEvent = ScreenEventFactory.createAfterMouseClickEvent();
this.allowMouseReleaseEvent = ScreenEventFactory.createAllowMouseReleaseEvent();
this.beforeMouseReleaseEvent = ScreenEventFactory.createBeforeMouseReleaseEvent();
this.afterMouseReleaseEvent = ScreenEventFactory.createAfterMouseReleaseEvent();
this.allowMouseScrollEvent = ScreenEventFactory.createAllowMouseScrollEvent();
this.beforeMouseScrollEvent = ScreenEventFactory.createBeforeMouseScrollEvent();
this.afterMouseScrollEvent = ScreenEventFactory.createAfterMouseScrollEvent();
ScreenEvents.BEFORE_INIT.invoker().beforeInit(client, (class_437) (Object) this, width, height);
}
@Unique
private void afterInit(class_310 client, int width, int height) {
ScreenEvents.AFTER_INIT.invoker().afterInit(client, (class_437) (Object) this, width, height);
}
@Override
public List<class_339> fabric_getButtons() {
// Lazy init to make the list access safe after Screen#init
if (this.fabricButtons == null) {
this.fabricButtons = new ButtonList(this.drawables, this.selectables, this.children);
}
return this.fabricButtons;
}
@Unique
private <T> Event<T> ensureEventsAreInitialized(Event<T> event) {
if (event == null) {
throw new IllegalStateException(String.format("[fabric-screen-api-v1] The current screen (%s) has not been correctly initialised, please send this crash log to the mod author. This is usually caused by calling setScreen on the wrong thread.", this.getClass().getName()));
}
return event;
}
@Override
public Event<ScreenEvents.Remove> fabric_getRemoveEvent() {
return ensureEventsAreInitialized(this.removeEvent);
}
@Override
public Event<ScreenEvents.BeforeTick> fabric_getBeforeTickEvent() {
return ensureEventsAreInitialized(this.beforeTickEvent);
}
@Override
public Event<ScreenEvents.AfterTick> fabric_getAfterTickEvent() {
return ensureEventsAreInitialized(this.afterTickEvent);
}
@Override
public Event<ScreenEvents.BeforeRender> fabric_getBeforeRenderEvent() {
return ensureEventsAreInitialized(this.beforeRenderEvent);
}
@Override
public Event<ScreenEvents.AfterRender> fabric_getAfterRenderEvent() {
return ensureEventsAreInitialized(this.afterRenderEvent);
}
// Keyboard
@Override
public Event<ScreenKeyboardEvents.AllowKeyPress> fabric_getAllowKeyPressEvent() {
return ensureEventsAreInitialized(this.allowKeyPressEvent);
}
@Override
public Event<ScreenKeyboardEvents.BeforeKeyPress> fabric_getBeforeKeyPressEvent() {
return ensureEventsAreInitialized(this.beforeKeyPressEvent);
}
@Override
public Event<ScreenKeyboardEvents.AfterKeyPress> fabric_getAfterKeyPressEvent() {
return ensureEventsAreInitialized(this.afterKeyPressEvent);
}
@Override
public Event<ScreenKeyboardEvents.AllowKeyRelease> fabric_getAllowKeyReleaseEvent() {
return ensureEventsAreInitialized(this.allowKeyReleaseEvent);
}
@Override
public Event<ScreenKeyboardEvents.BeforeKeyRelease> fabric_getBeforeKeyReleaseEvent() {
return ensureEventsAreInitialized(this.beforeKeyReleaseEvent);
}
@Override
public Event<ScreenKeyboardEvents.AfterKeyRelease> fabric_getAfterKeyReleaseEvent() {
return ensureEventsAreInitialized(this.afterKeyReleaseEvent);
}
// Mouse
@Override
public Event<ScreenMouseEvents.AllowMouseClick> fabric_getAllowMouseClickEvent() {
return ensureEventsAreInitialized(this.allowMouseClickEvent);
}
@Override
public Event<ScreenMouseEvents.BeforeMouseClick> fabric_getBeforeMouseClickEvent() {
return ensureEventsAreInitialized(this.beforeMouseClickEvent);
}
@Override
public Event<ScreenMouseEvents.AfterMouseClick> fabric_getAfterMouseClickEvent() {
return ensureEventsAreInitialized(this.afterMouseClickEvent);
}
@Override
public Event<ScreenMouseEvents.AllowMouseRelease> fabric_getAllowMouseReleaseEvent() {
return ensureEventsAreInitialized(this.allowMouseReleaseEvent);
}
@Override
public Event<ScreenMouseEvents.BeforeMouseRelease> fabric_getBeforeMouseReleaseEvent() {
return ensureEventsAreInitialized(this.beforeMouseReleaseEvent);
}
@Override
public Event<ScreenMouseEvents.AfterMouseRelease> fabric_getAfterMouseReleaseEvent() {
return ensureEventsAreInitialized(this.afterMouseReleaseEvent);
}
@Override
public Event<ScreenMouseEvents.AllowMouseScroll> fabric_getAllowMouseScrollEvent() {
return ensureEventsAreInitialized(this.allowMouseScrollEvent);
}
@Override
public Event<ScreenMouseEvents.BeforeMouseScroll> fabric_getBeforeMouseScrollEvent() {
return ensureEventsAreInitialized(this.beforeMouseScrollEvent);
}
@Override
public Event<ScreenMouseEvents.AfterMouseScroll> fabric_getAfterMouseScrollEvent() {
return ensureEventsAreInitialized(this.afterMouseScrollEvent);
}
}