Compare commits

...
23 Commits
Author SHA1 Message Date
querns 1ed004e619 Holding ALT now increases bookmark stack increase in increments of output item's stack size (#418) 2023-09-09 09:22:33 +02:00
Nico Spiske 153da523d6 Hide bookmarkItemPulling button if currently opened gui is not supported (#419)
* [minor] hide pullBookmarkedItems button if open container is not supported

* [minor] spotless apply
2023-09-08 07:16:37 +02:00
miozune c732361bbc More readable packet IDs (#417) 2023-09-06 11:05:15 +02:00
miozune bdb206b45d Fix world specific settings on MP being also specific to dimension (#414) 2023-08-18 21:42:20 +02:00
Raven Szewczyk aa44a97f80 Partial fix for the NEI custom diagram in recipe tooltip issue (#413) 2023-08-17 10:36:15 +02:00
Nico Spiske 00c4411ec5 Pull bookmarked items from container to player inventory (#410)
* [major] first potential version for basic chests

* [major] added api to register chest/inventory guis for bookmark item pulling

* [minor] added hotkey to pull all bookmarked items

* [major] finished

* [minor] spotless apply

* [minor] removed bak file

* [minor] function cleanup

* [minor] fixed bookmarks being set to 0

* [minor] little oversight

* [minor] private attribute and curly brackets
2023-08-07 15:29:05 +02:00
miozune 4f23d21d37 Fix recipe tooltip crash with BetterQuesting (#409)
* updateBuildScript

* Fix recipe tooltip crash with BetterQuesting
2023-07-28 13:20:45 +02:00
8569431e1d Recipe tooltip fixes (#402)
* Unconditionally override Minecraft.currentScreen when drawing tooltips

* Fix bad item lighting in recipe tooltips

* Update buildscript

* Fix NEI ignoring handler switching on click

Handlers might call Minecraft#displayGuiScreen and overwrite Minecraft.currentScreen, but the height hack would unconditionally undo this again.

* spotlessApply (#404)

Co-authored-by: GitHub GTNH Actions <>

* Attempt to fix CME when opening recipes immediately after load (#403)

* Rename the internal private class HeightHack->CompatibilityHacks to better reflect the new usage.

* Move trueGui assignment down.

* Fix overlay button y offsets

* Fix wrong recipe tooltip background rendering

* Apply spotless

---------

Co-authored-by: Wilhelm Schuster <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-23 08:04:31 +02:00
Wilhelm Schuster 5b9c27e253 Fix potential NPE when calling ItemMobSpawner#loadSpawners. (#405) 2023-07-16 14:29:31 +02:00
Raven Szewczyk d613d06471 Attempt to fix CME when opening recipes immediately after load (#403) 2023-07-16 09:00:35 +01:00
65ffbad491 Show a full recipe widget in item tooltips for bookmarked recipes (#398)
* Update buildscript

* Show a full recipe widget in item tooltips for bookmarked recipes

* Make recipe tooltips configurable and only show in the bookmarks panel

* Fix layout relative to tooltip boxes

* Fix wildcard import

* spotlessApply (#401)

Co-authored-by: GitHub GTNH Actions <>

* Fix handler tooltip offsets for new&legacy handlers

* Fix render order to draw crafting tooltips on top of container manager buttons

* Fix wrong mouse Y half-point calculation

* Allow saving recipes with empty item ingredient lists to bookmarks (e.g. fluid-only)

* Fix waila vs. non-waila tooltip offsets

Co-authored-by: Wilhelm Schuster <[email protected]>

---------

Co-authored-by: Wilhelm Schuster <[email protected]>
2023-07-10 17:38:07 +01:00
Wilhelm Schuster 885609720e Extend height hack for legacy recipe handlers (#395)
* Store heighthackhandlers.cfg as an internal asset instead of an array of strings

Is copied into the config directory upon first launch. Also, comments
are now allowed (only from the beginning of the file).

* Store serialhandlers.cfg as an internal asset instead of an array of strings

Is copied into the config directory upon first launch. Also, comments
are now allowed (only from the beginning of the file).

Removes GTNH-specific code to be replaced with a configuration file.

* Extend the height hack to also cover guiTop and getRecipePosition

Certain legacy recipe handlers hardcode even more of the NEI recipe
screen layout, requiring only the singular recipe handler switcher
widget at the top, whereas this improved NEI moves the recipe pager to
the top as well expecting recipe handler to move down another 16px. One
such mod that breaks is Immersive Engineering. To fix it we move the top
edge of the gui (guiTop) down by 16px so that the old gap calculation
works correctly. This required special handling in getRecipePosition()
and refreshSlots().

* Fix Immersive Engineering recipe handlers

* Fix Ex Nihilo recipe handlers

* Fix Thermal Expansion recipe handlers

These handlers expect only two recipes to be displayed at a time. This can only be fixed through asm AFAICT.
2023-07-08 23:23:19 +02:00
chochemandglowredman bacf246504 Adjust nei overlay to gt oregen changes (#391)
* adjust to oregen changes

* add compat for old worlds

* remove testing debug

* Update buildscript

* Adjust to changed oregenPattern API

* fix fieldname

---------

Co-authored-by: glowredman <[email protected]>
2023-07-04 18:36:35 +02:00
Wilhelm Schuster 1ab3350eb8 Adjust recipe handler scrolling again (#393)
* Update buildscript

* Rework recipe handler tab scrolling again

Move the recipe handler tab scrolling before the handler-specific
scrolling again. This ensures that tab scrolling while hovering over the
tab bar will always be possible, regardless of how a recipe handler
handles scrolling itself. This mostly reverts back to how this feature
was implemented originally with one change: the Shift-scrolling behavior
is moved outside the recipe tabs scroll handler after the recipe
handler-specific scroll handling to prevent this from overwriting any
other behavior.
2023-06-24 12:01:21 +02:00
Wilhelm Schuster f3aa12483d Expand the tooltips for the time manipulation action buttons (#392) 2023-06-15 23:19:57 +02:00
miozune d86c472790 Fix crash with IC2 setItemDamage (#387)
* Ducttape fix for crash with IC2 setItemDamage

* Use Items.feather
2023-06-01 07:20:24 +02:00
Wilhelm Schuster 4124151208 Prevent recipe handler tab scrolling from overwriting recipe handler-specific scrolling (#384)
* Rename variable in GuiRecipeTabs to avoid confusion

Based on feedback in a previous PR review.

* Make sure recipe handler-specific scrolling behavior takes precedence over recipe handler tab scrolling
2023-05-13 17:40:08 +02:00
miozune 68ad800620 Remove handlers for Et Futurum Requiem (#383)
* Update dependencies

* updateBuildScript

* Remove handlers for Et Futurum Requiem
2023-05-13 14:12:22 +02:00
Wilhelm Schuster 2c7207485d Ensure the NEI config is really only initialized once (#381)
bootNEI() is supposed to only be called once during the client's
lifetime. Turns out, if your pack has 800 mods, bootNEI() might be
called a second time before configLoaded is set to true at the end of
the plugin loading thread. This introduces a second variable that is
set at the end of the single threaded portion of bootNEI() so that it
truly can only be called once, but we can still retain the ability to
check if the plugin loading thread has finished.
2023-05-10 23:55:45 +02:00
Wilhelm Schuster e8094794c3 Allow scrolling through recipe handlers (#379)
In addition to scrolling through all recipes of a single handler, you
can now scroll through all the recipe handlers while hovering over the
handler tab bar (or anywhere in the recipe area while holding left
shift).
2023-05-09 21:57:27 +02:00
miozune ad86d8f9c5 Separate logic to get detailed string of fluid amount (#378)
* Separate logic to get detailed string of fluid amount

* updateBuildScript & spotlessApply

* probably better way
2023-05-07 20:10:18 +02:00
Wilhelm Schuster 30c87e9160 Make sure NEI plugins are loaded before processing keybindings (#375)
NEI plugins are initialized in a separate thread. If this takes too long,
the client tick handler might already be running checking the keybindings
in KeyManager while a plugin calls API.addKeyBind() which can lead to a
CME.

Reported in https://github.com/GTNewHorizons/GT-New-Horizons-Modpack/issues/13292
Thanks to @Denostrov for helping me track this down.
2023-05-05 21:01:50 +02:00
chill 5eeb001534 Readme: fix wording (#374) 2023-05-05 12:16:22 +02:00
51 changed files with 1149 additions and 478 deletions

No files matched your search

+9 -2
View File
@@ -1,6 +1,7 @@
.gradle
.settings
/.idea/
/.vscode/
/run/
/build/
/eclipse/
@@ -25,6 +26,12 @@ whitelist.json
*.iml
*.ipr
*.iws
src/main/resources/mixins.*.json
src/main/resources/mixins.*([!.]).json
*.bat
.DS_Store
*.DS_Store
!gradlew.bat
.factorypath
addon.local.gradle
addon.local.gradle.kts
addon.late.local.gradle
addon.late.local.gradle.kts
+1 -8
View File
@@ -12,7 +12,7 @@ If you have issues with NEI outside of the GTNH modpack you may report them in t
- Uses a parallel stream to search the item list over multiple cores, resulting in 2-6x faster searches on average
- Loads the recipe handlers in parallel
* A textbox for search with most of the features you'd expect - moving forward, backwards, selection, etc
* Bookmarks! What are you in the process of crafting? Bookmark it using either 'A' or configure your own key.
* Bookmarks! Are you in the process of crafting? Bookmark it using either 'A' or configure your own key.
* Toggle bookmark pane. Default shortcut key `B`. Item Subsets menu is only available if bookmarks are not visible.
* Utility/Cheat buttons line up and wrap based on GUI size
* ItemList is no longer regenerated from the ItemRegistry on every inventory load
@@ -27,13 +27,6 @@ If you have issues with NEI outside of the GTNH modpack you may report them in t
* Remove TMI style
* Removed inventory Load/Save state
## Development
Before launching, you need to add
```
-Dfml.coreMods.load=codechicken.nei.asm.NEICorePlugin
```
as a command line argument to the VM.
## License
GTNH Modifications Copyright (c) 2019-2022 mitchej123 and the GTNH Team
+206 -164
View File
@@ -1,4 +1,4 @@
//version: 1680120787
//version: 1692122114
/*
DO NOT CHANGE THIS FILE!
Also, you may replace this file at any time if there is an update available.
@@ -6,29 +6,25 @@
*/
import com.diffplug.blowdryer.Blowdryer
import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.gtnewhorizons.retrofuturagradle.ObfuscationAttribute
import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar
import com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask
import com.gtnewhorizons.retrofuturagradle.util.Distribution
import com.matthewprenger.cursegradle.CurseArtifact
import com.matthewprenger.cursegradle.CurseRelation
import com.modrinth.minotaur.dependencies.ModDependency
import com.modrinth.minotaur.dependencies.VersionDependency
import cpw.mods.fml.relauncher.Side
import org.gradle.api.tasks.options.Option;
import org.gradle.internal.logging.text.StyledTextOutput.Style
import org.gradle.internal.logging.text.StyledTextOutputFactory
import org.gradle.internal.xml.XmlTransformer
import org.jetbrains.gradle.ext.*
import org.jetbrains.gradle.ext.Application
import org.jetbrains.gradle.ext.Gradle
import javax.inject.Inject
import java.nio.file.Files
import java.nio.file.Paths
import java.util.concurrent.TimeUnit
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import javax.inject.Inject
buildscript {
repositories {
@@ -66,21 +62,25 @@ plugins {
id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false
id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false
id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle
id 'com.github.johnrengelman.shadow' version '7.1.2' apply false
id 'com.palantir.git-version' version '0.13.0' apply false // 0.13.0 is the last jvm8 supporting version
id 'de.undercouch.download' version '5.3.0'
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
id 'com.palantir.git-version' version '3.0.0' apply false
id 'de.undercouch.download' version '5.4.0'
id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle
id 'com.diffplug.spotless' version '6.7.2' apply false
id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version
id 'com.modrinth.minotaur' version '2.+' apply false
id 'com.matthewprenger.cursegradle' version '1.4.0' apply false
id 'com.gtnewhorizons.retrofuturagradle' version '1.2.4'
id 'com.gtnewhorizons.retrofuturagradle' version '1.3.24'
}
print("You might want to check out './gradlew :faq' if your build fails.\n")
boolean settingsupdated = verifySettingsGradle()
settingsupdated = verifyGitAttributes() || settingsupdated
if (settingsupdated)
throw new GradleException("Settings has been updated, please re-run task.")
if (project.file('.git/HEAD').isFile()) {
// In submodules, .git is a file pointing to the real git dir
if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) {
apply plugin: 'com.palantir.git-version'
}
@@ -115,6 +115,8 @@ propertyDefaultIfUnset("usesMixinDebug", project.usesMixins)
propertyDefaultIfUnset("forceEnableMixins", false)
propertyDefaultIfUnset("channel", "stable")
propertyDefaultIfUnset("mappingsVersion", "12")
propertyDefaultIfUnset("usesMavenPublishing", true)
propertyDefaultIfUnset("mavenPublishUrl", "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases")
propertyDefaultIfUnset("modrinthProjectId", "")
propertyDefaultIfUnset("modrinthRelations", "")
propertyDefaultIfUnset("curseForgeProjectId", "")
@@ -132,7 +134,7 @@ propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new
// this is meant to be set using the user wide property file. by default we do nothing.
propertyDefaultIfUnset("ideaOverrideBuildType", "") // Can be nothing, "gradle" or "idea"
project.extensions.add(Blowdryer, "Blowdryer", Blowdryer) // Make blowdryer available in "apply from:" scripts
project.extensions.add(com.diffplug.blowdryer.Blowdryer, "Blowdryer", com.diffplug.blowdryer.Blowdryer) // Make blowdryer available in "apply from:" scripts
if (!disableSpotless) {
apply plugin: 'com.diffplug.spotless'
apply from: Blowdryer.file('spotless.gradle')
@@ -201,6 +203,14 @@ configurations {
canBeConsumed = false
canBeResolved = false
}
create("devOnlyNonPublishable") {
description = "Runtime and compiletime dependencies that are not published alongside the jar (compileOnly + runtimeOnlyNonPublishable)"
canBeConsumed = false
canBeResolved = false
}
compileOnly.extendsFrom(devOnlyNonPublishable)
runtimeOnlyNonPublishable.extendsFrom(devOnlyNonPublishable)
}
if (enableModernJavaSyntax.toBoolean()) {
@@ -214,6 +224,8 @@ if (enableModernJavaSyntax.toBoolean()) {
dependencies {
annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0'
// workaround for https://github.com/bsideup/jabel/issues/174
annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0'
compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') {
transitive = false // We only care about the 1 annotation class
}
@@ -347,7 +359,27 @@ catch (Exception ignored) {
String identifiedVersion
String versionOverride = System.getenv("VERSION") ?: null
try {
identifiedVersion = versionOverride == null ? gitVersion() : versionOverride
// Produce a version based on the tag, or for branches something like 0.2.2-configurable-maven-and-extras.38+43090270b6-dirty
if (versionOverride == null) {
def gitDetails = versionDetails()
def isDirty = gitVersion().endsWith(".dirty") // No public API for this, isCleanTag has a different meaning
String branchName = gitDetails.branchName ?: (System.getenv('GIT_BRANCH') ?: 'git')
if (branchName.startsWith('origin/')) {
branchName = branchName.minus('origin/')
}
branchName = branchName.replaceAll("[^a-zA-Z0-9-]+", "-") // sanitize branch names for semver
identifiedVersion = gitDetails.lastTag ?: '${gitDetails.gitHash}'
if (gitDetails.commitDistance > 0) {
identifiedVersion += "-${branchName}.${gitDetails.commitDistance}+${gitDetails.gitHash}"
if (isDirty) {
identifiedVersion += "-dirty"
}
} else if (isDirty) {
identifiedVersion += "-${branchName}+${gitDetails.gitHash}-dirty"
}
} else {
identifiedVersion = versionOverride
}
}
catch (Exception ignored) {
out.style(Style.Failure).text(
@@ -369,9 +401,13 @@ if (identifiedVersion == versionOverride) {
group = "com.github.GTNewHorizons"
if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) {
archivesBaseName = customArchiveBaseName
base {
archivesName = customArchiveBaseName
}
} else {
archivesBaseName = modId
base {
archivesName = modId
}
}
@@ -399,7 +435,7 @@ minecraft {
username = developmentEnvironmentUserName.toString()
lwjgl3Version = "3.3.2-SNAPSHOT"
lwjgl3Version = "3.3.2"
// Enable assertions in the current mod
extraRunJvmArguments.add("-ea:${modGroup}")
@@ -455,10 +491,19 @@ sourceSets {
}
}
if (file('addon.gradle').exists()) {
if (file('addon.gradle.kts').exists()) {
apply from: 'addon.gradle.kts'
} else if (file('addon.gradle').exists()) {
apply from: 'addon.gradle'
}
// File for local tweaks not commited to Git
if (file('addon.local.gradle.kts').exists()) {
apply from: 'addon.local.gradle.kts'
} else if (file('addon.local.gradle').exists()) {
apply from: 'addon.local.gradle'
}
// Allow unsafe repos but warn
repositories.configureEach { repo ->
if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) {
@@ -469,7 +514,14 @@ repositories.configureEach { repo ->
}
}
apply from: 'repositories.gradle'
if (file('repositories.gradle.kts').exists()) {
apply from: 'repositories.gradle.kts'
} else if (file('repositories.gradle').exists()) {
apply from: 'repositories.gradle'
} else {
logger.error("Neither repositories.gradle.kts nor repositories.gradle was found, make sure you extracted the full ExampleMod template.")
throw new RuntimeException("Missing repositories.gradle[.kts]")
}
configurations {
runtimeClasspath.extendsFrom(runtimeOnlyNonPublishable)
@@ -510,9 +562,6 @@ repositories {
maven {
name 'Overmind forge repo mirror'
url 'https://gregtech.overminddl1.com/'
mavenContent {
excludeGroup("net.minecraftforge") // missing the `universal` artefact
}
}
maven {
name = "GTNH Maven"
@@ -527,13 +576,28 @@ repositories {
}
}
if (includeWellKnownRepositories.toBoolean()) {
maven {
name "CurseMaven"
url "https://cursemaven.com"
content {
exclusiveContent {
forRepository {
maven {
name "CurseMaven"
url "https://cursemaven.com"
}
}
filter {
includeGroup "curse.maven"
}
}
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
filter {
includeGroup "maven.modrinth"
}
}
maven {
name = "ic2"
url = "https://maven.ic2.player.to/"
@@ -559,9 +623,12 @@ repositories {
def mixinProviderGroup = "io.github.legacymoddingmc"
def mixinProviderModule = "unimixins"
def mixinProviderVersion = "0.1.6"
def mixinProviderVersion = "0.1.7.1"
def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}"
def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev"
ext.mixinProviderSpec = mixinProviderSpec
def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json'
dependencies {
if (usesMixins.toBoolean()) {
@@ -574,7 +641,7 @@ dependencies {
}
}
if (usesMixins.toBoolean()) {
implementation(mixinProviderSpec)
implementation(modUtils.enableMixins(mixinProviderSpec, mixingConfigRefMap))
} else if (forceEnableMixins.toBoolean()) {
runtimeOnlyNonPublishable(mixinProviderSpec)
}
@@ -600,12 +667,32 @@ configurations.all {
}
}
apply from: 'dependencies.gradle'
dependencies {
constraints {
def minGtnhLibVersion = "0.0.13"
implementation("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") {
because("fixes duplicate mod errors in java 17 configurations using old gtnhlib")
}
runtimeOnly("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") {
because("fixes duplicate mod errors in java 17 configurations using old gtnhlib")
}
devOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") {
because("fixes duplicate mod errors in java 17 configurations using old gtnhlib")
}
runtimeOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") {
because("fixes duplicate mod errors in java 17 configurations using old gtnhlib")
}
}
}
def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json'
def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins'
def refMap = "${mixinTmpDir}" + File.separator + mixingConfigRefMap
def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg"
if (file('dependencies.gradle.kts').exists()) {
apply from: 'dependencies.gradle.kts'
} else if (file('dependencies.gradle').exists()) {
apply from: 'dependencies.gradle'
} else {
logger.error("Neither dependencies.gradle.kts nor dependencies.gradle was found, make sure you extracted the full ExampleMod template.")
throw new RuntimeException("Missing dependencies.gradle[.kts]")
}
tasks.register('generateAssets') {
group = "GTNH Buildscript"
@@ -637,46 +724,17 @@ tasks.register('generateAssets') {
}
if (usesMixins.toBoolean()) {
tasks.named("reobfJar", ReobfuscatedJar).configure {
extraSrgFiles.from(mixinSrg)
}
tasks.named("processResources").configure {
dependsOn("generateAssets")
}
tasks.named("compileJava", JavaCompile).configure {
doFirst {
new File(mixinTmpDir).mkdirs()
}
options.compilerArgs += [
"-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}",
"-AoutSrgFile=${mixinSrg}",
"-AoutRefMapFile=${refMap}",
// Elan: from what I understand they are just some linter configs so you get some warning on how to properly code
"-XDenableSunApiLintControl",
"-XDignore.symbol.file"
]
}
pluginManager.withPlugin('org.jetbrains.kotlin.kapt') {
kapt {
correctErrorTypes = true
javacOptions {
option("-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}")
option("-AoutSrgFile=$mixinSrg")
option("-AoutRefMapFile=$refMap")
}
}
tasks.configureEach { task ->
if (task.name == "kaptKotlin") {
task.doFirst {
new File(mixinTmpDir).mkdirs()
}
}
}
}
}
tasks.named("processResources", ProcessResources).configure {
@@ -694,7 +752,6 @@ tasks.named("processResources", ProcessResources).configure {
}
if (usesMixins.toBoolean()) {
from refMap
dependsOn("compileJava", "compileScala")
}
}
@@ -713,16 +770,16 @@ ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies"
}
dependencies {
def lwjgl3ifyVersion = '1.3.3'
def lwjgl3ifyVersion = '1.4.0'
def asmVersion = '9.4'
if (modId != 'lwjgl3ify') {
java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}")
}
if (modId != 'hodgepodge') {
java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.4')
java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.26')
}
java17PatchDependencies('net.minecraft:launchwrapper:1.15') {transitive = false}
java17PatchDependencies('net.minecraft:launchwrapper:1.17.2') {transitive = false}
java17PatchDependencies("org.ow2.asm:asm:${asmVersion}")
java17PatchDependencies("org.ow2.asm:asm-commons:${asmVersion}")
java17PatchDependencies("org.ow2.asm:asm-tree:${asmVersion}")
@@ -793,7 +850,7 @@ public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask {
public boolean setEnableHotswap(boolean enable) { enableHotswap = enable }
@Inject
public RunHotswappableMinecraftTask(Side side, String superTask, org.gradle.api.invocation.Gradle gradle) {
public RunHotswappableMinecraftTask(Distribution side, String superTask, org.gradle.api.invocation.Gradle gradle) {
super(side, gradle)
this.lwjglVersion = 3
@@ -802,7 +859,7 @@ public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask {
this.extraJvmArgs.addAll(project.provider(() -> enableHotswap ? project.hotswapJvmArgs : []))
this.classpath(project.java17PatchDependenciesCfg)
if (side == Side.CLIENT) {
if (side == Distribution.CLIENT) {
this.classpath(project.minecraftTasks.lwjgl3Configuration)
}
// Use a raw provider instead of map to not create a dependency on the task
@@ -812,9 +869,21 @@ public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask {
}
this.classpath(project.java17DependenciesCfg)
}
public void setup(Project project) {
super.setup(project)
if (project.usesMixins.toBoolean()) {
this.extraJvmArgs.addAll(project.provider(() -> {
def mixinCfg = project.configurations.detachedConfiguration(project.dependencies.create(project.mixinProviderSpec))
mixinCfg.canBeConsumed = false
mixinCfg.transitive = false
enableHotswap ? ["-javaagent:" + mixinCfg.singleFile.absolutePath] : []
}))
}
}
}
def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Side.CLIENT, "runClient")
def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient")
runClient17Task.configure {
setup(project)
group = "Modded Minecraft"
@@ -825,7 +894,7 @@ runClient17Task.configure {
userUUID = minecraft.userUUID
}
def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Side.SERVER, "runServer")
def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer")
runServer17Task.configure {
setup(project)
group = "Modded Minecraft"
@@ -866,11 +935,6 @@ tasks.named("jar", Jar).configure {
}
if (usesShadowedDependencies.toBoolean()) {
tasks.register('relocateShadowJar', ConfigureShadowRelocation) {
target = tasks.shadowJar
prefix = modGroup + ".shadow"
enabled = relocateShadowedDependencies.toBoolean()
}
tasks.named("shadowJar", ShadowJar).configure {
manifest {
attributes(getManifestAttributes())
@@ -886,7 +950,8 @@ if (usesShadowedDependencies.toBoolean()) {
]
archiveClassifier.set('dev')
if (relocateShadowedDependencies.toBoolean()) {
dependsOn(relocateShadowJar)
relocationPrefix = modGroup + ".shadow"
enableRelocation = true
}
}
configurations.runtimeElements.outgoing.artifacts.clear()
@@ -960,6 +1025,9 @@ idea {
}
}
runConfigurations {
"0. Build and Test"(Gradle) {
taskNames = ["build"]
}
"1. Run Client"(Gradle) {
taskNames = ["runClient"]
}
@@ -1079,6 +1147,14 @@ tasks.named("processIdeaSettings").configure {
dependsOn("injectTags")
}
tasks.named("ideVirtualMainClasses").configure {
// Make IntelliJ "Build project" build the mod jars
dependsOn("jar", "reobfJar")
if (!disableSpotless) {
dependsOn("spotlessCheck")
}
}
// workaround variable hiding in pom processing
def projectConfigs = project.configurations
@@ -1099,12 +1175,14 @@ publishing {
}
repositories {
maven {
url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases"
allowInsecureProtocol = true
credentials {
username = System.getenv("MAVEN_USER") ?: "NONE"
password = System.getenv("MAVEN_PASSWORD") ?: "NONE"
if (usesMavenPublishing.toBoolean()) {
maven {
url = mavenPublishUrl
allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven
credentials {
username = System.getenv("MAVEN_USER") ?: "NONE"
password = System.getenv("MAVEN_PASSWORD") ?: "NONE"
}
}
}
}
@@ -1219,7 +1297,7 @@ def addCurseForgeRelation(String type, String name) {
// Updating
def buildscriptGradleVersion = "8.0.2"
def buildscriptGradleVersion = "8.2.1"
tasks.named('wrapper', Wrapper).configure {
gradleVersion = buildscriptGradleVersion
@@ -1251,6 +1329,23 @@ if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISA
}
}
// If you want to add more cases to this task, implement them as arguments if total amount to print gets too large
tasks.register('faq') {
group = 'GTNH Buildscript'
description = 'Prints frequently asked questions about building a project'
doLast {
print("If your build fails to fetch dependencies, run './gradlew updateDependencies'. " +
"Or you can manually check if the versions are still on the distributing sites - " +
"the links can be found in repositories.gradle and build.gradle:repositories, " +
"but not build.gradle:buildscript.repositories - those ones are for gradle plugin metadata.\n\n" +
"If your build fails to recognize the syntax of new Java versions, enable Jabel in your " +
"gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties. " +
"However, keep in mind that Jabel enables only syntax features, but not APIs that were introduced in " +
"Java 9 or later.")
}
}
static URL availableBuildScriptUrl() {
new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/build.gradle")
}
@@ -1308,8 +1403,14 @@ boolean isNewBuildScriptVersionAvailable() {
String currentBuildScript = getFile("build.gradle").getText()
String currentBuildScriptHash = getVersionHash(currentBuildScript)
String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText()
String availableBuildScriptHash = getVersionHash(availableBuildScript)
String availableBuildScriptHash
try {
String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText()
availableBuildScriptHash = getVersionHash(availableBuildScript)
} catch (IOException e) {
logger.warn("Could not check for buildscript update availability: {}", e.message)
return false
}
boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash
return !isUpToDate
@@ -1388,7 +1489,7 @@ static int replaceParams(File file, Map<String, String> params) {
return 0
}
// Dependency Deobfuscation
// Dependency Deobfuscation (Deprecated, use the new RFG API documented in dependencies.gradle)
def deobf(String sourceURL) {
try {
@@ -1430,11 +1531,7 @@ def deobfMaven(String repoURL, String mavenDep) {
}
def deobfCurse(String curseDep) {
try {
return deobfMaven("https://www.cursemaven.com/", "curse.maven:$curseDep")
} catch (Exception ignored) {
out.style(Style.Failure).println("Failed to get $curseDep from cursemaven.")
}
return dependencies.rfg.deobf("curse.maven:$curseDep")
}
// The method above is to be preferred. Use this method if the filename is not at the end of the URL.
@@ -1442,34 +1539,7 @@ def deobf(String sourceURL, String rawFileName) {
String bon2Version = "2.5.1"
String fileName = URLDecoder.decode(rawFileName, "UTF-8")
String cacheDir = "$project.gradle.gradleUserHomeDir/caches"
String bon2Dir = "$cacheDir/forge_gradle/deobf"
String bon2File = "$bon2Dir/BON2-${bon2Version}.jar"
String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar"
String deobfFile = "$cacheDir/modules-2/files-2.1/${fileName}-deobf.jar"
if (file(deobfFile).exists()) {
return files(deobfFile)
}
String mappingsVer
String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/'
if (remoteMappings) {
String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion"
String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip"
zipMappings(mappingsZIP, remoteMappings, bon2Dir)
mappingsVer = "snapshot_$id"
} else {
mappingsVer = "${channel}_$mappingsVersion"
}
download.run {
src "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases/com/github/parker8283/BON2/$bon2Version-CUSTOM/BON2-$bon2Version-CUSTOM-all.jar"
dest bon2File
quiet true
overwrite false
}
download.run {
src sourceURL
@@ -1477,50 +1547,8 @@ def deobf(String sourceURL, String rawFileName) {
quiet true
overwrite false
}
exec {
commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', minecraftVersion, '--mappingsVer', mappingsVer, '--notch'
workingDir bon2Dir
standardOutput = new FileOutputStream("${deobfFile}.log")
}
return files(deobfFile)
return dependencies.rfg.deobf(files(obfFile))
}
def zipMappings(String zipPath, String url, String bon2Dir) {
File zipFile = new File(zipPath)
if (zipFile.exists()) {
return
}
String fieldsCache = "$bon2Dir/data/fields.csv"
String methodsCache = "$bon2Dir/data/methods.csv"
download.run {
src "${url}fields.csv"
dest fieldsCache
quiet true
}
download.run {
src "${url}methods.csv"
dest methodsCache
quiet true
}
zipFile.getParentFile().mkdirs()
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))
zos.putNextEntry(new ZipEntry("fields.csv"))
Files.copy(Paths.get(fieldsCache), zos)
zos.closeEntry()
zos.putNextEntry(new ZipEntry("methods.csv"))
Files.copy(Paths.get(methodsCache), zos)
zos.closeEntry()
zos.close()
}
// Helper methods
def checkPropertyExists(String propertyName) {
@@ -1547,3 +1575,17 @@ def getSecondaryArtifacts() {
if (apiPackage) secondaryArtifacts += [apiJar]
return secondaryArtifacts
}
// For easier scripting of things that require variables defined earlier in the buildscript
if (file('addon.late.gradle.kts').exists()) {
apply from: 'addon.late.gradle.kts'
} else if (file('addon.late.gradle').exists()) {
apply from: 'addon.late.gradle'
}
// File for local tweaks not commited to Git
if (file('addon.late.local.gradle.kts').exists()) {
apply from: 'addon.late.local.gradle.kts'
} else if (file('addon.late.local.gradle').exists()) {
apply from: 'addon.late.local.gradle'
}
+3 -3
View File
@@ -1,7 +1,7 @@
// Add your dependencies here
dependencies {
api('com.github.GTNewHorizons:CodeChickenLib:1.1.6:dev')
api('com.github.GTNewHorizons:CodeChickenCore:1.1.10:dev')
shadowImplementation('org.apache.commons:commons-csv:1.9.0')
api('com.github.GTNewHorizons:CodeChickenLib:1.1.8:dev')
api('com.github.GTNewHorizons:CodeChickenCore:1.1.11:dev')
shadowImplementation('org.apache.commons:commons-csv:1.10.0')
}
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored
+4 -3
View File
@@ -85,9 +85,6 @@ done
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# 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"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then
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, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
-11
View File
@@ -1,15 +1,4 @@
// Add any additional repositiroes for your dependencies here
repositories {
mavenCentral()
maven {
name 'GTNH Maven'
url 'http://jenkins.usrv.eu:8081/nexus/content/groups/public/'
}
maven {
url 'https://cursemaven.com'
content {
includeGroup 'curse.maven'
}
}
}
+3
View File
@@ -26,3 +26,6 @@ blowdryerSetup {
github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.2.0')
//devLocal '.' // Use this when testing config updates locally
}
rootProject.name = "NotEnoughItems"
@@ -0,0 +1,31 @@
package codechicken.nei;
import java.util.HashMap;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.gui.inventory.GuiContainer;
import codechicken.nei.api.API;
import codechicken.nei.api.IBookmarkContainerHandler;
public class BookmarkContainerInfo {
private static final HashMap<Class<? extends GuiContainer>, IBookmarkContainerHandler> handlerMap = new HashMap<>();
public static void registerBookmarkContainerHandler(Class<? extends GuiContainer> classz,
IBookmarkContainerHandler handler) {
handlerMap.put(classz, handler);
}
public static boolean hasBookmarkContainerHandler(Class<? extends GuiContainer> classz) {
return handlerMap.containsKey(classz);
}
public static IBookmarkContainerHandler getBookmarkContainerHandler(GuiContainer gui) {
return handlerMap.get(gui.getClass());
}
public static void load() {
API.registerBookmarkContainerHandler(GuiChest.class, new DefaultBookmarkContainerHandler());
}
}
@@ -2,6 +2,7 @@ package codechicken.nei;
import static codechicken.lib.gui.GuiDraw.drawRect;
import static codechicken.lib.gui.GuiDraw.getMousePosition;
import static codechicken.nei.NEIClientUtils.getGuiContainer;
import static codechicken.nei.NEIClientUtils.translate;
import java.awt.Point;
@@ -24,20 +25,21 @@ import net.minecraft.nbt.NBTTagCompound;
import org.apache.commons.io.IOUtils;
import org.lwjgl.opengl.GL11;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import codechicken.core.CommonUtils;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.ItemPanel.ItemPanelSlot;
import codechicken.nei.api.IBookmarkContainerHandler;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.recipe.BookmarkRecipeId;
import codechicken.nei.recipe.StackInfo;
import codechicken.nei.util.NBTJson;
import codechicken.nei.util.ReadableNumberConverter;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
public class BookmarkPanel extends PanelWidget {
protected File bookmarkFile;
@@ -47,6 +49,7 @@ public class BookmarkPanel extends PanelWidget {
public Button namespacePrev;
public Button namespaceNext;
public Button pullBookmarkedItems;
public Label namespaceLabel;
protected List<BookmarkGrid> namespaces = new ArrayList<>();
@@ -84,6 +87,10 @@ public class BookmarkPanel extends PanelWidget {
protected boolean[] todoSpaces;
protected int todoItemsCount = 0;
public BookmarkGrid() {
this.setShowRecipeTooltips(true);
}
public void setViewMode(BookmarkViewMode mode) {
if (viewMode == mode) {
return;
@@ -413,6 +420,21 @@ public class BookmarkPanel extends PanelWidget {
}
};
pullBookmarkedItems = new Button("Pull") {
public boolean onButtonPress(boolean rightclick) {
if (rightclick) {
return false;
}
return pullBookmarkItems();
}
@Override
public String getRenderLabel() {
return "P";
}
};
namespaces.add(new BookmarkGrid());
grid = namespaces.get(activeNamespaceIndex);
}
@@ -464,7 +486,7 @@ public class BookmarkPanel extends PanelWidget {
final ItemStack normalizedA = StackInfo.loadFromNBT(nbTagA);
BookmarkRecipeId recipeId = null;
if (handlerName != "" && ingredients != null && !ingredients.isEmpty()) {
if (handlerName != "" && ingredients != null) {
recipeId = new BookmarkRecipeId(handlerName, ingredients);
}
@@ -474,7 +496,7 @@ public class BookmarkPanel extends PanelWidget {
BGrid.removeRecipe(idx, saveIngredients);
} else {
if (saveIngredients && handlerName != "" && ingredients != null && !ingredients.isEmpty()) {
if (saveIngredients && handlerName != "" && ingredients != null) {
final Map<NBTTagCompound, Integer> unique = new HashMap<>();
final ArrayList<NBTTagCompound> sorted = new ArrayList<>();
@@ -816,9 +838,9 @@ public class BookmarkPanel extends PanelWidget {
final int center = leftBorder + Math.max(0, (rightBorder - leftBorder) / 2);
int labelWidth = 2;
namespacePrev.h = namespaceNext.h = BUTTON_SIZE;
namespacePrev.w = namespaceNext.w = BUTTON_SIZE;
namespacePrev.y = namespaceNext.y = y + h - BUTTON_SIZE;
namespacePrev.h = namespaceNext.h = pullBookmarkedItems.h = BUTTON_SIZE;
namespacePrev.w = namespaceNext.w = pullBookmarkedItems.w = BUTTON_SIZE;
namespacePrev.y = namespaceNext.y = pullBookmarkedItems.y = y + h - BUTTON_SIZE;
if (rightBorder - leftBorder >= 70) {
labelWidth = 36;
@@ -833,6 +855,7 @@ public class BookmarkPanel extends PanelWidget {
namespacePrev.x = center - labelWidth / 2 - 2 - namespacePrev.w;
namespaceNext.x = center + labelWidth / 2 + 2;
pullBookmarkedItems.x = center + 2 * labelWidth / 2 + 2;
return BUTTON_SIZE + 2;
}
@@ -845,6 +868,9 @@ public class BookmarkPanel extends PanelWidget {
LayoutManager.addWidget(namespacePrev);
LayoutManager.addWidget(namespaceNext);
LayoutManager.addWidget(namespaceLabel);
if (BookmarkContainerInfo.getBookmarkContainerHandler(getGuiContainer()) != null) {
LayoutManager.addWidget(pullBookmarkedItems);
}
}
}
@@ -1031,6 +1057,10 @@ public class BookmarkPanel extends PanelWidget {
.contains(mx, my)) {
tooltip.add(translate("bookmark.viewmode.toggle.tip"));
}
if (new Rectangle4i(pullBookmarkedItems.x, pullBookmarkedItems.y, pullBookmarkedItems.w, pullBookmarkedItems.h)
.contains(mx, my) && BookmarkContainerInfo.getBookmarkContainerHandler(getGuiContainer()) != null) {
tooltip.add(translate("bookmark.pullBookmarkedItems.tip"));
}
return super.handleTooltip(mx, my, tooltip);
}
@@ -1080,6 +1110,10 @@ public class BookmarkPanel extends PanelWidget {
final BookmarkRecipeId recipeId = BGrid.getRecipeId(slot.slotIndex);
final boolean addFullRecipe = NEIClientUtils.shiftKey();
if (NEIClientUtils.altKey()) {
shift *= slot.item.getMaxStackSize();
}
if (addFullRecipe) {
BookmarkStackMeta iMeta;
@@ -1118,4 +1152,14 @@ public class BookmarkPanel extends PanelWidget {
}
}
}
public boolean pullBookmarkItems() {
IBookmarkContainerHandler containerHandler = BookmarkContainerInfo
.getBookmarkContainerHandler(getGuiContainer());
if (containerHandler == null) {
return false;
}
containerHandler.pullBookmarkItemsFromContainer(getGuiContainer(), ((BookmarkGrid) grid).realItems);
return true;
}
}
@@ -9,9 +9,6 @@ import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -37,6 +34,8 @@ import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.io.IOUtils;
import com.google.common.collect.Lists;
import codechicken.core.ClientUtils;
import codechicken.core.GuiModListScroll;
import codechicken.lib.packet.PacketCustom;
@@ -44,25 +43,14 @@ import codechicken.nei.api.API;
import codechicken.nei.api.ItemInfo;
import codechicken.nei.recipe.GuiRecipeTab;
import codechicken.nei.recipe.StackInfo;
import com.google.common.collect.Lists;
import cpw.mods.fml.client.CustomModLoadingErrorDisplayException;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.TickEvent;
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
public class ClientHandler {
private static String[] defaultSerialHandlers = {
"WayofTime.alchemicalWizardry.client.nei.NEIAlchemyRecipeHandler" };
private static String[] defaultHeightHackHandlerRegex = { "buildcraft.compat.nei.*",
"cofh.thermalexpansion.plugins.nei.handlers.*", "crazypants.enderio.nei.*",
"forestry.factory.recipes.nei.*", "ic2.neiIntegration.core.recipehandler.*", "mariculture.plugins.nei.*",
"redgear.brewcraft.plugins.nei.*", "tconstruct.plugins.nei.*",
"WayofTime.alchemicalWizardry.client.nei.*", };
private static String[] defaultHandlerOrdering = {
"# Each line in this file should either be a comment (starts with '#') or an ordering.",
"# Ordering lines are <handler ID>,<ordering number>.",
@@ -166,16 +154,19 @@ public class ClientHandler {
if (!file.exists()) {
try (FileWriter writer = new FileWriter(file)) {
NEIClientConfig.logger.info("Creating default serial handlers list {}", file);
Collection<String> toSave = Loader.isModLoaded("dreamcraft") ? Collections.singletonList("")
: Arrays.asList(defaultSerialHandlers);
IOUtils.writeLines(toSave, "\n", writer);
URL defaultSerialHandlersResource = ClientHandler.class
.getResource("/assets/nei/cfg/serialhandlers.cfg");
if (defaultSerialHandlersResource != null) {
IOUtils.copy(defaultSerialHandlersResource.openStream(), writer);
}
} catch (IOException e) {
NEIClientConfig.logger.error("Failed to save default serial handlers list to file {}", file, e);
}
}
try (FileReader reader = new FileReader(file)) {
NEIClientConfig.logger.info("Loading serial handlers from file {}", file);
NEIClientConfig.serialHandlers = new HashSet<>(IOUtils.readLines(reader));
NEIClientConfig.serialHandlers = IOUtils.readLines(reader).stream().filter((line) -> !line.startsWith("#"))
.collect(Collectors.toCollection(HashSet::new));
} catch (IOException e) {
NEIClientConfig.logger.error("Failed to load serial handlers from file {}", file, e);
}
@@ -186,8 +177,11 @@ public class ClientHandler {
if (!file.exists()) {
try (FileWriter writer = new FileWriter(file)) {
NEIClientConfig.logger.info("Creating default height hack handlers list {}", file);
Collection<String> toSave = Arrays.asList(defaultHeightHackHandlerRegex);
IOUtils.writeLines(toSave, "\n", writer);
URL defaultHeightHackHandlersResource = ClientHandler.class
.getResource("/assets/nei/cfg/heighthackhandlers.cfg");
if (defaultHeightHackHandlersResource != null) {
IOUtils.copy(defaultHeightHackHandlersResource.openStream(), writer);
}
} catch (IOException e) {
NEIClientConfig.logger.error("Failed to save default height hack handlers list to file {}", file, e);
}
@@ -195,7 +189,8 @@ public class ClientHandler {
try (FileReader reader = new FileReader(file)) {
NEIClientConfig.logger.info("Loading height hack handlers from file {}", file);
NEIClientConfig.heightHackHandlerRegex = IOUtils.readLines(reader).stream().map(Pattern::compile)
NEIClientConfig.heightHackHandlerRegex = IOUtils.readLines(reader).stream()
.filter((line) -> !line.startsWith("#")).map(Pattern::compile)
.collect(Collectors.toCollection(HashSet::new));
} catch (IOException e) {
NEIClientConfig.logger.error("Failed to load height hack handlers from file {}", file, e);
@@ -276,7 +271,11 @@ public class ClientHandler {
if (!NEIClientConfig.isEnabled()) return;
KeyManager.tickKeyStates();
/*
* NEI plugins are loaded in a separate thread. Make sure loading them has finished otherwise a CME might
* occur in KeyManager if a plugin calls API.addKeyBind() during initialization.
*/
if (NEIClientConfig.isLoaded()) KeyManager.tickKeyStates();
NEIController.updateUnlimitedItems(mc.thePlayer.inventory);
if (mc.currentScreen == null) NEIController.processCreativeCycling(mc.thePlayer.inventory);
@@ -0,0 +1,47 @@
package codechicken.nei;
import java.util.ArrayList;
import java.util.LinkedList;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.item.ItemStack;
import codechicken.nei.api.IBookmarkContainerHandler;
public class DefaultBookmarkContainerHandler implements IBookmarkContainerHandler {
@Override
public void pullBookmarkItemsFromContainer(GuiContainer guiContainer, ArrayList<ItemStack> bookmarkItems) {
FastTransferManager manager = new FastTransferManager();
LinkedList<ItemStack> containerStacks = manager.saveContainer(guiContainer.inventorySlots);
for (ItemStack bookmarkItem : bookmarkItems) {
int bookmarkSizeBackup = bookmarkItem.stackSize;
for (int i = 0; i < containerStacks.size() - 4 * 9; i++) { // Last 36 slots are player inventory
ItemStack containerItem = containerStacks.get(i);
if (containerItem == null) {
continue;
}
if (bookmarkItem.isItemEqual(containerItem)) {
if (bookmarkItem.stackSize <= 0) {
break;
}
int transferAmount = Math.min(bookmarkItem.stackSize, containerItem.stackSize);
manager.transferItems(guiContainer, i, transferAmount);
bookmarkItem.stackSize -= transferAmount;
if (bookmarkItem.stackSize == 0) {
break;
}
}
}
bookmarkItem.stackSize = bookmarkSizeBackup;
}
}
}
@@ -184,6 +184,12 @@ public class FastTransferManager {
moveOutputSet(window, fromSlot, toSlot);
}
public void transferItems(GuiContainer window, int fromSlot, int itemCount) {
for (int i = 0; i < itemCount; i++) {
transferItem(window, fromSlot);
}
}
public void moveOutputSet(GuiContainer window, int fromSlot, int toSlot) {
if (NEIClientUtils.getHeldItem() != null) return;
+3 -3
View File
@@ -13,15 +13,15 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import codechicken.nei.ThreadOperationTimer.TimeoutException;
import codechicken.nei.api.ItemFilter;
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
import codechicken.nei.api.ItemInfo;
import codechicken.nei.guihook.GuiContainerManager;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
public class ItemList {
/**
@@ -22,8 +22,8 @@ import net.minecraftforge.client.MinecraftForgeClient;
public class ItemMobSpawner extends ItemBlock {
private static Map<Integer, EntityLiving> entityHashMap;
private static Map<Integer, String> IDtoNameMap;
private static final Map<Integer, EntityLiving> entityHashMap = new HashMap<>();
private static final Map<Integer, String> IDtoNameMap = new HashMap<>();
public static int idPig;
private static boolean loaded;
@@ -32,9 +32,6 @@ public class ItemMobSpawner extends ItemBlock {
hasSubtypes = true;
MinecraftForgeClient.registerItemRenderer(this, new SpawnerRenderer());
entityHashMap = new HashMap<>();
IDtoNameMap = new HashMap<>();
}
/**
@@ -1,27 +1,37 @@
package codechicken.nei;
import static codechicken.lib.gui.GuiDraw.drawRect;
import static codechicken.lib.gui.GuiDraw.getMousePosition;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.shader.Framebuffer;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.ItemPanel.ItemPanelSlot;
import codechicken.nei.api.GuiInfo;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.recipe.BookmarkRecipeId;
import codechicken.nei.recipe.GuiCraftingRecipe;
import codechicken.nei.recipe.GuiRecipe;
import codechicken.nei.recipe.StackInfo;
public class ItemsGrid {
@@ -43,6 +53,7 @@ public class ItemsGrid {
protected int rows;
protected int columns;
protected boolean showRecipeTooltips = false;
protected boolean[] invalidSlotMap;
@@ -150,6 +161,10 @@ public class ItemsGrid {
refreshBuffer = true;
}
public void setShowRecipeTooltips(boolean show) {
this.showRecipeTooltips = show;
}
public void refresh(GuiContainer gui) {
updateGuiOverlapSlots(gui);
shiftPage(0);
@@ -244,6 +259,127 @@ public class ItemsGrid {
}
}
private int recipeTooltipSlotIdx = -1;
private int recipeTooltipLines = 2;
private Runnable recipeTooltipUpdater = null;
private GuiRecipe<?> recipeTooltipGui = null;
public void update() {
if (recipeTooltipUpdater != null) {
recipeTooltipUpdater.run();
recipeTooltipUpdater = null;
}
if (recipeTooltipGui != null) {
recipeTooltipGui.updateAsTooltip();
}
}
private static <T> List<T> listOrEmptyList(final List<T> listOrNull) {
return listOrNull == null ? Collections.emptyList() : listOrNull;
}
private void drawRecipeTooltip(int mousex, int mousey, List<String> itemTooltip) {
if (!NEIClientConfig.isLoaded()) {
return;
}
final Minecraft mc = Minecraft.getMinecraft();
ItemPanelSlot focused = getSlotMouseOver(mousex, mousey);
if (focused == null) {
recipeTooltipSlotIdx = -1;
recipeTooltipGui = null;
return;
}
final List<Integer> mask = getMask();
int slotIdx = -1;
for (int i = 0; i < mask.size(); i++) {
if (mask.get(i) == null) {
continue;
}
if (focused.slotIndex != mask.get(i)) {
continue;
}
slotIdx = i;
break;
}
if (slotIdx == -1) {
recipeTooltipSlotIdx = -1;
recipeTooltipGui = null;
return;
}
final Point mouseover = getMousePosition();
final ItemPanelSlot panelSlot = ItemPanels.bookmarkPanel.getSlotMouseOver(mouseover.x, mouseover.y);
final BookmarkRecipeId recipeId;
if (panelSlot != null) {
recipeId = ItemPanels.bookmarkPanel.getBookmarkRecipeId(panelSlot.slotIndex);
} else {
recipeId = ItemPanels.bookmarkPanel.getBookmarkRecipeId(focused.item);
}
if (recipeId == null) {
return;
}
if (slotIdx != recipeTooltipSlotIdx) {
recipeTooltipSlotIdx = slotIdx;
recipeTooltipGui = null;
recipeTooltipUpdater = () -> {
recipeTooltipGui = GuiCraftingRecipe.createRecipeGui("item", false, false, false, focused.item);
if (recipeTooltipGui != null) {
recipeTooltipGui.limitToOneRecipe();
recipeTooltipGui.initGui(true);
recipeTooltipGui.guiTop = 0;
recipeTooltipGui.guiLeft = 0;
}
recipeTooltipLines = Math.max(1, itemTooltip.size());
};
}
if (recipeTooltipGui == null) {
return;
}
GL11.glPushMatrix();
final float tooltipYOffset;
if (mousey - marginTop > height / 2) {
tooltipYOffset = mousey - recipeTooltipGui.getHeightAsWidget() + 8;
} else {
tooltipYOffset = mousey + ((recipeTooltipLines < 2) ? 1 : 3 + ((recipeTooltipLines - 1) * 10));
}
GL11.glTranslatef(mousex, tooltipYOffset, 500);
final GuiContainer gui;
if (mc.currentScreen instanceof GuiRecipe) {
gui = ((GuiRecipe<?>) mc.currentScreen).firstGui;
} else if (mc.currentScreen instanceof GuiContainer) {
gui = (GuiContainer) mc.currentScreen;
} else {
gui = null;
}
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
RenderHelper.disableStandardItemLighting();
recipeTooltipGui.drawGuiContainerBackgroundLayer(0.0f, -100, -100);
GL11.glPopAttrib();
if (recipeTooltipGui.slotcontainer != null) {
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
RenderHelper.enableGUIStandardItemLighting();
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
@SuppressWarnings("unchecked")
List<Slot> slots = (List<Slot>) recipeTooltipGui.slotcontainer.inventorySlots;
for (Slot slot : slots) {
if (slot != null && slot.getStack() != null) {
GuiContainerManager.drawItem(slot.xDisplayPosition, slot.yDisplayPosition, slot.getStack());
}
}
GL11.glPopAttrib();
}
recipeTooltipGui.drawGuiContainerForegroundLayer(-100, -100);
for (GuiButton btn : recipeTooltipGui.getOverlayButtons()) {
btn.drawButton(mc, -100, -100);
}
GL11.glPopMatrix();
}
protected void drawSlotOutline(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
if (focused != null && focused.slotIndex == slotIdx) {
drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555); // highlight
@@ -329,6 +465,16 @@ public class ItemsGrid {
}
}
public void postDrawTooltips(int mousex, int mousey, List<String> tooltip) {
if (NEIClientConfig.showRecipeTooltips() && showRecipeTooltips) {
try {
drawRecipeTooltip(mousex, mousey, tooltip);
} catch (Exception e) {
NEIClientConfig.logger.warn("Cannot draw recipe tooltip", e);
}
}
}
public void setVisible() {
if (getItems().isEmpty() && getMessageOnEmpty() != null) {
LayoutManager.addWidget(messageLabel);
@@ -226,6 +226,10 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
return true;
}
if (NEIClientConfig.isKeyHashDown("gui.bookmark_pull_items")) {
return bookmarkPanel.pullBookmarkItems();
}
if (isEnabled() && !isHidden()) {
for (Widget widget : controlWidgets) if (inputFocused == null) widget.lastKeyTyped(keyID, keyChar);
}
@@ -280,6 +284,13 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
}
}
@Override
public void postRenderTooltips(GuiContainer gui, int mousex, int mousey, List<String> tooltip) {
if (!isHidden() && isEnabled()) {
for (Widget widget : drawWidgets) widget.postDrawTooltips(mousex, mousey, tooltip);
}
}
@Override
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
@@ -531,8 +542,8 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
}
@Override
public String getButtonTip() {
return getTimeTip(NEIActions.timeZones[zone], state);
public void addTooltips(List<String> tooltip) {
addTimeTip(NEIActions.timeZones[zone], state, tooltip);
}
};
}
@@ -565,9 +576,13 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
return translate("inventory." + name + "." + sfx);
}
private static String getTimeTip(String name, int state) {
String sfx = (state & 0x3) == 2 ? "enable" : "set";
return translate("inventory." + name + "." + sfx);
private static void addTimeTip(String name, int state, List<String> tooltip) {
if ((state & 0x3) == 2) {
tooltip.add(translate("inventory." + name + ".enable"));
} else {
tooltip.add(translate("inventory." + name + ".set"));
tooltip.add(EnumChatFormatting.GRAY + translate("inventory." + name + ".disable"));
}
}
private static boolean handleDisabledButtonPress(String ident, boolean rightclick) {
+33 -31
View File
@@ -1,5 +1,7 @@
package codechicken.nei;
import static codechicken.nei.PacketIDs.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.item.ItemStack;
@@ -20,37 +22,37 @@ public class NEICPH implements IClientPacketHandler {
@Override
public void handlePacket(PacketCustom packet, Minecraft mc, INetHandlerPlayClient netHandler) {
switch (packet.getType()) {
case 1:
case S2C.SEND_SERVER_SIDE_CHECK:
handleSMPCheck(packet.readUByte(), packet.readString(), mc.theWorld);
break;
case 10:
case S2C.SEND_LOGIN_STATE:
handleLoginState(packet);
break;
case 11:
case S2C.SEND_ACTION_DISABLED:
handleActionDisabled(packet);
break;
case 12:
case S2C.SEND_ACTION_ENABLED:
handleActionEnabled(packet);
break;
case 13:
case S2C.SEND_MAGNETIC_ITEM:
ClientHandler.instance().addSMPMagneticItem(packet.readInt(), mc.theWorld);
break;
case 14:
case S2C.SEND_GAME_MODE:
handleGamemode(mc, packet.readUByte());
break;
case 21:
case S2C.OPEN_ENCHANTMENT_GUI:
ClientUtils.openSMPGui(
packet.readUByte(),
new GuiEnchantmentModifier(mc.thePlayer.inventory, mc.theWorld, 0, 0, 0));
break;
case 23:
case S2C.SET_CREATIVE_PLUS_MODE:
if (packet.readBoolean()) ClientUtils.openSMPGui(
packet.readUByte(),
new GuiExtendedCreativeInv(
new ContainerCreativeInv(mc.thePlayer, new ExtendedCreativeInv(null, Side.CLIENT))));
else mc.displayGuiScreen(new GuiInventory(mc.thePlayer));
break;
case 24:
case S2C.OPEN_POTION_GUI:
ClientUtils.openSMPGui(packet.readUByte(), new GuiPotionCreator(mc.thePlayer.inventory));
break;
}
@@ -102,7 +104,7 @@ public class NEICPH implements IClientPacketHandler {
try {
ClientHandler.instance().loadWorld(world, true);
NEIClientConfig.setHasSMPCounterPart(true);
NEIClientConfig.loadWorld(getSaveName(worldName));
NEIClientConfig.loadWorld(getSaveName());
sendRequestLoginInfo();
} catch (Exception e) {
NEIClientConfig.logger.error("Error handling SMP Check", e);
@@ -110,14 +112,14 @@ public class NEICPH implements IClientPacketHandler {
}
}
private static String getSaveName(String worldName) {
private static String getSaveName() {
if (Minecraft.getMinecraft().isSingleplayer()) return "local/" + ClientUtils.getWorldSaveName();
return "remote/" + ClientUtils.getServerIP().replace(':', '~') + "/" + worldName;
return "remote/" + ClientUtils.getServerIP().replace(':', '~');
}
public static void sendGiveItem(ItemStack spawnstack, boolean infinite, boolean doSpawn) {
PacketCustom packet = new PacketCustom(channel, 1);
PacketCustom packet = new PacketCustom(channel, C2S.GIVE_ITEM);
packet.writeItemStack(spawnstack, true);
packet.writeBoolean(infinite);
packet.writeBoolean(doSpawn);
@@ -125,7 +127,7 @@ public class NEICPH implements IClientPacketHandler {
}
public static void sendDeleteAllItems() {
PacketCustom packet = new PacketCustom(channel, 4);
PacketCustom packet = new PacketCustom(channel, C2S.DELETE_ALL_ITEMS);
packet.sendToServer();
}
@@ -139,18 +141,18 @@ public class NEICPH implements IClientPacketHandler {
sendSetSlot(slot, item, false);
}
PacketCustom packet = new PacketCustom(channel, 11);
PacketCustom packet = new PacketCustom(channel, C2S.REQUEST_CONTAINER_CONTENTS);
packet.sendToServer();
}
public static void sendRequestContainer() {
PacketCustom packet = new PacketCustom(channel, 16);
PacketCustom packet = new PacketCustom(channel, C2S.REQUEST_CONTAINER);
packet.writeInt(Minecraft.getMinecraft().thePlayer.openContainer.getInventory().size());
packet.sendToServer();
}
public static void sendSetSlot(int slot, ItemStack stack, boolean container) {
PacketCustom packet = new PacketCustom(channel, 5);
PacketCustom packet = new PacketCustom(channel, C2S.SET_SLOT);
packet.writeBoolean(container);
packet.writeShort(slot);
packet.writeItemStack(stack);
@@ -158,38 +160,38 @@ public class NEICPH implements IClientPacketHandler {
}
private static void sendRequestLoginInfo() {
PacketCustom packet = new PacketCustom(channel, 10);
PacketCustom packet = new PacketCustom(channel, C2S.REQUEST_LOGIN_INFO);
packet.sendToServer();
}
public static void sendToggleMagnetMode() {
PacketCustom packet = new PacketCustom(channel, 6);
PacketCustom packet = new PacketCustom(channel, C2S.TOGGLE_MAGNET);
packet.sendToServer();
}
public static void sendSetTime(int hour) {
PacketCustom packet = new PacketCustom(channel, 7);
PacketCustom packet = new PacketCustom(channel, C2S.SET_TIME);
packet.writeByte(hour);
packet.sendToServer();
}
public static void sendHeal() {
PacketCustom packet = new PacketCustom(channel, 8);
PacketCustom packet = new PacketCustom(channel, C2S.HEAL);
packet.sendToServer();
}
public static void sendToggleRain() {
PacketCustom packet = new PacketCustom(channel, 9);
PacketCustom packet = new PacketCustom(channel, C2S.TOGGLE_RAIN);
packet.sendToServer();
}
public static void sendOpenEnchantmentWindow() {
PacketCustom packet = new PacketCustom(channel, 21);
PacketCustom packet = new PacketCustom(channel, C2S.REQUEST_ENCHANTMENT_GUI);
packet.sendToServer();
}
public static void sendModifyEnchantment(int enchID, int level, boolean add) {
PacketCustom packet = new PacketCustom(channel, 22);
PacketCustom packet = new PacketCustom(channel, C2S.MODIFY_ENCHANTMENT);
packet.writeByte(enchID);
packet.writeByte(level);
packet.writeBoolean(add);
@@ -197,30 +199,30 @@ public class NEICPH implements IClientPacketHandler {
}
public static void sendSetPropertyDisabled(String name, boolean enable) {
PacketCustom packet = new PacketCustom(channel, 12);
PacketCustom packet = new PacketCustom(channel, C2S.CHANGE_PROPERTY);
packet.writeString(name);
packet.writeBoolean(enable);
packet.sendToServer();
}
public static void sendGamemode(int mode) {
new PacketCustom(channel, 13).writeByte(mode).sendToServer();
new PacketCustom(channel, C2S.SET_GAME_MODE).writeByte(mode).sendToServer();
}
public static void sendCreativeInv(boolean open) {
PacketCustom packet = new PacketCustom(channel, 23);
PacketCustom packet = new PacketCustom(channel, C2S.SET_CREATIVE_PLUS_MODE);
packet.writeBoolean(open);
packet.sendToServer();
}
public static void sendCreativeScroll(int steps) {
PacketCustom packet = new PacketCustom(channel, 14);
PacketCustom packet = new PacketCustom(channel, C2S.CYCLE_CREATIVE_INV);
packet.writeInt(steps);
packet.sendToServer();
}
public static void sendMobSpawnerID(int x, int y, int z, String mobtype) {
PacketCustom packet = new PacketCustom(channel, 15);
PacketCustom packet = new PacketCustom(channel, C2S.SEND_MOB_SPAWNER_ID);
packet.writeCoord(x, y, z);
packet.writeString(mobtype);
packet.sendToServer();
@@ -231,13 +233,13 @@ public class NEICPH implements IClientPacketHandler {
InventoryUtils.readItemStacksFromTag(
potionStore,
NEIClientConfig.global.nbt.getCompoundTag("potionStore").getTagList("items", 10));
PacketCustom packet = new PacketCustom(channel, 24);
PacketCustom packet = new PacketCustom(channel, C2S.REQUEST_POTION_GUI);
for (ItemStack stack : potionStore) packet.writeItemStack(stack);
packet.sendToServer();
}
public static void sendDummySlotSet(int slotNumber, ItemStack stack) {
PacketCustom packet = new PacketCustom(channel, 25);
PacketCustom packet = new PacketCustom(channel, C2S.SET_DUMMY_SLOT);
packet.writeShort(slotNumber);
packet.writeItemStack(stack, true);
packet.sendToServer();
@@ -21,6 +21,8 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.input.Keyboard;
import com.google.common.base.Objects;
import codechicken.core.CCUpdateChecker;
import codechicken.core.ClassDiscoverer;
import codechicken.core.ClientUtils;
@@ -53,11 +55,10 @@ import codechicken.nei.recipe.RecipeCatalysts;
import codechicken.nei.recipe.RecipeInfo;
import codechicken.obfuscator.ObfuscationRun;
import com.google.common.base.Objects;
public class NEIClientConfig {
private static boolean configLoaded;
private static boolean mainNEIConfigLoaded;
private static boolean pluginNEIConfigLoaded;
private static boolean enabledOverride;
private static String worldPath;
@@ -241,6 +242,9 @@ public class NEIClientConfig {
tag.getTag("inventory.bookmarksAnimationEnabled").setComment("REI Style Animation in Bookmarks")
.getBooleanValue(true);
API.addOption(new OptionToggleButton("inventory.bookmarksAnimationEnabled", true));
tag.getTag("inventory.recipeTooltipsEnabled").setComment("Show recipe tooltips in Bookmarks")
.getBooleanValue(true);
API.addOption(new OptionToggleButton("inventory.recipeTooltipsEnabled", true));
tag.getTag("inventory.showRecipeMarker").setComment("Show Recipe Marker").getBooleanValue(false);
API.addOption(new OptionToggleButton("inventory.showRecipeMarker", true));
@@ -350,6 +354,7 @@ public class NEIClientConfig {
API.addHashBind(
"gui.bookmark_recipe_count",
Keyboard.KEY_A + NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH);
API.addHashBind("gui.bookmark_pull_items", Keyboard.KEY_V);
API.addHashBind("gui.overlay", Keyboard.KEY_S);
API.addHashBind("gui.overlay_use", Keyboard.KEY_S + NEIClientUtils.SHIFT_HASH);
API.addHashBind("gui.overlay_hide", Keyboard.KEY_S + NEIClientUtils.CTRL_HASH);
@@ -463,21 +468,23 @@ public class NEIClientConfig {
}
public static void bootNEI(World world) {
if (configLoaded) return;
if (mainNEIConfigLoaded) return;
// main NEI config loading
ItemInfo.load(world);
GuiInfo.load();
RecipeInfo.load();
LayoutManager.load();
NEIController.load();
RecipeCatalysts.loadCatalystInfo();
configLoaded = true;
BookmarkContainerInfo.load();
mainNEIConfigLoaded = true;
new Thread("NEI Plugin Loader") {
@Override
public void run() {
logger.debug("Started NEI plugin loading");
ClassDiscoverer classDiscoverer = new ClassDiscoverer(
test -> test.startsWith("NEI") && test.endsWith("Config.class"),
IConfigureNEI.class);
@@ -495,6 +502,13 @@ public class NEIClientConfig {
}
}
// Set pluginNEIConfigLoaded here before posting the NEIConfigsLoadedEvent. This used to be the other
// way around, but apparently if your modpack includes 800 mods the event poster might not return in
// time and cause issues when loading a world for a second time as configLoaded is still false. This may
// cause issues in case one of the event handler calls the (non-thread-safe) NEI API. I don't expect any
// handler to do this, but who knows what modders have come up with...
pluginNEIConfigLoaded = true;
logger.debug("NEI plugin loading finished");
MinecraftForge.EVENT_BUS.post(new NEIConfigsLoadedEvent());
}
}.start();
@@ -549,6 +563,10 @@ public class NEIClientConfig {
return getBooleanSetting("inventory.bookmarksAnimationEnabled");
}
public static boolean showRecipeTooltips() {
return getBooleanSetting("inventory.recipeTooltipsEnabled");
}
public static boolean showRecipeMarker() {
return getBooleanSetting("inventory.showRecipeMarker");
}
@@ -597,6 +615,10 @@ public class NEIClientConfig {
return enabledOverride && getBooleanSetting("inventory.widgetsenabled");
}
public static boolean isLoaded() {
return mainNEIConfigLoaded && pluginNEIConfigLoaded;
}
public static boolean loadHandlersFromJar() {
return !getBooleanSetting("tools.handler_load_from_config");
}
@@ -43,6 +43,8 @@ import net.minecraft.util.ResourceLocation;
import org.lwjgl.input.Keyboard;
import com.google.common.collect.Iterables;
import codechicken.lib.inventory.InventoryRange;
import codechicken.lib.inventory.InventoryUtils;
import codechicken.lib.util.LangProxy;
@@ -50,8 +52,6 @@ import codechicken.nei.api.GuiInfo;
import codechicken.nei.api.IInfiniteItemHandler;
import codechicken.nei.api.ItemInfo;
import com.google.common.collect.Iterables;
public class NEIClientUtils extends NEIServerUtils {
public static LangProxy lang = new LangProxy("nei");
@@ -5,16 +5,15 @@ import java.util.*;
import net.minecraft.util.EnumChatFormatting;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import codechicken.core.CommonUtils;
import codechicken.core.launch.CodeChickenCorePlugin;
import codechicken.nei.api.IConfigureNEI;
import codechicken.nei.asm.NEICorePlugin;
import codechicken.nei.config.IMCHandler;
import codechicken.nei.recipe.GuiRecipeTab;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.client.FMLFileResourcePack;
import cpw.mods.fml.client.FMLFolderResourcePack;
import cpw.mods.fml.common.DummyModContainer;
+31 -28
View File
@@ -1,5 +1,7 @@
package codechicken.nei;
import static codechicken.nei.PacketIDs.*;
import java.util.LinkedList;
import java.util.Set;
@@ -28,61 +30,61 @@ public class NEISPH implements IServerPacketHandler {
if (!NEIServerConfig.authenticatePacket(sender, packet)) return;
switch (packet.getType()) {
case 1:
case C2S.GIVE_ITEM:
handleGiveItem(sender, packet);
break;
case 4:
case C2S.DELETE_ALL_ITEMS:
NEIServerUtils.deleteAllItems(sender);
break;
case 5:
case C2S.SET_SLOT:
setInventorySlot(sender, packet);
break;
case 6:
case C2S.TOGGLE_MAGNET:
NEIServerUtils.toggleMagnetMode(sender);
break;
case 7:
case C2S.SET_TIME:
NEIServerUtils.setHourForward(sender.worldObj, packet.readUByte(), true);
break;
case 8:
case C2S.HEAL:
NEIServerUtils.healPlayer(sender);
break;
case 9:
case C2S.TOGGLE_RAIN:
NEIServerUtils.toggleRaining(sender.worldObj, true);
break;
case 10:
case C2S.REQUEST_LOGIN_INFO:
sendLoginState(sender);
break;
case 11:
case C2S.REQUEST_CONTAINER_CONTENTS:
sender.sendContainerAndContentsToPlayer(sender.openContainer, sender.openContainer.getInventory());
break;
case 12:
case C2S.CHANGE_PROPERTY:
handlePropertyChange(sender, packet);
break;
case 13:
case C2S.SET_GAME_MODE:
NEIServerUtils.setGamemode(sender, packet.readUByte());
break;
case 14:
case C2S.CYCLE_CREATIVE_INV:
NEIServerUtils.cycleCreativeInv(sender, packet.readInt());
break;
case 15:
case C2S.SEND_MOB_SPAWNER_ID:
handleMobSpawnerID(sender.worldObj, packet.readCoord(), packet.readString());
break;
case 16:
case C2S.REQUEST_CONTAINER:
handleRequestContainer(sender, packet.readInt());
break;
case 21:
case C2S.REQUEST_ENCHANTMENT_GUI:
openEnchantmentGui(sender);
break;
case 22:
case C2S.MODIFY_ENCHANTMENT:
modifyEnchantment(sender, packet.readUByte(), packet.readUByte(), packet.readBoolean());
break;
case 23:
case C2S.SET_CREATIVE_PLUS_MODE:
processCreativeInv(sender, packet.readBoolean());
break;
case 24:
case C2S.REQUEST_POTION_GUI:
openPotionGui(sender, packet);
break;
case 25:
case C2S.SET_DUMMY_SLOT:
handleDummySlotSet(sender, packet);
break;
}
@@ -126,14 +128,14 @@ public class NEISPH implements IServerPacketHandler {
NEIServerConfig.forPlayer(sender.getCommandSenderName()),
Side.SERVER)),
(player, windowId) -> {
PacketCustom packet = new PacketCustom(channel, 23);
PacketCustom packet = new PacketCustom(channel, S2C.SET_CREATIVE_PLUS_MODE);
packet.writeBoolean(true);
packet.writeByte(windowId);
packet.sendToPlayer(player);
});
} else {
sender.closeContainer();
PacketCustom packet = new PacketCustom(channel, 23);
PacketCustom packet = new PacketCustom(channel, S2C.SET_CREATIVE_PLUS_MODE);
packet.writeBoolean(false);
packet.sendToPlayer(sender);
}
@@ -169,7 +171,7 @@ public class NEISPH implements IServerPacketHandler {
player,
new ContainerEnchantmentModifier(player.inventory, player.worldObj, 0, 0, 0),
(player1, windowId) -> {
PacketCustom packet = new PacketCustom(channel, 21);
PacketCustom packet = new PacketCustom(channel, S2C.OPEN_ENCHANTMENT_GUI);
packet.writeByte(windowId);
packet.sendToPlayer(player1);
});
@@ -179,18 +181,19 @@ public class NEISPH implements IServerPacketHandler {
InventoryBasic b = new InventoryBasic("potionStore", true, 9);
for (int i = 0; i < b.getSizeInventory(); i++) b.setInventorySlotContents(i, packet.readItemStack());
ServerUtils.openSMPContainer(player, new ContainerPotionCreator(player.inventory, b), (player1, windowId) -> {
PacketCustom packet1 = new PacketCustom(channel, 24);
PacketCustom packet1 = new PacketCustom(channel, S2C.OPEN_POTION_GUI);
packet1.writeByte(windowId);
packet1.sendToPlayer(player1);
});
}
public static void sendActionDisabled(int dim, String name, boolean disable) {
new PacketCustom(channel, 11).writeString(name).writeBoolean(disable).sendToDimension(dim);
new PacketCustom(channel, S2C.SEND_ACTION_DISABLED).writeString(name).writeBoolean(disable)
.sendToDimension(dim);
}
public static void sendActionEnabled(EntityPlayerMP player, String name, boolean enable) {
new PacketCustom(channel, 12).writeString(name).writeBoolean(enable).sendToPlayer(player);
new PacketCustom(channel, S2C.SEND_ACTION_ENABLED).writeString(name).writeBoolean(enable).sendToPlayer(player);
}
private void sendLoginState(EntityPlayerMP player) {
@@ -209,7 +212,7 @@ public class NEISPH implements IServerPacketHandler {
if (!NEIServerConfig.isPlayerInList(player.getCommandSenderName(), entry.value, true))
bannedItems.add(entry.key);
PacketCustom packet = new PacketCustom(channel, 10);
PacketCustom packet = new PacketCustom(channel, S2C.SEND_LOGIN_STATE);
packet.writeByte(actions.size());
for (String s : actions) packet.writeString(s);
@@ -228,7 +231,7 @@ public class NEISPH implements IServerPacketHandler {
public static void sendHasServerSideTo(EntityPlayerMP player) {
NEIServerConfig.logger.debug("Sending serverside check to: " + player.getCommandSenderName());
PacketCustom packet = new PacketCustom(channel, 1);
PacketCustom packet = new PacketCustom(channel, S2C.SEND_SERVER_SIDE_CHECK);
packet.writeByte(NEIActions.protocol);
packet.writeString(CommonUtils.getWorldName(player.worldObj));
@@ -236,7 +239,7 @@ public class NEISPH implements IServerPacketHandler {
}
public static void sendAddMagneticItemTo(EntityPlayerMP player, EntityItem item) {
PacketCustom packet = new PacketCustom(channel, 13);
PacketCustom packet = new PacketCustom(channel, S2C.SEND_MAGNETIC_ITEM);
packet.writeInt(item.getEntityId());
packet.sendToPlayer(player);
@@ -42,6 +42,7 @@ import codechicken.core.ServerUtils;
import codechicken.lib.inventory.InventoryRange;
import codechicken.lib.inventory.InventoryUtils;
import codechicken.lib.packet.PacketCustom;
import codechicken.nei.PacketIDs.S2C;
import codechicken.nei.util.NBTHelper;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.registry.GameRegistry;
@@ -295,7 +296,7 @@ public class NEIServerUtils {
player.theItemInWorldManager.setGameType(getGameType(mode));
// tell the client to change it
new PacketCustom(NEISPH.channel, 14).writeByte(mode).sendToPlayer(player);
new PacketCustom(NEISPH.channel, S2C.SEND_GAME_MODE).writeByte(mode).sendToPlayer(player);
player.addChatMessage(new ChatComponentTranslation("nei.chat.gamemode." + mode));
}
@@ -0,0 +1,40 @@
package codechicken.nei;
public final class PacketIDs {
public static final class C2S {
public static final int GIVE_ITEM = 1;
public static final int DELETE_ALL_ITEMS = 4;
public static final int SET_SLOT = 5;
public static final int TOGGLE_MAGNET = 6;
public static final int SET_TIME = 7;
public static final int HEAL = 8;
public static final int TOGGLE_RAIN = 9;
public static final int REQUEST_LOGIN_INFO = 10;
public static final int REQUEST_CONTAINER_CONTENTS = 11;
public static final int CHANGE_PROPERTY = 12;
public static final int SET_GAME_MODE = 13;
public static final int CYCLE_CREATIVE_INV = 14;
public static final int SEND_MOB_SPAWNER_ID = 15;
public static final int REQUEST_CONTAINER = 16;
public static final int REQUEST_ENCHANTMENT_GUI = 21;
public static final int MODIFY_ENCHANTMENT = 22;
public static final int SET_CREATIVE_PLUS_MODE = 23;
public static final int REQUEST_POTION_GUI = 24;
public static final int SET_DUMMY_SLOT = 25;
}
public static final class S2C {
public static final int SEND_SERVER_SIDE_CHECK = 1;
public static final int SEND_LOGIN_STATE = 10;
public static final int SEND_ACTION_DISABLED = 11;
public static final int SEND_ACTION_ENABLED = 12;
public static final int SEND_MAGNETIC_ITEM = 13;
public static final int SEND_GAME_MODE = 14;
public static final int OPEN_ENCHANTMENT_GUI = 21;
public static final int SET_CREATIVE_PLUS_MODE = 23;
public static final int OPEN_POTION_GUI = 24;
}
}
@@ -1,6 +1,7 @@
package codechicken.nei;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.item.ItemStack;
@@ -171,6 +172,11 @@ public abstract class PanelWidget extends Widget {
}
}
@Override
public void update() {
grid.update();
}
@Override
public void draw(int mousex, int mousey) {
grid.draw(mousex, mousey);
@@ -185,6 +191,11 @@ public abstract class PanelWidget extends Widget {
}
}
@Override
public void postDrawTooltips(int mx, int my, List<String> tooltip) {
grid.postDrawTooltips(mx, my, tooltip);
}
@Override
public void mouseDragged(int mousex, int mousey, int button, long heldTime) {
if (mouseDownSlot >= 0 && draggedStack == null
@@ -21,6 +21,11 @@ import net.minecraft.item.ItemStack;
import org.apache.commons.io.IOUtils;
import org.lwjgl.input.Keyboard;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import codechicken.core.CommonUtils;
import codechicken.core.gui.GuiScrollSlot;
import codechicken.lib.gui.GuiDraw;
@@ -30,11 +35,6 @@ import codechicken.nei.api.ItemFilter;
import codechicken.nei.recipe.GuiRecipe;
import codechicken.nei.recipe.StackInfo;
import codechicken.nei.util.NBTJson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import cpw.mods.fml.common.registry.GameRegistry;
public class PresetsWidget extends Widget {
@@ -1,6 +1,7 @@
package codechicken.nei;
import com.google.common.base.Objects;
import cpw.mods.fml.common.FMLCommonHandler;
public class ThreadOperationTimer extends Thread {
@@ -14,6 +14,8 @@ public abstract class Widget {
public void postDraw(int mx, int my) {}
public void postDrawTooltips(int mx, int my, List<String> tooltip) {}
public boolean handleClick(int mx, int my, int button) {
return true;
}
@@ -24,10 +24,13 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
public static int mobOverlay = 0;
private static byte[] mobSpawnCache;
private static long mobOverlayUpdateTime;
private static String oregenPatternName;
private static boolean hasOregenPatternBeenSet = false;
public static void reset() {
mobOverlay = 0;
chunkOverlay = 0;
hasOregenPatternBeenSet = false;
}
@Override
@@ -279,15 +282,33 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
GL11.glVertex3d(x2, y2, z1 + h);
}
} else if (chunkOverlay == 3) {
int gx1 = (((entity.chunkCoordX < 0 ? entity.chunkCoordX - 3 : entity.chunkCoordX) / 3 * 3) << 4)
- intOffsetX;
int gz1 = (((entity.chunkCoordZ < 0 ? entity.chunkCoordZ - 3 : entity.chunkCoordZ) / 3 * 3) << 4)
- intOffsetZ;
if (entity.chunkCoordX < 0) {
gx1 += 16;
if (!hasOregenPatternBeenSet) {
try {
oregenPatternName = ((Enum<?>) Class.forName("gregtech.common.GT_Worldgenerator")
.getDeclaredField("oregenPattern").get(null)).name();
} catch (Exception ignored) {
oregenPatternName = "AXISSYMMETRICAL";
}
hasOregenPatternBeenSet = true;
}
if (entity.chunkCoordZ < 0) {
gz1 += 16;
int gx1;
int gz1;
if (oregenPatternName.equals("EQUAL_SPACING")) {
// gt oregen uses new regular pattern
gx1 = ((Math.floorDiv(entity.chunkCoordX, 3) * 3) << 4) - intOffsetX;
gz1 = ((Math.floorDiv(entity.chunkCoordZ, 3) * 3) << 4) - intOffsetZ;
} else {
// gt oregen uses old bugged pattern
gx1 = (((entity.chunkCoordX < 0 ? entity.chunkCoordX - 3 : entity.chunkCoordX) / 3 * 3) << 4)
- intOffsetX;
gz1 = (((entity.chunkCoordZ < 0 ? entity.chunkCoordZ - 3 : entity.chunkCoordZ) / 3 * 3) << 4)
- intOffsetZ;
if (entity.chunkCoordX < 0) {
gx1 += 16;
}
if (entity.chunkCoordZ < 0) {
gz1 += 16;
}
}
int gx2 = gx1 + 48;
int gz2 = gz1 + 48;
+8 -2
View File
@@ -12,6 +12,9 @@ import net.minecraft.item.ItemStack;
import org.lwjgl.input.Keyboard;
import com.google.common.collect.Sets;
import codechicken.nei.BookmarkContainerInfo;
import codechicken.nei.ItemList;
import codechicken.nei.ItemSorter;
import codechicken.nei.ItemStackSet;
@@ -37,8 +40,6 @@ import codechicken.nei.recipe.RecipeCatalysts;
import codechicken.nei.recipe.RecipeInfo;
import codechicken.nei.recipe.StackInfo;
import com.google.common.collect.Sets;
/**
* This is the main class that handles item property configuration. WARNING: DO NOT access this class until the world
* has been loaded These methods should be called from INEIConfig implementors
@@ -390,6 +391,11 @@ public class API {
RecipeCatalysts.removeRecipeCatalyst(handlerID, stack);
}
public static void registerBookmarkContainerHandler(Class<? extends GuiContainer> gui,
IBookmarkContainerHandler handler) {
BookmarkContainerInfo.registerBookmarkContainerHandler(gui, handler);
}
@Deprecated
public static void addRecipeCatalyst(List<ItemStack> stacks, IRecipeHandler handler) {
for (ItemStack stack : stacks) {
@@ -0,0 +1,11 @@
package codechicken.nei.api;
import java.util.ArrayList;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.item.ItemStack;
public interface IBookmarkContainerHandler {
void pullBookmarkItemsFromContainer(GuiContainer guiContainer, ArrayList<ItemStack> realItems);
}
@@ -39,6 +39,8 @@ import net.minecraftforge.common.BiomeDictionary;
import net.minecraftforge.common.IShearable;
import net.minecraftforge.oredict.OreDictionary;
import com.google.common.collect.ArrayListMultimap;
import codechicken.core.featurehack.GameDataManipulator;
import codechicken.nei.InfiniteStackSizeHandler;
import codechicken.nei.InfiniteToolHandler;
@@ -55,9 +57,6 @@ import codechicken.nei.config.RegistryDumper;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.recipe.BrewingRecipeHandler;
import codechicken.nei.recipe.RecipeItemInputHandler;
import com.google.common.collect.ArrayListMultimap;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.registry.GameRegistry;
@@ -20,6 +20,10 @@ public abstract class ShortcutInputHandler {
public static boolean handleKeyEvent(ItemStack stackover) {
if (!NEIClientConfig.isLoaded()) {
return false;
}
if (NEIClientConfig.isKeyHashDown("gui.overlay_hide")) {
return hideOverlayRecipe();
}
@@ -67,6 +71,10 @@ public abstract class ShortcutInputHandler {
public static boolean handleMouseClick(ItemStack stackover) {
if (!NEIClientConfig.isLoaded()) {
return false;
}
if (stackover != null) {
final int button = Mouse.getEventButton();
stackover = stackover.copy();
@@ -10,6 +10,8 @@ import net.minecraft.util.ChatComponentTranslation;
import org.apache.commons.io.IOUtils;
import com.google.common.base.Objects;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.recipe.GuiRecipeTab;
import codechicken.nei.recipe.GuiUsageRecipe;
@@ -18,8 +20,6 @@ import codechicken.nei.recipe.IRecipeHandler;
import codechicken.nei.recipe.TemplateRecipeHandler;
import codechicken.nei.util.NBTJson;
import com.google.common.base.Objects;
public class HandlerDumper extends DataDumper {
public HandlerDumper(String name) {
@@ -8,12 +8,12 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.LayoutManager;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.LayoutManager;
public abstract class OptionStringSet extends Option {
public final LinkedList<String> options = new LinkedList<>();
@@ -14,6 +14,8 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiScreen;
@@ -159,33 +161,21 @@ public class GuiContainerManager {
return namelist;
}
public static String itemCountDetails(ItemStack stack) {
final FluidStack fluid = StackInfo.getFluid(stack);
int maxStackSize = stack.getMaxStackSize();
int stackSize = stack.stackSize;
String FULL_PATTERN = "Count: %s = %s * %s + %s";
String SHORT_PATTERN = "Count: %s = %s * %s";
if (fluid != null) {
maxStackSize = 144;
stackSize = fluid.amount * Math.max(1, stack.stackSize);
FULL_PATTERN = "Amount: %s L = %s * %s L + %s L";
SHORT_PATTERN = "Amount: %s L = %s * %s L";
}
@Nullable
public static String countDetails(int stackSize, int maxStackSize, String fullPattern, String shortPattern) {
if (maxStackSize > 1 && stackSize > maxStackSize) {
final int remainder = stackSize % maxStackSize;
if (remainder > 0) {
return String.format(
FULL_PATTERN,
fullPattern,
NEIClientUtils.formatNumbers(stackSize),
NEIClientUtils.formatNumbers(stackSize / maxStackSize),
NEIClientUtils.formatNumbers(maxStackSize),
NEIClientUtils.formatNumbers(remainder));
} else {
return String.format(
SHORT_PATTERN,
shortPattern,
NEIClientUtils.formatNumbers(stackSize),
NEIClientUtils.formatNumbers(stackSize / maxStackSize),
NEIClientUtils.formatNumbers(maxStackSize));
@@ -195,6 +185,31 @@ public class GuiContainerManager {
return null;
}
@Nullable
public static String itemCountDetails(ItemStack stack) {
FluidStack fluid = StackInfo.getFluid(stack);
if (fluid != null) {
return fluidAmountDetails(fluid.amount * Math.max(1, stack.stackSize));
} else {
return countDetails(
stack.stackSize,
stack.getMaxStackSize(),
"Count: %s = %s * %s + %s",
"Count: %s = %s * %s");
}
}
@SuppressWarnings("unused")
@Nullable
public static String fluidAmountDetails(FluidStack fluid) {
return fluidAmountDetails(fluid.amount);
}
@Nullable
public static String fluidAmountDetails(int amount) {
return countDetails(amount, 144, "Amount: %s L = %s * %s L + %s L", "Amount: %s L = %s * %s L");
}
/**
* The general name of this item.
*
@@ -499,6 +514,10 @@ public class GuiContainerManager {
if (tooltip.size() > 0) tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE); // add space after 'title'
drawPagedTooltip(font, mousex + 12, mousey - 12, tooltip);
for (IContainerDrawHandler drawHandler : drawHandlers) {
drawHandler.postRenderTooltips(window, mousex, mousey, tooltip);
}
}
private static int tooltipPage;
@@ -1,5 +1,7 @@
package codechicken.nei.guihook;
import java.util.List;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.inventory.Slot;
@@ -30,6 +32,17 @@ public interface IContainerDrawHandler {
*/
public void postRenderObjects(GuiContainer gui, int mousex, int mousey);
/**
* Use this to draw things that should be drawn just after vanilla slot tooltips, on top of buttons and other
* usually always-on-top widgets.
*
* @param gui An instance of the currentscreen
* @param mousex The x position of the mouse in pixels from left
* @param mousey The y position of the mouse in pixels from top
* @param tooltip The contents of the tooltip that has previously been drawn
*/
default void postRenderTooltips(GuiContainer gui, int mousex, int mousey, List<String> tooltip) {}
/**
* Render something over a slot before the item in the slot.
*
@@ -6,14 +6,14 @@ import java.util.List;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import codechicken.nei.PositionedStack;
import codechicken.nei.util.NBTJson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import codechicken.nei.PositionedStack;
import codechicken.nei.util.NBTJson;
public class BookmarkRecipeId {
public int position = -1;
@@ -121,6 +121,43 @@ public class BookmarkRecipeId {
return arr;
}
/**
* Ensures the {@link BookmarkRecipeId#recipetype} and {@link BookmarkRecipeId#position} fields point to a valid
* recipe. This is needed, because the recipe IDs are loaded lazily on first use.
*
* @param recipeHandlers The subset of recipe handlers to search for the recipe
*/
public void updateTargetRecipe(List<? extends IRecipeHandler> recipeHandlers) {
if (this.recipetype == -1 || this.position == -1) {
this.recipetype = 0;
this.position = 0;
if (this.handlerName != null) {
for (int j = 0; j < recipeHandlers.size(); j++) {
IRecipeHandler localHandler = recipeHandlers.get(j);
HandlerInfo localHandlerInfo = GuiRecipeTab.getHandlerInfo(localHandler);
if (localHandlerInfo.getHandlerName().equals(this.handlerName)) {
if (!this.ingredients.isEmpty()) {
for (int i = 0; i < localHandler.numRecipes(); i++) {
if (this.equalsIngredients(localHandler.getIngredientStacks(i))) {
this.recipetype = j;
this.position = i;
break;
}
}
}
break;
}
}
}
}
}
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
@@ -8,11 +8,11 @@ import javax.annotation.Nonnull;
import net.minecraft.item.ItemStack;
import com.google.common.collect.ForwardingList;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIServerUtils;
import com.google.common.collect.ForwardingList;
// Do not directly extend ArrayList, see Effective Java Item 16
public class CatalystInfoList extends ForwardingList<CatalystInfo> {
@@ -28,28 +28,27 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
public static boolean openRecipeGui(String outputId, final Boolean overlay, final Boolean shift,
Object... results) {
return createRecipeGui(outputId, overlay, shift, true, results) != null;
}
public static GuiRecipe<?> createRecipeGui(String outputId, final Boolean overlay, final Boolean shift,
final boolean open, Object... results) {
final Minecraft mc = NEIClientUtils.mc();
final BookmarkRecipeId recipeId = "item".equals(outputId)
? getRecipeId(mc.currentScreen, (ItemStack) results[0])
: getCurrentRecipe(mc.currentScreen);
if (overlay && recipeId == null) return false;
if (overlay && recipeId == null) return null;
final RecipeHandlerQuery<ICraftingHandler> recipeQuery = new RecipeHandlerQuery<>(
h -> h.getRecipeHandler(outputId, results),
craftinghandlers,
serialCraftingHandlers,
"Error while looking up crafting recipe",
"outputId: " + outputId,
"results: " + Arrays.toString(results));
final ArrayList<ICraftingHandler> handlers = recipeQuery.runWithProfiling("recipe.concurrent.crafting");
final ArrayList<ICraftingHandler> handlers = getCraftingHandlers(outputId, results);
if (!handlers.isEmpty()) {
GuiCraftingRecipe gui = new GuiCraftingRecipe(handlers, recipeId);
mc.displayGuiScreen(gui);
if (open) {
mc.displayGuiScreen(gui);
}
if (recipeId != null) {
gui.openTargetRecipe(gui.recipeId);
@@ -59,10 +58,22 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
gui.overlayRecipe(gui.recipeId.position, shift);
}
return true;
return gui;
}
return false;
return null;
}
public static ArrayList<ICraftingHandler> getCraftingHandlers(String outputId, Object... results) {
final RecipeHandlerQuery<ICraftingHandler> recipeQuery = new RecipeHandlerQuery<>(
h -> h.getRecipeHandler(outputId, results),
craftinghandlers,
serialCraftingHandlers,
"Error while looking up crafting recipe",
"outputId: " + outputId,
"results: " + Arrays.toString(results));
return recipeQuery.runWithProfiling("recipe.concurrent.crafting");
}
protected static BookmarkRecipeId getRecipeId(GuiScreen gui, ItemStack stackover) {
@@ -94,6 +105,7 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
public static void registerRecipeHandler(ICraftingHandler handler) {
final String handlerId = handler.getHandlerId();
if (craftinghandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId))
|| serialCraftingHandlers.stream().anyMatch(h -> h.getHandlerId().equals(handlerId)))
return;
@@ -1,5 +1,7 @@
package codechicken.nei.recipe;
import static codechicken.lib.gui.GuiDraw.fontRenderer;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
@@ -13,6 +15,7 @@ import java.util.stream.IntStream;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
@@ -59,6 +62,8 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
private static final int buttonWidth = 13;
private static final int buttonHeight = 12;
private boolean limitToOneRecipe = false;
// Background image
final DrawableResource bgTop = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_TOP_Y, 176, BG_TOP_HEIGHT)
.build();
@@ -100,6 +105,12 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
private int yShift = 0;
/**
* This will only be true iff height hacking has been configured for the current recipe handler AND we are currently
* within the scope of an active {@link CompatibilityHacks} instance.
*/
private boolean isHeightHackApplied = false;
protected GuiRecipe(GuiScreen prevgui) {
super(new ContainerRecipe());
recipeTabs = new GuiRecipeTabs(this);
@@ -116,52 +127,113 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
}
/** Changes the GUI mode to only display one recipe at a time, e.g. for tooltip usage */
public void limitToOneRecipe() {
limitToOneRecipe = true;
}
/** Checks if the gui only displays one recipe at a time, e.g. for tooltip usage */
public boolean isLimitedToOneRecipe() {
return limitToOneRecipe;
}
/**
* Many old mods assumed a fixed NEI window height of {@code 166} pixels. Now that this is no longer the case, their
* fluid mouseover handling is broken. This helper class fixes these old mods by hacking the {@link #height}
* tooltip and click zone handling is broken. This helper class fixes these old mods by hacking the {@link #height}
* property's value so that these old mods' calculations return the correct value for the new height.
*
* <p>
* New and old mods often assume that the handler is only drawn when {@link GuiRecipe} is the currently active
* screen in {@link net.minecraft.client.Minecraft}. This is no longer true since the addition of recipe tooltips
* which need to render the recipe in other containers on mouse hover, this class temporarily switches the active
* screen to {@code this} while rendering them to avoid ClassCastExceptions and other similar crashes.
*
* <p>
* This class is an {@link AutoCloseable} so that it can be used with try-with-resources, which will ensure that
* {@link #height} is returned to the correct value afterwards.
* {@link #height} and {@link net.minecraft.client.Minecraft#currentScreen} is returned to the correct value
* afterwards.
*/
private class HeightHack implements AutoCloseable {
private class CompatibilityHacks implements AutoCloseable {
private final int trueHeight;
private final int trueGuiTop;
private final GuiScreen trueGui;
private HeightHack() {
private CompatibilityHacks() {
trueHeight = height;
trueGuiTop = guiTop;
boolean applyHeightHack = NEIClientConfig.heightHackHandlerRegex.stream()
isHeightHackApplied = NEIClientConfig.heightHackHandlerRegex.stream()
.map(pattern -> pattern.matcher(handler.getHandlerId())).anyMatch(Matcher::matches);
if (applyHeightHack) {
// The old mods use the calculation ((height - 166) / 2) to compute the y-value of
// the top edge of the NEI window.
// guiTop is exactly that: the y-value of the top edge of the NEI window.
// So we set height to be equal to the inverse of this calculation, applied to
// guiTop, so that old mods get the right result back when they use this calculation.
if (isHeightHackApplied) {
// guiTop is the top edge of the recipe screen on the y-axis. Old recipe handlers expect a single paging
// widget at the top and at the bottom of the recipe screen with a height of 16px each, but GTNH NEI
// moved the bottom paging widget to the top following JEI's design, increasing the "forbidden" zone at
// the top to 32px. To fix these old recipe handlers we move guiTop down 16px so that they can keep
// working with the old 16px gap.
guiTop += 16;
// The old NEI recipe screen had a fixed width and height and was always centered on the screen. Legacy
// recipe handlers use the calculation ((height - 166) / 2) to compute the y-value of the top edge of
// the NEI window. GTNH NEI changes the layout so that the recipe screen length now has a flexible
// length and is no longer centered vertically. In order for the top-of-screen calculation to return the
// correct result, we have to hack the height field with an inverse of the calculation using the actual
// top of the recipe screen stored in guiTop.
height = (2 * guiTop) + 166;
// For reference, in case we ever need to modify width as well:
// the legacy calculation used for width is ((width - 176) / 2), which should
// evaluate to be equal to guiWidth (the x-value of the left edge of the NEI window).
// So if we wanted to override width as well, we'd do this:
// the legacy calculation used for width is ((width - 176) / 2), which should evaluate to be equal to
// guiWidth (the x-value of the left edge of the NEI recipe screen). So if we wanted to override width
// as well, we'd do this:
// width = (2 * guiWidth) + 176;
}
// Recipe handlers may assume the current screen is the GuiRecipe object, which is not the case in
// recipe tooltips drawn on the bookmarks panel with the main inventory open.
trueGui = NEIClientUtils.mc().currentScreen;
if (limitToOneRecipe) {
NEIClientUtils.mc().currentScreen = GuiRecipe.this;
}
}
@Override
public void close() {
guiTop = trueGuiTop;
height = trueHeight;
// Only restore currentScreen if it hasn't been altered by a recipe handler (for example through
// Minecraft#displayGuiScreen).
if (limitToOneRecipe && NEIClientUtils.mc().currentScreen == GuiRecipe.this) {
NEIClientUtils.mc().currentScreen = trueGui;
}
isHeightHackApplied = false;
}
}
@Override
@SuppressWarnings("unchecked")
public void initGui() {
initGui(false);
}
@SuppressWarnings("unchecked")
public void initGui(boolean asWidget) {
xSize = 176;
ySize = Math.min(Math.max(height - 68, 166), 370);
super.initGui();
if (!asWidget) {
super.initGui();
} else {
this.guiLeft = (this.width - this.xSize) / 2;
this.ySize = this.getHeightAsWidget();
this.mc = NEIClientUtils.mc();
this.fontRendererObj = mc.fontRenderer;
ScaledResolution scaledresolution = new ScaledResolution(
this.mc,
this.mc.displayWidth,
this.mc.displayHeight);
this.width = scaledresolution.getScaledWidth();
this.height = scaledresolution.getScaledHeight();
}
guiTop = (height - ySize) / 2 + 10;
currenthandlers = getCurrentRecipeHandlers(); // Probably don't comment me out
@@ -198,14 +270,24 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
final int recipesPerPage = getRecipesPerPage();
overlayButtons = new GuiButton[recipesPerPage];
final int xOffset = limitToOneRecipe ? ((xSize / 2) - 2) : (width / 2);
final int yOffset = limitToOneRecipe ? 0 : guiTop - 18;
final String overlayKeyName = NEIClientConfig
.getKeyName(NEIClientConfig.getKeyBinding("gui.overlay_use"), true);
for (int i = 0; i < recipesPerPage; i++) {
overlayButtons[i] = new GuiNEIButton(
OVERLAY_BUTTON_ID_START + i,
(width / 2) + 65,
guiTop + 16 + (handlerInfo.getHeight() * (i + 1)) - 2,
xOffset + 65,
yOffset + getRecipePosition(i).y + handlerInfo.getHeight(),
buttonWidth,
buttonHeight,
"?");
if (overlayKeyName != null && limitToOneRecipe) {
overlayButtons[i].visible = true;
overlayButtons[i].displayString = overlayKeyName;
overlayButtons[i].width = fontRenderer.getStringWidth(overlayKeyName) + 6;
overlayButtons[i].xPosition = xOffset + 85 - overlayButtons[i].width;
}
}
Collections.addAll(buttonList, overlayButtons);
itemPresenceCacheRecipe = -1;
@@ -232,41 +314,17 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
initOverlayButtons();
}
public List<GuiButton> getOverlayButtons() {
return Collections.unmodifiableList(Arrays.asList(overlayButtons));
}
public void openTargetRecipe(BookmarkRecipeId recipeId) {
if (recipeId == null) {
return;
}
if (recipeId.recipetype == -1 || recipeId.position == -1) {
recipeId.recipetype = 0;
recipeId.position = 0;
if (recipeId.handlerName != null) {
for (int j = 0; j < currenthandlers.size(); j++) {
H localHandler = currenthandlers.get(j);
HandlerInfo localHandlerInfo = GuiRecipeTab.getHandlerInfo(localHandler);
if (localHandlerInfo.getHandlerName().equals(recipeId.handlerName)) {
if (!recipeId.ingredients.isEmpty()) {
for (int i = 0; i < localHandler.numRecipes(); i++) {
if (recipeId.equalsIngredients(localHandler.getIngredientStacks(i))) {
recipeId.recipetype = j;
recipeId.position = i;
break;
}
}
}
break;
}
}
}
}
recipeId.updateTargetRecipe(currenthandlers);
setRecipePage(recipeId.recipetype, recipeId.position);
}
@@ -350,7 +408,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
if (GuiContainerManager.getManager(this).lastKeyTyped(i, c)) return;
try (HeightHack heightHack = new HeightHack()) {
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
for (int recipe : getRecipeIndices()) if (handler.keyTyped(this, c, i, recipe)) return;
}
@@ -372,7 +430,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
@Override
protected void mouseClicked(int x, int y, int button) {
try (HeightHack heightHack = new HeightHack()) {
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
for (int recipe : getRecipeIndices()) if (handler.mouseClicked(this, button, recipe)) return;
}
@@ -388,8 +446,22 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
// the value of the height field will be different from in other mouseover methods, which
// could be confusing...
// First, invoke scroll handling over recipe handler tabbar. Makes sure it is not overwritten by recipe
// handler-specific scroll behavior.
if (recipeTabs.mouseScrolled(i)) return;
for (int recipe : getRecipeIndices()) if (handler.mouseScrolled(this, i, recipe)) return;
// If shift is held, try switching to the next recipe handler. Replicates the GuiRecipeTabs.mouseScrolled()
// without the checking for the cursor being inside the tabbar.
if (NEIClientUtils.shiftKey()) {
if (i < 0) nextType();
else prevType();
return;
}
// Finally, if nothing else has handled scrolling, try changing to the next recipe page.
if (new Rectangle(guiLeft, guiTop, xSize, ySize).contains(GuiDraw.getMousePosition())) {
if (i > 0) prevPage();
else nextPage();
@@ -424,13 +496,18 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
@Override
public void updateScreen() {
super.updateScreen();
updateAsTooltip();
}
/** updateScreen() that's safe to call when this isn't the currently open GUI */
public void updateAsTooltip() {
handler.onUpdate();
refreshPage();
}
@Override
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
try (HeightHack heightHack = new HeightHack()) {
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
for (int i : getRecipeIndices()) currenttip = handler.handleTooltip(this, currenttip, i);
}
recipeTabs.handleTooltip(mousex, mousey, currenttip);
@@ -440,9 +517,9 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
@Override
public List<String> handleItemTooltip(GuiContainer gui, ItemStack stack, int mousex, int mousey,
List<String> currenttip) {
// Height hacking is probably not needed as it doesn't look like any mods check mouse
// position for this method.
for (int i : getRecipeIndices()) currenttip = handler.handleItemTooltip(this, stack, currenttip, i);
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
for (int i : getRecipeIndices()) currenttip = handler.handleItemTooltip(this, stack, currenttip, i);
}
return currenttip;
}
@@ -462,11 +539,11 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
if (page < 0) page = (handler.numRecipes() - 1) / getRecipesPerPage();
}
private void nextType() {
protected void nextType() {
setRecipePage(++recipetype);
}
private void prevType() {
protected void prevType() {
setRecipePage(--recipetype);
}
@@ -528,6 +605,12 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
final int recipesPerPage = getRecipesPerPage();
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
Point p = getRecipePosition(i);
// Legacy recipe handlers only expect a single paging widget at the top of the recipe screen, in contrast,
// GTNH NEI moves the recipe paging widget from the bottom to the top, which means said legacy handlers will
// position item slots 16px too high in the screen.
if (isHeightHackApplied) {
p.translate(0, 16);
}
List<PositionedStack> stacks = handler.getIngredientStacks(i);
for (PositionedStack stack : stacks) slotcontainer.addSlot(stack, p.x, p.y);
@@ -538,11 +621,13 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
PositionedStack result = handler.getResultStack(i);
if (result != null) slotcontainer.addSlot(result, p.x, p.y);
List<PositionedStack> catalysts = RecipeCatalysts.getRecipeCatalysts(handler);
for (PositionedStack catalyst : catalysts) {
int xOffset = -GuiRecipeCatalyst.ingredientSize + 1;
int yOffset = BG_TOP_Y + GuiRecipeCatalyst.fullBorder;
slotcontainer.addSlot(catalyst, xOffset, yOffset);
if (!limitToOneRecipe) {
List<PositionedStack> catalysts = RecipeCatalysts.getRecipeCatalysts(handler);
for (PositionedStack catalyst : catalysts) {
int xOffset = -GuiRecipeCatalyst.ingredientSize + 1;
int yOffset = BG_TOP_Y + GuiRecipeCatalyst.fullBorder;
slotcontainer.addSlot(catalyst, xOffset, yOffset);
}
}
}
}
@@ -576,21 +661,25 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
@Override
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
public void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
GuiContainerManager.enable2DRender();
final int recipesPerPage = getRecipesPerPage();
String s = handler.getRecipeName().trim();
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 5, 0xffffff);
s = NEIClientUtils.translate("recipe.page", page + 1, (handler.numRecipes() - 1) / recipesPerPage + 1);
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 19, 0xffffff);
final int ySkip = limitToOneRecipe ? 25 : 0;
if (!limitToOneRecipe) {
String s = handler.getRecipeName().trim();
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 5, 0xffffff);
s = NEIClientUtils.translate("recipe.page", page + 1, (handler.numRecipes() - 1) / recipesPerPage + 1);
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 19, 0xffffff);
}
final boolean drawItemPresence = NEIClientConfig.isJEIStyleItemPresenceOverlayVisible();
GL11.glPushMatrix();
GL11.glTranslatef(5, 32 + yShift, 0);
try (HeightHack heightHack = new HeightHack()) {
GL11.glTranslatef(5, 32 - ySkip + yShift, 0);
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
handler.drawForeground(i);
if (drawItemPresence && isMouseOverOverlayButton(i - page * recipesPerPage)
if (drawItemPresence && (isMouseOverOverlayButton(i - page * recipesPerPage) || limitToOneRecipe)
&& firstGui != null
&& firstGui.inventorySlots != null) {
List<PositionedStack> ingredients = handler.getIngredientStacks(i);
if (itemPresenceCacheRecipe != i || itemPresenceCacheSlots == null
@@ -610,28 +699,27 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
@Override
protected void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) {
public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) {
final int recipesPerPage = getRecipesPerPage();
final int ySkip = limitToOneRecipe ? 25 : 0;
GL11.glColor4f(1, 1, 1, 1);
final int j = (width - xSize) / 2;
final int k = guiTop;
drawBackgroundTiled(j, k);
drawBackgroundTiled(guiLeft, guiTop);
drawRect(
guiLeft + borderPadding + buttonWidth - 1,
nexttype.yPosition,
guiLeft + xSize - borderPadding - buttonWidth,
nexttype.yPosition + buttonHeight,
0x30000000);
drawRect(
guiLeft + borderPadding + buttonWidth - 1,
nextpage.yPosition,
guiLeft + xSize - borderPadding - buttonWidth,
nextpage.yPosition + buttonHeight,
0x30000000);
if (NEIClientConfig.areJEIStyleTabsVisible() && !limitToOneRecipe) {
drawRect(
guiLeft + borderPadding + buttonWidth - 1,
nexttype.yPosition,
guiLeft + xSize - borderPadding - buttonWidth,
nexttype.yPosition + buttonHeight,
0x30000000);
drawRect(
guiLeft + borderPadding + buttonWidth - 1,
nextpage.yPosition,
guiLeft + xSize - borderPadding - buttonWidth,
nextpage.yPosition + buttonHeight,
0x30000000);
if (NEIClientConfig.areJEIStyleTabsVisible()) {
RenderHelper.enableGUIStandardItemLighting();
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
recipeTabs.draw(mouseX, mouseY);
@@ -642,8 +730,8 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
GL11.glPushMatrix();
GL11.glTranslatef(j + 5, k + 32 + yShift, 0);
try (HeightHack heightHack = new HeightHack()) {
GL11.glTranslatef(guiLeft + 5, guiTop - ySkip + 32 + yShift, 0);
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
handler.drawBackground(i);
GL11.glTranslatef(0, handlerInfo.getHeight(), 0);
@@ -654,10 +742,12 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
private void drawBackgroundTiled(int j, int k) {
// Draw the top
final int ySkip = limitToOneRecipe ? 25 : 0;
final int handlerHeight = limitToOneRecipe ? getHeightAsWidget() : ySize;
bgTop.draw(j, k + BG_TOP_Y);
// Maybe Tile the middle
final int tiledHeight = ySize - BG_TOP_HEIGHT - BG_BOTTOM_HEIGHT;
final int tiledHeight = handlerHeight - ySkip - BG_TOP_HEIGHT - BG_BOTTOM_HEIGHT;
if (tiledHeight > 0) {
final int yTileCount = tiledHeight / BG_MIDDLE_HEIGHT;
@@ -674,7 +764,11 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
// Draw the bottom
bgBottom.draw(j, k + ySize - BG_BOTTOM_HEIGHT);
bgBottom.draw(j, k + handlerHeight - ySkip - BG_BOTTOM_HEIGHT);
}
public int getHeightAsWidget() {
return (handlerInfo == null) ? ySize : (handlerInfo.getHeight() + 56);
}
@Override
@@ -710,7 +804,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
private int getRecipesPerPage() {
return getRecipesPerPage(handlerInfo);
return limitToOneRecipe ? 1 : getRecipesPerPage(handlerInfo);
}
private int getRecipesPerPage(HandlerInfo handlerInfo) {
@@ -721,7 +815,14 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
}
public Point getRecipePosition(int recipe) {
return new Point(5, 32 + yShift + ((recipe % getRecipesPerPage()) * handlerInfo.getHeight()));
// Legacy recipe handlers using the height hack might use getRecipePosition in combination with guiTop/height to
// position certain elements like tooltips. Since guiTop is moved down by 16px during height hacking, we need to
// reduce the vertical shift here to 16px instead of 32px.
return new Point(
5,
(isHeightHackApplied ? 16 : 32) - (limitToOneRecipe ? 25 : 0)
+ yShift
+ ((recipe % getRecipesPerPage()) * handlerInfo.getHeight()));
}
public abstract ArrayList<H> getCurrentRecipeHandlers();
@@ -1,5 +1,7 @@
package codechicken.nei.recipe;
import static codechicken.lib.gui.GuiDraw.getMousePosition;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
@@ -192,4 +194,18 @@ public class GuiRecipeTabs {
}
return false;
}
protected boolean mouseScrolled(int i) {
Point mousePosition = getMousePosition();
// Switch between recipe handlers if the cursor is over the tabbar.
if (NEIClientConfig.areJEIStyleTabsVisible() && area.contains(mousePosition)) {
if (i < 0) guiRecipe.nextType();
else guiRecipe.prevType();
return true;
}
return false;
}
}
@@ -24,11 +24,11 @@ import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import com.google.common.base.Objects;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIServerUtils;
import codechicken.nei.PositionedStack;
import com.google.common.base.Objects;
import cpw.mods.fml.common.Loader;
public class RecipeCatalysts {
@@ -8,13 +8,13 @@ import net.minecraft.client.gui.inventory.GuiCrafting;
import net.minecraft.client.gui.inventory.GuiFurnace;
import net.minecraft.client.gui.inventory.GuiInventory;
import com.google.common.base.Objects;
import codechicken.nei.OffsetPositioner;
import codechicken.nei.api.API;
import codechicken.nei.api.IOverlayHandler;
import codechicken.nei.api.IStackPositioner;
import com.google.common.base.Objects;
public class RecipeInfo {
private static class OverlayKey {
@@ -21,6 +21,7 @@ import java.util.stream.Collectors;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.inventory.Container;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@@ -29,6 +30,8 @@ import net.minecraft.tileentity.TileEntityFurnace;
import org.lwjgl.opengl.GL11;
import com.google.common.base.Stopwatch;
import codechicken.lib.vec.Rectangle4i;
import codechicken.nei.ItemList;
import codechicken.nei.NEIClientConfig;
@@ -43,8 +46,6 @@ import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.guihook.IContainerInputHandler;
import codechicken.nei.guihook.IContainerTooltipHandler;
import com.google.common.base.Stopwatch;
/**
* A Template Recipe Handler! How about that. Because it was sooo hard, and more seriously required lots of copied code
* to make a handler in the past. you can now extend this class to make your custom recipe handlers much easier to
@@ -210,7 +211,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
for (int i = 0; i < stack.items.length; i++) {
if (NEIServerUtils.areStacksSameTypeCrafting(ingredient, stack.items[i])) {
stack.item = stack.items[i];
stack.item.setItemDamage(ingredient.getItemDamage());
Items.feather.setDamage(stack.item, Items.feather.getDamage(ingredient));
if (ingredient.hasTagCompound()) {
stack.item.setTagCompound((NBTTagCompound) ingredient.getTagCompound().copy());
}
@@ -0,0 +1,15 @@
# Each line in this file should either be a comment (line starts with '#'), or a fully-qualified class name (that
# includes the package name) for a recipe handler. Wildcard patterns ('*') can be used to catch multiple classes with a
# single entry.
# If you delete this file, it will be regenerated with the default height hacked handlers list.
buildcraft.compat.nei.*
cofh.thermalexpansion.plugins.nei.handlers.*
crazypants.enderio.nei.*
forestry.factory.recipes.nei.*
ic2.neiIntegration.core.recipehandler.*
mariculture.plugins.nei.*
redgear.brewcraft.plugins.nei.*
tconstruct.plugins.nei.*
WayofTime.alchemicalWizardry.client.nei.*
exnihilo.compatibility.nei.*
blusunrize.immersiveengineering.client.nei.*
@@ -0,0 +1,6 @@
# This version of NEI loads recipes in parallel. Some recipe handlers have not been designed with that in mind and might
# crash. List these handlers in this file to force them to be loaded single threaded. Each line in this file should
# either be a comment (line starts with '#'), or a fully-qualified class name (that includes the package name) for a
# recipe handler.
# If you delete this file, it will be regenerated with the default serial handlers list.
WayofTime.alchemicalWizardry.client.nei.NEIAlchemyRecipeHandler
@@ -550,8 +550,6 @@ nc.crafting.nei.FusionSteamRecipeHandler,NuclearCraft:fusionReactorSteam,,Nuclea
nc.crafting.nei.ElectrolyserRecipeHandler,NuclearCraft:electrolyserIdle,,NuclearCraft,TRUE,,,,,,
nc.crafting.nei.CrusherRecipeHandler,NuclearCraft:crusherIdle,,NuclearCraft,TRUE,,,,,,
nc.crafting.nei.ElectricCrusherRecipeHandler,NuclearCraft:electricCrusherIdle,,NuclearCraft,TRUE,,,,,,
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_Smoker,etfuturum:smoker,,etfuturum,TRUE,,,,,,not working well
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_BlastFurnace,etfuturum:blast_furnace,,etfuturum,TRUE,,,,,,not working well
connor135246.campfirebackport.client.compat.nei.NEICampfireRecipeHandler,campfirebackport:campfire,,campfirebackport,TRUE,,,,,,
connor135246.campfirebackport.client.compat.nei.NEICampfireRecipeHandler,campfirebackport:soul_campfire,,campfirebackport,TRUE,,,,,,
connor135246.campfirebackport.client.compat.nei.NEICampfireStateChangerHandler,campfirebackport:campfire,,campfirebackport,TRUE,,,,,,
1 handler itemName nbtInfo modId modRequired excludedModId priority minVersion maxVersion forceClassName itemNotes
550 nc.crafting.nei.ElectrolyserRecipeHandler NuclearCraft:electrolyserIdle NuclearCraft TRUE
551 nc.crafting.nei.CrusherRecipeHandler NuclearCraft:crusherIdle NuclearCraft TRUE
552 nc.crafting.nei.ElectricCrusherRecipeHandler NuclearCraft:electricCrusherIdle NuclearCraft TRUE
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_Smoker etfuturum:smoker etfuturum TRUE not working well
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_BlastFurnace etfuturum:blast_furnace etfuturum TRUE not working well
553 connor135246.campfirebackport.client.compat.nei.NEICampfireRecipeHandler campfirebackport:campfire campfirebackport TRUE
554 connor135246.campfirebackport.client.compat.nei.NEICampfireRecipeHandler campfirebackport:soul_campfire campfirebackport TRUE
555 connor135246.campfirebackport.client.compat.nei.NEICampfireStateChangerHandler campfirebackport:campfire campfirebackport TRUE
+9 -11
View File
@@ -373,11 +373,11 @@ NEIArcFurnaceHandlerCarrot Ingot,Immersive Engineering,minecraft:carrot,,Immersi
NEIArcFurnaceHandlerExtraction,Immersive Engineering,minecraft:glowstone_dust,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIShaderBagHandler,Immersive Engineering,ImmersiveEngineering:shaderBag,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIBlueprintHandler,Immersive Engineering,ImmersiveEngineering:woodenDevice:5,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEICokeOvenHandler,Immersive Engineering,ImmersiveEngineering:stoneDecoration:1,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIBlastFurnaceHandler,Immersive Engineering,ImmersiveEngineering:stoneDecoration:2,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEISqueezerHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:2,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIFermenterHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:3,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIRefineryHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:4,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEICokeOvenHandler,Immersive Engineering,ImmersiveEngineering:stoneDecoration:1,,ImmersiveEngineering,TRUE,,,71,166,2,,,,,,
blusunrize.immersiveengineering.client.nei.NEIBlastFurnaceHandler,Immersive Engineering,ImmersiveEngineering:stoneDecoration:2,,ImmersiveEngineering,TRUE,,,71,166,2,,,,,,
blusunrize.immersiveengineering.client.nei.NEISqueezerHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:2,,ImmersiveEngineering,TRUE,,1,64,166,2,,,,,,
blusunrize.immersiveengineering.client.nei.NEIFermenterHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:3,,ImmersiveEngineering,TRUE,,1,64,166,2,,,,,,
blusunrize.immersiveengineering.client.nei.NEIRefineryHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:4,,ImmersiveEngineering,TRUE,,,65,166,2,,,,,,
blusunrize.immersiveengineering.client.nei.NEIBottlingMachineHandler,Immersive Engineering,minecraft:glass_bottle,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEIMetalPressHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:13,,ImmersiveEngineering,TRUE,,,65,166,5,,,,,,
blusunrize.immersiveengineering.client.nei.NEICrusherHandler,Immersive Engineering,ImmersiveEngineering:metalMultiblock:5,,ImmersiveEngineering,TRUE,,,71,166,5,,,,,,
@@ -410,13 +410,13 @@ cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCharger,Thermal Expansio
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingMachine,Thermal Expansion,ThermalExpansion:Frame,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingSecure,Thermal Expansion,ThermalExpansion:material:16,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingUpgrade,Thermal Expansion,ThermalExpansion:Frame:3,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCrucible,Thermal Expansion,ThermalExpansion:Machine:4,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCrucible,Thermal Expansion,ThermalExpansion:Machine:4,,ThermalExpansion,TRUE,,,65,166,2,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerFurnace,Thermal Expansion,ThermalExpansion:Machine:0,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerInsolator,Thermal Expansion,ThermalExpansion:Machine:11,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerInsolator,Thermal Expansion,ThermalExpansion:Machine:11,,ThermalExpansion,TRUE,,,65,166,2,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerPulverizer,Thermal Expansion,ThermalExpansion:Machine:1,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerSawmill,Thermal Expansion,ThermalExpansion:Machine:2,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerSmelter,Thermal Expansion,ThermalExpansion:Machine:3,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerTransposer,Thermal Expansion,ThermalExpansion:Machine:5,,ThermalExpansion,TRUE,,,65,166,5,,,,,,
cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerTransposer,Thermal Expansion,ThermalExpansion:Machine:5,,ThermalExpansion,TRUE,,,65,166,2,,,,,,
mekanism.client.nei.ChemicalCrystallizerRecipeHandler,Mekanism,Mekanism:MachineBlock2:8,,Mekanism,TRUE,,,79,,4,,,,,,
mekanism.client.nei.ChemicalDissolutionChamberRecipeHandler,Mekanism,Mekanism:MachineBlock2:6,,Mekanism,TRUE,,,79,,4,,,,,,
mekanism.client.nei.ChemicalInfuserRecipeHandler,Mekanism,Mekanism:MachineBlock2:2,,Mekanism,TRUE,,,80,,4,,,,,,
@@ -437,7 +437,7 @@ mekanism.client.nei.ShapelessMekanismRecipeHandler,Mekanism,minecraft:crafting_t
mekanism.client.nei.SolarNeutronRecipeHandler,Mekanism,Mekanism:MachineBlock3:1,,Mekanism,TRUE,,,70,,5,,,,,,
mekanism.client.nei.ThermalEvaporationRecipeHandler,Mekanism,Mekanism:BasicBlock:14,,Mekanism,TRUE,,,62,,5,,,,,,
exnihilo.compatibility.nei.RecipeHandlerHammer,Ex Nihilo,exnihilo:hammer_iron,,exnihilo,TRUE,,,58,,5,,,,,,
exnihilo.compatibility.nei.RecipeHandlerSieve,Ex Nihilo,exnihilo:sifting_table,,exnihilo,TRUE,,,130,,2,,,,,,
exnihilo.compatibility.nei.RecipeHandlerSieve,Ex Nihilo,exnihilo:sifting_table,,exnihilo,TRUE,,,130,,1,,,,,,
gregtech.Alloy,GregTech-Addon,gregtech_addon:machine:56,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
gregtech.Assembler,GregTech-Addon,gregtech_addon:machine:60,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
gregtech.Bender,GregTech-Addon,gregtech_addon:machine:59,,gregtech_addon,TRUE,,15,145,166,2,,,,,,
@@ -499,8 +499,6 @@ nc.crafting.nei.FusionSteamRecipeHandler,NuclearCraft,NuclearCraft:fusionReactor
nc.crafting.nei.ElectrolyserRecipeHandler,NuclearCraft,NuclearCraft:electrolyserIdle,,NuclearCraft,TRUE,,,65,,4,,,,,,
nc.crafting.nei.CrusherRecipeHandler,NuclearCraft,NuclearCraft:crusherIdle,,NuclearCraft,TRUE,,,65,,4,,,,,,
nc.crafting.nei.ElectricCrusherRecipeHandler,NuclearCraft,NuclearCraft:electricCrusherIdle,,NuclearCraft,TRUE,,,65,,4,,,,,,
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_Smoker,EtFuturum Requiem,etfuturum:lit_smoker,,etfuturum,TRUE,,,65,166,5,,,,,,
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_BlastFurnace,EtFuturum Requiem,etfuturum:lit_blast_furnace,,etfuturum,TRUE,,,65,166,5,,,,,,
connor135246.campfirebackport.client.compat.nei.NEICampfireRecipeHandler,Campfire Backport,campfirebackport:campfire,,campfirebackport,TRUE,,,65,166,5,,,,,,
connor135246.campfirebackport.client.compat.nei.NEICampfireStateChangerHandler,Campfire Backport,campfirebackport:campfire_base,,campfirebackport,TRUE,,,65,166,5,,,,,,
net.blay09.mods.excompressum.compat.nei.RecipeHandlerHeavySieve,Ex Compressum,excompressum:heavySieve,,excompressum,TRUE,,,130,166,5,,,,,,
1 handler modName itemName nbtInfo modId modRequired excludedModId yShift handlerHeight handlerWidth maxRecipesPerPage imageResource imageX imageY imageWidth imageHeight itemNotes
373 NEIArcFurnaceHandlerExtraction Immersive Engineering minecraft:glowstone_dust ImmersiveEngineering TRUE 65 166 5
374 blusunrize.immersiveengineering.client.nei.NEIShaderBagHandler Immersive Engineering ImmersiveEngineering:shaderBag ImmersiveEngineering TRUE 65 166 5
375 blusunrize.immersiveengineering.client.nei.NEIBlueprintHandler Immersive Engineering ImmersiveEngineering:woodenDevice:5 ImmersiveEngineering TRUE 65 166 5
376 blusunrize.immersiveengineering.client.nei.NEICokeOvenHandler Immersive Engineering ImmersiveEngineering:stoneDecoration:1 ImmersiveEngineering TRUE 71 166 5 2
377 blusunrize.immersiveengineering.client.nei.NEIBlastFurnaceHandler Immersive Engineering ImmersiveEngineering:stoneDecoration:2 ImmersiveEngineering TRUE 71 166 5 2
378 blusunrize.immersiveengineering.client.nei.NEISqueezerHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:2 ImmersiveEngineering TRUE 1 71 64 166 5 2
379 blusunrize.immersiveengineering.client.nei.NEIFermenterHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:3 ImmersiveEngineering TRUE 1 71 64 166 5 2
380 blusunrize.immersiveengineering.client.nei.NEIRefineryHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:4 ImmersiveEngineering TRUE 65 166 5 2
381 blusunrize.immersiveengineering.client.nei.NEIBottlingMachineHandler Immersive Engineering minecraft:glass_bottle ImmersiveEngineering TRUE 65 166 5
382 blusunrize.immersiveengineering.client.nei.NEIMetalPressHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:13 ImmersiveEngineering TRUE 65 166 5
383 blusunrize.immersiveengineering.client.nei.NEICrusherHandler Immersive Engineering ImmersiveEngineering:metalMultiblock:5 ImmersiveEngineering TRUE 71 166 5
410 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingMachine Thermal Expansion ThermalExpansion:Frame ThermalExpansion TRUE 65 166 5
411 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingSecure Thermal Expansion ThermalExpansion:material:16 ThermalExpansion TRUE 65 166 5
412 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCraftingUpgrade Thermal Expansion ThermalExpansion:Frame:3 ThermalExpansion TRUE 65 166 5
413 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerCrucible Thermal Expansion ThermalExpansion:Machine:4 ThermalExpansion TRUE 65 166 5 2
414 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerFurnace Thermal Expansion ThermalExpansion:Machine:0 ThermalExpansion TRUE 65 166 5
415 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerInsolator Thermal Expansion ThermalExpansion:Machine:11 ThermalExpansion TRUE 65 166 5 2
416 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerPulverizer Thermal Expansion ThermalExpansion:Machine:1 ThermalExpansion TRUE 65 166 5
417 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerSawmill Thermal Expansion ThermalExpansion:Machine:2 ThermalExpansion TRUE 65 166 5
418 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerSmelter Thermal Expansion ThermalExpansion:Machine:3 ThermalExpansion TRUE 65 166 5
419 cofh.thermalexpansion.plugins.nei.handlers.RecipeHandlerTransposer Thermal Expansion ThermalExpansion:Machine:5 ThermalExpansion TRUE 65 166 5 2
420 mekanism.client.nei.ChemicalCrystallizerRecipeHandler Mekanism Mekanism:MachineBlock2:8 Mekanism TRUE 79 4
421 mekanism.client.nei.ChemicalDissolutionChamberRecipeHandler Mekanism Mekanism:MachineBlock2:6 Mekanism TRUE 79 4
422 mekanism.client.nei.ChemicalInfuserRecipeHandler Mekanism Mekanism:MachineBlock2:2 Mekanism TRUE 80 4
437 mekanism.client.nei.SolarNeutronRecipeHandler Mekanism Mekanism:MachineBlock3:1 Mekanism TRUE 70 5
438 mekanism.client.nei.ThermalEvaporationRecipeHandler Mekanism Mekanism:BasicBlock:14 Mekanism TRUE 62 5
439 exnihilo.compatibility.nei.RecipeHandlerHammer Ex Nihilo exnihilo:hammer_iron exnihilo TRUE 58 5
440 exnihilo.compatibility.nei.RecipeHandlerSieve Ex Nihilo exnihilo:sifting_table exnihilo TRUE 130 2 1
441 gregtech.Alloy GregTech-Addon gregtech_addon:machine:56 gregtech_addon TRUE 15 145 166 2
442 gregtech.Assembler GregTech-Addon gregtech_addon:machine:60 gregtech_addon TRUE 15 145 166 2
443 gregtech.Bender GregTech-Addon gregtech_addon:machine:59 gregtech_addon TRUE 15 145 166 2
499 nc.crafting.nei.ElectrolyserRecipeHandler NuclearCraft NuclearCraft:electrolyserIdle NuclearCraft TRUE 65 4
500 nc.crafting.nei.CrusherRecipeHandler NuclearCraft NuclearCraft:crusherIdle NuclearCraft TRUE 65 4
501 nc.crafting.nei.ElectricCrusherRecipeHandler NuclearCraft NuclearCraft:electricCrusherIdle NuclearCraft TRUE 65 4
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_Smoker EtFuturum Requiem etfuturum:lit_smoker etfuturum TRUE 65 166 5
ganymedes01.etfuturum.NEI_EtFuturum_Config$NEI_Recipes_BlastFurnace EtFuturum Requiem etfuturum:lit_blast_furnace etfuturum TRUE 65 166 5
502 connor135246.campfirebackport.client.compat.nei.NEICampfireRecipeHandler Campfire Backport campfirebackport:campfire campfirebackport TRUE 65 166 5
503 connor135246.campfirebackport.client.compat.nei.NEICampfireStateChangerHandler Campfire Backport campfirebackport:campfire_base campfirebackport TRUE 65 166 5
504 net.blay09.mods.excompressum.compat.nei.RecipeHandlerHeavySieve Ex Compressum excompressum:heavySieve excompressum TRUE 130 166 5
+10 -1
View File
@@ -9,6 +9,7 @@ nei.key.ctrl.mac=CMD
nei.bookmark.toggle=Bookmarks
nei.bookmark.toggle.tip=Toggle visibility of the Bookmark Panel
nei.bookmark.viewmode.toggle.tip=Toggle Bookmark View Mode
nei.bookmark.pullBookmarkedItems.tip=Pull all bookmarked items from storage to inventory
nei.itempanel.quantity.default=One stack
nei.itempanel.loading=Loading Item List...
@@ -44,12 +45,16 @@ nei.inventory.magnet.enable=Enable magnet mode
nei.inventory.magnet.1=Turn magnet mode on
nei.inventory.magnet.0=Turn magnet mode off
nei.inventory.dawn.enable=Enable dawn-noon
nei.inventory.dawn.disable=Right-click: Disable dawn-noon phase
nei.inventory.dawn.set=Set time to dawn
nei.inventory.noon.enable=Enable noon-dusk
nei.inventory.noon.disable=Right-click: Disable noon-dusk phase
nei.inventory.noon.set=Set time to noon
nei.inventory.dusk.enable=Enable dusk-midnight
nei.inventory.dusk.disable=Right-click: Disable dusk-midnight phase
nei.inventory.dusk.set=Set time to dusk
nei.inventory.midnight.enable=Enable midnight-dawn
nei.inventory.midnight.disable=Right-click: Disable midnight-dawn phase
nei.inventory.midnight.set=Set time to midnight
nei.inventory.heal=Heal the player
nei.inventory.current.gamemode.0=Current gamemode: survival
@@ -102,6 +107,7 @@ nei.options.keys.gui.search=Focus Search Bar
nei.options.keys.gui.bookmark=Add Bookmark
nei.options.keys.gui.bookmark_recipe=Add Bookmark with Recipe
nei.options.keys.gui.bookmark_count=Add Bookmark with Count
nei.options.keys.gui.bookmark_pull_items=Pull all Bookmarked Items
nei.options.keys.gui.bookmark_recipe_count=Add Bookmark with Recipe & Count
nei.options.keys.gui.hide_bookmarks=Toggle Bookmark Panel Visibility
nei.options.keys.gui.overlay=Overlay Recipe
@@ -148,6 +154,9 @@ nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.false=Disabled
nei.options.inventory.useNBTInBookmarks=Use NBT in Bookmarks
nei.options.inventory.useNBTInBookmarks.true=Yes
nei.options.inventory.useNBTInBookmarks.false=No
nei.options.inventory.recipeTooltipsEnabled=Show recipe tooltips in Bookmarks
nei.options.inventory.recipeTooltipsEnabled.true=Yes
nei.options.inventory.recipeTooltipsEnabled.false=No
nei.options.inventory.bookmarksAnimationEnabled=REI Style Animation in Bookmarks
nei.options.inventory.bookmarksAnimationEnabled.true=Yes
nei.options.inventory.bookmarksAnimationEnabled.false=No
@@ -338,4 +347,4 @@ nei.presets.whitelist.tooltip=Whitelist
nei.presets.textfield.tooltip.1=Enter - save
nei.presets.textfield.tooltip.2=Escape - cancel
nei.presets.label.tooltip=Double click to edit
nei.presets.label.selected=%s Presets
nei.presets.label.selected=%s Presets