]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/client/gui/WorldSaveRow.java
Fully support keyboard nav in gui
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / client / gui / WorldSaveRow.java
1 package com.irtimaled.bbor.client.gui;
2
3 import com.google.common.hash.Hashing;
4 import com.irtimaled.bbor.client.interop.ClientInterop;
5 import net.minecraft.client.Minecraft;
6 import net.minecraft.client.gui.AbstractGui;
7 import net.minecraft.client.renderer.texture.DynamicTexture;
8 import net.minecraft.client.renderer.texture.NativeImage;
9 import net.minecraft.util.ResourceLocation;
10 import net.minecraft.util.Util;
11 import net.minecraft.world.storage.SaveFormat;
12 import net.minecraft.world.storage.WorldInfo;
13 import net.minecraft.world.storage.WorldSummary;
14 import org.apache.logging.log4j.LogManager;
15 import org.apache.logging.log4j.Logger;
16 import org.lwjgl.opengl.GL11;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.InputStream;
21 import java.text.DateFormat;
22 import java.text.SimpleDateFormat;
23 import java.util.Date;
24 import java.util.function.Consumer;
25
26 public class WorldSaveRow extends ControlListEntry implements Comparable<WorldSaveRow> {
27     private static final Logger LOGGER = LogManager.getLogger();
28     private static final DateFormat DATE_FORMAT = new SimpleDateFormat();
29     private static final ResourceLocation ICON_MISSING = new ResourceLocation("textures/misc/unknown_server.png");
30     private static final int ICON_SIZE = 20;
31     private final Minecraft client;
32     private final WorldSummary worldSummary;
33     private final SaveFormat saveLoader;
34     private final Consumer<ControlListEntry> setSelectedEntry;
35     private final ResourceLocation iconLocation;
36     private final DynamicTexture icon;
37
38     private File iconFile;
39     private long lastClickTime;
40
41     WorldSaveRow(WorldSummary worldSummary, SaveFormat saveLoader, Consumer<ControlListEntry> setSelectedEntry) {
42         this.worldSummary = worldSummary;
43         this.saveLoader = saveLoader;
44         this.setSelectedEntry = setSelectedEntry;
45         this.client = Minecraft.getInstance();
46         this.iconLocation = new ResourceLocation("worlds/" + Hashing.sha1().hashUnencodedChars(worldSummary.getFileName()) + "/icon");
47         this.iconFile = saveLoader.getFile(worldSummary.getFileName(), "icon.png");
48         if (!this.iconFile.isFile()) {
49             this.iconFile = null;
50         }
51
52         this.icon = this.loadIcon();
53     }
54
55     @Override
56     public boolean isMouseOver(double mouseX, double mouseY) {
57         return mouseX > this.getX() &&
58                 mouseX < this.getX() + ControlList.CONTROLS_WIDTH &&
59                 mouseY > this.getY() &&
60                 mouseY < this.getY() + this.getControlHeight();
61     }
62
63     @Override
64     public boolean mouseClicked(double mouseX, double mouseY, int button) {
65         if (!isMouseOver(mouseX, mouseY)) return false;
66
67         this.setSelectedEntry.accept(this);
68         if (Util.milliTime() - this.lastClickTime < 250L) {
69             done();
70         } else {
71             this.lastClickTime = Util.milliTime();
72         }
73         return true;
74     }
75
76     @Override
77     public void done() {
78         String fileName = this.worldSummary.getFileName();
79         WorldInfo worldInfo = saveLoader.getWorldInfo(fileName);
80         long seed = worldInfo.getSeed();
81         ClientInterop.saveLoaded(fileName, seed);
82     }
83
84     private DynamicTexture loadIcon() {
85         if (this.iconFile == null || !this.iconFile.isFile()) {
86             this.client.getTextureManager().deleteTexture(this.iconLocation);
87             return null;
88         }
89
90         try (InputStream stream = new FileInputStream(this.iconFile)) {
91             DynamicTexture texture = new DynamicTexture(NativeImage.read(stream));
92             this.client.getTextureManager().loadTexture(this.iconLocation, texture);
93             return texture;
94         } catch (Throwable exception) {
95             LOGGER.error("Invalid icon for world {}", this.worldSummary.getFileName(), exception);
96             this.iconFile = null;
97             return null;
98         }
99     }
100
101     @Override
102     public void render(int mouseX, int mouseY) {
103         String displayName = this.worldSummary.getDisplayName();
104         String details = this.worldSummary.getFileName() + " (" + DATE_FORMAT.format(new Date(this.worldSummary.getLastTimePlayed())) + ")";
105
106         int x = this.getX();
107         int y = this.getY();
108         this.client.fontRenderer.drawString(displayName, (float) (x + ICON_SIZE + 3), (float) (y + 1), 16777215);
109         this.client.fontRenderer.drawString(details, (float) (x + ICON_SIZE + 3), (float) (y + 1 + this.client.fontRenderer.FONT_HEIGHT + 1), 8421504);
110         this.client.getTextureManager().bindTexture(this.icon != null ? this.iconLocation : ICON_MISSING);
111         GL11.glEnable(GL11.GL_BLEND);
112         AbstractGui.blit(x, y, 0.0F, 0.0F, ICON_SIZE, ICON_SIZE, 32, 32);
113         GL11.glDisable(GL11.GL_BLEND);
114     }
115
116     @Override
117     public void filter(String lowerValue) {
118         super.setVisible(lowerValue.isEmpty() ||
119                 this.worldSummary.getDisplayName().toLowerCase().contains(lowerValue) ||
120                 this.worldSummary.getFileName().toLowerCase().contains(lowerValue));
121     }
122
123     @Override
124     public void close() {
125         if (this.icon != null) {
126             this.icon.close();
127         }
128     }
129
130     @Override
131     public int compareTo(WorldSaveRow other) {
132         return this.worldSummary.compareTo(other.worldSummary);
133     }
134 }