Make disconnected screen reason text scrollable (#2349)

* Make disconnected screen reason text scrollable

* Remove redundant mixin.

* wrong unique

* fix max scroll having additional line-sized gap

* turns out it's the testmod fault for having an extra new line

Co-authored-by: modmuss50 <modmuss50@gmail.com>
This commit is contained in:
deirn 2022-07-22 02:07:37 +07:00 committed by GitHub
parent 5187d39fe0
commit c54bb47e4e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 137 additions and 1 deletions

View file

@ -0,0 +1,94 @@
/*
* 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.networking.client;
import com.mojang.blaze3d.systems.RenderSystem;
import org.objectweb.asm.Opcodes;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.font.MultilineText;
import net.minecraft.client.gui.screen.DisconnectedScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.MathHelper;
/**
* This mixin makes disconnect reason text scrollable.
*/
@Mixin(DisconnectedScreen.class)
public abstract class DisconnectedScreenMixin extends Screen {
@Shadow
private int reasonHeight;
@Unique
private int actualReasonHeight;
@Unique
private int scroll;
@Unique
private int maxScroll;
private DisconnectedScreenMixin() {
super(null);
}
// Inject to right after reasonHeight is stored, to make sure the back button have correct position.
@Inject(method = "init", at = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/screen/DisconnectedScreen;reasonHeight:I", opcode = Opcodes.PUTFIELD, shift = At.Shift.AFTER))
private void init(CallbackInfo ci) {
actualReasonHeight = reasonHeight;
reasonHeight = Math.min(reasonHeight, height - 100);
scroll = 0;
maxScroll = actualReasonHeight - reasonHeight;
}
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/font/MultilineText;drawCenterWithShadow(Lnet/minecraft/client/util/math/MatrixStack;II)I"))
private int render(MultilineText instance, MatrixStack matrixStack, int x, int y) {
double scale = client.getWindow().getScaleFactor();
RenderSystem.enableScissor(0, (int) (y * scale), (int) (width * scale), (int) (reasonHeight * scale));
instance.drawCenterWithShadow(matrixStack, x, y - scroll);
RenderSystem.disableScissor();
// Draw gradient at the top/bottom to indicate that the text is scrollable.
if (actualReasonHeight > reasonHeight) {
int startX = (width - instance.getMaxWidth()) / 2;
int endX = (width + instance.getMaxWidth()) / 2;
if (scroll > 0) {
fillGradient(matrixStack, startX, y, endX, y + 10, 0xFF000000, 0);
}
if (scroll < maxScroll) {
fillGradient(matrixStack, startX, y + reasonHeight - 10, endX, y + reasonHeight, 0, 0xFF000000);
}
}
return y + reasonHeight;
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
scroll = MathHelper.clamp(scroll - (MathHelper.sign(amount) * client.textRenderer.fontHeight * 10), 0, maxScroll);
return super.mouseScrolled(mouseX, mouseY, amount);
}
}

View file

@ -6,7 +6,8 @@
"accessor.ConnectScreenAccessor", "accessor.ConnectScreenAccessor",
"accessor.MinecraftClientAccessor", "accessor.MinecraftClientAccessor",
"client.ClientLoginNetworkHandlerMixin", "client.ClientLoginNetworkHandlerMixin",
"client.ClientPlayNetworkHandlerMixin" "client.ClientPlayNetworkHandlerMixin",
"client.DisconnectedScreenMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1

View file

@ -0,0 +1,40 @@
/*
* 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.test.networking.disconnectscreen;
import net.minecraft.text.Text;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
public class DisconnectScreenTest implements ClientModInitializer {
@Override
public void onInitializeClient() {
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) ->
dispatcher.register(ClientCommandManager.literal("disconnect_screen_test").executes(context -> {
StringBuilder builder = new StringBuilder("A very long disconnect reason:");
for (int i = 0; i < 100; i++) {
builder.append("\nLine ").append(i + 1);
}
context.getSource().getPlayer().networkHandler.getConnection().disconnect(Text.of(builder.toString()));
return 1;
})));
}
}

View file

@ -17,6 +17,7 @@
], ],
"client": [ "client": [
"net.fabricmc.fabric.test.networking.channeltest.NetworkingChannelClientTest", "net.fabricmc.fabric.test.networking.channeltest.NetworkingChannelClientTest",
"net.fabricmc.fabric.test.networking.disconnectscreen.DisconnectScreenTest",
"net.fabricmc.fabric.test.networking.keybindreciever.NetworkingKeybindClientPacketTest", "net.fabricmc.fabric.test.networking.keybindreciever.NetworkingKeybindClientPacketTest",
"net.fabricmc.fabric.test.networking.login.NetworkingLoginQueryClientTest", "net.fabricmc.fabric.test.networking.login.NetworkingLoginQueryClientTest",
"net.fabricmc.fabric.test.networking.play.NetworkingPlayPacketClientTest" "net.fabricmc.fabric.test.networking.play.NetworkingPlayPacketClientTest"