diff --git a/src/main/java/gregtech/api/mui/GTGuiTextures.java b/src/main/java/gregtech/api/mui/GTGuiTextures.java index 998ad9c1d03..a90a838feb5 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTextures.java +++ b/src/main/java/gregtech/api/mui/GTGuiTextures.java @@ -267,6 +267,7 @@ private static String id(String path) { public static final UITexture MENU_OVERLAY = fullImage("textures/gui/overlay/menu_overlay.png"); public static final UITexture RECIPE_LOCK = fullImage("textures/gui/widget/lock.png"); + public static final UITexture RECIPE_LOCK_WHITE = fullImage("textures/gui/widget/lock_white.png"); public static final UITexture PRIMITIVE_FURNACE_OVERLAY = fullImage( "textures/gui/primitive/overlay_primitive_furnace.png"); public static final UITexture PRIMITIVE_DUST_OVERLAY = fullImage( @@ -290,6 +291,11 @@ private static String id(String path) { public static final UITexture FLUID_LOCK_OVERLAY = fullImage("textures/gui/widget/button_lock.png", ColorType.DEFAULT); + public static final UITexture TERMINAL_FRAME = fullImage("textures/gui/terminal/terminal_frame.png"); + public static final UITexture HOME_BUTTON = fullImage("textures/gui/terminal/home_button.png"); + public static final UITexture HOME_BUTTON_HOVER = fullImage("textures/gui/terminal/home_button_hover.png"); + public static final UITexture CAPES_APP_ICON = fullImage("textures/gui/terminal/capes/icon.png"); + // todo bronze/steel/primitive fluid slots? // SLOT OVERLAYS diff --git a/src/main/java/gregtech/api/mui/GTGuiTheme.java b/src/main/java/gregtech/api/mui/GTGuiTheme.java index 01b5084ec2c..91144635b04 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTheme.java +++ b/src/main/java/gregtech/api/mui/GTGuiTheme.java @@ -99,6 +99,12 @@ private static String gregtech(String s) { .itemSlot(GTGuiTextures.IDs.PRIMITIVE_SLOT) .build(); + // TODO make this better + public static final GTGuiTheme TERMINAL = templateBuilder("gregtech_terminal") + .parent(Names.STANDARD) + .textColor(0xFFFDFDFD) + .build(); + protected final String themeId; protected final List> elementBuilder; diff --git a/src/main/java/gregtech/api/terminal2/ITerminalApp.java b/src/main/java/gregtech/api/terminal2/ITerminalApp.java new file mode 100644 index 00000000000..0865c6baf4a --- /dev/null +++ b/src/main/java/gregtech/api/terminal2/ITerminalApp.java @@ -0,0 +1,34 @@ +package gregtech.api.terminal2; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.GuiTextures; +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.UISettings; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; + +public interface ITerminalApp { + + /** + * Create the UI for your app. + */ + IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, UISettings settings, ModularPanel panel); + + /** + * @return The drawable that will be used for the icon of your app on the terminal home screen. + */ + default IDrawable getIcon() { + return GuiTextures.IMAGE; + } + + /** + * Called when the user opens your app from the terminal home screen. + */ + default void onOpen() {} + + /** + * Called when the terminal is closed. Free any references to UI elements or sync handlers here. + */ + default void dispose() {} +} diff --git a/src/main/java/gregtech/api/terminal2/Terminal2.java b/src/main/java/gregtech/api/terminal2/Terminal2.java new file mode 100644 index 00000000000..3dbe2f8018c --- /dev/null +++ b/src/main/java/gregtech/api/terminal2/Terminal2.java @@ -0,0 +1,59 @@ +package gregtech.api.terminal2; + +import gregtech.api.util.FileUtility; +import gregtech.api.util.GTUtility; +import gregtech.common.ConfigHolder; +import gregtech.common.terminal2.CapeSelectorApp; +import gregtech.common.terminal2.SettingsApp; + +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.io.File; +import java.util.LinkedHashMap; +import java.util.Map; + +public class Terminal2 { + + public static final int SCREEN_WIDTH = 340, SCREEN_HEIGHT = 240; + public static final Map appMap = new LinkedHashMap<>(); + public static final ResourceLocation HOME_ID = GTUtility.gregtechId("home"); + + @SideOnly(Side.CLIENT) + public static File TERMINAL_PATH; + + public static void init() { + if (FMLCommonHandler.instance().getSide().isClient()) { + TERMINAL_PATH = new File(Loader.instance().getConfigDir(), ConfigHolder.client.terminalRootPath); + FileUtility.extractJarFiles("/assets/gregtech/terminal", TERMINAL_PATH, false); + Terminal2Theme.init(); + } + registerApp(GTUtility.gregtechId("settings"), new SettingsApp()); + registerApp(GTUtility.gregtechId("capes"), new CapeSelectorApp()); + + /* + * TODO potential apps to create/port: + * guide/tutorial app using mui2 rich text and markup files of some sort + * terminal games (minesweeper, pong, theseus' escape) + * recipe chart (if anyone actually wants to port it) + * teleporter (would require a system allowing gating apps behind some requirement, too powerful to be default) + */ + } + + /** + * Register a terminal app. Call this during initialization. + * + * @param id A unique identifier for your app. This is used to determine the lang key for the app name tooltip. + *

+ * e.g. gregtech:capes -> terminal.app.gregtech.capes + */ + public static void registerApp(ResourceLocation id, ITerminalApp app) { + if (appMap.containsKey(id) || HOME_ID.equals(id)) { + throw new AssertionError("A terminal app with id " + id + " already exists!"); + } + appMap.put(id, app); + } +} diff --git a/src/main/java/gregtech/api/terminal2/Terminal2Theme.java b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java new file mode 100644 index 00000000000..98d7b2e93bf --- /dev/null +++ b/src/main/java/gregtech/api/terminal2/Terminal2Theme.java @@ -0,0 +1,143 @@ +package gregtech.api.terminal2; + +import gregtech.api.util.FileUtility; +import gregtech.api.util.GTUtility; +import gregtech.common.mui.drawable.BoundRectangle; +import gregtech.common.mui.drawable.FileTexture; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.drawable.UITexture; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + +import java.awt.Color; +import java.io.File; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@SuppressWarnings("unused") +public class Terminal2Theme { + + private static final String CONFIG_PATH = "config/theme.json"; + private static IDrawable currentBackgroundDrawable = null; + private static final UITexture defaultBackground = UITexture + .fullImage(GTUtility.gregtechId("textures/gui/terminal/terminal_background.png")); + public static File backgroundsDir; + private static final Map defaultColors = new Object2IntOpenHashMap<>(); + + public static String currentBackground = "default"; + // theres enough colors here to make specifying stuff for all of them annoying + // therefore, we use reflection for its intended purpose + public static final List colors = Arrays.stream(Terminal2Theme.class.getFields()) + .map(Field::getName).filter(name -> name.startsWith("COLOR_")).collect(Collectors.toList()); + + public static BoundRectangle COLOR_BRIGHT_1 = new BoundRectangle() + .setColor(new Color(144, 243, 116).getRGB()); + public static BoundRectangle COLOR_BRIGHT_2 = new BoundRectangle() + .setColor(new Color(243, 208, 116).getRGB()); + public static BoundRectangle COLOR_BRIGHT_3 = new BoundRectangle() + .setColor(new Color(231, 95, 95).getRGB()); + public static BoundRectangle COLOR_BRIGHT_4 = new BoundRectangle() + .setColor(new Color(230, 230, 230).getRGB()); + + public static BoundRectangle COLOR_DARK_1 = new BoundRectangle() + .setColor(new Color(0, 115, 255).getRGB()); + public static BoundRectangle COLOR_DARK_2 = new BoundRectangle() + .setColor(new Color(113, 27, 217).getRGB()); + public static BoundRectangle COLOR_DARK_3 = new BoundRectangle().setColor(new Color(30, 80, 30).getRGB()); + public static BoundRectangle COLOR_DARK_4 = new BoundRectangle().setColor(new Color(30, 30, 30).getRGB()); + + public static BoundRectangle COLOR_FOREGROUND_BRIGHT = new BoundRectangle() + .setColor(new Color(148, 226, 193).getRGB()); + public static BoundRectangle COLOR_FOREGROUND_DARK = new BoundRectangle() + .setColor(new Color(175, 0, 0, 131).getRGB()); + + public static BoundRectangle COLOR_BACKGROUND_1 = new BoundRectangle() + .setColor(new Color(0, 0, 0, 80).getRGB()); + public static BoundRectangle COLOR_BACKGROUND_2 = new BoundRectangle() + .setColor(new Color(0, 0, 0, 160).getRGB()); + public static BoundRectangle COLOR_BACKGROUND_3 = new BoundRectangle() + .setColor(new Color(246, 120, 120, 160).getRGB()); + + public static void init() { + backgroundsDir = new File(Terminal2.TERMINAL_PATH, "backgrounds"); + + JsonElement element = FileUtility.loadJson(new File(Terminal2.TERMINAL_PATH, CONFIG_PATH)); + if (element == null || !element.isJsonObject()) { + saveConfig(); + return; + } + + JsonObject config = element.getAsJsonObject(); + + for (String color : colors) { + defaultColors.put(color, getColorRect(color).getColor()); + if (config.has(color)) { + setColor(color, config.get(color).getAsInt()); + } + } + + if (config.has("BACKGROUND_FILE")) { + setBackground(config.get("BACKGROUND_FILE").getAsString()); + } + } + + public static boolean saveConfig() { + JsonObject config = new JsonObject(); + + for (String color : colors) { + config.addProperty(color, getColorRect(color).getColor()); + } + + config.addProperty("BACKGROUND_FILE", currentBackground); + + return FileUtility.saveJson(new File(Terminal2.TERMINAL_PATH, CONFIG_PATH), config); + } + + public static IDrawable getBackgroundDrawable() { + // noinspection ReplaceNullCheck + if (currentBackgroundDrawable == null) { + return defaultBackground; + } + return currentBackgroundDrawable; + } + + public static void setBackground(String file) { + currentBackground = file; + if (file.equals("default")) { + currentBackgroundDrawable = null; + } else { + currentBackgroundDrawable = new FileTexture(new File(backgroundsDir, file)); + } + } + + public static BoundRectangle getColorRect(String color) { + try { + return (BoundRectangle) Terminal2Theme.class.getField(color).get(null); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new RuntimeException("Failed to get color rect " + color, e); + } + } + + public static void setColor(String color, int i) { + getColorRect(color).setColor(i); + } + + public static void resetToDefaultColor(String color) { + setColor(color, defaultColors.get(color)); + } + + public static boolean isDefaultColor(String color) { + return getColorRect(color).getColor() == defaultColors.get(color); + } + + public static void gcBoundRects() { + for (String color : colors) { + getColorRect(color).gc(); + } + } +} diff --git a/src/main/java/gregtech/api/util/CapesRegistry.java b/src/main/java/gregtech/api/util/CapesRegistry.java index 7d0acaa0ba6..fcdfa3bd27d 100644 --- a/src/main/java/gregtech/api/util/CapesRegistry.java +++ b/src/main/java/gregtech/api/util/CapesRegistry.java @@ -23,6 +23,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import crafttweaker.annotations.ZenRegister; +import org.jetbrains.annotations.ApiStatus; import stanhebben.zenscript.annotations.ZenClass; import stanhebben.zenscript.annotations.ZenMethod; @@ -37,7 +38,8 @@ public class CapesRegistry { private static final Map> UNLOCKED_CAPES = new HashMap<>(); private static final Map WORN_CAPES = new HashMap<>(); private static final Map CAPE_ADVANCEMENTS = new HashMap<>(); - private static final Set FREE_CAPES = new HashSet<>(); + private static final Set ADVANCEMENT_CAPES = new LinkedHashSet<>(); + private static final Set FREE_CAPES = new LinkedHashSet<>(); public static void registerDevCapes() { unlockCape(UUID.fromString("a24a9108-23d2-43fc-8db7-43f809d017db"), Textures.GREGTECH_CAPE_TEXTURE); // ALongStringOfNumbers @@ -199,6 +201,7 @@ public static void registerCape(ResourceLocation advancement, ResourceLocation c CAPE_ADVANCEMENTS.put(advObject, cape); } } + ADVANCEMENT_CAPES.add(cape); } /** @@ -206,10 +209,19 @@ public static void registerCape(ResourceLocation advancement, ResourceLocation c * * @param cape A ResourceLocation pointing to the cape texture. */ - public static void addFreeCape(ResourceLocation cape) { + public static void registerFreeCape(ResourceLocation cape) { FREE_CAPES.add(cape); } + /** + * Deprecated for naming consistency, use {@link #registerFreeCape(ResourceLocation)} instead + */ + @ApiStatus.ScheduledForRemoval(inVersion = "2.10") + @Deprecated + public static void addFreeCape(ResourceLocation cape) { + registerFreeCape(cape); + } + private static final List> ctRegisterCapes = new ArrayList<>(); private static final List ctFreeCapes = new ArrayList<>(); @@ -250,6 +262,17 @@ public static void unlockCapeOnAdvancement(EntityPlayer player, Advancement adva } } + /** + * @return A list of all registered capes, with advancement capes sorted before free capes. + * This currently does not count capes that are manually unlocked by other mods. + */ + public static List allCapes() { + List result = new ArrayList<>(); + result.addAll(ADVANCEMENT_CAPES); + result.addAll(FREE_CAPES); + return result; + } + public static void clearMaps() { UNLOCKED_CAPES.clear(); WORN_CAPES.clear(); diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index b528f3c1041..bfe4ce48567 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -48,6 +48,7 @@ import gregtech.common.items.behaviors.MultiblockBuilderBehavior; import gregtech.common.items.behaviors.NanoSaberBehavior; import gregtech.common.items.behaviors.ProspectorScannerBehavior; +import gregtech.common.items.behaviors.Terminal2Behavior; import gregtech.common.items.behaviors.TooltipBehavior; import gregtech.common.items.behaviors.TricorderBehavior; import gregtech.common.items.behaviors.TurbineRotorBehavior; @@ -832,6 +833,7 @@ public void registerSubItems() { .setMaxStackSize(1) .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); TERMINAL = addItem(465, "terminal") + .addComponents(new Terminal2Behavior()) .setMaxStackSize(1) .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); PROSPECTOR_LV = addItem(466, "prospector.lv") diff --git a/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java new file mode 100644 index 00000000000..fb0bf74a208 --- /dev/null +++ b/src/main/java/gregtech/common/items/behaviors/Terminal2Behavior.java @@ -0,0 +1,119 @@ +package gregtech.common.items.behaviors; + +import gregtech.api.items.gui.ItemUIFactory; +import gregtech.api.items.metaitem.stats.IItemBehaviour; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuiTheme; +import gregtech.api.mui.GTGuis; +import gregtech.api.mui.factory.MetaItemGuiFactory; +import gregtech.api.terminal2.ITerminalApp; +import gregtech.api.terminal2.Terminal2; +import gregtech.api.terminal2.Terminal2Theme; +import gregtech.common.mui.widget.IDPagedWidget; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.drawable.DynamicDrawable; +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.UISettings; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.layout.Grid; + +public class Terminal2Behavior implements IItemBehaviour, ItemUIFactory { + + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { + ItemStack heldItem = player.getHeldItem(hand); + if (!world.isRemote) { + MetaItemGuiFactory.open(player, hand); + } + return ActionResult.newResult(EnumActionResult.SUCCESS, heldItem); + } + + @Override + public GTGuiTheme getUITheme() { + return GTGuiTheme.TERMINAL; + } + + @Override + public ModularPanel buildUI(HandGuiData guiData, PanelSyncManager guiSyncManager, UISettings settings) { + ModularPanel panel = GTGuis.createPanel(guiData.getUsedItemStack(), 364, 248); + + // to avoid tying the custom disposal logic to IDPagedWidget itself + @SuppressWarnings("rawtypes") + IDPagedWidget appPages = new IDPagedWidget() { + + @Override + public void dispose() { + super.dispose(); + Terminal2Theme.gcBoundRects(); + for (var app : Terminal2.appMap.values()) { + app.dispose(); + } + } + }; + for (var app : Terminal2.appMap.entrySet()) { + appPages.addPage(app.getKey(), app.getValue().buildWidgets(guiData, guiSyncManager, settings, panel)); + } + appPages.size(Terminal2.SCREEN_WIDTH, Terminal2.SCREEN_HEIGHT).pos(4, 4); + + Grid appGrid = new Grid() + .pos(44, 22) + .size(Terminal2.SCREEN_WIDTH - 44 * 2, Terminal2.SCREEN_HEIGHT - 22 * 2) + .minElementMargin(6) + .nextRow(); + + for (var appEntry : Terminal2.appMap.entrySet()) { + ResourceLocation appID = appEntry.getKey(); + ITerminalApp app = appEntry.getValue(); + if (appID == Terminal2.HOME_ID) continue; + + appGrid.child(new ButtonWidget<>() + .overlay(app.getIcon()) + .background(Terminal2Theme.COLOR_BACKGROUND_2.getCircle()) + .hoverBackground(Terminal2Theme.COLOR_BACKGROUND_2.getCircle(), + Terminal2Theme.COLOR_BRIGHT_2.getRing()) + .size(24, 24) + .addTooltipLine(IKey.lang("terminal.app." + appID.getNamespace() + "." + appID.getPath() + ".name")) + .onMousePressed(i -> { + appPages.setPage(appID); + app.onOpen(); + return true; + })); + + if (appGrid.getChildren().size() % 7 == 0) { + appGrid.nextRow(); + } + } + appPages.addPage(Terminal2.HOME_ID, appGrid).setDefaultPage(Terminal2.HOME_ID); + + return panel.background(GTGuiTextures.TERMINAL_FRAME) + .child(new DynamicDrawable(Terminal2Theme::getBackgroundDrawable).asWidget() + .size(Terminal2.SCREEN_WIDTH, Terminal2.SCREEN_HEIGHT) + .pos(4, 4)) + .child(appPages) + .child(new ButtonWidget<>() + .overlay(GTGuiTextures.HOME_BUTTON) + .hoverOverlay(GTGuiTextures.HOME_BUTTON_HOVER) + .background(IDrawable.NONE) + .disableHoverBackground() + .addTooltipLine(IKey.lang("terminal.app.gregtech.home.name")) + .size(16, 16) + .left(346) + .topRelAnchor(0.5F, 0.5F) + .onMousePressed(i -> { + appPages.setPage(Terminal2.HOME_ID); + return true; + })); + } +} diff --git a/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java b/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java new file mode 100644 index 00000000000..e4b144256a6 --- /dev/null +++ b/src/main/java/gregtech/common/mui/drawable/BoundRectangle.java @@ -0,0 +1,74 @@ +package gregtech.common.mui.drawable; + +import com.cleanroommc.modularui.drawable.Circle; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.widget.AbstractScrollWidget; +import com.cleanroommc.modularui.widget.scroll.HorizontalScrollData; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BooleanSupplier; +import java.util.function.IntConsumer; + +public class BoundRectangle extends Rectangle { + + private Circle circle; + private Ring ring; + private final List> colorSetters = new ArrayList<>(); + + @Override + public BoundRectangle setColor(int color) { + getCircle().setColor(color, color); + getRing().setColor(color); + super.setColor(color); + if (colorSetters != null) { + for (int i = 0; i < colorSetters.size(); i++) { + var setterPair = colorSetters.get(i); + if (setterPair.getRight().getAsBoolean()) { + colorSetters.remove(i); + i--; + continue; + } + setterPair.getLeft().accept(color); + } + } + return this; + } + + public Circle getCircle() { + // circle needs to be initialized during the super constructor somehow, and this is the simplest way + return circle == null ? circle = new Circle() : circle; + } + + public Ring getRing() { + return ring == null ? ring = new Ring() : ring; + } + + public BoundRectangle bind(IntConsumer colorSetter, BooleanSupplier removeCondition) { + colorSetters.add(Pair.of(colorSetter, removeCondition)); + colorSetter.accept(this.getColor()); + return this; + } + + public BoundRectangle bindScrollFG(AbstractScrollWidget widget) { + HorizontalScrollData scrollX = widget.getScrollArea().getScrollX(); + VerticalScrollData scrollY = widget.getScrollArea().getScrollY(); + if (scrollX != null) { + scrollX.texture(this); + } + if (scrollY != null) { + scrollY.texture(this); + } + return this; + } + + public BoundRectangle bindScrollBG(AbstractScrollWidget widget) { + return bind(widget.getScrollArea()::setScrollBarBackgroundColor, () -> !widget.isValid()); + } + + public void gc() { + colorSetters.removeIf((e) -> e.getRight().getAsBoolean()); + } +} diff --git a/src/main/java/gregtech/common/mui/drawable/FileTexture.java b/src/main/java/gregtech/common/mui/drawable/FileTexture.java new file mode 100644 index 00000000000..4f3d6221ea9 --- /dev/null +++ b/src/main/java/gregtech/common/mui/drawable/FileTexture.java @@ -0,0 +1,82 @@ +package gregtech.common.mui.drawable; + +import gregtech.api.util.GTLog; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.texture.TextureUtil; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.drawable.GuiDraw; +import com.cleanroommc.modularui.screen.viewport.GuiContext; +import com.cleanroommc.modularui.theme.WidgetTheme; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import javax.imageio.ImageIO; + +public class FileTexture implements IDrawable { + + private static final Map pathLookup = new HashMap<>(); + private int texID; + + public FileTexture(File file) { + String fullPath = file.getAbsolutePath(); + if (pathLookup.containsKey(fullPath)) { + texID = pathLookup.get(fullPath); + return; + } + + try { + BufferedImage image = ImageIO.read(file); + if (image == null) { + throw new IOException("Read null image from " + file.getName()); + } + int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth()); + ByteBuffer buffer = ByteBuffer.allocateDirect(pixels.length * 4); + for (int pixel : pixels) { + buffer.put((byte) ((pixel >> 16) & 0xFF)); + buffer.put((byte) ((pixel >> 8) & 0xFF)); + buffer.put((byte) (pixel & 0xFF)); + buffer.put((byte) ((pixel >> 24) & 0xFF)); + } + buffer.flip(); + + int texID = GL11.glGenTextures(); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE); + + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + + GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, image.getWidth(), image.getHeight(), 0, + GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); + + this.texID = texID; + pathLookup.put(fullPath, texID); + } catch (IOException e) { + GTLog.logger.error("Could not create FileTexture for {}", file.getName(), e); + this.texID = TextureUtil.MISSING_TEXTURE.getGlTextureId(); + pathLookup.put(fullPath, this.texID); + } + } + + @Override + public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) { + GlStateManager.disableAlpha(); + GlStateManager.enableBlend(); + GlStateManager.enableTexture2D(); + GlStateManager.bindTexture(texID); + GuiDraw.drawTexture(x, y, 0, 0, width, height, width, height); + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + } +} diff --git a/src/main/java/gregtech/common/mui/drawable/Ring.java b/src/main/java/gregtech/common/mui/drawable/Ring.java new file mode 100644 index 00000000000..21acb867945 --- /dev/null +++ b/src/main/java/gregtech/common/mui/drawable/Ring.java @@ -0,0 +1,90 @@ +package gregtech.common.mui.drawable; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.screen.viewport.GuiContext; +import com.cleanroommc.modularui.theme.WidgetTheme; +import com.cleanroommc.modularui.utils.Color; +import org.lwjgl.opengl.GL11; + +public class Ring implements IDrawable { + + private int color; + private float ringWidth; + private int segments, start, end; + + public Ring() { + this.color = 0; + this.ringWidth = 0.2f; + this.segments = 40; + this.start = 0; + this.end = this.segments; + } + + public Ring setColor(int color) { + this.color = color; + return this; + } + + public Ring setWidth(float ringWidth) { + if (ringWidth < 0 || ringWidth > 1) { + throw new IllegalArgumentException("ringWidth must be between 0 and 1"); + } + this.ringWidth = ringWidth; + return this; + } + + /** + * This will reset end to segments, call {@link this#setProgress} after this! + */ + public Ring setSegments(int segments) { + this.segments = segments; + this.end = this.segments; + return this; + } + + public Ring setProgress(int start, int end) { + this.start = start; + this.end = end; + return this; + } + + public Ring setProgress(int end) { + this.end = end; + return this; + } + + @Override + public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) { + drawRing(x, y, width, height, ringWidth, color, segments, start, end); + } + + // modified from mui0 Widget#drawTorus + private static void drawRing(float x, float y, float w, float h, float ringWidth, int color, int segments, int from, + int to) { + float cx = x + w / 2f, cy = y + h / 2f; + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, + GlStateManager.DestFactor.ZERO); + GlStateManager.color(Color.getRedF(color), Color.getGreenF(color), Color.getBlueF(color), + Color.getAlphaF(color)); + bufferbuilder.begin(GL11.GL_QUAD_STRIP, DefaultVertexFormats.POSITION); + for (int i = from; i <= to; i++) { + float angle = (i / (float) segments) * 3.14159f * 2.0f; + bufferbuilder.pos(cx + (w / 2) * (1 - ringWidth) * Math.cos(-angle), + cy + (h / 2) * (1 - ringWidth) * Math.sin(-angle), 0).endVertex(); + bufferbuilder.pos(cx + (w / 2) * Math.cos(-angle), cy + (h / 2) * Math.sin(-angle), 0).endVertex(); + } + tessellator.draw(); + GlStateManager.enableTexture2D(); + GlStateManager.color(1, 1, 1, 1); + } +} diff --git a/src/main/java/gregtech/common/mui/widget/DrawableNoHoverWidget.java b/src/main/java/gregtech/common/mui/widget/DrawableNoHoverWidget.java new file mode 100644 index 00000000000..f14f7ffe5ee --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/DrawableNoHoverWidget.java @@ -0,0 +1,15 @@ +package gregtech.common.mui.widget; + +import com.cleanroommc.modularui.api.drawable.IDrawable; + +public class DrawableNoHoverWidget extends IDrawable.DrawableWidget { + + public DrawableNoHoverWidget(IDrawable drawable) { + super(drawable); + } + + @Override + public boolean canHover() { + return false; + } +} diff --git a/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java b/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java new file mode 100644 index 00000000000..a021234e211 --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/GTColorPickerDialog.java @@ -0,0 +1,28 @@ +package gregtech.common.mui.widget; + +import com.cleanroommc.modularui.widget.WidgetTree; +import com.cleanroommc.modularui.widgets.ColorPickerDialog; +import com.cleanroommc.modularui.widgets.SliderWidget; + +import java.util.function.Consumer; + +// TODO remove this class when the weird resizing bugs are fixed +public class GTColorPickerDialog extends ColorPickerDialog { + + public GTColorPickerDialog(String name, Consumer resultConsumer, int startColor, boolean controlAlpha) { + super(name, resultConsumer, startColor, controlAlpha); + } + + @Override + public void onResized() { + super.onResized(); + // forEachChild has flawed logic and doesnt actually work + WidgetTree.foreachChildBFS(getThis(), (w) -> { + if (w instanceof SliderWidget slider) { + // HACK: work around this not getting called by MUI2 in some situations + slider.onResized(); + } + return true; + }); + } +} diff --git a/src/main/java/gregtech/common/mui/widget/IDPagedWidget.java b/src/main/java/gregtech/common/mui/widget/IDPagedWidget.java new file mode 100644 index 00000000000..22f98f78162 --- /dev/null +++ b/src/main/java/gregtech/common/mui/widget/IDPagedWidget.java @@ -0,0 +1,70 @@ +package gregtech.common.mui.widget; + +import net.minecraft.util.ResourceLocation; + +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.widget.Widget; +import com.google.common.collect.ImmutableList; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class IDPagedWidget> extends Widget { + + private final Map pages = new Object2ObjectOpenHashMap<>(); + private IWidget currentPage; + private ResourceLocation currentPageID = null; + private ResourceLocation defaultPageID = null; + + @Override + public void afterInit() { + if (defaultPageID == null) { + throw new IllegalStateException("IDPagedWidget has no default page!"); + } + setPage(defaultPageID); + } + + public void setPage(ResourceLocation page) { + if (!pages.containsKey(page)) { + throw new IndexOutOfBoundsException(); + } + this.currentPageID = page; + if (this.currentPage != null) { + this.currentPage.setEnabled(false); + } + this.currentPage = this.pages.get(this.currentPageID); + this.currentPage.setEnabled(true); + } + + public Collection getPages() { + return this.pages.values(); + } + + public IWidget getCurrentPage() { + return this.currentPage; + } + + public ResourceLocation getCurrentPageID() { + return this.currentPageID; + } + + @Override + public @Unmodifiable @NotNull List getChildren() { + return ImmutableList.copyOf(this.pages.values()); + } + + public W addPage(ResourceLocation id, IWidget widget) { + this.pages.put(id, widget); + widget.setEnabled(false); + return getThis(); + } + + public W setDefaultPage(ResourceLocation id) { + defaultPageID = id; + return getThis(); + } +} diff --git a/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java new file mode 100644 index 00000000000..216183bd530 --- /dev/null +++ b/src/main/java/gregtech/common/terminal2/CapeSelectorApp.java @@ -0,0 +1,196 @@ +package gregtech.common.terminal2; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.screen.RichTooltip; + +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.terminal2.ITerminalApp; +import gregtech.api.terminal2.Terminal2Theme; +import gregtech.api.util.CapesRegistry; + +import gregtech.common.mui.widget.DrawableNoHoverWidget; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.ResourceLocation; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.DynamicDrawable; +import com.cleanroommc.modularui.drawable.UITexture; +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.UISettings; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.value.sync.SyncHandler; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.layout.Grid; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class CapeSelectorApp implements ITerminalApp { + + private static final int SYNC_UNLOCKED_CAPES = 1; + private static final int SELECT_CAPE = 2; + + private CapeSelectorSyncHandler syncHandler; + + @Override + public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, UISettings settings, + ModularPanel panel) { + UUID uuid = guiData.getPlayer().getPersistentID(); + syncHandler = new CapeSelectorSyncHandler(uuid); + guiSyncManager.syncValue("cape_handler", syncHandler); + + var capeGrid = new Grid() + .sizeRel(1f) + .posRel(0.5f, 0.5f) + .minElementMargin(18) + .scrollable(new VerticalScrollData().texture(Terminal2Theme.COLOR_FOREGROUND_BRIGHT)) + .nextRow(); + + for (ResourceLocation cape : CapesRegistry.allCapes()) { + if (capeGrid.getChildren().size() % 4 == 0 && !capeGrid.getChildren().isEmpty()) { + capeGrid.nextRow(); + } + + IWidget capeButton = new ButtonWidget<>() + .size(40, 72) + .posRel(0.5F, 0.5F) + .background(new UITexture(cape, 1f / 64, 1f / 32, 11f / 64, 17f / 32, null, false)) + .overlay(new DynamicDrawable(capeForeground(cape))) + .disableHoverOverlay() + .disableHoverBackground() + .tooltipDynamic(capeTooltip(cape)) + .onMousePressed(b -> { + syncHandler.syncToServer(SELECT_CAPE, buf -> buf.writeString(cape.toString())); + return true; + }); + + capeGrid.child(new ParentWidget<>() + .size(46, 78) + .background(new DynamicDrawable(capeBackground(cape))) + .child(capeButton) + .child(new DrawableNoHoverWidget(new DynamicDrawable(capeOverlay(cape))) + .size(24) + .posRel(0.5F, 0.5F))); + } + + return new ParentWidget<>() + .sizeRel(0.98f) + .posRel(0.5f, 0.5f) + .background(Terminal2Theme.COLOR_BACKGROUND_1) + .child(capeGrid); + } + + @Override + public IDrawable getIcon() { + return GTGuiTextures.CAPES_APP_ICON; + } + + @Override + public void onOpen() { + syncHandler.syncUnlockedCapes(); + } + + @Override + public void dispose() { + syncHandler = null; + } + + private Supplier capeBackground(ResourceLocation cape) { + return () -> { + if (cape.equals(CapesRegistry.getPlayerCape(syncHandler.uuid))) { + return Terminal2Theme.COLOR_BRIGHT_1; + } else if (syncHandler.unlockedCapes.contains(cape)) { + return Terminal2Theme.COLOR_BACKGROUND_2; + } + return Terminal2Theme.COLOR_BRIGHT_3; + }; + } + + private Supplier capeOverlay(ResourceLocation cape) { + return () -> syncHandler.unlockedCapes.contains(cape) ? IDrawable.EMPTY : GTGuiTextures.RECIPE_LOCK_WHITE; + } + + private Supplier capeForeground(ResourceLocation cape) { + return () -> syncHandler.unlockedCapes.contains(cape) ? IDrawable.EMPTY : Terminal2Theme.COLOR_FOREGROUND_DARK; + } + + private Consumer capeTooltip(ResourceLocation cape) { + return (tooltip) -> { + if (cape.equals(CapesRegistry.getPlayerCape(syncHandler.uuid))) { + tooltip.addLine(IKey.lang("terminal.capes.selected")); + } else if (!syncHandler.unlockedCapes.contains(cape)) { + tooltip.addLine(IKey.lang("terminal.capes.locked")); + tooltip.addLine(IKey.lang("terminal.capes.advancement")); + } + }; + } + + private static final class CapeSelectorSyncHandler extends SyncHandler { + + private final UUID uuid; + private List unlockedCapes = Collections.emptyList(); + + public CapeSelectorSyncHandler(UUID uuid) { + this.uuid = uuid; + } + + private void syncUnlockedCapes() { + if (!getSyncManager().isClient()) { + unlockedCapes = CapesRegistry.getUnlockedCapes(uuid); + syncToClient(SYNC_UNLOCKED_CAPES, buf -> { + buf.writeVarInt(unlockedCapes.size()); + for (ResourceLocation cape : unlockedCapes) { + buf.writeString(cape.toString()); + } + }); + } else { + syncToServer(SYNC_UNLOCKED_CAPES); + } + } + + @Override + public void detectAndSendChanges(boolean init) { + super.detectAndSendChanges(init); + if (init) { + // prevents flicker when opening the app on dedicated server + syncUnlockedCapes(); + } + } + + @Override + public void readOnClient(int id, PacketBuffer buf) { + if (id == SYNC_UNLOCKED_CAPES) { + int len = buf.readVarInt(); + unlockedCapes = new ArrayList<>(len); + for (int i = 0; i < len; i++) { + unlockedCapes.add(new ResourceLocation(buf.readString(Short.MAX_VALUE))); + } + } + } + + @Override + public void readOnServer(int id, PacketBuffer buf) { + if (id == SELECT_CAPE) { + ResourceLocation cape = new ResourceLocation(buf.readString(Short.MAX_VALUE)); + if (unlockedCapes.contains(cape)) { + if (cape.equals(CapesRegistry.getPlayerCape(uuid))) { + CapesRegistry.giveCape(uuid, null); + } else { + CapesRegistry.giveCape(uuid, cape); + } + } + } else if (id == SYNC_UNLOCKED_CAPES) { + syncUnlockedCapes(); + } + } + } +} diff --git a/src/main/java/gregtech/common/terminal2/SettingsApp.java b/src/main/java/gregtech/common/terminal2/SettingsApp.java new file mode 100644 index 00000000000..d5711f255eb --- /dev/null +++ b/src/main/java/gregtech/common/terminal2/SettingsApp.java @@ -0,0 +1,152 @@ +package gregtech.common.terminal2; + +import gregtech.api.mui.GTGuis; +import gregtech.api.terminal2.ITerminalApp; +import gregtech.api.terminal2.Terminal2Theme; +import gregtech.common.mui.widget.GTColorPickerDialog; + +import com.cleanroommc.modularui.api.IPanelHandler; +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.GuiTextures; +import com.cleanroommc.modularui.factory.HandGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.screen.SecondaryPanel; +import com.cleanroommc.modularui.screen.UISettings; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widget.ScrollWidget; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.ListWidget; +import com.cleanroommc.modularui.widgets.layout.Flow; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +public class SettingsApp implements ITerminalApp { + + @Override + public IWidget buildWidgets(HandGuiData guiData, PanelSyncManager guiSyncManager, UISettings settings, + ModularPanel panel) { + var backgroundSelectPanel = IPanelHandler.simple(panel, + backgroundSelectWidget(), true); + + int rows = Terminal2Theme.colors.size() + 1; + + var column = Flow.column() + .crossAxisAlignment(Alignment.CrossAxis.START) + .widthRel(0.95F) + .height(rows * 24) + .leftRel(0.4F); + + column.child(Flow.row() + .widthRel(1.0F) + .height(24) + .child(IKey.lang("terminal.settings.background").asWidget()) + .child(new ButtonWidget<>() + .overlay(IKey.dynamic(() -> Terminal2Theme.currentBackground)) + .size(140, 18) + .align(Alignment.CenterRight) + .onMousePressed(i -> { + if (backgroundSelectPanel.isPanelOpen()) { + backgroundSelectPanel.closePanel(); + } else { + backgroundSelectPanel.openPanel(); + } + return true; + }))); + + for (String color : Terminal2Theme.colors) { + IPanelHandler colorPanel = IPanelHandler.simple(panel, + (mainPanel, player) -> new GTColorPickerDialog("color_select_" + color, i -> { + Terminal2Theme.setColor(color, i); + Terminal2Theme.saveConfig(); + }, Terminal2Theme.getColorRect(color).getColor(), true), + true); + + column.child(Flow.row() + .widthRel(1.0F) + .height(24) + .child(IKey.lang("terminal.settings.color", color.substring(6)).asWidget()) + .child(new ButtonWidget<>() + .overlay(GuiTextures.REFRESH) + .left(276) + .topRelAnchor(0.5F, 0.5F) + .addTooltipLine(IKey.lang("terminal.settings.reset_color")) + .setEnabledIf((w) -> !Terminal2Theme.isDefaultColor(color)) + .onMousePressed(i -> { + Terminal2Theme.resetToDefaultColor(color); + Terminal2Theme.saveConfig(); + // force reset color picker state + colorPanel.deleteCachedPanel(); + return true; + })) + .child(new ButtonWidget<>() + .overlay(Terminal2Theme.getColorRect(color)) + .background(GuiTextures.CHECKBOARD) + .disableHoverOverlay() + .disableHoverBackground() + .align(Alignment.CenterRight) + .onMousePressed(i -> { + colorPanel.openPanel(); + return true; + }))); + } + + var scroll = new ScrollWidget<>(new VerticalScrollData()) + .child(column) + .sizeRel(1.0F); + + scroll.getScrollArea().getScrollY() + .texture(Terminal2Theme.COLOR_FOREGROUND_BRIGHT) + .setScrollSize(rows * 24); + + return new ParentWidget<>() + .sizeRel(0.98F) + .posRel(0.5F, 0.5F) + .background(Terminal2Theme.COLOR_BACKGROUND_1) + .child(scroll); + } + + @Override + public IDrawable getIcon() { + return GuiTextures.GEAR; + } + + private SecondaryPanel.IPanelBuilder backgroundSelectWidget() { + return (syncManager, syncHandler) -> { + String[] files = Terminal2Theme.backgroundsDir.list(); + List options; + if (files == null) { + options = new ArrayList<>(); + } else { + options = new ArrayList<>(Arrays.asList(files)); + } + options.sort(Comparator.naturalOrder()); + options.add(0, "default"); + + var list = new ListWidget<>().children(options.size(), (i) -> new ButtonWidget<>() + .overlay(IKey.str(options.get(i))) + .size(140, 18) + .leftRel(0.2F) + .onMousePressed(j -> { + Terminal2Theme.setBackground(options.get(i)); + Terminal2Theme.saveConfig(); + return true; + })) + .scrollDirection(new VerticalScrollData().texture(Terminal2Theme.COLOR_FOREGROUND_BRIGHT)) + .size(150, 90).pos(9, 16); + + return GTGuis.createPopupPanel("terminal_background_select", 168, 112) + .child(IKey.lang("terminal.settings.background_select").asWidget() + .leftRel(0.5F) + .top(6)) + .child(list); + }; + } +} diff --git a/src/main/java/gregtech/core/CoreModule.java b/src/main/java/gregtech/core/CoreModule.java index f4121bb3ecb..df51a0704b4 100644 --- a/src/main/java/gregtech/core/CoreModule.java +++ b/src/main/java/gregtech/core/CoreModule.java @@ -22,6 +22,7 @@ import gregtech.api.recipes.ModHandler; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.properties.impl.TemperatureProperty; +import gregtech.api.terminal2.Terminal2; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Materials; import gregtech.api.unification.material.event.MaterialEvent; @@ -291,6 +292,8 @@ public void init(FMLInitializationEvent event) { DungeonLootLoader.init(); MetaBlocks.registerWalkingSpeedBonus(); + + Terminal2.init(); } @Override diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 2eddc0b2147..64959e03fdd 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -6050,230 +6050,31 @@ gregtech.creative.energy.source=Source gregtech.creative.activity.on=Active gregtech.creative.activity.off=Not active -gregtech.terminal.app_name.items=Item Guides -gregtech.terminal.app_name.machines=Machine Guides -gregtech.terminal.app_name.multiblocks=Multiblock Guides -gregtech.terminal.app_name.tutorials=Tutorials -gregtech.terminal.app_name.settings=System Settings -gregtech.terminal.app_name.guide_editor=Guide Editor -gregtech.terminal.app_name.recipe_chart=Recipe Chart -gregtech.terminal.app_name.ore_prospector=Ore Prospector -gregtech.terminal.app_name.fluid_prospector=Fluid Prospector -gregtech.terminal.app_name.pong=Pong -gregtech.terminal.app_name.minesweeper=Minesweeper -gregtech.terminal.app_name.maze=Theseus's Escape -gregtech.terminal.app_name.console=GT Console -gregtech.terminal.app_name.battery=Battery Manager -gregtech.terminal.app_name.hardware=Hardware Manager -gregtech.terminal.app_name.store=App Store -gregtech.terminal.app_name.multiblock_ar=Multiblock Helper -gregtech.terminal.app_name.world_prospector=World Prospector -gregtech.terminal.app_name.vtank_viewer=Virtual Tank Viewer -gregtech.terminal.app_name.cape_selector=Cape Selector -gregtech.terminal.app_name.teleport=Teleporter - - -terminal.app_name.description=No description. -terminal.app_name.tier=Tier %d -terminal.app_name.maximize.unsupported=This App does not support maximize. -terminal.items.description=A guide book about items. -terminal.machines.description=A guide book about gt machines. -terminal.multiblocks.description=A guide book about multi-blocks. -terminal.tutorials.description=Introduces all kinds of things, CT integration, tips, tutorials and more. -terminal.pong.description=A classic pong game, if you're really that bored of waiting for that tungstensteel. -terminal.minesweeper.description=A classic minesweeper game, if you're in class. -terminal.maze.description=A GTOS exclusive game finding you racing through an endless labyrinth to survive the Minotaur! -terminal.cape_selector.description=An app that allows you to equip GT capes that you've unlocked through advancements. -terminal.teleport.description=Open portals to any coordinate in any dimension. Be careful not to teleport into a wall! - -texture.modify_gui_texture.missing=Missing Texture -texture.url_texture.fail=Load Failed - -terminal.hw.battery=Battery -terminal.hw.device=Device - -terminal.os.shutdown_confirm=Confirm shutdown? (Press ESC again to see ok) -terminal.os.hw_demand=Missing mounting hardware: - -terminal.system_call.null=NULL -terminal.system_call.call_menu=Call Menu -terminal.system_call.full_screen=Full Screen -terminal.system_call.minimize_focus_app=Back to Desktop -terminal.system_call.close_focus_app=Close App -terminal.system_call.shutdown=Shutdown -terminal.system_call.open_app=Open App - -terminal.menu.close=Close App -terminal.menu.minimize=Minimize App -terminal.menu.maximize=Full Screen/Recover - -terminal.component.new_page=New Page -terminal.component.page_name=Page Name -terminal.component.load_file=Load File -terminal.component.load_file.error=An error occurred while loading the file. -terminal.component.save_file=Save File -terminal.component.save_file.error=An error occurred while saving the file. -terminal.component.confirm=Are you sure? -terminal.component.error=ERROR -terminal.component.warning=WARNING +# new terminal +terminal.app.gregtech.home.name=Home +terminal.app.gregtech.settings.name=Theme Settings +terminal.app.gregtech.capes.name=Cape Selector + +terminal.settings.background=Background +terminal.settings.background_select=Select Background +terminal.settings.color=Set color %s +terminal.settings.reset_color=Reset to default color + +terminal.capes.locked=Locked +terminal.capes.advancement=Unlock this cape by progressing through GregTech's advancements +terminal.capes.selected=Equipped + +# old terminal +# currently indirectly used in alarm terminal.component.searching=searching -terminal.component.reload=reload resource - -terminal.dialog.notice=NOTICE -terminal.dialog.error_path=error file path: -terminal.dialog.no_file_selected=No file selected. -terminal.dialog.folder=Open Folder - -terminal.guide_editor.description=An interactive guide page editor that allows you to create guide pages easily. -terminal.guide_editor.up=Up -terminal.guide_editor.down=Down -terminal.guide_editor.remove=Remove -terminal.guide_editor.add_stream=Add to stream -terminal.guide_editor.add_fixed=Add to fixed -terminal.guide_editor.update=Update -terminal.guide_editor.add_slot=Add Slot -terminal.guide_editor.default=Default Value -terminal.guide_editor.page_config=Page Config -terminal.guide_editor.widgets_box=Widgets Box -terminal.guide_editor.widget_config=Widget Config -terminal.guide_editor.error_type=Item types do not match and will still be saved, but will not be seen in app. - -terminal.settings.description=The system settings for GTOS. -terminal.settings.theme=Theme -terminal.settings.theme.color=Theme Color Settings -terminal.settings.theme.wallpaper=Wallpaper Settings -terminal.settings.theme.wallpaper.resource=resource -terminal.settings.theme.wallpaper.url=url -terminal.settings.theme.wallpaper.color=color -terminal.settings.theme.wallpaper.file=file -terminal.settings.theme.select=Select -terminal.settings.theme.image=Image File -terminal.settings.home=Home Button -terminal.settings.home.double=Double -terminal.settings.home.action=Click Action -terminal.settings.home.args=Args -terminal.settings.home.click=click -terminal.settings.home.double_click=double Click -terminal.settings.os=Os settings -terminal.settings.os.double_check=Double Check -terminal.settings.os.double_check.desc=Should Double Check when shutdown. - - -terminal.recipe_chart.description=A tool for analyzing recipe chains, with which you can easily build a recipe graph and even calculate the ingredients needed like JEC. -terminal.recipe_chart.limit=Page limit. -terminal.recipe_chart.delete=Delete Page -terminal.recipe_chart.add_slot=Add Root Slot -terminal.recipe_chart.demand=Demand -terminal.recipe_chart.calculator=Calculator -terminal.recipe_chart.add=Set the item from inventory -terminal.recipe_chart.drag=Drag ingredients here. -terminal.recipe_chart.visible=Visible -terminal.recipe_chart.jei=JEI Focus -terminal.recipe_chart.tier=Tier: -terminal.recipe_chart.ratio=Weight -terminal.recipe_chart.tier.0=cache of 5 pages -terminal.recipe_chart.tier.1=cache of 6 pages -terminal.recipe_chart.tier.2=cache of 7 pages -terminal.recipe_chart.tier.3=cache of 8 pages - -terminal.prospector.vis_mode=Switch color mode + +# currently used in prospector terminal.prospector.list=All Resources terminal.prospector.ore=Ore Data terminal.prospector.fluid=Fluid Deposit Data terminal.prospector.fluid.info=%s %s - %s%% terminal.prospector.waypoint.add=[Double §7Left click§r] to add waypoint -terminal.ore_prospector.description=Hate the scanner toy? Don't want to run around looking for ores? Come and look at it. -terminal.ore_prospector.tier.0=radius size 1 -terminal.ore_prospector.tier.1=radius size 2 -terminal.ore_prospector.tier.2=radius size 3 -terminal.ore_prospector.tier.3=radius size 4 -terminal.ore_prospector.tier.4=radius size 5 -terminal.ore_prospector.tier.5=radius size 6 -terminal.ore_prospector.tier.6=radius size 7 - -terminal.fluid_prospector.description=You know, there's gold in bedrocks. -terminal.fluid_prospector.tier.0=radius size 1 -terminal.fluid_prospector.tier.1=radius size 2 -terminal.fluid_prospector.tier.2=radius size 3 -terminal.fluid_prospector.tier.3=radius size 4 -terminal.fluid_prospector.tier.4=radius size 5 -terminal.fluid_prospector.tier.5=radius size 6 -terminal.fluid_prospector.tier.6=radius size 7 - -terminal.console.description=A tool to help you free your inventory, it's time to say goodbye to wrench, screwdriver, hammer, and crowbar. -terminal.console.notice=Please shift-right-click a machine when opening the terminal. -terminal.console.front=Set as front -terminal.console.items=set as items output -terminal.console.fluids=set as fluids output -terminal.console.auto_output=allow auto output -terminal.console.input=allow input from output -terminal.console.cover_rs=signal: %s -terminal.console.cover_gui=Gui -terminal.console.gui=Open machine gui -terminal.console.maintenance=Fix all problems -terminal.console.venting=set as venting -terminal.console.controllable=set working enable - -terminal.hardware.description=Hardware Manager, masterpieces of elegance and precision. How can a tablet be without hardware? -terminal.hardware.select=Mounting hardware -terminal.hardware.remove=Remove hardware -terminal.hardware.remove.full=There are no empty slots in inventory -terminal.hardware.tip.remove=§4right-click remove the hardware - -terminal.battery.description=Battery manager, visually analyze your app's energy consumption. -terminal.battery.hover=%s: Usage %d eu/s -terminal.battery.low_energy=Low power! Plz recharge the terminal. - -terminal.store.description=App store, check out what you got? Install and upgrade the app. -terminal.store.match=Detected required item in inventory, install/upgrade App? -terminal.store.miss=Requires %s (%d). -terminal.store.close=Close - -terminal.ar.open=Open AR - -terminal.multiblock_ar.description=Remember the §cFreedom Wrench§r? Unfortunately, it it's gone. It doesn't matter, we have a new technology now. This app can also help you build your multi-block machine. -terminal.multiblock_ar.tier.0=AR Camera -terminal.multiblock_ar.tier.1=3D Builder -terminal.multiblock_ar.unlock=Unlock this mode after the upgrade -terminal.multiblock_ar.builder.hover=3D Builder -terminal.multiblock_ar.builder.auto=Automatic Build -terminal.multiblock_ar.builder.place=Place block -terminal.multiblock_ar.builder.debug=Debug - -terminal.world_prospector.description="I wish I had X-ray vision."\n"Sir, I'm sorry, but we don't sell superpowers. You should trust the science." -terminal.world_prospector.tier.0=Radius 15m (1 slot) -terminal.world_prospector.tier.1=Radius 30m (2 slot) -terminal.world_prospector.tier.2=Radius 60m (4 slot) -terminal.world_prospector.radius=Radius %sm -terminal.world_prospector.reference=Select a reference -terminal.world_prospector.color=Select box color - -terminal.vtank_viewer.description=Never lose any fluids to changing ender link frequencies again! Here's a scrollable list of every virtual tank that you have access to in your world. -terminal.vtank_viewer.title=Virtual Tank Viewer -terminal.vtank_viewer.refresh=Refresh tank index - -terminal.teleporter.dimension=Dimension: -terminal.teleporter.spawn_portal=Engage - -terminal.maze.title=Theseus's Escape -terminal.maze.play=Play -terminal.maze.continue=Continue -terminal.maze.pause=Game Paused -terminal.maze.death.1=Oh no! You were eaten by the Minotaur! -terminal.maze.death.2=You got through %s mazes before losing. -terminal.maze.death.3=Try again? -terminal.maze.retry=Retry - -terminal.minesweeper.time=%s seconds elapsed -terminal.minesweeper.lose=You lost. Game will restart in %s seconds. -terminal.minesweeper.win.1=You won in %s seconds! -terminal.minesweeper.win.2=Game will restart in %s - -terminal.cape_selector.empty=It looks like you haven't unlocked any capes yet! -terminal.cape_selector.select=Click on an unlocked cape to select it! -terminal.cape_selector.tip=You can get these from high-level advancements. - metaitem.cover.digital.title.mode=Mode: metaitem.cover.digital.title.spin=Spin: metaitem.cover.digital.wireless.tooltip.1=§fWirelessly§7 connects machines to the §fCentral Monitor§7 as §fCover§7. diff --git a/src/main/resources/assets/gregtech/terminal/image/wallpaper_Kumquat.png b/src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_Kumquat.png similarity index 100% rename from src/main/resources/assets/gregtech/terminal/image/wallpaper_Kumquat.png rename to src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_Kumquat.png diff --git a/src/main/resources/assets/gregtech/terminal/image/wallpaper_Zalgo.png b/src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_Zalgo.png similarity index 100% rename from src/main/resources/assets/gregtech/terminal/image/wallpaper_Zalgo.png rename to src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_Zalgo.png diff --git a/src/main/resources/assets/gregtech/terminal/image/wallpaper_celeryman.png b/src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_celeryman.png similarity index 100% rename from src/main/resources/assets/gregtech/terminal/image/wallpaper_celeryman.png rename to src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_celeryman.png diff --git a/src/main/resources/assets/gregtech/terminal/image/wallpaper_moth.png b/src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_moth.png similarity index 100% rename from src/main/resources/assets/gregtech/terminal/image/wallpaper_moth.png rename to src/main/resources/assets/gregtech/terminal/backgrounds/wallpaper_moth.png diff --git a/src/main/resources/assets/gregtech/terminal/config/theme.json b/src/main/resources/assets/gregtech/terminal/config/theme.json deleted file mode 100644 index ac33fcf5bdf..00000000000 --- a/src/main/resources/assets/gregtech/terminal/config/theme.json +++ /dev/null @@ -1 +0,0 @@ -{"COLOR_1":-7277708,"COLOR_2":-798604,"COLOR_3":-1613985,"COLOR_4":-16747521,"COLOR_5":-9364519,"COLOR_6":-14803426,"COLOR_7":-1644826,"COLOR_F_1":-7019839,"COLOR_F_2":-2085683200,"COLOR_B_1":1342177280,"COLOR_B_2":-1610612736,"COLOR_B_3":-1594460040,"WALL_PAPER":{"type":"resource","resource":"gregtech:textures/gui/terminal/terminal_background.png"}} \ No newline at end of file diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/capes/icon.png b/src/main/resources/assets/gregtech/textures/gui/terminal/capes/icon.png new file mode 100644 index 00000000000..9858d9325ed Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/terminal/capes/icon.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/home_button.png b/src/main/resources/assets/gregtech/textures/gui/terminal/home_button.png new file mode 100644 index 00000000000..f78a813adda Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/terminal/home_button.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/home_button_hover.png b/src/main/resources/assets/gregtech/textures/gui/terminal/home_button_hover.png new file mode 100644 index 00000000000..41cc5f33834 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/terminal/home_button_hover.png differ diff --git a/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_frame.png b/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_frame.png new file mode 100644 index 00000000000..fcd89e52fd8 Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/terminal/terminal_frame.png differ