Skip to content
This repository has been archived by the owner on Oct 14, 2023. It is now read-only.

Commit

Permalink
添加经典样式二次屏幕
Browse files Browse the repository at this point in the history
  • Loading branch information
CaaMoe committed Apr 27, 2023
1 parent 531b542 commit f243f66
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 14 deletions.
49 changes: 42 additions & 7 deletions src/main/java/moe/caa/fabric/quitconfirm/client/config/Config.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
package moe.caa.fabric.quitconfirm.client.config;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import moe.caa.fabric.quitconfirm.client.main.QuitConfirm;
import moe.caa.fabric.quitconfirm.client.screen.confirm.style.BaseStyle;
import moe.caa.fabric.quitconfirm.client.screen.confirm.style.ClassicStyle;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.function.Supplier;

public class Config {
public static Config config = new Config();
public static final Config config = new Config();
private static final Gson gson = new Gson();
private static final Path path = Path.of("config/quitconfirm.json");

public ConfirmTypeEnum confirmTypeInFinalQuit = ConfirmTypeEnum.SCREEN;
public ConfirmTypeEnum confirmTypeInSinglePlayer = ConfirmTypeEnum.TOAST;
public ConfirmTypeEnum confirmTypeInMultiplayer = ConfirmTypeEnum.TOAST;
Expand All @@ -29,9 +34,38 @@ public static void load() {
save();
return;
}
config = gson.fromJson(Files.readString(path), Config.class);
JsonElement element = JsonParser.parseString(Files.readString(path));
JsonObject object = element.getAsJsonObject();
if (object.has("confirmTypeInFinalQuit")) {
config.confirmTypeInFinalQuit = ConfirmTypeEnum.valueOf(object.getAsJsonPrimitive("confirmTypeInFinalQuit").getAsString());
}
if (object.has("confirmTypeInSinglePlayer")) {
config.confirmTypeInSinglePlayer = ConfirmTypeEnum.valueOf(object.getAsJsonPrimitive("confirmTypeInSinglePlayer").getAsString());
}
if (object.has("confirmTypeInMultiplayer")) {
config.confirmTypeInMultiplayer = ConfirmTypeEnum.valueOf(object.getAsJsonPrimitive("confirmTypeInMultiplayer").getAsString());
}
if (object.has("enableScreenShortcutKey")) {
config.enableScreenShortcutKey = object.getAsJsonPrimitive("enableScreenShortcutKey").getAsBoolean();
}
if (object.has("keepDarkInConfirmScreenTime")) {
config.keepDarkInConfirmScreenTime = object.getAsJsonPrimitive("keepDarkInConfirmScreenTime").getAsLong();
}
if (object.has("confirmScreenDisplayType")) {
config.confirmScreenDisplayType = ConfirmScreenDisplayTypeEnum.valueOf(object.getAsJsonPrimitive("confirmScreenDisplayType").getAsString());
}
if (object.has("toastConfirmDisplayTime")) {
config.toastConfirmDisplayTime = object.getAsJsonPrimitive("toastConfirmDisplayTime").getAsLong();
}
if (object.has("toastConfirmStartAliveTime")) {
config.toastConfirmStartAliveTime = object.getAsJsonPrimitive("toastConfirmStartAliveTime").getAsLong();
}
if (object.has("toastConfirmEndAliveTime")) {
config.toastConfirmEndAliveTime = object.getAsJsonPrimitive("toastConfirmEndAliveTime").getAsLong();
}
} catch (Exception e){
QuitConfirm.LOGGER.error("Failed to read " + path, e);
save();
}
}

Expand All @@ -50,13 +84,14 @@ public <T extends Enum<T>> T nextEnum(Class<T> tClass, T value) {
}

public enum ConfirmScreenDisplayTypeEnum {
CLASSIC("经典"),
BEDROCK("基岩"),
BEDROCK_OPAQUE("基岩(不透明)");
CLASSIC("经典", ClassicStyle::new),
BEDROCK("基岩", ClassicStyle::new);
public final String displayName;
public final Supplier<BaseStyle> baseStyleSupplier;

ConfirmScreenDisplayTypeEnum(String displayName) {
ConfirmScreenDisplayTypeEnum(String displayName, Supplier<BaseStyle> baseStyleSupplier) {
this.displayName = displayName;
this.baseStyleSupplier = baseStyleSupplier;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
import moe.caa.fabric.quitconfirm.client.event.ClientScheduleStopEvent;
import moe.caa.fabric.quitconfirm.client.event.EventResult;
import moe.caa.fabric.quitconfirm.client.handle.ToastQuitHandler;
import moe.caa.fabric.quitconfirm.client.screen.confirm.ConfirmScreen;
import net.fabricmc.api.ClientModInitializer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.GameMenuScreen;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableTextContent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



public class QuitConfirm implements ClientModInitializer {
public static final Logger LOGGER = LoggerFactory.getLogger("QuitConfirm");
private final ToastQuitHandler toastInFinalQuitHandler = new ToastQuitHandler("退出这个游戏,请再次操作");
Expand All @@ -28,7 +29,8 @@ public void onInitializeClient() {
return toastInFinalQuitHandler.trigger();
}
if (Config.config.confirmTypeInFinalQuit == Config.ConfirmTypeEnum.SCREEN) {
return toastInFinalQuitHandler.trigger();
MinecraftClient.getInstance().setScreen(new ConfirmScreen(MinecraftClient.getInstance().currentScreen, Text.literal("退出这个游戏"), () -> MinecraftClient.getInstance().scheduleStop()));
return EventResult.CANCEL;
}
return EventResult.PASS;
});
Expand All @@ -45,10 +47,24 @@ public void onInitializeClient() {
key = ((TranslatableTextContent) button.getMessage().getContent()).getKey();
}
if ("menu.returnToMenu".equals(key)) {
return toastInSinglePlayerQuitHandle.trigger();
if (Config.config.confirmTypeInSinglePlayer == Config.ConfirmTypeEnum.TOAST) {
return toastInSinglePlayerQuitHandle.trigger();
}
if (Config.config.confirmTypeInSinglePlayer == Config.ConfirmTypeEnum.SCREEN) {
MinecraftClient.getInstance().setScreen(new ConfirmScreen(MinecraftClient.getInstance().currentScreen, Text.literal("退出单人游戏"), button::onPress));
return EventResult.CANCEL;
}
return EventResult.PASS;
}
if ("menu.disconnect".equals(key)) {
return toastInMultiplayerQuitHandle.trigger();
if (Config.config.confirmTypeInMultiplayer == Config.ConfirmTypeEnum.TOAST) {
return toastInMultiplayerQuitHandle.trigger();
}
if (Config.config.confirmTypeInMultiplayer == Config.ConfirmTypeEnum.SCREEN) {
MinecraftClient.getInstance().setScreen(new ConfirmScreen(MinecraftClient.getInstance().currentScreen, Text.literal("退出多人游戏"), button::onPress));
return EventResult.CANCEL;
}
return EventResult.PASS;
}
return EventResult.PASS;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import moe.caa.fabric.quitconfirm.client.event.ButtonPressEvent;
import moe.caa.fabric.quitconfirm.client.event.EventResult;
import moe.caa.fabric.quitconfirm.client.screen.confirm.ConfirmScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.ButtonWidget;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
Expand All @@ -13,6 +15,7 @@
public class MixinButtonWidget {
@Inject(method = "onPress", at = @At("HEAD"), cancellable = true)
private void onOnPress(CallbackInfo ci) {
if (MinecraftClient.getInstance().currentScreen instanceof ConfirmScreen) return;
EventResult result = ButtonPressEvent.BUTTON_PRESS.invoker().onPress((ButtonWidget) (Object) this);
if(result == EventResult.CANCEL){
ci.cancel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import moe.caa.fabric.quitconfirm.client.event.ClientScheduleStopEvent;
import moe.caa.fabric.quitconfirm.client.event.EventResult;
import moe.caa.fabric.quitconfirm.client.screen.confirm.ConfirmScreen;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.Window;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -14,12 +17,18 @@

@Mixin(MinecraftClient.class)
public class MixinMinecraftClient {
@Shadow @Final private Window window;
@Shadow
@Nullable
public Screen currentScreen;
@Shadow
@Final
private Window window;

@Inject(method = "scheduleStop", at = @At("HEAD"), cancellable = true)
private void onScheduleStop(CallbackInfo ci){
private void onScheduleStop(CallbackInfo ci) {
if (currentScreen instanceof ConfirmScreen) return;
EventResult result = ClientScheduleStopEvent.CLIENT_SCHEDULE_STOP.invoker().onScheduleStop();
if(result == EventResult.CANCEL){
if (result == EventResult.CANCEL) {
GLFW.glfwSetWindowShouldClose(this.window.getHandle(), false);
ci.cancel();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package moe.caa.fabric.quitconfirm.client.screen.confirm;

import moe.caa.fabric.quitconfirm.client.config.Config;
import moe.caa.fabric.quitconfirm.client.screen.confirm.style.BaseStyle;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;

public class ConfirmScreen extends Screen {
private final Text message;
private final ButtonWidget.PressAction onCancel;
private final ButtonWidget.PressAction onConfirm;
private final long openTime;
private final BaseStyle style = Config.config.confirmScreenDisplayType.baseStyleSupplier.get();
private ButtonWidget cancel;
private ButtonWidget confirm;

public ConfirmScreen(Screen parentScreen, Text message, Runnable confirm) {
this(parentScreen, message, button -> confirm.run());
}

public ConfirmScreen(Screen parentScreen, Text message, ButtonWidget.PressAction confirm) {
super(Text.literal("你确定?"));
openTime = System.currentTimeMillis();
this.message = message;
onCancel = (buttonWidget) -> this.client.setScreen(parentScreen);
onConfirm = confirm;
}

@Override
protected void init() {
initButton();
}

@Override
public void tick() {
if (openTime + Config.config.keepDarkInConfirmScreenTime < System.currentTimeMillis()) {
cancel.active = true;
confirm.active = true;
}
}

private void initButton() {
confirm = style.generateConfirmButtons(this, onConfirm);
cancel = style.generateCancelButtons(this, onCancel);

confirm.active = false;
cancel.active = false;
this.addDrawableChild(confirm);
this.addDrawableChild(cancel);
}

@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
style.render(this.client, this.textRenderer, this, title, message, matrices, mouseX, mouseY, delta);
super.render(matrices, mouseX, mouseY, delta);
}

@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (Config.config.enableScreenShortcutKey && keyCode == 257 /* ENTER */) {
onConfirm.onPress(confirm);
}
return super.keyPressed(keyCode, scanCode, modifiers);
}

@Override
public boolean shouldCloseOnEsc() {
return Config.config.enableScreenShortcutKey;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package moe.caa.fabric.quitconfirm.client.screen.confirm.style;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Text;

public abstract class BaseStyle extends DrawableHelper {


public abstract ButtonWidget generateConfirmButtons(Screen screen, ButtonWidget.PressAction onConfirm);

public abstract ButtonWidget generateCancelButtons(Screen screen, ButtonWidget.PressAction onCancel);

public abstract void render(MinecraftClient client, TextRenderer textRenderer, Screen screen, Text title, Text message,
MatrixStack matrices, int mouseX, int mouseY, float delta);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package moe.caa.fabric.quitconfirm.client.screen.confirm.style;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.ScreenTexts;
import net.minecraft.text.Text;

public class ClassicStyle extends BaseStyle {
// 按钮宽度
private static final int buttonWidth = 150;
// 按钮长度
private static final int buttonHeight = 20;
// 按钮间隔
private static final int buttonFMargin = 10;
// 按钮下边距
private static final int buttonBMargin = 40;
// 标题上边距
private static final int titleTMargin = 30;

@Override
public ButtonWidget generateConfirmButtons(Screen screen, ButtonWidget.PressAction onConfirm) {
return ButtonWidget.builder(ScreenTexts.YES, onConfirm)
.dimensions(screen.width / 2 - buttonWidth - buttonFMargin,
screen.height - buttonHeight - buttonBMargin,
buttonWidth, buttonHeight).build();
}

@Override
public ButtonWidget generateCancelButtons(Screen screen, ButtonWidget.PressAction onCancel) {
return ButtonWidget.builder(ScreenTexts.NO, onCancel)
.dimensions(screen.width / 2 + buttonFMargin,
screen.height - buttonHeight - buttonBMargin,
buttonWidth, buttonHeight).build();
}

@Override
public void render(MinecraftClient client, TextRenderer textRenderer, Screen screen, Text title, Text message,
MatrixStack matrices, int mouseX, int mouseY, float delta) {
this.renderBackground(matrices, screen);
drawTextAndMessage(textRenderer, screen, title, message, matrices);
}

public void renderBackground(MatrixStack matrices, Screen screen) {
if (MinecraftClient.getInstance().world != null) {
fillGradient(matrices, 0, 0, screen.width, screen.height, -1072689136, -804253680);
} else {
screen.renderBackgroundTexture(matrices);
}
}

private void drawTextAndMessage(TextRenderer textRenderer, Screen screen, Text title, Text message, MatrixStack matrices) {
drawCenteredTextWithShadow(matrices, textRenderer, title,
screen.width / 2,
titleTMargin,
16777215);

drawCenteredTextWithShadow(matrices, textRenderer, message,
screen.width / 2,
screen.height / 2 - 30,
10526880);
}
}

0 comments on commit f243f66

Please sign in to comment.