Improve look of notification GUI, improve StartupQuery API
This commit is contained in:
parent
f0bab0fb38
commit
eb9c966095
|
@ -25,6 +25,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
import org.apache.logging.log4j.MarkerManager;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.dedicated.DedicatedServer;
|
||||
|
@ -34,31 +43,74 @@ import net.minecraftforge.fml.client.gui.screen.NotificationScreen;
|
|||
import net.minecraftforge.fml.common.thread.EffectiveSide;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
import org.apache.logging.log4j.MarkerManager;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class StartupQuery {
|
||||
|
||||
public static class QueryBuilder
|
||||
{
|
||||
private String header = "";
|
||||
private String text = "";
|
||||
private String action = "";
|
||||
|
||||
QueryBuilder() {}
|
||||
|
||||
public QueryBuilder header(String header)
|
||||
{
|
||||
this.header = Strings.nullToEmpty(header);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryBuilder text(String text)
|
||||
{
|
||||
this.text = Strings.nullToEmpty(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
public QueryBuilder action(String action)
|
||||
{
|
||||
this.action = Strings.nullToEmpty(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean confirm()
|
||||
{
|
||||
return build(new AtomicBoolean()).getResult();
|
||||
}
|
||||
|
||||
public void notification()
|
||||
{
|
||||
build(null);
|
||||
}
|
||||
|
||||
private StartupQuery build(AtomicBoolean result)
|
||||
{
|
||||
StartupQuery query = new StartupQuery(header, text, action, new AtomicBoolean());
|
||||
query.execute();
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
// internal class/functionality, do not use
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Marker SQ = MarkerManager.getMarker("STARTUPQUERY");
|
||||
|
||||
public static QueryBuilder builder()
|
||||
{
|
||||
return new QueryBuilder();
|
||||
}
|
||||
|
||||
@Deprecated // TODO 1.16 remove
|
||||
public static boolean confirm(String text)
|
||||
{
|
||||
StartupQuery query = new StartupQuery(text, new AtomicBoolean());
|
||||
query.execute();
|
||||
return query.getResult();
|
||||
return builder().text(text).confirm();
|
||||
}
|
||||
|
||||
private InterruptedException exception;
|
||||
|
||||
@Deprecated // TODO 1.16 remove
|
||||
public static void notify(String text)
|
||||
{
|
||||
StartupQuery query = new StartupQuery(text, null);
|
||||
query.execute();
|
||||
builder().text(text).notification();
|
||||
}
|
||||
|
||||
public static void abort()
|
||||
|
@ -116,9 +168,11 @@ public class StartupQuery {
|
|||
private static volatile boolean aborted = false;
|
||||
|
||||
|
||||
private StartupQuery(String text, @Nullable AtomicBoolean result)
|
||||
private StartupQuery(String header, String text, String action, @Nullable AtomicBoolean result)
|
||||
{
|
||||
this.header = header;
|
||||
this.text = text;
|
||||
this.action = action;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
|
@ -133,11 +187,21 @@ public class StartupQuery {
|
|||
this.result.set(result);
|
||||
}
|
||||
|
||||
public String getHeader()
|
||||
{
|
||||
return header;
|
||||
}
|
||||
|
||||
public String getText()
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
public String getAction()
|
||||
{
|
||||
return action;
|
||||
}
|
||||
|
||||
public boolean isSynchronous()
|
||||
{
|
||||
return synchronous;
|
||||
|
@ -194,7 +258,9 @@ public class StartupQuery {
|
|||
}
|
||||
}
|
||||
|
||||
private String text;
|
||||
private final String header;
|
||||
private final String text;
|
||||
private final String action;
|
||||
@Nullable
|
||||
private AtomicBoolean result;
|
||||
private CountDownLatch signal = new CountDownLatch(1);
|
||||
|
|
|
@ -30,16 +30,16 @@ public class ConfirmationScreen extends NotificationScreen
|
|||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
protected void addConfirmationButtons()
|
||||
{
|
||||
this.addButton(new Button(this.width / 2 - 104, this.height - 38, 100, 20, ForgeI18n.parseMessage("gui.yes"), b ->
|
||||
this.addButton(new Button(this.width / 2 - 104, this.height - PADDING - 20, 100, 20, ForgeI18n.parseMessage("gui.yes"), b ->
|
||||
{
|
||||
ConfirmationScreen.this.minecraft.currentScreen = null;
|
||||
query.setResult(true);
|
||||
query.finish();
|
||||
}
|
||||
));
|
||||
this.addButton(new Button(this.width / 2 + 4, this.height - 38, 100, 20, ForgeI18n.parseMessage("gui.no"), b ->
|
||||
this.addButton(new Button(this.width / 2 + 4, this.height - PADDING - 20, 100, 20, ForgeI18n.parseMessage("gui.no"), b ->
|
||||
{
|
||||
ConfirmationScreen.this.minecraft.currentScreen = null;
|
||||
query.setResult(false);
|
||||
|
|
|
@ -20,23 +20,81 @@
|
|||
package net.minecraftforge.fml.client.gui.screen;
|
||||
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraftforge.client.gui.ScrollPanel;
|
||||
import net.minecraftforge.fml.StartupQuery;
|
||||
|
||||
public class NotificationScreen extends Screen
|
||||
{
|
||||
private class TextPanel extends ScrollPanel
|
||||
{
|
||||
TextPanel(Minecraft client, int width, int height, int top, int left)
|
||||
{
|
||||
super(client, width, height, top, left);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getContentHeight()
|
||||
{
|
||||
int height = 0;
|
||||
height += (textLines.length * font.FONT_HEIGHT) + 4;
|
||||
if (height < this.height - 50)
|
||||
height = this.height - 50;
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawPanel(int entryRight, int relativeY, Tessellator tess, int mouseX, int mouseY)
|
||||
{
|
||||
drawCenteredLines(relativeY, textLines);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getScrollAmount()
|
||||
{
|
||||
return font.FONT_HEIGHT * 3;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final int PADDING = 6;
|
||||
|
||||
protected final StartupQuery query;
|
||||
|
||||
private final String[] headerLines;
|
||||
private final String[] textLines;
|
||||
private final String action;
|
||||
|
||||
private ScrollPanel textPanel;
|
||||
|
||||
public NotificationScreen(StartupQuery query)
|
||||
{
|
||||
super(new TranslationTextComponent("fml.menu.notification.title"));
|
||||
this.query = query;
|
||||
this.headerLines = query.getHeader().isEmpty() ? new String[0] : query.getHeader().split("\n");
|
||||
this.textLines = query.getText().split("\n");
|
||||
this.action = query.getAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
this.buttons.add(new Button(this.width / 2 - 100, this.height - 38, 200, 20, I18n.format("gui.done"), b -> {
|
||||
super.init();
|
||||
int panelY = PADDING + headerLines.length * font.FONT_HEIGHT + PADDING;
|
||||
int panelHeight = this.height - PADDING - 20 - panelY;
|
||||
if (!action.isEmpty()) {
|
||||
panelHeight = panelHeight - font.FONT_HEIGHT - PADDING;
|
||||
}
|
||||
textPanel = new TextPanel(this.minecraft, this.width - (PADDING * 2), panelHeight, panelY, PADDING);
|
||||
this.children.add(textPanel);
|
||||
addConfirmationButtons();
|
||||
}
|
||||
|
||||
protected void addConfirmationButtons() {
|
||||
this.buttons.add(new Button(this.width / 2 - 100, this.height - PADDING - 20, 200, 20, I18n.format("gui.done"), b -> {
|
||||
NotificationScreen.this.minecraft.displayGuiScreen(null);
|
||||
query.finish();
|
||||
}));
|
||||
|
@ -47,29 +105,28 @@ public class NotificationScreen extends Screen
|
|||
{
|
||||
this.renderBackground();
|
||||
|
||||
String[] lines = query.getText().split("\n");
|
||||
drawCenteredLines(PADDING, headerLines);
|
||||
|
||||
int spaceAvailable = this.height - 38 - 20;
|
||||
int spaceRequired = Math.min(spaceAvailable, 10 + 10 * lines.length);
|
||||
|
||||
int offset = 10 + (spaceAvailable - spaceRequired) / 2; // vertically centered
|
||||
|
||||
for (String line : lines)
|
||||
if (textPanel != null)
|
||||
{
|
||||
if (offset >= spaceAvailable)
|
||||
{
|
||||
this.drawCenteredString(this.font, "...", this.width / 2, offset, 0xFFFFFF);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!line.isEmpty()) this.drawCenteredString(this.font, line, this.width / 2, offset, 0xFFFFFF);
|
||||
offset += 10;
|
||||
}
|
||||
textPanel.render(mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
if (!action.isEmpty())
|
||||
{
|
||||
drawCenteredString(font, action, this.width / 2, this.height - PADDING - 20 - font.FONT_HEIGHT, -1);
|
||||
}
|
||||
|
||||
super.render(mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
protected final StartupQuery query;
|
||||
protected void drawCenteredLines(int yStart, String... lines)
|
||||
{
|
||||
for (String line : lines)
|
||||
{
|
||||
if (!line.isEmpty())
|
||||
this.drawCenteredString(font, line, this.width / 2, yStart, 0xFFFFFF);
|
||||
yStart += font.FONT_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,8 +99,6 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static net.minecraftforge.registries.ForgeRegistry.REGISTRIES;
|
||||
|
||||
import net.minecraftforge.fml.common.EnhancedRuntimeException.WrappedPrintStream;
|
||||
|
||||
/**
|
||||
* INTERNAL ONLY
|
||||
* MODDERS SHOULD HAVE NO REASON TO USE THIS CLASS
|
||||
|
@ -728,16 +726,23 @@ public class GameData
|
|||
List<ResourceLocation> missingRegs = snapshot.keySet().stream().filter(name -> !RegistryManager.ACTIVE.registries.containsKey(name)).collect(Collectors.toList());
|
||||
if (missingRegs.size() > 0)
|
||||
{
|
||||
String text = "Forge Mod Loader detected missing/unknown registrie(s).\n\n" +
|
||||
String header = "Forge Mod Loader detected missing/unknown registrie(s).\n\n" +
|
||||
"There are " + missingRegs.size() + " missing registries in this save.\n" +
|
||||
"If you continue the missing registries will get removed.\n" +
|
||||
"This may cause issues, it is advised that you create a world backup before continuing.\n\n" +
|
||||
"Missing Registries:\n";
|
||||
"This may cause issues, it is advised that you create a world backup before continuing.\n\n";
|
||||
|
||||
StringBuilder text = new StringBuilder("Missing Registries:\n");
|
||||
|
||||
for (ResourceLocation s : missingRegs)
|
||||
text += s.toString() + "\n";
|
||||
text.append(s).append("\n");
|
||||
|
||||
if (!StartupQuery.confirm(text))
|
||||
boolean confirmed = StartupQuery.builder()
|
||||
.header(header)
|
||||
.text(text.toString())
|
||||
.action("Continue anyway?")
|
||||
.confirm();
|
||||
|
||||
if (!confirmed)
|
||||
StartupQuery.abort();
|
||||
}
|
||||
}
|
||||
|
@ -816,19 +821,24 @@ public class GameData
|
|||
|
||||
if (!defaulted.isEmpty())
|
||||
{
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("Forge Mod Loader detected missing registry entries.\n\n")
|
||||
.append("There are ").append(defaulted.size()).append(" missing entries in this save.\n")
|
||||
.append("If you continue the missing entries will get removed.\n")
|
||||
.append("A world backup will be automatically created in your saves directory.\n\n");
|
||||
String header = "Forge Mod Loader detected missing registry entries.\n\n" +
|
||||
"There are " + defaulted.size() + " missing entries in this save.\n" +
|
||||
"If you continue the missing entries will get removed.\n" +
|
||||
"A world backup will be automatically created in your saves directory.\n\n";
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
defaulted.asMap().forEach((name, entries) ->
|
||||
{
|
||||
buf.append("Missing ").append(name).append(":\n");
|
||||
entries.forEach(rl -> buf.append(" ").append(rl).append("\n"));
|
||||
buf.append("\n");
|
||||
});
|
||||
|
||||
boolean confirmed = StartupQuery.confirm(buf.toString());
|
||||
boolean confirmed = StartupQuery.builder()
|
||||
.header(header)
|
||||
.text(buf.toString())
|
||||
.action("Remove entries and continue?")
|
||||
.confirm();
|
||||
if (!confirmed)
|
||||
StartupQuery.abort();
|
||||
|
||||
|
|
Loading…
Reference in New Issue