Initial commit

This commit is contained in:
2024-09-26 00:04:47 +02:00
commit 84e394e189
38 changed files with 2751 additions and 0 deletions

118
.gitignore vendored Normal file
View File

@@ -0,0 +1,118 @@
# User-specific stuff
.idea/
*.iml
*.ipr
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
.gradle
build/
# Ignore Gradle GUI config
gradle-app.setting
# Cache of project
.gradletasknamecache
**/build/
# Common working directory
run/
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

193
build.gradle Normal file
View File

@@ -0,0 +1,193 @@
plugins {
id 'eclipse'
id 'idea'
id 'net.minecraftforge.gradle' version '[6.0.16,6.2)'
id 'maven-publish'
}
group = "com.${author}.${modid}"
version = "${minecraft_version}-${mod_version}"
archivesBaseName = modid
java {
toolchain.languageVersion = JavaLanguageVersion.of(17)
}
minecraft {
// The mappings can be changed at any time and must be in the following format.
// Channel: Version:
// official MCVersion Official field/method names from Mojang mapping files
// parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official
//
// You must be aware of the Mojang license when using the 'official' or 'parchment' mappings.
// See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
//
// Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge
// Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started
//
// Use non-default mappings at your own risk. They may not always work.
// Simply re-run your setup task after changing the mappings to update your workspace.
mappings channel: mapping_channel, version: mapping_version
// When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game.
// In most cases, it is not necessary to enable.
// enableEclipsePrepareRuns = true
// enableIdeaPrepareRuns = true
// This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game.
// It is REQUIRED to be set to true for this template to function.
// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html
copyIdeResources = true
// When true, this property will add the folder name of all declared run configurations to generated IDE run configurations.
// The folder name can be set on a run configuration using the "folderName" property.
// By default, the folder name of a run configuration is the name of the Gradle project containing it.
// generateRunFolders = true
// This property enables access transformers for use in development.
// They will be applied to the Minecraft artifact.
// The access transformer file can be anywhere in the project.
// However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge.
// This default location is a best practice to automatically put the file in the right place in the final jar.
// See https://docs.minecraftforge.net/en/latest/advanced/accesstransformers/ for more information.
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
runs {
// applies to all the run configs below
configureEach {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment
// The markers can be added/remove as needed separated by commas.
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
mods {
"${modid}" {
source sourceSets.main
}
}
}
client {
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', modid
}
server {
property 'forge.enabledGameTestNamespaces', modid
args '--nogui'
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
property 'forge.enabledGameTestNamespaces', modid
}
data {
// example of overriding the workingDirectory set in configureEach above
workingDirectory project.file('run-data')
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
args '--mod', modid, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
}
}
}
// Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' }
repositories {
maven {
// location of the maven for Registrate and Flywheel
name = 'tterrag maven'
url = 'https://maven.tterrag.com'
}
maven {
// location of the maven that hosts JEI files since January 2023
// location of the maven for Vazkii's mods
name = "Jared's maven"
url = "https://maven.blamejared.com/"
}
maven {
// location of the maven for Curios API
url = "https://maven.theillusivec4.top/"
}
maven {
url = 'https://www.cursemaven.com'
content {
includeGroup "curse.maven"
}
}
}
dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
compileOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}-common-api:${jei_version}")
compileOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}-forge-api:${jei_version}")
runtimeOnly fg.deobf("mezz.jei:jei-${jei_minecraft_version}-forge:${jei_version}")
implementation fg.deobf("curse.maven:jade-324717:${jade_id}")
}
// This block of code expands all declared replace properties in the specified resource targets.
// A missing property will result in an error. Properties are expanded using ${} Groovy notation.
// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments.
// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html
tasks.named('processResources', ProcessResources).configure {
var replaceProperties = [minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range,
forge_version : forge_version, forge_version_range: forge_version_range,
loader_version_range: loader_version_range,
modid : modid, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version,
author : author, mod_description: mod_description,]
inputs.properties replaceProperties
filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) {
expand replaceProperties + [project: project]
}
}
// Example for how to get properties into the manifest for reading at runtime.
tasks.named('jar', Jar).configure {
manifest {
attributes(["Specification-Title" : modid,
"Specification-Vendor" : author,
"Specification-Version" : "1", // We are version 1 of ourselves
"Implementation-Title" : project.name,
"Implementation-Version" : project.jar.archiveVersion,
"Implementation-Vendor" : author,
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")])
}
// This is the preferred method to reobfuscate your jar file
finalizedBy 'reobfJar'
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}
publishing {
// other settings of publication
publications {
mavenJava(MavenPublication) {
artifact jar
}
}
}

26
gradle.properties Normal file
View File

@@ -0,0 +1,26 @@
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
minecraft_version=1.20.1
minecraft_version_range=[1.20.1,1.21)
forge_version=47.3.7
forge_version_range=[47,)
loader_version_range=[47,)
mapping_channel=official
mapping_version=1.20.1
modid=mechanical_lemon_ui
mod_name=Mechanical Lemon UI
mod_license=MIT
mod_version=0.0.2
mod_group_id=com.oierbravo
author=oierbravo
mod_description=Library
jei_minecraft_version = 1.20.1
jei_version = 15.2.0.22
curios_minecraft_version = 1.20.1
curios_version = 5.2.0-beta.3
jade_id = 4654448

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

249
gradlew vendored Executable file
View File

@@ -0,0 +1,249 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

92
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

15
settings.gradle Normal file
View File

@@ -0,0 +1,15 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven {
name = 'MinecraftForge'
url = 'https://maven.minecraftforge.net/'
}
}
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0'
}
rootProject.name = 'MechanicalLemonUI'

View File

@@ -0,0 +1,31 @@
package com.oierbravo.mechanical_lemon_ui;
import com.mojang.logging.LogUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import org.slf4j.Logger;
// The value here should match an entry in the META-INF/mods.toml file
@Mod(MechanicalLemonUI.MODID)
public class MechanicalLemonUI {
public static final String MODID = "mechanical_lemon_ui";
private static final Logger LOGGER = LogUtils.getLogger();
public MechanicalLemonUI() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
MinecraftForge.EVENT_BUS.register(this);
}
public static ResourceLocation asResource(String path) {
return new ResourceLocation(MODID, path);
}
}

View File

@@ -0,0 +1,182 @@
package com.oierbravo.mechanical_lemon_ui.foundation.gui;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.blaze3d.vertex.PoseStack;
import com.oierbravo.mechanical_lemon_ui.foundation.gui.widget.AbstractSimiWidget;
import com.oierbravo.mechanical_lemon_ui.foundation.utility.Components;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.Renderable;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import java.util.Collection;
import java.util.List;
@OnlyIn(Dist.CLIENT)
public abstract class AbstractSimiScreen extends Screen {
protected int windowWidth, windowHeight;
protected int windowXOffset, windowYOffset;
protected int guiLeft, guiTop;
protected AbstractSimiScreen(Component title) {
super(title);
}
protected AbstractSimiScreen() {
this(Components.immutableEmpty());
}
/**
* This method must be called before {@code super.init()}!
*/
protected void setWindowSize(int width, int height) {
windowWidth = width;
windowHeight = height;
}
/**
* This method must be called before {@code super.init()}!
*/
protected void setWindowOffset(int xOffset, int yOffset) {
windowXOffset = xOffset;
windowYOffset = yOffset;
}
@Override
protected void init() {
guiLeft = (width - windowWidth) / 2;
guiTop = (height - windowHeight) / 2;
guiLeft += windowXOffset;
guiTop += windowYOffset;
}
@Override
public void tick() {
for (GuiEventListener listener : children()) {
if (listener instanceof TickableGuiEventListener tickable) {
tickable.tick();
}
}
}
@Override
public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) {
if (getFocused() != null && !getFocused().isMouseOver(pMouseX, pMouseY))
setFocused(null);
return super.mouseClicked(pMouseX, pMouseY, pButton);
}
@Override
public boolean isPauseScreen() {
return false;
}
@SuppressWarnings("unchecked")
protected <W extends GuiEventListener & Renderable & NarratableEntry> void addRenderableWidgets(W... widgets) {
for (W widget : widgets) {
addRenderableWidget(widget);
}
}
protected <W extends GuiEventListener & Renderable & NarratableEntry> void addRenderableWidgets(Collection<W> widgets) {
for (W widget : widgets) {
addRenderableWidget(widget);
}
}
protected void removeWidgets(GuiEventListener... widgets) {
for (GuiEventListener widget : widgets) {
removeWidget(widget);
}
}
protected void removeWidgets(Collection<? extends GuiEventListener> widgets) {
for (GuiEventListener widget : widgets) {
removeWidget(widget);
}
}
@Override
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
partialTicks = minecraft.getFrameTime();
PoseStack ms = graphics.pose();
ms.pushPose();
prepareFrame();
renderWindowBackground(graphics, mouseX, mouseY, partialTicks);
renderWindow(graphics, mouseX, mouseY, partialTicks);
super.render(graphics, mouseX, mouseY, partialTicks);
renderWindowForeground(graphics, mouseX, mouseY, partialTicks);
endFrame();
ms.popPose();
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
boolean keyPressed = super.keyPressed(keyCode, scanCode, modifiers);
if (keyPressed || getFocused() instanceof EditBox)
return keyPressed;
InputConstants.Key mouseKey = InputConstants.getKey(keyCode, scanCode);
if (this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey)) {
this.onClose();
return true;
}
return false;
}
protected void prepareFrame() {}
protected void renderWindowBackground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
renderBackground(graphics);
}
protected abstract void renderWindow(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks);
protected void renderWindowForeground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
for (Renderable widget : renderables) {
if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isMouseOver(mouseX, mouseY)
&& simiWidget.visible) {
List<Component> tooltip = simiWidget.getToolTip();
if (tooltip.isEmpty())
continue;
int ttx = simiWidget.lockedTooltipX == -1 ? mouseX : simiWidget.lockedTooltipX + simiWidget.getX();
int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.getY();
graphics.renderComponentTooltip(font, tooltip, ttx, tty);
}
}
}
protected void endFrame() {}
@Deprecated
protected void debugWindowArea(GuiGraphics graphics) {
graphics.fill(guiLeft + windowWidth, guiTop + windowHeight, guiLeft, guiTop, 0xD3D3D3D3);
}
@Override
public GuiEventListener getFocused() {
GuiEventListener focused = super.getFocused();
if (focused instanceof AbstractWidget && !((AbstractWidget) focused).isFocused())
focused = null;
setFocused(focused);
return focused;
}
}

View File

@@ -0,0 +1,11 @@
package com.oierbravo.mechanical_lemon_ui.foundation.gui;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import net.minecraft.client.gui.components.events.GuiEventListener;
public interface TickableGuiEventListener extends GuiEventListener {
void tick();
}

View File

@@ -0,0 +1,101 @@
package com.oierbravo.mechanical_lemon_ui.foundation.gui;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.Window;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.oierbravo.mechanical_lemon_ui.foundation.utility.Color;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import org.joml.Matrix4f;
public class UIRenderHelper {
public static CustomRenderTarget framebuffer;
public UIRenderHelper() {
}
public static void init() {
RenderSystem.recordRenderCall(() -> {
Window mainWindow = Minecraft.getInstance().getWindow();
framebuffer = UIRenderHelper.CustomRenderTarget.create(mainWindow);
});
}
public static void updateWindowSize(Window mainWindow) {
if (framebuffer != null) {
framebuffer.resize(mainWindow.getWidth(), mainWindow.getHeight(), Minecraft.ON_OSX);
}
}
public static void drawColoredTexture(GuiGraphics graphics, Color c, int x, int y, int tex_left, int tex_top, int width, int height) {
drawColoredTexture(graphics, c, x, y, 0, (float) tex_left, (float) tex_top, width, height, 256, 256);
}
public static void drawColoredTexture(GuiGraphics graphics, Color c, int x, int y, int z, float tex_left, float tex_top, int width, int height, int sheet_width, int sheet_height) {
drawColoredTexture(graphics, c, x, x + width, y, y + height, z, width, height, tex_left, tex_top, sheet_width, sheet_height);
}
private static void drawColoredTexture(GuiGraphics graphics, Color c, int left, int right, int top, int bot, int z, int tex_width, int tex_height, float tex_left, float tex_top, int sheet_width, int sheet_height) {
drawTexturedQuad(graphics.pose().last().pose(), c, left, right, top, bot, z, (tex_left + 0.0F) / (float)sheet_width, (tex_left + (float)tex_width) / (float)sheet_width, (tex_top + 0.0F) / (float)sheet_height, (tex_top + (float)tex_height) / (float)sheet_height);
}
private static void drawTexturedQuad(Matrix4f m, Color c, int left, int right, int top, int bot, int z, float u1, float u2, float v1, float v2) {
Tesselator tesselator = Tesselator.getInstance();
BufferBuilder bufferbuilder = tesselator.getBuilder();
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.setShader(GameRenderer::getPositionColorTexShader);
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX);
bufferbuilder.vertex(m, (float)left, (float)bot, (float)z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u1, v2).endVertex();
bufferbuilder.vertex(m, (float)right, (float)bot, (float)z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u2, v2).endVertex();
bufferbuilder.vertex(m, (float)right, (float)top, (float)z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u2, v1).endVertex();
bufferbuilder.vertex(m, (float)left, (float)top, (float)z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u1, v1).endVertex();
tesselator.end();
RenderSystem.disableBlend();
}
public static class CustomRenderTarget extends RenderTarget {
public CustomRenderTarget(boolean useDepth) {
super(useDepth);
}
public static CustomRenderTarget create(Window mainWindow) {
CustomRenderTarget framebuffer = new CustomRenderTarget(true);
framebuffer.resize(mainWindow.getWidth(), mainWindow.getHeight(), Minecraft.ON_OSX);
framebuffer.setClearColor(0.0F, 0.0F, 0.0F, 0.0F);
framebuffer.enableStencil();
return framebuffer;
}
public void renderWithAlpha(float alpha) {
Window window = Minecraft.getInstance().getWindow();
float vx = (float)window.getGuiScaledWidth();
float vy = (float)window.getGuiScaledHeight();
float tx = (float)this.viewWidth / (float)this.width;
float ty = (float)this.viewHeight / (float)this.height;
RenderSystem.enableDepthTest();
RenderSystem.setShader(() -> {
return Minecraft.getInstance().gameRenderer.blitShader;
});
RenderSystem.getShader().setSampler("DiffuseSampler", this.colorTextureId);
this.bindRead();
Tesselator tessellator = Tesselator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuilder();
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX);
bufferbuilder.vertex(0.0, (double)vy, 0.0).color(1.0F, 1.0F, 1.0F, alpha).uv(0.0F, 0.0F).endVertex();
bufferbuilder.vertex((double)vx, (double)vy, 0.0).color(1.0F, 1.0F, 1.0F, alpha).uv(tx, 0.0F).endVertex();
bufferbuilder.vertex((double)vx, 0.0, 0.0).color(1.0F, 1.0F, 1.0F, alpha).uv(tx, ty).endVertex();
bufferbuilder.vertex(0.0, 0.0, 0.0).color(1.0F, 1.0F, 1.0F, alpha).uv(0.0F, ty).endVertex();
tessellator.end();
this.unbindRead();
}
}
}

View File

@@ -0,0 +1,188 @@
package com.oierbravo.mechanical_lemon_ui.foundation.gui.menu;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import com.mojang.blaze3d.platform.InputConstants;
import com.oierbravo.mechanical_lemon_ui.foundation.gui.TickableGuiEventListener;
import com.oierbravo.mechanical_lemon_ui.foundation.gui.widget.AbstractSimiWidget;
import com.oierbravo.mechanical_lemon_ui.register.LibGuiTextures;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.Renderable;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.gui.screens.inventory.ContainerScreen;
import net.minecraft.client.renderer.Rect2i;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public abstract class AbstractSimiContainerScreen<T extends AbstractContainerMenu> extends AbstractContainerScreen<T> {
protected int titleXOffset = 2;
protected int titleYOffset = 6;
protected int windowXOffset, windowYOffset;
public AbstractSimiContainerScreen(T container, Inventory inv, Component title) {
super(container, inv, title);
}
/**
* This method must be called before {@code super.init()}!
*/
protected void setWindowSize(int width, int height) {
imageWidth = width;
imageHeight = height;
}
/**
* This method must be called before {@code super.init()}!
*/
protected void setWindowOffset(int xOffset, int yOffset) {
windowXOffset = xOffset;
windowYOffset = yOffset;
}
@Override
protected void init() {
super.init();
leftPos += windowXOffset;
topPos += windowYOffset;
}
@Override
protected void containerTick() {
for (GuiEventListener listener : children()) {
if (listener instanceof TickableGuiEventListener tickable) {
tickable.tick();
}
}
}
@SuppressWarnings("unchecked")
protected <W extends GuiEventListener & Renderable & NarratableEntry> void addRenderableWidgets(W... widgets) {
for (W widget : widgets) {
addRenderableWidget(widget);
}
}
protected <W extends GuiEventListener & Renderable & NarratableEntry> void addRenderableWidgets(Collection<W> widgets) {
for (W widget : widgets) {
addRenderableWidget(widget);
}
}
protected void removeWidgets(GuiEventListener... widgets) {
for (GuiEventListener widget : widgets) {
removeWidget(widget);
}
}
protected void removeWidgets(Collection<? extends GuiEventListener> widgets) {
for (GuiEventListener widget : widgets) {
removeWidget(widget);
}
}
@Override
public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
partialTicks = minecraft.getFrameTime();
renderBackground(graphics);
super.render(graphics, mouseX, mouseY, partialTicks);
renderForeground(graphics, mouseX, mouseY, partialTicks);
}
@Override
protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {
// no-op to prevent screen- and inventory-title from being rendered at incorrect
// location
// could also set this.titleX/Y and this.playerInventoryTitleX/Y to the proper
// values instead
}
protected void renderForeground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
renderTooltip(graphics, mouseX, mouseY);
for (Renderable widget : renderables) {
if (widget instanceof AbstractSimiWidget simiWidget && simiWidget.isMouseOver(mouseX, mouseY)) {
List<Component> tooltip = simiWidget.getToolTip();
if (tooltip.isEmpty())
continue;
int ttx = simiWidget.lockedTooltipX == -1 ? mouseX : simiWidget.lockedTooltipX + simiWidget.getX();
int tty = simiWidget.lockedTooltipY == -1 ? mouseY : simiWidget.lockedTooltipY + simiWidget.getY();
graphics.renderComponentTooltip(font, tooltip, ttx, tty);
}
}
}
public int getLeftOfCentered(int textureWidth) {
return leftPos - windowXOffset + (imageWidth - textureWidth) / 2;
}
public void renderPlayerInventory(GuiGraphics graphics, int x, int y) {
LibGuiTextures.PLAYER_INVENTORY.render(graphics, x, y);
graphics.drawString(font, playerInventoryTitle, x + titleXOffset, y + titleYOffset, 0x404040, false);
}
@Override
public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) {
InputConstants.Key mouseKey = InputConstants.getKey(pKeyCode, pScanCode);
if (getFocused() instanceof EditBox && this.minecraft.options.keyInventory.isActiveAndMatches(mouseKey))
return false;
return super.keyPressed(pKeyCode, pScanCode, pModifiers);
}
@Override
public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) {
if (getFocused() != null && !getFocused().isMouseOver(pMouseX, pMouseY))
setFocused(null);
return super.mouseClicked(pMouseX, pMouseY, pButton);
}
@Override
public GuiEventListener getFocused() {
GuiEventListener focused = super.getFocused();
if (focused instanceof AbstractWidget && !((AbstractWidget) focused).isFocused())
focused = null;
setFocused(focused);
return focused;
}
/**
* Used for moving JEI out of the way of extra things like block renders.
*
* @return the space that the GUI takes up outside the normal rectangle defined
* by {@link ContainerScreen}.
*/
public List<Rect2i> getExtraAreas() {
return Collections.emptyList();
}
@Deprecated
protected void debugWindowArea(GuiGraphics graphics) {
graphics.fill(leftPos + imageWidth, topPos + imageHeight, leftPos, topPos, 0xD3D3D3D3);
}
@Deprecated
protected void debugExtraAreas(GuiGraphics graphics) {
for (Rect2i area : getExtraAreas()) {
graphics.fill(area.getX() + area.getWidth(), area.getY() + area.getHeight(), area.getX(), area.getY(),
0xD3D3D3D3);
}
}
}

View File

@@ -0,0 +1,74 @@
package com.oierbravo.mechanical_lemon_ui.foundation.gui.menu;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import com.oierbravo.mechanical_lemon_ui.foundation.utility.IInteractionChecker;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.Slot;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class MenuBase<T> extends AbstractContainerMenu {
public Player player;
public Inventory playerInventory;
public T contentHolder;
protected MenuBase(MenuType<?> type, int id, Inventory inv, FriendlyByteBuf extraData) {
super(type, id);
init(inv, createOnClient(extraData));
}
protected MenuBase(MenuType<?> type, int id, Inventory inv, T contentHolder) {
super(type, id);
init(inv, contentHolder);
}
protected void init(Inventory inv, T contentHolderIn) {
player = inv.player;
playerInventory = inv;
contentHolder = contentHolderIn;
initAndReadInventory(contentHolder);
addSlots();
broadcastChanges();
}
@OnlyIn(Dist.CLIENT)
protected abstract T createOnClient(FriendlyByteBuf extraData);
protected abstract void initAndReadInventory(T contentHolder);
protected abstract void addSlots();
protected abstract void saveData(T contentHolder);
protected void addPlayerSlots(int x, int y) {
for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot)
this.addSlot(new Slot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58));
for (int row = 0; row < 3; ++row)
for (int col = 0; col < 9; ++col)
this.addSlot(new Slot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18));
}
@Override
public void removed(Player playerIn) {
super.removed(playerIn);
saveData(contentHolder);
}
@Override
public boolean stillValid(Player player) {
if (contentHolder == null)
return false;
if (contentHolder instanceof IInteractionChecker)
return ((IInteractionChecker) contentHolder).canPlayerUse(player);
return true;
}
}

View File

@@ -0,0 +1,106 @@
package com.oierbravo.mechanical_lemon_ui.foundation.gui.widget;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import com.oierbravo.mechanical_lemon_ui.foundation.gui.TickableGuiEventListener;
import com.oierbravo.mechanical_lemon_ui.foundation.utility.Components;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.narration.NarrationElementOutput;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipPositioner;
import net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner;
import net.minecraft.network.chat.Component;
import javax.annotation.Nonnull;
import java.util.LinkedList;
import java.util.List;
import java.util.function.BiConsumer;
public abstract class AbstractSimiWidget extends AbstractWidget implements TickableGuiEventListener {
public static final int HEADER_RGB = 0x5391E1;
public static final int HINT_RGB = 0x96B7E0;
protected float z;
protected boolean wasHovered = false;
protected List<Component> toolTip = new LinkedList<>();
protected BiConsumer<Integer, Integer> onClick = (_$, _$$) -> {};
public int lockedTooltipX = -1;
public int lockedTooltipY = -1;
protected AbstractSimiWidget(int x, int y) {
this(x, y, 16, 16);
}
protected AbstractSimiWidget(int x, int y, int width, int height) {
this(x, y, width, height, Components.immutableEmpty());
}
protected AbstractSimiWidget(int x, int y, int width, int height, Component message) {
super(x, y, width, height, message);
}
@Override
protected ClientTooltipPositioner createTooltipPositioner() {
return DefaultTooltipPositioner.INSTANCE;
}
public <T extends AbstractSimiWidget> T withCallback(BiConsumer<Integer, Integer> cb) {
this.onClick = cb;
//noinspection unchecked
return (T) this;
}
public <T extends AbstractSimiWidget> T withCallback(Runnable cb) {
return withCallback((_$, _$$) -> cb.run());
}
public <T extends AbstractSimiWidget> T atZLevel(float z) {
this.z = z;
//noinspection unchecked
return (T) this;
}
public List<Component> getToolTip() {
return toolTip;
}
@Override
public void tick() {}
@Override
public void renderWidget(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
beforeRender(graphics, mouseX, mouseY, partialTicks);
doRender(graphics, mouseX, mouseY, partialTicks);
afterRender(graphics, mouseX, mouseY, partialTicks);
wasHovered = isHoveredOrFocused();
}
protected void beforeRender(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
graphics.pose().pushPose();
}
protected void doRender(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
}
protected void afterRender(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
graphics.pose().popPose();
}
public void runCallback(double mouseX, double mouseY) {
onClick.accept((int) mouseX, (int) mouseY);
}
@Override
public void onClick(double mouseX, double mouseY) {
runCallback(mouseX, mouseY);
}
@Override
public void updateWidgetNarration(NarrationElementOutput pNarrationElementOutput) {
defaultButtonNarrationText(pNarrationElementOutput);
}
}

View File

@@ -0,0 +1,56 @@
package com.oierbravo.mechanical_lemon_ui.foundation.gui.widget;
import com.mojang.blaze3d.systems.RenderSystem;
import com.oierbravo.mechanical_lemon_ui.register.LibGuiTextures;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
import net.minecraftforge.energy.IEnergyStorage;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Optional;
public class EnergyDisplay extends AbstractSimiWidget {
private final IEnergyStorage energy;
private final int xPos;
private final int yPos;
private final int width;
private final int height;
public EnergyDisplay(int x, int y, IEnergyStorage pEnergy) {
super(x, y);
this.xPos = x;
this.yPos = y;
this.width = 9;
this.height = 30;
this.energy = pEnergy;
}
@Override
protected void doRender(@NotNull GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float partialTicks) {
if (visible) {
isHovered = pMouseX >= getX() && pMouseY >= getY() && pMouseX < getX() + width && pMouseY < getY() + height;
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
drawBg(pGuiGraphics, LibGuiTextures.RF_VERTIVAL_BAR);
int stored = (int)(height * (energy.getEnergyStored() / (float)energy.getMaxEnergyStored()));
pGuiGraphics.fillGradient(xPos,yPos + (height - stored),xPos + width, yPos + height,0xffb51500, 0xff600b00);
if(isHovered()) {
Font font = Minecraft.getInstance().font;
pGuiGraphics.renderTooltip(font, getTooltips(),
Optional.empty(), pMouseX, pMouseY);
}
}
}
protected void drawBg(GuiGraphics graphics, LibGuiTextures button) {
graphics.blit(button.location, getX(), getY(), button.startX, button.startY, button.width, button.height);
}
public List<Component> getTooltips() {
return List.of(Component.literal(energy.getEnergyStored()+" / "+energy.getMaxEnergyStored()+" FE"));
}
}

View File

@@ -0,0 +1,52 @@
package com.oierbravo.mechanical_lemon_ui.foundation.gui.widget;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import com.mojang.blaze3d.systems.RenderSystem;
import com.oierbravo.mechanical_lemon_ui.foundation.utility.ScreenElement;
import com.oierbravo.mechanical_lemon_ui.register.LibGuiTextures;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
public class IconButton extends AbstractSimiWidget {
protected ScreenElement icon;
public IconButton(int x, int y, ScreenElement icon) {
this(x, y, 18, 18, icon);
}
public IconButton(int x, int y, int w, int h, ScreenElement icon) {
super(x, y, w, h);
this.icon = icon;
}
@Override
public void doRender(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
if (visible) {
isHovered = mouseX >= getX() && mouseY >= getY() && mouseX < getX() + width && mouseY < getY() + height;
LibGuiTextures button = !active ? LibGuiTextures.BUTTON_DOWN
: isMouseOver(mouseX, mouseY) ? LibGuiTextures.BUTTON_HOVER : LibGuiTextures.BUTTON;
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
drawBg(graphics, button);
icon.render(graphics, getX() + 1, getY() + 1);
}
}
protected void drawBg(GuiGraphics graphics, LibGuiTextures button) {
graphics.blit(button.location, getX(), getY(), button.startX, button.startY, button.width, button.height);
}
public void setToolTip(Component text) {
toolTip.clear();
toolTip.add(text);
}
public void setIcon(ScreenElement icon) {
this.icon = icon;
}
}

View File

@@ -0,0 +1,25 @@
package com.oierbravo.mechanical_lemon_ui.foundation.gui.widget;
import com.oierbravo.mechanical_lemon_ui.register.LibGuiTextures;
import net.minecraft.client.gui.GuiGraphics;
import org.jetbrains.annotations.NotNull;
public class ProgressArrow extends AbstractSimiWidget {
LibGuiTextures TEXTURE = LibGuiTextures.PROGRESS_ARROW_EMPTY;
int currentProgress;
private int progress;
public ProgressArrow(int x, int y) {
super(x, y);
}
@Override
protected void doRender(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) {
graphics.blit(TEXTURE.location, getX(), getY(), TEXTURE.startX, TEXTURE.startY, currentProgress, TEXTURE.height);
}
public void setProgress(int progress, int maxProgress) {
int progressArrowSize = TEXTURE.width;
this.currentProgress = maxProgress != 0 && progress != 0 ? progress * progressArrowSize / maxProgress : 0;
}
}

View File

@@ -0,0 +1,243 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import com.google.common.hash.Hashing;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
import org.joml.Vector3f;
import javax.annotation.Nonnull;
import java.util.function.UnaryOperator;
public class Color {
public static final Color TRANSPARENT_BLACK = (new Color(0, 0, 0, 0)).setImmutable();
public static final Color BLACK = (new Color(0, 0, 0)).setImmutable();
public static final Color WHITE = (new Color(255, 255, 255)).setImmutable();
public static final Color RED = (new Color(255, 0, 0)).setImmutable();
public static final Color GREEN = (new Color(0, 255, 0)).setImmutable();
public static final Color SPRING_GREEN = (new Color(0, 255, 187)).setImmutable();
protected boolean mutable;
protected int value;
public Color(int r, int g, int b) {
this(r, g, b, 255);
}
public Color(int r, int g, int b, int a) {
this.mutable = true;
this.value = (a & 255) << 24 | (r & 255) << 16 | (g & 255) << 8 | (b & 255) << 0;
}
public Color(float r, float g, float b, float a) {
this((int)(0.5 + (double)(255.0F * Mth.clamp(r, 0.0F, 1.0F))), (int)(0.5 + (double)(255.0F * Mth.clamp(g, 0.0F, 1.0F))), (int)(0.5 + (double)(255.0F * Mth.clamp(b, 0.0F, 1.0F))), (int)(0.5 + (double)(255.0F * Mth.clamp(a, 0.0F, 1.0F))));
}
public Color(int rgba) {
this.mutable = true;
this.value = rgba;
}
public Color(int rgb, boolean hasAlpha) {
this.mutable = true;
if (hasAlpha) {
this.value = rgb;
} else {
this.value = rgb | -16777216;
}
}
public Color copy() {
return this.copy(true);
}
public Color copy(boolean mutable) {
return mutable ? new Color(this.value) : (new Color(this.value)).setImmutable();
}
public Color setImmutable() {
this.mutable = false;
return this;
}
public int getRed() {
return this.getRGB() >> 16 & 255;
}
public int getGreen() {
return this.getRGB() >> 8 & 255;
}
public int getBlue() {
return this.getRGB() >> 0 & 255;
}
public int getAlpha() {
return this.getRGB() >> 24 & 255;
}
public float getRedAsFloat() {
return (float)this.getRed() / 255.0F;
}
public float getGreenAsFloat() {
return (float)this.getGreen() / 255.0F;
}
public float getBlueAsFloat() {
return (float)this.getBlue() / 255.0F;
}
public float getAlphaAsFloat() {
return (float)this.getAlpha() / 255.0F;
}
public int getRGB() {
return this.value;
}
public Vec3 asVector() {
return new Vec3((double)this.getRedAsFloat(), (double)this.getGreenAsFloat(), (double)this.getBlueAsFloat());
}
public Vector3f asVectorF() {
return new Vector3f(this.getRedAsFloat(), this.getGreenAsFloat(), this.getBlueAsFloat());
}
public Color setRed(int r) {
return this.ensureMutable().setRedUnchecked(r);
}
public Color setGreen(int g) {
return this.ensureMutable().setGreenUnchecked(g);
}
public Color setBlue(int b) {
return this.ensureMutable().setBlueUnchecked(b);
}
public Color setAlpha(int a) {
return this.ensureMutable().setAlphaUnchecked(a);
}
public Color setRed(float r) {
return this.ensureMutable().setRedUnchecked((int)(255.0F * Mth.clamp(r, 0.0F, 1.0F)));
}
public Color setGreen(float g) {
return this.ensureMutable().setGreenUnchecked((int)(255.0F * Mth.clamp(g, 0.0F, 1.0F)));
}
public Color setBlue(float b) {
return this.ensureMutable().setBlueUnchecked((int)(255.0F * Mth.clamp(b, 0.0F, 1.0F)));
}
public Color setAlpha(float a) {
return this.ensureMutable().setAlphaUnchecked((int)(255.0F * Mth.clamp(a, 0.0F, 1.0F)));
}
public Color scaleAlpha(float factor) {
return this.ensureMutable().setAlphaUnchecked((int)((float)this.getAlpha() * Mth.clamp(factor, 0.0F, 1.0F)));
}
public Color mixWith(Color other, float weight) {
return this.ensureMutable().setRedUnchecked((int)((float)this.getRed() + (float)(other.getRed() - this.getRed()) * weight)).setGreenUnchecked((int)((float)this.getGreen() + (float)(other.getGreen() - this.getGreen()) * weight)).setBlueUnchecked((int)((float)this.getBlue() + (float)(other.getBlue() - this.getBlue()) * weight)).setAlphaUnchecked((int)((float)this.getAlpha() + (float)(other.getAlpha() - this.getAlpha()) * weight));
}
public Color darker() {
int a = this.getAlpha();
return this.ensureMutable().mixWith(BLACK, 0.25F).setAlphaUnchecked(a);
}
public Color brighter() {
int a = this.getAlpha();
return this.ensureMutable().mixWith(WHITE, 0.25F).setAlphaUnchecked(a);
}
public Color setValue(int value) {
return this.ensureMutable().setValueUnchecked(value);
}
public Color modifyValue(UnaryOperator<Integer> function) {
int newValue = (Integer)function.apply(this.value);
return newValue == this.value ? this : this.ensureMutable().setValueUnchecked(newValue);
}
protected Color ensureMutable() {
return this.mutable ? this : new Color(this.value);
}
protected Color setRedUnchecked(int r) {
this.value = this.value & -16711681 | (r & 255) << 16;
return this;
}
protected Color setGreenUnchecked(int g) {
this.value = this.value & -65281 | (g & 255) << 8;
return this;
}
protected Color setBlueUnchecked(int b) {
this.value = this.value & -256 | (b & 255) << 0;
return this;
}
protected Color setAlphaUnchecked(int a) {
this.value = this.value & 16777215 | (a & 255) << 24;
return this;
}
protected Color setValueUnchecked(int value) {
this.value = value;
return this;
}
public static Color mixColors(@Nonnull Color c1, @Nonnull Color c2, float w) {
return new Color((int)((float)c1.getRed() + (float)(c2.getRed() - c1.getRed()) * w), (int)((float)c1.getGreen() + (float)(c2.getGreen() - c1.getGreen()) * w), (int)((float)c1.getBlue() + (float)(c2.getBlue() - c1.getBlue()) * w), (int)((float)c1.getAlpha() + (float)(c2.getAlpha() - c1.getAlpha()) * w));
}
public static Color mixColors(@Nonnull Couple<Color> colors, float w) {
return mixColors((Color)colors.getFirst(), (Color)colors.getSecond(), w);
}
public static int mixColors(int color1, int color2, float w) {
int a1 = color1 >> 24;
int r1 = color1 >> 16 & 255;
int g1 = color1 >> 8 & 255;
int b1 = color1 & 255;
int a2 = color2 >> 24;
int r2 = color2 >> 16 & 255;
int g2 = color2 >> 8 & 255;
int b2 = color2 & 255;
return ((int)((float)a1 + (float)(a2 - a1) * w) << 24) + ((int)((float)r1 + (float)(r2 - r1) * w) << 16) + ((int)((float)g1 + (float)(g2 - g1) * w) << 8) + ((int)((float)b1 + (float)(b2 - b1) * w) << 0);
}
public static Color rainbowColor(int timeStep) {
int localTimeStep = Math.abs(timeStep) % 1536;
int timeStepInPhase = localTimeStep % 256;
int phaseBlue = localTimeStep / 256;
int red = colorInPhase(phaseBlue + 4, timeStepInPhase);
int green = colorInPhase(phaseBlue + 2, timeStepInPhase);
int blue = colorInPhase(phaseBlue, timeStepInPhase);
return new Color(red, green, blue);
}
private static int colorInPhase(int phase, int progress) {
phase %= 6;
if (phase <= 1) {
return 0;
} else if (phase == 2) {
return progress;
} else {
return phase <= 4 ? 255 : 255 - progress;
}
}
public static Color generateFromLong(long l) {
return rainbowColor(Hashing.crc32().hashLong(l).asInt()).mixWith(WHITE, 0.5F);
}
}

View File

@@ -0,0 +1,37 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
public final class Components {
private static final Component IMMUTABLE_EMPTY = Component.empty();
public static Component immutableEmpty() {
return IMMUTABLE_EMPTY;
}
/** Use {@link #immutableEmpty()} when possible to prevent creating an extra object. */
public static MutableComponent empty() {
return Component.empty();
}
public static MutableComponent literal(String str) {
return Component.literal(str);
}
public static MutableComponent translatable(String key) {
return Component.translatable(key);
}
public static MutableComponent translatable(String key, Object... args) {
return Component.translatable(key, args);
}
public static MutableComponent keybind(String name) {
return Component.keybind(name);
}
}

View File

@@ -0,0 +1,155 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import com.google.common.collect.ImmutableList;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import java.util.Iterator;
import java.util.List;
import java.util.function.*;
import java.util.stream.Stream;
public class Couple<T> extends Pair<T, T> implements Iterable<T> {
private static final Couple<Boolean> TRUE_AND_FALSE = Couple.create(true, false);
protected Couple(T first, T second) {
super(first, second);
}
public static <T> Couple<T> create(T first, T second) {
return new Couple<>(first, second);
}
public static <T> Couple<T> create(Supplier<T> factory) {
return new Couple<>(factory.get(), factory.get());
}
public static <T> Couple<T> createWithContext(Function<Boolean, T> factory) {
return new Couple<>(factory.apply(true), factory.apply(false));
}
public T get(boolean first) {
return first ? getFirst() : getSecond();
}
public void set(boolean first, T value) {
if (first)
setFirst(value);
else
setSecond(value);
}
@Override
public Couple<T> copy() {
return create(first, second);
}
public <S> Couple<S> map(Function<T, S> function) {
return Couple.create(function.apply(first), function.apply(second));
}
public <S> Couple<S> mapWithContext(BiFunction<T, Boolean, S> function) {
return Couple.create(function.apply(first, true), function.apply(second, false));
}
public <S, R> Couple<S> mapWithParams(BiFunction<T, R, S> function, Couple<R> values) {
return Couple.create(function.apply(first, values.first), function.apply(second, values.second));
}
public <S, R> Couple<S> mapNotNullWithParam(BiFunction<T, R, S> function, R value) {
return Couple.create(first != null ? function.apply(first, value) : null,
second != null ? function.apply(second, value) : null);
}
public boolean both(Predicate<T> test) {
return test.test(getFirst()) && test.test(getSecond());
}
public boolean either(Predicate<T> test) {
return test.test(getFirst()) || test.test(getSecond());
}
public void replace(Function<T, T> function) {
setFirst(function.apply(getFirst()));
setSecond(function.apply(getSecond()));
}
public void replaceWithContext(BiFunction<T, Boolean, T> function) {
replaceWithParams(function, TRUE_AND_FALSE);
}
public <S> void replaceWithParams(BiFunction<T, S, T> function, Couple<S> values) {
setFirst(function.apply(getFirst(), values.getFirst()));
setSecond(function.apply(getSecond(), values.getSecond()));
}
@Override
public void forEach(Consumer<? super T> consumer) {
consumer.accept(getFirst());
consumer.accept(getSecond());
}
public void forEachWithContext(BiConsumer<T, Boolean> consumer) {
forEachWithParams(consumer, TRUE_AND_FALSE);
}
public <S> void forEachWithParams(BiConsumer<T, S> function, Couple<S> values) {
function.accept(getFirst(), values.getFirst());
function.accept(getSecond(), values.getSecond());
}
public Couple<T> swap() {
return Couple.create(second, first);
}
public ListTag serializeEach(Function<T, CompoundTag> serializer) {
return NBTHelper.writeCompoundList(ImmutableList.of(first, second), serializer);
}
public static <S> Couple<S> deserializeEach(ListTag list, Function<CompoundTag, S> deserializer) {
List<S> readCompoundList = NBTHelper.readCompoundList(list, deserializer);
return new Couple<>(readCompoundList.get(0), readCompoundList.get(1));
}
@Override
public Iterator<T> iterator() {
return new Couplerator<>(this);
}
public Stream<T> stream() {
return Stream.of(first, second);
}
private static class Couplerator<T> implements Iterator<T> {
int state;
private final Couple<T> couple;
public Couplerator(Couple<T> couple) {
this.couple = couple;
state = 0;
}
@Override
public boolean hasNext() {
return state != 2;
}
@Override
public T next() {
state++;
if (state == 1)
return couple.first;
if (state == 2)
return couple.second;
return null;
}
}
}

View File

@@ -0,0 +1,35 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
/*
* smashingmods
*
* This code is licensed under "GNU Lesser General Public License"
* https://github.com/SmashingMods/AlchemyLib/
*
* Slightly Modified Version by: oierbravo
*/
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.world.item.ItemStack;
public class FakeItemRenderer {
public static void renderFakeItem(GuiGraphics pGuiGraphics, ItemStack pItemStack, int pX, int pY) {
renderFakeItem(pGuiGraphics, pItemStack, pX, pY, true, false);
}
public static void renderFakeItem(GuiGraphics pGuiGraphics, ItemStack pItemStack, int pX, int pY, boolean pDrawItemDecorations) {
renderFakeItem(pGuiGraphics, pItemStack, pX, pY, true, pDrawItemDecorations);
}
public static void renderFakeItem(GuiGraphics pGuiGraphics, ItemStack pItemStack, int pX, int pY, boolean pSemiTransparent, boolean pDrawItemDecorations) {
pGuiGraphics.renderFakeItem(pItemStack, pX, pY);
if (pSemiTransparent) {
pGuiGraphics.fill(RenderType.guiGhostRecipeOverlay(), pX, pY, pX + 16, pY + 16, 0x88888888);
}
if (pDrawItemDecorations) {
pGuiGraphics.renderItemDecorations(Minecraft.getInstance().font, pItemStack, pX, pY);
}
}
}

View File

@@ -0,0 +1,39 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
import com.mojang.blaze3d.systems.RenderSystem;
import com.oierbravo.mechanical_lemon_ui.foundation.gui.UIRenderHelper;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.resources.ResourceLocation;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public abstract class IGuiTextures {
ResourceLocation location = null;
int width = 0;
int height = 0;
int startX = 0;
int startY = 0;
@OnlyIn(Dist.CLIENT)
public void bind() {
RenderSystem.setShaderTexture(0, location);
}
@OnlyIn(Dist.CLIENT)
public void render(GuiGraphics graphics, int x, int y) {
graphics.blit(location, x, y, startX, startY, width, height);
}
@OnlyIn(Dist.CLIENT)
public void render(GuiGraphics graphics, int x, int y, Color c) {
bind();
UIRenderHelper.drawColoredTexture(graphics, c, x, y, startX, startY, width, height);
}
}

View File

@@ -0,0 +1,11 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import net.minecraft.world.entity.player.Player;
public interface IInteractionChecker {
boolean canPlayerUse(Player player);
}

View File

@@ -0,0 +1,85 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.fluids.FluidStack;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class Lang {
public Lang() {
}
public static MutableComponent translateDirect(String key, Object... args) {
return Components.translatable("create." + key, resolveBuilders(args));
}
public static String asId(String name) {
return name.toLowerCase(Locale.ROOT);
}
public static String nonPluralId(String name) {
String asId = asId(name);
return asId.endsWith("s") ? asId.substring(0, asId.length() - 1) : asId;
}
public static List<Component> translatedOptions(String prefix, String... keys) {
List<Component> result = new ArrayList(keys.length);
String[] var3 = keys;
int var4 = keys.length;
for(int var5 = 0; var5 < var4; ++var5) {
String key = var3[var5];
result.add(translate((prefix != null ? prefix + "." : "") + key).component());
}
return result;
}
public static LangBuilder builder() {
return new LangBuilder("create");
}
public static LangBuilder builder(String namespace) {
return new LangBuilder(namespace);
}
public static LangBuilder blockName(BlockState state) {
return builder().add(state.getBlock().getName());
}
public static LangBuilder itemName(ItemStack stack) {
return builder().add(stack.getHoverName().copy());
}
public static LangBuilder fluidName(FluidStack stack) {
return builder().add(stack.getDisplayName().copy());
}
public static LangBuilder number(double d) {
return builder().text(LangNumberFormat.format(d));
}
public static LangBuilder translate(String langKey, Object... args) {
return builder().translate(langKey, args);
}
public static LangBuilder text(String text) {
return builder().text(text);
}
public static Object[] resolveBuilders(Object[] args) {
for(int i = 0; i < args.length; ++i) {
Object var3 = args[i];
if (var3 instanceof LangBuilder cb) {
args[i] = cb.component();
}
}
return args;
}
}

View File

@@ -0,0 +1,190 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
import joptsimple.internal.Strings;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Player;
import java.util.List;
public class LangBuilder {
String namespace;
MutableComponent component;
public LangBuilder(String namespace) {
this.namespace = namespace;
}
public LangBuilder space() {
return text(" ");
}
public LangBuilder newLine() {
return text("\n");
}
/**
* Appends a localised component<br>
* To add an independently formatted localised component, use add() and a nested
* builder
*
* @param langKey
* @param args
* @return
*/
public LangBuilder translate(String langKey, Object... args) {
return add(Components.translatable(namespace + "." + langKey, Lang.resolveBuilders(args)));
}
/**
* Appends a text component
*
* @param literalText
* @return
*/
public LangBuilder text(String literalText) {
return add(Components.literal(literalText));
}
/**
* Appends a colored text component
*
* @param format
* @param literalText
* @return
*/
public LangBuilder text(ChatFormatting format, String literalText) {
return add(Components.literal(literalText).withStyle(format));
}
/**
* Appends a colored text component
*
* @param color
* @param literalText
* @return
*/
public LangBuilder text(int color, String literalText) {
return add(Components.literal(literalText).withStyle(s -> s.withColor(color)));
}
/**
* Appends the contents of another builder
*
* @param otherBuilder
* @return
*/
public LangBuilder add(LangBuilder otherBuilder) {
return add(otherBuilder.component());
}
/**
* Appends a component
*
* @param customComponent
* @return
*/
public LangBuilder add(MutableComponent customComponent) {
component = component == null ? customComponent : component.append(customComponent);
return this;
}
/**
* Appends a component
*
* @param component the component to append
* @return this builder
*/
public LangBuilder add(Component component) {
if (component instanceof MutableComponent mutableComponent)
return add(mutableComponent);
else
return add(component.copy());
}
//
/**
* Applies the format to all added components
*
* @param format
* @return
*/
public LangBuilder style(ChatFormatting format) {
assertComponent();
component = component.withStyle(format);
return this;
}
/**
* Applies the color to all added components
*
* @param color
* @return
*/
public LangBuilder color(int color) {
assertComponent();
component = component.withStyle(s -> s.withColor(color));
return this;
}
//
public MutableComponent component() {
assertComponent();
return component;
}
public String string() {
return component().getString();
}
public String json() {
return Component.Serializer.toJson(component());
}
public void sendStatus(Player player) {
player.displayClientMessage(component(), true);
}
public void sendChat(Player player) {
player.displayClientMessage(component(), false);
}
public void addTo(List<? super MutableComponent> tooltip) {
tooltip.add(component());
}
public void forGoggles(List<? super MutableComponent> tooltip) {
forGoggles(tooltip, 0);
}
public void forGoggles(List<? super MutableComponent> tooltip, int indents) {
tooltip.add(Lang.builder()
.text(Strings.repeat(' ', getIndents(Minecraft.getInstance().font, 4 + indents)))
.add(this)
.component());
}
public static final float DEFAULT_SPACE_WIDTH = 4.0F; // space width in vanilla's default font
static int getIndents(Font font, int defaultIndents) {
int spaceWidth = font.width(" ");
if (DEFAULT_SPACE_WIDTH == spaceWidth) {
return defaultIndents;
}
return Mth.ceil(DEFAULT_SPACE_WIDTH * defaultIndents / spaceWidth);
}
//
private void assertComponent() {
if (component == null)
throw new IllegalStateException("No components were added to builder");
}
}

View File

@@ -0,0 +1,35 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
import net.minecraft.client.Minecraft;
import net.minecraft.util.Mth;
import java.text.NumberFormat;
import java.util.Locale;
public class LangNumberFormat {
private NumberFormat format = NumberFormat.getNumberInstance(Locale.ROOT);
public static LangNumberFormat numberFormat = new LangNumberFormat();
public NumberFormat get() {
return format;
}
public void update() {
format = NumberFormat.getInstance(Minecraft.getInstance()
.getLanguageManager()
.getJavaLocale());
format.setMaximumFractionDigits(2);
format.setMinimumFractionDigits(0);
format.setGroupingUsed(true);
}
public static String format(double d) {
if (Mth.equal(d, 0))
d = 0;
return numberFormat.get()
.format(d)
.replace("\u00A0", " ");
}
}

View File

@@ -0,0 +1,129 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.AABB;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
public class NBTHelper {
public static void putMarker(CompoundTag nbt, String marker) {
nbt.putBoolean(marker, true);
}
public static <T extends Enum<?>> T readEnum(CompoundTag nbt, String key, Class<T> enumClass) {
T[] enumConstants = enumClass.getEnumConstants();
if (enumConstants == null)
throw new IllegalArgumentException("Non-Enum class passed to readEnum: " + enumClass.getName());
if (nbt.contains(key, Tag.TAG_STRING)) {
String name = nbt.getString(key);
for (T t : enumConstants) {
if (t.name()
.equals(name))
return t;
}
}
return enumConstants[0];
}
public static <T extends Enum<?>> void writeEnum(CompoundTag nbt, String key, T enumConstant) {
nbt.putString(key, enumConstant.name());
}
public static <T> ListTag writeCompoundList(Iterable<T> list, Function<T, CompoundTag> serializer) {
ListTag listNBT = new ListTag();
list.forEach(t -> {
CompoundTag apply = serializer.apply(t);
if (apply == null)
return;
listNBT.add(apply);
});
return listNBT;
}
public static <T> List<T> readCompoundList(ListTag listNBT, Function<CompoundTag, T> deserializer) {
List<T> list = new ArrayList<>(listNBT.size());
listNBT.forEach(inbt -> list.add(deserializer.apply((CompoundTag) inbt)));
return list;
}
public static <T> void iterateCompoundList(ListTag listNBT, Consumer<CompoundTag> consumer) {
listNBT.forEach(inbt -> consumer.accept((CompoundTag) inbt));
}
public static ListTag writeItemList(Iterable<ItemStack> stacks) {
return writeCompoundList(stacks, ItemStack::serializeNBT);
}
public static List<ItemStack> readItemList(ListTag stacks) {
return readCompoundList(stacks, ItemStack::of);
}
public static ListTag writeAABB(AABB bb) {
ListTag bbtag = new ListTag();
bbtag.add(FloatTag.valueOf((float) bb.minX));
bbtag.add(FloatTag.valueOf((float) bb.minY));
bbtag.add(FloatTag.valueOf((float) bb.minZ));
bbtag.add(FloatTag.valueOf((float) bb.maxX));
bbtag.add(FloatTag.valueOf((float) bb.maxY));
bbtag.add(FloatTag.valueOf((float) bb.maxZ));
return bbtag;
}
public static AABB readAABB(ListTag bbtag) {
if (bbtag == null || bbtag.isEmpty())
return null;
return new AABB(bbtag.getFloat(0), bbtag.getFloat(1), bbtag.getFloat(2), bbtag.getFloat(3),
bbtag.getFloat(4), bbtag.getFloat(5));
}
public static ListTag writeVec3i(Vec3i vec) {
ListTag tag = new ListTag();
tag.add(IntTag.valueOf(vec.getX()));
tag.add(IntTag.valueOf(vec.getY()));
tag.add(IntTag.valueOf(vec.getZ()));
return tag;
}
public static Vec3i readVec3i(ListTag tag) {
return new Vec3i(tag.getInt(0), tag.getInt(1), tag.getInt(2));
}
@Nonnull
public static Tag getINBT(CompoundTag nbt, String id) {
Tag inbt = nbt.get(id);
if (inbt != null)
return inbt;
return new CompoundTag();
}
public static CompoundTag intToCompound(int i) {
CompoundTag compoundTag = new CompoundTag();
compoundTag.putInt("V", i);
return compoundTag;
}
public static int intFromCompound(CompoundTag compoundTag) {
return compoundTag.getInt("V");
}
public static void writeResourceLocation(CompoundTag nbt, String key, ResourceLocation location) {
nbt.putString(key, location.toString());
}
public static ResourceLocation readResourceLocation(CompoundTag nbt, String key) {
return new ResourceLocation(nbt.getString(key));
}
}

View File

@@ -0,0 +1,72 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import java.util.Objects;
public class Pair<F, S> {
F first;
S second;
protected Pair(F first, S second) {
this.first = first;
this.second = second;
}
public static <F, S> Pair<F, S> of(F first, S second) {
return new Pair<>(first, second);
}
public F getFirst() {
return first;
}
public S getSecond() {
return second;
}
public void setFirst(F first) {
this.first = first;
}
public void setSecond(S second) {
this.second = second;
}
public Pair<F, S> copy() {
return Pair.of(first, second);
}
@Override
public boolean equals(final Object obj) {
if (obj == this)
return true;
if (obj instanceof Pair) {
final Pair<?, ?> other = (Pair<?, ?>) obj;
return Objects.equals(first, other.first) && Objects.equals(second, other.second);
}
return false;
}
@Override
public int hashCode() {
return (nullHash(first) * 31) ^ nullHash(second);
}
int nullHash(Object o) {
return o == null ? 0 : o.hashCode();
}
@Override
public String toString() {
return "(" + first + ", " + second + ")";
}
public Pair<S, F> swap() {
return Pair.of(second, first);
}
}

View File

@@ -0,0 +1,14 @@
package com.oierbravo.mechanical_lemon_ui.foundation.utility;
/*
* Credits: Creators of create
* https://github.com/Creators-of-Create/Create
* License: MIT
*/
import net.minecraft.client.gui.GuiGraphics;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public interface ScreenElement {
@OnlyIn(Dist.CLIENT)
void render(GuiGraphics var1, int var2, int var3);
}

View File

@@ -0,0 +1,67 @@
package com.oierbravo.mechanical_lemon_ui.register;
import com.mojang.blaze3d.systems.RenderSystem;
import com.oierbravo.mechanical_lemon_ui.MechanicalLemonUI;
import com.oierbravo.mechanical_lemon_ui.foundation.gui.UIRenderHelper;
import com.oierbravo.mechanical_lemon_ui.foundation.utility.Color;
import com.oierbravo.mechanical_lemon_ui.foundation.utility.ScreenElement;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public enum LibGuiTextures implements ScreenElement {
PLAYER_INVENTORY("player_inventory", 176, 108),
BUTTON("widgets", 18, 18),
BUTTON_HOVER("widgets", 18, 0, 18, 18),
BUTTON_DOWN("widgets", 36, 0, 18, 18),
SLOT_EMPTY("widgets", 36, 0, 18, 18),
RF_VERTIVAL_BAR("widgets",0,18,10,30),
PROGRESS_ARROW_EMPTY("widgets",0,48,32,8),
PROGRESS_ARROW_FULL("widgets",0,56,32,8)
;
public static final int FONT_COLOR = 0x575F7A;
public final ResourceLocation location;
public int width, height;
public int startX, startY;
private LibGuiTextures(String location, int width, int height) {
this(location, 0, 0, width, height);
}
private LibGuiTextures(int startX, int startY) {
this("icons", startX * 16, startY * 16, 16, 16);
}
private LibGuiTextures(String location, int startX, int startY, int width, int height) {
this(MechanicalLemonUI.MODID, location, startX, startY, width, height);
}
private LibGuiTextures(String namespace, String location, int startX, int startY, int width, int height) {
this.location = new ResourceLocation(namespace, "textures/gui/" + location + ".png");
this.width = width;
this.height = height;
this.startX = startX;
this.startY = startY;
}
@OnlyIn(Dist.CLIENT)
public void bind() {
RenderSystem.setShaderTexture(0, location);
}
@OnlyIn(Dist.CLIENT)
public void render(GuiGraphics graphics, int x, int y) {
graphics.blit(location, x, y, startX, startY, width, height);
}
@OnlyIn(Dist.CLIENT)
public void render(GuiGraphics graphics, int x, int y, Color c) {
bind();
UIRenderHelper.drawColoredTexture(graphics, c, x, y, startX, startY, width, height);
}
}

View File

@@ -0,0 +1,81 @@
package com.oierbravo.mechanical_lemon_ui.register;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.oierbravo.mechanical_lemon_ui.MechanicalLemonUI;
import com.oierbravo.mechanical_lemon_ui.foundation.utility.Color;
import com.oierbravo.mechanical_lemon_ui.foundation.utility.ScreenElement;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
public class LibIcons implements ScreenElement {
public static final ResourceLocation ICON_ATLAS = MechanicalLemonUI.asResource("textures/gui/icons.png");
public static final int ICON_ATLAS_SIZE = 256;
private static int x = 0;
private static int y = -1;
private int iconX;
private int iconY;
public static final LibIcons ARROW_LEFT = newRow();
public static final LibIcons TRASH = next();
public static final LibIcons REDSTONE_HIGH = next();
public static final LibIcons REDSTONE_LOW = next();
public static final LibIcons REDSTONE_IGNORE = next();
public static final LibIcons SEARCH = next();
public static final LibIcons CHECK = next();
public LibIcons(int x, int y) {
this.iconX = x * 16;
this.iconY = y * 16;
}
private static LibIcons next() {
return new LibIcons(++x, y);
}
private static LibIcons newRow() {
x = 0;
return new LibIcons(0, ++y);
}
@OnlyIn(Dist.CLIENT)
public void bind() {
RenderSystem.setShaderTexture(0, ICON_ATLAS);
}
@OnlyIn(Dist.CLIENT)
public void render(GuiGraphics graphics, int x, int y) {
graphics.blit(ICON_ATLAS, x, y, 0, (float)this.iconX, (float)this.iconY, 16, 16, 256, 256);
}
@OnlyIn(Dist.CLIENT)
public void render(PoseStack ms, MultiBufferSource buffer, int color) {
VertexConsumer builder = buffer.getBuffer(RenderType.text(ICON_ATLAS));
Matrix4f matrix = ms.last().pose();
Color rgb = new Color(color);
int light = 15728880;
Vec3 vec1 = new Vec3(0.0, 0.0, 0.0);
Vec3 vec2 = new Vec3(0.0, 1.0, 0.0);
Vec3 vec3 = new Vec3(1.0, 1.0, 0.0);
Vec3 vec4 = new Vec3(1.0, 0.0, 0.0);
float u1 = (float)this.iconX * 1.0F / 256.0F;
float u2 = (float)(this.iconX + 16) * 1.0F / 256.0F;
float v1 = (float)this.iconY * 1.0F / 256.0F;
float v2 = (float)(this.iconY + 16) * 1.0F / 256.0F;
this.vertex(builder, matrix, vec1, rgb, u1, v1, light);
this.vertex(builder, matrix, vec2, rgb, u1, v2, light);
this.vertex(builder, matrix, vec3, rgb, u2, v2, light);
this.vertex(builder, matrix, vec4, rgb, u2, v1, light);
}
@OnlyIn(Dist.CLIENT)
private void vertex(VertexConsumer builder, Matrix4f matrix, Vec3 vec, Color rgb, float u, float v, int light) {
builder.vertex(matrix, (float)vec.x, (float)vec.y, (float)vec.z).color(rgb.getRed(), rgb.getGreen(), rgb.getBlue(), 255).uv(u, v).uv2(light).endVertex();
}
}

View File

@@ -0,0 +1,24 @@
modLoader = "javafml" #mandatory
loaderVersion = "${loader_version_range}" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
license = "${mod_license}"
[[mods]] #mandatory
modId = "${modid}" #mandatory
version = "${mod_version}" #mandatory
displayName = "${mod_name}" #mandatory
authors = "${author}" #optional
description = '''${mod_description}'''
[[dependencies."${modid}"]] #optional
modId = "forge" #mandatory
mandatory = true #mandatory
versionRange = "${forge_version_range}" #mandatory
ordering = "NONE"
side = "BOTH"# Here's another dependency
[[dependencies."${modid}"]]
modId = "minecraft"
mandatory = true
versionRange = "${minecraft_version_range}"
ordering = "NONE"
side = "BOTH"

View File

@@ -0,0 +1,2 @@
{
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 740 B

View File

@@ -0,0 +1,6 @@
{
"pack": {
"description": "mechanical_lemon_ui resources",
"pack_format": 15
}
}