mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-11-14 17:24:41 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48934d621f | ||
|
|
0bbb889f39 | ||
|
|
af55a6b191 | ||
|
|
b3e1f23683 | ||
|
|
39578a4419 | ||
|
|
e3574800c0 | ||
|
|
5cd7556e6a | ||
|
|
80c2cba778 | ||
|
|
31173a1fbd | ||
|
|
fd08a93554 | ||
|
|
4dace1f6e5 | ||
|
|
0c0cf37eb0 | ||
|
|
3ec4f8dd68 | ||
|
|
e0dd6847cb | ||
|
|
6374c162ba | ||
|
|
8dd36f1c4a | ||
|
|
4613ade468 | ||
|
|
ca7030df72 | ||
|
|
b32f25c2ce | ||
|
|
4be7a30578 | ||
|
|
7ac3e32635 | ||
|
|
088d37a11a | ||
|
|
6a787dd5b7 | ||
|
|
c305649b95 | ||
|
|
b5d2815eab | ||
|
|
6049d0e9c3 | ||
|
|
9288fc4575 | ||
|
|
ec749ecc8e | ||
|
|
7471a82bca | ||
|
|
3f3c1791cb | ||
|
|
a0e16835c2 | ||
|
|
e9ce5cf72b | ||
|
|
fac011b67e | ||
|
|
f9c8ac504e | ||
|
|
f97711a33a | ||
|
|
b2934c4910 | ||
|
|
759ea69c9f | ||
|
|
36a2cafdac | ||
|
|
6100012f5b | ||
|
|
2e5781beb5 | ||
|
|
43918f3bb1 | ||
|
|
a41299dfca | ||
|
|
ee060b9253 | ||
|
|
82a2273995 | ||
|
|
06fadcc362 | ||
|
|
b328fd3db1 | ||
|
|
9563ebfe5a | ||
|
|
d9143c584e | ||
|
|
65652e5896 | ||
|
|
bd5e991a84 | ||
|
|
165afa2910 | ||
|
|
2507634196 | ||
|
|
e0171adc65 | ||
|
|
72ad8aa2e7 | ||
|
|
f0a554bcc1 | ||
|
|
65781a1649 | ||
|
|
6ad8f05323 | ||
|
|
d61a545d9d | ||
|
|
1774685af6 | ||
|
|
a63a227c3c | ||
|
|
0f115d5439 | ||
|
|
0fad93fb3b | ||
|
|
b1a34c761b | ||
|
|
cc9715d9f2 | ||
|
|
be253a00d2 | ||
|
|
5dde3b2e2f | ||
|
|
8da541460f | ||
|
|
dc4426d9c9 | ||
|
|
d05a9eafb3 | ||
|
|
5056fe5437 | ||
|
|
9fd9aad357 | ||
|
|
acaead41ee | ||
|
|
951f1b0d0d | ||
|
|
daab313288 | ||
|
|
25eaa492f7 | ||
|
|
1b34b24495 | ||
|
|
b9cd48f8f9 | ||
|
|
b2afc8c9e0 | ||
|
|
dc400ea560 | ||
|
|
ea03cfa17d | ||
|
|
94676e0934 | ||
|
|
f7ba34c0af | ||
|
|
db1fd255bb | ||
|
|
94ca7f3134 | ||
|
|
dea024173f | ||
|
|
af320a6c9f | ||
|
|
dcb10bb79d | ||
|
|
d3b6603d06 | ||
|
|
adf2065305 | ||
|
|
e30f6a41ad | ||
|
|
b1a45d0305 | ||
|
|
566d1b095d | ||
|
|
f35a92a101 | ||
|
|
fdf130f741 | ||
|
|
064f31f8db | ||
|
|
9b081ed2a7 | ||
|
|
2fc2ecf082 | ||
|
|
bc7efcfce5 | ||
|
|
0c5af2b892 | ||
|
|
0c61e559ec | ||
|
|
b94bd11e64 | ||
|
|
151a9957de | ||
|
|
b011024164 | ||
|
|
74d98a86f3 | ||
|
|
bd5946f5bf | ||
|
|
1647e8765f | ||
|
|
744b2ffc64 | ||
|
|
e88348aabf | ||
|
|
4766d90db0 | ||
|
|
1dc02a3730 | ||
|
|
a6a5e19e80 | ||
|
|
e9ab2eba9e | ||
|
|
0e3ff1ee06 | ||
|
|
95e9ac3c89 | ||
|
|
1ed004e619 | ||
|
|
153da523d6 | ||
|
|
c732361bbc | ||
|
|
bdb206b45d | ||
|
|
aa44a97f80 | ||
|
|
00c4411ec5 | ||
|
|
4f23d21d37 | ||
|
|
8569431e1d | ||
|
|
5b9c27e253 | ||
|
|
d613d06471 | ||
|
|
65ffbad491 | ||
|
|
885609720e | ||
|
|
bacf246504 | ||
|
|
1ab3350eb8 | ||
|
|
f3aa12483d | ||
|
|
d86c472790 | ||
|
|
4124151208 | ||
|
|
68ad800620 | ||
|
|
2c7207485d | ||
|
|
e8094794c3 | ||
|
|
ad86d8f9c5 | ||
|
|
30c87e9160 | ||
|
|
5eeb001534 | ||
|
|
962754ee10 | ||
|
|
0e34840c21 | ||
|
|
a12fadb10d | ||
|
|
9218e233aa | ||
|
|
23e16abae6 | ||
|
|
b3cb4db9ca | ||
|
|
45fea43a4b | ||
|
|
088d9c08a8 | ||
|
|
98547c2bcf | ||
|
|
02fa633043 | ||
|
|
9df6ab0232 | ||
|
|
89cc203875 | ||
|
|
4b247d08a5 | ||
|
|
8ecc8f20d5 | ||
|
|
74b9f8339a | ||
|
|
e20756a196 | ||
|
|
6d0f83c499 | ||
|
|
8e219c06be | ||
|
|
3fc576b6fc | ||
|
|
249cb2b308 | ||
|
|
e8d8c1994b | ||
|
|
195b47944f | ||
|
|
3224fdef7d | ||
|
|
46a159d788 | ||
|
|
bd20e00a6e | ||
|
|
bf06b09d5a | ||
|
|
1b1dd3567a | ||
|
|
f106b5e766 | ||
|
|
f1dea5460a | ||
|
|
9b73b94d16 | ||
|
|
e133afc774 | ||
|
|
75ff631f16 | ||
|
|
6f5d45c4ea | ||
|
|
fb51475bb9 | ||
|
|
99ec3a4204 | ||
|
|
8c4d609e4c | ||
|
|
336c7dc621 | ||
|
|
2130a47f6f | ||
|
|
73b492b0e3 | ||
|
|
efa69f31b6 | ||
|
|
95b437e5c9 | ||
|
|
afe3c54c29 | ||
|
|
2cab09e91b | ||
|
|
4b4ab434c0 | ||
|
|
9d108b21f9 | ||
|
|
2302dac5c0 | ||
|
|
7c2fb2df5f | ||
|
|
14aa3728ca | ||
|
|
66fc2270dd | ||
|
|
138d25dbfd | ||
|
|
d9191750a7 | ||
|
|
6d9ec0c0da | ||
|
|
617ac0600d | ||
|
|
7d7e3b61a6 | ||
|
|
748695158f | ||
|
|
a2c037e0c0 | ||
|
|
e93d23e444 | ||
|
|
748cfe3754 | ||
|
|
b64d104d7e | ||
|
|
46d90b6923 | ||
|
|
e61120099a | ||
|
|
bcb6eb214f | ||
|
|
9221434b2e | ||
|
|
02937061d4 | ||
|
|
0e6425295b |
No files matched your search
@@ -0,0 +1,2 @@
|
||||
# Ignore spotlessApply reformat
|
||||
f106b5e7665df6341ae8539f74dc391a7efc98b1
|
||||
@@ -0,0 +1,44 @@
|
||||
* text eol=lf
|
||||
|
||||
*.[jJ][aA][rR] binary
|
||||
|
||||
*.[pP][nN][gG] binary
|
||||
*.[jJ][pP][gG] binary
|
||||
*.[jJ][pP][eE][gG] binary
|
||||
*.[gG][iI][fF] binary
|
||||
*.[tT][iI][fF] binary
|
||||
*.[tT][iI][fF][fF] binary
|
||||
*.[iI][cC][oO] binary
|
||||
*.[sS][vV][gG] text
|
||||
*.[eE][pP][sS] binary
|
||||
*.[xX][cC][fF] binary
|
||||
|
||||
*.[kK][aA][rR] binary
|
||||
*.[mM]4[aA] binary
|
||||
*.[mM][iI][dD] binary
|
||||
*.[mM][iI][dD][iI] binary
|
||||
*.[mM][pP]3 binary
|
||||
*.[oO][gG][gG] binary
|
||||
*.[rR][aA] binary
|
||||
|
||||
*.7[zZ] binary
|
||||
*.[gG][zZ] binary
|
||||
*.[tT][aA][rR] binary
|
||||
*.[tT][gG][zZ] binary
|
||||
*.[zZ][iI][pP] binary
|
||||
|
||||
*.[tT][cC][nN] binary
|
||||
*.[sS][oO] binary
|
||||
*.[dD][lL][lL] binary
|
||||
*.[dD][yY][lL][iI][bB] binary
|
||||
*.[pP][sS][dD] binary
|
||||
*.[tT][tT][fF] binary
|
||||
*.[oO][tT][fF] binary
|
||||
|
||||
*.[pP][aA][tT][cC][hH] -text
|
||||
|
||||
*.[bB][aA][tT] text eol=crlf
|
||||
*.[cC][mM][dD] text eol=crlf
|
||||
*.[pP][sS]1 text eol=crlf
|
||||
|
||||
*[aA][uU][tT][oO][gG][eE][nN][eE][rR][aA][tT][eE][dD]* binary
|
||||
@@ -0,0 +1,62 @@
|
||||
name: Report Bug
|
||||
description: "Report a bug."
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "A bug/crash report with sufficient information and logs to reproduce and track down."
|
||||
- type: input
|
||||
id: discord
|
||||
attributes:
|
||||
label: Your GTNH Discord Username
|
||||
description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info.
|
||||
placeholder: "Example: Fake#1234"
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Mod Version
|
||||
description: "What version of the Mod are you using?"
|
||||
placeholder: "Example: 1.0.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: report
|
||||
attributes:
|
||||
label: Bug Report
|
||||
description: "Relevant information, as well as relevant logs attached such as `logs/fml-client-latest.log."
|
||||
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: java
|
||||
attributes:
|
||||
label: Java Version
|
||||
description: What Java version are you using? It's worth mentioning that if you play on Java9+ you should try update to latest minor release (e.g. prefer Java 17.0.6 over 17.0.2) of that version.
|
||||
options:
|
||||
- Java 8
|
||||
- Java 9
|
||||
- Java 11
|
||||
- Java 17
|
||||
- Java 19
|
||||
- Java 20
|
||||
- Java 21
|
||||
- Other (Please Specify)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: modlist
|
||||
attributes:
|
||||
label: Mod List or GTNH Pack Version
|
||||
description: "List of mods, ideally a minimal reproducible set (can be retrieved from latest.log). If using GTNH please indicate pack version and any changed mods, not the entire modlist."
|
||||
placeholder: "List of mods or GTNH Pack version goes here"
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: final
|
||||
attributes:
|
||||
label: Final Checklist
|
||||
description: Certify that you read things
|
||||
options:
|
||||
- label: "I have searched the issues and haven't found a similar issue."
|
||||
required: true
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Feature Request
|
||||
description: "Request a feature."
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "Please use this form to request features. We ask you check if it was already requested though"
|
||||
- type: input
|
||||
id: discord
|
||||
attributes:
|
||||
label: Your GTNH Discord Username
|
||||
description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info.
|
||||
placeholder: "Example: Wumpus#1234"
|
||||
- type: textarea
|
||||
id: request
|
||||
attributes:
|
||||
label: Feature Request
|
||||
description: "Relevant information, as well as relevant images"
|
||||
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: final
|
||||
attributes:
|
||||
label: Final Checklist
|
||||
description: Certify that you read things
|
||||
options:
|
||||
- label: "I have searched the issues and haven't found a similar issue."
|
||||
required: true
|
||||
+10
-1
@@ -1,6 +1,7 @@
|
||||
.gradle
|
||||
.settings
|
||||
/.idea/
|
||||
/.vscode/
|
||||
/run/
|
||||
/build/
|
||||
/eclipse/
|
||||
@@ -25,5 +26,13 @@ whitelist.json
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
src/main/resources/mixins.*.json
|
||||
src/main/resources/mixins.*([!.]).json
|
||||
*.bat
|
||||
*.DS_Store
|
||||
!gradlew.bat
|
||||
.factorypath
|
||||
addon.local.gradle
|
||||
addon.local.gradle.kts
|
||||
addon.late.local.gradle
|
||||
addon.late.local.gradle.kts
|
||||
layout.json
|
||||
@@ -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
|
||||
@@ -29,7 +29,7 @@ If you have issues with NEI outside of the GTNH modpack you may report them in t
|
||||
|
||||
## License
|
||||
|
||||
GTNH Modifications Copyright (c) 2019-2022 mitchej123 and the GTNH Team
|
||||
GTNH Modifications Copyright (c) 2019-2024 mitchej123 and the GTNH Team
|
||||
|
||||
Licensed under LGPL-3.0 or later - use this however you want, but please give back any modifications
|
||||
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
compileJava {
|
||||
options.encoding = "UTF-8"
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
+2
-929
@@ -1,932 +1,5 @@
|
||||
//version: 1656003794
|
||||
/*
|
||||
DO NOT CHANGE THIS FILE!
|
||||
|
||||
Also, you may replace this file at any time if there is an update available.
|
||||
Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates.
|
||||
*/
|
||||
|
||||
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.internal.logging.text.StyledTextOutput.Style
|
||||
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
||||
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
maven {
|
||||
name 'forge'
|
||||
url 'https://maven.minecraftforge.net'
|
||||
}
|
||||
maven {
|
||||
name 'sonatype'
|
||||
url 'https://oss.sonatype.org/content/repositories/snapshots/'
|
||||
}
|
||||
maven {
|
||||
name 'Scala CI dependencies'
|
||||
url 'https://repo1.maven.org/maven2/'
|
||||
}
|
||||
maven {
|
||||
name 'jitpack'
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.7'
|
||||
}
|
||||
}
|
||||
//version: 1707058017
|
||||
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'idea'
|
||||
id 'eclipse'
|
||||
id 'scala'
|
||||
id 'maven-publish'
|
||||
id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false
|
||||
id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false
|
||||
id 'com.google.devtools.ksp' version '1.5.30-1.0.0' apply false
|
||||
id 'org.ajoberstar.grgit' version '4.1.1'
|
||||
id 'com.github.johnrengelman.shadow' version '4.0.4'
|
||||
id 'com.palantir.git-version' version '0.13.0' apply false
|
||||
id 'de.undercouch.download' version '5.0.1'
|
||||
id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false
|
||||
id "com.diffplug.spotless" version "6.7.2"
|
||||
}
|
||||
|
||||
if (project.file('.git/HEAD').isFile()) {
|
||||
apply plugin: 'com.palantir.git-version'
|
||||
}
|
||||
|
||||
def out = services.get(StyledTextOutputFactory).create('an-output')
|
||||
|
||||
apply plugin: 'forge'
|
||||
|
||||
def projectJavaVersion = JavaLanguageVersion.of(8)
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(projectJavaVersion)
|
||||
}
|
||||
}
|
||||
|
||||
idea {
|
||||
module {
|
||||
inheritOutputDirs = true
|
||||
downloadJavadoc = true
|
||||
downloadSources = true
|
||||
}
|
||||
}
|
||||
|
||||
// Spotless autoformatter
|
||||
// See https://github.com/diffplug/spotless/tree/main/plugin-gradle
|
||||
// Can be locally toggled via spotless:off/spotless:on comments
|
||||
spotless {
|
||||
encoding 'UTF-8'
|
||||
|
||||
format 'misc', {
|
||||
target '*.md', '.gitignore'
|
||||
|
||||
trimTrailingWhitespace()
|
||||
indentWithSpaces(4)
|
||||
endWithNewline()
|
||||
}
|
||||
java {
|
||||
toggleOffOn()
|
||||
importOrder()
|
||||
removeUnusedImports()
|
||||
palantirJavaFormat('1.1.0') // last version supporting jvm 8
|
||||
}
|
||||
kotlin {
|
||||
toggleOffOn()
|
||||
ktfmt('0.39')
|
||||
}
|
||||
groovyGradle {
|
||||
toggleOffOn()
|
||||
importOrder()
|
||||
target '*.gradle'
|
||||
greclipse('4.19.0') // last version supporting jvm 8
|
||||
}
|
||||
}
|
||||
|
||||
if(JavaVersion.current() != JavaVersion.VERSION_1_8) {
|
||||
throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current())
|
||||
}
|
||||
|
||||
checkPropertyExists("modName")
|
||||
checkPropertyExists("modId")
|
||||
checkPropertyExists("modGroup")
|
||||
checkPropertyExists("autoUpdateBuildScript")
|
||||
checkPropertyExists("minecraftVersion")
|
||||
checkPropertyExists("forgeVersion")
|
||||
checkPropertyExists("replaceGradleTokenInFile")
|
||||
checkPropertyExists("gradleTokenModId")
|
||||
checkPropertyExists("gradleTokenModName")
|
||||
checkPropertyExists("gradleTokenVersion")
|
||||
checkPropertyExists("gradleTokenGroupName")
|
||||
checkPropertyExists("apiPackage")
|
||||
checkPropertyExists("accessTransformersFile")
|
||||
checkPropertyExists("usesMixins")
|
||||
checkPropertyExists("mixinPlugin")
|
||||
checkPropertyExists("mixinsPackage")
|
||||
checkPropertyExists("coreModClass")
|
||||
checkPropertyExists("containsMixinsAndOrCoreModOnly")
|
||||
checkPropertyExists("usesShadowedDependencies")
|
||||
checkPropertyExists("developmentEnvironmentUserName")
|
||||
|
||||
boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false
|
||||
boolean usesMixinDebug = project.findProperty('usesMixinDebug') ?: project.usesMixins.toBoolean()
|
||||
String channel = project.findProperty('channel') ? project.channel : 'stable'
|
||||
String mappingsVersion = project.findProperty('mappingsVersion') ? project.mappingsVersion : '12'
|
||||
String remoteMappings = project.findProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/'
|
||||
|
||||
String javaSourceDir = "src/main/java/"
|
||||
String scalaSourceDir = "src/main/scala/"
|
||||
String kotlinSourceDir = "src/main/kotlin/"
|
||||
|
||||
String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
String targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
|
||||
throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
|
||||
}
|
||||
|
||||
if(apiPackage) {
|
||||
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
|
||||
throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
|
||||
}
|
||||
}
|
||||
|
||||
if(accessTransformersFile) {
|
||||
String targetFile = "src/main/resources/META-INF/" + accessTransformersFile
|
||||
if(!getFile(targetFile).exists()) {
|
||||
throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile)
|
||||
}
|
||||
}
|
||||
|
||||
if(usesMixins.toBoolean()) {
|
||||
if(mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) {
|
||||
throw new GradleException("\"mixinPlugin\" requires \"mixinsPackage\" and \"mixinPlugin\" to be set!")
|
||||
}
|
||||
|
||||
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
|
||||
throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
|
||||
}
|
||||
|
||||
String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
|
||||
String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala"
|
||||
String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
|
||||
String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".kt"
|
||||
if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) {
|
||||
throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin)
|
||||
}
|
||||
}
|
||||
|
||||
if(coreModClass) {
|
||||
String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
|
||||
String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala"
|
||||
String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
|
||||
String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".kt"
|
||||
if(!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) {
|
||||
throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin)
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS)
|
||||
|
||||
// Make sure GregTech build won't time out
|
||||
System.setProperty("org.gradle.internal.http.connectionTimeout", 120000 as String)
|
||||
System.setProperty("org.gradle.internal.http.socketTimeout", 120000 as String)
|
||||
}
|
||||
|
||||
// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version
|
||||
try {
|
||||
'git config core.fileMode false'.execute()
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
out.style(Style.Failure).println("git isn't installed at all")
|
||||
}
|
||||
|
||||
// Pulls version first from the VERSION env and then git tag
|
||||
String identifiedVersion
|
||||
String versionOverride = System.getenv("VERSION") ?: null
|
||||
try {
|
||||
identifiedVersion = versionOverride == null ? gitVersion() : versionOverride
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
out.style(Style.Failure).text(
|
||||
'This mod must be version controlled by Git AND the repository must provide at least one tag,\n' +
|
||||
'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' +
|
||||
'clone the repository, see ').style(Style.Info).text('https://gtnh.miraheze.org/wiki/Development').style(Style.SuccessHeader).println(' for details.)'
|
||||
)
|
||||
versionOverride = 'NO-GIT-TAG-SET'
|
||||
identifiedVersion = versionOverride
|
||||
}
|
||||
version = minecraftVersion + '-' + identifiedVersion
|
||||
ext {
|
||||
modVersion = identifiedVersion
|
||||
}
|
||||
|
||||
if(identifiedVersion == versionOverride) {
|
||||
out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7')
|
||||
}
|
||||
|
||||
group = modGroup
|
||||
if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) {
|
||||
archivesBaseName = customArchiveBaseName
|
||||
}
|
||||
else {
|
||||
archivesBaseName = modId
|
||||
}
|
||||
|
||||
def arguments = []
|
||||
def jvmArguments = []
|
||||
|
||||
if (usesMixins.toBoolean()) {
|
||||
arguments += [
|
||||
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
|
||||
]
|
||||
if (usesMixinDebug.toBoolean()) {
|
||||
jvmArguments += [
|
||||
"-Dmixin.debug.countInjections=true",
|
||||
"-Dmixin.debug.verbose=true",
|
||||
"-Dmixin.debug.export=true"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
minecraft {
|
||||
version = minecraftVersion + '-' + forgeVersion + '-' + minecraftVersion
|
||||
runDir = 'run'
|
||||
|
||||
if (replaceGradleTokenInFile) {
|
||||
replaceIn replaceGradleTokenInFile
|
||||
if(gradleTokenModId) {
|
||||
replace gradleTokenModId, modId
|
||||
}
|
||||
if(gradleTokenModName) {
|
||||
replace gradleTokenModName, modName
|
||||
}
|
||||
if(gradleTokenVersion) {
|
||||
replace gradleTokenVersion, modVersion
|
||||
}
|
||||
if(gradleTokenGroupName) {
|
||||
replace gradleTokenGroupName, modGroup
|
||||
}
|
||||
}
|
||||
|
||||
clientIntellijRun {
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
|
||||
if(developmentEnvironmentUserName) {
|
||||
args("--username", developmentEnvironmentUserName)
|
||||
}
|
||||
}
|
||||
|
||||
serverIntellijRun {
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
}
|
||||
}
|
||||
|
||||
if(file('addon.gradle').exists()) {
|
||||
apply from: 'addon.gradle'
|
||||
}
|
||||
|
||||
apply from: 'repositories.gradle'
|
||||
|
||||
configurations {
|
||||
implementation.extendsFrom(shadowImplementation) // TODO: remove after all uses are refactored
|
||||
implementation.extendsFrom(shadowCompile)
|
||||
implementation.extendsFrom(shadeCompile)
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name 'Overmind forge repo mirror'
|
||||
url 'https://gregtech.overminddl1.com/'
|
||||
}
|
||||
if(usesMixins.toBoolean()) {
|
||||
maven {
|
||||
name 'sponge'
|
||||
url 'https://repo.spongepowered.org/repository/maven-public'
|
||||
}
|
||||
maven {
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
if(usesMixins.toBoolean()) {
|
||||
annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3')
|
||||
annotationProcessor('com.google.guava:guava:24.1.1-jre')
|
||||
annotationProcessor('com.google.code.gson:gson:2.8.6')
|
||||
annotationProcessor('org.spongepowered:mixin:0.8-SNAPSHOT')
|
||||
// using 0.8 to workaround a issue in 0.7 which fails mixin application
|
||||
compile('com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH') {
|
||||
// Mixin includes a lot of dependencies that are too up-to-date
|
||||
exclude module: 'launchwrapper'
|
||||
exclude module: 'guava'
|
||||
exclude module: 'gson'
|
||||
exclude module: 'commons-io'
|
||||
exclude module: 'log4j-core'
|
||||
}
|
||||
compile('com.github.GTNewHorizons:SpongeMixins:1.5.0')
|
||||
}
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json'
|
||||
def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap
|
||||
def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg"
|
||||
|
||||
task generateAssets {
|
||||
if (usesMixins.toBoolean()) {
|
||||
def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json");
|
||||
if (!mixinConfigFile.exists()) {
|
||||
mixinConfigFile.text = """{
|
||||
"required": true,
|
||||
"minVersion": "0.7.11",
|
||||
"package": "${modGroup}.${mixinsPackage}",
|
||||
"plugin": "${modGroup}.${mixinPlugin}",
|
||||
"refmap": "${mixingConfigRefMap}",
|
||||
"target": "@env(DEFAULT)",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"mixins": [],
|
||||
"client": [],
|
||||
"server": []
|
||||
}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task relocateShadowJar(type: ConfigureShadowRelocation) {
|
||||
target = tasks.shadowJar
|
||||
prefix = modGroup + ".shadow"
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
minimize() // This will only allow shading for actually used classes
|
||||
configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile]
|
||||
dependsOn(relocateShadowJar)
|
||||
}
|
||||
|
||||
jar {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
if(usesShadowedDependencies.toBoolean()) {
|
||||
dependsOn(shadowJar)
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
reobf {
|
||||
if(usesMixins.toBoolean()) {
|
||||
addExtraSrgFile mixinSrg
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
if(usesMixins.toBoolean()) {
|
||||
tasks.compileJava {
|
||||
options.compilerArgs += [
|
||||
"-AreobfSrgFile=${tasks.reobf.srg}",
|
||||
"-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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runClient {
|
||||
if(developmentEnvironmentUserName) {
|
||||
arguments += [
|
||||
"--username",
|
||||
developmentEnvironmentUserName
|
||||
]
|
||||
}
|
||||
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
}
|
||||
|
||||
runServer {
|
||||
args(arguments)
|
||||
jvmArgs(jvmArguments)
|
||||
}
|
||||
|
||||
tasks.withType(JavaExec).configureEach {
|
||||
javaLauncher.set(
|
||||
javaToolchains.launcherFor {
|
||||
languageVersion = projectJavaVersion
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
processResources {
|
||||
// this will ensure that this task is redone when the versions change.
|
||||
inputs.property "version", project.version
|
||||
inputs.property "mcversion", project.minecraft.version
|
||||
|
||||
// replace stuff in mcmod.info, nothing else
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include 'mcmod.info'
|
||||
|
||||
// replace modVersion and minecraftVersion
|
||||
expand "minecraftVersion": project.minecraft.version,
|
||||
"modVersion": modVersion,
|
||||
"modId": modId,
|
||||
"modName": modName
|
||||
}
|
||||
|
||||
if(usesMixins.toBoolean()) {
|
||||
from refMap
|
||||
}
|
||||
|
||||
// copy everything else that's not the mcmod.info
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
def getManifestAttributes() {
|
||||
def manifestAttributes = [:]
|
||||
if(!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) {
|
||||
manifestAttributes += ["FMLCorePluginContainsFMLMod": true]
|
||||
}
|
||||
|
||||
if(accessTransformersFile) {
|
||||
manifestAttributes += ["FMLAT" : accessTransformersFile.toString()]
|
||||
}
|
||||
|
||||
if(coreModClass) {
|
||||
manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass]
|
||||
}
|
||||
|
||||
if(usesMixins.toBoolean()) {
|
||||
manifestAttributes += [
|
||||
"TweakClass" : "org.spongepowered.asm.launch.MixinTweaker",
|
||||
"MixinConfigs" : "mixins." + modId + ".json",
|
||||
"ForceLoadAsMod" : !containsMixinsAndOrCoreModOnly.toBoolean()
|
||||
]
|
||||
}
|
||||
return manifestAttributes
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
from (sourceSets.main.allSource)
|
||||
from (file("$projectDir/LICENSE"))
|
||||
getArchiveClassifier().set('sources')
|
||||
}
|
||||
|
||||
task shadowDevJar(type: ShadowJar) {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
from sourceSets.main.output
|
||||
getArchiveClassifier().set("dev")
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
minimize() // This will only allow shading for actually used classes
|
||||
configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile]
|
||||
}
|
||||
|
||||
task relocateShadowDevJar(type: ConfigureShadowRelocation) {
|
||||
target = tasks.shadowDevJar
|
||||
prefix = modGroup + ".shadow"
|
||||
}
|
||||
|
||||
task circularResolverJar(type: Jar) {
|
||||
dependsOn(relocateShadowDevJar)
|
||||
dependsOn(shadowDevJar)
|
||||
enabled = false
|
||||
}
|
||||
|
||||
task devJar(type: Jar) {
|
||||
project.configurations.shadeCompile.each { dep ->
|
||||
from(project.zipTree(dep)) {
|
||||
exclude 'META-INF', 'META-INF/**'
|
||||
}
|
||||
}
|
||||
|
||||
from sourceSets.main.output
|
||||
getArchiveClassifier().set("dev")
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
if(usesShadowedDependencies.toBoolean()) {
|
||||
dependsOn(circularResolverJar)
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
task apiJar(type: Jar) {
|
||||
from (sourceSets.main.allSource) {
|
||||
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
|
||||
}
|
||||
|
||||
from (sourceSets.main.output) {
|
||||
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
|
||||
}
|
||||
|
||||
from (sourceSets.main.resources.srcDirs) {
|
||||
include("LICENSE")
|
||||
}
|
||||
|
||||
getArchiveClassifier().set('api')
|
||||
}
|
||||
|
||||
artifacts {
|
||||
if(!noPublishedSources) {
|
||||
archives sourcesJar
|
||||
}
|
||||
archives devJar
|
||||
if(apiPackage) {
|
||||
archives apiJar
|
||||
}
|
||||
}
|
||||
|
||||
// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID),
|
||||
// and isn't strictly needed with the POM so just disable it.
|
||||
tasks.withType(GenerateModuleMetadata) {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
// workaround variable hiding in pom processing
|
||||
def projectConfigs = project.configurations
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
from components.java
|
||||
if(usesShadowedDependencies.toBoolean()) {
|
||||
artifact source: shadowJar, classifier: ""
|
||||
}
|
||||
if(!noPublishedSources) {
|
||||
artifact source: sourcesJar, classifier: "sources"
|
||||
}
|
||||
artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev"
|
||||
if (apiPackage) {
|
||||
artifact source: apiJar, classifier: "api"
|
||||
}
|
||||
|
||||
groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons"
|
||||
artifactId = System.getenv("ARTIFACT_ID") ?: project.name
|
||||
// Using the identified version, not project.version as it has the prepended 1.7.10
|
||||
version = System.getenv("RELEASE_VERSION") ?: identifiedVersion
|
||||
|
||||
// remove extra garbage from minecraft and minecraftDeps configuration
|
||||
pom.withXml {
|
||||
def badArtifacts = [:].withDefault {[] as Set<String>}
|
||||
for (configuration in [projectConfigs.minecraft, projectConfigs.minecraftDeps]) {
|
||||
for (dependency in configuration.allDependencies) {
|
||||
badArtifacts[dependency.group == null ? "" : dependency.group] += dependency.name
|
||||
}
|
||||
}
|
||||
// example for specifying extra stuff to ignore
|
||||
// badArtifacts["org.example.group"] += "artifactName"
|
||||
|
||||
Node pomNode = asNode()
|
||||
pomNode.dependencies.'*'.findAll() {
|
||||
badArtifacts[it.groupId.text()].contains(it.artifactId.text())
|
||||
}.each() {
|
||||
it.parent().remove(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases"
|
||||
credentials {
|
||||
username = System.getenv("MAVEN_USER") ?: "NONE"
|
||||
password = System.getenv("MAVEN_PASSWORD") ?: "NONE"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Updating
|
||||
task updateBuildScript {
|
||||
doLast {
|
||||
if (performBuildScriptUpdate(projectDir.toString())) return
|
||||
|
||||
print("Build script already up-to-date!")
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewBuildScriptVersionAvailable(projectDir.toString())) {
|
||||
if (autoUpdateBuildScript.toBoolean()) {
|
||||
performBuildScriptUpdate(projectDir.toString())
|
||||
} else {
|
||||
out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'")
|
||||
}
|
||||
}
|
||||
|
||||
static URL availableBuildScriptUrl() {
|
||||
new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/build.gradle")
|
||||
}
|
||||
|
||||
boolean performBuildScriptUpdate(String projectDir) {
|
||||
if (isNewBuildScriptVersionAvailable(projectDir)) {
|
||||
def buildscriptFile = getFile("build.gradle")
|
||||
availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } }
|
||||
out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
boolean isNewBuildScriptVersionAvailable(String projectDir) {
|
||||
Map parameters = ["connectTimeout": 2000, "readTimeout": 2000]
|
||||
|
||||
String currentBuildScript = getFile("build.gradle").getText()
|
||||
String currentBuildScriptHash = getVersionHash(currentBuildScript)
|
||||
String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText()
|
||||
String availableBuildScriptHash = getVersionHash(availableBuildScript)
|
||||
|
||||
boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash
|
||||
return !isUpToDate
|
||||
}
|
||||
|
||||
static String getVersionHash(String buildScriptContent) {
|
||||
String versionLine = buildScriptContent.find("^//version: [a-z0-9]*")
|
||||
if(versionLine != null) {
|
||||
return versionLine.split(": ").last()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
configure(updateBuildScript) {
|
||||
group = 'forgegradle'
|
||||
description = 'Updates the build script to the latest version'
|
||||
}
|
||||
|
||||
// Parameter Deobfuscation
|
||||
|
||||
task deobfParams {
|
||||
doLast {
|
||||
|
||||
String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion"
|
||||
String mcpZIP = "$mcpDir/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip"
|
||||
String paramsCSV = "$mcpDir/params.csv"
|
||||
|
||||
download.run {
|
||||
src "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion-$minecraftVersion/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip"
|
||||
dest mcpZIP
|
||||
overwrite false
|
||||
}
|
||||
|
||||
if(!file(paramsCSV).exists()) {
|
||||
println("Extracting MCP archive ...")
|
||||
unzip(mcpZIP, mcpDir)
|
||||
}
|
||||
|
||||
println("Parsing params.csv ...")
|
||||
Map<String, String> params = new HashMap<>()
|
||||
Files.lines(Paths.get(paramsCSV)).forEach{line ->
|
||||
String[] cells = line.split(",")
|
||||
if(cells.length > 2 && cells[0].matches("p_i?\\d+_\\d+_")) {
|
||||
params.put(cells[0], cells[1])
|
||||
}
|
||||
}
|
||||
|
||||
out.style(Style.Success).println("Modified ${replaceParams(file("$projectDir/src/main/java"), params)} files!")
|
||||
out.style(Style.Failure).println("Don't forget to verify that the code still works as before!\n It could be broken due to duplicate variables existing now\n or parameters taking priority over other variables.")
|
||||
}
|
||||
}
|
||||
|
||||
static int replaceParams(File file, Map<String, String> params) {
|
||||
int fileCount = 0
|
||||
|
||||
if(file.isDirectory()) {
|
||||
for(File f : file.listFiles()) {
|
||||
fileCount += replaceParams(f, params)
|
||||
}
|
||||
return fileCount
|
||||
}
|
||||
println("Visiting ${file.getName()} ...")
|
||||
try {
|
||||
String content = new String(Files.readAllBytes(file.toPath()))
|
||||
int hash = content.hashCode()
|
||||
params.forEach{key, value ->
|
||||
content = content.replaceAll(key, value)
|
||||
}
|
||||
if(hash != content.hashCode()) {
|
||||
Files.write(file.toPath(), content.getBytes("UTF-8"))
|
||||
return 1
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Credit: bitsnaps (https://gist.github.com/bitsnaps/00947f2dce66f4bbdabc67d7e7b33681)
|
||||
static unzip(String zipFileName, String outputDir) {
|
||||
byte[] buffer = new byte[16384]
|
||||
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName))
|
||||
ZipEntry zipEntry = zis.getNextEntry()
|
||||
while (zipEntry != null) {
|
||||
File newFile = new File(outputDir + File.separator, zipEntry.name)
|
||||
if (zipEntry.isDirectory()) {
|
||||
if (!newFile.isDirectory() && !newFile.mkdirs()) {
|
||||
throw new IOException("Failed to create directory $newFile")
|
||||
}
|
||||
} else {
|
||||
// fix for Windows-created archives
|
||||
File parent = newFile.parentFile
|
||||
if (!parent.isDirectory() && !parent.mkdirs()) {
|
||||
throw new IOException("Failed to create directory $parent")
|
||||
}
|
||||
// write file content
|
||||
FileOutputStream fos = new FileOutputStream(newFile)
|
||||
int len = 0
|
||||
while ((len = zis.read(buffer)) > 0) {
|
||||
fos.write(buffer, 0, len)
|
||||
}
|
||||
fos.close()
|
||||
}
|
||||
zipEntry = zis.getNextEntry()
|
||||
}
|
||||
zis.closeEntry()
|
||||
zis.close()
|
||||
}
|
||||
|
||||
configure(deobfParams) {
|
||||
group = 'forgegradle'
|
||||
description = 'Rename all obfuscated parameter names inherited from Minecraft classes'
|
||||
}
|
||||
|
||||
// Dependency Deobfuscation
|
||||
|
||||
def deobf(String sourceURL) {
|
||||
try {
|
||||
URL url = new URL(sourceURL)
|
||||
String fileName = url.getFile()
|
||||
|
||||
//get rid of directories:
|
||||
int lastSlash = fileName.lastIndexOf("/")
|
||||
if(lastSlash > 0) {
|
||||
fileName = fileName.substring(lastSlash + 1)
|
||||
}
|
||||
//get rid of extension:
|
||||
if(fileName.endsWith(".jar") || fileName.endsWith(".litemod")) {
|
||||
fileName = fileName.substring(0, fileName.lastIndexOf("."))
|
||||
}
|
||||
|
||||
String hostName = url.getHost()
|
||||
if(hostName.startsWith("www.")) {
|
||||
hostName = hostName.substring(4)
|
||||
}
|
||||
List parts = Arrays.asList(hostName.split("\\."))
|
||||
Collections.reverse(parts)
|
||||
hostName = String.join(".", parts)
|
||||
|
||||
return deobf(sourceURL, "$hostName/$fileName")
|
||||
} catch(Exception e) {
|
||||
return deobf(sourceURL, "deobf/${sourceURL.hashCode()}")
|
||||
}
|
||||
}
|
||||
|
||||
// The method above is to be preferred. Use this method if the filename is not at the end of the URL.
|
||||
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
|
||||
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
|
||||
dest obfFile
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!project.hasProperty(propertyName)) {
|
||||
throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/gradle.properties")
|
||||
}
|
||||
}
|
||||
|
||||
def getFile(String relativePath) {
|
||||
return new File(projectDir, relativePath)
|
||||
id 'com.gtnewhorizons.gtnhconvention'
|
||||
}
|
||||
+4
-3
@@ -1,7 +1,8 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
compile('com.github.GTNewHorizons:CodeChickenLib:1.1.5.3:dev')
|
||||
compile('com.github.GTNewHorizons:CodeChickenCore:1.1.3:dev')
|
||||
shadowImplementation('org.apache.commons:commons-csv:1.8')
|
||||
api('com.github.GTNewHorizons:CodeChickenCore:1.4.1:dev')
|
||||
implementation('com.github.GTNewHorizons:GTNHLib:0.6.5:dev')
|
||||
|
||||
shadowImplementation('org.apache.commons:commons-csv:1.10.0')
|
||||
}
|
||||
+166
-23
@@ -1,60 +1,203 @@
|
||||
# ExampleMod tag to use as Blowdryer (Spotless, etc.) settings version, leave empty to disable.
|
||||
# LOCAL to test local config updates.
|
||||
gtnh.settings.blowdryerTag = 0.2.0
|
||||
|
||||
# Human-readable mod name, available for mcmod.info population.
|
||||
modName = NotEnoughItems
|
||||
|
||||
# This is a case-sensitive string to identify your mod. Convention is to use lower case.
|
||||
# Case-sensitive identifier string, available for mcmod.info population and used for automatic mixin JSON generation.
|
||||
# Conventionally lowercase.
|
||||
modId = NotEnoughItems
|
||||
|
||||
# Root package of the mod, used to find various classes in other properties,
|
||||
# mcmod.info substitution, enabling assertions in run tasks, etc.
|
||||
modGroup = codechicken.nei
|
||||
|
||||
# WHY is there no version field?
|
||||
# The build script relies on git to provide a version via tags. It is super easy and will enable you to always know the
|
||||
# code base or your binary. Check out this tutorial: https://blog.mattclemente.com/2017/10/13/versioning-with-git-tags/
|
||||
# Whether to use modGroup as the maven publishing group.
|
||||
# Due to a history of using JitPack, the default is com.github.GTNewHorizons for all mods.
|
||||
useModGroupForPublishing = false
|
||||
|
||||
# Will update your build.gradle automatically whenever an update is available
|
||||
# Updates your build.gradle and settings.gradle automatically whenever an update is available.
|
||||
autoUpdateBuildScript = false
|
||||
|
||||
# Version of Minecraft to target
|
||||
minecraftVersion = 1.7.10
|
||||
|
||||
# Version of Minecraft Forge to target
|
||||
forgeVersion = 10.13.4.1614
|
||||
|
||||
# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you
|
||||
# restart Minecraft in development. Choose this dependent on your mod:
|
||||
# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name
|
||||
# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty
|
||||
# Specify an MCP channel for dependency deobfuscation and the deobfParams task.
|
||||
channel = stable
|
||||
|
||||
# Specify an MCP mappings version for dependency deobfuscation and the deobfParams task.
|
||||
mappingsVersion = 12
|
||||
|
||||
# Defines other MCP mappings for dependency deobfuscation.
|
||||
remoteMappings = https\://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/
|
||||
|
||||
# Select a default username for testing your mod. You can always override this per-run by running
|
||||
# `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE.
|
||||
developmentEnvironmentUserName = Developer
|
||||
|
||||
# Define a source file of your project with:
|
||||
# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8.
|
||||
# See https://github.com/bsideup/jabel for details on how this works.
|
||||
enableModernJavaSyntax = true
|
||||
|
||||
# Enables injecting missing generics into the decompiled source code for a better coding experience.
|
||||
# Turns most publicly visible List, Map, etc. into proper List<E>, Map<K, V> types.
|
||||
enableGenericInjection = true
|
||||
|
||||
# Generate a class with a String field for the mod version named as defined below.
|
||||
# If generateGradleTokenClass is empty or not missing, no such class will be generated.
|
||||
# If gradleTokenVersion is empty or missing, the field will not be present in the class.
|
||||
generateGradleTokenClass = codechicken.nei.Tags
|
||||
|
||||
# Name of the token containing the project's current version to generate/replace.
|
||||
gradleTokenVersion = VERSION
|
||||
|
||||
# [DEPRECATED] Mod ID replacement token.
|
||||
gradleTokenModId =
|
||||
|
||||
# [DEPRECATED] Mod name replacement token.
|
||||
gradleTokenModName =
|
||||
|
||||
# [DEPRECATED] Mod Group replacement token.
|
||||
gradleTokenGroupName =
|
||||
|
||||
# [DEPRECATED]
|
||||
# Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java
|
||||
# public static final String VERSION = "GRADLETOKEN_VERSION";
|
||||
# The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's
|
||||
# version in @Mod([...], version = VERSION, [...])
|
||||
# Leave these properties empty to skip individual token replacements
|
||||
replaceGradleTokenInFile = NEIModContainer.java
|
||||
gradleTokenModId = GRADLETOKEN_MODID
|
||||
gradleTokenModName = GRADLETOKEN_MODNAME
|
||||
gradleTokenVersion = GRADLETOKEN_VERSION
|
||||
gradleTokenGroupName =
|
||||
# version in @Mod([...], version = VERSION, [...]).
|
||||
# Leave these properties empty to skip individual token replacements.
|
||||
replaceGradleTokenInFile =
|
||||
|
||||
# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can
|
||||
# leave this property empty.
|
||||
# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api
|
||||
# Example value: (apiPackage = api) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.api
|
||||
apiPackage =
|
||||
|
||||
# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/
|
||||
# Example value: mymodid_at.cfg
|
||||
# There can be multiple files in a space-separated list.
|
||||
# Example value: mymodid_at.cfg nei_at.cfg
|
||||
accessTransformersFile = nei_at.cfg
|
||||
|
||||
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
|
||||
usesMixins = false
|
||||
# Specify the location of your implementation of IMixinPlugin. Leave it empty otherwise.
|
||||
|
||||
# Set to a non-empty string to configure mixins in a separate source set under src/VALUE, instead of src/main.
|
||||
# This can speed up compile times thanks to not running the mixin annotation processor on all input sources.
|
||||
# Mixin classes will have access to "main" classes, but not the other way around.
|
||||
separateMixinSourceSet =
|
||||
|
||||
# Adds some debug arguments like verbose output and class export.
|
||||
usesMixinDebug = false
|
||||
|
||||
# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise.
|
||||
mixinPlugin =
|
||||
|
||||
# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
|
||||
mixinsPackage =
|
||||
|
||||
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
|
||||
# This parameter is for legacy compatibility only
|
||||
# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin
|
||||
# Example value: (coreModClass = asm.FMLPlugin) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.asm.FMLPlugin
|
||||
coreModClass = asm.NEICorePlugin
|
||||
|
||||
# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class
|
||||
# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false!
|
||||
containsMixinsAndOrCoreModOnly = true
|
||||
|
||||
# If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your
|
||||
# responsibility check the licence and request permission for distribution, if required.
|
||||
# Enables Mixins even if this mod doesn't use them, useful if one of the dependencies uses mixins.
|
||||
forceEnableMixins = false
|
||||
|
||||
# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated into your jar. It is your
|
||||
# responsibility to check the license and request permission for distribution if required.
|
||||
usesShadowedDependencies = true
|
||||
|
||||
# If disabled, won't remove unused classes from shadowed dependencies. Some libraries use reflection to access
|
||||
# their own classes, making the minimization unreliable.
|
||||
minimizeShadowedDependencies = true
|
||||
|
||||
# If disabled, won't rename the shadowed classes.
|
||||
relocateShadowedDependencies = true
|
||||
|
||||
# Adds CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
|
||||
includeWellKnownRepositories = true
|
||||
|
||||
# A list of repositories to exclude from the includeWellKnownRepositories setting. Should be a space separated
|
||||
# list of strings, with the acceptable keys being(case does not matter):
|
||||
# cursemaven
|
||||
# modrinth
|
||||
excludeWellKnownRepositories =
|
||||
|
||||
# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven.
|
||||
# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables.
|
||||
# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle.
|
||||
usesMavenPublishing = true
|
||||
|
||||
# Maven repository to publish the mod to.
|
||||
# mavenPublishUrl = https\://nexus.gtnewhorizons.com/repository/releases/
|
||||
|
||||
# Publishing to Modrinth requires you to set the MODRINTH_TOKEN environment variable to your current Modrinth API token.
|
||||
#
|
||||
# The project's ID on Modrinth. Can be either the slug or the ID.
|
||||
# Leave this empty if you don't want to publish to Modrinth.
|
||||
modrinthProjectId = notenoughitems-unofficial
|
||||
|
||||
# The project's relations on Modrinth. You can use this to refer to other projects on Modrinth.
|
||||
# Syntax: scope1-type1:name1;scope2-type2:name2;...
|
||||
# Where scope can be one of [required, optional, incompatible, embedded],
|
||||
# type can be one of [project, version],
|
||||
# and the name is the Modrinth project or version slug/id of the other mod.
|
||||
# Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech
|
||||
# Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true
|
||||
modrinthRelations = required-project\:codechickencore-unofficial
|
||||
|
||||
# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens.
|
||||
#
|
||||
# The project's numeric ID on CurseForge. You can find this in the About Project box.
|
||||
# Leave this empty if you don't want to publish on CurseForge.
|
||||
curseForgeProjectId = 358228
|
||||
|
||||
# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge.
|
||||
# Syntax: type1:name1;type2:name2;...
|
||||
# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible],
|
||||
# and the name is the CurseForge project slug of the other mod.
|
||||
# Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft
|
||||
# Note: UniMixins is automatically set as a required dependency if usesMixins = true.
|
||||
curseForgeRelations = requiredDependency\:codechickencore-unofficial
|
||||
|
||||
# Optional parameter to customize the produced artifacts. Use this to preserve artifact naming when migrating older
|
||||
# projects. New projects should not use this parameter.
|
||||
# customArchiveBaseName =
|
||||
|
||||
# Optional parameter to have the build automatically fail if an illegal version is used.
|
||||
# This can be useful if you e.g. only want to allow versions in the form of '1.1.xxx'.
|
||||
# The check is ONLY performed if the version is a git tag.
|
||||
# Note: the specified string must be escaped, so e.g. 1\\.1\\.\\d+ instead of 1\.1\.\d+
|
||||
# versionPattern =
|
||||
|
||||
# Uncomment to prevent the source code from being published.
|
||||
# noPublishedSources = true
|
||||
|
||||
# Uncomment this to disable Spotless checks.
|
||||
# This should only be uncommented to keep it easier to sync with upstream/other forks.
|
||||
# That is, if there is no other active fork/upstream, NEVER change this.
|
||||
# disableSpotless = true
|
||||
|
||||
# Uncomment this to disable Checkstyle checks (currently wildcard import check).
|
||||
# disableCheckstyle = true
|
||||
|
||||
# Override the IDEA build type. Valid values are: "" (leave blank, do not override), "idea" (force use native IDEA build), "gradle"
|
||||
# (force use delegated build).
|
||||
# This is meant to be set in $HOME/.gradle/gradle.properties.
|
||||
# e.g. add "systemProp.org.gradle.project.ideaOverrideBuildType=idea" will override the build type to be native build.
|
||||
# WARNING: If you do use this option, it will overwrite whatever you have in your existing projects. This might not be what you want!
|
||||
# Usually there is no need to uncomment this here as other developers do not necessarily use the same build type as you.
|
||||
# ideaOverrideBuildType = idea
|
||||
|
||||
# Whether IDEA should run spotless checks when pressing the Build button.
|
||||
# This is meant to be set in $HOME/.gradle/gradle.properties.
|
||||
# ideaCheckSpotlessOnBuild = true
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+3
-1
@@ -1,5 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -15,80 +15,116 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# 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"'
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
@@ -97,92 +133,120 @@ Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
+27
-33
@@ -13,8 +13,10 @@
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -25,10 +27,14 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@@ -37,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
@@ -51,48 +57,36 @@ goto fail
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
@@ -1,18 +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'
|
||||
}
|
||||
}
|
||||
maven {
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
maven {
|
||||
// RetroFuturaGradle
|
||||
name "GTNH Maven"
|
||||
url "https://nexus.gtnewhorizons.com/repository/public/"
|
||||
mavenContent {
|
||||
includeGroup("com.gtnewhorizons")
|
||||
includeGroupByRegex("com\\.gtnewhorizons\\..+")
|
||||
}
|
||||
}
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.31'
|
||||
}
|
||||
|
||||
|
||||
|
||||
rootProject.name = "NotEnoughItems"
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
|
||||
public class AutoFocusWidget implements IContainerInputHandler {
|
||||
|
||||
/**
|
||||
* Implement this interface on a GuiContainer to enable the autofocus search in NEI (if the autofocus option is
|
||||
* enabled) without needing to add the classname to the config file .
|
||||
*/
|
||||
public interface INEIAutoFocusSearchEnable {
|
||||
}
|
||||
|
||||
public static AutoFocusWidget instance = new AutoFocusWidget();
|
||||
|
||||
public static List<String> enableAutoFocusPrefixes = new ArrayList<>();
|
||||
|
||||
protected boolean autofocus = false;
|
||||
protected Point mouse;
|
||||
|
||||
public AutoFocusWidget() {
|
||||
GuiContainerManager.addInputHandler(this);
|
||||
}
|
||||
|
||||
public void load(GuiContainer gui) {
|
||||
this.autofocus = LayoutManager.searchField.isVisible() && NEIClientConfig.searchWidgetAutofocus() != 0
|
||||
&& isAllowedGuiAutoSearchFocus(gui);
|
||||
this.mouse = getMousePosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
|
||||
if (this.autofocus) {
|
||||
this.autofocus = false;
|
||||
|
||||
if (!this.mouse.equals(getMousePosition())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.searchWidgetAutofocus() == 2
|
||||
&& GameSettings.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindInventory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keyCode == Keyboard.KEY_RETURN || keyCode == Keyboard.KEY_NUMPADENTER
|
||||
|| keyCode == Keyboard.KEY_ESCAPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LayoutManager.searchField.setFocus(true);
|
||||
LayoutManager.searchField.handleKeyPress(keyCode, keyChar);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
this.autofocus = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
this.autofocus = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) {}
|
||||
|
||||
@Override
|
||||
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
this.autofocus = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) {
|
||||
this.autofocus = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
this.autofocus = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
this.autofocus = false;
|
||||
}
|
||||
|
||||
protected boolean isAllowedGuiAutoSearchFocus(GuiContainer gui) {
|
||||
if (gui instanceof INEIAutoFocusSearchEnable) {
|
||||
return true;
|
||||
}
|
||||
String guiClassName = gui.getClass().getName();
|
||||
for (String prefix : enableAutoFocusPrefixes) {
|
||||
if (guiClassName.startsWith(prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
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) {
|
||||
if (gui != null) {
|
||||
return handlerMap.get(gui.getClass());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
API.registerBookmarkContainerHandler(GuiChest.class, new DefaultBookmarkContainerHandler());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import codechicken.nei.BookmarkPanel.ItemStackMetadata;
|
||||
import codechicken.nei.recipe.BookmarkRecipeId;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class BookmarkCraftingChain {
|
||||
|
||||
public HashMap<ItemStack, ItemStack> calculatedItems = new HashMap<>();
|
||||
public HashMap<ItemStack, Integer> multiplier = new HashMap<>();
|
||||
|
||||
public HashMap<ItemStack, ItemStack> inputs = new HashMap<>();
|
||||
public HashMap<ItemStack, ItemStack> outputs = new HashMap<>();
|
||||
public HashMap<ItemStack, ItemStack> remainder = new HashMap<>();
|
||||
public HashMap<ItemStack, ItemStack> intermediate = new HashMap<>();
|
||||
|
||||
protected static class CraftingChainItem {
|
||||
|
||||
public String guid;
|
||||
public int stackIndex = 0;
|
||||
public int recipeIndex = 0;
|
||||
public int factor = 0;
|
||||
public int count = 0;
|
||||
public boolean ingredient = false;
|
||||
public int fluidCellAmount = 1;
|
||||
public ItemStack stack = null;
|
||||
|
||||
public CraftingChainItem(ItemStack stack, ItemStackMetadata stackMetadata) {
|
||||
FluidStack fluid = StackInfo.getFluid(stack);
|
||||
this.recipeIndex = getRecipeIndex(stackMetadata.recipeId);
|
||||
this.ingredient = stackMetadata.ingredient;
|
||||
this.stack = stack;
|
||||
|
||||
if (fluid != null) {
|
||||
this.stackIndex = getStackIndex(fluid);
|
||||
this.count = fluid.amount * Math.max(0, stack.stackSize);
|
||||
this.fluidCellAmount = StackInfo.isFluidContainer(stack) ? fluid.amount : 1;
|
||||
this.factor = this.fluidCellAmount * stackMetadata.factor;
|
||||
} else {
|
||||
this.stackIndex = getStackIndex(stack);
|
||||
this.count = StackInfo.itemStackToNBT(stack).getInteger("Count");
|
||||
this.factor = stackMetadata.factor;
|
||||
}
|
||||
|
||||
this.guid = this.stackIndex + " " + this.recipeIndex;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack(long count) {
|
||||
return StackInfo.loadFromNBT(
|
||||
StackInfo.itemStackToNBT(this.stack),
|
||||
this.factor > 0 ? (count / this.fluidCellAmount) : 0);
|
||||
}
|
||||
|
||||
public static void clearStatic() {
|
||||
itemCache.clear();
|
||||
fluidCache.clear();
|
||||
recipeCache.clear();
|
||||
}
|
||||
|
||||
private static HashMap<ItemStack, Integer> itemCache = new HashMap<>();
|
||||
|
||||
private static int getStackIndex(ItemStack stackA) {
|
||||
|
||||
if (!itemCache.containsKey(stackA)) {
|
||||
|
||||
for (ItemStack item : itemCache.keySet()) {
|
||||
if (StackInfo.equalItemAndNBT(stackA, item, true)) {
|
||||
itemCache.put(stackA, itemCache.get(item));
|
||||
return itemCache.get(stackA);
|
||||
}
|
||||
}
|
||||
|
||||
itemCache.put(stackA, itemCache.size() + fluidCache.size());
|
||||
}
|
||||
|
||||
return itemCache.get(stackA);
|
||||
}
|
||||
|
||||
private static HashMap<FluidStack, Integer> fluidCache = new HashMap<>();
|
||||
|
||||
private static int getStackIndex(FluidStack fluidA) {
|
||||
|
||||
if (!fluidCache.containsKey(fluidA)) {
|
||||
for (FluidStack item : fluidCache.keySet()) {
|
||||
if (fluidA.isFluidEqual(item)) {
|
||||
fluidCache.put(fluidA, fluidCache.get(item));
|
||||
return fluidCache.get(fluidA);
|
||||
}
|
||||
}
|
||||
|
||||
fluidCache.put(fluidA, itemCache.size() + fluidCache.size());
|
||||
}
|
||||
|
||||
return fluidCache.get(fluidA);
|
||||
}
|
||||
|
||||
private static HashMap<BookmarkRecipeId, Integer> recipeCache = new HashMap<>();
|
||||
|
||||
private static int getRecipeIndex(BookmarkRecipeId recipe) {
|
||||
|
||||
if (recipe == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!recipeCache.containsKey(recipe)) {
|
||||
for (BookmarkRecipeId item : recipeCache.keySet()) {
|
||||
if (item.equals(recipe)) {
|
||||
recipeCache.put(recipe, recipeCache.get(item));
|
||||
return recipeCache.get(recipe);
|
||||
}
|
||||
}
|
||||
|
||||
recipeCache.put(recipe, recipeCache.size());
|
||||
}
|
||||
|
||||
return recipeCache.get(recipe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class CraftingChainRequest {
|
||||
|
||||
public List<CraftingChainItem> items = new ArrayList<>();
|
||||
|
||||
public HashMap<Integer, Integer> multiplier = new HashMap<>();
|
||||
public HashMap<String, Long> counts = new HashMap<>();
|
||||
|
||||
public HashMap<Integer, HashSet<CraftingChainItem>> inputs = new HashMap<>();
|
||||
public HashMap<Integer, HashSet<CraftingChainItem>> outputs = new HashMap<>();
|
||||
|
||||
public HashSet<Integer> initialItems = new HashSet<>();
|
||||
public HashSet<Integer> startedIngrs = new HashSet<>();
|
||||
|
||||
public CraftingChainRequest(List<ItemStack> items, List<ItemStackMetadata> metadata) {
|
||||
HashSet<Integer> inputs = new HashSet<>();
|
||||
HashSet<Integer> outputs = new HashSet<>();
|
||||
|
||||
for (int index = 0; index < items.size(); index++) {
|
||||
CraftingChainItem item = new CraftingChainItem(items.get(index), metadata.get(index));
|
||||
item.guid = item.ingredient ? "i" + item.guid : "r" + item.guid;
|
||||
this.items.add(item);
|
||||
|
||||
if (this.multiplier.get(item.recipeIndex) == null) {
|
||||
this.multiplier.put(item.recipeIndex, 0);
|
||||
}
|
||||
|
||||
this.counts.put(item.guid, this.counts.getOrDefault(item.guid, 0L) + item.count);
|
||||
|
||||
if (item.ingredient) {
|
||||
inputs.add(item.recipeIndex);
|
||||
|
||||
if (this.inputs.get(item.stackIndex) == null) {
|
||||
this.inputs.put(item.stackIndex, new HashSet<>());
|
||||
}
|
||||
|
||||
this.inputs.get(item.stackIndex).add(item);
|
||||
} else {
|
||||
outputs.add(item.recipeIndex);
|
||||
|
||||
if (this.outputs.get(item.stackIndex) == null) {
|
||||
this.outputs.put(item.stackIndex, new HashSet<>());
|
||||
}
|
||||
|
||||
this.outputs.get(item.stackIndex).add(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int recipeIndex : this.multiplier.keySet()) {
|
||||
if (recipeIndex == -1 || !inputs.contains(recipeIndex) || !outputs.contains(recipeIndex)) {
|
||||
this.initialItems.add(recipeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
for (CraftingChainItem item : this.items) {
|
||||
if (item.ingredient == false && !this.initialItems.contains(item.recipeIndex)) {
|
||||
this.startedIngrs.add(item.stackIndex);
|
||||
}
|
||||
}
|
||||
|
||||
CraftingChainItem.clearStatic();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void refresh(List<ItemStack> items, List<ItemStackMetadata> metadata) {
|
||||
CraftingChainRequest request = new CraftingChainRequest(items, metadata);
|
||||
HashMap<Integer, Long> iShift = new HashMap<>();
|
||||
HashMap<Integer, Long> oShift = new HashMap<>();
|
||||
boolean change = true;
|
||||
int iteration = 100;
|
||||
|
||||
while (--iteration > 0 && change) {
|
||||
change = false;
|
||||
for (int stackIndex : request.startedIngrs) {
|
||||
change = calculateShift(request, stackIndex) || change;
|
||||
}
|
||||
}
|
||||
|
||||
this.inputs.clear();
|
||||
this.outputs.clear();
|
||||
this.remainder.clear();
|
||||
this.intermediate.clear();
|
||||
this.calculatedItems.clear();
|
||||
this.multiplier.clear();
|
||||
|
||||
for (CraftingChainItem item : request.items) {
|
||||
if (request.initialItems.contains(item.recipeIndex)) {
|
||||
long iCount = calculateCount(request, request.inputs.get(item.stackIndex))
|
||||
- iShift.getOrDefault(item.stackIndex, 0L);
|
||||
this.calculatedItems.put(item.stack, item.stack);
|
||||
|
||||
if (iCount == 0) {
|
||||
this.inputs.put(item.stack, item.getItemStack(0));
|
||||
} else {
|
||||
long count = Math.min(iCount, item.count);
|
||||
this.inputs.put(item.stack, item.getItemStack(count));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + count);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (CraftingChainItem item : request.items) {
|
||||
if (!request.initialItems.contains(item.recipeIndex)) {
|
||||
long count = item.count + item.factor * request.multiplier.get(item.recipeIndex);
|
||||
this.calculatedItems.put(item.stack, item.getItemStack(count));
|
||||
|
||||
if (item.ingredient) { // input
|
||||
long oCount = calculateCount(request, request.outputs.get(item.stackIndex))
|
||||
- oShift.getOrDefault(item.stackIndex, 0L);
|
||||
|
||||
if (oCount < count) {
|
||||
this.inputs.put(item.stack, item.getItemStack(count - oCount));
|
||||
oShift.put(item.stackIndex, oShift.getOrDefault(item.stackIndex, 0L) + oCount);
|
||||
} else if (oCount >= count) {
|
||||
this.intermediate.put(item.stack, item.getItemStack(0));
|
||||
oShift.put(item.stackIndex, oShift.getOrDefault(item.stackIndex, 0L) + count);
|
||||
}
|
||||
|
||||
} else { // output
|
||||
long iCalcCount = calculateCount(request, request.inputs.get(item.stackIndex));
|
||||
long iCount = iCalcCount - iShift.getOrDefault(item.stackIndex, 0L);
|
||||
this.multiplier.put(item.stack, item.factor > 0 ? (int) (count / item.factor) : 0);
|
||||
|
||||
if (iCount >= count) {
|
||||
this.intermediate.put(item.stack, item.getItemStack(0));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + count);
|
||||
} else if (iCalcCount > 0) {
|
||||
this.remainder.put(item.stack, item.getItemStack(count - iCount));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + iCount);
|
||||
} else {
|
||||
this.outputs.put(item.stack, item.getItemStack(count - iCount));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + iCount);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean calculateShift(CraftingChainRequest request, int stackIndex) {
|
||||
|
||||
if (!request.outputs.containsKey(stackIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int minRecipeIndex = 0;
|
||||
int minShift = Integer.MAX_VALUE;
|
||||
|
||||
for (CraftingChainItem item : request.outputs.get(stackIndex)) {
|
||||
if (!request.initialItems.contains(item.recipeIndex) && item.factor > 0) {
|
||||
long ingrCount = calculateCount(request, request.inputs.get(item.stackIndex), item.recipeIndex);
|
||||
long outputCount = calculateCount(request, request.outputs.get(item.stackIndex));
|
||||
long shift = (long) Math.ceil((ingrCount - outputCount) / (double) item.factor);
|
||||
|
||||
if (shift > 0 && shift < minShift) {
|
||||
minShift = (int) shift;
|
||||
minRecipeIndex = item.recipeIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minShift < Integer.MAX_VALUE) {
|
||||
request.multiplier.put(minRecipeIndex, request.multiplier.get(minRecipeIndex) + minShift);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private long calculateCount(CraftingChainRequest request, HashSet<CraftingChainItem> items) {
|
||||
return calculateCount(request, items, -1);
|
||||
}
|
||||
|
||||
private long calculateCount(CraftingChainRequest request, HashSet<CraftingChainItem> items, int recipeIndex) {
|
||||
long count = 0L;
|
||||
|
||||
if (items != null) {
|
||||
for (CraftingChainItem item : items) {
|
||||
if (item.recipeIndex != recipeIndex || recipeIndex == -1) {
|
||||
count += request.counts.get(item.guid) + item.factor * request.multiplier.get(item.recipeIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -5,6 +5,7 @@ import static codechicken.lib.gui.GuiDraw.getStringWidth;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Button extends Widget {
|
||||
|
||||
public Button(String s) {
|
||||
label = s;
|
||||
}
|
||||
@@ -60,10 +61,7 @@ public abstract class Button extends Widget {
|
||||
public Image icon;
|
||||
|
||||
/**
|
||||
* 0x4 = state flag, as opposed to 1 click
|
||||
* 0 = normal
|
||||
* 1 = on
|
||||
* 2 = disabled
|
||||
* 0x4 = state flag, as opposed to 1 click 0 = normal 1 = on 2 = disabled
|
||||
*/
|
||||
public int state;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
public abstract class ButtonCycled extends Button {
|
||||
|
||||
public ButtonCycled() {}
|
||||
|
||||
public ButtonCycled(int num) {
|
||||
|
||||
@@ -1,36 +1,20 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.core.ClientUtils;
|
||||
import codechicken.core.GuiModListScroll;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
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;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
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;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
@@ -44,35 +28,34 @@ import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
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>.",
|
||||
"# Handlers will be sorted in order of number ascending, so smaller numbers first.",
|
||||
"# Any handlers that are missing from this file will be assigned to 0.",
|
||||
"# Negative numbers are fine.",
|
||||
"# If you delete this file, it will be regenerated with all registered handler IDs.",
|
||||
};
|
||||
private static ClientHandler instance;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
private ArrayList<EntityItem> SMPmagneticItems = new ArrayList<>();
|
||||
import codechicken.core.ClassDiscoverer;
|
||||
import codechicken.core.ClientUtils;
|
||||
import codechicken.core.GuiModListScroll;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.IConfigureNEI;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import cpw.mods.fml.client.CustomModLoadingErrorDisplayException;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class ClientHandler {
|
||||
|
||||
private static ClientHandler instance;
|
||||
private final ArrayList<EntityItem> SMPmagneticItems = new ArrayList<>();
|
||||
private World lastworld;
|
||||
private GuiScreen lastGui;
|
||||
|
||||
@@ -100,9 +83,10 @@ public class ClientHandler {
|
||||
items = SMPmagneticItems;
|
||||
} else {
|
||||
items = world.getEntitiesWithinAABB(
|
||||
EntityItem.class, player.boundingBox.expand(distancexz, distancey, distancexz));
|
||||
EntityItem.class,
|
||||
player.boundingBox.expand(distancexz, distancey, distancexz));
|
||||
}
|
||||
for (Iterator<EntityItem> iterator = items.iterator(); iterator.hasNext(); ) {
|
||||
for (Iterator<EntityItem> iterator = items.iterator(); iterator.hasNext();) {
|
||||
EntityItem item = iterator.next();
|
||||
|
||||
if (item.delayBeforeCanPickup > 0) continue;
|
||||
@@ -156,52 +140,77 @@ public class ClientHandler {
|
||||
|
||||
public static void preInit() {
|
||||
loadSerialHandlers();
|
||||
loadHiddenItems();
|
||||
loadHeightHackHandlers();
|
||||
loadHiddenHandlers();
|
||||
loadEnableAutoFocus();
|
||||
ItemInfo.preInit();
|
||||
StackInfo.loadGuidFilters();
|
||||
}
|
||||
|
||||
public static void loadSerialHandlers() {
|
||||
File file = NEIClientConfig.serialHandlersFile;
|
||||
public static void loadSettingsFile(String resource, Consumer<Stream<String>> callback) {
|
||||
loadSettingsFile(resource, (file, writer) -> {
|
||||
String folder = resource.substring(resource.lastIndexOf(".") + 1);
|
||||
URL defaultResource = ClientHandler.class.getResource("/assets/nei/" + folder + "/" + resource);
|
||||
|
||||
if (defaultResource != null) {
|
||||
try {
|
||||
IOUtils.copy(defaultResource.openStream(), writer);
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}, callback);
|
||||
}
|
||||
|
||||
public static void loadSettingsFile(String resource, BiConsumer<File, FileWriter> createDefault,
|
||||
Consumer<Stream<String>> callback) {
|
||||
File file = new File(NEIClientConfig.configDir, resource);
|
||||
|
||||
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);
|
||||
NEIClientConfig.logger.info("Creating default '{}' {}", resource, file);
|
||||
createDefault.accept(file, writer);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to save default serial handlers list to file {}", file, e);
|
||||
NEIClientConfig.logger.error("Failed to save default '{}' to file {}", resource, 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.logger.info("Loading '{}' file {}", resource, file);
|
||||
callback.accept(
|
||||
IOUtils.readLines(reader).stream().filter(line -> !line.startsWith("#") && !line.trim().isEmpty()));
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load serial handlers from file {}", file, e);
|
||||
NEIClientConfig.logger.error("Failed to load '{}' file {}", resource, file, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadHeightHackHandlers() {
|
||||
File file = NEIClientConfig.heightHackHandlersFile;
|
||||
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);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to save default height hack handlers list to file {}", file, e);
|
||||
}
|
||||
}
|
||||
public static void loadSerialHandlers() {
|
||||
loadSettingsFile(
|
||||
"serialhandlers.cfg",
|
||||
lines -> NEIClientConfig.serialHandlers = lines.collect(Collectors.toCollection(HashSet::new)));
|
||||
}
|
||||
|
||||
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)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load height hack handlers from file {}", file, e);
|
||||
}
|
||||
public static void loadHeightHackHandlers() {
|
||||
loadSettingsFile(
|
||||
"heighthackhandlers.cfg",
|
||||
lines -> NEIClientConfig.heightHackHandlerRegex = lines.map(Pattern::compile)
|
||||
.collect(Collectors.toCollection(HashSet::new)));
|
||||
}
|
||||
|
||||
public static void loadHiddenHandlers() {
|
||||
loadSettingsFile(
|
||||
"hiddenhandlers.cfg",
|
||||
lines -> NEIClientConfig.hiddenHandlers = lines.collect(Collectors.toCollection(HashSet::new)));
|
||||
}
|
||||
|
||||
public static void loadEnableAutoFocus() {
|
||||
loadSettingsFile(
|
||||
"enableautofocus.cfg",
|
||||
lines -> AutoFocusWidget.enableAutoFocusPrefixes = lines
|
||||
.collect(Collectors.toCollection(ArrayList::new)));
|
||||
}
|
||||
|
||||
public static void loadHiddenItems() {
|
||||
loadSettingsFile("hiddenitems.cfg", lines -> lines.forEach(API::hideItem));
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
@@ -218,55 +227,38 @@ public class ClientHandler {
|
||||
}
|
||||
|
||||
public static void postInit() {
|
||||
loadHandlerOrdering();
|
||||
GuiContainerManager.registerReloadResourceListener();
|
||||
}
|
||||
|
||||
public static void loadHandlerOrdering() {
|
||||
File file = NEIClientConfig.handlerOrderingFile;
|
||||
if (!file.exists()) {
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
NEIClientConfig.logger.info("Creating default handler ordering CSV {}", file);
|
||||
|
||||
List<String> toWrite = Lists.newArrayList(defaultHandlerOrdering);
|
||||
GuiRecipeTab.handlerMap.keySet().stream()
|
||||
.sorted()
|
||||
.forEach(handlerId -> toWrite.add(String.format("%s,0", handlerId)));
|
||||
final String COMMA_DELIMITER = ",";
|
||||
final String[] defaultHandlerOrdering = {
|
||||
"# Each line in this file should either be a comment (starts with '#') or an ordering.",
|
||||
"# Ordering lines are <handler ID>,<ordering number>.",
|
||||
"# Handlers will be sorted in order of number ascending, so smaller numbers first.",
|
||||
"# Any handlers that are missing from this file will be assigned to 0.", "# Negative numbers are fine.",
|
||||
"# If you delete this file, it will be regenerated with all registered handler IDs.", };
|
||||
|
||||
loadSettingsFile("handlerordering.csv", (file, writer) -> {
|
||||
List<String> toWrite = Lists.newArrayList(defaultHandlerOrdering);
|
||||
GuiRecipeTab.handlerMap.keySet().stream().sorted()
|
||||
.forEach(handlerId -> toWrite.add(String.format("%s" + COMMA_DELIMITER + "0", handlerId)));
|
||||
try {
|
||||
IOUtils.writeLines(toWrite, "\n", writer);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to save default handler ordering to file {}", file, e);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {}
|
||||
}, lines -> lines.map(line -> line.split(COMMA_DELIMITER)).filter(parts -> parts.length == 2).forEach(parts -> {
|
||||
String handlerId = parts[0];
|
||||
int ordering = Integer.parseInt(parts[1]);
|
||||
NEIClientConfig.handlerOrdering.put(handlerId, ordering);
|
||||
}));
|
||||
}
|
||||
|
||||
URL url;
|
||||
try {
|
||||
url = file.toURI().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
NEIClientConfig.logger.info("Invalid URL for handler ordering CSV.");
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
public static void loadPluginsList() {
|
||||
final ClassDiscoverer classDiscoverer = new ClassDiscoverer(
|
||||
test -> test.startsWith("NEI") && test.endsWith("Config.class"),
|
||||
IConfigureNEI.class);
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
|
||||
NEIClientConfig.logger.info("Loading handler ordering from file {}", file);
|
||||
CSVParser csvParser = CSVFormat.EXCEL.withCommentMarker('#').parse(reader);
|
||||
for (CSVRecord record : csvParser) {
|
||||
final String handlerId = record.get(0);
|
||||
|
||||
int ordering;
|
||||
try {
|
||||
ordering = Integer.parseInt(record.get(1));
|
||||
} catch (NumberFormatException e) {
|
||||
NEIClientConfig.logger.error("Error parsing CSV record {}: {}", record, e);
|
||||
continue;
|
||||
}
|
||||
|
||||
NEIClientConfig.handlerOrdering.put(handlerId, ordering);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.info("Error parsing CSV");
|
||||
e.printStackTrace();
|
||||
}
|
||||
NEIClientConfig.pluginsList.addAll(classDiscoverer.findClasses());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -279,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);
|
||||
@@ -309,6 +305,15 @@ public class ClientHandler {
|
||||
if (NEIClientConfig.isEnabled()) WorldOverlayRenderer.render(event.partialTicks);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@SubscribeEvent
|
||||
public void onWorldUnload(WorldEvent.Unload event) {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (event.world == mc.theWorld) {
|
||||
NEIClientConfig.unloadWorld();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadWorld(World world, boolean fromServer) {
|
||||
if (world != lastworld) {
|
||||
SMPmagneticItems.clear();
|
||||
@@ -319,10 +324,9 @@ public class ClientHandler {
|
||||
NEIClientConfig.setInternalEnabled(false);
|
||||
|
||||
if (!Minecraft.getMinecraft().isSingleplayer()) // wait for server to initiate in singleplayer
|
||||
NEIClientConfig.loadWorld("remote/" + ClientUtils.getServerIP().replace(':', '~'));
|
||||
|
||||
ItemMobSpawner.clearEntityReferences(world);
|
||||
NEIClientConfig.loadWorld("remote/" + ClientUtils.getServerIP().replace(':', '~'));
|
||||
}
|
||||
ItemMobSpawner.clearEntityReferences(world);
|
||||
|
||||
lastworld = world;
|
||||
}
|
||||
@@ -334,6 +338,7 @@ public class ClientHandler {
|
||||
|
||||
public static RuntimeException throwCME(final String message) {
|
||||
final GuiScreen errorGui = new GuiErrorScreen(null, null) {
|
||||
|
||||
@Override
|
||||
public void handleMouseInput() {}
|
||||
|
||||
@@ -349,19 +354,17 @@ public class ClientHandler {
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
CustomModLoadingErrorDisplayException e = new CustomModLoadingErrorDisplayException() {
|
||||
|
||||
private static final long serialVersionUID = -5593387489666663375L;
|
||||
|
||||
@Override
|
||||
public void initGui(GuiErrorScreen errorScreen, FontRenderer fontRenderer) {
|
||||
Minecraft.getMinecraft().displayGuiScreen(errorGui);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(
|
||||
GuiErrorScreen errorScreen,
|
||||
FontRenderer fontRenderer,
|
||||
int mouseRelX,
|
||||
int mouseRelY,
|
||||
public void drawScreen(GuiErrorScreen errorScreen, FontRenderer fontRenderer, int mouseRelX, int mouseRelY,
|
||||
float tickTime) {}
|
||||
};
|
||||
throw e;
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTBase.NBTPrimitive;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.StatCollector;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.EverythingItemFilter;
|
||||
import codechicken.nei.ItemList.NothingItemFilter;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.PresetsList.PresetMode;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.util.ItemStackFilterParser;
|
||||
|
||||
public class CollapsibleItems {
|
||||
|
||||
protected static class GroupItem {
|
||||
|
||||
public String guid;
|
||||
public ItemFilter filter;
|
||||
public boolean expanded = false;
|
||||
public String displayName = "";
|
||||
|
||||
public void setFilter(String filter) {
|
||||
this.filter = ItemStackFilterParser.parse(filter.trim());
|
||||
this.guid = this.filter != null ? UUID.nameUUIDFromBytes(filter.getBytes()).toString() : "";
|
||||
}
|
||||
|
||||
public void setFilter(ItemFilter filter, String guid) {
|
||||
this.filter = filter;
|
||||
this.guid = guid;
|
||||
}
|
||||
|
||||
public boolean matches(ItemStack stack) {
|
||||
return this.filter.matches(stack);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String STATE_KEY = "collapsibleitems";
|
||||
|
||||
protected static File statesFile;
|
||||
protected static final List<GroupItem> groups = new ArrayList<>();
|
||||
protected static final Map<ItemStack, Integer> cache = new ConcurrentHashMap<>();
|
||||
|
||||
private CollapsibleItems() {}
|
||||
|
||||
public static void load() {
|
||||
CollapsibleItems.groups.clear();
|
||||
CollapsibleItems.cache.clear();
|
||||
|
||||
for (int i = PresetsList.presets.size() - 1; i >= 0; i--) {
|
||||
Preset preset = PresetsList.presets.get(i);
|
||||
if (preset.enabled && preset.mode == PresetMode.GROUP) {
|
||||
GroupItem group = new GroupItem();
|
||||
group.setFilter(preset, UUID.nameUUIDFromBytes(preset.items.toString().getBytes()).toString());
|
||||
group.displayName = preset.name;
|
||||
addGroup(group);
|
||||
}
|
||||
}
|
||||
|
||||
if (NEIClientConfig.enableCollapsibleItems()) {
|
||||
ClientHandler.loadSettingsFile(
|
||||
"collapsibleitems.cfg",
|
||||
lines -> parseFile(lines.collect(Collectors.toCollection(ArrayList::new))));
|
||||
}
|
||||
|
||||
loadStates();
|
||||
}
|
||||
|
||||
private static void parseFile(List<String> itemStrings) {
|
||||
final JsonParser parser = new JsonParser();
|
||||
GroupItem group = new GroupItem();
|
||||
|
||||
for (String itemStr : itemStrings) {
|
||||
try {
|
||||
|
||||
if (itemStr.startsWith("; ")) {
|
||||
JsonObject settings = parser.parse(itemStr.substring(2)).getAsJsonObject();
|
||||
|
||||
if (settings.get("displayName") != null) {
|
||||
group.displayName = settings.get("displayName").getAsString();
|
||||
}
|
||||
|
||||
if (settings.get("unlocalizedName") != null) {
|
||||
String unlocalizedName = settings.get("unlocalizedName").getAsString();
|
||||
String displayName = StatCollector.translateToLocal(unlocalizedName);
|
||||
|
||||
if (!displayName.equals(unlocalizedName)) {
|
||||
group.displayName = displayName;
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.get("expanded") != null) {
|
||||
group.expanded = settings.get("expanded").getAsBoolean();
|
||||
}
|
||||
|
||||
} else {
|
||||
group.setFilter(itemStr);
|
||||
}
|
||||
|
||||
if (group != null && group.filter != null) {
|
||||
addGroup(group);
|
||||
group = new GroupItem();
|
||||
}
|
||||
|
||||
} catch (IllegalArgumentException | JsonSyntaxException | IllegalStateException e) {
|
||||
NEIClientConfig.logger.error("Failed to load collapsible items from json string:\n{}", itemStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addGroup(GroupItem group) {
|
||||
if (group == null || group.filter == null
|
||||
|| group.filter instanceof EverythingItemFilter
|
||||
|| group.filter instanceof NothingItemFilter)
|
||||
return;
|
||||
CollapsibleItems.groups.add(group);
|
||||
}
|
||||
|
||||
public static boolean isEmpty() {
|
||||
return CollapsibleItems.groups.isEmpty();
|
||||
}
|
||||
|
||||
public static ItemFilter getItemFilter() {
|
||||
AnyMultiItemFilter filter = new AnyMultiItemFilter();
|
||||
|
||||
for (GroupItem group : CollapsibleItems.groups) {
|
||||
filter.filters.add(group.filter);
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
public static void clearCache() {
|
||||
CollapsibleItems.cache.clear();
|
||||
}
|
||||
|
||||
public static void putItem(ItemStack stack) {
|
||||
final GroupItem group = CollapsibleItems.groups.stream().filter(g -> g.matches(stack)).findFirst().orElse(null);
|
||||
|
||||
if (group != null) {
|
||||
CollapsibleItems.cache.put(stack, CollapsibleItems.groups.indexOf(group));
|
||||
}
|
||||
}
|
||||
|
||||
public static int getGroupIndex(ItemStack stack) {
|
||||
|
||||
if (stack == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return CollapsibleItems.cache.getOrDefault(stack, -1);
|
||||
}
|
||||
|
||||
public static String getDisplayName(int groupIndex) {
|
||||
|
||||
if (groupIndex < CollapsibleItems.groups.size()) {
|
||||
return CollapsibleItems.groups.get(groupIndex).displayName;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isExpanded(int groupIndex) {
|
||||
|
||||
if (groupIndex < CollapsibleItems.groups.size()) {
|
||||
return CollapsibleItems.groups.get(groupIndex).expanded;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void setExpanded(int groupIndex, boolean expanded) {
|
||||
|
||||
if (groupIndex < CollapsibleItems.groups.size()) {
|
||||
CollapsibleItems.groups.get(groupIndex).expanded = expanded;
|
||||
}
|
||||
}
|
||||
|
||||
public static void toggleGroups(Boolean expanded) {
|
||||
|
||||
if (expanded == null) {
|
||||
expanded = CollapsibleItems.groups.stream().noneMatch(g -> g.expanded);
|
||||
}
|
||||
|
||||
for (GroupItem group : CollapsibleItems.groups) {
|
||||
group.expanded = expanded;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void saveStates() {
|
||||
NBTTagCompound list = new NBTTagCompound();
|
||||
|
||||
for (GroupItem group : CollapsibleItems.groups) {
|
||||
list.setBoolean(group.guid, group.expanded);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.world != null) {
|
||||
NEIClientConfig.world.nbt.setTag(STATE_KEY, list);
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadStates() {
|
||||
|
||||
try {
|
||||
|
||||
if (NEIClientConfig.world.nbt.hasKey(STATE_KEY)) {
|
||||
NBTTagCompound states = NEIClientConfig.world.nbt.getCompoundTag(STATE_KEY);
|
||||
@SuppressWarnings("unchecked")
|
||||
final Map<String, NBTPrimitive> list = (Map<String, NBTPrimitive>) states.tagMap;
|
||||
final Map<String, GroupItem> mapping = new HashMap<>();
|
||||
|
||||
for (GroupItem group : CollapsibleItems.groups) {
|
||||
mapping.put(group.guid, group);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, NBTPrimitive> nbtEntry : list.entrySet()) {
|
||||
if (mapping.containsKey(nbtEntry.getKey())) {
|
||||
mapping.get(nbtEntry.getKey()).expanded = nbtEntry.getValue().func_150290_f() == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Error loading collapsible items states", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.inventory.Container;
|
||||
@@ -11,8 +9,13 @@ import net.minecraft.item.ItemArmor;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IIcon;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class ContainerCreativeInv extends Container {
|
||||
|
||||
private class SlotArmor extends Slot {
|
||||
|
||||
final int armorType;
|
||||
|
||||
public SlotArmor(IInventory inv, int x, int y, int slot, int armor) {
|
||||
@@ -38,14 +41,15 @@ public class ContainerCreativeInv extends Container {
|
||||
}
|
||||
|
||||
private class SlotBlockArmor extends SlotArmor {
|
||||
|
||||
public SlotBlockArmor(IInventory inv, int x, int y, int slot, int armor) {
|
||||
super(inv, x, y, slot, armor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValid(ItemStack stack) {
|
||||
return super.isItemValid(stack)
|
||||
|| stack != null; // && Block.getBlockFromItem(stack.getItem()) != Blocks.air;
|
||||
return super.isItemValid(stack) || stack != null; // && Block.getBlockFromItem(stack.getItem()) !=
|
||||
// Blocks.air;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,20 +58,22 @@ public class ContainerCreativeInv extends Container {
|
||||
public ContainerCreativeInv(EntityPlayer player, ExtendedCreativeInv extraInv) {
|
||||
this.player = player;
|
||||
InventoryPlayer invPlayer = player.inventory;
|
||||
for (int row = 0; row < 6; row++)
|
||||
for (int col = 0; col < 9; col++)
|
||||
addSlotToContainer(new Slot(extraInv, col + row * 9, 8 + col * 18, 5 + row * 18));
|
||||
for (int row = 0; row < 6; row++) for (int col = 0; col < 9; col++)
|
||||
addSlotToContainer(new Slot(extraInv, col + row * 9, 8 + col * 18, 5 + row * 18));
|
||||
|
||||
for (int row = 0; row < 3; ++row)
|
||||
for (int col = 0; col < 9; ++col)
|
||||
addSlotToContainer(new Slot(invPlayer, col + row * 9 + 9, 8 + col * 18, 118 + row * 18));
|
||||
for (int row = 0; row < 3; ++row) for (int col = 0; col < 9; ++col)
|
||||
addSlotToContainer(new Slot(invPlayer, col + row * 9 + 9, 8 + col * 18, 118 + row * 18));
|
||||
|
||||
for (int col = 0; col < 9; ++col) addSlotToContainer(new Slot(invPlayer, col, 8 + col * 18, 176));
|
||||
|
||||
addSlotToContainer(new SlotBlockArmor(invPlayer, invPlayer.getSizeInventory() - 1, -15, 23, 0));
|
||||
for (int armorType = 1; armorType < 4; armorType++)
|
||||
addSlotToContainer(new SlotArmor(
|
||||
invPlayer, invPlayer.getSizeInventory() - 1 - armorType, -15, 23 + armorType * 18, armorType));
|
||||
for (int armorType = 1; armorType < 4; armorType++) addSlotToContainer(
|
||||
new SlotArmor(
|
||||
invPlayer,
|
||||
invPlayer.getSizeInventory() - 1 - armorType,
|
||||
-15,
|
||||
23 + armorType * 18,
|
||||
armorType));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
@@ -13,13 +13,18 @@ import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
|
||||
/**
|
||||
* This is crap code, don't ever do this.
|
||||
*/
|
||||
public class ContainerEnchantmentModifier extends ContainerEnchantment {
|
||||
|
||||
public static class EnchantmentHash {
|
||||
|
||||
public EnchantmentHash(Enchantment e, int i, int l) {
|
||||
enchantment = e;
|
||||
state = i;
|
||||
@@ -101,9 +106,7 @@ public class ContainerEnchantmentModifier extends ContainerEnchantment {
|
||||
int barempty = height - getScrollBarHeight();
|
||||
int sbary = rely + (int) (barempty * percentscrolled + 0.5);
|
||||
|
||||
if (button == 0
|
||||
&& getScrollBarHeight() < height
|
||||
&& // the scroll bar can move (not full length)
|
||||
if (button == 0 && getScrollBarHeight() < height && // the scroll bar can move (not full length)
|
||||
mousex >= relx + cwidth
|
||||
&& mousex < relx + cwidth + getScrollBarWidth()
|
||||
&& mousey >= rely
|
||||
@@ -217,10 +220,10 @@ public class ContainerEnchantmentModifier extends ContainerEnchantment {
|
||||
if (NEIServerUtils.stackHasEnchantment(toolstack, e.effectId)) {
|
||||
state = 2;
|
||||
level = NEIServerUtils.getEnchantmentLevel(toolstack, e.effectId);
|
||||
} else if (NEIServerUtils.doesEnchantmentConflict(NEIServerUtils.getEnchantments(toolstack), e)
|
||||
&& validate) {
|
||||
state = 1;
|
||||
}
|
||||
} else
|
||||
if (NEIServerUtils.doesEnchantmentConflict(NEIServerUtils.getEnchantments(toolstack), e) && validate) {
|
||||
state = 1;
|
||||
}
|
||||
slotEnchantment.add(new EnchantmentHash(e, state, level));
|
||||
}
|
||||
if (numoptions != slotEnchantment.size()) {
|
||||
@@ -255,7 +258,12 @@ public class ContainerEnchantmentModifier extends ContainerEnchantment {
|
||||
GL11.glColor3f(1, 1, 1);
|
||||
if (hasScrollBar()) {
|
||||
gui.drawTexturedModalRect(
|
||||
relx, rely + slot * slotheight, 0, gui.ySize + slotheight * shade, cwidth - 30, slotheight);
|
||||
relx,
|
||||
rely + slot * slotheight,
|
||||
0,
|
||||
gui.ySize + slotheight * shade,
|
||||
cwidth - 30,
|
||||
slotheight);
|
||||
gui.drawTexturedModalRect(
|
||||
relx + cwidth - 30,
|
||||
rely + slot * slotheight,
|
||||
@@ -265,7 +273,12 @@ public class ContainerEnchantmentModifier extends ContainerEnchantment {
|
||||
slotheight);
|
||||
} else {
|
||||
gui.drawTexturedModalRect(
|
||||
relx, rely + slot * slotheight, 0, gui.ySize + slotheight * shade, cwidth + 7, slotheight);
|
||||
relx,
|
||||
rely + slot * slotheight,
|
||||
0,
|
||||
gui.ySize + slotheight * shade,
|
||||
cwidth + 7,
|
||||
slotheight);
|
||||
}
|
||||
|
||||
gui.getFontRenderer().drawString(text, relx + 4, rely + slot * slotheight + 5, textColourFromState(shade));
|
||||
@@ -284,12 +297,8 @@ public class ContainerEnchantmentModifier extends ContainerEnchantment {
|
||||
|
||||
Gui.drawRect(sbarx, rely, sbarx + getScrollBarWidth(), rely + height, 0xFF202020); // background
|
||||
Gui.drawRect(sbarx, sbary, sbarx + getScrollBarWidth(), sbary + getScrollBarHeight(), 0xFF8B8B8B); // corners
|
||||
Gui.drawRect(
|
||||
sbarx,
|
||||
sbary,
|
||||
sbarx + getScrollBarWidth() - 1,
|
||||
sbary + getScrollBarHeight() - 1,
|
||||
0xFFF0F0F0); // topleft up
|
||||
Gui.drawRect(sbarx, sbary, sbarx + getScrollBarWidth() - 1, sbary + getScrollBarHeight() - 1, 0xFFF0F0F0); // topleft
|
||||
// up
|
||||
Gui.drawRect(
|
||||
sbarx + 1,
|
||||
sbary + 1,
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.inventory.ContainerExtended;
|
||||
import codechicken.lib.inventory.InventoryNBT;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.inventory.SlotHandleClicks;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
@@ -16,8 +11,16 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
|
||||
import codechicken.lib.inventory.ContainerExtended;
|
||||
import codechicken.lib.inventory.InventoryNBT;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.inventory.SlotHandleClicks;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
|
||||
public class ContainerPotionCreator extends ContainerExtended {
|
||||
|
||||
public class SlotPotion extends Slot {
|
||||
|
||||
public SlotPotion(IInventory inv, int slotIndex, int x, int y) {
|
||||
super(inv, slotIndex, x, y);
|
||||
}
|
||||
@@ -40,6 +43,7 @@ public class ContainerPotionCreator extends ContainerExtended {
|
||||
}
|
||||
|
||||
public class SlotPotionStore extends SlotHandleClicks {
|
||||
|
||||
public SlotPotionStore(IInventory inv, int slotIndex, int x, int y) {
|
||||
super(inv, slotIndex, x, y);
|
||||
}
|
||||
@@ -68,6 +72,7 @@ public class ContainerPotionCreator extends ContainerExtended {
|
||||
}
|
||||
|
||||
public static class InventoryPotionStore extends InventoryNBT {
|
||||
|
||||
public InventoryPotionStore() {
|
||||
super(9, NEIClientConfig.global.nbt.getCompoundTag("potionStore"));
|
||||
}
|
||||
@@ -76,7 +81,6 @@ public class ContainerPotionCreator extends ContainerExtended {
|
||||
public void markDirty() {
|
||||
super.markDirty();
|
||||
NEIClientConfig.global.nbt.setTag("potionStore", tag);
|
||||
NEIClientConfig.global.saveNBT();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +116,6 @@ public class ContainerPotionCreator extends ContainerExtended {
|
||||
if (!player.worldObj.isRemote) InventoryUtils.dropOnClose(player, potionInv);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void handleServerPacket(PacketCustom packet) {
|
||||
ItemStack potion = potionInv.getStackInSlot(0);
|
||||
@@ -128,9 +131,9 @@ public class ContainerPotionCreator extends ContainerExtended {
|
||||
PotionEffect e = PotionEffect.readCustomPotionEffectFromNBT(tag);
|
||||
if (e.getPotionID() != effectID) newEffects.appendTag(tag);
|
||||
}
|
||||
if (add)
|
||||
newEffects.appendTag(new PotionEffect(effectID, packet.readInt(), packet.readUByte())
|
||||
.writeCustomPotionEffectToNBT(new NBTTagCompound()));
|
||||
if (add) newEffects.appendTag(
|
||||
new PotionEffect(effectID, packet.readInt(), packet.readUByte())
|
||||
.writeCustomPotionEffectToNBT(new NBTTagCompound()));
|
||||
potion.getTagCompound().setTag("CustomPotionEffects", newEffects);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,29 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.nei.api.IHighlightHandler;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import codechicken.nei.api.IHighlightHandler;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
|
||||
public class DefaultHighlightHandler implements IHighlightHandler {
|
||||
|
||||
@Override
|
||||
public List<String> handleTextData(
|
||||
ItemStack stack,
|
||||
World world,
|
||||
EntityPlayer player,
|
||||
MovingObjectPosition mop,
|
||||
List<String> currenttip,
|
||||
ItemInfo.Layout layout) {
|
||||
public List<String> handleTextData(ItemStack stack, World world, EntityPlayer player, MovingObjectPosition mop,
|
||||
List<String> currenttip, ItemInfo.Layout layout) {
|
||||
String name = null;
|
||||
try {
|
||||
String s = GuiContainerManager.itemDisplayNameShort(stack);
|
||||
if (s != null && !s.endsWith("Unnamed")) name = s;
|
||||
|
||||
if (name != null) currenttip.add(name);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
if (name != null && stack.getItem() == Items.redstone) {
|
||||
int md = world.getBlockMetadata(mop.blockX, mop.blockY, mop.blockZ);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
|
||||
public class DoubleFilteredFilter implements ItemFilter {
|
||||
|
||||
private ItemFilter filter;
|
||||
private ItemList.PatternItemFilter patternFilter;
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
|
||||
public class ExtendedCreativeInv implements IInventory {
|
||||
|
||||
final PlayerSave playerSave;
|
||||
final Side side;
|
||||
|
||||
|
||||
@@ -4,21 +4,25 @@ import static codechicken.nei.NEIServerUtils.areStacksIdentical;
|
||||
import static codechicken.nei.NEIServerUtils.areStacksSameType;
|
||||
import static codechicken.nei.NEIServerUtils.copyStack;
|
||||
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
|
||||
public class FastTransferManager {
|
||||
|
||||
/**
|
||||
* Based on the general assumption that we want to fill top to bottom, left to right
|
||||
*/
|
||||
public static class SlotPositionComparator implements Comparator<Integer> {
|
||||
|
||||
final Container container;
|
||||
|
||||
public SlotPositionComparator(Container c) {
|
||||
@@ -101,8 +105,7 @@ public class FastTransferManager {
|
||||
if (!fillZoneWithHeldItem(window, toZone)) return;
|
||||
|
||||
for (int transferFrom : slotZones.get(fromZone)) {
|
||||
ItemStack transferStack =
|
||||
window.inventorySlots.getSlot(transferFrom).getStack();
|
||||
ItemStack transferStack = window.inventorySlots.getSlot(transferFrom).getStack();
|
||||
|
||||
if (!areStacksSameType(heldStack, transferStack)) continue;
|
||||
|
||||
@@ -142,12 +145,10 @@ public class FastTransferManager {
|
||||
ItemStack after = compareAfter.get(i);
|
||||
|
||||
if (!areStacksIdentical(before, after) && after != null)
|
||||
if (before == null
|
||||
? areStacksSameType(stack, after)
|
||||
: // transfered into this empty slot
|
||||
areStacksSameType(stack, after)
|
||||
&& after.stackSize - before.stackSize > 0) // it added to this stack
|
||||
return i;
|
||||
if (before == null ? areStacksSameType(stack, after) : // transfered into this empty slot
|
||||
areStacksSameType(stack, after) && after.stackSize - before.stackSize > 0) // it added to
|
||||
// this stack
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -180,16 +181,22 @@ public class FastTransferManager {
|
||||
|
||||
if (from.isItemValid(from.getStack())) moveOneItem(window, fromSlot, toSlot);
|
||||
else // slots that you can't put stuff in
|
||||
moveOutputSet(window, fromSlot, toSlot);
|
||||
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;
|
||||
|
||||
clickSlot(window, fromSlot); // pickup fromSlot
|
||||
if (NEIClientUtils.getHeldItem()
|
||||
== null) // maybe this container does auto transfers. No need to pick up the final item
|
||||
return;
|
||||
if (NEIClientUtils.getHeldItem() == null) // maybe this container does auto transfers. No need to pick up the
|
||||
// final item
|
||||
return;
|
||||
clickSlot(window, toSlot); // place one in toSlot
|
||||
}
|
||||
|
||||
@@ -202,15 +209,15 @@ public class FastTransferManager {
|
||||
public void retrieveItem(GuiContainer window, int toSlot) {
|
||||
Slot slot = window.inventorySlots.getSlot(toSlot);
|
||||
ItemStack slotStack = slot.getStack();
|
||||
if (slotStack == null
|
||||
|| slotStack.stackSize == slot.getSlotStackLimit()
|
||||
|| slotStack.stackSize == slotStack.getMaxStackSize()) return;
|
||||
if (slotStack == null || slotStack.stackSize == slot.getSlotStackLimit()
|
||||
|| slotStack.stackSize == slotStack.getMaxStackSize())
|
||||
return;
|
||||
|
||||
generateSlotMap(window.inventorySlots, slotStack);
|
||||
|
||||
Integer destZone = slotZoneMap.get(toSlot);
|
||||
if (destZone == null) // slots that don't accept
|
||||
return;
|
||||
return;
|
||||
|
||||
int firstZoneSlot = findShiftClickDestinationSlot(window.inventorySlots, toSlot);
|
||||
int firstZone = -1;
|
||||
@@ -239,9 +246,9 @@ public class FastTransferManager {
|
||||
Slot slot = window.inventorySlots.getSlot(i);
|
||||
ItemStack stack1 = slot.getStack();
|
||||
|
||||
if (areStacksSameType(stack, stack1)
|
||||
&& stack1.stackSize != slot.getSlotStackLimit()
|
||||
&& // get from full stacks on second pass
|
||||
if (areStacksSameType(stack, stack1) && stack1.stackSize != slot.getSlotStackLimit() && // get from full
|
||||
// stacks on second
|
||||
// pass
|
||||
stack1.stackSize != stack1.getMaxStackSize()) {
|
||||
moveOneItem(window, i, toSlot);
|
||||
return true;
|
||||
@@ -312,7 +319,7 @@ public class FastTransferManager {
|
||||
generateSlotMap(window.inventorySlots, held);
|
||||
Integer zone = slotZoneMap.get(pickedUpFromSlot);
|
||||
if (zone == null) // something went wrong and we can't work out where the item was picked up from
|
||||
return;
|
||||
return;
|
||||
|
||||
for (int slotIndex : slotZones.get(zone)) {
|
||||
Slot slot = window.inventorySlots.getSlot(slotIndex);
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class FormattedTextField extends GuiTextField {
|
||||
|
||||
public static interface TextFormatter {
|
||||
|
||||
TextFormatter DEFAULT = (text) -> text;
|
||||
|
||||
public String format(String text);
|
||||
}
|
||||
|
||||
protected FontRenderer fontRenderer;
|
||||
protected String rawText = "";
|
||||
protected String formattedText = "";
|
||||
protected boolean editable = true;
|
||||
protected int editableColor = 14737632;
|
||||
protected int notEditableColor = 7368816;
|
||||
protected TextFormatter formatter = TextFormatter.DEFAULT;
|
||||
protected int lineScrollOffset = 0;
|
||||
protected int frame = 0;
|
||||
|
||||
public FormattedTextField(FontRenderer fontRenderer, int xPosition, int yPosition, int width, int height) {
|
||||
super(fontRenderer, xPosition, yPosition, width, height);
|
||||
this.fontRenderer = fontRenderer;
|
||||
}
|
||||
|
||||
public void setFormatter(TextFormatter formatter) {
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCursorCounter() {
|
||||
super.updateCursorCounter();
|
||||
++this.frame;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocused(boolean focus) {
|
||||
if (focus && !this.isFocused()) {
|
||||
this.frame = 0;
|
||||
}
|
||||
|
||||
super.setFocused(focus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectionPos(int p_146199_1_) {
|
||||
String text = this.getText();
|
||||
int j = text.length();
|
||||
|
||||
super.setSelectionPos(p_146199_1_);
|
||||
|
||||
p_146199_1_ = Math.max(0, Math.min(p_146199_1_, j));
|
||||
|
||||
if (this.fontRenderer != null) {
|
||||
|
||||
if (this.lineScrollOffset > j) {
|
||||
this.lineScrollOffset = j;
|
||||
}
|
||||
|
||||
int k = this.getWidth();
|
||||
String s = this.fontRenderer.trimStringToWidth(text.substring(this.lineScrollOffset), k);
|
||||
int l = s.length() + this.lineScrollOffset;
|
||||
|
||||
if (p_146199_1_ == this.lineScrollOffset) {
|
||||
this.lineScrollOffset -= this.fontRenderer.trimStringToWidth(text, k, true).length();
|
||||
}
|
||||
|
||||
if (p_146199_1_ > l) {
|
||||
this.lineScrollOffset += p_146199_1_ - l;
|
||||
} else if (p_146199_1_ <= this.lineScrollOffset) {
|
||||
this.lineScrollOffset -= this.lineScrollOffset - p_146199_1_;
|
||||
}
|
||||
|
||||
this.lineScrollOffset = Math.max(0, Math.min(this.lineScrollOffset, j));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTextColor(int p_146193_1_) {
|
||||
super.setTextColor(p_146193_1_);
|
||||
this.editableColor = p_146193_1_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisabledTextColour(int p_146204_1_) {
|
||||
super.setDisabledTextColour(p_146204_1_);
|
||||
this.notEditableColor = p_146204_1_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean p_146184_1_) {
|
||||
super.setEnabled(p_146184_1_);
|
||||
this.editable = p_146184_1_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTextBox() {
|
||||
if (this.getVisible()) {
|
||||
if (this.getEnableBackgroundDrawing()) {
|
||||
drawRect(
|
||||
this.xPosition - 1,
|
||||
this.yPosition - 1,
|
||||
this.xPosition + this.width + 1,
|
||||
this.yPosition + this.height + 1,
|
||||
-6250336);
|
||||
drawRect(
|
||||
this.xPosition,
|
||||
this.yPosition,
|
||||
this.xPosition + this.width,
|
||||
this.yPosition + this.height,
|
||||
-16777216);
|
||||
}
|
||||
|
||||
if (!this.rawText.equals(getText())) {
|
||||
this.rawText = getText();
|
||||
this.formattedText = this.formatter.format(this.rawText);
|
||||
if (!EnumChatFormatting.getTextWithoutFormattingCodes(this.formattedText).toLowerCase()
|
||||
.equals(this.rawText.toLowerCase())) {
|
||||
this.formattedText = this.rawText;
|
||||
}
|
||||
}
|
||||
|
||||
int firstCharacterIndex = getFormattedTextShift(this.lineScrollOffset);
|
||||
String rawTextClipped = this.fontRenderer
|
||||
.trimStringToWidth(this.rawText.substring(this.lineScrollOffset), this.getWidth());
|
||||
String textClipped = this.formattedText.substring(
|
||||
firstCharacterIndex,
|
||||
getFormattedTextShift(this.lineScrollOffset + rawTextClipped.length()));
|
||||
int cursorPosition = getFormattedTextShift(this.getCursorPosition());
|
||||
int selectionEnd = getFormattedTextShift(this.getSelectionEnd());
|
||||
|
||||
int color = this.editable ? this.editableColor : this.notEditableColor;
|
||||
int cursorA = cursorPosition - firstCharacterIndex;
|
||||
int cursorB = selectionEnd - firstCharacterIndex;
|
||||
boolean flag = cursorA >= 0 && cursorA <= textClipped.length();
|
||||
boolean flag1 = this.isFocused() && this.frame / 6 % 2 == 0 && flag;
|
||||
boolean flag2 = this.getCursorPosition() < this.rawText.length()
|
||||
|| this.rawText.length() >= this.getMaxStringLength();
|
||||
int x = this.getEnableBackgroundDrawing() ? this.xPosition + 4 : this.xPosition;
|
||||
int y = this.getEnableBackgroundDrawing() ? this.yPosition + (this.height - 8) / 2 : this.yPosition;
|
||||
int x2 = x;
|
||||
|
||||
if (cursorB > textClipped.length()) {
|
||||
cursorB = textClipped.length();
|
||||
}
|
||||
|
||||
if (textClipped.length() > 0) {
|
||||
String s1 = flag ? textClipped.substring(0, cursorA) : textClipped;
|
||||
String colorA = getPreviousColor(firstCharacterIndex);
|
||||
x2 = this.fontRenderer.drawStringWithShadow(colorA + s1, x, y, color);
|
||||
}
|
||||
|
||||
int k1 = x2;
|
||||
|
||||
if (!flag) {
|
||||
k1 = cursorA > 0 ? x + this.width : x;
|
||||
} else if (flag2) {
|
||||
k1 = x2 - 1;
|
||||
--x2;
|
||||
}
|
||||
|
||||
if (textClipped.length() > 0 && flag && cursorA < textClipped.length()) {
|
||||
String colorB = getPreviousColor(firstCharacterIndex + cursorA);
|
||||
this.fontRenderer.drawStringWithShadow(colorB + textClipped.substring(cursorA), x2, y, color);
|
||||
}
|
||||
|
||||
if (flag1) {
|
||||
if (flag2) {
|
||||
Gui.drawRect(k1, y - 1, k1 + 1, y + 1 + this.fontRenderer.FONT_HEIGHT, -3092272);
|
||||
} else {
|
||||
this.fontRenderer.drawStringWithShadow("_", k1, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
if (cursorB != cursorA) {
|
||||
int l1 = x + this.fontRenderer.getStringWidth(textClipped.substring(0, cursorB));
|
||||
drawCursorVertical(k1, y - 1, l1 - 1, y + 1 + this.fontRenderer.FONT_HEIGHT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawCursorVertical(int x1, int y1, int x2, int y2) {
|
||||
int i1;
|
||||
|
||||
if (x1 < x2) {
|
||||
i1 = x1;
|
||||
x1 = x2;
|
||||
x2 = i1;
|
||||
}
|
||||
|
||||
if (y1 < y2) {
|
||||
i1 = y1;
|
||||
y1 = y2;
|
||||
y2 = i1;
|
||||
}
|
||||
|
||||
if (x2 > this.xPosition + this.width) {
|
||||
x2 = this.xPosition + this.width;
|
||||
}
|
||||
|
||||
if (x1 > this.xPosition + this.width) {
|
||||
x1 = this.xPosition + this.width;
|
||||
}
|
||||
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
GL11.glColor4f(0.0F, 0.0F, 255.0F, 255.0F);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_COLOR_LOGIC_OP);
|
||||
GL11.glLogicOp(GL11.GL_OR_REVERSE);
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.addVertex((double) x1, (double) y2, 0.0D);
|
||||
tessellator.addVertex((double) x2, (double) y2, 0.0D);
|
||||
tessellator.addVertex((double) x2, (double) y1, 0.0D);
|
||||
tessellator.addVertex((double) x1, (double) y1, 0.0D);
|
||||
tessellator.draw();
|
||||
GL11.glDisable(GL11.GL_COLOR_LOGIC_OP);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
private int getFormattedTextShift(int position) {
|
||||
int shift = 0;
|
||||
|
||||
for (int i = 0; i < position; i++) {
|
||||
while (this.formattedText.length() > i + shift && this.formattedText.charAt(i + shift) == '\u00a7') {
|
||||
shift += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return position + shift;
|
||||
}
|
||||
|
||||
private String getPreviousColor(int position) {
|
||||
while (position >= 0) {
|
||||
if (this.formattedText.charAt(position) == '\u00a7') {
|
||||
return this.formattedText.substring(position, position + 2);
|
||||
}
|
||||
position--;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,15 +2,18 @@ package codechicken.nei;
|
||||
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
|
||||
public class GuiEnchantmentModifier extends GuiContainer {
|
||||
|
||||
final ContainerEnchantmentModifier container;
|
||||
|
||||
public GuiEnchantmentModifier(InventoryPlayer inventoryplayer, World world, int i, int j, int k) {
|
||||
@@ -59,7 +62,6 @@ public class GuiEnchantmentModifier extends GuiContainer {
|
||||
|
||||
public static void toggleEnchantmentValidation() {
|
||||
NEIClientConfig.world.nbt.setBoolean("validateenchantments", !validateEnchantments());
|
||||
NEIClientConfig.world.saveNBT();
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton guibutton) {
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.api.TaggedInventoryArea;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class GuiExtendedCreativeInv extends GuiContainer implements INEIGuiHandler {
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.AutoFocusWidget.INEIAutoFocusSearchEnable;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.api.TaggedInventoryArea;
|
||||
|
||||
public class GuiExtendedCreativeInv extends GuiContainer implements INEIGuiHandler, INEIAutoFocusSearchEnable {
|
||||
|
||||
public GuiExtendedCreativeInv(Container par1Container) {
|
||||
super(par1Container);
|
||||
ySize = 198;
|
||||
@@ -55,13 +60,13 @@ public class GuiExtendedCreativeInv extends GuiContainer implements INEIGuiHandl
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleMouseClick(Slot p_146984_1_, int p_146984_2_, int p_146984_3_, int p_146984_4_) {
|
||||
protected void handleMouseClick(Slot slotIn, int slotId, int clickedButton, int clickType) {
|
||||
|
||||
// Hack for armor slots, because they are outside the container
|
||||
if (p_146984_1_ != null && p_146984_4_ == 4 && p_146984_1_.xDisplayPosition < 0) {
|
||||
p_146984_4_ = 0;
|
||||
if (slotIn != null && clickType == 4 && slotIn.xDisplayPosition < 0) {
|
||||
clickType = 0;
|
||||
}
|
||||
|
||||
super.handleMouseClick(p_146984_1_, p_146984_2_, p_146984_3_, p_146984_4_);
|
||||
super.handleMouseClick(slotIn, slotId, clickedButton, clickType);
|
||||
}
|
||||
}
|
||||
@@ -4,26 +4,27 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class GuiNEIButton extends GuiButton {
|
||||
|
||||
protected static final ResourceLocation guiTex = new ResourceLocation("textures/gui/widgets.png");
|
||||
|
||||
public GuiNEIButton(int i, int j, int k, int l, int i1, String s) {
|
||||
super(i, j, k, l, i1, s);
|
||||
}
|
||||
|
||||
public void drawButton(Minecraft minecraft, int i, int j) {
|
||||
public void drawButton(Minecraft minecraft, int x, int y) {
|
||||
if (!visible) return;
|
||||
|
||||
FontRenderer fontrenderer = minecraft.fontRenderer;
|
||||
minecraft.renderEngine.bindTexture(guiTex);
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
boolean flag = i >= xPosition && j >= yPosition && i < xPosition + width && j < yPosition + height;
|
||||
int k = getHoverState(flag);
|
||||
boolean mouseOver = x >= xPosition && y >= yPosition && x < xPosition + width && y < yPosition + height;
|
||||
int k = getHoverState(mouseOver);
|
||||
drawTexturedModalRect(xPosition, yPosition, 0, 46 + k * 20, width / 2, height / 2); // top left
|
||||
drawTexturedModalRect(
|
||||
xPosition + width / 2, yPosition, 200 - width / 2, 46 + k * 20, width / 2, height / 2); // top right
|
||||
drawTexturedModalRect(xPosition + width / 2, yPosition, 200 - width / 2, 46 + k * 20, width / 2, height / 2); // top
|
||||
// right
|
||||
drawTexturedModalRect(
|
||||
xPosition,
|
||||
yPosition + height / 2,
|
||||
@@ -38,16 +39,27 @@ public class GuiNEIButton extends GuiButton {
|
||||
46 + k * 20 + 20 - height / 2,
|
||||
width / 2,
|
||||
height / 2); // bottom right
|
||||
mouseDragged(minecraft, i, j);
|
||||
mouseDragged(minecraft, x, y);
|
||||
|
||||
if (!enabled)
|
||||
drawCenteredString(
|
||||
fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, 0xffa0a0a0);
|
||||
else if (flag)
|
||||
drawCenteredString(
|
||||
fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, 0xffffa0);
|
||||
else
|
||||
drawCenteredString(
|
||||
fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, 0xe0e0e0);
|
||||
drawContent(minecraft, x, y, mouseOver);
|
||||
}
|
||||
|
||||
protected int getTextColour(boolean mouseOver) {
|
||||
int color = 0xe0e0e0;
|
||||
|
||||
if (!enabled) {
|
||||
color = 0xffa0a0a0;
|
||||
} else if (mouseOver) {
|
||||
color = 0xffffa0;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
protected void drawContent(Minecraft minecraft, int y, int x, boolean mouseOver) {
|
||||
FontRenderer fontrenderer = minecraft.fontRenderer;
|
||||
int color = getTextColour(mouseOver);
|
||||
|
||||
drawCenteredString(fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, color);
|
||||
}
|
||||
}
|
||||
@@ -2,24 +2,29 @@ package codechicken.nei;
|
||||
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.StatCollector;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.core.gui.GuiCCButton;
|
||||
import codechicken.core.gui.GuiCCTextField;
|
||||
import codechicken.core.gui.GuiScrollSlot;
|
||||
import codechicken.core.inventory.GuiContainerWidget;
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
import codechicken.lib.render.FontUtils;
|
||||
import java.awt.Dimension;
|
||||
import java.util.ArrayList;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.potion.Potion;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class GuiPotionCreator extends GuiContainerWidget {
|
||||
|
||||
public class GuiSlotPotionEffects extends GuiScrollSlot {
|
||||
|
||||
public int selectedslot = -1;
|
||||
public boolean enabled = true;
|
||||
private final ArrayList<Potion> validPotions = new ArrayList<>();
|
||||
@@ -69,7 +74,12 @@ public class GuiPotionCreator extends GuiContainerWidget {
|
||||
CCRenderState.changeTexture("textures/gui/container/enchanting_table.png");
|
||||
drawTexturedModalRect(x, y, 0, 166 + getSlotHeight(slot) * shade, width - 30, getSlotHeight(slot));
|
||||
drawTexturedModalRect(
|
||||
x + width - 30, y, width - 23, 166 + getSlotHeight(slot) * shade, 30, getSlotHeight(slot));
|
||||
x + width - 30,
|
||||
y,
|
||||
width - 23,
|
||||
166 + getSlotHeight(slot) * shade,
|
||||
30,
|
||||
getSlotHeight(slot));
|
||||
|
||||
if (potion.hasStatusIcon()) {
|
||||
CCRenderState.changeTexture("textures/gui/container/inventory.png");
|
||||
@@ -94,9 +104,7 @@ public class GuiPotionCreator extends GuiContainerWidget {
|
||||
|
||||
private PotionEffect getEffect(int id) {
|
||||
ItemStack potion = container.potionInv.getStackInSlot(0);
|
||||
if (potion != null
|
||||
&& potion.hasTagCompound()
|
||||
&& potion.getTagCompound().hasKey("CustomPotionEffects")) {
|
||||
if (potion != null && potion.hasTagCompound() && potion.getTagCompound().hasKey("CustomPotionEffects")) {
|
||||
NBTTagList potionTagList = potion.getTagCompound().getTagList("CustomPotionEffects", 10);
|
||||
for (int i = 0; i < potionTagList.tagCount(); i++) {
|
||||
PotionEffect effect = PotionEffect.readCustomPotionEffectFromNBT(potionTagList.getCompoundTagAt(i));
|
||||
@@ -167,6 +175,7 @@ public class GuiPotionCreator extends GuiContainerWidget {
|
||||
}
|
||||
|
||||
public class GuiDurationField extends GuiCCTextField {
|
||||
|
||||
private String baseValue;
|
||||
|
||||
public GuiDurationField(int x, int y, int width, int height) {
|
||||
@@ -216,8 +225,8 @@ public class GuiPotionCreator extends GuiContainerWidget {
|
||||
@Override
|
||||
public void drawText() {
|
||||
String s = getText();
|
||||
String seconds =
|
||||
s.substring(Math.max(0, s.length() - 2), Math.max(0, s.length() - 2) + Math.min(s.length(), 2));
|
||||
String seconds = s
|
||||
.substring(Math.max(0, s.length() - 2), Math.max(0, s.length() - 2) + Math.min(s.length(), 2));
|
||||
String minutes = s.length() < 3 ? "" : s.substring(0, s.length() - 2);
|
||||
int ty = y + height / 2 - 4;
|
||||
int tcolour = getTextColour();
|
||||
|
||||
@@ -5,23 +5,27 @@ import static codechicken.lib.gui.GuiDraw.drawString;
|
||||
import static codechicken.lib.gui.GuiDraw.drawTooltipBox;
|
||||
import static codechicken.lib.gui.GuiDraw.getStringWidth;
|
||||
|
||||
import codechicken.lib.config.ConfigTag;
|
||||
import codechicken.nei.KeyManager.IKeyStateTracker;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.MovingObjectPosition.MovingObjectType;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.lib.config.ConfigTag;
|
||||
import codechicken.nei.KeyManager.IKeyStateTracker;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class HUDRenderer implements IKeyStateTracker {
|
||||
|
||||
@Override
|
||||
public void tickKeyStates() {
|
||||
if (KeyManager.keyStates.get("world.highlight_tips").down) {
|
||||
@@ -32,8 +36,7 @@ public class HUDRenderer implements IKeyStateTracker {
|
||||
|
||||
public static void renderOverlay() {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (mc.currentScreen == null
|
||||
&& mc.theWorld != null
|
||||
if (mc.currentScreen == null && mc.theWorld != null
|
||||
&& !mc.gameSettings.keyBindPlayerList.getIsKeyPressed()
|
||||
&& NEIClientConfig.getBooleanSetting("world.highlight_tips")
|
||||
&& mc.objectMouseOver != null
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
|
||||
public class HeldItemHandler implements IContainerInputHandler, IContainerTooltipHandler {
|
||||
|
||||
protected HeldItemHandler() {
|
||||
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
HeldItemHandler instance = new HeldItemHandler();
|
||||
GuiContainerManager.addInputHandler(instance);
|
||||
GuiContainerManager.addTooltipHandler(instance);
|
||||
}
|
||||
|
||||
protected boolean contains(int mousex, int mousey) {
|
||||
return NEIClientUtils.getHeldItem() != null
|
||||
&& (ItemPanels.bookmarkPanel.contains(mousex, mousey) || ItemPanels.itemPanel.contains(mousex, mousey)
|
||||
|| ItemPanels.itemPanel.historyPanel.contains(mousex, mousey));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
|
||||
if (contains(mousex, mousey)) {
|
||||
|
||||
if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) {
|
||||
if (button == 1) {
|
||||
NEIClientUtils.decreaseSlotStack(-999);
|
||||
} else {
|
||||
NEIClientUtils.deleteHeldItem();
|
||||
}
|
||||
} else {
|
||||
NEIClientUtils.dropHeldItem();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
|
||||
if (contains(mousex, mousey)) {
|
||||
currenttip.clear();
|
||||
|
||||
if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) {
|
||||
currenttip.add(EnumChatFormatting.RED + translate("itempanel.deleteItem"));
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
public class Image {
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
public int width;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.nei.api.IInfiniteItemHandler;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.nei.api.IInfiniteItemHandler;
|
||||
|
||||
public class InfiniteStackSizeHandler implements IInfiniteItemHandler {
|
||||
|
||||
@Override
|
||||
public void onPickup(ItemStack heldItem) {
|
||||
heldItem.stackSize = 1;
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.nei.api.IInfiniteItemHandler;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.api.IInfiniteItemHandler;
|
||||
|
||||
public class InfiniteToolHandler implements IInfiniteItemHandler {
|
||||
|
||||
@Override
|
||||
public void onPickup(ItemStack heldItem) {
|
||||
heldItem.setItemDamage(0);
|
||||
|
||||
@@ -5,15 +5,14 @@ import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.InventoryCrafting;
|
||||
|
||||
public class InventoryCraftingDummy extends InventoryCrafting {
|
||||
|
||||
public InventoryCraftingDummy() {
|
||||
super(
|
||||
new Container() {
|
||||
@Override
|
||||
public boolean canInteractWith(EntityPlayer entityplayer) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
3,
|
||||
3);
|
||||
super(new Container() {
|
||||
|
||||
@Override
|
||||
public boolean canInteractWith(EntityPlayer entityplayer) {
|
||||
return true;
|
||||
}
|
||||
}, 3, 3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.GuiUsageRecipe;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class ItemHistoryPanel extends Widget {
|
||||
|
||||
protected int mouseDownSlot = -1;
|
||||
protected ItemsGrid grid;
|
||||
|
||||
public ItemHistoryPanel() {
|
||||
grid = new ItemsGrid();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return grid.isEmpty();
|
||||
}
|
||||
|
||||
public void draw(int mousex, int mousey) {
|
||||
|
||||
if (NEIClientConfig.getIntSetting("inventory.history.splittingMode") == 0) {
|
||||
GuiDraw.drawRect(x, y, w, h, NEIClientConfig.getSetting("inventory.history.historyColor").getHexValue());
|
||||
} else {
|
||||
drawSplittingArea(x, y, w, h, NEIClientConfig.getSetting("inventory.history.historyColor").getHexValue());
|
||||
}
|
||||
|
||||
grid.draw(mousex, mousey);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
grid.update();
|
||||
}
|
||||
|
||||
public void addItem(ItemStack stack) {
|
||||
if (stack != null) {
|
||||
ItemStack is = StackInfo.loadFromNBT(StackInfo.itemStackToNBT(stack), 0);
|
||||
|
||||
grid.realItems.removeIf(historyStack -> StackInfo.equalItemAndNBT(historyStack, stack, true));
|
||||
grid.realItems.add(0, is);
|
||||
|
||||
if (grid.realItems.size() > Math.max(50, grid.rows * grid.columns)) {
|
||||
grid.realItems.remove(grid.realItems.size() - 1);
|
||||
}
|
||||
|
||||
grid.onItemsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void resize(GuiContainer gui) {
|
||||
grid.setGridSize(x, y, w, h);
|
||||
grid.refresh(gui);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackMouseOver(int mousex, int mousey) {
|
||||
ItemPanelSlot slot = getSlotMouseOver(mousex, mousey);
|
||||
return slot == null ? null : slot.item;
|
||||
}
|
||||
|
||||
public ItemPanelSlot getSlotMouseOver(int mousex, int mousey) {
|
||||
return grid.getSlotMouseOver(mousex, mousey);
|
||||
}
|
||||
|
||||
private void drawSplittingArea(int x, int y, int width, int height, int color) {
|
||||
|
||||
float alpha = (color >> 24 & 255) / 255.0F;
|
||||
float red = (color >> 16 & 255) / 255.0F;
|
||||
float green = (color >> 8 & 255) / 255.0F;
|
||||
float blue = (color & 255) / 255.0F;
|
||||
|
||||
GL11.glPushMatrix();
|
||||
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_LINE_STIPPLE);
|
||||
GL11.glColor4f(red, green, blue, alpha);
|
||||
GL11.glLineWidth(2F);
|
||||
GL11.glLineStipple(2, (short) 0x00FF);
|
||||
|
||||
GL11.glBegin(GL11.GL_LINE_LOOP);
|
||||
|
||||
GL11.glVertex2i(x, y);
|
||||
GL11.glVertex2i(x + width, y);
|
||||
GL11.glVertex2i(x + width, y + height);
|
||||
GL11.glVertex2i(x, y + height);
|
||||
|
||||
GL11.glEnd();
|
||||
|
||||
GL11.glLineStipple(1, (short) 0xFFFF);
|
||||
GL11.glLineWidth(1F);
|
||||
GL11.glDisable(GL11.GL_LINE_STIPPLE);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glColor4f(1F, 1F, 1F, 1F);
|
||||
|
||||
GL11.glPopMatrix();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(int mousex, int mousey, int button, long heldTime) {
|
||||
|
||||
if (mouseDownSlot >= 0 && ItemPanels.itemPanel.draggedStack == null
|
||||
&& NEIClientUtils.getHeldItem() == null
|
||||
&& NEIClientConfig.hasSMPCounterPart()) {
|
||||
|
||||
ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500) {
|
||||
ItemPanels.itemPanel.draggedStack = getDraggedStackWithQuantity(mouseDownSlot);
|
||||
mouseDownSlot = -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClick(int mousex, int mousey, int button) {
|
||||
if (handleClickExt(mousex, mousey, button)) return true;
|
||||
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
if (hoverSlot != null) {
|
||||
|
||||
if (button == 2) {
|
||||
|
||||
if (hoverSlot.item != null) {
|
||||
ItemPanels.itemPanel.draggedStack = getDraggedStackWithQuantity(hoverSlot.slotIndex);
|
||||
}
|
||||
|
||||
} else {
|
||||
mouseDownSlot = hoverSlot.slotIndex;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(int mousex, int mousey, int button) {
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && ItemPanels.itemPanel.draggedStack == null) {
|
||||
ItemStack item = hoverSlot.item.copy();
|
||||
|
||||
if (NEIController.manager.window instanceof GuiRecipe || NEIClientUtils.shiftKey()
|
||||
|| !NEIClientConfig.canCheatItem(item)) {
|
||||
|
||||
if (button == 0) {
|
||||
GuiCraftingRecipe.openRecipeGui("item", item);
|
||||
} else if (button == 1) {
|
||||
GuiUsageRecipe.openRecipeGui("item", item);
|
||||
}
|
||||
|
||||
mouseDownSlot = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
NEIClientUtils.cheatItem(getDraggedStackWithQuantity(hoverSlot.slotIndex), button, -1);
|
||||
}
|
||||
|
||||
mouseDownSlot = -1;
|
||||
}
|
||||
|
||||
protected ItemStack getDraggedStackWithQuantity(int mouseDownSlot) {
|
||||
ItemStack stack = grid.getItem(mouseDownSlot);
|
||||
|
||||
if (stack != null) {
|
||||
int amount = NEIClientConfig.showItemQuantityWidget() ? NEIClientConfig.getItemQuantity() : 0;
|
||||
|
||||
if (amount == 0) {
|
||||
amount = stack.getMaxStackSize();
|
||||
}
|
||||
|
||||
return NEIServerUtils.copyStack(stack, amount);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +1,36 @@
|
||||
package codechicken.nei;
|
||||
|
||||
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;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinWorkerThread;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
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.search.TooltipFilter;
|
||||
|
||||
public class ItemList {
|
||||
|
||||
/**
|
||||
* Fields are replaced atomically and contents never modified.
|
||||
*/
|
||||
@@ -32,13 +43,18 @@ public class ItemList {
|
||||
* Updates to this should be synchronised on this
|
||||
*/
|
||||
public static final List<ItemFilterProvider> itemFilterers = new LinkedList<>();
|
||||
|
||||
public static final List<ItemsLoadedCallback> loadCallbacks = new LinkedList<>();
|
||||
|
||||
private static final HashSet<Item> erroredItems = new HashSet<>();
|
||||
private static final HashSet<String> stackTraces = new HashSet<>();
|
||||
private static HashMap<ItemStack, Integer> ordering = new HashMap<>();
|
||||
/**
|
||||
* Unlike {@link LayoutManager#itemsLoaded}, this indicates whether item loading is actually finished or not.
|
||||
*/
|
||||
public static boolean loadFinished;
|
||||
|
||||
public static class EverythingItemFilter implements ItemFilter {
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return true;
|
||||
@@ -46,13 +62,29 @@ public class ItemList {
|
||||
}
|
||||
|
||||
public static class NothingItemFilter implements ItemFilter {
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NegatedItemFilter implements ItemFilter {
|
||||
|
||||
public ItemFilter filter;
|
||||
|
||||
public NegatedItemFilter(ItemFilter filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return this.filter == null || !this.filter.matches(item);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PatternItemFilter implements ItemFilter {
|
||||
|
||||
public Pattern pattern;
|
||||
|
||||
public PatternItemFilter(Pattern pattern) {
|
||||
@@ -61,35 +93,54 @@ public class ItemList {
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return pattern.matcher(ItemInfo.getSearchName(item)).find();
|
||||
String displayName = EnumChatFormatting.getTextWithoutFormattingCodes(item.getDisplayName());
|
||||
|
||||
if (displayName != null && !displayName.isEmpty() && pattern.matcher(displayName).find()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (item.hasDisplayName()) {
|
||||
displayName = EnumChatFormatting
|
||||
.getTextWithoutFormattingCodes(item.getItem().getItemStackDisplayName(item));
|
||||
|
||||
return displayName != null && !displayName.isEmpty() && pattern.matcher(displayName).find();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AllMultiItemFilter implements ItemFilter {
|
||||
|
||||
public List<ItemFilter> filters;
|
||||
|
||||
public AllMultiItemFilter(List<ItemFilter> filters) {
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
public AllMultiItemFilter(ItemFilter... filters) {
|
||||
this(new LinkedList<>(Arrays.asList(filters)));
|
||||
}
|
||||
|
||||
public AllMultiItemFilter() {
|
||||
this(new LinkedList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
for (ItemFilter filter : filters)
|
||||
try {
|
||||
if (!filter.matches(item)) return false;
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Exception filtering " + item + " with " + filter, e);
|
||||
}
|
||||
for (ItemFilter filter : filters) try {
|
||||
if (filter != null && !filter.matches(item)) return false;
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger
|
||||
.error("Exception filtering " + item + " with " + filter + " (" + e.getMessage() + ")", e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AnyMultiItemFilter implements ItemFilter {
|
||||
|
||||
public List<ItemFilter> filters;
|
||||
|
||||
public AnyMultiItemFilter(List<ItemFilter> filters) {
|
||||
@@ -102,27 +153,29 @@ public class ItemList {
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
for (ItemFilter filter : filters)
|
||||
try {
|
||||
if (filter.matches(item)) return true;
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Exception filtering " + item + " with " + filter, e);
|
||||
}
|
||||
for (ItemFilter filter : filters) try {
|
||||
if (filter != null && filter.matches(item)) return true;
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger
|
||||
.error("Exception filtering " + item + " with " + filter + " (" + e.getMessage() + ")", e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface ItemsLoadedCallback {
|
||||
|
||||
public void itemsLoaded();
|
||||
}
|
||||
|
||||
public static boolean itemMatchesAll(ItemStack item, List<ItemFilter> filters) {
|
||||
for (ItemFilter filter : filters) {
|
||||
try {
|
||||
if (!filter.matches(item)) return false;
|
||||
if (filter != null && !filter.matches(item)) return false;
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Exception filtering " + item + " with " + filter, e);
|
||||
NEIClientConfig.logger
|
||||
.error("Exception filtering " + item + " with " + filter + " (" + e.getMessage() + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +183,7 @@ public class ItemList {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use getItemListFilter().matches(item)
|
||||
* @deprecated use getItemListFilter().matches(item)
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean itemMatches(ItemStack item) {
|
||||
@@ -144,72 +197,157 @@ public class ItemList {
|
||||
public static List<ItemFilter> getItemFilters() {
|
||||
LinkedList<ItemFilter> filters = new LinkedList<>();
|
||||
synchronized (itemFilterers) {
|
||||
for (ItemFilterProvider p : itemFilterers) filters.add(p.getFilter());
|
||||
for (ItemFilterProvider p : itemFilterers) {
|
||||
filters.add(p.getFilter());
|
||||
}
|
||||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
public static final RestartableTask loadItems = new RestartableTask("NEI Item Loading") {
|
||||
|
||||
private void damageSearch(Item item, List<ItemStack> permutations) {
|
||||
HashSet<String> damageIconSet = new HashSet<>();
|
||||
for (int damage = 0; damage < 16; damage++)
|
||||
try {
|
||||
ItemStack itemstack = new ItemStack(item, 1, damage);
|
||||
IIcon icon = item.getIconIndex(itemstack);
|
||||
String name = GuiContainerManager.concatenatedDisplayName(itemstack, false);
|
||||
String s = name + "@" + (icon == null ? 0 : icon.hashCode());
|
||||
if (!damageIconSet.contains(s)) {
|
||||
damageIconSet.add(s);
|
||||
permutations.add(itemstack);
|
||||
}
|
||||
} catch (TimeoutException t) {
|
||||
throw t;
|
||||
} catch (Throwable t) {
|
||||
NEIServerUtils.logOnce(
|
||||
t,
|
||||
stackTraces,
|
||||
"Ommiting " + item + ":" + damage + " "
|
||||
+ item.getClass().getSimpleName(),
|
||||
item.toString());
|
||||
for (int damage = 0; damage < 16; damage++) try {
|
||||
ItemStack itemstack = new ItemStack(item, 1, damage);
|
||||
IIcon icon = item.getIconIndex(itemstack);
|
||||
String name = getTooltip(itemstack);
|
||||
String s = name + "@" + (icon == null ? 0 : icon.hashCode());
|
||||
if (!damageIconSet.contains(s)) {
|
||||
damageIconSet.add(s);
|
||||
permutations.add(itemstack);
|
||||
}
|
||||
} catch (TimeoutException t) {
|
||||
throw t;
|
||||
} catch (Throwable t) {
|
||||
NEIServerUtils.logOnce(
|
||||
t,
|
||||
stackTraces,
|
||||
"Ommiting " + item + ":" + damage + " " + item.getClass().getSimpleName(),
|
||||
item.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private String getTooltip(ItemStack stack) {
|
||||
try {
|
||||
return String.join("\n", stack.getTooltip(Minecraft.getMinecraft().thePlayer, false));
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private void updateOrdering(List<ItemStack> items) {
|
||||
ItemSorter.sort(items);
|
||||
|
||||
HashMap<ItemStack, Integer> newOrdering = new HashMap<>();
|
||||
|
||||
if (!CollapsibleItems.isEmpty()) {
|
||||
HashMap<Integer, Integer> groups = new HashMap<>();
|
||||
int orderIndex = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
final int groupIndex = CollapsibleItems.getGroupIndex(stack);
|
||||
|
||||
if (groupIndex == -1) {
|
||||
newOrdering.put(stack, orderIndex++);
|
||||
} else {
|
||||
|
||||
if (!groups.containsKey(groupIndex)) {
|
||||
groups.put(groupIndex, orderIndex++);
|
||||
}
|
||||
|
||||
newOrdering.put(stack, groups.get(groupIndex));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int orderIndex = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
newOrdering.put(stack, orderIndex++);
|
||||
}
|
||||
}
|
||||
|
||||
ItemList.ordering = newOrdering;
|
||||
}
|
||||
|
||||
private List<ItemStack> getPermutations(Item item) {
|
||||
final List<ItemStack> permutations = new LinkedList<>(ItemInfo.itemOverrides.get(item));
|
||||
|
||||
if (permutations.isEmpty()) {
|
||||
item.getSubItems(item, null, permutations);
|
||||
}
|
||||
|
||||
if (permutations.isEmpty()) {
|
||||
damageSearch(item, permutations);
|
||||
}
|
||||
|
||||
permutations.addAll(ItemInfo.itemVariants.get(item));
|
||||
|
||||
return permutations.stream()
|
||||
.filter(
|
||||
stack -> stack.getItem() != null && stack.getItem().delegate.name() != null
|
||||
&& !ItemInfo.isHidden(stack))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// For optimization it generate itemslist, permutations, orders & collapsibleitems
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void execute() {
|
||||
// System.out.println("Executing NEI Item Loading");
|
||||
ThreadOperationTimer timer = getTimer(NEIClientConfig.getItemLoadingTimeout());
|
||||
if (!NEIClientConfig.isEnabled()) return;
|
||||
|
||||
LinkedList<ItemStack> items = new LinkedList<>();
|
||||
LinkedList<ItemStack> permutations = new LinkedList<>();
|
||||
ThreadOperationTimer timer = getTimer(NEIClientConfig.getItemLoadingTimeout());
|
||||
LayoutManager.itemsLoaded = true;
|
||||
loadFinished = false;
|
||||
|
||||
SearchField.searchParser.clearCache();
|
||||
ItemSorter.instance.ordering.clear();
|
||||
CollapsibleItems.clearCache();
|
||||
TooltipFilter.clearCache();
|
||||
|
||||
List<ItemStack> items = new ArrayList<>();
|
||||
ListMultimap<Item, ItemStack> itemMap = ArrayListMultimap.create();
|
||||
ItemStackSet unique = new ItemStackSet();
|
||||
|
||||
timer.setLimit(NEIClientConfig.getItemLoadingTimeout());
|
||||
for (Item item : (Iterable<Item>) Item.itemRegistry) {
|
||||
if (interrupted()) return;
|
||||
|
||||
if (item == null || erroredItems.contains(item)) continue;
|
||||
StreamSupport.stream(((Iterable<Item>) Item.itemRegistry).spliterator(), true).forEach(item -> {
|
||||
if (item == null || item.delegate.name() == null || erroredItems.contains(item)) return;
|
||||
|
||||
try {
|
||||
timer.reset(item);
|
||||
|
||||
permutations.clear();
|
||||
permutations.addAll(ItemInfo.itemOverrides.get(item));
|
||||
|
||||
if (permutations.isEmpty()) item.getSubItems(item, null, permutations);
|
||||
|
||||
if (permutations.isEmpty()) damageSearch(item, permutations);
|
||||
|
||||
permutations.addAll(ItemInfo.itemVariants.get(item));
|
||||
|
||||
List<ItemStack> permutations = getPermutations(item);
|
||||
timer.reset();
|
||||
|
||||
items.addAll(permutations);
|
||||
itemMap.putAll(item, permutations);
|
||||
for (ItemStack stack : permutations) {
|
||||
if (!unique.contains(stack)) {
|
||||
|
||||
synchronized (unique) {
|
||||
unique.add(stack);
|
||||
}
|
||||
|
||||
synchronized (items) {
|
||||
items.add(stack);
|
||||
}
|
||||
|
||||
CollapsibleItems.putItem(stack);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (itemMap) {
|
||||
itemMap.putAll(item, permutations);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
NEIServerConfig.logger.error("Removing item: " + item + " from list.", t);
|
||||
NEIServerConfig.logger.error("Removing item: {} from list.", item, t);
|
||||
erroredItems.add(item);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
int index = 0;
|
||||
for (Item item : (Iterable<Item>) Item.itemRegistry) {
|
||||
for (ItemStack stack : itemMap.get(item)) {
|
||||
ItemSorter.instance.ordering.put(stack, index++);
|
||||
}
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
@@ -217,31 +355,51 @@ public class ItemList {
|
||||
ItemList.itemMap = itemMap;
|
||||
for (ItemsLoadedCallback callback : loadCallbacks) callback.itemsLoaded();
|
||||
|
||||
if (interrupted()) return;
|
||||
updateOrdering(ItemList.items);
|
||||
|
||||
new Thread(
|
||||
() -> ItemList.items.parallelStream().forEach(TooltipFilter::getSearchTooltip),
|
||||
"NEI Tooltip Filter Loader").start();
|
||||
|
||||
loadFinished = true;
|
||||
|
||||
SubsetWidget.updateHiddenItems();
|
||||
updateFilter.restart();
|
||||
}
|
||||
};
|
||||
|
||||
public static ForkJoinPool getPool(int poolSize) {
|
||||
if (poolSize < 1) poolSize = 1;
|
||||
public static ForkJoinPool forkJoinPool;
|
||||
|
||||
return new ForkJoinPool(poolSize);
|
||||
static {
|
||||
final ForkJoinPool.ForkJoinWorkerThreadFactory factory = new ForkJoinPool.ForkJoinWorkerThreadFactory() {
|
||||
|
||||
private int workerId;
|
||||
|
||||
@Override
|
||||
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
|
||||
final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
|
||||
worker.setName("NEI-worker-thread-" + workerId++);
|
||||
return worker;
|
||||
}
|
||||
};
|
||||
int poolSize = Runtime.getRuntime().availableProcessors() * 2 / 3;
|
||||
if (poolSize < 1) poolSize = 1;
|
||||
forkJoinPool = new ForkJoinPool(poolSize, factory, null, false);
|
||||
}
|
||||
|
||||
public static final int numProcessors = Runtime.getRuntime().availableProcessors();
|
||||
public static ForkJoinPool forkJoinPool = getPool(numProcessors * 2 / 3);
|
||||
|
||||
public static final RestartableTask updateFilter = new RestartableTask("NEI Item Filtering") {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
// System.out.println("Executing NEI Item Filtering");
|
||||
ArrayList<ItemStack> filtered;
|
||||
|
||||
if (!loadFinished) return;
|
||||
ItemFilter filter = getItemListFilter();
|
||||
ArrayList<ItemStack> filtered;
|
||||
|
||||
try {
|
||||
filtered = ItemList.forkJoinPool
|
||||
.submit(() -> items.parallelStream()
|
||||
.filter(PresetsWidget::matches)
|
||||
.filter(filter::matches)
|
||||
filtered = ItemList.forkJoinPool.submit(
|
||||
() -> items.parallelStream().filter(filter::matches)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
@@ -251,8 +409,12 @@ public class ItemList {
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
ItemSorter.sort(filtered);
|
||||
|
||||
Comparator<ItemStack> comparator = Comparator.comparingInt(ItemList.ordering::get);
|
||||
filtered.sort(comparator::compare);
|
||||
|
||||
if (interrupted()) return;
|
||||
|
||||
ItemPanel.updateItemList(filtered);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ package codechicken.nei;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityList;
|
||||
@@ -20,8 +21,9 @@ import net.minecraft.world.World;
|
||||
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;
|
||||
|
||||
@@ -30,9 +32,6 @@ public class ItemMobSpawner extends ItemBlock {
|
||||
|
||||
hasSubtypes = true;
|
||||
MinecraftForgeClient.registerItemRenderer(this, new SpawnerRenderer());
|
||||
|
||||
entityHashMap = new HashMap<>();
|
||||
IDtoNameMap = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,20 +47,11 @@ public class ItemMobSpawner extends ItemBlock {
|
||||
return Blocks.mob_spawner.getBlockTextureFromSide(0);
|
||||
}
|
||||
|
||||
public boolean onItemUse(
|
||||
ItemStack itemstack,
|
||||
EntityPlayer entityplayer,
|
||||
World world,
|
||||
int x,
|
||||
int y,
|
||||
int z,
|
||||
int par7,
|
||||
float par8,
|
||||
float par9,
|
||||
float par10) {
|
||||
public boolean onItemUse(ItemStack itemstack, EntityPlayer entityplayer, World world, int x, int y, int z, int par7,
|
||||
float par8, float par9, float par10) {
|
||||
if (super.onItemUse(itemstack, entityplayer, world, x, y, z, par7, par8, par9, par10) && world.isRemote) {
|
||||
TileEntityMobSpawner tileentitymobspawner =
|
||||
(TileEntityMobSpawner) world.getTileEntity(placedX, placedY, placedZ);
|
||||
TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) world
|
||||
.getTileEntity(placedX, placedY, placedZ);
|
||||
if (tileentitymobspawner != null) {
|
||||
setDefaultTag(itemstack);
|
||||
String mobtype = IDtoNameMap.get(itemstack.getItemDamage());
|
||||
@@ -76,7 +66,7 @@ public class ItemMobSpawner extends ItemBlock {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInformation(ItemStack itemstack, EntityPlayer par2EntityPlayer, List list, boolean par4) {
|
||||
public void addInformation(ItemStack itemstack, EntityPlayer par2EntityPlayer, List<String> list, boolean par4) {
|
||||
setDefaultTag(itemstack);
|
||||
int meta = itemstack.getItemDamage();
|
||||
if (meta == 0) {
|
||||
@@ -93,8 +83,7 @@ public class ItemMobSpawner extends ItemBlock {
|
||||
loadSpawners(world);
|
||||
Class<?> clazz = (Class<?>) EntityList.IDtoClassMapping.get(ID);
|
||||
try {
|
||||
e = (EntityLiving)
|
||||
clazz.getConstructor(new Class[] {World.class}).newInstance(world);
|
||||
e = (EntityLiving) clazz.getConstructor(new Class[] { World.class }).newInstance(world);
|
||||
} catch (Throwable t) {
|
||||
if (clazz == null)
|
||||
NEIClientConfig.logger.error("Null class for entity (" + ID + ", " + IDtoNameMap.get(ID));
|
||||
@@ -117,15 +106,14 @@ public class ItemMobSpawner extends ItemBlock {
|
||||
public static void loadSpawners(World world) {
|
||||
if (loaded) return;
|
||||
loaded = true;
|
||||
HashMap<Class<Entity>, String> classToStringMapping =
|
||||
(HashMap<Class<Entity>, String>) EntityList.classToStringMapping;
|
||||
HashMap<Class<Entity>, Integer> classToIDMapping =
|
||||
(HashMap<Class<Entity>, Integer>) EntityList.classToIDMapping;
|
||||
for (Class<Entity> eclass : classToStringMapping.keySet()) {
|
||||
Map<Class<? extends Entity>, String> classToStringMapping = EntityList.classToStringMapping;
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Class<? extends Entity>, Integer> classToIDMapping = (Map<Class<? extends Entity>, Integer>) EntityList.classToIDMapping;
|
||||
for (Class<? extends Entity> eclass : classToStringMapping.keySet()) {
|
||||
if (!EntityLiving.class.isAssignableFrom(eclass)) continue;
|
||||
try {
|
||||
EntityLiving entityliving = (EntityLiving)
|
||||
eclass.getConstructor(new Class[] {World.class}).newInstance(world);
|
||||
EntityLiving entityliving = (EntityLiving) eclass.getConstructor(new Class[] { World.class })
|
||||
.newInstance(world);
|
||||
entityliving.isChild();
|
||||
|
||||
int id = classToIDMapping.get(eclass);
|
||||
@@ -136,17 +124,15 @@ public class ItemMobSpawner extends ItemBlock {
|
||||
IDtoNameMap.put(id, name);
|
||||
|
||||
if (name.equals("Pig")) idPig = id;
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
IDtoNameMap.entrySet()
|
||||
.removeIf(e -> getEntity(e.getKey()).getClass() == EntityPig.class
|
||||
&& !e.getValue().equals("Pig"));
|
||||
.removeIf(e -> getEntity(e.getKey()).getClass() == EntityPig.class && !e.getValue().equals("Pig"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getSubItems(Item item, CreativeTabs tab, List list) {
|
||||
public void getSubItems(Item item, CreativeTabs tab, List<ItemStack> list) {
|
||||
if (!NEIClientConfig.hasSMPCounterPart()) list.add(new ItemStack(item));
|
||||
else for (int i : IDtoNameMap.keySet()) list.add(new ItemStack(item, 1, i));
|
||||
}
|
||||
|
||||
@@ -1,17 +1,30 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
|
||||
public class ItemPanel extends PanelWidget {
|
||||
|
||||
/**
|
||||
* Backwards compat :-/
|
||||
* Backwards compat :-/
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated
|
||||
@@ -28,11 +41,11 @@ public class ItemPanel extends PanelWidget {
|
||||
return super.getStackMouseOver(mousex, mousey);
|
||||
}
|
||||
|
||||
public Button more;
|
||||
public Button less;
|
||||
public ItemQuantityField quantity;
|
||||
public ItemHistoryPanel historyPanel;
|
||||
public Button toggleGroups;
|
||||
|
||||
public static class ItemPanelSlot {
|
||||
|
||||
public ItemStack item;
|
||||
public int slotIndex;
|
||||
|
||||
@@ -47,8 +60,30 @@ public class ItemPanel extends PanelWidget {
|
||||
}
|
||||
}
|
||||
|
||||
protected static class MaskMetadata {
|
||||
|
||||
public int groupIndex = -1;
|
||||
public String displayName = "";
|
||||
public boolean extended = false;
|
||||
|
||||
public Color bgColor = null;
|
||||
public Color color = null;
|
||||
|
||||
public boolean left = false;
|
||||
public boolean top = false;
|
||||
public boolean right = false;
|
||||
public boolean bottom = false;
|
||||
|
||||
}
|
||||
|
||||
protected static class ItemPanelGrid extends ItemsGrid {
|
||||
|
||||
public ArrayList<ItemStack> newItems;
|
||||
public ArrayList<ItemStack> rawItems;
|
||||
|
||||
protected final HashMap<Integer, List<ItemStack>> groupItems = new HashMap<>();
|
||||
protected final HashMap<Integer, MaskMetadata> maskMetadata = new HashMap<>();
|
||||
protected boolean forceExpand = false;
|
||||
|
||||
public void setItems(ArrayList<ItemStack> items) {
|
||||
newItems = items;
|
||||
@@ -56,22 +91,226 @@ public class ItemPanel extends PanelWidget {
|
||||
|
||||
public void refresh(GuiContainer gui) {
|
||||
|
||||
if (newItems != null) {
|
||||
realItems = newItems;
|
||||
newItems = null;
|
||||
onGridChanged();
|
||||
if (this.newItems != null) {
|
||||
this.groupItems.clear();
|
||||
this.forceExpand = false;
|
||||
|
||||
if (!CollapsibleItems.isEmpty() && !this.newItems.isEmpty()) {
|
||||
final Set<Integer> groups = new HashSet<>();
|
||||
boolean outsideGroup = false;
|
||||
|
||||
this.realItems = new ArrayList<>();
|
||||
this.rawItems = new ArrayList<>(this.newItems);
|
||||
|
||||
for (ItemStack stack : this.newItems) {
|
||||
final int groupIndex = CollapsibleItems.getGroupIndex(stack);
|
||||
|
||||
if (groupIndex == -1) {
|
||||
this.realItems.add(stack);
|
||||
outsideGroup = true;
|
||||
} else {
|
||||
|
||||
if (!groups.contains(groupIndex) || CollapsibleItems.isExpanded(groupIndex)) {
|
||||
this.realItems.add(stack);
|
||||
groups.add(groupIndex);
|
||||
}
|
||||
|
||||
if (!this.groupItems.containsKey(groupIndex)) {
|
||||
this.groupItems.put(groupIndex, new ArrayList<>());
|
||||
}
|
||||
|
||||
this.groupItems.get(groupIndex).add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
// automatically opens if there are elements from only one group
|
||||
if (!outsideGroup && groups.size() == 1) {
|
||||
this.realItems = new ArrayList<>(this.newItems);
|
||||
this.forceExpand = true;
|
||||
}
|
||||
} else {
|
||||
this.realItems = new ArrayList<>(this.newItems);
|
||||
}
|
||||
|
||||
this.newItems = null;
|
||||
onItemsChanged();
|
||||
}
|
||||
|
||||
super.refresh(gui);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSlotOutline(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
if (PresetsWidget.inEditMode()) {
|
||||
if (!PresetsWidget.isHidden(getItem(slotIdx))) drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);
|
||||
} else {
|
||||
super.drawSlotOutline(focused, slotIdx, rect);
|
||||
protected List<Integer> getMask() {
|
||||
final boolean updateBorders = this.gridMask == null;
|
||||
final List<Integer> mask = super.getMask();
|
||||
|
||||
if (updateBorders) {
|
||||
calculateGroupBorders(mask);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
protected void calculateGroupBorders(List<Integer> mask) {
|
||||
this.maskMetadata.clear();
|
||||
|
||||
if (mask.isEmpty() || this.groupItems.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final HashMap<Integer, Integer> maskGroup = new HashMap<>();
|
||||
final Color collapsedColor = new Color(
|
||||
NEIClientConfig.getSetting("inventory.collapsibleItems.collapsedColor").getHexValue(),
|
||||
true);
|
||||
final Color expandedColor = new Color(
|
||||
NEIClientConfig.getSetting("inventory.collapsibleItems.expandedColor").getHexValue(),
|
||||
true);
|
||||
|
||||
for (int slotIndex = 0; slotIndex < mask.size(); slotIndex++) {
|
||||
if (mask.get(slotIndex) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = mask.get(slotIndex);
|
||||
maskGroup.put(idx, CollapsibleItems.getGroupIndex(getItem(idx)));
|
||||
}
|
||||
|
||||
for (int slotIndex = 0; slotIndex < mask.size(); slotIndex++) {
|
||||
if (mask.get(slotIndex) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = mask.get(slotIndex);
|
||||
int groupIndex = maskGroup.get(idx);
|
||||
|
||||
if (groupIndex == -1 || this.groupItems.get(groupIndex).size() == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int column = slotIndex % this.columns;
|
||||
int row = slotIndex / this.columns;
|
||||
int prevSlotIndex = (row - 1) * this.columns + column;
|
||||
int nextSlotIndex = (row + 1) * this.columns + column;
|
||||
MaskMetadata metadata = new MaskMetadata();
|
||||
|
||||
metadata.groupIndex = groupIndex;
|
||||
metadata.displayName = CollapsibleItems.getDisplayName(groupIndex);
|
||||
metadata.extended = this.forceExpand || CollapsibleItems.isExpanded(groupIndex);
|
||||
metadata.bgColor = metadata.extended ? expandedColor : collapsedColor;
|
||||
metadata.color = darkerColor(metadata.bgColor);
|
||||
metadata.left = column == 0 || idx == 0
|
||||
|| mask.get(slotIndex - 1) == null
|
||||
|| maskGroup.getOrDefault(idx - 1, -1) != groupIndex;
|
||||
metadata.right = column == this.columns - 1 || maskGroup.getOrDefault(idx + 1, -1) != groupIndex;
|
||||
|
||||
if (prevSlotIndex >= 0) {
|
||||
Integer previdx = mask.get(prevSlotIndex);
|
||||
metadata.top = previdx == null || maskGroup.getOrDefault(previdx, -1) != groupIndex;
|
||||
} else {
|
||||
metadata.top = true;
|
||||
}
|
||||
|
||||
if (nextSlotIndex < mask.size()) {
|
||||
Integer nextidx = mask.get(nextSlotIndex);
|
||||
metadata.bottom = nextidx == null || maskGroup.getOrDefault(nextidx, -1) != groupIndex;
|
||||
} else {
|
||||
metadata.bottom = true;
|
||||
}
|
||||
|
||||
this.maskMetadata.put(idx, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
final List<Integer> mask = getMask();
|
||||
|
||||
super.beforeDrawItems(mousex, mousey, focused);
|
||||
|
||||
for (int i = 0; i < mask.size(); i++) {
|
||||
if (mask.get(i) != null) {
|
||||
drawBorder(mask.get(i), getSlotRect(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawBorder(int slotIdx, Rectangle4i rect) {
|
||||
final MaskMetadata metadata = this.maskMetadata.get(slotIdx);
|
||||
|
||||
if (metadata != null) {
|
||||
final float LINE_WIDTH = 0.75f;
|
||||
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, metadata.bgColor);
|
||||
|
||||
if (metadata.left) {
|
||||
float leftBottom = metadata.bottom ? -LINE_WIDTH : 0;
|
||||
drawRect(rect.x, rect.y, LINE_WIDTH, rect.h + leftBottom, metadata.color);
|
||||
}
|
||||
|
||||
if (metadata.right) {
|
||||
float rightTop = metadata.top ? LINE_WIDTH : 0;
|
||||
drawRect(rect.x + rect.w, rect.y - rightTop, LINE_WIDTH, rect.h + rightTop, metadata.color);
|
||||
}
|
||||
|
||||
if (metadata.top) {
|
||||
drawRect(rect.x, rect.y - LINE_WIDTH, rect.w, LINE_WIDTH, metadata.color);
|
||||
}
|
||||
|
||||
if (metadata.bottom) {
|
||||
drawRect(rect.x, rect.y + rect.h - LINE_WIDTH, rect.w, LINE_WIDTH, metadata.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Color darkerColor(Color color) {
|
||||
return new Color(
|
||||
color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue(),
|
||||
Math.min((int) (color.getAlpha() + (255f / 5) * 2), 255));
|
||||
}
|
||||
|
||||
private static void drawRect(double left, double top, double width, double height, Color color) {
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
OpenGlHelper.glBlendFunc(770, 771, 1, 0);
|
||||
GL11.glColor4f(
|
||||
color.getRed() / 255f,
|
||||
color.getGreen() / 255f,
|
||||
color.getBlue() / 255f,
|
||||
color.getAlpha() / 255f);
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.addVertex(left, top + height, 0.0D);
|
||||
tessellator.addVertex(left + width, top + height, 0.0D);
|
||||
tessellator.addVertex(left + width, top, 0.0D);
|
||||
tessellator.addVertex(left, top, 0.0D);
|
||||
tessellator.draw();
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawItem(Rectangle4i rect, int slotIdx) {
|
||||
final MaskMetadata metadata = this.maskMetadata.get(slotIdx);
|
||||
|
||||
if (metadata != null && !metadata.extended) {
|
||||
final List<ItemStack> groupItems = this.groupItems.get(metadata.groupIndex);
|
||||
|
||||
GuiContainerManager.drawItems.zLevel -= 10F;
|
||||
GuiContainerManager.drawItem(rect.x + 1, rect.y - 1, groupItems.get(groupItems.size() - 1), true, "");
|
||||
GuiContainerManager.drawItems.zLevel += 10F;
|
||||
|
||||
GuiContainerManager.drawItem(rect.x - 1, rect.y + 1, getItem(slotIdx), true, "");
|
||||
} else {
|
||||
super.drawItem(rect, slotIdx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageOnEmpty() {
|
||||
return ItemList.loadFinished ? null : NEIClientUtils.translate("itempanel.loading");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,40 +327,22 @@ public class ItemPanel extends PanelWidget {
|
||||
public void init() {
|
||||
super.init();
|
||||
|
||||
more = new Button("+") {
|
||||
toggleGroups = new Button("G") {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick) return false;
|
||||
|
||||
int modifier = NEIClientUtils.controlKey() ? 64 : NEIClientUtils.shiftKey() ? 10 : 1;
|
||||
int quantity = NEIClientConfig.getItemQuantity() + modifier;
|
||||
|
||||
if (quantity < 0) {
|
||||
quantity = 0;
|
||||
}
|
||||
|
||||
ItemPanels.itemPanel.quantity.setText(Integer.toString(quantity));
|
||||
return true;
|
||||
public String getButtonTip() {
|
||||
return NEIClientUtils.translate("itempanel.collapsed.button.tip");
|
||||
}
|
||||
};
|
||||
less = new Button("-") {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick) return false;
|
||||
|
||||
int modifier = NEIClientUtils.controlKey() ? -64 : NEIClientUtils.shiftKey() ? -10 : -1;
|
||||
int quantity = NEIClientConfig.getItemQuantity() + modifier;
|
||||
|
||||
if (quantity < 0) {
|
||||
quantity = 0;
|
||||
}
|
||||
|
||||
ItemPanels.itemPanel.quantity.setText(Integer.toString(quantity));
|
||||
CollapsibleItems.toggleGroups(rightclick ? false : null);
|
||||
ItemList.updateFilter.restart();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
quantity = new ItemQuantityField("quantity");
|
||||
historyPanel = new ItemHistoryPanel();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@@ -130,7 +351,7 @@ public class ItemPanel extends PanelWidget {
|
||||
}
|
||||
|
||||
public String getLabelText() {
|
||||
return String.format("(%d/%d)", getPage(), Math.max(1, getNumPages()));
|
||||
return String.format("%d/%d", getPage(), Math.max(1, getNumPages()));
|
||||
}
|
||||
|
||||
protected String getPositioningSettingName() {
|
||||
@@ -153,35 +374,62 @@ public class ItemPanel extends PanelWidget {
|
||||
return gui.height - getMarginTop(gui) - PADDING;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int resizeHeader(GuiContainer gui) {
|
||||
int marginTop = super.resizeHeader(gui);
|
||||
|
||||
toggleGroups.w = pageNext.w;
|
||||
toggleGroups.h = pageNext.h;
|
||||
toggleGroups.y = pageNext.y;
|
||||
toggleGroups.x = pageNext.x - toggleGroups.w - 2;
|
||||
|
||||
return marginTop;
|
||||
}
|
||||
|
||||
protected int resizeFooter(GuiContainer gui) {
|
||||
if (!NEIClientConfig.showItemQuantityWidget()) return 0;
|
||||
if (!NEIClientConfig.showItemQuantityWidget() && NEIClientConfig.isSearchWidgetCentered()
|
||||
&& !NEIClientConfig.showHistoryPanelWidget()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final int BUTTON_SIZE = 16;
|
||||
if (NEIClientConfig.showHistoryPanelWidget()) {
|
||||
historyPanel.x = x;
|
||||
historyPanel.w = w;
|
||||
historyPanel.h = ItemsGrid.SLOT_SIZE * NEIClientConfig.getIntSetting("inventory.history.useRows");
|
||||
|
||||
more.w = less.w = BUTTON_SIZE;
|
||||
more.h = less.h = quantity.h = BUTTON_SIZE;
|
||||
if (NEIClientConfig.showItemQuantityWidget() || !NEIClientConfig.isSearchWidgetCentered()) {
|
||||
historyPanel.y = LayoutManager.quantity.y - historyPanel.h - PanelWidget.PADDING;
|
||||
return LayoutManager.quantity.h + historyPanel.h + PanelWidget.PADDING * 2;
|
||||
} else {
|
||||
historyPanel.y = y + h - historyPanel.h;
|
||||
return historyPanel.h + PanelWidget.PADDING;
|
||||
}
|
||||
}
|
||||
|
||||
less.x = x;
|
||||
more.x = x + w - BUTTON_SIZE;
|
||||
more.y = less.y = quantity.y = y + h - BUTTON_SIZE;
|
||||
|
||||
quantity.x = x + BUTTON_SIZE + 2;
|
||||
quantity.w = more.x - quantity.x - 2;
|
||||
|
||||
return BUTTON_SIZE + 2;
|
||||
return LayoutManager.quantity.h + PanelWidget.PADDING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible() {
|
||||
super.setVisible();
|
||||
|
||||
if (grid.getPerPage() > 0 && NEIClientConfig.showItemQuantityWidget()) {
|
||||
LayoutManager.addWidget(more);
|
||||
LayoutManager.addWidget(less);
|
||||
LayoutManager.addWidget(quantity);
|
||||
if (grid.getPerPage() > 0) {
|
||||
if (!CollapsibleItems.isEmpty() && !grid.isEmpty()) {
|
||||
LayoutManager.addWidget(toggleGroups);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.showHistoryPanelWidget() && (!grid.isEmpty() || !historyPanel.isEmpty())) {
|
||||
LayoutManager.addWidget(historyPanel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(GuiContainer gui) {
|
||||
super.resize(gui);
|
||||
historyPanel.resize(gui);
|
||||
}
|
||||
|
||||
protected ItemStack getDraggedStackWithQuantity(int mouseDownSlot) {
|
||||
ItemStack stack = grid.getItem(mouseDownSlot);
|
||||
|
||||
@@ -197,4 +445,61 @@ public class ItemPanel extends PanelWidget {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
final ItemPanelGrid panelGrid = ((ItemPanelGrid) this.grid);
|
||||
|
||||
if (!panelGrid.forceExpand && !NEIClientConfig.isHidden() && !currenttip.isEmpty()) {
|
||||
final ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null) {
|
||||
final MaskMetadata metadata = panelGrid.maskMetadata.get(hoverSlot.slotIndex);
|
||||
|
||||
if (metadata != null) {
|
||||
final List<ItemStack> items = panelGrid.groupItems.get(metadata.groupIndex);
|
||||
|
||||
if (NEIClientConfig.getBooleanSetting("inventory.collapsibleItems.customName") && !metadata.extended
|
||||
&& !"".equals(metadata.displayName)) {
|
||||
currenttip.clear();
|
||||
currenttip.add(metadata.displayName + GuiDraw.TOOLTIP_LINESPACE);
|
||||
}
|
||||
|
||||
if (items != null && items.size() > 1) {
|
||||
String message = metadata.extended ? "itempanel.collapsed.hint.collapse"
|
||||
: "itempanel.collapsed.hint.expand";
|
||||
currenttip.add(
|
||||
1,
|
||||
EnumChatFormatting.GRAY + NEIClientUtils.translate(message, items.size())
|
||||
+ EnumChatFormatting.RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.handleItemTooltip(gui, itemstack, mousex, mousey, currenttip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClick(int mousex, int mousey, int button) {
|
||||
final ItemPanelGrid panelGrid = ((ItemPanelGrid) this.grid);
|
||||
|
||||
if (NEIClientUtils.altKey() && button == 0 && !panelGrid.forceExpand) {
|
||||
final ItemPanelSlot hoverSlot = grid.getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null) {
|
||||
final MaskMetadata metadata = panelGrid.maskMetadata.get(hoverSlot.slotIndex);
|
||||
|
||||
if (metadata != null) {
|
||||
CollapsibleItems.setExpanded(metadata.groupIndex, !metadata.extended);
|
||||
panelGrid.setItems(panelGrid.rawItems);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.handleClick(mousex, mousey, button);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
public class ItemPanels {
|
||||
|
||||
public static final ItemPanel itemPanel = new ItemPanel();
|
||||
public static final BookmarkPanel bookmarkPanel = new BookmarkPanel();
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package codechicken.nei;
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
|
||||
public class ItemQuantityField extends TextField {
|
||||
|
||||
public ItemQuantityField(String ident) {
|
||||
super(ident);
|
||||
centered = true;
|
||||
@@ -43,6 +44,7 @@ public class ItemQuantityField extends TextField {
|
||||
|
||||
if (!focused() && intValue() == 0) {
|
||||
field.setText(translate("itempanel.quantity.default"));
|
||||
field.setCursorPositionZero();
|
||||
field.setEnabled(false);
|
||||
super.draw(mousex, mousey);
|
||||
field.setEnabled(true);
|
||||
@@ -51,4 +53,20 @@ public class ItemQuantityField extends TextField {
|
||||
super.draw(mousex, mousey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMouseWheel(int i, int mx, int my) {
|
||||
if (!contains(mx, my)) return false;
|
||||
int multiplier = 1;
|
||||
if (NEIClientUtils.shiftKey()) {
|
||||
multiplier = 10;
|
||||
} else if (NEIClientUtils.controlKey()) {
|
||||
multiplier = 64;
|
||||
}
|
||||
|
||||
int quantity = intValue() + i * multiplier;
|
||||
setText(Integer.toString(quantity));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +1,25 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.config.ConfigTagParent;
|
||||
import codechicken.nei.ItemList.ItemsLoadedCallback;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.config.GuiItemSorter;
|
||||
import codechicken.nei.config.OptionOpenGui;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.StatCollector;
|
||||
|
||||
public class ItemSorter implements Comparator<ItemStack>, ItemsLoadedCallback {
|
||||
import codechicken.lib.config.ConfigTagParent;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.config.GuiItemSorter;
|
||||
import codechicken.nei.config.OptionOpenGui;
|
||||
|
||||
public class ItemSorter implements Comparator<ItemStack> {
|
||||
|
||||
public static class SortEntry {
|
||||
|
||||
public final String name;
|
||||
public final Comparator<ItemStack> comparator;
|
||||
|
||||
@@ -40,12 +44,10 @@ public class ItemSorter implements Comparator<ItemStack>, ItemsLoadedCallback {
|
||||
public static final ItemSorter instance = new ItemSorter();
|
||||
|
||||
// optimisations
|
||||
public HashMap<ItemStack, Integer> ordering = null;
|
||||
public Map<ItemStack, Integer> ordering = new HashMap<>();
|
||||
|
||||
public static void sort(ArrayList<ItemStack> items) {
|
||||
public static void sort(List<ItemStack> items) {
|
||||
try {
|
||||
// items = (ArrayList<ItemStack>)
|
||||
// items.parallelStream().sorted(instance).collect(Collectors.toList());
|
||||
items.sort(instance);
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Exception sorting item list", e);
|
||||
@@ -61,14 +63,6 @@ public class ItemSorter implements Comparator<ItemStack>, ItemsLoadedCallback {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemsLoaded() {
|
||||
HashMap<ItemStack, Integer> newMap = new HashMap<>();
|
||||
int i = 0;
|
||||
for (ItemStack stack : ItemList.items) newMap.put(stack, i++);
|
||||
ordering = newMap;
|
||||
}
|
||||
|
||||
public static SortEntry find(String name) {
|
||||
for (SortEntry e : entries) if (e.name.equals(name)) return e;
|
||||
|
||||
@@ -119,19 +113,19 @@ public class ItemSorter implements Comparator<ItemStack>, ItemsLoadedCallback {
|
||||
return compareInt(id1, id2);
|
||||
});
|
||||
API.addSortOption("nei.itemsort.name", (o1, o2) -> {
|
||||
String name1 = ItemInfo.getSearchName(o1);
|
||||
String name2 = ItemInfo.getSearchName(o2);
|
||||
String name1 = o1.getDisplayName();
|
||||
String name2 = o2.getDisplayName();
|
||||
return name1.compareTo(name2);
|
||||
});
|
||||
tag.getTag("inventory.itemsort").setDefaultValue(getSaveString(list));
|
||||
API.addOption(new OptionOpenGui("inventory.itemsort", GuiItemSorter.class) {
|
||||
|
||||
@Override
|
||||
public void useGlobals() {
|
||||
super.useGlobals();
|
||||
list = fromSaveString(activeTag().getValue());
|
||||
}
|
||||
});
|
||||
ItemList.loadCallbacks.add(instance);
|
||||
}
|
||||
|
||||
public static String getSaveString(List<SortEntry> list) {
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class ItemStackAmount {
|
||||
|
||||
private final Map<NBTTagCompound, Long> itemMap = new LinkedHashMap<>();
|
||||
|
||||
public void putAll(ItemStackAmount amounts) {
|
||||
for (Map.Entry<NBTTagCompound, Long> entry : amounts.itemMap.entrySet()) {
|
||||
this.itemMap.put(entry.getKey(), entry.getValue() + this.itemMap.getOrDefault(entry.getKey(), 0L));
|
||||
}
|
||||
}
|
||||
|
||||
public void add(ItemStack item) {
|
||||
add(item, (long) StackInfo.getAmount(item));
|
||||
}
|
||||
|
||||
public void add(ItemStack stack, Long value) {
|
||||
if (stack == null || stack.getItem() == null) return;
|
||||
final NBTTagCompound key = StackInfo.itemStackToNBT(stack, false);
|
||||
|
||||
this.itemMap.put(key, value + this.itemMap.getOrDefault(key, 0L));
|
||||
}
|
||||
|
||||
public Long get(ItemStack stack) {
|
||||
if (stack == null || stack.getItem() == null) return null;
|
||||
final NBTTagCompound key = StackInfo.itemStackToNBT(stack, false);
|
||||
|
||||
return this.itemMap.get(key);
|
||||
}
|
||||
|
||||
public void put(ItemStack stack, long value) {
|
||||
if (stack == null || stack.getItem() == null) return;
|
||||
final NBTTagCompound key = StackInfo.itemStackToNBT(stack, false);
|
||||
|
||||
this.itemMap.put(key, value);
|
||||
}
|
||||
|
||||
public long getOrDefault(ItemStack stack, long defaultAmount) {
|
||||
final Long e = get(stack);
|
||||
|
||||
return e == null ? defaultAmount : e;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.itemMap.clear();
|
||||
}
|
||||
|
||||
public Long remove(ItemStack stack) {
|
||||
if (stack == null || stack.getItem() == null) return null;
|
||||
final NBTTagCompound key = StackInfo.itemStackToNBT(stack, false);
|
||||
|
||||
return this.itemMap.remove(key);
|
||||
}
|
||||
|
||||
public boolean removeIf(Predicate<Map.Entry<NBTTagCompound, Long>> predicate) {
|
||||
return this.itemMap.entrySet().removeIf(predicate);
|
||||
}
|
||||
|
||||
public Set<Map.Entry<NBTTagCompound, Long>> entrySet() {
|
||||
return this.itemMap.entrySet();
|
||||
}
|
||||
|
||||
public List<ItemStack> values() {
|
||||
List<ItemStack> list = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<NBTTagCompound, Long> entry : this.itemMap.entrySet()) {
|
||||
list.add(StackInfo.loadFromNBT(entry.getKey(), Math.max(0, entry.getValue())));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.itemMap.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.itemMap.isEmpty();
|
||||
}
|
||||
|
||||
public static ItemStackAmount of(ItemStackAmount map) {
|
||||
ItemStackAmount result = new ItemStackAmount();
|
||||
result.itemMap.putAll(map.itemMap);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ItemStackAmount of(ItemStackMap<Long> map) {
|
||||
ItemStackAmount result = new ItemStackAmount();
|
||||
|
||||
for (ItemStackMap.Entry<Long> entry : map.entries()) {
|
||||
result.put(entry.key, entry.value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ItemStackAmount of(Iterable<ItemStack> items) {
|
||||
ItemStackAmount result = new ItemStackAmount();
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
result.add(stack);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,24 +4,35 @@ import static codechicken.lib.inventory.InventoryUtils.actualDamage;
|
||||
import static codechicken.lib.inventory.InventoryUtils.newItemStack;
|
||||
import static net.minecraftforge.oredict.OreDictionary.WILDCARD_VALUE;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* A maplike class for ItemStack keys with wildcard damage/NBT. Optimised for lookup
|
||||
*/
|
||||
public class ItemStackMap<T> {
|
||||
|
||||
public static class StackMetaKey {
|
||||
|
||||
public final int damage;
|
||||
public final NBTTagCompound tag;
|
||||
private final int hashCode;
|
||||
|
||||
public StackMetaKey(int damage, NBTTagCompound tag) {
|
||||
if (tag != null && tag.hasNoTags()) {
|
||||
tag = null;
|
||||
}
|
||||
this.hashCode = Objects.hashCode(damage, tag);
|
||||
this.damage = damage;
|
||||
this.tag = tag;
|
||||
}
|
||||
@@ -31,7 +42,7 @@ public class ItemStackMap<T> {
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(damage, tag);
|
||||
return this.hashCode;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
@@ -42,6 +53,7 @@ public class ItemStackMap<T> {
|
||||
}
|
||||
|
||||
public static class Entry<T> {
|
||||
|
||||
public final ItemStack key;
|
||||
public final T value;
|
||||
|
||||
@@ -52,6 +64,7 @@ public class ItemStackMap<T> {
|
||||
}
|
||||
|
||||
public class DetailMap {
|
||||
|
||||
private boolean hasWildcard;
|
||||
private T wildcard;
|
||||
private HashMap<Integer, T> damageMap;
|
||||
@@ -121,8 +134,7 @@ public class ItemStackMap<T> {
|
||||
}
|
||||
|
||||
private void updateSize() {
|
||||
int newSize = (hasWildcard ? 1 : 0)
|
||||
+ (metaMap != null ? metaMap.size() : 0)
|
||||
int newSize = (hasWildcard ? 1 : 0) + (metaMap != null ? metaMap.size() : 0)
|
||||
+ (tagMap != null ? tagMap.size() : 0)
|
||||
+ (damageMap != null ? damageMap.size() : 0);
|
||||
|
||||
@@ -151,16 +163,12 @@ public class ItemStackMap<T> {
|
||||
|
||||
public void addEntries(Item item, List<Entry<T>> list) {
|
||||
if (wildcard != null) list.add(new Entry<>(newItemStack(item, 1, WILDCARD_VALUE, WILDCARD_TAG), wildcard));
|
||||
if (damageMap != null)
|
||||
for (Map.Entry<Integer, T> entry : damageMap.entrySet())
|
||||
list.add(new Entry<>(newItemStack(item, 1, entry.getKey(), WILDCARD_TAG), entry.getValue()));
|
||||
if (tagMap != null)
|
||||
for (Map.Entry<NBTTagCompound, T> entry : tagMap.entrySet())
|
||||
list.add(new Entry<>(newItemStack(item, 1, WILDCARD_VALUE, entry.getKey()), entry.getValue()));
|
||||
if (metaMap != null)
|
||||
for (Map.Entry<StackMetaKey, T> entry : metaMap.entrySet())
|
||||
list.add(new Entry<>(
|
||||
newItemStack(item, 1, entry.getKey().damage, entry.getKey().tag), entry.getValue()));
|
||||
if (damageMap != null) for (Map.Entry<Integer, T> entry : damageMap.entrySet())
|
||||
list.add(new Entry<>(newItemStack(item, 1, entry.getKey(), WILDCARD_TAG), entry.getValue()));
|
||||
if (tagMap != null) for (Map.Entry<NBTTagCompound, T> entry : tagMap.entrySet())
|
||||
list.add(new Entry<>(newItemStack(item, 1, WILDCARD_VALUE, entry.getKey()), entry.getValue()));
|
||||
if (metaMap != null) for (Map.Entry<StackMetaKey, T> entry : metaMap.entrySet()) list.add(
|
||||
new Entry<>(newItemStack(item, 1, entry.getKey().damage, entry.getKey().tag), entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +198,7 @@ public class ItemStackMap<T> {
|
||||
WILDCARD_TAG.setBoolean("*", true);
|
||||
}
|
||||
|
||||
private final HashMap<Item, DetailMap> itemMap = new HashMap<>();
|
||||
private final Map<Item, DetailMap> itemMap = new LinkedHashMap<>();
|
||||
private int size;
|
||||
|
||||
public T get(ItemStack key) {
|
||||
@@ -202,6 +210,11 @@ public class ItemStackMap<T> {
|
||||
return map == null ? null : map.get(key);
|
||||
}
|
||||
|
||||
public T getOrDefault(ItemStack key, T defaultValue) {
|
||||
T e = get(key);
|
||||
return e == null ? defaultValue : e;
|
||||
}
|
||||
|
||||
public void put(ItemStack key, T value) {
|
||||
if (key == null || key.getItem() == null) return;
|
||||
|
||||
@@ -210,8 +223,22 @@ public class ItemStackMap<T> {
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
public T computeIfAbsent(ItemStack key, Function<ItemStack, ? extends T> mappingFunction) {
|
||||
T value;
|
||||
if ((value = get(key)) == null) {
|
||||
T newValue;
|
||||
if ((newValue = mappingFunction.apply(key)) != null) {
|
||||
put(key, newValue);
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
itemMap.clear();
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public T remove(ItemStack key) {
|
||||
@@ -223,8 +250,7 @@ public class ItemStackMap<T> {
|
||||
|
||||
public List<ItemStack> keys() {
|
||||
LinkedList<ItemStack> list = new LinkedList<>();
|
||||
for (Map.Entry<Item, DetailMap> entry : itemMap.entrySet())
|
||||
entry.getValue().addKeys(entry.getKey(), list);
|
||||
for (Map.Entry<Item, DetailMap> entry : itemMap.entrySet()) entry.getValue().addKeys(entry.getKey(), list);
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -236,8 +262,7 @@ public class ItemStackMap<T> {
|
||||
|
||||
public List<Entry<T>> entries() {
|
||||
LinkedList<Entry<T>> list = new LinkedList<>();
|
||||
for (Map.Entry<Item, DetailMap> entry : itemMap.entrySet())
|
||||
entry.getValue().addEntries(entry.getKey(), list);
|
||||
for (Map.Entry<Item, DetailMap> entry : itemMap.entrySet()) entry.getValue().addEntries(entry.getKey(), list);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
|
||||
public class ItemStackSet extends ItemStackMap<ItemStack> implements ItemFilter {
|
||||
|
||||
public ItemStackSet with(ItemStack... items) {
|
||||
for (ItemStack item : items) add(item);
|
||||
return this;
|
||||
@@ -25,6 +27,16 @@ public class ItemStackSet extends ItemStackMap<ItemStack> implements ItemFilter
|
||||
put(item, item);
|
||||
}
|
||||
|
||||
public ItemStackSet addAll(Iterable<ItemStack> items) {
|
||||
for (ItemStack item : items) add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemStackSet removeAll(Iterable<ItemStack> items) {
|
||||
for (ItemStack item : items) remove(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean contains(ItemStack item) {
|
||||
return get(item) != null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class ItemZoom extends Widget implements IContainerInputHandler {
|
||||
|
||||
public static final int MIN_ZOOM = 0;
|
||||
public static final int MAX_ZOOM = 1000;
|
||||
|
||||
private static final int MIN_SCALE = 2;
|
||||
private static final int SLOT_SIZE = 16;
|
||||
|
||||
private Boolean previousKeyboardRepeatEnabled = null;
|
||||
|
||||
private ItemStack stack = null;
|
||||
private String displayName = "";
|
||||
private int availableAreaWidth = 0;
|
||||
private float xPosition = 0;
|
||||
private float yPosition = 0;
|
||||
private float scale = 1;
|
||||
|
||||
public ItemZoom() {
|
||||
GuiContainerManager.addInputHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mx, int my) {
|
||||
|
||||
if (this.stack != null
|
||||
&& (NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled")
|
||||
|| NEIClientConfig.isKeyHashDown("gui.itemzoom_hold"))
|
||||
&& GuiContainerManager.shouldShowTooltip(NEIClientUtils.getGuiContainer())) {
|
||||
final float inverseScaleFactor = 1.0f / this.scale;
|
||||
final float screenScale = getScreenScale();
|
||||
final float size = SLOT_SIZE * this.scale;
|
||||
int shiftText = 10;
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glScaled(screenScale, screenScale, 1);
|
||||
GL11.glScaled(this.scale, this.scale, 2);
|
||||
GL11.glTranslated(this.xPosition * inverseScaleFactor, this.yPosition * inverseScaleFactor, 0);
|
||||
|
||||
GuiContainerManager.drawItem(0, 0, this.stack, false, "");
|
||||
|
||||
GL11.glPopMatrix();
|
||||
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GuiContainerManager.enable2DRender();
|
||||
|
||||
if (NEIClientConfig.getBooleanSetting("inventory.itemzoom.showName")) {
|
||||
String dispalyName = NEIClientUtils
|
||||
.cropText(GuiDraw.fontRenderer, this.displayName, this.availableAreaWidth);
|
||||
GuiDraw.drawStringC(
|
||||
dispalyName,
|
||||
(int) ((this.xPosition + size / 2) * screenScale),
|
||||
(int) ((this.yPosition + size) * screenScale) + shiftText,
|
||||
NEIClientConfig.getSetting("inventory.itemzoom.nameColor").getHexValue());
|
||||
shiftText += GuiDraw.fontRenderer.FONT_HEIGHT;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled")
|
||||
&& NEIClientConfig.getBooleanSetting("inventory.itemzoom.helpText")) {
|
||||
String keyName = NEIClientConfig.getKeyName("gui.itemzoom_toggle");
|
||||
|
||||
if (keyName != null) {
|
||||
String helpText = NEIClientUtils.translate("itemzoom.toggle", keyName);
|
||||
List<String> lines = GuiDraw.fontRenderer
|
||||
.listFormattedStringToWidth(helpText, this.availableAreaWidth);
|
||||
|
||||
for (String line : lines) {
|
||||
GuiDraw.drawStringC(
|
||||
line,
|
||||
(int) ((this.xPosition + size / 2) * screenScale),
|
||||
(int) ((this.yPosition + size) * screenScale) + 10 + shiftText,
|
||||
0x66555555);
|
||||
shiftText += GuiDraw.fontRenderer.FONT_HEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
}
|
||||
|
||||
public void resize(GuiContainer gui) {
|
||||
final ItemStack stack = getStackMouseOver(gui);
|
||||
|
||||
if (stack != null && (!NEIClientConfig.getBooleanSetting("inventory.itemzoom.onlySolid")
|
||||
|| Block.getBlockFromItem(stack.getItem()).getMaterial().isSolid())) {
|
||||
final float screenScale = 1.0f / getScreenScale();
|
||||
final float availableAreaWidth = (gui.width - gui.xSize) / 2 * screenScale;
|
||||
final float availableAreaHeight = gui.height * screenScale;
|
||||
final Point mouse = GuiDraw.getMousePosition();
|
||||
|
||||
this.scale = Math.round(getZoomAmount(gui) * getPointSize(gui) / SLOT_SIZE);
|
||||
this.yPosition = (availableAreaHeight - this.scale * SLOT_SIZE) / 2;
|
||||
this.xPosition = (availableAreaWidth - this.scale * SLOT_SIZE) / 2;
|
||||
this.availableAreaWidth = (int) (availableAreaWidth / screenScale);
|
||||
|
||||
if (availableAreaWidth / screenScale >= mouse.x) {
|
||||
this.xPosition += gui.width * screenScale - availableAreaWidth;
|
||||
}
|
||||
|
||||
try {
|
||||
this.displayName = stack.getDisplayName();
|
||||
} catch (Throwable ignored) {
|
||||
this.displayName = "Unnamed";
|
||||
}
|
||||
|
||||
this.stack = StackInfo.loadFromNBT(StackInfo.itemStackToNBT(stack), 0);
|
||||
} else {
|
||||
this.stack = null;
|
||||
this.displayName = "";
|
||||
}
|
||||
}
|
||||
|
||||
private float getPointSize(GuiContainer gui) {
|
||||
final float screenScale = 1.0f / getScreenScale();
|
||||
final float availableAreaWidth = (gui.width - (gui.xSize + gui.width) / 2) * screenScale;
|
||||
return availableAreaWidth / MAX_ZOOM;
|
||||
}
|
||||
|
||||
private float getScreenScale() {
|
||||
return Minecraft.getMinecraft().currentScreen.width * 1f / Minecraft.getMinecraft().displayWidth;
|
||||
}
|
||||
|
||||
private int getZoomAmount(GuiContainer gui) {
|
||||
return Math.max(
|
||||
Math.round(SLOT_SIZE * MIN_SCALE / getPointSize(gui)),
|
||||
NEIClientConfig.getIntSetting("inventory.itemzoom.zoom"));
|
||||
}
|
||||
|
||||
private void increaseZoom(GuiContainer gui) {
|
||||
final float pointSize = getPointSize(gui);
|
||||
final float scale = Math.round(getZoomAmount(gui) * pointSize / SLOT_SIZE);
|
||||
|
||||
NEIClientConfig.setIntSetting(
|
||||
"inventory.itemzoom.zoom",
|
||||
Math.min(MAX_ZOOM, Math.round((scale + 1) / (pointSize / SLOT_SIZE))));
|
||||
}
|
||||
|
||||
private void decreaseZoom(GuiContainer gui) {
|
||||
final float pointSize = getPointSize(gui);
|
||||
final float scale = Math.round(getZoomAmount(gui) * pointSize / SLOT_SIZE);
|
||||
|
||||
NEIClientConfig.setIntSetting(
|
||||
"inventory.itemzoom.zoom",
|
||||
Math.max(MIN_ZOOM, Math.round(Math.max(MIN_SCALE, scale - 1) / (pointSize / SLOT_SIZE))));
|
||||
}
|
||||
|
||||
private ItemStack getStackMouseOver(GuiContainer gui) {
|
||||
|
||||
if (NEIClientConfig.getBooleanSetting("inventory.itemzoom.neiOnly")) {
|
||||
final Point mouse = GuiDraw.getMousePosition();
|
||||
ItemStack stack = ItemPanels.itemPanel.getStackMouseOver(mouse.x, mouse.y);
|
||||
|
||||
if (stack == null) {
|
||||
stack = ItemPanels.bookmarkPanel.getStackMouseOver(mouse.x, mouse.y);
|
||||
}
|
||||
|
||||
if (stack == null) {
|
||||
stack = ItemPanels.itemPanel.historyPanel.getStackMouseOver(mouse.x, mouse.y);
|
||||
}
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
return GuiContainerManager.getStackMouseOver(gui);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) {}
|
||||
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.itemzoom_toggle")) {
|
||||
NEIClientConfig.getSetting("inventory.itemzoom.enabled")
|
||||
.setBooleanValue(!NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_hold")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_zoom_in")) {
|
||||
increaseZoom(gui);
|
||||
previousKeyboardRepeatEnabled = Keyboard.areRepeatEventsEnabled();
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_zoom_out")) {
|
||||
decreaseZoom(gui);
|
||||
previousKeyboardRepeatEnabled = Keyboard.areRepeatEventsEnabled();
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (previousKeyboardRepeatEnabled != null) {
|
||||
Keyboard.enableRepeatEvents(previousKeyboardRepeatEnabled);
|
||||
previousKeyboardRepeatEnabled = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {}
|
||||
|
||||
@Override
|
||||
public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) {}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {}
|
||||
|
||||
@Override
|
||||
public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) {}
|
||||
|
||||
}
|
||||
@@ -2,15 +2,12 @@ package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
@@ -18,9 +15,131 @@ import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.shader.Framebuffer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class ItemsGrid {
|
||||
|
||||
private static class ScreenCapture {
|
||||
|
||||
private long nextCacheRefresh = 0;
|
||||
private Framebuffer framebuffer;
|
||||
|
||||
public ScreenCapture() {
|
||||
this.framebuffer = new Framebuffer(1, 1, true);
|
||||
this.framebuffer.setFramebufferColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
|
||||
}
|
||||
|
||||
protected int getGridRenderingCacheFPS(int mode) {
|
||||
return mode == 1 ? NEIClientConfig.getIntSetting("inventory.gridRenderingCacheFPS") : 0;
|
||||
}
|
||||
|
||||
public boolean needRefresh(int mode) {
|
||||
final Minecraft minecraft = Minecraft.getMinecraft();
|
||||
return this.nextCacheRefresh == 0 || this.framebuffer.framebufferWidth != minecraft.displayWidth
|
||||
|| framebuffer.framebufferHeight != minecraft.displayHeight
|
||||
|| getGridRenderingCacheFPS(mode) > 0 && this.nextCacheRefresh < System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void refreshBuffer() {
|
||||
this.nextCacheRefresh = 0;
|
||||
}
|
||||
|
||||
public void captureScreen(Runnable callback, int mode) {
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
|
||||
resetFramebuffer();
|
||||
this.framebuffer.bindFramebuffer(false);
|
||||
|
||||
/* Set up some rendering state needed for items to work correctly */
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glDepthMask(true);
|
||||
OpenGlHelper.glBlendFunc(
|
||||
GL11.GL_SRC_ALPHA,
|
||||
GL11.GL_ONE_MINUS_SRC_ALPHA,
|
||||
GL11.GL_SRC_ALPHA,
|
||||
GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
||||
callback.run();
|
||||
|
||||
GL11.glPopAttrib();
|
||||
|
||||
Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
|
||||
this.nextCacheRefresh = System.currentTimeMillis() + (1000 / Math.max(1, getGridRenderingCacheFPS(mode)));
|
||||
}
|
||||
|
||||
private void resetFramebuffer() {
|
||||
final Minecraft minecraft = Minecraft.getMinecraft();
|
||||
|
||||
if (this.framebuffer.framebufferWidth != minecraft.displayWidth
|
||||
|| framebuffer.framebufferHeight != minecraft.displayHeight) {
|
||||
this.framebuffer.createBindFramebuffer(minecraft.displayWidth, minecraft.displayHeight);
|
||||
this.framebuffer.setFramebufferFilter(GL11.GL_NEAREST);
|
||||
} else {
|
||||
this.framebuffer.framebufferClear();
|
||||
}
|
||||
|
||||
// copy depth buffer from MC (fix Angelica)
|
||||
OpenGlHelper.func_153171_g(GL30.GL_READ_FRAMEBUFFER, minecraft.getFramebuffer().framebufferObject);
|
||||
OpenGlHelper.func_153171_g(GL30.GL_DRAW_FRAMEBUFFER, this.framebuffer.framebufferObject);
|
||||
GL30.glBlitFramebuffer(
|
||||
0,
|
||||
0,
|
||||
minecraft.displayWidth,
|
||||
minecraft.displayHeight,
|
||||
0,
|
||||
0,
|
||||
minecraft.displayWidth,
|
||||
minecraft.displayHeight,
|
||||
GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT,
|
||||
GL11.GL_NEAREST);
|
||||
}
|
||||
|
||||
public void renderCapturedScreen() {
|
||||
this.framebuffer.bindFramebufferTexture();
|
||||
|
||||
final Tessellator tessellator = Tessellator.instance;
|
||||
final Minecraft minecraft = Minecraft.getMinecraft();
|
||||
final ScaledResolution scaledresolution = new ScaledResolution(
|
||||
minecraft,
|
||||
minecraft.displayWidth,
|
||||
minecraft.displayHeight);
|
||||
|
||||
/* Set up some rendering state needed for items to work correctly */
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
OpenGlHelper
|
||||
.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
|
||||
tessellator.startDrawingQuads();
|
||||
|
||||
tessellator.addVertexWithUV(0, scaledresolution.getScaledHeight_double(), 0.0, 0, 0);
|
||||
tessellator.addVertexWithUV(
|
||||
scaledresolution.getScaledWidth_double(),
|
||||
scaledresolution.getScaledHeight_double(),
|
||||
0.0,
|
||||
1,
|
||||
0);
|
||||
tessellator.addVertexWithUV(scaledresolution.getScaledWidth_double(), 0, 0.0, 1, 1);
|
||||
tessellator.addVertexWithUV(0, 0, 0, 0, 1);
|
||||
|
||||
tessellator.draw();
|
||||
|
||||
this.framebuffer.unbindFramebufferTexture();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final int SLOT_SIZE = 18;
|
||||
|
||||
protected int width;
|
||||
@@ -38,13 +157,13 @@ public class ItemsGrid {
|
||||
|
||||
protected int rows;
|
||||
protected int columns;
|
||||
protected List<Integer> gridMask = null;
|
||||
|
||||
protected boolean[] invalidSlotMap;
|
||||
|
||||
@Nullable
|
||||
private Framebuffer framebuffer = null;
|
||||
protected Label messageLabel = new Label(getMessageOnEmpty(), true);
|
||||
|
||||
protected boolean refreshBuffer = true;
|
||||
protected ScreenCapture screenCapture = null;
|
||||
|
||||
public ArrayList<ItemStack> getItems() {
|
||||
return realItems;
|
||||
@@ -58,6 +177,10 @@ public class ItemsGrid {
|
||||
return realItems.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return realItems.isEmpty();
|
||||
}
|
||||
|
||||
public int indexOf(ItemStack stackA, boolean useNBT) {
|
||||
|
||||
for (int idx = 0; idx < realItems.size(); idx++) {
|
||||
@@ -69,6 +192,11 @@ public class ItemsGrid {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void setPage(int page) {
|
||||
this.page = Math.max(0, Math.min(page, getNumPages() - 1));
|
||||
onGridChanged();
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return page + 1;
|
||||
}
|
||||
@@ -93,6 +221,10 @@ public class ItemsGrid {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public int getLastRowIndex() {
|
||||
return this.columns > 0 ? (int) Math.ceil((float) this.getMask().size() / this.columns) - 1 : 0;
|
||||
}
|
||||
|
||||
public void setGridSize(int mleft, int mtop, int w, int h) {
|
||||
marginLeft = mleft;
|
||||
marginTop = mtop;
|
||||
@@ -104,6 +236,9 @@ public class ItemsGrid {
|
||||
rows = height / SLOT_SIZE;
|
||||
|
||||
paddingLeft = (width % SLOT_SIZE) / 2;
|
||||
|
||||
messageLabel.x = marginLeft + width / 2;
|
||||
messageLabel.y = marginTop + height / 2;
|
||||
}
|
||||
|
||||
public void shiftPage(int shift) {
|
||||
@@ -132,7 +267,14 @@ public class ItemsGrid {
|
||||
}
|
||||
|
||||
protected void onGridChanged() {
|
||||
refreshBuffer = true;
|
||||
if (this.screenCapture != null) {
|
||||
this.screenCapture.refreshBuffer();
|
||||
}
|
||||
this.gridMask = null;
|
||||
}
|
||||
|
||||
protected void onItemsChanged() {
|
||||
onGridChanged();
|
||||
}
|
||||
|
||||
public void refresh(GuiContainer gui) {
|
||||
@@ -148,8 +290,14 @@ public class ItemsGrid {
|
||||
invalidSlotMap = new boolean[rows * columns];
|
||||
perPage = columns * rows;
|
||||
|
||||
checkGuiOverlap(gui, 0, columns - 2, 1);
|
||||
checkGuiOverlap(gui, columns - 1, 1, -1);
|
||||
if (gui != null) {
|
||||
if (NEIClientConfig.optimizeGuiOverlapComputation()) {
|
||||
checkGuiOverlap(gui, 0, columns - 2, 1);
|
||||
checkGuiOverlap(gui, columns - 1, 1, -1);
|
||||
} else {
|
||||
checkGuiOverlap(gui, 0, columns, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (oldRows != rows || oldColumns != columns || !Arrays.equals(oldSlotMap, invalidSlotMap)) {
|
||||
onGridChanged();
|
||||
@@ -159,15 +307,14 @@ public class ItemsGrid {
|
||||
private void checkGuiOverlap(GuiContainer gui, int start, int end, int dir) {
|
||||
boolean validColumn = false;
|
||||
|
||||
for (int c = start; c != end && !validColumn; c += dir) {
|
||||
for (int c = start; c != end && (!NEIClientConfig.optimizeGuiOverlapComputation() || !validColumn); c += dir) {
|
||||
validColumn = true;
|
||||
|
||||
for (int r = 0; r < rows; r++) {
|
||||
final int idx = columns * r + c;
|
||||
if (GuiInfo.hideItemPanelSlot(gui, getSlotRect(r, c))
|
||||
&& idx >= 0
|
||||
&& idx < invalidSlotMap.length
|
||||
&& !invalidSlotMap[idx]) {
|
||||
if (idx >= 0 && idx < invalidSlotMap.length
|
||||
&& !invalidSlotMap[idx]
|
||||
&& GuiInfo.hideItemPanelSlot(gui, getSlotRect(r, c))) {
|
||||
invalidSlotMap[idx] = true;
|
||||
validColumn = false;
|
||||
perPage--;
|
||||
@@ -194,7 +341,10 @@ public class ItemsGrid {
|
||||
|
||||
public Rectangle4i getSlotRect(int row, int column) {
|
||||
return new Rectangle4i(
|
||||
marginLeft + paddingLeft + column * SLOT_SIZE, marginTop + row * SLOT_SIZE, SLOT_SIZE, SLOT_SIZE);
|
||||
marginLeft + paddingLeft + column * SLOT_SIZE,
|
||||
marginTop + row * SLOT_SIZE,
|
||||
SLOT_SIZE,
|
||||
SLOT_SIZE);
|
||||
}
|
||||
|
||||
public boolean isInvalidSlot(int index) {
|
||||
@@ -202,60 +352,50 @@ public class ItemsGrid {
|
||||
}
|
||||
|
||||
protected List<Integer> getMask() {
|
||||
List<Integer> mask = new ArrayList<>();
|
||||
|
||||
int idx = page * perPage;
|
||||
for (int i = 0; i < rows * columns && idx < size(); i++) {
|
||||
mask.add(isInvalidSlot(i) ? null : idx++);
|
||||
if (this.gridMask == null) {
|
||||
this.gridMask = new ArrayList<>();
|
||||
int idx = page * perPage;
|
||||
|
||||
for (int i = 0; i < rows * columns && idx < size(); i++) {
|
||||
this.gridMask.add(isInvalidSlot(i) ? null : idx++);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return mask;
|
||||
return this.gridMask;
|
||||
}
|
||||
|
||||
private void drawSlotOutlines(int mousex, int mousey) {
|
||||
ItemPanelSlot focused = getSlotMouseOver(mousex, mousey);
|
||||
protected void beforeDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
|
||||
final List<Integer> mask = getMask();
|
||||
|
||||
for (int i = 0; i < mask.size(); i++) {
|
||||
if (mask.get(i) != null) {
|
||||
drawSlotOutline(focused, mask.get(i), getSlotRect(i));
|
||||
beforeDrawSlot(focused, mask.get(i), getSlotRect(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawSlotOutline(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
protected void afterDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
final List<Integer> mask = getMask();
|
||||
|
||||
for (int i = 0; i < mask.size(); i++) {
|
||||
if (mask.get(i) != null) {
|
||||
afterDrawSlot(focused, mask.get(i), getSlotRect(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {}
|
||||
|
||||
protected void beforeDrawSlot(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
if (focused != null && focused.slotIndex == slotIdx) {
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555); // highlight
|
||||
}
|
||||
}
|
||||
|
||||
private void blitExistingBuffer() {
|
||||
Minecraft minecraft = Minecraft.getMinecraft();
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
getFrameBuffer().bindFramebufferTexture();
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
ScaledResolution res = new ScaledResolution(minecraft, minecraft.displayWidth, minecraft.displayHeight);
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.addVertexWithUV(0, res.getScaledHeight_double(), 0.0, 0, 0);
|
||||
tessellator.addVertexWithUV(res.getScaledWidth_double(), res.getScaledHeight_double(), 0.0, 1, 0);
|
||||
tessellator.addVertexWithUV(res.getScaledWidth_double(), 0, 0.0, 1, 1);
|
||||
tessellator.addVertexWithUV(0, 0, 0, 0, 1);
|
||||
tessellator.draw();
|
||||
OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
}
|
||||
|
||||
private Framebuffer getFrameBuffer() {
|
||||
|
||||
if (framebuffer == null) {
|
||||
framebuffer = new Framebuffer(1, 1, true);
|
||||
framebuffer.setFramebufferColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
}
|
||||
|
||||
return framebuffer;
|
||||
}
|
||||
protected void afterDrawSlot(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {}
|
||||
|
||||
private void drawItems() {
|
||||
GuiContainerManager.enableMatrixStackLogging();
|
||||
@@ -270,39 +410,42 @@ public class ItemsGrid {
|
||||
GuiContainerManager.disableMatrixStackLogging();
|
||||
}
|
||||
|
||||
protected int getGridRenderingCacheMode() {
|
||||
return NEIClientConfig.getGridRenderingCacheMode();
|
||||
}
|
||||
|
||||
public void draw(int mousex, int mousey) {
|
||||
if (getPerPage() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.shouldCacheItemRendering()) {
|
||||
final ItemPanelSlot focused = getSlotMouseOver(mousex, mousey);
|
||||
final int gridRenderingCacheMode = getGridRenderingCacheMode();
|
||||
|
||||
if (refreshBuffer) {
|
||||
Minecraft minecraft = Minecraft.getMinecraft();
|
||||
Framebuffer framebuffer = getFrameBuffer();
|
||||
framebuffer.createBindFramebuffer(minecraft.displayWidth, minecraft.displayHeight);
|
||||
framebuffer.framebufferClear();
|
||||
framebuffer.bindFramebuffer(false);
|
||||
beforeDrawItems(mousex, mousey, focused);
|
||||
|
||||
/* Set up some rendering state needed for items to work correctly */
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glDepthMask(true);
|
||||
OpenGlHelper.glBlendFunc(
|
||||
GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
if (gridRenderingCacheMode > 0) {
|
||||
|
||||
drawItems();
|
||||
|
||||
Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
|
||||
refreshBuffer = false;
|
||||
if (this.screenCapture == null) {
|
||||
this.screenCapture = new ScreenCapture();
|
||||
}
|
||||
|
||||
drawSlotOutlines(mousex, mousey);
|
||||
blitExistingBuffer();
|
||||
if (this.screenCapture.needRefresh(gridRenderingCacheMode)) {
|
||||
this.screenCapture.captureScreen(this::drawItems, gridRenderingCacheMode);
|
||||
}
|
||||
|
||||
this.screenCapture.renderCapturedScreen();
|
||||
} else {
|
||||
drawSlotOutlines(mousex, mousey);
|
||||
drawItems();
|
||||
}
|
||||
|
||||
afterDrawItems(mousex, mousey, focused);
|
||||
}
|
||||
|
||||
public void setVisible() {
|
||||
if (getItems().isEmpty() && getMessageOnEmpty() != null) {
|
||||
LayoutManager.addWidget(messageLabel);
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawItem(Rectangle4i rect, int idx) {
|
||||
@@ -314,8 +457,8 @@ public class ItemsGrid {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int overRow = (int) ((mousey - marginTop) / SLOT_SIZE);
|
||||
final int overColumn = (int) ((mousex - marginLeft - paddingLeft) / SLOT_SIZE);
|
||||
final int overRow = (mousey - marginTop) / SLOT_SIZE;
|
||||
final int overColumn = (mousex - marginLeft - paddingLeft) / SLOT_SIZE;
|
||||
final int slt = columns * overRow + overColumn;
|
||||
|
||||
if (overRow >= rows || overColumn >= columns) {
|
||||
@@ -334,15 +477,23 @@ public class ItemsGrid {
|
||||
}
|
||||
|
||||
public boolean contains(int px, int py) {
|
||||
final Rectangle4i rect = new Rectangle4i(
|
||||
marginLeft + paddingLeft,
|
||||
marginTop,
|
||||
columns * SLOT_SIZE,
|
||||
rows * SLOT_SIZE);
|
||||
|
||||
if (!(new Rectangle4i(marginLeft + paddingLeft, marginTop, columns * SLOT_SIZE, height)).contains(px, py)) {
|
||||
if (!rect.contains(px, py)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int r = (int) ((py - marginTop) / SLOT_SIZE);
|
||||
final int c = (int) ((px - marginLeft - paddingLeft) / SLOT_SIZE);
|
||||
final int slt = columns * r + c;
|
||||
final int r = (py - marginTop) / SLOT_SIZE;
|
||||
final int c = (px - marginLeft - paddingLeft) / SLOT_SIZE;
|
||||
|
||||
return r >= rows || c >= columns || !isInvalidSlot(slt);
|
||||
return !isInvalidSlot(columns * r + c);
|
||||
}
|
||||
|
||||
public String getMessageOnEmpty() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.fontRenderer;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw.ITooltipLineHandler;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.ReadableNumberConverter;
|
||||
|
||||
public class ItemsTooltipLineHandler implements ITooltipLineHandler {
|
||||
|
||||
protected static final int MAX_COLUMNS = 11;
|
||||
protected static final int MARGIN_TOP = 2;
|
||||
|
||||
protected String label;
|
||||
protected EnumChatFormatting labelColor = EnumChatFormatting.GRAY;
|
||||
protected List<ItemStack> items;
|
||||
protected Dimension size = new Dimension();
|
||||
protected boolean saveStackSize = false;
|
||||
protected int columns = 0;
|
||||
protected int count = 0;
|
||||
protected int rows = 0;
|
||||
protected int length = 0;
|
||||
|
||||
public ItemsTooltipLineHandler(String label, List<ItemStack> items) {
|
||||
this(label, items, true, 5);
|
||||
}
|
||||
|
||||
public ItemsTooltipLineHandler(String label, List<ItemStack> items, boolean saveStackSize, int maxRows) {
|
||||
this.label = label;
|
||||
this.items = groupingItemStacks(items);
|
||||
this.saveStackSize = saveStackSize;
|
||||
this.length = this.items.size();
|
||||
|
||||
if (this.length > 0) {
|
||||
this.columns = Math.min(MAX_COLUMNS, this.length);
|
||||
this.rows = Math.min(maxRows, (int) Math.ceil((float) this.length / this.columns));
|
||||
|
||||
this.size.width = Math
|
||||
.max(this.columns * ItemsGrid.SLOT_SIZE, fontRenderer.getStringWidth(this.label) + 15);
|
||||
this.size.height = this.rows * ItemsGrid.SLOT_SIZE + fontRenderer.FONT_HEIGHT + 2 + MARGIN_TOP;
|
||||
|
||||
this.count = Math.min(
|
||||
this.length,
|
||||
Math.min(
|
||||
this.columns * this.rows,
|
||||
this.length > MAX_COLUMNS * maxRows ? (MAX_COLUMNS * maxRows) : Integer.MAX_VALUE));
|
||||
|
||||
if (this.items.size() > this.count) {
|
||||
String text = "+" + (this.items.size() - this.count);
|
||||
this.count -= (int) Math.ceil((float) (fontRenderer.getStringWidth(text) - 2) / ItemsGrid.SLOT_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.items.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
public void setLabelColor(EnumChatFormatting color) {
|
||||
this.labelColor = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int x, int y) {
|
||||
if (this.length == 0) return;
|
||||
|
||||
y += MARGIN_TOP;
|
||||
|
||||
fontRenderer.drawStringWithShadow(this.labelColor + this.label + ":", x, y, 0);
|
||||
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glPushMatrix();
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
|
||||
GL11.glScaled(1, 1, 3);
|
||||
GL11.glTranslatef(x, y + fontRenderer.FONT_HEIGHT + 2, 0);
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
for (int i = 0; i < this.count; i++) {
|
||||
ItemStack drawStack = this.items.get(i);
|
||||
int col = i % this.columns;
|
||||
int row = i / this.columns;
|
||||
|
||||
String stackSize = !this.saveStackSize || drawStack.stackSize == 0 ? ""
|
||||
: ReadableNumberConverter.INSTANCE.toWideReadableForm(drawStack.stackSize);
|
||||
|
||||
drawItem(col * ItemsGrid.SLOT_SIZE, row * ItemsGrid.SLOT_SIZE, drawStack, stackSize);
|
||||
}
|
||||
|
||||
if (this.count < this.items.size()) {
|
||||
String text = "+" + (this.items.size() - this.count);
|
||||
|
||||
fontRenderer.drawStringWithShadow(
|
||||
text,
|
||||
MAX_COLUMNS * ItemsGrid.SLOT_SIZE - fontRenderer.getStringWidth(text) - 2,
|
||||
(this.rows - 1) * ItemsGrid.SLOT_SIZE + (ItemsGrid.SLOT_SIZE - fontRenderer.FONT_HEIGHT) / 2,
|
||||
0xee555555);
|
||||
|
||||
}
|
||||
|
||||
GL11.glPopMatrix();
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
protected void drawItem(int x, int y, ItemStack drawStack, String stackSize) {
|
||||
GuiContainerManager.drawItem(x, y, drawStack, true, stackSize);
|
||||
}
|
||||
|
||||
private List<ItemStack> groupingItemStacks(List<ItemStack> items) {
|
||||
final List<ItemStack> result = ItemStackAmount.of(items).values();
|
||||
|
||||
for (ItemStack stack : result) {
|
||||
if (StackInfo.itemStackToNBT(stack).hasKey("gtFluidName")) {
|
||||
stack.stackSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,11 +8,14 @@ import java.util.Map.Entry;
|
||||
* Good old down/held/up keystate tracker
|
||||
*/
|
||||
public class KeyManager {
|
||||
|
||||
public static interface IKeyStateTracker {
|
||||
|
||||
public void tickKeyStates();
|
||||
}
|
||||
|
||||
public static class KeyState {
|
||||
|
||||
public boolean down;
|
||||
public boolean held;
|
||||
public boolean up;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
// Simple LRUCache
|
||||
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
|
||||
|
||||
private final int capacity;
|
||||
|
||||
public LRUCache(int capacity) {
|
||||
super(capacity, 0.75f, true);
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
|
||||
return size() > capacity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import static codechicken.lib.gui.GuiDraw.drawString;
|
||||
import static codechicken.lib.gui.GuiDraw.drawStringC;
|
||||
|
||||
public class Label extends Widget {
|
||||
|
||||
final boolean centered;
|
||||
final int colour;
|
||||
public String text;
|
||||
|
||||
@@ -14,7 +14,6 @@ import static codechicken.nei.NEIClientConfig.isEnabled;
|
||||
import static codechicken.nei.NEIClientConfig.isHidden;
|
||||
import static codechicken.nei.NEIClientConfig.showIDs;
|
||||
import static codechicken.nei.NEIClientConfig.toggleBooleanSetting;
|
||||
import static codechicken.nei.NEIClientConfig.world;
|
||||
import static codechicken.nei.NEIClientUtils.cycleGamemode;
|
||||
import static codechicken.nei.NEIClientUtils.decreaseSlotStack;
|
||||
import static codechicken.nei.NEIClientUtils.deleteEverything;
|
||||
@@ -32,6 +31,26 @@ import static codechicken.nei.NEIClientUtils.toggleMagnetMode;
|
||||
import static codechicken.nei.NEIClientUtils.toggleRaining;
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.gui.inventory.GuiContainerCreative;
|
||||
import net.minecraft.client.renderer.InventoryEffectRenderer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.KeyManager.IKeyStateTracker;
|
||||
import codechicken.nei.api.API;
|
||||
@@ -48,27 +67,10 @@ import codechicken.nei.guihook.IContainerObjectHandler;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.RecipeCatalysts;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.gui.inventory.GuiContainerCreative;
|
||||
import net.minecraft.client.renderer.InventoryEffectRenderer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class LayoutManager
|
||||
implements IContainerInputHandler,
|
||||
IContainerTooltipHandler,
|
||||
IContainerDrawHandler,
|
||||
IContainerObjectHandler,
|
||||
IKeyStateTracker {
|
||||
public class LayoutManager implements IContainerInputHandler, IContainerTooltipHandler, IContainerDrawHandler,
|
||||
IContainerObjectHandler, IKeyStateTracker {
|
||||
|
||||
private static LayoutManager instance;
|
||||
|
||||
/** Note: this variable isn't actually used by this mod, but NEI add-ons might need it. */
|
||||
@@ -77,28 +79,23 @@ public class LayoutManager
|
||||
/**
|
||||
* Sorted bottom first
|
||||
*/
|
||||
private static TreeSet<Widget> drawWidgets = new TreeSet<>(new WidgetZOrder(false));
|
||||
private static Set<Widget> drawWidgets = new TreeSet<>(new WidgetZOrder(false));
|
||||
/**
|
||||
* Sorted top first
|
||||
*/
|
||||
private static TreeSet<Widget> controlWidgets = new TreeSet<>(new WidgetZOrder(true));
|
||||
private static Set<Widget> controlWidgets = new TreeSet<>(new WidgetZOrder(true));
|
||||
|
||||
public static ItemPanel itemPanel;
|
||||
public static BookmarkPanel bookmarkPanel;
|
||||
public static SubsetWidget dropDown;
|
||||
public static PresetsWidget presetsPanel;
|
||||
public static SearchField searchField;
|
||||
public static ItemZoom itemZoom;
|
||||
|
||||
public static ButtonCycled options;
|
||||
public static ButtonCycled bookmarksButton;
|
||||
|
||||
@Deprecated
|
||||
public static Button more;
|
||||
|
||||
@Deprecated
|
||||
public static Button less;
|
||||
|
||||
@Deprecated
|
||||
public static ItemQuantityField quantity;
|
||||
|
||||
public static Button delete;
|
||||
@@ -112,6 +109,11 @@ public class LayoutManager
|
||||
|
||||
public static HashMap<Integer, LayoutStyle> layoutStyles = new HashMap<>();
|
||||
|
||||
/**
|
||||
* This is set to true immediately after item loading thread is started, to prevent duplicated loading thread from
|
||||
* being executed. If you want to know if item list is actually finished loading, Use {@link ItemList#loadFinished}
|
||||
* instead.
|
||||
*/
|
||||
public static boolean itemsLoaded = false;
|
||||
|
||||
/**
|
||||
@@ -133,19 +135,16 @@ public class LayoutManager
|
||||
|
||||
@Override
|
||||
public void onPreDraw(GuiContainer gui) {
|
||||
if (!isHidden()
|
||||
&& isEnabled()
|
||||
&& gui
|
||||
instanceof
|
||||
InventoryEffectRenderer) // Reset the gui to the center of the screen, for potion effect offsets
|
||||
if (!isHidden() && isEnabled() && gui instanceof InventoryEffectRenderer) // Reset the gui to the center of the
|
||||
// screen, for potion effect offsets
|
||||
// etc
|
||||
{
|
||||
gui.guiLeft = (gui.width - gui.xSize) / 2;
|
||||
gui.guiTop = (gui.height - gui.ySize) / 2;
|
||||
|
||||
if (gui instanceof GuiContainerCreative && gui.buttonList.size() >= 2) {
|
||||
GuiButton button1 = (GuiButton) gui.buttonList.get(0);
|
||||
GuiButton button2 = (GuiButton) gui.buttonList.get(1);
|
||||
GuiButton button1 = gui.buttonList.get(0);
|
||||
GuiButton button2 = gui.buttonList.get(1);
|
||||
button1.xPosition = gui.guiLeft;
|
||||
button2.xPosition = gui.guiLeft + gui.xSize - 20;
|
||||
}
|
||||
@@ -166,20 +165,24 @@ public class LayoutManager
|
||||
public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
if (isHidden()) return;
|
||||
|
||||
for (Widget widget : controlWidgets) widget.onGuiClick(mousex, mousey);
|
||||
for (Widget widget : controlWidgets) {
|
||||
widget.onGuiClick(mousex, mousey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) {
|
||||
if (isHidden()) return false;
|
||||
|
||||
if (!isEnabled()) return options.contains(mousex, mousey) && options.handleClick(mousex, mousey, button);
|
||||
if (!isEnabled()) {
|
||||
return options.contains(mousex, mousey) && options.handleClick(mousex, mousey, button);
|
||||
}
|
||||
|
||||
for (Widget widget : controlWidgets) {
|
||||
widget.onGuiClick(mousex, mousey);
|
||||
if (widget.contains(mousex, mousey)
|
||||
? widget.handleClick(mousex, mousey, button)
|
||||
: widget.handleClickExt(mousex, mousey, button)) return true;
|
||||
if (widget.contains(mousex, mousey) ? widget.handleClick(mousex, mousey, button)
|
||||
: widget.handleClickExt(mousex, mousey, button))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -187,10 +190,22 @@ public class LayoutManager
|
||||
|
||||
@Override
|
||||
public boolean objectUnderMouse(GuiContainer gui, int mousex, int mousey) {
|
||||
if (!isHidden() && isEnabled())
|
||||
for (Widget widget : drawWidgets) if (widget.contains(mousex, mousey)) return true;
|
||||
return getWidgetUnderMouse(mousex, mousey) != null;
|
||||
}
|
||||
|
||||
return false;
|
||||
public Widget getWidgetUnderMouse(int mousex, int mousey) {
|
||||
|
||||
if (isHidden() || !isEnabled()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Widget widget : controlWidgets) {
|
||||
if (widget.contains(mousex, mousey)) {
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
@@ -215,7 +230,12 @@ public class LayoutManager
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.hide_bookmarks")) {
|
||||
toggleBooleanSetting("inventory.bookmarksEnabled");
|
||||
toggleBooleanSetting("inventory.bookmarks.enabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.next_tooltip")) {
|
||||
GuiContainerManager.incrementTooltipPage();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -241,12 +261,12 @@ public class LayoutManager
|
||||
|
||||
@Override
|
||||
public ItemStack getStackUnderMouse(GuiContainer gui, int mousex, int mousey) {
|
||||
if (!isHidden() && isEnabled()) {
|
||||
for (Widget widget : drawWidgets) {
|
||||
ItemStack stack = widget.getStackMouseOver(mousex, mousey);
|
||||
if (stack != null) return stack;
|
||||
}
|
||||
final Widget focused = getWidgetUnderMouse(mousex, mousey);
|
||||
|
||||
if (focused != null) {
|
||||
return focused.getStackMouseOver(mousex, mousey);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -274,10 +294,33 @@ public class LayoutManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
public void postRenderTooltips(GuiContainer gui, int mousex, int mousey, List<String> tooltip) {
|
||||
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
for (Widget widget : drawWidgets) currenttip = widget.handleTooltip(mousex, mousey, currenttip);
|
||||
final Widget focused = getWidgetUnderMouse(mousex, mousey);
|
||||
|
||||
if (focused != null) {
|
||||
focused.postDrawTooltips(mousex, mousey, tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
final Widget focused = getWidgetUnderMouse(mousex, mousey);
|
||||
|
||||
if (focused != null) {
|
||||
currenttip = focused.handleTooltip(mousex, mousey, currenttip);
|
||||
|
||||
if (focused instanceof IContainerTooltipHandler tip) {
|
||||
currenttip = tip.handleTooltip(gui, mousex, mousey, currenttip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@@ -294,29 +337,55 @@ public class LayoutManager
|
||||
currenttip.set(0, mainname);
|
||||
}
|
||||
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
final Point mouse = GuiDraw.getMousePosition();
|
||||
final Widget focused = getWidgetUnderMouse(mouse.x, mouse.y);
|
||||
|
||||
if (focused instanceof IContainerTooltipHandler tip) {
|
||||
currenttip = tip.handleItemDisplayName(gui, stack, currenttip);
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(
|
||||
GuiContainer gui, ItemStack itemstack, int mousex, int mousey, List<String> currenttip) {
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
final Widget focused = getWidgetUnderMouse(mousex, mousey);
|
||||
|
||||
if (focused instanceof IContainerTooltipHandler tip) {
|
||||
currenttip = tip.handleItemTooltip(gui, itemstack, mousex, mousey, currenttip);
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> handleHotkeys(GuiContainer gui, int mousex, int mousey, Map<String, String> hotkeys) {
|
||||
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
final Widget focused = getWidgetUnderMouse(mousex, mousey);
|
||||
|
||||
if (focused instanceof IContainerTooltipHandler tip) {
|
||||
hotkeys = tip.handleHotkeys(gui, mousex, mousey, hotkeys);
|
||||
}
|
||||
}
|
||||
|
||||
return hotkeys;
|
||||
}
|
||||
|
||||
public static void layout(GuiContainer gui) {
|
||||
VisiblityData visiblity = new VisiblityData();
|
||||
|
||||
if (isHidden()) visiblity.showNEI = false;
|
||||
|
||||
if (isBookmarkPanelHidden()) visiblity.showBookmarkPanel = false;
|
||||
|
||||
if (gui.height - gui.ySize <= 40) visiblity.showSearchSection = false;
|
||||
|
||||
if (visiblity.showBookmarkPanel || gui.guiTop <= 20) visiblity.showSubsetDropdown = false;
|
||||
|
||||
if (!visiblity.showBookmarkPanel || gui.guiTop <= 20) visiblity.showPresetsDropdown = false;
|
||||
|
||||
if (gui.guiLeft - 4 < 76) visiblity.showWidgets = false;
|
||||
visiblity.showNEI = !isHidden();
|
||||
visiblity.showBookmarkPanel = !isBookmarkPanelHidden();
|
||||
visiblity.showSearchSection = !(gui.height - gui.ySize <= 40 && NEIClientConfig.isSearchWidgetCentered());
|
||||
visiblity.showSubsetDropdown = NEIClientConfig.showSubsetWidget()
|
||||
&& (gui.guiTop > 20 || visiblity.showSearchSection && !NEIClientConfig.subsetWidgetOnTop());
|
||||
visiblity.showWidgets = gui.guiLeft - 4 > 76;
|
||||
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
@@ -339,11 +408,14 @@ public class LayoutManager
|
||||
bookmarkPanel = ItemPanels.bookmarkPanel;
|
||||
bookmarkPanel.init();
|
||||
|
||||
itemZoom = new ItemZoom();
|
||||
|
||||
dropDown = new SubsetWidget();
|
||||
presetsPanel = new PresetsWidget();
|
||||
searchField = new SearchField("search");
|
||||
API.addItemFilter(searchField);
|
||||
|
||||
options = new ButtonCycled(3) {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.icons[0] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 32, 0, 16, 16).build();
|
||||
@@ -351,17 +423,23 @@ public class LayoutManager
|
||||
this.icons[2] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 64, 0, 16, 16).build();
|
||||
}
|
||||
|
||||
private boolean getIsAccessibleControlEventKey() {
|
||||
if (Minecraft.isRunningOnMac) {
|
||||
return Keyboard.getEventKey() == Keyboard.KEY_LMETA || Keyboard.getEventKey() == Keyboard.KEY_RMETA;
|
||||
}
|
||||
return Keyboard.getEventKey() == Keyboard.KEY_LCONTROL
|
||||
|| Keyboard.getEventKey() == Keyboard.KEY_RCONTROL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
if (Keyboard.getEventKeyState()
|
||||
&& (Keyboard.getEventKey() == Keyboard.KEY_LCONTROL
|
||||
|| Keyboard.getEventKey() == Keyboard.KEY_RCONTROL)) {
|
||||
if (Keyboard.getEventKeyState() && getIsAccessibleControlEventKey()
|
||||
&& NEIClientConfig.canChangeCheatMode()) {
|
||||
NEIClientConfig.cycleSetting("inventory.cheatmode", 3);
|
||||
} else {
|
||||
if (Keyboard.getEventKeyState()
|
||||
&& (Keyboard.getEventKey() == Keyboard.KEY_LSHIFT
|
||||
|| Keyboard.getEventKey() == Keyboard.KEY_RSHIFT)) {
|
||||
if (Keyboard.getEventKeyState() && (Keyboard.getEventKey() == Keyboard.KEY_LSHIFT
|
||||
|| Keyboard.getEventKey() == Keyboard.KEY_RSHIFT)) {
|
||||
GuiRecipeTab.loadHandlerInfo();
|
||||
RecipeCatalysts.loadCatalystInfo();
|
||||
}
|
||||
@@ -381,7 +459,10 @@ public class LayoutManager
|
||||
else if (cheatMode == 2) modeColor = EnumChatFormatting.RED.toString();
|
||||
String controlKeyLocalization = translate(Minecraft.isRunningOnMac ? "key.ctrl.mac" : "key.ctrl");
|
||||
tooltip.add(modeColor + translate("inventory.options.tip.cheatmode." + cheatMode));
|
||||
tooltip.add(modeColor + translate("inventory.options.tip.cheatmode.disable", controlKeyLocalization));
|
||||
if (NEIClientConfig.canChangeCheatMode()) {
|
||||
tooltip.add(
|
||||
modeColor + translate("inventory.options.tip.cheatmode.disable", controlKeyLocalization));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -391,6 +472,7 @@ public class LayoutManager
|
||||
};
|
||||
|
||||
bookmarksButton = new ButtonCycled(2) {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.icons[0] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 0, 0, 16, 16).build();
|
||||
@@ -399,7 +481,7 @@ public class LayoutManager
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
NEIClientConfig.toggleBooleanSetting("inventory.bookmarksEnabled");
|
||||
NEIClientConfig.toggleBooleanSetting("inventory.bookmarks.enabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -413,10 +495,45 @@ public class LayoutManager
|
||||
}
|
||||
};
|
||||
|
||||
more = ItemPanels.itemPanel.more;
|
||||
less = ItemPanels.itemPanel.less;
|
||||
quantity = ItemPanels.itemPanel.quantity;
|
||||
more = new Button("+") {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick) return false;
|
||||
|
||||
int modifier = NEIClientUtils.controlKey() ? 64 : NEIClientUtils.shiftKey() ? 10 : 1;
|
||||
int quantity = NEIClientConfig.getItemQuantity() + modifier;
|
||||
|
||||
if (quantity < 0) {
|
||||
quantity = 0;
|
||||
}
|
||||
|
||||
LayoutManager.quantity.setText(Integer.toString(quantity));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
less = new Button("-") {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick) return false;
|
||||
|
||||
int modifier = NEIClientUtils.controlKey() ? -64 : NEIClientUtils.shiftKey() ? -10 : -1;
|
||||
int quantity = NEIClientConfig.getItemQuantity() + modifier;
|
||||
|
||||
if (quantity < 0) {
|
||||
quantity = 0;
|
||||
}
|
||||
|
||||
LayoutManager.quantity.setText(Integer.toString(quantity));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
quantity = new ItemQuantityField("quantity");
|
||||
|
||||
delete = new Button() {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if ((state & 0x3) == 2) return false;
|
||||
@@ -444,16 +561,16 @@ public class LayoutManager
|
||||
|
||||
@Override
|
||||
public void postDraw(int mousex, int mousey) {
|
||||
if (contains(mousex, mousey) && getHeldItem() != null && (state & 0x3) != 2)
|
||||
GuiDraw.drawTip(
|
||||
mousex + 9,
|
||||
mousey,
|
||||
translate(
|
||||
"inventory.delete." + (shiftKey() ? "all" : "one"),
|
||||
GuiContainerManager.itemDisplayNameShort(getHeldItem())));
|
||||
if (contains(mousex, mousey) && getHeldItem() != null && (state & 0x3) != 2) GuiDraw.drawTip(
|
||||
mousex + 9,
|
||||
mousey,
|
||||
translate(
|
||||
"inventory.delete." + (shiftKey() ? "all" : "one"),
|
||||
GuiContainerManager.itemDisplayNameShort(getHeldItem())));
|
||||
}
|
||||
};
|
||||
gamemode = new ButtonCycled(3) {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
@@ -469,6 +586,7 @@ public class LayoutManager
|
||||
}
|
||||
};
|
||||
rain = new Button() {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (handleDisabledButtonPress("rain", rightclick)) return true;
|
||||
@@ -485,6 +603,7 @@ public class LayoutManager
|
||||
}
|
||||
};
|
||||
magnet = new Button() {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
@@ -501,6 +620,7 @@ public class LayoutManager
|
||||
for (int i = 0; i < 4; i++) {
|
||||
final int zone = i;
|
||||
timeButtons[i] = new Button() {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (handleDisabledButtonPress(NEIActions.timeZones[zone], rightclick)) return true;
|
||||
@@ -513,12 +633,13 @@ public class LayoutManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getButtonTip() {
|
||||
return getTimeTip(NEIActions.timeZones[zone], state);
|
||||
public void addTooltips(List<String> tooltip) {
|
||||
addTimeTip(NEIActions.timeZones[zone], state, tooltip);
|
||||
}
|
||||
};
|
||||
}
|
||||
heal = new Button() {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
@@ -546,9 +667,13 @@ public class LayoutManager
|
||||
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) {
|
||||
@@ -582,19 +707,19 @@ public class LayoutManager
|
||||
|
||||
if (!itemsLoaded) {
|
||||
ItemList.loadItems.restart();
|
||||
itemsLoaded = true;
|
||||
}
|
||||
overlayRenderer = null;
|
||||
|
||||
overlayRenderer = null;
|
||||
getLayoutStyle().init();
|
||||
layout(gui);
|
||||
AutoFocusWidget.instance.load(gui);
|
||||
}
|
||||
|
||||
NEIController.load(gui);
|
||||
|
||||
if (checkCreativeInv(gui)
|
||||
&& gui.mc.currentScreen instanceof GuiContainerCreative) // override creative with creative+
|
||||
gui.mc.displayGuiScreen(null); // close the screen and wait for the server to open it for us
|
||||
if (checkCreativeInv(gui) && gui.mc.currentScreen instanceof GuiContainerCreative) // override creative with
|
||||
// creative+
|
||||
gui.mc.displayGuiScreen(null); // close the screen and wait for the server to open it for us
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -619,14 +744,15 @@ public class LayoutManager
|
||||
|
||||
addWidget(options);
|
||||
addWidget(bookmarksButton);
|
||||
|
||||
if (visiblity.showItemPanel && NEIClientConfig.showItemQuantityWidget()) {
|
||||
addWidget(quantity);
|
||||
addWidget(more);
|
||||
addWidget(less);
|
||||
}
|
||||
|
||||
if (visiblity.showItemPanel) {
|
||||
|
||||
if (PresetsWidget.inEditMode()) {
|
||||
drawWidgets.add(itemPanel);
|
||||
} else {
|
||||
addWidget(itemPanel);
|
||||
}
|
||||
|
||||
addWidget(itemPanel);
|
||||
itemPanel.setVisible();
|
||||
}
|
||||
|
||||
@@ -635,13 +761,13 @@ public class LayoutManager
|
||||
bookmarkPanel.setVisible();
|
||||
}
|
||||
|
||||
if (visiblity.showPresetsDropdown) {
|
||||
addWidget(presetsPanel);
|
||||
}
|
||||
|
||||
searchField.setVisible(visiblity.showSearchSection);
|
||||
if (visiblity.showSearchSection) {
|
||||
if (visiblity.showSearchSection && NEIClientConfig.isSearchWidgetCentered()
|
||||
|| visiblity.showItemPanel && !NEIClientConfig.isSearchWidgetCentered()) {
|
||||
searchField.setVisible(true);
|
||||
addWidget(searchField);
|
||||
} else {
|
||||
searchField.setVisible(false);
|
||||
searchField.setFocus(false);
|
||||
}
|
||||
|
||||
if (visiblity.showUtilityButtons) {
|
||||
@@ -656,6 +782,8 @@ public class LayoutManager
|
||||
if (canPerformAction("delete")) addWidget(delete);
|
||||
}
|
||||
|
||||
addWidget(itemZoom);
|
||||
|
||||
if (visiblity.showSubsetDropdown) {
|
||||
// Bookmarks or Subset/dropdown
|
||||
addWidget(dropDown);
|
||||
@@ -690,7 +818,9 @@ public class LayoutManager
|
||||
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
if (isHidden() || !isEnabled()) return false;
|
||||
|
||||
for (Widget widget : drawWidgets) if (widget.onMouseWheel(scrolled, mousex, mousey)) return true;
|
||||
for (Widget widget : controlWidgets) {
|
||||
if (widget.onMouseWheel(scrolled, mousex, mousey)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -700,7 +830,7 @@ public class LayoutManager
|
||||
|
||||
@Override
|
||||
public boolean shouldShowTooltip(GuiContainer gui) {
|
||||
return itemPanel.draggedStack == null && bookmarkPanel.sortedStackIndex == -1;
|
||||
return itemPanel.draggedStack == null && !bookmarkPanel.inEditingState();
|
||||
}
|
||||
|
||||
/** Note: this method isn't actually used by this mod, but NEI add-ons might need it. */
|
||||
@@ -723,17 +853,21 @@ public class LayoutManager
|
||||
|
||||
@Override
|
||||
public void renderSlotOverlay(GuiContainer window, Slot slot) {
|
||||
ItemStack item = slot.getStack();
|
||||
if (world.nbt.getBoolean("searchinventories")
|
||||
&& (item == null
|
||||
? !getSearchExpression().equals("")
|
||||
: !((SearchField) searchField).getFilter().matches(item))) {
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glTranslatef(0, 0, 150);
|
||||
drawRect(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, 0x80000000);
|
||||
GL11.glTranslatef(0, 0, -150);
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
|
||||
if (SearchField.searchInventories()) {
|
||||
ItemStack item = slot.getStack();
|
||||
|
||||
if (item == null ? !getSearchExpression().equals("") : !searchField.getFilter().matches(item)) {
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glTranslatef(0, 0, 150);
|
||||
drawRect(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, 0x80000000);
|
||||
GL11.glTranslatef(0, 0, -150);
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void drawIcon(int x, int y, Image image) {
|
||||
@@ -745,7 +879,7 @@ public class LayoutManager
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
if (!isDrawableResource) drawTexturedModalRect(x, y, image.x, image.y, image.width, image.height);
|
||||
else ((DrawableResource) image).draw(x, y);
|
||||
else((DrawableResource) image).draw(x, y);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
|
||||
@@ -789,9 +923,19 @@ public class LayoutManager
|
||||
drawTexturedModalRect(x2, y2, tx2, ty2, w2, h2); // bottom right
|
||||
}
|
||||
|
||||
public static void drawItemPresenceOverlay(int slotX, int slotY, boolean isPresent) {
|
||||
Image icon = itemPresenceOverlays[isPresent ? 1 : 0];
|
||||
drawIcon(slotX + 16 - icon.width, slotY + 16 - icon.height, icon);
|
||||
public static void drawItemPresenceOverlay(int slotX, int slotY, boolean isPresent, boolean slotHighlight) {
|
||||
|
||||
if (slotHighlight) {
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
drawRect(slotX, slotY, 16, 16, isPresent ? 0x8000AA00 : 0x80AA0000);
|
||||
GL11.glPopAttrib();
|
||||
} else {
|
||||
Image icon = itemPresenceOverlays[isPresent ? 1 : 0];
|
||||
drawIcon(slotX + 16 - icon.width, slotY + 16 - icon.height, icon);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static LayoutManager instance() {
|
||||
|
||||
@@ -1,31 +1,20 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawStringC;
|
||||
import static codechicken.nei.LayoutManager.bookmarkPanel;
|
||||
import static codechicken.nei.LayoutManager.bookmarksButton;
|
||||
import static codechicken.nei.LayoutManager.delete;
|
||||
import static codechicken.nei.LayoutManager.dropDown;
|
||||
import static codechicken.nei.LayoutManager.gamemode;
|
||||
import static codechicken.nei.LayoutManager.heal;
|
||||
import static codechicken.nei.LayoutManager.itemPanel;
|
||||
import static codechicken.nei.LayoutManager.itemPresenceOverlays;
|
||||
import static codechicken.nei.LayoutManager.magnet;
|
||||
import static codechicken.nei.LayoutManager.options;
|
||||
import static codechicken.nei.LayoutManager.presetsPanel;
|
||||
import static codechicken.nei.LayoutManager.rain;
|
||||
import static codechicken.nei.LayoutManager.searchField;
|
||||
import static codechicken.nei.LayoutManager.timeButtons;
|
||||
import static codechicken.nei.NEIClientConfig.canPerformAction;
|
||||
import static codechicken.nei.NEIClientConfig.disabledActions;
|
||||
import static codechicken.nei.NEIClientConfig.getMagnetMode;
|
||||
import static codechicken.nei.NEIClientConfig.isEnabled;
|
||||
|
||||
import codechicken.nei.api.LayoutStyle;
|
||||
import codechicken.nei.drawable.DrawableBuilder;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.LayoutStyle;
|
||||
import codechicken.nei.drawable.DrawableBuilder;
|
||||
|
||||
public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
|
||||
protected static final int BUTTON_SIZE = 20;
|
||||
protected static final int MARGIN = 2;
|
||||
|
||||
public int buttonCount;
|
||||
public int leftSize;
|
||||
public int numButtons;
|
||||
@@ -37,19 +26,21 @@ public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
delete.icon = new Image(144, 12, 12, 12);
|
||||
rain.icon = new Image(120, 12, 12, 12);
|
||||
gamemode.icons[0] = new Image(132, 12, 12, 12);
|
||||
gamemode.icons[1] = new Image(156, 12, 12, 12);
|
||||
gamemode.icons[2] = new Image(168, 12, 12, 12);
|
||||
magnet.icon = new Image(180, 24, 12, 12);
|
||||
timeButtons[0].icon = new Image(132, 24, 12, 12);
|
||||
timeButtons[1].icon = new Image(120, 24, 12, 12);
|
||||
timeButtons[2].icon = new Image(144, 24, 12, 12);
|
||||
timeButtons[3].icon = new Image(156, 24, 12, 12);
|
||||
heal.icon = new Image(168, 24, 12, 12);
|
||||
itemPresenceOverlays[0] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 0, 40, 8, 8).build();
|
||||
itemPresenceOverlays[1] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 8, 40, 8, 8).build();
|
||||
LayoutManager.delete.icon = new Image(144, 12, 12, 12);
|
||||
LayoutManager.rain.icon = new Image(120, 12, 12, 12);
|
||||
LayoutManager.gamemode.icons[0] = new Image(132, 12, 12, 12);
|
||||
LayoutManager.gamemode.icons[1] = new Image(156, 12, 12, 12);
|
||||
LayoutManager.gamemode.icons[2] = new Image(168, 12, 12, 12);
|
||||
LayoutManager.magnet.icon = new Image(180, 24, 12, 12);
|
||||
LayoutManager.timeButtons[0].icon = new Image(132, 24, 12, 12);
|
||||
LayoutManager.timeButtons[1].icon = new Image(120, 24, 12, 12);
|
||||
LayoutManager.timeButtons[2].icon = new Image(144, 24, 12, 12);
|
||||
LayoutManager.timeButtons[3].icon = new Image(156, 24, 12, 12);
|
||||
LayoutManager.heal.icon = new Image(168, 24, 12, 12);
|
||||
LayoutManager.itemPresenceOverlays[0] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 0, 40, 8, 8)
|
||||
.build();
|
||||
LayoutManager.itemPresenceOverlays[1] = new DrawableBuilder("nei:textures/nei_tabbed_sprites.png", 8, 40, 8, 8)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,84 +53,177 @@ public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
reset();
|
||||
|
||||
leftSize = ItemPanels.bookmarkPanel.getWidth(gui);
|
||||
numButtons = Math.max(leftSize / 18, 1);
|
||||
numButtons = Math.max(leftSize / 20, 1);
|
||||
|
||||
delete.state = 0x4;
|
||||
if (NEIController.getDeleteMode()) delete.state |= 1;
|
||||
else if (!visiblity.enableDeleteMode) delete.state |= 2;
|
||||
|
||||
rain.state = 0x4;
|
||||
if (disabledActions.contains("rain")) rain.state |= 2;
|
||||
else if (NEIClientUtils.isRaining()) rain.state |= 1;
|
||||
|
||||
gamemode.state = 0x4;
|
||||
if (NEIClientUtils.getGamemode() != 0) {
|
||||
gamemode.state |= 0x1;
|
||||
gamemode.index = NEIClientUtils.getGamemode() - 1;
|
||||
} else {
|
||||
if (NEIClientUtils.isValidGamemode("creative")) gamemode.index = 0;
|
||||
else if (NEIClientUtils.isValidGamemode("creative+")) gamemode.index = 1;
|
||||
else if (NEIClientUtils.isValidGamemode("adventure")) gamemode.index = 2;
|
||||
LayoutManager.delete.state = 0x4;
|
||||
if (NEIController.getDeleteMode()) {
|
||||
LayoutManager.delete.state |= 1;
|
||||
} else if (!visiblity.enableDeleteMode) {
|
||||
LayoutManager.delete.state |= 2;
|
||||
}
|
||||
bookmarksButton.index = NEIClientConfig.isBookmarkPanelHidden() ? 0 : 1;
|
||||
options.index = NEIClientConfig.getCheatMode();
|
||||
|
||||
magnet.state = 0x4 | (getMagnetMode() ? 1 : 0);
|
||||
LayoutManager.rain.state = 0x4;
|
||||
if (NEIClientConfig.disabledActions.contains("rain")) {
|
||||
LayoutManager.rain.state |= 2;
|
||||
} else if (NEIClientUtils.isRaining()) {
|
||||
LayoutManager.rain.state |= 1;
|
||||
}
|
||||
|
||||
if (canPerformAction("delete")) layoutButton(delete);
|
||||
if (canPerformAction("rain")) layoutButton(rain);
|
||||
if (NEIClientUtils.isValidGamemode("creative")
|
||||
|| NEIClientUtils.isValidGamemode("creative+")
|
||||
|| NEIClientUtils.isValidGamemode("adventure")) layoutButton(gamemode);
|
||||
if (canPerformAction("magnet")) layoutButton(magnet);
|
||||
if (canPerformAction("time")) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
timeButtons[i].state = disabledActions.contains(NEIActions.timeZones[i]) ? 2 : 0;
|
||||
layoutButton(timeButtons[i]);
|
||||
LayoutManager.gamemode.state = 0x4;
|
||||
if (NEIClientUtils.getGamemode() != 0) {
|
||||
LayoutManager.gamemode.state |= 0x1;
|
||||
LayoutManager.gamemode.index = NEIClientUtils.getGamemode() - 1;
|
||||
} else {
|
||||
if (NEIClientUtils.isValidGamemode("creative")) {
|
||||
LayoutManager.gamemode.index = 0;
|
||||
} else if (NEIClientUtils.isValidGamemode("creative+")) {
|
||||
LayoutManager.gamemode.index = 1;
|
||||
} else if (NEIClientUtils.isValidGamemode("adventure")) {
|
||||
LayoutManager.gamemode.index = 2;
|
||||
}
|
||||
}
|
||||
if (canPerformAction("heal")) layoutButton(heal);
|
||||
LayoutManager.bookmarksButton.index = NEIClientConfig.isBookmarkPanelHidden() ? 0 : 1;
|
||||
LayoutManager.options.index = NEIClientConfig.getCheatMode();
|
||||
|
||||
itemPanel.resize(gui);
|
||||
bookmarkPanel.resize(gui);
|
||||
LayoutManager.magnet.state = 0x4 | (NEIClientConfig.getMagnetMode() ? 1 : 0);
|
||||
|
||||
options.x = isEnabled() ? 0 : 6;
|
||||
options.y = isEnabled() ? gui.height - 22 : gui.height - 28;
|
||||
options.w = 22;
|
||||
options.h = 22;
|
||||
|
||||
bookmarksButton.x = 24 + (isEnabled() ? 0 : 6);
|
||||
bookmarksButton.y = isEnabled() ? gui.height - 22 : gui.height - 28;
|
||||
bookmarksButton.w = 22;
|
||||
bookmarksButton.h = 22;
|
||||
|
||||
dropDown.h = 18;
|
||||
dropDown.w = 150;
|
||||
dropDown.y = 0;
|
||||
dropDown.x = (gui.width - gui.xSize) / 2 + gui.xSize - dropDown.w;
|
||||
|
||||
presetsPanel.h = 16;
|
||||
presetsPanel.w = 150;
|
||||
presetsPanel.y = 2;
|
||||
presetsPanel.x = (gui.width - gui.xSize) / 2 + gui.xSize - presetsPanel.w;
|
||||
|
||||
searchField.h = 20;
|
||||
searchField.w = 150;
|
||||
searchField.x = (gui.width - searchField.w) / 2;
|
||||
searchField.y = gui.height - searchField.h - 2;
|
||||
|
||||
if (!visiblity.showItemSection) {
|
||||
searchField.setFocus(false);
|
||||
if (NEIClientConfig.canPerformAction("delete")) {
|
||||
layoutButton(LayoutManager.delete);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.canPerformAction("rain")) {
|
||||
layoutButton(LayoutManager.rain);
|
||||
}
|
||||
|
||||
if (NEIClientUtils.isValidGamemode("creative") || NEIClientUtils.isValidGamemode("creative+")
|
||||
|| NEIClientUtils.isValidGamemode("adventure")) {
|
||||
layoutButton(LayoutManager.gamemode);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.canPerformAction("magnet")) {
|
||||
layoutButton(LayoutManager.magnet);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.canPerformAction("time")) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
LayoutManager.timeButtons[i].state = NEIClientConfig.disabledActions.contains(NEIActions.timeZones[i])
|
||||
? 2
|
||||
: 0;
|
||||
layoutButton(LayoutManager.timeButtons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (NEIClientConfig.canPerformAction("heal")) {
|
||||
layoutButton(LayoutManager.heal);
|
||||
}
|
||||
|
||||
layoutFooter(gui, visiblity);
|
||||
|
||||
LayoutManager.itemPanel.resize(gui);
|
||||
LayoutManager.bookmarkPanel.resize(gui);
|
||||
LayoutManager.itemZoom.resize(gui);
|
||||
}
|
||||
|
||||
protected void layoutFooter(GuiContainer gui, VisiblityData visiblity) {
|
||||
|
||||
LayoutManager.options.x = MARGIN;
|
||||
LayoutManager.options.y = gui.height - BUTTON_SIZE - MARGIN;
|
||||
LayoutManager.options.w = LayoutManager.options.h = BUTTON_SIZE;
|
||||
|
||||
LayoutManager.bookmarksButton.x = LayoutManager.options.x + LayoutManager.options.w + MARGIN;
|
||||
LayoutManager.bookmarksButton.y = gui.height - BUTTON_SIZE - MARGIN;
|
||||
LayoutManager.bookmarksButton.w = LayoutManager.bookmarksButton.h = BUTTON_SIZE;
|
||||
|
||||
final Rectangle4i searchArea = getSearchFieldArea(gui);
|
||||
final Rectangle4i quantityArea = getQuantityFieldArea(visiblity);
|
||||
|
||||
LayoutManager.searchField.x = searchArea.x;
|
||||
LayoutManager.searchField.y = searchArea.y;
|
||||
LayoutManager.searchField.w = searchArea.w;
|
||||
LayoutManager.searchField.h = searchArea.h;
|
||||
|
||||
if (!NEIClientConfig.subsetWidgetOnTop() && visiblity.showSubsetDropdown) {
|
||||
LayoutManager.dropDown.x = searchArea.x;
|
||||
LayoutManager.dropDown.y = searchArea.y;
|
||||
LayoutManager.dropDown.h = LayoutManager.dropDown.w = BUTTON_SIZE;
|
||||
|
||||
LayoutManager.searchField.x += BUTTON_SIZE;
|
||||
LayoutManager.searchField.w -= BUTTON_SIZE;
|
||||
} else {
|
||||
LayoutManager.dropDown.h = 16;
|
||||
LayoutManager.dropDown.w = 150;
|
||||
LayoutManager.dropDown.y = MARGIN;
|
||||
LayoutManager.dropDown.x = (gui.width - LayoutManager.dropDown.w) / 2;
|
||||
}
|
||||
|
||||
if (quantityArea.w == ItemPanels.itemPanel.w) {
|
||||
LayoutManager.more.w = LayoutManager.less.w = BUTTON_SIZE;
|
||||
LayoutManager.more.h = LayoutManager.less.h = LayoutManager.quantity.h = quantityArea.h;
|
||||
LayoutManager.more.y = LayoutManager.less.y = LayoutManager.quantity.y = quantityArea.y;
|
||||
|
||||
LayoutManager.less.x = quantityArea.x;
|
||||
LayoutManager.more.x = quantityArea.x2() - BUTTON_SIZE;
|
||||
|
||||
LayoutManager.quantity.x = LayoutManager.less.x + LayoutManager.less.w + 1;
|
||||
LayoutManager.quantity.w = LayoutManager.more.x - LayoutManager.quantity.x - 1;
|
||||
} else {
|
||||
LayoutManager.quantity.x = quantityArea.x;
|
||||
LayoutManager.quantity.w = quantityArea.w - 18;
|
||||
LayoutManager.quantity.y = LayoutManager.more.y = quantityArea.y;
|
||||
LayoutManager.quantity.h = quantityArea.h;
|
||||
|
||||
LayoutManager.more.w = LayoutManager.less.w = 18;
|
||||
LayoutManager.more.x = LayoutManager.less.x = LayoutManager.quantity.x + LayoutManager.quantity.w;
|
||||
LayoutManager.more.h = LayoutManager.less.h = LayoutManager.quantity.h / 2;
|
||||
LayoutManager.less.y = LayoutManager.more.y + LayoutManager.more.h;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Rectangle4i getSearchFieldArea(GuiContainer gui) {
|
||||
final Rectangle4i area = new Rectangle4i(0, 0, 0, BUTTON_SIZE);
|
||||
|
||||
if (NEIClientConfig.isSearchWidgetCentered()) {
|
||||
area.w = gui.xSize - MARGIN * 2;
|
||||
area.x = (gui.width - area.w) / 2;
|
||||
area.y = gui.height - BUTTON_SIZE - MARGIN;
|
||||
} else if (NEIClientConfig.showItemQuantityWidget()) {
|
||||
area.w = ItemPanels.itemPanel.w - (int) Math.max(BUTTON_SIZE * 2.5f, ItemPanels.itemPanel.w * 0.3f) - 1;
|
||||
area.x = ItemPanels.itemPanel.x;
|
||||
area.y = ItemPanels.itemPanel.y + ItemPanels.itemPanel.h - BUTTON_SIZE;
|
||||
} else {
|
||||
area.w = ItemPanels.itemPanel.w;
|
||||
area.x = ItemPanels.itemPanel.x;
|
||||
area.y = ItemPanels.itemPanel.y + ItemPanels.itemPanel.h - BUTTON_SIZE;
|
||||
}
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
private Rectangle4i getQuantityFieldArea(VisiblityData visiblity) {
|
||||
final Rectangle4i area = new Rectangle4i(0, 0, 0, BUTTON_SIZE);
|
||||
|
||||
if (!visiblity.showSearchSection || NEIClientConfig.isSearchWidgetCentered()) {
|
||||
area.w = ItemPanels.itemPanel.w;
|
||||
area.x = ItemPanels.itemPanel.x;
|
||||
} else {
|
||||
area.w = (int) Math.max(BUTTON_SIZE * 2.5f, ItemPanels.itemPanel.w * 0.3f);
|
||||
area.x = ItemPanels.itemPanel.x + ItemPanels.itemPanel.w - area.w;
|
||||
}
|
||||
|
||||
area.y = ItemPanels.itemPanel.y + ItemPanels.itemPanel.h - BUTTON_SIZE;
|
||||
|
||||
return area;
|
||||
}
|
||||
|
||||
public void layoutButton(Button button) {
|
||||
button.x = 2 + (buttonCount % numButtons) * 19;
|
||||
button.y = 2 + (buttonCount / numButtons) * 18;
|
||||
|
||||
button.h = 17;
|
||||
button.w = button.contentWidth() + 6;
|
||||
|
||||
button.x = MARGIN + (buttonCount % numButtons) * (button.w + MARGIN);
|
||||
button.y = MARGIN + (buttonCount / numButtons) * (button.h + MARGIN);
|
||||
|
||||
buttonCount++;
|
||||
}
|
||||
|
||||
@@ -150,10 +234,9 @@ public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
|
||||
int tex;
|
||||
if ((b.state & 0x3) == 2) tex = 0;
|
||||
else if ((b.state & 0x4) == 0 && b.contains(mousex, mousey)
|
||||
|| // not a state button and mouseover
|
||||
else if ((b.state & 0x4) == 0 && b.contains(mousex, mousey) || // not a state button and mouseover
|
||||
(b.state & 0x3) == 1) // state active
|
||||
tex = 2;
|
||||
tex = 2;
|
||||
else tex = 1;
|
||||
LayoutManager.drawButtonBackground(b.x, b.y, b.w, b.h, true, tex);
|
||||
|
||||
@@ -174,9 +257,16 @@ public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
|
||||
@Override
|
||||
public void drawSubsetTag(String text, int x, int y, int w, int h, int state, boolean mouseover) {
|
||||
if (state == 1) GL11.glColor4f(0.65F, 0.65F, 0.65F, 1.0F);
|
||||
else GL11.glColor4f(1, 1, 1, 1);
|
||||
if (state == 1) {
|
||||
GL11.glColor4f(0.65F, 0.65F, 0.65F, 1.0F);
|
||||
} else {
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
LayoutManager.drawButtonBackground(x, y, w, h, false, state == 0 ? 0 : 1);
|
||||
if (text != null) drawStringC(text, x, y, w, h, state == 2 ? 0xFFE0E0E0 : 0xFFA0A0A0);
|
||||
|
||||
if (text != null) {
|
||||
drawStringC(text, x, y, w, h, mouseover ? 0xFFFFFFA0 : (state == 2 ? 0xFFE0E0E0 : 0xFFA0A0A0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class NEIActions {
|
||||
|
||||
public static final int protocol = 0;
|
||||
|
||||
public static HashMap<String, NEIActions> nameActionMap = new HashMap<>();
|
||||
@@ -61,8 +62,8 @@ public class NEIActions {
|
||||
canDisable.add("rain");
|
||||
}
|
||||
|
||||
public static final String[] timeZones = new String[] {"dawn", "noon", "dusk", "midnight"};
|
||||
public static final String[] gameModes = new String[] {"survival", "creative", "creative+", "adventure"};
|
||||
public static final String[] timeZones = new String[] { "dawn", "noon", "dusk", "midnight" };
|
||||
public static final String[] gameModes = new String[] { "survival", "creative", "creative+", "adventure" };
|
||||
|
||||
public String name;
|
||||
public String base;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.core.ClientUtils;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.lib.packet.PacketCustom.IClientPacketHandler;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import static codechicken.nei.PacketIDs.C2S;
|
||||
import static codechicken.nei.PacketIDs.S2C;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.inventory.GuiInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -12,43 +10,50 @@ import net.minecraft.network.play.INetHandlerPlayClient;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import codechicken.core.ClientUtils;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.lib.packet.PacketCustom.IClientPacketHandler;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
|
||||
public class NEICPH implements IClientPacketHandler {
|
||||
|
||||
public static final String channel = "NEI";
|
||||
|
||||
@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));
|
||||
packet.readUByte(),
|
||||
new GuiEnchantmentModifier(mc.thePlayer.inventory, mc.theWorld, 0, 0, 0));
|
||||
break;
|
||||
case 23:
|
||||
if (packet.readBoolean())
|
||||
ClientUtils.openSMPGui(
|
||||
packet.readUByte(),
|
||||
new GuiExtendedCreativeInv(new ContainerCreativeInv(
|
||||
mc.thePlayer, new ExtendedCreativeInv(null, Side.CLIENT))));
|
||||
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;
|
||||
}
|
||||
@@ -100,7 +105,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);
|
||||
@@ -108,14 +113,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);
|
||||
@@ -123,7 +128,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();
|
||||
}
|
||||
|
||||
@@ -137,12 +142,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, 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);
|
||||
@@ -150,38 +161,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);
|
||||
@@ -189,30 +200,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();
|
||||
@@ -223,13 +234,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();
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
import codechicken.nei.api.TaggedInventoryArea;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiChest;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.ContainerChest;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
import codechicken.nei.api.TaggedInventoryArea;
|
||||
|
||||
public class NEIChestGuiHandler extends INEIGuiAdapter {
|
||||
|
||||
public int chestSize(GuiContainer gui) {
|
||||
return ((ContainerChest) gui.inventorySlots).getLowerChestInventory().getSizeInventory();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -8,13 +8,8 @@ import static codechicken.nei.NEIClientConfig.hasSMPCounterPart;
|
||||
import static codechicken.nei.NEIClientConfig.invCreativeMode;
|
||||
import static codechicken.nei.NEIClientConfig.world;
|
||||
|
||||
import codechicken.lib.inventory.InventoryRange;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.util.LangProxy;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.IInfiniteItemHandler;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import com.google.common.collect.Iterables;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
@@ -29,7 +24,10 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
@@ -41,18 +39,44 @@ import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
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;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.IInfiniteItemHandler;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
|
||||
public class NEIClientUtils extends NEIServerUtils {
|
||||
|
||||
public static LangProxy lang = new LangProxy("nei");
|
||||
|
||||
/** Formats a number with group separator and at most 2 fraction digits. */
|
||||
private static final Map<Locale, DecimalFormat> decimalFormatters = new HashMap<>();
|
||||
private static final Map<Integer, Integer> keyHashMap = new HashMap<>();
|
||||
|
||||
public static final int ALT_HASH = 1 << 27;
|
||||
public static final int SHIFT_HASH = 1 << 26;
|
||||
public static final int CTRL_HASH = 1 << 25;
|
||||
|
||||
static {
|
||||
keyHashMap.put(Keyboard.KEY_LSHIFT, SHIFT_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_RSHIFT, SHIFT_HASH);
|
||||
|
||||
keyHashMap.put(Keyboard.KEY_LCONTROL, CTRL_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_LCONTROL, CTRL_HASH);
|
||||
|
||||
keyHashMap.put(Keyboard.KEY_LMETA, CTRL_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_RMETA, CTRL_HASH);
|
||||
|
||||
keyHashMap.put(Keyboard.KEY_LMENU, ALT_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_LMENU, ALT_HASH);
|
||||
}
|
||||
|
||||
public static Minecraft mc() {
|
||||
return Minecraft.getMinecraft();
|
||||
}
|
||||
@@ -105,8 +129,7 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
}
|
||||
|
||||
public static void decreaseSlotStack(int slotNumber) {
|
||||
ItemStack stack = slotNumber == -999
|
||||
? getHeldItem()
|
||||
ItemStack stack = slotNumber == -999 ? getHeldItem()
|
||||
: mc().thePlayer.openContainer.getSlot(slotNumber).getStack();
|
||||
if (stack == null) return;
|
||||
|
||||
@@ -147,7 +170,7 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mode -1 = normal cheats, 0 = no infinites, 1 = replenish stack
|
||||
* @param mode -1 = normal cheats, 0 = no infinites, 1 = replenish stack
|
||||
*/
|
||||
public static void cheatItem(ItemStack stack, int button, int mode) {
|
||||
if (!canCheatItem(stack)) return;
|
||||
@@ -186,16 +209,14 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
ItemStack stack = copyStack(base, i);
|
||||
if (hasSMPCounterPart()) {
|
||||
ItemStack typestack = copyStack(stack, 1);
|
||||
if (!infinite
|
||||
&& !canItemFitInInventory(mc().thePlayer, stack)
|
||||
if (!infinite && !canItemFitInInventory(mc().thePlayer, stack)
|
||||
&& (mc().currentScreen instanceof GuiContainer)) {
|
||||
GuiContainer gui = getGuiContainer();
|
||||
final List<Iterable<Integer>> handlerSlots;
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
handlerSlots = GuiInfo.guiHandlers.stream()
|
||||
.map(handler -> handler.getItemSpawnSlots(gui, typestack))
|
||||
.filter(x -> x != null)
|
||||
.map(handler -> handler.getItemSpawnSlots(gui, typestack)).filter(x -> x != null)
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
} finally {
|
||||
GuiInfo.readLock.unlock();
|
||||
@@ -220,7 +241,7 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
if (given > 0) NEICPH.sendGiveItem(copyStack(typestack, given), false, false);
|
||||
} else NEICPH.sendGiveItem(stack, infinite, true);
|
||||
} else {
|
||||
for (int given = 0; given < stack.stackSize; ) {
|
||||
for (int given = 0; given < stack.stackSize;) {
|
||||
int qty = Math.min(stack.stackSize - given, stack.getMaxStackSize());
|
||||
sendCommand(
|
||||
getStringSetting("command.item"),
|
||||
@@ -244,6 +265,9 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
}
|
||||
|
||||
public static boolean controlKey() {
|
||||
if (Minecraft.isRunningOnMac) {
|
||||
return Keyboard.isKeyDown(Keyboard.KEY_LMETA) || Keyboard.isKeyDown(Keyboard.KEY_RMETA);
|
||||
}
|
||||
return Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL);
|
||||
}
|
||||
|
||||
@@ -256,9 +280,7 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
|
||||
public static boolean isValidGamemode(String s) {
|
||||
return s.equals("survival")
|
||||
|| canPerformAction(s)
|
||||
&& Arrays.asList(getStringArrSetting("inventory.gamemodes"))
|
||||
.contains(s);
|
||||
|| canPerformAction(s) && Arrays.asList(getStringArrSetting("inventory.gamemodes")).contains(s);
|
||||
}
|
||||
|
||||
public static int getNextGamemode() {
|
||||
@@ -277,11 +299,10 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
if (mode == nmode) return;
|
||||
|
||||
if (hasSMPCounterPart()) NEICPH.sendGamemode(nmode);
|
||||
else
|
||||
sendCommand(
|
||||
getStringSetting("command.creative"),
|
||||
getGameType(nmode),
|
||||
mc().thePlayer.getCommandSenderName());
|
||||
else sendCommand(
|
||||
getStringSetting("command.creative"),
|
||||
getGameType(nmode),
|
||||
mc().thePlayer.getCommandSenderName());
|
||||
}
|
||||
|
||||
public static long getTime() {
|
||||
@@ -301,14 +322,13 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
}
|
||||
|
||||
public static void sendCommand(String command, Object... args) {
|
||||
if (command.length() == 0) return;
|
||||
if (command.isEmpty()) return;
|
||||
|
||||
NumberFormat numberformat = NumberFormat.getIntegerInstance();
|
||||
numberformat.setGroupingUsed(false);
|
||||
MessageFormat messageformat = new MessageFormat(command);
|
||||
for (int i = 0; i < args.length; i++)
|
||||
if (args[i] instanceof Integer || args[i] instanceof Long)
|
||||
messageformat.setFormatByArgumentIndex(i, numberformat);
|
||||
for (int i = 0; i < args.length; i++) if (args[i] instanceof Integer || args[i] instanceof Long)
|
||||
messageformat.setFormatByArgumentIndex(i, numberformat);
|
||||
|
||||
mc().thePlayer.sendChatMessage(messageformat.format(args));
|
||||
}
|
||||
@@ -344,13 +364,13 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
continue;
|
||||
}
|
||||
if (next + 1 != i) {
|
||||
ranges.add(new int[] {start, next});
|
||||
ranges.add(new int[] { start, next });
|
||||
start = next = i;
|
||||
continue;
|
||||
}
|
||||
next = i;
|
||||
}
|
||||
ranges.add(new int[] {start, next});
|
||||
ranges.add(new int[] { start, next });
|
||||
return ranges;
|
||||
}
|
||||
|
||||
@@ -361,18 +381,23 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
}
|
||||
|
||||
public static String cropText(FontRenderer fontRenderer, String text, int containerWidth) {
|
||||
|
||||
int textWidth = fontRenderer.getStringWidth(text);
|
||||
|
||||
if (textWidth > containerWidth) {
|
||||
textWidth += fontRenderer.getStringWidth("...");
|
||||
int dots = fontRenderer.getStringWidth("...");
|
||||
|
||||
while (textWidth > containerWidth) {
|
||||
textWidth -= fontRenderer.getCharWidth(text.charAt(text.length() - 1));
|
||||
text = text.substring(0, text.length() - 1);
|
||||
if (containerWidth > dots) {
|
||||
textWidth += dots;
|
||||
|
||||
while (textWidth > containerWidth) {
|
||||
textWidth -= fontRenderer.getCharWidth(text.charAt(text.length() - 1));
|
||||
text = text.substring(0, text.length() - 1);
|
||||
}
|
||||
|
||||
return text + "...";
|
||||
}
|
||||
|
||||
return text + "...";
|
||||
return "...";
|
||||
}
|
||||
|
||||
return text;
|
||||
@@ -388,7 +413,6 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
|
||||
public static void setItemQuantity(int i) {
|
||||
world.nbt.setInteger("quantity", i);
|
||||
world.saveNBT();
|
||||
}
|
||||
|
||||
public static GuiContainer getGuiContainer() {
|
||||
@@ -428,12 +452,7 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
if (Keyboard.getEventKeyState()) {
|
||||
final int keycode = Keyboard.getEventKey();
|
||||
|
||||
if (keycode != Keyboard.KEY_LSHIFT
|
||||
&& keycode != Keyboard.KEY_RSHIFT
|
||||
&& keycode != Keyboard.KEY_LCONTROL
|
||||
&& keycode != Keyboard.KEY_RCONTROL
|
||||
&& keycode != Keyboard.KEY_LMENU
|
||||
&& keycode != Keyboard.KEY_RMENU) {
|
||||
if (!keyHashMap.containsKey(keycode)) {
|
||||
return getMetaHash() + keycode;
|
||||
}
|
||||
}
|
||||
@@ -441,8 +460,66 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
return Keyboard.CHAR_NONE;
|
||||
}
|
||||
|
||||
public static String getKeyHashName(int keyBind) {
|
||||
StringJoiner keyText = new StringJoiner(" + ");
|
||||
|
||||
if ((keyBind & CTRL_HASH) != 0) {
|
||||
keyText.add(translate(Minecraft.isRunningOnMac ? "key.ctrl.mac" : "key.ctrl"));
|
||||
}
|
||||
|
||||
if ((keyBind & SHIFT_HASH) != 0) {
|
||||
keyText.add(translate("key.shift"));
|
||||
}
|
||||
|
||||
if ((keyBind & ALT_HASH) != 0) {
|
||||
keyText.add(translate("key.alt"));
|
||||
}
|
||||
|
||||
return keyText.toString();
|
||||
}
|
||||
|
||||
public static String getKeyName(int keyBind) {
|
||||
keyBind = keyHashMap.getOrDefault(keyBind, keyBind);
|
||||
StringJoiner keyText = new StringJoiner(" + ");
|
||||
String hashText = getKeyHashName(keyBind);
|
||||
int keyID = unHashKey(keyBind);
|
||||
|
||||
if (!hashText.isEmpty()) {
|
||||
keyText.add(hashText);
|
||||
}
|
||||
|
||||
if (keyID != Keyboard.CHAR_NONE || hashText.isEmpty()) {
|
||||
keyText.add(Keyboard.getKeyName(keyID));
|
||||
}
|
||||
|
||||
return keyText.toString();
|
||||
}
|
||||
|
||||
public static int unHashKey(int keyBind) {
|
||||
return keyBind & ~(CTRL_HASH | SHIFT_HASH | ALT_HASH);
|
||||
}
|
||||
|
||||
public static void playClickSound() {
|
||||
mc().getSoundHandler()
|
||||
.playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
}
|
||||
|
||||
public static void reportErrorBuffered(Throwable e, Set<String> buffer, String cause) {
|
||||
StringWriter sw = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(sw));
|
||||
String stackTrace = cause + sw;
|
||||
if (buffer.contains(stackTrace)) return;
|
||||
|
||||
System.err.println("Error while rendering: " + cause + " (" + e.getMessage() + ")");
|
||||
e.printStackTrace();
|
||||
buffer.add(stackTrace);
|
||||
}
|
||||
|
||||
public static void reportErrorBuffered(Throwable e, Set<String> buffer, ItemStack cause) {
|
||||
if (cause != null) {
|
||||
reportErrorBuffered(e, buffer, cause.toString());
|
||||
} else {
|
||||
reportErrorBuffered(e, buffer, "null");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
package codechicken.nei;
|
||||
|
||||
public class NEICompatibility {}
|
||||
public class NEICompatibility {
|
||||
}
|
||||
@@ -2,6 +2,16 @@ package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.gui.inventory.GuiContainerCreative;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.inventory.SlotCrafting;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.IInfiniteItemHandler;
|
||||
@@ -11,16 +21,9 @@ import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.guihook.IContainerSlotClickHandler;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import java.awt.Point;
|
||||
import java.util.LinkedList;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.gui.inventory.GuiContainerCreative;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.inventory.SlotCrafting;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public class NEIController implements IContainerSlotClickHandler, IContainerInputHandler {
|
||||
|
||||
private static final NEIController instance = new NEIController();
|
||||
|
||||
public static GuiContainerManager manager;
|
||||
@@ -82,16 +85,15 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
|
||||
public static void processCreativeCycling(InventoryPlayer inventory) {
|
||||
if (NEIClientConfig.invCreativeMode() && NEIClientUtils.controlKey()) {
|
||||
if (selectedItem != inventory.currentItem) {
|
||||
if (inventory.currentItem == selectedItem + 1
|
||||
|| (inventory.currentItem == 0 && selectedItem == 8)) // foward
|
||||
if (inventory.currentItem == selectedItem + 1 || (inventory.currentItem == 0 && selectedItem == 8)) // foward
|
||||
{
|
||||
NEICPH.sendCreativeScroll(1);
|
||||
inventory.currentItem = selectedItem;
|
||||
} else if (inventory.currentItem == selectedItem - 1
|
||||
|| (inventory.currentItem == 8 && selectedItem == 0)) {
|
||||
NEICPH.sendCreativeScroll(-1);
|
||||
inventory.currentItem = selectedItem;
|
||||
}
|
||||
NEICPH.sendCreativeScroll(-1);
|
||||
inventory.currentItem = selectedItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,8 +108,8 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleSlotClick(
|
||||
GuiContainer gui, int slotIndex, int button, Slot slot, int modifier, boolean eventconsumed) {
|
||||
public boolean handleSlotClick(GuiContainer gui, int slotIndex, int button, Slot slot, int modifier,
|
||||
boolean eventconsumed) {
|
||||
if (eventconsumed || !NEIClientConfig.isEnabled() || isSpreading(gui)) return eventconsumed;
|
||||
|
||||
if (deleteMode && slotIndex >= 0 && slot != null) {
|
||||
@@ -123,12 +125,12 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
|
||||
if (button == 1 && slot instanceof SlotCrafting) // right click
|
||||
{
|
||||
for (int i1 = 0; i1 < 64; i1++) // click this slot 64 times
|
||||
manager.handleSlotClick(slot.slotNumber, button, 0);
|
||||
manager.handleSlotClick(slot.slotNumber, button, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NEIClientUtils.controlKey()
|
||||
&& modifier != 4 // Drop key pressed: net.minecraft.client.gui.inventory.GuiContainer.keyTyped
|
||||
if (NEIClientUtils.controlKey() && modifier != 4 // Drop key pressed:
|
||||
// net.minecraft.client.gui.inventory.GuiContainer.keyTyped
|
||||
&& slot != null
|
||||
&& slot.getStack() != null
|
||||
&& slot.isItemValid(slot.getStack())) {
|
||||
@@ -138,8 +140,7 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
|
||||
|
||||
if (GuiInfo.hasCustomSlots(gui)) return false;
|
||||
|
||||
if (slotIndex >= 0
|
||||
&& NEIClientUtils.shiftKey()
|
||||
if (slotIndex >= 0 && NEIClientUtils.shiftKey()
|
||||
&& NEIClientUtils.getHeldItem() != null
|
||||
&& !slot.getHasStack()) {
|
||||
ItemStack held = NEIClientUtils.getHeldItem();
|
||||
@@ -167,8 +168,7 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
|
||||
if (firstheld != nowHeld) pickedUpFromSlot = slotIndex;
|
||||
|
||||
if (NEIClientConfig.canPerformAction("item") && NEIClientConfig.hasSMPCounterPart()) {
|
||||
if (heldStackInfinite != null
|
||||
&& slot != null
|
||||
if (heldStackInfinite != null && slot != null
|
||||
&& slot.inventory == NEIClientUtils.mc().thePlayer.inventory) {
|
||||
ItemStack stack = slot.getStack();
|
||||
if (stack != null) {
|
||||
@@ -214,9 +214,9 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) {
|
||||
if (!NEIClientConfig.isEnabled()
|
||||
|| GuiInfo.hasCustomSlots(gui)
|
||||
|| !NEIClientConfig.isMouseScrollTransferEnabled()) return false;
|
||||
if (!NEIClientConfig.isEnabled() || GuiInfo.hasCustomSlots(gui)
|
||||
|| !NEIClientConfig.isMouseScrollTransferEnabled())
|
||||
return false;
|
||||
|
||||
// slot in GuiRecipe does not contain actual stack
|
||||
// and scroll should be handled by GuiRecipe, not here
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.gui.inventory.GuiContainerCreative;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
|
||||
public class NEICreativeGuiHandler extends INEIGuiAdapter {
|
||||
|
||||
@Override
|
||||
public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility) {
|
||||
if (!(gui instanceof GuiContainerCreative)) return currentVisibility;
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.inventory.ContainerExtended;
|
||||
import codechicken.lib.inventory.SlotDummy;
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.lib.inventory.ContainerExtended;
|
||||
import codechicken.lib.inventory.SlotDummy;
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
|
||||
public class NEIDummySlotHandler extends INEIGuiAdapter {
|
||||
|
||||
@Override
|
||||
public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) {
|
||||
Slot slot = gui.getSlotAtPosition(mousex, mousey);
|
||||
if (slot instanceof SlotDummy
|
||||
&& slot.isItemValid(draggedStack)
|
||||
if (slot instanceof SlotDummy && slot.isItemValid(draggedStack)
|
||||
&& gui.inventorySlots instanceof ContainerExtended) {
|
||||
((SlotDummy) slot).slotClick(draggedStack, button, NEIClientUtils.shiftKey());
|
||||
NEICPH.sendDummySlotSet(slot.slotNumber, slot.getStack());
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
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;
|
||||
@@ -16,19 +27,19 @@ import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModMetadata;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLInterModComms;
|
||||
import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
|
||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.VersionParser;
|
||||
import cpw.mods.fml.common.versioning.VersionRange;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
public class NEIModContainer extends DummyModContainer {
|
||||
|
||||
public static LinkedList<IConfigureNEI> plugins = new LinkedList<>();
|
||||
|
||||
private static boolean gregTech5Loaded;
|
||||
private static boolean gtnhLibLoaded;
|
||||
|
||||
public NEIModContainer() {
|
||||
super(getModMetadata());
|
||||
@@ -37,13 +48,12 @@ public class NEIModContainer extends DummyModContainer {
|
||||
|
||||
private static ModMetadata getModMetadata() {
|
||||
final ModMetadata modMetadata = new ModMetadata();
|
||||
modMetadata.name = "GRADLETOKEN_MODNAME";
|
||||
modMetadata.modId = "GRADLETOKEN_MODID";
|
||||
modMetadata.version = "GRADLETOKEN_VERSION";
|
||||
modMetadata.name = "NotEnoughItems";
|
||||
modMetadata.modId = "NotEnoughItems";
|
||||
modMetadata.version = Tags.VERSION;
|
||||
modMetadata.authorList = Arrays.asList("ChickenBones", "mitchej123");
|
||||
modMetadata.url = "https://github.com/GTNewHorizons/NotEnoughItems";
|
||||
modMetadata.description =
|
||||
"Recipe Viewer, Inventory Manager, Item Spawner, Cheats and more; GTNH Version includes many enhancements.";
|
||||
modMetadata.description = "Recipe Viewer, Inventory Manager, Item Spawner, Cheats and more; GTNH Version includes many enhancements.";
|
||||
return modMetadata;
|
||||
}
|
||||
|
||||
@@ -51,16 +61,23 @@ public class NEIModContainer extends DummyModContainer {
|
||||
return gregTech5Loaded;
|
||||
}
|
||||
|
||||
public static boolean isGTNHLibLoaded() {
|
||||
return gtnhLibLoaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ArtifactVersion> getRequirements() {
|
||||
Set<ArtifactVersion> deps = new HashSet<>();
|
||||
deps.add(VersionParser.parseVersionReference("CodeChickenCore@[" + CodeChickenCorePlugin.version + ",)"));
|
||||
deps.add(VersionParser.parseVersionReference("CodeChickenCore@[" + codechicken.core.asm.Tags.VERSION + ",)"));
|
||||
return deps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ArtifactVersion> getDependencies() {
|
||||
return new LinkedList<>(getRequirements());
|
||||
List<ArtifactVersion> deps = new ArrayList<>();
|
||||
deps.add(VersionParser.parseVersionReference("CodeChickenCore@[" + codechicken.core.asm.Tags.VERSION + ",)"));
|
||||
deps.add(VersionParser.parseVersionReference("gtnhlib@[0.6.0,)"));
|
||||
return deps;
|
||||
}
|
||||
|
||||
private String description;
|
||||
@@ -98,6 +115,7 @@ public class NEIModContainer extends DummyModContainer {
|
||||
@Subscribe
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
gregTech5Loaded = Loader.isModLoaded("gregtech") && !Loader.isModLoaded("gregapi_post");
|
||||
gtnhLibLoaded = Loader.isModLoaded("gtnhlib");
|
||||
if (CommonUtils.isClient()) ClientHandler.preInit();
|
||||
}
|
||||
|
||||
@@ -111,11 +129,19 @@ public class NEIModContainer extends DummyModContainer {
|
||||
@Subscribe
|
||||
public void postInit(FMLPostInitializationEvent event) {
|
||||
if (CommonUtils.isClient()) {
|
||||
GuiRecipeTab.loadHandlerInfo();
|
||||
ClientHandler.postInit();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void loadComplete(FMLLoadCompleteEvent event) {
|
||||
if (CommonUtils.isClient()) {
|
||||
GuiRecipeTab.loadHandlerInfo();
|
||||
ClientHandler.loadPluginsList();
|
||||
ClientHandler.loadHandlerOrdering();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleIMCMessages(FMLInterModComms.IMCEvent event) {
|
||||
IMCHandler.processIMC(event.getMessages());
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
import java.util.Collection;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.InventoryEffectRenderer;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.INEIGuiAdapter;
|
||||
|
||||
/**
|
||||
* Inspired by InventoryEffectRendererGuiHandler.java in JEI
|
||||
*/
|
||||
public class NEIPotionGuiHandler extends INEIGuiAdapter {
|
||||
|
||||
@Override
|
||||
public boolean hideItemPanelSlot(GuiContainer guiContainer, int slotX, int slotY, int slotW, int slotH) {
|
||||
if (NEIClientConfig.ignorePotionOverlap()) {
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.core.ServerUtils;
|
||||
import codechicken.lib.inventory.SlotDummy;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.lib.packet.PacketCustom.IServerPacketHandler;
|
||||
import codechicken.lib.vec.BlockCoord;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import static codechicken.nei.PacketIDs.C2S;
|
||||
import static codechicken.nei.PacketIDs.S2C;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.inventory.InventoryBasic;
|
||||
@@ -19,64 +16,76 @@ import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityMobSpawner;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.core.ServerUtils;
|
||||
import codechicken.lib.inventory.SlotDummy;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.lib.packet.PacketCustom.IServerPacketHandler;
|
||||
import codechicken.lib.vec.BlockCoord;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
|
||||
public class NEISPH implements IServerPacketHandler {
|
||||
|
||||
@Override
|
||||
public void handlePacket(PacketCustom packet, EntityPlayerMP sender, INetHandlerPlayServer netHandler) {
|
||||
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 21:
|
||||
case C2S.REQUEST_CONTAINER:
|
||||
handleRequestContainer(sender, packet.readInt());
|
||||
break;
|
||||
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;
|
||||
}
|
||||
@@ -99,6 +108,11 @@ public class NEISPH implements IServerPacketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRequestContainer(EntityPlayerMP sender, int containerSize) {
|
||||
if (sender.openContainer.getInventory().size() != containerSize) return;
|
||||
sender.sendContainerToPlayer(sender.openContainer);
|
||||
}
|
||||
|
||||
private void handlePropertyChange(EntityPlayerMP sender, PacketCustom packet) {
|
||||
String name = packet.readString();
|
||||
if (NEIServerConfig.canPlayerPerformAction(sender.getCommandSenderName(), name))
|
||||
@@ -112,16 +126,17 @@ public class NEISPH implements IServerPacketHandler {
|
||||
new ContainerCreativeInv(
|
||||
sender,
|
||||
new ExtendedCreativeInv(
|
||||
NEIServerConfig.forPlayer(sender.getCommandSenderName()), Side.SERVER)),
|
||||
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);
|
||||
}
|
||||
@@ -157,7 +172,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);
|
||||
});
|
||||
@@ -167,18 +182,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) {
|
||||
@@ -197,7 +213,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);
|
||||
@@ -216,7 +232,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));
|
||||
|
||||
@@ -224,7 +240,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);
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.core.ServerUtils;
|
||||
import codechicken.lib.config.ConfigFile;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.PrintWriter;
|
||||
@@ -16,6 +11,7 @@ import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -25,11 +21,20 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.core.ServerUtils;
|
||||
import codechicken.lib.config.ConfigFile;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
|
||||
public class NEIServerConfig {
|
||||
|
||||
private static MinecraftServer server;
|
||||
|
||||
public static Logger logger = LogManager.getLogger("NotEnoughItems");
|
||||
@@ -73,8 +78,7 @@ public class NEIServerConfig {
|
||||
|
||||
serverConfig.setNewLineMode(1);
|
||||
serverConfig.getTag("permissions").useBraces();
|
||||
serverConfig
|
||||
.getTag("permissions")
|
||||
serverConfig.getTag("permissions")
|
||||
.setComment("List of players who can use these features.\nEg. time=CodeChicken, Friend1");
|
||||
|
||||
setDefaultFeature("time");
|
||||
@@ -93,7 +97,7 @@ public class NEIServerConfig {
|
||||
}
|
||||
|
||||
private static void setDefaultFeature(String featurename, String... names) {
|
||||
if (names.length == 0) names = new String[] {"OP"};
|
||||
if (names.length == 0) names = new String[] { "OP" };
|
||||
|
||||
StringBuilder list = new StringBuilder();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
@@ -105,7 +109,11 @@ public class NEIServerConfig {
|
||||
|
||||
private static void saveWorld(int dim) {
|
||||
try {
|
||||
File file = new File(getSaveDir(DimensionManager.getWorld(dim)), "world.dat");
|
||||
final File saveDir = getSaveDir(DimensionManager.getWorld(dim));
|
||||
if (!saveDir.isDirectory()) {
|
||||
FileUtils.forceMkdir(saveDir);
|
||||
}
|
||||
File file = new File(saveDir, "world.dat");
|
||||
NEIServerUtils.writeNBT(dimTags.get(dim), file);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -189,7 +197,7 @@ public class NEIServerConfig {
|
||||
FileReader r = new FileReader(file);
|
||||
int line = 0;
|
||||
for (String s : IOUtils.readLines(r)) {
|
||||
if (s.charAt(0) == '#' || s.trim().length() == 0) continue;
|
||||
if (s.charAt(0) == '#' || s.trim().isEmpty()) continue;
|
||||
int delim = s.lastIndexOf('=');
|
||||
if (delim < 0) {
|
||||
logger.error("line " + line + ": Missing =");
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.core.ServerUtils;
|
||||
import codechicken.lib.inventory.InventoryRange;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.nei.util.NBTHelper;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -19,6 +11,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.enchantment.Enchantment;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
@@ -41,9 +34,21 @@ import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.WorldSettings.GameType;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
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;
|
||||
|
||||
public class NEIServerUtils {
|
||||
|
||||
public static boolean isRaining(World world) {
|
||||
return world.getWorldInfo().isRaining();
|
||||
}
|
||||
@@ -51,7 +56,7 @@ public class NEIServerUtils {
|
||||
public static void toggleRaining(World world, boolean notify) {
|
||||
boolean raining = !world.isRaining();
|
||||
if (!raining) // turn off
|
||||
((WorldServer) world).provider.resetRainAndThunder();
|
||||
((WorldServer) world).provider.resetRainAndThunder();
|
||||
else world.getWorldInfo().setRaining(!isRaining(world));
|
||||
|
||||
if (notify)
|
||||
@@ -84,9 +89,8 @@ public class NEIServerUtils {
|
||||
else return player.inventory.getStackInSlot(slot);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void deleteAllItems(EntityPlayerMP player) {
|
||||
for (Slot slot : (List<Slot>) player.openContainer.inventorySlots) slot.putStack(null);
|
||||
for (Slot slot : player.openContainer.inventorySlots) slot.putStack(null);
|
||||
|
||||
player.sendContainerAndContentsToPlayer(player.openContainer, player.openContainer.getInventory());
|
||||
}
|
||||
@@ -114,17 +118,18 @@ public class NEIServerUtils {
|
||||
}
|
||||
|
||||
public static void sendNotice(ICommandSender sender, IChatComponent msg, String permission) {
|
||||
ChatComponentTranslation notice =
|
||||
new ChatComponentTranslation("chat.type.admin", sender.getCommandSenderName(), msg.createCopy());
|
||||
ChatComponentTranslation notice = new ChatComponentTranslation(
|
||||
"chat.type.admin",
|
||||
sender.getCommandSenderName(),
|
||||
msg.createCopy());
|
||||
notice.getChatStyle().setColor(EnumChatFormatting.GRAY).setItalic(true);
|
||||
|
||||
if (NEIServerConfig.canPlayerPerformAction("CONSOLE", permission))
|
||||
MinecraftServer.getServer().addChatMessage(notice);
|
||||
|
||||
for (EntityPlayer p : ServerUtils.getPlayers())
|
||||
if (p == sender) p.addChatComponentMessage(msg);
|
||||
else if (NEIServerConfig.canPlayerPerformAction(p.getCommandSenderName(), permission))
|
||||
p.addChatComponentMessage(notice);
|
||||
for (EntityPlayer p : ServerUtils.getPlayers()) if (p == sender) p.addChatComponentMessage(msg);
|
||||
else if (NEIServerConfig.canPlayerPerformAction(p.getCommandSenderName(), permission))
|
||||
p.addChatComponentMessage(notice);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,8 +138,7 @@ public class NEIServerUtils {
|
||||
* @return whether the two items are the same in terms of damage and itemID.
|
||||
*/
|
||||
public static boolean areStacksSameType(ItemStack stack1, ItemStack stack2) {
|
||||
return stack1 != null
|
||||
&& stack2 != null
|
||||
return stack1 != null && stack2 != null
|
||||
&& (stack1.getItem() == stack2.getItem()
|
||||
&& (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage())
|
||||
&& ItemStack.areItemStackTagsEqual(stack2, stack1));
|
||||
@@ -142,28 +146,28 @@ public class NEIServerUtils {
|
||||
|
||||
/**
|
||||
* NBT-friendly version of {@link #areStacksSameType(ItemStack, ItemStack)}
|
||||
*
|
||||
* @param stack1 The {@link ItemStack} being compared.
|
||||
* @param stack2 The {@link ItemStack} to compare to.
|
||||
* @return whether the two items are the same in terms of itemID, damage and NBT.
|
||||
*/
|
||||
public static boolean areStacksSameTypeWithNBT(ItemStack stack1, ItemStack stack2) {
|
||||
return stack1 != null
|
||||
&& stack2 != null
|
||||
return stack1 != null && stack2 != null
|
||||
&& stack1.getItem() == stack2.getItem()
|
||||
&& (!stack2.getHasSubtypes() || stack2.getItemDamage() == stack1.getItemDamage())
|
||||
&& NBTHelper.matchTag(stack1.getTagCompound(), stack2.getTagCompound());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ItemStack}s with damage -1 are wildcards allowing all damages. Eg all colours of wool are allowed to create Beds.
|
||||
* {@link ItemStack}s with damage -1 are wildcards allowing all damages. Eg all colours of wool are allowed to
|
||||
* create Beds.
|
||||
*
|
||||
* @param stack1 The {@link ItemStack} being compared.
|
||||
* @param stack2 The {@link ItemStack} to compare to.
|
||||
* @return whether the two items are the same from the perspective of a crafting inventory.
|
||||
*/
|
||||
public static boolean areStacksSameTypeCrafting(ItemStack stack1, ItemStack stack2) {
|
||||
return stack1 != null
|
||||
&& stack2 != null
|
||||
return stack1 != null && stack2 != null
|
||||
&& stack1.getItem() == stack2.getItem()
|
||||
&& (stack1.getItemDamage() == stack2.getItemDamage()
|
||||
|| stack1.getItemDamage() == OreDictionary.WILDCARD_VALUE
|
||||
@@ -173,13 +177,13 @@ public class NEIServerUtils {
|
||||
|
||||
/**
|
||||
* NBT-friendly version of {@link #areStacksSameTypeCrafting(ItemStack, ItemStack)}
|
||||
*
|
||||
* @param stack1 The {@link ItemStack} being compared.
|
||||
* @param stack2 The {@link ItemStack} to compare to.
|
||||
* @return whether the two items are the same from the perspective of a crafting inventory.
|
||||
*/
|
||||
public static boolean areStacksSameTypeCraftingWithNBT(ItemStack stack1, ItemStack stack2) {
|
||||
return stack1 != null
|
||||
&& stack2 != null
|
||||
return stack1 != null && stack2 != null
|
||||
&& stack1.getItem() == stack2.getItem()
|
||||
&& (stack1.getItemDamage() == stack2.getItemDamage()
|
||||
|| stack1.getItemDamage() == OreDictionary.WILDCARD_VALUE
|
||||
@@ -276,24 +280,22 @@ public class NEIServerUtils {
|
||||
}
|
||||
|
||||
public static void setGamemode(EntityPlayerMP player, int mode) {
|
||||
if (mode < 0
|
||||
|| mode >= NEIActions.gameModes.length
|
||||
|| NEIActions.nameActionMap.containsKey(NEIActions.gameModes[mode])
|
||||
&& !NEIServerConfig.canPlayerPerformAction(
|
||||
player.getCommandSenderName(), NEIActions.gameModes[mode])) return;
|
||||
if (mode < 0 || mode >= NEIActions.gameModes.length
|
||||
|| NEIActions.nameActionMap.containsKey(NEIActions.gameModes[mode]) && !NEIServerConfig
|
||||
.canPlayerPerformAction(player.getCommandSenderName(), NEIActions.gameModes[mode]))
|
||||
return;
|
||||
|
||||
// creative+
|
||||
NEIServerConfig.forPlayer(player.getCommandSenderName()).enableAction("creative+", mode == 2);
|
||||
if (mode == 2
|
||||
&& !(player.openContainer
|
||||
instanceof ContainerCreativeInv)) // open the container immediately for the client
|
||||
NEISPH.processCreativeInv(player, true);
|
||||
if (mode == 2 && !(player.openContainer instanceof ContainerCreativeInv)) // open the container immediately for
|
||||
// the client
|
||||
NEISPH.processCreativeInv(player, true);
|
||||
|
||||
// change it on the server
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -331,11 +333,10 @@ public class NEIServerUtils {
|
||||
ArrayList<int[]> arraylist = new ArrayList<>();
|
||||
if (itemstack != null) {
|
||||
NBTTagList nbttaglist = itemstack.getEnchantmentTagList();
|
||||
if (nbttaglist != null)
|
||||
for (int i = 0; i < nbttaglist.tagCount(); i++) {
|
||||
NBTTagCompound tag = nbttaglist.getCompoundTagAt(i);
|
||||
arraylist.add(new int[] {tag.getShort("id"), tag.getShort("lvl")});
|
||||
}
|
||||
if (nbttaglist != null) for (int i = 0; i < nbttaglist.tagCount(); i++) {
|
||||
NBTTagCompound tag = nbttaglist.getCompoundTagAt(i);
|
||||
arraylist.add(new int[] { tag.getShort("id"), tag.getShort("lvl") });
|
||||
}
|
||||
}
|
||||
return arraylist;
|
||||
}
|
||||
@@ -368,7 +369,7 @@ public class NEIServerUtils {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static ItemStack[] extractRecipeItems(Object obj) {
|
||||
if (obj instanceof ItemStack) return new ItemStack[] {(ItemStack) obj};
|
||||
if (obj instanceof ItemStack) return new ItemStack[] { (ItemStack) obj };
|
||||
if (obj instanceof ItemStack[]) return (ItemStack[]) obj;
|
||||
if (obj instanceof List) return ((List<ItemStack>) obj).toArray(new ItemStack[0]);
|
||||
|
||||
@@ -377,6 +378,7 @@ public class NEIServerUtils {
|
||||
|
||||
public static List<Integer> getRange(final int start, final int end) {
|
||||
return new AbstractList<Integer>() {
|
||||
|
||||
@Override
|
||||
public Integer get(int index) {
|
||||
return start + index;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.nei.api.IStackPositioner;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import codechicken.nei.api.IStackPositioner;
|
||||
|
||||
public class OffsetPositioner implements IStackPositioner {
|
||||
|
||||
public OffsetPositioner(int x, int y) {
|
||||
offsetx = x;
|
||||
offsety = y;
|
||||
|
||||
@@ -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,18 +1,23 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.GuiUsageRecipe;
|
||||
import java.util.ArrayList;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
public abstract class PanelWidget extends Widget {
|
||||
public abstract class PanelWidget extends Widget implements IContainerTooltipHandler {
|
||||
|
||||
protected static final int PADDING = 2;
|
||||
|
||||
public ItemStack draggedStack;
|
||||
@@ -36,12 +41,16 @@ public abstract class PanelWidget extends Widget {
|
||||
pageLabel = new Label("0/0", true);
|
||||
|
||||
pagePrev = new Button("Prev") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
|
||||
if (rightclick) {
|
||||
grid.setPage(0);
|
||||
} else {
|
||||
grid.shiftPage(-1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,12 +59,16 @@ public abstract class PanelWidget extends Widget {
|
||||
}
|
||||
};
|
||||
pageNext = new Button("Next") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
|
||||
if (rightclick) {
|
||||
grid.setPage(grid.getNumPages() - 1);
|
||||
} else {
|
||||
grid.shiftPage(1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,21 +91,24 @@ public abstract class PanelWidget extends Widget {
|
||||
public abstract int getHeight(GuiContainer gui);
|
||||
|
||||
public void resize(GuiContainer gui) {
|
||||
final Rectangle4i margin =
|
||||
new Rectangle4i(getMarginLeft(gui), getMarginTop(gui), getWidth(gui), getHeight(gui));
|
||||
final Rectangle4i margin = new Rectangle4i(
|
||||
getMarginLeft(gui),
|
||||
getMarginTop(gui),
|
||||
getWidth(gui),
|
||||
getHeight(gui));
|
||||
|
||||
final int minWidth = 5 * ItemsGrid.SLOT_SIZE;
|
||||
final int minHeight = 9 * ItemsGrid.SLOT_SIZE;
|
||||
|
||||
final String settingName = getPositioningSettingName();
|
||||
int paddingLeft = (int) Math.ceil(
|
||||
margin.w * NEIClientConfig.getSetting(settingName + ".left").getIntValue() / 100000.0);
|
||||
int paddingTop = (int) Math.ceil(
|
||||
margin.h * NEIClientConfig.getSetting(settingName + ".top").getIntValue() / 100000.0);
|
||||
int paddingRight = (int) Math.ceil(
|
||||
margin.w * NEIClientConfig.getSetting(settingName + ".right").getIntValue() / 100000.0);
|
||||
int paddingBottom = (int) Math.ceil(
|
||||
margin.h * NEIClientConfig.getSetting(settingName + ".bottom").getIntValue() / 100000.0);
|
||||
int paddingLeft = (int) Math
|
||||
.ceil(margin.w * NEIClientConfig.getSetting(settingName + ".left").getIntValue() / 100000.0);
|
||||
int paddingTop = (int) Math
|
||||
.ceil(margin.h * NEIClientConfig.getSetting(settingName + ".top").getIntValue() / 100000.0);
|
||||
int paddingRight = (int) Math
|
||||
.ceil(margin.w * NEIClientConfig.getSetting(settingName + ".right").getIntValue() / 100000.0);
|
||||
int paddingBottom = (int) Math
|
||||
.ceil(margin.h * NEIClientConfig.getSetting(settingName + ".bottom").getIntValue() / 100000.0);
|
||||
|
||||
int deltaHeight = Math.min(0, margin.h - paddingTop - paddingBottom - minHeight) / 2;
|
||||
|
||||
@@ -118,20 +134,19 @@ public abstract class PanelWidget extends Widget {
|
||||
int paddingLeft = 0;
|
||||
int paddingRight = 0;
|
||||
|
||||
while (paddingLeft < w
|
||||
&& GuiInfo.hideItemPanelSlot(
|
||||
gui, new Rectangle4i(x + paddingLeft, y, ItemsGrid.SLOT_SIZE, ItemsGrid.SLOT_SIZE))) {
|
||||
while (paddingLeft < w && GuiInfo.hideItemPanelSlot(
|
||||
gui,
|
||||
new Rectangle4i(x + paddingLeft, y, ItemsGrid.SLOT_SIZE, ItemsGrid.SLOT_SIZE))) {
|
||||
paddingLeft += ItemsGrid.SLOT_SIZE;
|
||||
}
|
||||
|
||||
while (paddingRight < w
|
||||
&& GuiInfo.hideItemPanelSlot(
|
||||
gui,
|
||||
new Rectangle4i(
|
||||
x + w - paddingRight - ItemsGrid.SLOT_SIZE,
|
||||
y,
|
||||
ItemsGrid.SLOT_SIZE,
|
||||
ItemsGrid.SLOT_SIZE))) {
|
||||
while (paddingRight < w && GuiInfo.hideItemPanelSlot(
|
||||
gui,
|
||||
new Rectangle4i(
|
||||
x + w - paddingRight - ItemsGrid.SLOT_SIZE,
|
||||
y,
|
||||
ItemsGrid.SLOT_SIZE,
|
||||
ItemsGrid.SLOT_SIZE))) {
|
||||
paddingRight += ItemsGrid.SLOT_SIZE;
|
||||
}
|
||||
|
||||
@@ -156,13 +171,19 @@ public abstract class PanelWidget extends Widget {
|
||||
protected abstract int resizeFooter(GuiContainer gui);
|
||||
|
||||
public void setVisible() {
|
||||
if (grid.getPerPage() > 0) {
|
||||
if (grid.getPerPage() > 0 && !grid.isEmpty()) {
|
||||
LayoutManager.addWidget(pagePrev);
|
||||
LayoutManager.addWidget(pageNext);
|
||||
LayoutManager.addWidget(pageLabel);
|
||||
grid.setVisible();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
grid.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
grid.draw(mousex, mousey);
|
||||
@@ -179,11 +200,13 @@ public abstract class PanelWidget extends Widget {
|
||||
|
||||
@Override
|
||||
public void mouseDragged(int mousex, int mousey, int button, long heldTime) {
|
||||
if (mouseDownSlot >= 0
|
||||
&& draggedStack == null
|
||||
if (mouseDownSlot >= grid.realItems.size()) {
|
||||
mouseDownSlot = -1;
|
||||
}
|
||||
|
||||
if (mouseDownSlot >= 0 && draggedStack == null
|
||||
&& NEIClientUtils.getHeldItem() == null
|
||||
&& NEIClientConfig.hasSMPCounterPart()
|
||||
&& !GuiInfo.hasCustomSlots(NEIClientUtils.getGuiContainer())) {
|
||||
&& NEIClientConfig.hasSMPCounterPart()) {
|
||||
ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500) {
|
||||
@@ -197,28 +220,8 @@ public abstract class PanelWidget extends Widget {
|
||||
|
||||
@Override
|
||||
public boolean handleClick(int mousex, int mousey, int button) {
|
||||
|
||||
if (handleClickExt(mousex, mousey, button)) return true;
|
||||
|
||||
if (NEIClientUtils.getHeldItem() != null) {
|
||||
|
||||
if (!grid.contains(mousex, mousey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) {
|
||||
if (button == 1) {
|
||||
NEIClientUtils.decreaseSlotStack(-999);
|
||||
} else {
|
||||
NEIClientUtils.deleteHeldItem();
|
||||
}
|
||||
} else {
|
||||
NEIClientUtils.dropHeldItem();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
if (hoverSlot != null) {
|
||||
|
||||
@@ -240,6 +243,13 @@ public abstract class PanelWidget extends Widget {
|
||||
|
||||
@Override
|
||||
public boolean handleClickExt(int mouseX, int mouseY, int button) {
|
||||
|
||||
if (ItemPanels.itemPanel.draggedStack != null && ItemPanels.bookmarkPanel.contains(mouseX, mouseY)) {
|
||||
ItemPanels.bookmarkPanel.addOrRemoveItem(ItemPanels.itemPanel.draggedStack, null, null, false, true);
|
||||
ItemPanels.itemPanel.draggedStack = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ItemPanels.itemPanel.draggedStack != null) {
|
||||
return ItemPanels.itemPanel.handleDraggedClick(mouseX, mouseY, button);
|
||||
}
|
||||
@@ -271,8 +281,7 @@ public abstract class PanelWidget extends Widget {
|
||||
}
|
||||
|
||||
final GuiContainer gui = NEIClientUtils.getGuiContainer();
|
||||
if (mouseX < gui.guiLeft
|
||||
|| mouseY < gui.guiTop
|
||||
if (mouseX < gui.guiLeft || mouseY < gui.guiTop
|
||||
|| mouseX >= gui.guiLeft + gui.xSize
|
||||
|| mouseY >= gui.guiTop + gui.ySize) {
|
||||
draggedStack = null;
|
||||
@@ -289,9 +298,6 @@ public abstract class PanelWidget extends Widget {
|
||||
GuiInfo.readLock.lock();
|
||||
for (INEIGuiHandler handler : GuiInfo.guiHandlers) {
|
||||
if (handler.handleDragNDrop(gui, mouseX, mouseY, draggedStack, button)) {
|
||||
|
||||
NEIClientConfig.logger.info(handler);
|
||||
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
@@ -308,9 +314,10 @@ public abstract class PanelWidget extends Widget {
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && draggedStack == null) {
|
||||
ItemStack item = hoverSlot.item;
|
||||
ItemStack item = hoverSlot.item.copy();
|
||||
|
||||
if (NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canCheatItem(item)) {
|
||||
if (NEIController.manager.window instanceof GuiRecipe || NEIClientUtils.shiftKey()
|
||||
|| !NEIClientConfig.canCheatItem(item)) {
|
||||
|
||||
if (button == 0) {
|
||||
GuiCraftingRecipe.openRecipeGui("item", item);
|
||||
@@ -374,4 +381,21 @@ public abstract class PanelWidget extends Widget {
|
||||
public boolean contains(int px, int py) {
|
||||
return grid.contains(px, py);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.core.ServerUtils;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import java.io.File;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
|
||||
import codechicken.core.ServerUtils;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
|
||||
public class PlayerSave {
|
||||
|
||||
public String username;
|
||||
|
||||
private File saveFile;
|
||||
|
||||
@@ -2,10 +2,12 @@ package codechicken.nei;
|
||||
|
||||
import static codechicken.nei.NEIClientConfig.canPerformAction;
|
||||
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
|
||||
public class PopupInputHandler implements IContainerInputHandler {
|
||||
|
||||
@Override
|
||||
public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
return false;
|
||||
|
||||
@@ -1,17 +1,25 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import codechicken.nei.ItemList.AllMultiItemFilter;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
|
||||
/**
|
||||
* Simply an {@link ItemStack} with position.
|
||||
* Mainly used in the recipe handlers.
|
||||
* Simply an {@link ItemStack} with position. Mainly used in the recipe handlers.
|
||||
*/
|
||||
public class PositionedStack {
|
||||
|
||||
public int relx;
|
||||
public int rely;
|
||||
public ItemStack[] items;
|
||||
@@ -25,8 +33,11 @@ public class PositionedStack {
|
||||
relx = x;
|
||||
rely = y;
|
||||
|
||||
if (genPerms) generatePermutations();
|
||||
else setPermutationToRender(0);
|
||||
if (genPerms) {
|
||||
generatePermutations();
|
||||
} else {
|
||||
setPermutationToRender(0);
|
||||
}
|
||||
}
|
||||
|
||||
public PositionedStack(Object object, int x, int y) {
|
||||
@@ -36,14 +47,18 @@ public class PositionedStack {
|
||||
public void generatePermutations() {
|
||||
if (permutated) return;
|
||||
|
||||
ArrayList<ItemStack> stacks = new ArrayList<>();
|
||||
List<ItemStack> stacks = new ArrayList<>();
|
||||
for (ItemStack item : items) {
|
||||
if (item == null || item.getItem() == null) continue;
|
||||
|
||||
if (item.getItemDamage() == Short.MAX_VALUE) {
|
||||
List<ItemStack> permutations = ItemList.itemMap.get(item.getItem());
|
||||
if (!permutations.isEmpty()) {
|
||||
for (ItemStack stack : permutations) stacks.add(stack.copy());
|
||||
for (ItemStack stack : permutations) {
|
||||
ItemStack toAdd = stack.copy();
|
||||
toAdd.stackSize = item.stackSize;
|
||||
stacks.add(toAdd);
|
||||
}
|
||||
} else {
|
||||
ItemStack base = new ItemStack(item.getItem(), item.stackSize);
|
||||
base.stackTagCompound = item.stackTagCompound;
|
||||
@@ -56,7 +71,7 @@ public class PositionedStack {
|
||||
}
|
||||
items = stacks.toArray(new ItemStack[0]);
|
||||
|
||||
if (items.length == 0) items = new ItemStack[] {new ItemStack(Blocks.fire)};
|
||||
if (items.length == 0) items = new ItemStack[] { new ItemStack(Blocks.fire) };
|
||||
|
||||
permutated = true;
|
||||
setPermutationToRender(0);
|
||||
@@ -67,15 +82,60 @@ public class PositionedStack {
|
||||
}
|
||||
|
||||
public PositionedStack copy() {
|
||||
return new PositionedStack(items, relx, rely);
|
||||
PositionedStack pStack = new PositionedStack(Arrays.asList(items), relx, rely, false);
|
||||
pStack.permutated = this.permutated;
|
||||
return pStack;
|
||||
}
|
||||
|
||||
public List<ItemStack> getFilteredPermutations() {
|
||||
return getFilteredPermutations(null);
|
||||
}
|
||||
|
||||
public List<ItemStack> getFilteredPermutations(ItemFilter additionalFilter) {
|
||||
List<ItemStack> items = Arrays.asList(this.items).stream().filter(getItemFilter(additionalFilter)::matches)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (items.isEmpty()) {
|
||||
items.addAll(
|
||||
Arrays.asList(this.items).stream().filter(item -> !ItemInfo.isHidden(item))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
if (items.isEmpty()) {
|
||||
items.addAll(Arrays.asList(this.items));
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private ItemFilter getItemFilter(ItemFilter additionalFilter) {
|
||||
return new AllMultiItemFilter(
|
||||
additionalFilter,
|
||||
item -> !ItemInfo.isHidden(item),
|
||||
PresetsList.getItemFilter(),
|
||||
GuiRecipe.getSearchItemFilter());
|
||||
}
|
||||
|
||||
public boolean setPermutationToRender(ItemStack ingredient) {
|
||||
|
||||
for (int index = 0; index < this.items.length; index++) {
|
||||
if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(this.items[index], ingredient)) {
|
||||
setPermutationToRender(index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setPermutationToRender(int index) {
|
||||
item = items[index].copy();
|
||||
if (item.getItem() == null) item = new ItemStack(Blocks.fire);
|
||||
else if (item.getItemDamage() == OreDictionary.WILDCARD_VALUE
|
||||
&& item.getItem() != null
|
||||
&& item.getItem().isRepairable()) item.setItemDamage(0);
|
||||
this.item = this.items[index].copy();
|
||||
|
||||
if (this.item.getItem() == null) {
|
||||
this.item = new ItemStack(Blocks.fire);
|
||||
} else if (this.item.getItemDamage() == OreDictionary.WILDCARD_VALUE && this.item.getItem().isRepairable()) {
|
||||
this.item.setItemDamage(0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(ItemStack ingredient) {
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
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.nei.api.API;
|
||||
import codechicken.nei.api.IRecipeFilter;
|
||||
import codechicken.nei.api.IRecipeFilter.IRecipeFilterProvider;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.NBTJson;
|
||||
|
||||
public class PresetsList {
|
||||
|
||||
public enum PresetMode {
|
||||
HIDE,
|
||||
REMOVE,
|
||||
GROUP;
|
||||
}
|
||||
|
||||
public static class Preset implements ItemFilter {
|
||||
|
||||
public String name = "";
|
||||
public boolean enabled = true;
|
||||
public PresetMode mode = PresetMode.HIDE;
|
||||
public Set<String> items = new HashSet<>();
|
||||
|
||||
public static String getIdentifier(ItemStack stack) {
|
||||
return StackInfo.getItemStackGUID(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return items.contains(Preset.getIdentifier(item));
|
||||
}
|
||||
|
||||
public Preset copy() {
|
||||
Preset preset = new Preset();
|
||||
|
||||
preset.name = name;
|
||||
preset.enabled = enabled;
|
||||
preset.mode = mode;
|
||||
preset.items = new HashSet<>(items);
|
||||
|
||||
return preset;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class RecipesFilter implements IRecipeFilterProvider, IRecipeFilter {
|
||||
|
||||
public Set<String> cache;
|
||||
|
||||
public IRecipeFilter getFilter() {
|
||||
|
||||
if (cache == null) {
|
||||
cache = PresetsList.presets.stream().filter(p -> p.enabled && p.mode == PresetMode.REMOVE)
|
||||
.flatMap(p -> p.items.stream()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
return cache.isEmpty() ? null : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(IRecipeHandler handler, List<PositionedStack> ingredients, PositionedStack result,
|
||||
List<PositionedStack> others) {
|
||||
|
||||
if (matchPositionedStack(ingredients, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result != null && matchPositionedStack(result)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!others.isEmpty() && matchPositionedStack(others, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return result == null && others.isEmpty();
|
||||
}
|
||||
|
||||
private boolean matchPositionedStack(List<PositionedStack> items, boolean dir) {
|
||||
for (PositionedStack pStack : items) {
|
||||
if (matchPositionedStack(pStack) == dir) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchPositionedStack(PositionedStack pStack) {
|
||||
for (ItemStack stack : pStack.items) {
|
||||
if (!cache.contains(Preset.getIdentifier(stack))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class ItemPanelFilter implements ItemFilterProvider, ItemFilter {
|
||||
|
||||
public Set<String> cache;
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
|
||||
if (cache == null) {
|
||||
cache = PresetsList.presets.stream()
|
||||
.filter(p -> p.enabled && (p.mode == PresetMode.HIDE || p.mode == PresetMode.REMOVE))
|
||||
.flatMap(p -> p.items.stream()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
return cache.isEmpty() ? null : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack stack) {
|
||||
return !cache.contains(Preset.getIdentifier(stack));
|
||||
}
|
||||
}
|
||||
|
||||
public static final List<Preset> presets = new ArrayList<>();
|
||||
protected static RecipesFilter recipeFilter = new RecipesFilter();
|
||||
protected static ItemPanelFilter itemFilter = new ItemPanelFilter();
|
||||
|
||||
static {
|
||||
API.addItemFilter(itemFilter);
|
||||
API.addRecipeFilter(recipeFilter);
|
||||
}
|
||||
|
||||
public static ItemFilter getItemFilter() {
|
||||
return itemFilter.getFilter();
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
final File presetsFile = new File(CommonUtils.getMinecraftDir(), "saves/NEI/global/presets.ini");
|
||||
|
||||
if (presetsFile == null || !presetsFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> itemStrings;
|
||||
try (FileInputStream reader = new FileInputStream(presetsFile)) {
|
||||
NEIClientConfig.logger.info("Loading presets from file {}", presetsFile);
|
||||
itemStrings = IOUtils.readLines(reader, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load presets from file {}", presetsFile, e);
|
||||
return;
|
||||
}
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
Preset preset = new Preset();
|
||||
presets.clear();
|
||||
|
||||
for (String itemStr : itemStrings) {
|
||||
|
||||
try {
|
||||
|
||||
if (itemStr.isEmpty()) {
|
||||
itemStr = "; {}";
|
||||
}
|
||||
|
||||
if (itemStr.startsWith("; ")) {
|
||||
JsonObject settings = parser.parse(itemStr.substring(2)).getAsJsonObject();
|
||||
|
||||
if (!preset.items.isEmpty()) {
|
||||
// do not create empty namespaces
|
||||
presets.add(preset);
|
||||
preset = new Preset();
|
||||
}
|
||||
|
||||
if (settings.has("name")) {
|
||||
preset.name = settings.get("name").getAsString();
|
||||
}
|
||||
|
||||
if (settings.has("enabled")) {
|
||||
preset.enabled = settings.get("enabled").getAsBoolean();
|
||||
}
|
||||
|
||||
if (settings.has("mode")) {
|
||||
preset.mode = PresetMode.valueOf(settings.get("mode").getAsString());
|
||||
}
|
||||
|
||||
} else {
|
||||
preset.items.add(itemStr);
|
||||
}
|
||||
|
||||
} catch (IllegalArgumentException | JsonSyntaxException | IllegalStateException e) {
|
||||
NEIClientConfig.logger.error("Failed to load presets ItemStack from json string:\n{}", itemStr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!preset.items.isEmpty()) {
|
||||
presets.add(preset);
|
||||
}
|
||||
}
|
||||
|
||||
public static void savePresets() {
|
||||
final File presetsFile = new File(CommonUtils.getMinecraftDir(), "saves/NEI/global/presets.ini");
|
||||
final List<String> strings = new ArrayList<>();
|
||||
|
||||
for (Preset preset : presets) {
|
||||
JsonObject settings = new JsonObject();
|
||||
|
||||
settings.add("name", new JsonPrimitive(preset.name));
|
||||
settings.add("enabled", new JsonPrimitive(preset.enabled));
|
||||
settings.add("mode", new JsonPrimitive(preset.mode.toString()));
|
||||
|
||||
strings.add("; " + NBTJson.toJson(settings));
|
||||
strings.addAll(preset.items);
|
||||
}
|
||||
|
||||
try (FileOutputStream output = new FileOutputStream(presetsFile)) {
|
||||
IOUtils.writeLines(strings, "\n", output, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Filed to save presets list to file {}", presetsFile, e);
|
||||
}
|
||||
|
||||
recipeFilter.cache = null;
|
||||
itemFilter.cache = null;
|
||||
CollapsibleItems.saveStates();
|
||||
CollapsibleItems.load();
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,920 +0,0 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.nei.NEIClientUtils.translate;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.core.gui.GuiScrollSlot;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
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;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
public class PresetsWidget extends Widget {
|
||||
|
||||
public static class PresetTag implements ItemFilter {
|
||||
public String filename = null;
|
||||
public String displayName = "";
|
||||
public boolean whitelist = true;
|
||||
public HashSet<String> items;
|
||||
|
||||
public PresetTag(String displayName) {
|
||||
this(displayName, new HashSet<>(), false, null);
|
||||
}
|
||||
|
||||
public PresetTag(String displayName, HashSet<String> items) {
|
||||
this(displayName, items, true, null);
|
||||
}
|
||||
|
||||
public PresetTag(String displayName, HashSet<String> items, boolean whitelist, String filename) {
|
||||
this.displayName = displayName;
|
||||
this.items = items != null ? items : new HashSet<>();
|
||||
this.whitelist = whitelist;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public boolean matches(final ItemStack stack) {
|
||||
return items.contains(StackInfo.getItemStackGUID(stack)) == whitelist;
|
||||
}
|
||||
|
||||
public static PresetTag loadFromFile(File file) {
|
||||
if (!file.isFile() || !file.exists() || file.getName().equals("selected.ini")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
List<String> itemStrings;
|
||||
try (FileInputStream input = new FileInputStream(file)) {
|
||||
NEIClientConfig.logger.info("Loading presets from file {}", file);
|
||||
itemStrings = IOUtils.readLines(input, "UTF-8");
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load presets from file {}", file, e);
|
||||
return null;
|
||||
}
|
||||
|
||||
final JsonParser parser = new JsonParser();
|
||||
final JsonObject metaObject =
|
||||
parser.parse(itemStrings.remove(0)).getAsJsonObject();
|
||||
final String displayName = metaObject.get("displayName").getAsString();
|
||||
final boolean whitelist = metaObject.get("whitelist").getAsBoolean();
|
||||
final HashSet<String> items = new HashSet<>();
|
||||
|
||||
for (String itemStr : itemStrings) {
|
||||
items.add(itemStr);
|
||||
}
|
||||
|
||||
return new PresetTag(displayName, items, whitelist, file.getName());
|
||||
} catch (Throwable th) {
|
||||
NEIClientConfig.logger.error("Failed to load presets ItemStack from file", file);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void deleteFile() {
|
||||
if (presetsDir == null || filename == null) return;
|
||||
final File tagFile = new File(presetsDir, filename);
|
||||
|
||||
if (tagFile.exists()) {
|
||||
tagFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public void saveToFile() {
|
||||
if (presetsDir == null) return;
|
||||
|
||||
if (filename == null) {
|
||||
final String sanitized = displayName.replaceAll("[^_\\-.0-9a-zA-Z]", "_");
|
||||
int index = 1;
|
||||
|
||||
filename = sanitized + ".ini";
|
||||
|
||||
while ((new File(presetsDir, filename)).exists() || filename.equals("selected.ini")) {
|
||||
filename = sanitized + " (" + index + ").ini";
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> strings = new ArrayList<>();
|
||||
final JsonObject row = new JsonObject();
|
||||
|
||||
row.add("displayName", new JsonPrimitive(displayName));
|
||||
row.add("whitelist", new JsonPrimitive(whitelist));
|
||||
|
||||
strings.add(NBTJson.toJson(row));
|
||||
|
||||
try {
|
||||
strings.addAll(items);
|
||||
} catch (JsonSyntaxException e) {
|
||||
NEIClientConfig.logger.error("Failed to stringify presets ItemStack to json string");
|
||||
}
|
||||
|
||||
final File tagFile = new File(presetsDir, filename);
|
||||
|
||||
try (FileOutputStream output = new FileOutputStream(tagFile)) {
|
||||
IOUtils.writeLines(strings, "\n", output, "UTF-8");
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Filed to save presets list to file {}", tagFile, e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PresetTag copy() {
|
||||
return new PresetTag(displayName, (HashSet) items.clone(), whitelist, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected static class SubsetListBox extends GuiScrollSlot {
|
||||
protected final List<PresetTag> presets = new ArrayList<>();
|
||||
protected final List<PresetTag> selected = new ArrayList<>();
|
||||
protected int lastSelectedIndex = 0;
|
||||
|
||||
public SubsetListBox(File presetsDir) {
|
||||
super(0, 0, 0, 0);
|
||||
setSmoothScroll(false);
|
||||
|
||||
try {
|
||||
|
||||
presets.addAll(ItemList.forkJoinPool
|
||||
.submit(() -> Arrays.asList(presetsDir.listFiles()).parallelStream()
|
||||
.map(f -> PresetTag.loadFromFile(f))
|
||||
.filter(p -> p != null)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.get());
|
||||
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
selected.addAll(loadSelFromFile(presetsDir, presets));
|
||||
sort();
|
||||
}
|
||||
|
||||
public SubsetListBox() {
|
||||
super(0, 0, 0, 0);
|
||||
setSmoothScroll(false);
|
||||
}
|
||||
|
||||
public void addTag(final PresetTag tag, boolean sel) {
|
||||
presets.add(tag);
|
||||
|
||||
if (sel) {
|
||||
selected.add(tag);
|
||||
}
|
||||
}
|
||||
|
||||
protected List<PresetTag> getPresets() {
|
||||
return presets;
|
||||
}
|
||||
|
||||
protected List<PresetTag> getSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
public void replaceSeleted(final PresetTag tag) {
|
||||
|
||||
if (selected.size() == 1) {
|
||||
selected.get(0).deleteFile();
|
||||
presets.set(presets.indexOf(selected.get(0)), tag);
|
||||
selected.set(0, tag);
|
||||
} else {
|
||||
presets.add(tag);
|
||||
selected.add(tag);
|
||||
}
|
||||
|
||||
tag.saveToFile();
|
||||
saveSelToFile();
|
||||
sort();
|
||||
}
|
||||
|
||||
public void sort() {
|
||||
presets.sort((o1, o2) -> o1.displayName.compareTo(o2.displayName));
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
presets.clear();
|
||||
selected.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlotHeight(int slot) {
|
||||
return 18;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getNumSlots() {
|
||||
return presets.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void slotClicked(int slot, int button, int mx, int my, int count) {
|
||||
|
||||
if (slot >= presets.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PresetTag tag = presets.get(slot);
|
||||
final int width = windowBounds().width;
|
||||
|
||||
final Rectangle4i direction = new Rectangle4i(0, 0, 18, 18);
|
||||
final Rectangle4i delete = new Rectangle4i(width - 18, 0, 18, 18);
|
||||
final Rectangle4i option = new Rectangle4i(18, 0, width - 18 - 18, 18);
|
||||
|
||||
if (option.contains(mx, my)) {
|
||||
final boolean sel = selected.contains(tag);
|
||||
|
||||
if (NEIClientUtils.controlKey()) {
|
||||
|
||||
if (sel) {
|
||||
selected.remove(tag);
|
||||
} else {
|
||||
selected.add(tag);
|
||||
}
|
||||
|
||||
} else if (NEIClientUtils.shiftKey()) {
|
||||
selected.clear();
|
||||
|
||||
for (int i = Math.min(lastSelectedIndex, slot); i <= Math.max(lastSelectedIndex, slot); i++) {
|
||||
if (!selected.contains(presets.get(i))) {
|
||||
selected.add(presets.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
final int size = selected.size();
|
||||
selected.clear();
|
||||
|
||||
if (!sel || size > 1) {
|
||||
selected.add(tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (selected.isEmpty()) {
|
||||
lastSelectedIndex = 0;
|
||||
} else if (!NEIClientUtils.shiftKey()) {
|
||||
lastSelectedIndex = slot;
|
||||
}
|
||||
|
||||
} else if (delete.contains(mx, my)) {
|
||||
presets.remove(tag);
|
||||
selected.remove(tag);
|
||||
tag.deleteFile();
|
||||
} else if (direction.contains(mx, my)) {
|
||||
tag.whitelist = !tag.whitelist;
|
||||
tag.saveToFile();
|
||||
}
|
||||
|
||||
saveSelToFile();
|
||||
PresetsWidget.edit = null;
|
||||
PresetsWidget.openListBox = !presets.isEmpty()
|
||||
&& (NEIClientUtils.controlKey() || NEIClientUtils.shiftKey() || !option.contains(mx, my));
|
||||
ItemList.updateFilter.restart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSlot(int slot, int x, int y, int mx, int my, float frame) {
|
||||
if (slot >= presets.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int width = windowBounds().width;
|
||||
final Rectangle4i direction = new Rectangle4i(x, y, 18, 18);
|
||||
final Rectangle4i delete = new Rectangle4i(x + width - 18, y, 18, 18);
|
||||
final Rectangle4i option = new Rectangle4i(x + 18, y, width - 18 - 18, 18);
|
||||
final PresetTag tag = presets.get(slot);
|
||||
|
||||
final int optionState = selected.contains(tag) ? 0 : option.contains(x + mx, y + my) ? 1 : 2;
|
||||
final int directionState = direction.contains(x + mx, y + my) ? 1 : 2;
|
||||
final int deleteState = delete.contains(x + mx, y + my) ? 1 : 2;
|
||||
|
||||
final String displayName = NEIClientUtils.cropText(fontRenderer, tag.displayName, option.w - 6);
|
||||
final String dirName =
|
||||
tag.whitelist ? translate("presets.whitelist.label") : translate("presets.blacklist.label");
|
||||
|
||||
// blacklist or whitelist
|
||||
LayoutManager.getLayoutStyle()
|
||||
.drawSubsetTag(null, direction.x, direction.y, direction.w, direction.h, directionState, false);
|
||||
GuiDraw.drawString(dirName, direction.x + 6, direction.y + 5, directionState == 2 ? 0xFFE0E0E0 : 0xFFFFA0);
|
||||
|
||||
// option name
|
||||
LayoutManager.getLayoutStyle()
|
||||
.drawSubsetTag(null, option.x, option.y, option.w, option.h, optionState, false);
|
||||
GuiDraw.drawString(displayName, option.x + 3, option.y + 5, optionState == 2 ? 0xFFE0E0E0 : 0xFFFFA0);
|
||||
|
||||
// remove icon
|
||||
LayoutManager.getLayoutStyle()
|
||||
.drawSubsetTag(null, delete.x, delete.y, delete.w, delete.h, deleteState, false);
|
||||
GuiDraw.drawString("✕", delete.x + 6, delete.y + 5, deleteState == 2 ? 0xFFE0E0E0 : 0x601010);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOverlay(float frame) {}
|
||||
|
||||
@Override
|
||||
public void drawBackground(float frame) {
|
||||
drawRect(x, y, x + width, y + height, 0xFF202020);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScrollbar(float frame) {
|
||||
if (hasScrollbar()) {
|
||||
super.drawScrollbar(frame);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int scrollbarGuideAlignment() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected List<PresetTag> loadSelFromFile(File presetsDir, List<PresetTag> presets) {
|
||||
final File file = new File(presetsDir, "selected.ini");
|
||||
List<PresetTag> selected = new ArrayList<>();
|
||||
|
||||
if (file.exists()) {
|
||||
|
||||
try {
|
||||
|
||||
List<String> itemStrings;
|
||||
try (FileInputStream input = new FileInputStream(file)) {
|
||||
NEIClientConfig.logger.info("Loading presets selected from file {}", file);
|
||||
itemStrings = IOUtils.readLines(input, "UTF-8");
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load presets selected from file {}", file, e);
|
||||
return selected;
|
||||
}
|
||||
|
||||
final HashMap<String, PresetTag> map = new HashMap<>();
|
||||
|
||||
for (PresetTag tag : presets) {
|
||||
map.put(tag.filename, tag);
|
||||
}
|
||||
|
||||
for (String filename : itemStrings) {
|
||||
if (map.containsKey(filename)) {
|
||||
selected.add(map.get(filename));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Throwable th) {
|
||||
NEIClientConfig.logger.error("Failed to load presets selected from file", file);
|
||||
}
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
public void saveSelToFile() {
|
||||
|
||||
final File file = new File(presetsDir, "selected.ini");
|
||||
final List<String> list = new ArrayList<>();
|
||||
|
||||
for (final PresetTag tag : selected) {
|
||||
list.add(tag.filename);
|
||||
}
|
||||
|
||||
try (FileOutputStream output = new FileOutputStream(file)) {
|
||||
IOUtils.writeLines(list, "\n", output, "UTF-8");
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Filed to save presets selected list to file {}", file, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static class MouseSelection {
|
||||
public int startX = -1;
|
||||
public int startY = -1;
|
||||
public int startIndex = -1;
|
||||
public int endIndex = -1;
|
||||
public HashSet<ItemStack> items = new HashSet<>();
|
||||
public boolean append = true;
|
||||
|
||||
public MouseSelection(int slotIndex, boolean append) {
|
||||
final ItemsGrid grid = ItemPanels.itemPanel.getGrid();
|
||||
final Rectangle4i rec = grid.getItemRect(slotIndex);
|
||||
|
||||
this.append = append;
|
||||
endIndex = slotIndex;
|
||||
startIndex = slotIndex;
|
||||
startX = rec.x;
|
||||
startY = rec.y;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer;
|
||||
protected static SubsetListBox listbox = new SubsetListBox();
|
||||
protected static File presetsDir;
|
||||
|
||||
protected static boolean openListBox = false;
|
||||
protected static PresetTag edit;
|
||||
protected long lastclicktime;
|
||||
protected static MouseSelection mouseSelection;
|
||||
|
||||
protected static final Button dropdown = new Button() {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
openListBox = !openListBox;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRenderLabel() {
|
||||
return "...";
|
||||
}
|
||||
};
|
||||
|
||||
protected static final Label selectedValue = new Label("", false) {
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
final String text = NEIClientUtils.cropText(fontRenderer, this.text, w);
|
||||
|
||||
if (text.equals(this.text)) {
|
||||
GuiDraw.drawString(text, x + w - fontRenderer.getStringWidth(text), y + (h - 8) / 2, colour);
|
||||
} else {
|
||||
GuiDraw.drawString(text, x, y + (h - 8) / 2, colour);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(int mx, int my, List<String> tooltip) {
|
||||
if (contains(mx, my) && listbox.getSelected().size() <= 1) {
|
||||
tooltip.add(translate("presets.label.tooltip"));
|
||||
}
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
};
|
||||
|
||||
protected static final TextField selectedDisplayName = new TextField("") {
|
||||
|
||||
public void onTextChange(String oldText) {
|
||||
if (edit != null) {
|
||||
edit.displayName = text();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
super.draw(mousex, mousey);
|
||||
|
||||
if (text().isEmpty()) {
|
||||
GuiDraw.drawGradientRect(x - 1, y - 1, 1, h + 2, 0xFFcc3300, 0xFFcc3300); // Left
|
||||
GuiDraw.drawGradientRect(x - 1, y - 1, w + 2, 1, 0xFFcc3300, 0xFFcc3300); // Top
|
||||
GuiDraw.drawGradientRect(x + w, y - 1, 1, h + 2, 0xFFcc3300, 0xFFcc3300); // Left
|
||||
GuiDraw.drawGradientRect(x - 1, y + h, w + 2, 1, 0xFFcc3300, 0xFFcc3300); // Bottom
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(int mx, int my, List<String> tooltip) {
|
||||
if (contains(mx, my) && listbox.getSelected().size() <= 1) {
|
||||
tooltip.add(translate("presets.textfield.tooltip.1"));
|
||||
tooltip.add(translate("presets.textfield.tooltip.2"));
|
||||
}
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
};
|
||||
|
||||
protected static final Button selectedState = new Button("B") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick && edit != null) {
|
||||
edit.whitelist = !edit.whitelist;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRenderLabel() {
|
||||
return edit != null && edit.whitelist
|
||||
? translate("presets.whitelist.label")
|
||||
: translate("presets.blacklist.label");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTooltips(List<String> tooltip) {
|
||||
if (edit != null) {
|
||||
tooltip.add(
|
||||
edit.whitelist
|
||||
? translate("presets.whitelist.tooltip")
|
||||
: translate("presets.blacklist.tooltip"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected static void setEditedTag(final PresetTag tag) {
|
||||
edit = tag;
|
||||
openListBox = false;
|
||||
selectedDisplayName.setText(tag != null ? tag.displayName : "");
|
||||
ItemList.updateFilter.restart();
|
||||
}
|
||||
|
||||
public static void addTag(final PresetTag tag) {
|
||||
addTag(tag, false);
|
||||
}
|
||||
|
||||
public static void addTag(final PresetTag tag, boolean sel) {
|
||||
listbox.addTag(tag, sel);
|
||||
}
|
||||
|
||||
public static boolean inEditMode() {
|
||||
return edit != null;
|
||||
}
|
||||
|
||||
public static boolean isHidden(final ItemStack item) {
|
||||
|
||||
if (edit != null) {
|
||||
|
||||
if (mouseSelection != null && mouseSelection.items.contains(item)) {
|
||||
return mouseSelection.append != edit.whitelist;
|
||||
}
|
||||
|
||||
return !edit.matches(item);
|
||||
}
|
||||
|
||||
if (!listbox.getSelected().isEmpty()) {
|
||||
final List<PresetTag> selected = listbox.getSelected();
|
||||
|
||||
for (int idx = 0; idx < selected.size(); idx++) {
|
||||
if (!selected.get(idx).matches(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void setHidden(final ItemStack stack, final boolean append) {
|
||||
if (edit == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NEIClientUtils.shiftKey()) {
|
||||
final ArrayList<ItemStack> items = ItemPanels.itemPanel.getItems();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
if (stack.getItem().equals(items.get(i).getItem())) {
|
||||
hideItem(items.get(i), append);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (NEIClientUtils.controlKey()) {
|
||||
final String modId = getModId(stack);
|
||||
|
||||
if (modId == null) {
|
||||
hideItem(stack, append);
|
||||
} else {
|
||||
final ArrayList<ItemStack> items = ItemPanels.itemPanel.getItems();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
final String mod = getModId(items.get(i));
|
||||
if (mod != null && mod.equals(modId)) {
|
||||
hideItem(items.get(i), append);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
hideItem(stack, append);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void hideItem(final ItemStack stack, boolean append) {
|
||||
final String guid = StackInfo.getItemStackGUID(stack);
|
||||
|
||||
if (append) {
|
||||
edit.items.add(guid);
|
||||
} else {
|
||||
edit.items.remove(guid);
|
||||
}
|
||||
}
|
||||
|
||||
protected static String getModId(final ItemStack stack) {
|
||||
try {
|
||||
return GameRegistry.findUniqueIdentifierFor(stack.getItem()).modId;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void loadPresets(final String worldPath) {
|
||||
final File dir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath);
|
||||
presetsDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath + "/presets");
|
||||
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
if (!presetsDir.exists()) {
|
||||
presetsDir.mkdirs();
|
||||
}
|
||||
|
||||
listbox = new SubsetListBox(presetsDir);
|
||||
|
||||
edit = null;
|
||||
openListBox = false;
|
||||
selectedDisplayName.setText("");
|
||||
|
||||
ItemList.updateFilter.restart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mx, int my) {
|
||||
|
||||
if (edit != null) {
|
||||
|
||||
selectedState.x = x;
|
||||
selectedState.y = y;
|
||||
selectedState.w = selectedState.h = h;
|
||||
selectedState.draw(mx, my);
|
||||
|
||||
selectedDisplayName.y = y;
|
||||
selectedDisplayName.h = h;
|
||||
selectedDisplayName.x = selectedState.x + selectedState.w + 1;
|
||||
selectedDisplayName.w = w - h * 2 - 5;
|
||||
selectedDisplayName.draw(mx, my);
|
||||
|
||||
} else {
|
||||
final List<PresetTag> selected = listbox.getSelected();
|
||||
final int size = selected.size();
|
||||
|
||||
selectedValue.text = size > 1
|
||||
? translate("presets.label.selected", size)
|
||||
: (size == 1 ? selected.get(0).displayName : "");
|
||||
selectedValue.y = y;
|
||||
selectedValue.h = h;
|
||||
selectedValue.w = w - h - 4;
|
||||
selectedValue.x = x;
|
||||
|
||||
selectedValue.draw(mx, my);
|
||||
}
|
||||
|
||||
dropdown.y = y;
|
||||
dropdown.w = dropdown.h = h;
|
||||
dropdown.x = x + w - dropdown.w;
|
||||
dropdown.state = edit != null || listbox.getNumSlots() == 0 ? 2 : 0;
|
||||
dropdown.draw(mx, my);
|
||||
|
||||
if (openListBox) {
|
||||
final int scrollbarWidth = listbox.hasScrollbar() ? listbox.scrollbarDim().width : 0;
|
||||
|
||||
listbox.setSize(
|
||||
x,
|
||||
y + h + 1,
|
||||
w,
|
||||
Math.min(((LayoutManager.searchField.y - h - y) / 18) * 18, listbox.contentHeight()));
|
||||
|
||||
listbox.setMargins(0, 0, scrollbarWidth, 0);
|
||||
listbox.draw(mx, my, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int px, int py) {
|
||||
return super.contains(px, py) || openListBox && listbox.contains(px, py);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClick(int mx, int my, int button) {
|
||||
|
||||
if (openListBox && listbox.contains(mx, my)) {
|
||||
listbox.mouseClicked(mx, my, button);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (edit != null) {
|
||||
|
||||
if (selectedState.contains(mx, my)) {
|
||||
selectedState.handleClick(mx, my, button);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (selectedDisplayName.contains(mx, my)) {
|
||||
selectedDisplayName.handleClick(mx, my, button);
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (button == 0 && dropdown.contains(mx, my)) {
|
||||
openListBox = !openListBox;
|
||||
return true;
|
||||
}
|
||||
|
||||
openListBox = false;
|
||||
|
||||
if (button == 0 && selectedValue.contains(mx, my)) {
|
||||
|
||||
if (System.currentTimeMillis() - lastclicktime < 400) { // double click
|
||||
final List<PresetTag> selected = listbox.getSelected();
|
||||
final int size = selected.size();
|
||||
|
||||
if (size <= 1) {
|
||||
setEditedTag(size == 1 ? selected.get(0).copy() : new PresetTag(""));
|
||||
}
|
||||
}
|
||||
|
||||
lastclicktime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
return contains(mx, my);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClickExt(int mx, int my, int button) {
|
||||
|
||||
if (edit != null && mouseSelection == null) {
|
||||
ItemPanelSlot slot = ItemPanels.itemPanel.getSlotMouseOver(mx, my);
|
||||
|
||||
if (slot != null && button != 2) {
|
||||
mouseSelection = new MouseSelection(slot.slotIndex, button == 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyPress(int keyID, char keyChar) {
|
||||
if (keyID == Keyboard.KEY_ESCAPE) {
|
||||
openListBox = false;
|
||||
}
|
||||
|
||||
if (edit == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectedDisplayName.focused()
|
||||
&& (keyID == Keyboard.KEY_RETURN || keyID == Keyboard.KEY_NUMPADENTER)
|
||||
&& !selectedDisplayName.text().isEmpty()) {
|
||||
selectedDisplayName.handleKeyPress(keyID, keyChar);
|
||||
selectedDisplayName.setFocus(false);
|
||||
listbox.replaceSeleted(edit);
|
||||
setEditedTag(null);
|
||||
return true;
|
||||
} else if (selectedDisplayName.focused()) {
|
||||
return selectedDisplayName.handleKeyPress(keyID, keyChar);
|
||||
} else if (keyID == Keyboard.KEY_ESCAPE && !(NEIClientUtils.mc().currentScreen instanceof GuiRecipe)) {
|
||||
setEditedTag(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(int mx, int my, int button, long heldTime) {
|
||||
|
||||
if (openListBox) {
|
||||
listbox.mouseDragged(mx, my, button, heldTime);
|
||||
}
|
||||
|
||||
if (edit != null && button != 2 && mouseSelection != null) {
|
||||
final ItemPanelSlot slot = ItemPanels.itemPanel.getSlotMouseOver(mx, my);
|
||||
|
||||
if (slot != null && slot.slotIndex != mouseSelection.endIndex) {
|
||||
final ItemsGrid grid = ItemPanels.itemPanel.getGrid();
|
||||
mouseSelection.endIndex = slot.slotIndex;
|
||||
mouseSelection.items.clear();
|
||||
|
||||
final Rectangle4i rec = grid.getItemRect(slot.slotIndex);
|
||||
final Rectangle4i sel = new Rectangle4i(
|
||||
Math.min(rec.x, mouseSelection.startX),
|
||||
Math.min(rec.y, mouseSelection.startY),
|
||||
Math.max(rec.x, mouseSelection.startX) - Math.min(rec.x, mouseSelection.startX),
|
||||
Math.max(rec.y, mouseSelection.startY) - Math.min(rec.y, mouseSelection.startY));
|
||||
|
||||
for (int x = sel.x; x <= sel.x + sel.w; x += ItemsGrid.SLOT_SIZE) {
|
||||
for (int y = sel.y; y <= sel.y + sel.h; y += ItemsGrid.SLOT_SIZE) {
|
||||
ItemStack stack = ItemPanels.itemPanel.getStackMouseOver(x, y);
|
||||
|
||||
if (stack != null) {
|
||||
mouseSelection.items.add(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(int mx, int my, int button) {
|
||||
|
||||
if (openListBox) {
|
||||
listbox.mouseMovedOrUp(mx, my, button);
|
||||
}
|
||||
|
||||
if (edit != null && mouseSelection != null) {
|
||||
ItemPanelSlot hoverSlot = ItemPanels.itemPanel.getSlotMouseOver(mx, my);
|
||||
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseSelection.startIndex) {
|
||||
setHidden(hoverSlot.item, button == 0);
|
||||
} else if (!mouseSelection.items.isEmpty()) {
|
||||
|
||||
for (ItemStack stack : mouseSelection.items) {
|
||||
hideItem(stack, mouseSelection.append);
|
||||
}
|
||||
}
|
||||
|
||||
mouseSelection = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMouseWheel(int i, int mx, int my) {
|
||||
|
||||
if (openListBox && listbox.hasScrollbar() && listbox.contains(mx, my)) {
|
||||
listbox.scroll(-i);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClick(int mx, int my) {
|
||||
|
||||
if (!contains(mx, my)) {
|
||||
openListBox = false;
|
||||
}
|
||||
|
||||
selectedDisplayName.onGuiClick(mx, my);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(int mx, int my, List<String> tooltip) {
|
||||
|
||||
if (edit != null) {
|
||||
|
||||
if (selectedState.contains(mx, my)) {
|
||||
return selectedState.handleTooltip(mx, my, tooltip);
|
||||
}
|
||||
|
||||
if (selectedDisplayName.contains(mx, my)) {
|
||||
return selectedDisplayName.handleTooltip(mx, my, tooltip);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (selectedValue.contains(mx, my)) {
|
||||
return selectedValue.handleTooltip(mx, my, tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
public static boolean matches(ItemStack stack) {
|
||||
|
||||
if (edit != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final List<PresetTag> selected = listbox.getSelected();
|
||||
|
||||
for (int idx = 0; idx < selected.size(); idx++) {
|
||||
if (!selected.get(idx).matches(stack)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.nei.SearchField.GuiSearchField;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.util.TextHistory;
|
||||
|
||||
public abstract class RecipeSearchField extends TextField {
|
||||
|
||||
private static final TextHistory history = new TextHistory();
|
||||
|
||||
public RecipeSearchField(String ident) {
|
||||
super(ident);
|
||||
this.field.setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initInternalTextField() {
|
||||
field = new GuiSearchField();
|
||||
field.setMaxStringLength(maxSearchLength);
|
||||
field.setCursorPositionZero();
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return this.field.getVisible();
|
||||
}
|
||||
|
||||
public void setVisible(boolean visible) {
|
||||
this.field.setVisible(visible);
|
||||
}
|
||||
|
||||
protected abstract boolean noResults();
|
||||
|
||||
@Override
|
||||
public int getTextColour() {
|
||||
if (!text().isEmpty() && !noResults()) {
|
||||
return focused() ? 0xFFcc3300 : 0xFF993300;
|
||||
} else {
|
||||
return focused() ? 0xFFE0E0E0 : 0xFF909090;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lastKeyTyped(int keyID, char keyChar) {
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getprevioussearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.PREVIOUS);
|
||||
}
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getnextsearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.NEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filterText(String s) {
|
||||
return EnumChatFormatting.getTextWithoutFormattingCodes(s);
|
||||
}
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
return ((GuiSearchField) field).getFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocus(boolean focus) {
|
||||
final boolean previousFocus = field.isFocused();
|
||||
|
||||
if (previousFocus != focus) {
|
||||
history.add(text());
|
||||
}
|
||||
|
||||
super.setFocus(focus);
|
||||
}
|
||||
|
||||
private boolean handleNavigateHistory(TextHistory.Direction direction) {
|
||||
if (focused()) {
|
||||
return history.get(direction, text()).map(newText -> {
|
||||
setText(newText);
|
||||
return true;
|
||||
}).orElse(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
public abstract class RestartableTask {
|
||||
|
||||
public final String name;
|
||||
private Thread thread;
|
||||
private volatile boolean restart;
|
||||
@@ -14,14 +15,13 @@ public abstract class RestartableTask {
|
||||
|
||||
private void start() {
|
||||
thread = new Thread(name) {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
do {
|
||||
while (stopped)
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
while (stopped) try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException ignored) {}
|
||||
if (!restart) execute();
|
||||
} while (!finish());
|
||||
}
|
||||
@@ -52,7 +52,8 @@ public abstract class RestartableTask {
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops execution until restart is called. If a thread is running, the restart flag will be set, and the thread will be paused once the execute method exits.
|
||||
* Stops execution until restart is called. If a thread is running, the restart flag will be set, and the thread
|
||||
* will be paused once the execute method exits.
|
||||
*/
|
||||
public synchronized void stop() {
|
||||
if (thread != null) {
|
||||
|
||||
@@ -1,25 +1,34 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.nei.NEIClientConfig.world;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.EverythingItemFilter;
|
||||
import codechicken.nei.ItemList.PatternItemFilter;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemList.NothingItemFilter;
|
||||
import codechicken.nei.SearchTokenParser.ISearchParserProvider;
|
||||
import codechicken.nei.SearchTokenParser.SearchMode;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.TextHistory;
|
||||
|
||||
public class SearchField extends TextField implements ItemFilterProvider {
|
||||
|
||||
/**
|
||||
* Interface for returning a custom filter based on search field text
|
||||
*/
|
||||
@Deprecated
|
||||
public static interface ISearchProvider {
|
||||
|
||||
/**
|
||||
* @return false if this filter should only be used if no other non-default filters match the search string
|
||||
*/
|
||||
@@ -31,32 +40,98 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
public ItemFilter getFilter(String searchText);
|
||||
}
|
||||
|
||||
private static class DefaultSearchProvider implements ISearchProvider {
|
||||
@Override
|
||||
public boolean isPrimary() {
|
||||
return false;
|
||||
public static class SearchParserProvider implements ISearchParserProvider {
|
||||
|
||||
protected final Function<Pattern, ItemFilter> createFilter;
|
||||
protected final String name;
|
||||
protected final char prefix;
|
||||
protected final EnumChatFormatting highlightedColor;
|
||||
|
||||
public SearchParserProvider(char prefix, String name, EnumChatFormatting highlightedColor,
|
||||
Function<Pattern, ItemFilter> createFilter) {
|
||||
this.prefix = prefix;
|
||||
this.name = name;
|
||||
this.highlightedColor = highlightedColor;
|
||||
this.createFilter = createFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemFilter getFilter(String searchText) {
|
||||
Pattern pattern = getPattern(searchText);
|
||||
return pattern == null ? null : new PatternItemFilter(pattern);
|
||||
Pattern pattern = SearchField.getPattern(searchText);
|
||||
|
||||
if (pattern != null) {
|
||||
return this.createFilter(pattern);
|
||||
}
|
||||
|
||||
return new NothingItemFilter();
|
||||
}
|
||||
|
||||
protected ItemFilter createFilter(Pattern pattern) {
|
||||
final ItemFilter filter = this.createFilter.apply(pattern);
|
||||
|
||||
return filter == null ? new NothingItemFilter() : filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char getPrefix() {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumChatFormatting getHighlightedColor() {
|
||||
return this.highlightedColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchMode getSearchMode() {
|
||||
return SearchMode.fromInt(NEIClientConfig.getIntSetting("inventory.search." + this.name + "SearchMode"));
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ISearchProvider> searchProviders = new LinkedList<>();
|
||||
private boolean isVisible = true;
|
||||
public static class GuiSearchField extends FormattedTextField {
|
||||
|
||||
long lastclicktime;
|
||||
protected final SearchTokenParser searchParser;
|
||||
|
||||
public GuiSearchField() {
|
||||
this(SearchField.searchParser);
|
||||
}
|
||||
|
||||
public GuiSearchField(SearchTokenParser searchParser) {
|
||||
super(Minecraft.getMinecraft().fontRenderer, 0, 0, 0, 0);
|
||||
this.searchParser = searchParser;
|
||||
setFormatter(new SearchTextFormatter(searchParser));
|
||||
}
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
return getFilter(getText());
|
||||
}
|
||||
|
||||
public ItemFilter getFilter(String filterText) {
|
||||
return this.searchParser.getFilter(filterText);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static List<ISearchProvider> searchProviders = new LinkedList<>();
|
||||
public static final SearchTokenParser searchParser = new SearchTokenParser();
|
||||
private static final TextHistory history = new TextHistory();
|
||||
private boolean isVisible = true;
|
||||
private long lastclicktime;
|
||||
|
||||
public SearchField(String ident) {
|
||||
super(ident);
|
||||
API.addItemFilter(this);
|
||||
API.addSearchProvider(new DefaultSearchProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initInternalTextField() {
|
||||
field = new GuiSearchField();
|
||||
field.setMaxStringLength(maxSearchLength);
|
||||
field.setCursorPositionZero();
|
||||
}
|
||||
|
||||
public static boolean searchInventories() {
|
||||
return world.nbt.getBoolean("searchinventories");
|
||||
return NEIClientConfig.world.nbt.getBoolean("searchinventories");
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
@@ -69,7 +144,8 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
|
||||
@Override
|
||||
public int getTextColour() {
|
||||
if (ItemPanels.itemPanel.getItems().isEmpty()) {
|
||||
if (ItemPanels.itemPanel.getItems().isEmpty()
|
||||
&& (!this.field.getText().isEmpty() || !NEIClientConfig.hideItemsUntilSearching())) {
|
||||
return focused() ? 0xFFcc3300 : 0xFF993300;
|
||||
} else {
|
||||
return focused() ? 0xFFE0E0E0 : 0xFF909090;
|
||||
@@ -78,14 +154,37 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
|
||||
super.draw(mousex, mousey);
|
||||
|
||||
if (searchInventories()) {
|
||||
GuiDraw.drawGradientRect(x - 1, y - 1, 1, h + 2, 0xFFFFFF00, 0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(x - 1, y - 1, w + 2, 1, 0xFFFFFF00, 0xFFC0B000); // Top
|
||||
GuiDraw.drawGradientRect(x + w, y - 1, 1, h + 2, 0xFFFFFF00, 0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(x - 1, y + h, w + 2, 1, 0xFFFFFF00, 0xFFC0B000); // Bottom
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition - 1,
|
||||
field.yPosition - 1,
|
||||
1,
|
||||
field.height + 2,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition - 1,
|
||||
field.yPosition - 1,
|
||||
field.width + 2,
|
||||
1,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Top
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition + field.width,
|
||||
field.yPosition - 1,
|
||||
1,
|
||||
field.height + 2,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition - 1,
|
||||
field.yPosition + field.height,
|
||||
field.width + 2,
|
||||
1,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Bottom
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +193,6 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
if (button == 0) {
|
||||
if (focused() && (System.currentTimeMillis() - lastclicktime < 400)) { // double click
|
||||
NEIClientConfig.world.nbt.setBoolean("searchinventories", !searchInventories());
|
||||
NEIClientConfig.world.saveNBT();
|
||||
}
|
||||
lastclicktime = System.currentTimeMillis();
|
||||
}
|
||||
@@ -104,10 +202,11 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
@Override
|
||||
public void onTextChange(String oldText) {
|
||||
final String newText = text();
|
||||
if (newText.length() > 0) NEIClientConfig.logger.debug("Searching for " + text());
|
||||
|
||||
NEIClientConfig.setSearchExpression(newText);
|
||||
ItemList.updateFilter.restart();
|
||||
if (!newText.equals(oldText)) {
|
||||
if (newText.length() > 0) NEIClientConfig.logger.debug("Searching for " + newText);
|
||||
NEIClientConfig.setSearchExpression(newText);
|
||||
ItemList.updateFilter.restart();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,6 +215,13 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
if (isVisible() && NEIClientConfig.isKeyHashDown("gui.search")) {
|
||||
setFocus(true);
|
||||
}
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getprevioussearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.PREVIOUS);
|
||||
}
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getnextsearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.NEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,36 +230,121 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
}
|
||||
|
||||
public static Pattern getPattern(String search) {
|
||||
switch (NEIClientConfig.getIntSetting("inventory.searchmode")) {
|
||||
return getPattern(search, NEIClientConfig.getIntSetting("inventory.search.patternMode"));
|
||||
}
|
||||
|
||||
public static Pattern getPattern(String search, int patternMode) {
|
||||
switch (patternMode) {
|
||||
case 0: // plain
|
||||
search = "\\Q" + search + "\\E";
|
||||
search = Pattern.quote(search);
|
||||
break;
|
||||
case 1:
|
||||
search = search.replace(".", "").replace("?", ".").replace("*", ".+?");
|
||||
case 1: // extended
|
||||
|
||||
if (search.length() >= 3 && search.startsWith("r/") && search.endsWith("/")) {
|
||||
search = search.substring(2, search.length() - 1);
|
||||
} else {
|
||||
final Matcher matcher = Pattern.compile("(\\?|\\*)").matcher(search);
|
||||
final StringBuilder cleanedString = new StringBuilder();
|
||||
int lastEndIndex = 0;
|
||||
|
||||
while (matcher.find()) {
|
||||
cleanedString.append(Pattern.quote(search.substring(lastEndIndex, matcher.start())));
|
||||
|
||||
switch (matcher.group(0).charAt(0)) {
|
||||
case '?':
|
||||
cleanedString.append(".");
|
||||
break;
|
||||
case '*':
|
||||
cleanedString.append(".+?");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
lastEndIndex = matcher.end();
|
||||
}
|
||||
|
||||
search = cleanedString + Pattern.quote(search.substring(lastEndIndex, search.length()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Pattern pattern = null;
|
||||
try {
|
||||
pattern = Pattern.compile(search);
|
||||
} catch (PatternSyntaxException ignored) {
|
||||
if (!search.isEmpty()) {
|
||||
try {
|
||||
return Pattern.compile(search, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
||||
} catch (PatternSyntaxException ignored) {}
|
||||
}
|
||||
return pattern == null || pattern.toString().length() == 0 ? null : pattern;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getEscapedSearchText(ItemStack stack) {
|
||||
final FluidStack fluidStack = StackInfo.isFluidContainer(stack) ? null : StackInfo.getFluid(stack);
|
||||
String displayName;
|
||||
|
||||
if (fluidStack != null) {
|
||||
displayName = fluidStack.getLocalizedName();
|
||||
} else {
|
||||
displayName = stack.getDisplayName();
|
||||
}
|
||||
|
||||
return getEscapedSearchText(displayName);
|
||||
}
|
||||
|
||||
public static String getEscapedSearchText(String text) {
|
||||
text = EnumChatFormatting.getTextWithoutFormattingCodes(text);
|
||||
|
||||
switch (NEIClientConfig.getIntSetting("inventory.search.patternMode")) {
|
||||
case 1:
|
||||
text = text.replaceAll("[\\?|\\*]", "\\\\$0");
|
||||
break;
|
||||
case 2:
|
||||
text = text.replaceAll("[{}()\\[\\].+*?^$\\\\|]", "\\\\$0");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (text.contains(" ") && NEIClientConfig.getBooleanSetting("inventory.search.quoteDropItemName")) {
|
||||
text = "\"" + text + "\"";
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemFilter getFilter() {
|
||||
String s_filter = text().toLowerCase();
|
||||
|
||||
List<ItemFilter> primary = new LinkedList<>();
|
||||
List<ItemFilter> secondary = new LinkedList<>();
|
||||
for (ISearchProvider p : searchProviders) {
|
||||
ItemFilter filter = p.getFilter(s_filter);
|
||||
if (filter != null) (p.isPrimary() ? primary : secondary).add(filter);
|
||||
if (field.getText().isEmpty() && NEIClientConfig.hideItemsUntilSearching()) {
|
||||
return new NothingItemFilter();
|
||||
}
|
||||
|
||||
if (!primary.isEmpty()) return new AnyMultiItemFilter(primary);
|
||||
if (!secondary.isEmpty()) return new AnyMultiItemFilter(secondary);
|
||||
return new EverythingItemFilter();
|
||||
return ((GuiSearchField) field).getFilter();
|
||||
}
|
||||
|
||||
public static ItemFilter getFilter(String filterText) {
|
||||
return SearchField.searchParser.getFilter(filterText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocus(boolean focus) {
|
||||
final boolean previousFocus = field.isFocused();
|
||||
|
||||
if (previousFocus != focus) {
|
||||
history.add(text());
|
||||
}
|
||||
super.setFocus(focus);
|
||||
}
|
||||
|
||||
private boolean handleNavigateHistory(TextHistory.Direction direction) {
|
||||
if (focused()) {
|
||||
return history.get(direction, text()).map(newText -> {
|
||||
setText(newText);
|
||||
return true;
|
||||
}).orElse(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.nei.FormattedTextField.TextFormatter;
|
||||
import codechicken.nei.SearchTokenParser.SearchToken;
|
||||
|
||||
public class SearchTextFormatter implements TextFormatter {
|
||||
|
||||
protected final SearchTokenParser searchParser;
|
||||
|
||||
public SearchTextFormatter(SearchTokenParser searchParser) {
|
||||
this.searchParser = searchParser;
|
||||
}
|
||||
|
||||
public String format(String text) {
|
||||
final String[] parts = (text + "| ").split("\\|");
|
||||
StringJoiner formattedText = new StringJoiner(EnumChatFormatting.GRAY + "|");
|
||||
|
||||
for (int i = 0; i < parts.length - 1; i++) {
|
||||
final String filterText = parts[i];
|
||||
final List<SearchToken> tokens = searchParser.splitSearchText(filterText);
|
||||
StringBuilder formattedPart = new StringBuilder();
|
||||
int startIndex = 0;
|
||||
|
||||
for (SearchToken token : tokens) {
|
||||
formattedPart.append(filterText.substring(startIndex, token.start));
|
||||
EnumChatFormatting tokenColor = EnumChatFormatting.RESET;
|
||||
|
||||
if (token.firstChar != null) {
|
||||
tokenColor = searchParser.getProvider(token.firstChar).getHighlightedColor();
|
||||
}
|
||||
|
||||
if (token.ignore) {
|
||||
formattedPart.append(EnumChatFormatting.BLUE + "-");
|
||||
}
|
||||
|
||||
if (token.firstChar != null) {
|
||||
formattedPart.append(tokenColor + String.valueOf(token.firstChar));
|
||||
}
|
||||
|
||||
if (token.quotes) {
|
||||
formattedPart.append(EnumChatFormatting.GOLD + "\"");
|
||||
}
|
||||
|
||||
if (!token.rawText.isEmpty()) {
|
||||
formattedPart.append(tokenColor + token.rawText);
|
||||
}
|
||||
|
||||
if (token.quotes) {
|
||||
formattedPart.append(EnumChatFormatting.GOLD + "\"");
|
||||
}
|
||||
|
||||
startIndex = token.end;
|
||||
}
|
||||
|
||||
formattedPart.append(filterText.substring(startIndex, filterText.length()));
|
||||
formattedText.add(formattedPart);
|
||||
}
|
||||
|
||||
return formattedText.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.Language;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.nei.ItemList.AllMultiItemFilter;
|
||||
import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.EverythingItemFilter;
|
||||
import codechicken.nei.ItemList.NegatedItemFilter;
|
||||
import codechicken.nei.ItemList.NothingItemFilter;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
|
||||
public class SearchTokenParser {
|
||||
|
||||
public enum SearchMode {
|
||||
|
||||
ALWAYS,
|
||||
PREFIX,
|
||||
NEVER;
|
||||
|
||||
public static SearchMode fromInt(int value) {
|
||||
return switch (value) {
|
||||
case 0 -> ALWAYS;
|
||||
case 1 -> PREFIX;
|
||||
default -> NEVER;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class SearchToken {
|
||||
|
||||
public boolean ignore = false;
|
||||
public boolean quotes = false;
|
||||
public Character firstChar = null;
|
||||
|
||||
public String[] words;
|
||||
|
||||
public String rawText = "";
|
||||
public int start = 0;
|
||||
public int end = 0;
|
||||
|
||||
}
|
||||
|
||||
public static interface ISearchParserProvider {
|
||||
|
||||
public ItemFilter getFilter(String searchText);
|
||||
|
||||
public static List<Language> getAllLanguages() {
|
||||
return new ArrayList<>(Minecraft.getMinecraft().getLanguageManager().getLanguages());
|
||||
}
|
||||
|
||||
default List<Language> getMatchingLanguages() {
|
||||
return getAllLanguages();
|
||||
}
|
||||
|
||||
public char getPrefix();
|
||||
|
||||
public EnumChatFormatting getHighlightedColor();
|
||||
|
||||
public SearchMode getSearchMode();
|
||||
}
|
||||
|
||||
private static class ProvidersCache {
|
||||
|
||||
public String languageCode = null;
|
||||
public List<ISearchParserProvider> providers = new ArrayList<>();
|
||||
|
||||
public void clear() {
|
||||
this.languageCode = null;
|
||||
this.providers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static class IsRegisteredItemFilter implements ItemFilter {
|
||||
|
||||
public ItemFilter filter;
|
||||
|
||||
public IsRegisteredItemFilter(ItemFilter filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return item != null && item.getItem() != null
|
||||
&& item.getItem().delegate.name() != null
|
||||
&& this.filter.matches(item);
|
||||
}
|
||||
}
|
||||
|
||||
protected final LRUCache<String, ItemFilter> filtersCache = new LRUCache<>(20);
|
||||
protected final List<ISearchParserProvider> searchProviders;
|
||||
protected final ProvidersCache providersCache = new ProvidersCache();
|
||||
protected final Map<Character, Character> prefixRedefinitions = new HashMap<>();
|
||||
|
||||
public SearchTokenParser(List<ISearchParserProvider> searchProviders) {
|
||||
this.searchProviders = searchProviders;
|
||||
}
|
||||
|
||||
public SearchTokenParser() {
|
||||
this(new ArrayList<>());
|
||||
}
|
||||
|
||||
public void addProvider(ISearchParserProvider provider) {
|
||||
this.searchProviders.add(provider);
|
||||
this.providersCache.clear();
|
||||
this.filtersCache.clear();
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
this.filtersCache.clear();
|
||||
}
|
||||
|
||||
protected List<ISearchParserProvider> getProviders() {
|
||||
Language currentLanguage = Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage();
|
||||
|
||||
if (!currentLanguage.getLanguageCode().equals(providersCache.languageCode)) {
|
||||
Map<Character, ISearchParserProvider> providers = new HashMap<>();
|
||||
|
||||
for (int index = this.searchProviders.size() - 1; index >= 0; index--) {
|
||||
ISearchParserProvider provider = this.searchProviders.get(index);
|
||||
|
||||
if (!providers.containsKey(provider.getPrefix())
|
||||
&& provider.getMatchingLanguages().contains(currentLanguage)) {
|
||||
providers.put(provider.getPrefix(), provider);
|
||||
}
|
||||
}
|
||||
|
||||
providersCache.providers = new ArrayList<>(providers.values());
|
||||
providersCache.languageCode = currentLanguage.getLanguageCode();
|
||||
}
|
||||
|
||||
return providersCache.providers;
|
||||
}
|
||||
|
||||
public ISearchParserProvider getProvider(char ch) {
|
||||
return getProviders().stream()
|
||||
.filter(
|
||||
provider -> provider.getSearchMode() == SearchMode.PREFIX
|
||||
&& getRedefinedPrefix(provider.getPrefix()) == ch)
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public synchronized ItemFilter getFilter(String filterText) {
|
||||
filterText = EnumChatFormatting.getTextWithoutFormattingCodes(filterText).toLowerCase();
|
||||
|
||||
return this.filtersCache.computeIfAbsent(filterText, text -> {
|
||||
final String[] parts = text.split("\\|");
|
||||
final List<ItemFilter> searchTokens = Arrays.stream(parts).map(this::parseSearchText).filter(s -> s != null)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
if (searchTokens.isEmpty()) {
|
||||
return new EverythingItemFilter();
|
||||
} else if (searchTokens.size() == 1) {
|
||||
return new IsRegisteredItemFilter(searchTokens.get(0));
|
||||
} else {
|
||||
return new IsRegisteredItemFilter(new AnyMultiItemFilter(searchTokens));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public List<SearchToken> splitSearchText(String filterText) {
|
||||
|
||||
if (filterText.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<SearchToken> tokens = new ArrayList<>();
|
||||
final String prefixes = getPrefixes();
|
||||
final int spaceMode = NEIClientConfig.getIntSetting("inventory.search.spaceMode");
|
||||
// The regular expression first tries to match a string that starts with a space or the beginning of the string,
|
||||
// followed by a sequence of characters that do not contain special characters -"@#$%&, and ends with a space
|
||||
// and the characters -"@#$%& or the end of the string.
|
||||
final String patternPart1 = "(?<tokenA>(^|\\s+)(?:[^" + Pattern.quote(" -\"" + prefixes)
|
||||
+ "]).+?(?=\\s+["
|
||||
+ Pattern.quote("-\"" + prefixes)
|
||||
+ "]|$))";
|
||||
// If the first condition is not met, it tries to match a sequence of - characters, followed by @#$%&
|
||||
// characters, then either a quoted string or non-space characters.
|
||||
final String patternPart2 = "((?<ignore>-*)(?<firstChar>[" + Pattern.quote(prefixes)
|
||||
+ "]*)(?<tokenB>\\\".*?(?:\\\"|$)|\\S+\\s*))";
|
||||
final Pattern pattern = Pattern.compile(spaceMode == 0 ? patternPart2 : (patternPart1 + "|" + patternPart2));
|
||||
final Matcher filterMatcher = pattern.matcher(filterText);
|
||||
|
||||
while (filterMatcher.find()) {
|
||||
String firstChar = filterMatcher.group("firstChar");
|
||||
SearchToken token = new SearchToken();
|
||||
token.start = filterMatcher.start();
|
||||
token.end = filterMatcher.end();
|
||||
token.ignore = "-".equals(filterMatcher.group("ignore"));
|
||||
token.rawText = spaceMode == 0 ? null : filterMatcher.group("tokenA");
|
||||
|
||||
if (firstChar != null && !firstChar.isEmpty()) {
|
||||
token.firstChar = firstChar.charAt(0);
|
||||
}
|
||||
|
||||
if (token.rawText == null) { // spaceMode == 0
|
||||
token.rawText = filterMatcher.group("tokenB");
|
||||
token.quotes = token.rawText.length() > 1 && token.rawText.startsWith("\"")
|
||||
&& token.rawText.endsWith("\"");
|
||||
|
||||
if (token.quotes) {
|
||||
token.rawText = token.rawText.substring(1, token.rawText.length() - 1);
|
||||
}
|
||||
|
||||
token.words = new String[] { token.rawText.trim() };
|
||||
} else if (spaceMode == 2) {
|
||||
token.words = token.rawText.trim().split("\\s+");
|
||||
} else {
|
||||
token.words = new String[] { token.rawText.trim() };
|
||||
}
|
||||
|
||||
tokens.add(token);
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private String getPrefixes() {
|
||||
StringBuilder prefixes = new StringBuilder().append('\0');
|
||||
|
||||
for (ISearchParserProvider provider : getProviders()) {
|
||||
if (provider.getSearchMode() == SearchMode.PREFIX) {
|
||||
prefixes.append(getRedefinedPrefix(provider.getPrefix()));
|
||||
}
|
||||
}
|
||||
|
||||
return prefixes.toString();
|
||||
}
|
||||
|
||||
public char getRedefinedPrefix(char prefix) {
|
||||
return this.prefixRedefinitions.getOrDefault(prefix, prefix);
|
||||
}
|
||||
|
||||
private ItemFilter parseSearchText(String filterText) {
|
||||
|
||||
if (filterText.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final AllMultiItemFilter searchTokens = new AllMultiItemFilter();
|
||||
final List<SearchToken> tokens = splitSearchText(filterText);
|
||||
|
||||
for (SearchToken token : tokens) {
|
||||
if (!token.rawText.isEmpty()) {
|
||||
ItemFilter result = parseToken(token);
|
||||
|
||||
if (token.ignore) {
|
||||
searchTokens.filters.add(new NegatedItemFilter(result));
|
||||
} else {
|
||||
searchTokens.filters.add(result);
|
||||
}
|
||||
} else if (!token.ignore) {
|
||||
searchTokens.filters.add(new NothingItemFilter());
|
||||
}
|
||||
}
|
||||
|
||||
return searchTokens;
|
||||
}
|
||||
|
||||
private ItemFilter parseToken(SearchToken token) {
|
||||
final ISearchParserProvider provider = token.firstChar == null ? null : this.getProvider(token.firstChar);
|
||||
|
||||
if (provider == null || provider.getSearchMode() == SearchMode.NEVER) {
|
||||
final List<ItemFilter> filters = new ArrayList<>();
|
||||
|
||||
for (ISearchParserProvider _provider : getProviders()) {
|
||||
if (_provider.getSearchMode() == SearchMode.ALWAYS) {
|
||||
AllMultiItemFilter filter = generateFilters(_provider, token.words);
|
||||
|
||||
if (!filter.filters.isEmpty()) {
|
||||
filters.add(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filters.isEmpty() ? new NothingItemFilter() : new AnyMultiItemFilter(filters);
|
||||
} else {
|
||||
return generateFilters(provider, token.words);
|
||||
}
|
||||
}
|
||||
|
||||
private AllMultiItemFilter generateFilters(ISearchParserProvider provider, String[] words) {
|
||||
final AllMultiItemFilter filters = new AllMultiItemFilter();
|
||||
|
||||
for (String work : words) {
|
||||
final ItemFilter filter = provider.getFilter(work);
|
||||
|
||||
if (filter != null) {
|
||||
filters.filters.add(filter);
|
||||
}
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
@@ -10,14 +18,9 @@ import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent;
|
||||
import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerRespawnEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
|
||||
import java.util.List;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
public class ServerHandler {
|
||||
|
||||
private static ServerHandler instance;
|
||||
|
||||
public static void load() {
|
||||
@@ -32,11 +35,10 @@ public class ServerHandler {
|
||||
|
||||
@SubscribeEvent
|
||||
public void tickEvent(TickEvent.WorldTickEvent event) {
|
||||
if (event.phase == Phase.START
|
||||
&& !event.world.isRemote
|
||||
&& NEIServerConfig.dimTags.containsKey(
|
||||
CommonUtils.getDimension(event.world))) // fake worlds that don't call Load
|
||||
processDisabledProperties(event.world);
|
||||
if (event.phase == Phase.START && !event.world.isRemote
|
||||
&& NEIServerConfig.dimTags.containsKey(CommonUtils.getDimension(event.world))) // fake worlds that don't
|
||||
// call Load
|
||||
processDisabledProperties(event.world);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -72,8 +74,8 @@ public class ServerHandler {
|
||||
double maxspeedy = 0.5;
|
||||
double speedxz = 0.05;
|
||||
double speedy = 0.07;
|
||||
List<EntityItem> items = player.worldObj.getEntitiesWithinAABB(
|
||||
EntityItem.class, player.boundingBox.expand(distancexz, distancey, distancexz));
|
||||
List<EntityItem> items = player.worldObj
|
||||
.getEntitiesWithinAABB(EntityItem.class, player.boundingBox.expand(distancexz, distancey, distancexz));
|
||||
for (EntityItem item : items) {
|
||||
if (item.delayBeforeCanPickup > 0) continue;
|
||||
if (!NEIServerUtils.canItemFitInInventory(player, item.getEntityItem())) continue;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
public abstract class SlotOP {
|
||||
|
||||
public abstract String getDescription();
|
||||
|
||||
public abstract int[] getKeyBind();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.core.ClientUtils;
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.RenderBlocks;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
@@ -13,10 +11,15 @@ import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.IItemRenderer;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.core.ClientUtils;
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
|
||||
public class SpawnerRenderer implements IItemRenderer {
|
||||
|
||||
@Override
|
||||
public boolean handleRenderType(ItemStack item, ItemRenderType type) {
|
||||
return true;
|
||||
@@ -61,7 +64,6 @@ public class SpawnerRenderer implements IItemRenderer {
|
||||
BossStatus.hasColorModifier = bossHasColorModifier;
|
||||
}
|
||||
|
||||
@SuppressWarnings("incomplete-switch")
|
||||
@Override
|
||||
public void renderItem(ItemRenderType type, ItemStack item, Object... data) {
|
||||
switch (type) {
|
||||
@@ -72,6 +74,8 @@ public class SpawnerRenderer implements IItemRenderer {
|
||||
case ENTITY:
|
||||
renderInventoryItem((RenderBlocks) data[0], item);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -2,12 +2,14 @@ package codechicken.nei;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
public abstract class TextField extends Widget {
|
||||
|
||||
protected GuiTextField field;
|
||||
|
||||
private static final int maxSearchLength = 256;
|
||||
protected static final int maxSearchLength = 256;
|
||||
|
||||
public boolean centered;
|
||||
public String identifier;
|
||||
@@ -23,7 +25,7 @@ public abstract class TextField extends Widget {
|
||||
public TextField(String ident) {
|
||||
identifier = ident;
|
||||
initInternalTextField();
|
||||
// Keyboard.enableRepeatEvents(true);
|
||||
// Keyboard.enableRepeatEvents(true);
|
||||
}
|
||||
|
||||
public int getTextColour() {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
|
||||
public class ThreadOperationTimer extends Thread {
|
||||
@SuppressWarnings("serial")
|
||||
|
||||
public static class TimeoutException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -8621458005263888185L;
|
||||
public final Object operation;
|
||||
|
||||
public TimeoutException(String msg, Object op) {
|
||||
@@ -48,10 +51,13 @@ public class ThreadOperationTimer extends Thread {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void run() {
|
||||
if (FMLCommonHandler.instance()
|
||||
.findContainerFor("NotEnoughItems")
|
||||
.getVersion()
|
||||
.contains("$")) return; // don't run this thread in a source environment
|
||||
if (FMLCommonHandler.instance().findContainerFor("NotEnoughItems").getVersion().contains("$")) return; // don't
|
||||
// run
|
||||
// this
|
||||
// thread
|
||||
// in a
|
||||
// source
|
||||
// environment
|
||||
|
||||
while (thread.isAlive()) {
|
||||
synchronized (this) {
|
||||
@@ -63,8 +69,7 @@ public class ThreadOperationTimer extends Thread {
|
||||
}
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException ie) {
|
||||
}
|
||||
} catch (InterruptedException ie) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
public class VisiblityData {
|
||||
|
||||
public boolean showUtilityButtons = true;
|
||||
/**
|
||||
* Item panel and associated buttons
|
||||
@@ -14,10 +15,6 @@ public class VisiblityData {
|
||||
* Subset dropdown
|
||||
*/
|
||||
public boolean showSubsetDropdown = true;
|
||||
/**
|
||||
* Presets dropdown
|
||||
*/
|
||||
public boolean showPresetsDropdown = true;
|
||||
/**
|
||||
* Item and search section
|
||||
*/
|
||||
@@ -43,7 +40,6 @@ public class VisiblityData {
|
||||
public void translateDependancies() {
|
||||
if (!showNEI) showWidgets = false;
|
||||
if (!showWidgets) showItemSection = showUtilityButtons = false;
|
||||
if (!showItemSection)
|
||||
showBookmarkPanel = showSubsetDropdown = showPresetsDropdown = showSearchSection = showItemPanel = false;
|
||||
if (!showItemSection) showBookmarkPanel = showSubsetDropdown = showSearchSection = showItemPanel = false;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,21 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
|
||||
public abstract class Widget {
|
||||
|
||||
public Widget() {}
|
||||
|
||||
public abstract void draw(int mx, int my);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package codechicken.nei;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class WidgetZOrder implements Comparator<Widget> {
|
||||
|
||||
final boolean topfirst;
|
||||
|
||||
public WidgetZOrder(boolean topfirst) {
|
||||
@@ -10,6 +11,6 @@ public class WidgetZOrder implements Comparator<Widget> {
|
||||
}
|
||||
|
||||
public int compare(Widget w1, Widget w2) {
|
||||
return w1.z != w2.z ? ((topfirst ? w1.z > w2.z : w1.z < w2.z) ? 1 : -1) : 1;
|
||||
return w1.z != w2.z ? ((topfirst ? w1.z < w2.z : w1.z > w2.z) ? 1 : -1) : 1;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,24 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import codechicken.lib.math.MathHelper;
|
||||
import codechicken.lib.render.RenderUtils;
|
||||
import codechicken.nei.KeyManager.IKeyStateTracker;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EnumCreatureType;
|
||||
import net.minecraft.entity.passive.EntityPig;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.world.EnumSkyBlock;
|
||||
import net.minecraft.world.SpawnerAnimals;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.biome.BiomeGenBase;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.math.MathHelper;
|
||||
import codechicken.nei.KeyManager.IKeyStateTracker;
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||
|
||||
public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
|
||||
public static int chunkOverlay = 0;
|
||||
@@ -22,10 +26,12 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
public static int mobOverlay = 0;
|
||||
private static byte[] mobSpawnCache;
|
||||
private static long mobOverlayUpdateTime;
|
||||
private static String oregenPatternName;
|
||||
|
||||
public static void reset() {
|
||||
mobOverlay = 0;
|
||||
chunkOverlay = 0;
|
||||
oregenPatternName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -33,17 +39,31 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
if (Minecraft.getMinecraft().currentScreen != null) return;
|
||||
|
||||
if (KeyManager.keyStates.get("world.moboverlay").down) mobOverlay = (mobOverlay + 1) % 2;
|
||||
if (KeyManager.keyStates.get("world.chunkoverlay").down)
|
||||
if (KeyManager.keyStates.get("world.chunkoverlay").down) {
|
||||
chunkOverlay = (chunkOverlay + 1) % (NEIModContainer.isGT5Loaded() ? 4 : 3);
|
||||
// 0-2 (or 3 with gt)
|
||||
NEIClientUtils.printChatMessage(
|
||||
new ChatComponentText(NEIClientUtils.translate("chat.chunkoverlay." + chunkOverlay)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void render(float frame) {
|
||||
GL11.glPushMatrix();
|
||||
Entity entity = Minecraft.getMinecraft().renderViewEntity;
|
||||
RenderUtils.translateToWorldCoords(entity, frame);
|
||||
|
||||
renderChunkBounds(entity);
|
||||
renderMobSpawnOverlay(entity);
|
||||
double interpPosX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * frame;
|
||||
double interpPosY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * frame;
|
||||
double interpPosZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * frame;
|
||||
|
||||
int intOffsetX = (int) interpPosX;
|
||||
int intOffsetY = (int) interpPosY;
|
||||
int intOffsetZ = (int) interpPosZ;
|
||||
|
||||
GL11.glTranslated(-interpPosX + intOffsetX, -interpPosY + intOffsetY, -interpPosZ + intOffsetZ);
|
||||
|
||||
renderChunkBounds(entity, intOffsetX, intOffsetY, intOffsetZ);
|
||||
renderMobSpawnOverlay(entity, intOffsetX, intOffsetY, intOffsetZ);
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
@@ -84,7 +104,7 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderMobSpawnOverlay(Entity entity) {
|
||||
private static void renderMobSpawnOverlay(Entity entity, int intOffsetX, int intOffsetY, int intOffsetZ) {
|
||||
if (mobOverlay == 0) {
|
||||
if (mobSpawnCache != null) {
|
||||
mobSpawnCache = null;
|
||||
@@ -103,15 +123,17 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glLineWidth(1.5F);
|
||||
GL11.glBegin(GL11.GL_LINES);
|
||||
|
||||
GL11.glColor4f(1, 0, 0, 1);
|
||||
int curSpawnMode = 2;
|
||||
|
||||
World world = entity.worldObj;
|
||||
int x1 = (int) entity.posX;
|
||||
int z1 = (int) entity.posZ;
|
||||
int y1 = (int) MathHelper.clip(entity.posY, 16, world.getHeight() - 16);
|
||||
int x1 = (int) entity.posX - intOffsetX;
|
||||
int z1 = (int) entity.posZ - intOffsetZ;
|
||||
int y1 = (int) MathHelper.clip(entity.posY, 16, world.getHeight() - 16) - intOffsetY;
|
||||
|
||||
final Tessellator tess = Tessellator.instance;
|
||||
tess.startDrawing(GL11.GL_LINES);
|
||||
tess.setColorOpaque(255, 0, 0);
|
||||
|
||||
for (int i = 0; i <= 32; i++) {
|
||||
int x = x1 - 16 + i;
|
||||
@@ -130,22 +152,22 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
|
||||
if (spawnMode != curSpawnMode) {
|
||||
if (spawnMode == 1) {
|
||||
GL11.glColor4f(1, 1, 0, 1);
|
||||
tess.setColorOpaque(255, 255, 0);
|
||||
} else {
|
||||
GL11.glColor4f(1, 0, 0, 1);
|
||||
tess.setColorOpaque(255, 0, 0);
|
||||
}
|
||||
curSpawnMode = spawnMode;
|
||||
}
|
||||
|
||||
GL11.glVertex3d(x, y + 0.02, z);
|
||||
GL11.glVertex3d(x + 1, y + 0.02, z + 1);
|
||||
GL11.glVertex3d(x + 1, y + 0.02, z);
|
||||
GL11.glVertex3d(x, y + 0.02, z + 1);
|
||||
tess.addVertex(x, y + 0.02, z);
|
||||
tess.addVertex(x + 1, y + 0.02, z + 1);
|
||||
tess.addVertex(x + 1, y + 0.02, z);
|
||||
tess.addVertex(x, y + 0.02, z + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glEnd();
|
||||
tess.draw();
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
@@ -155,8 +177,8 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
private static final AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(0, 0, 0, 0, 0, 0);
|
||||
|
||||
private static byte getSpawnMode(Chunk chunk, int x, int y, int z) {
|
||||
if (!SpawnerAnimals.canCreatureTypeSpawnAtLocation(EnumCreatureType.monster, chunk.worldObj, x, y, z)
|
||||
|| chunk.getSavedLightValue(EnumSkyBlock.Block, x & 15, y, z & 15) >= 8) {
|
||||
if (chunk.getSavedLightValue(EnumSkyBlock.Block, x & 15, y, z & 15) >= 8
|
||||
|| !SpawnerAnimals.canCreatureTypeSpawnAtLocation(EnumCreatureType.monster, chunk.worldObj, x, y, z)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -174,7 +196,7 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
return (byte) (chunk.getSavedLightValue(EnumSkyBlock.Sky, x & 15, y, z & 15) >= 8 ? 1 : 2);
|
||||
}
|
||||
|
||||
private static void renderChunkBounds(Entity entity) {
|
||||
private static void renderChunkBounds(Entity entity, int intOffsetX, int intOffsetY, int intOffsetZ) {
|
||||
if (chunkOverlay == 0) return;
|
||||
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
@@ -182,145 +204,179 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glLineWidth(1.5F);
|
||||
GL11.glBegin(GL11.GL_LINES);
|
||||
|
||||
for (int cx = -4; cx <= 4; cx++)
|
||||
for (int cz = -4; cz <= 4; cz++) {
|
||||
double x1 = (entity.chunkCoordX + cx) << 4;
|
||||
double z1 = (entity.chunkCoordZ + cz) << 4;
|
||||
double x2 = x1 + 16;
|
||||
double z2 = z1 + 16;
|
||||
final Tessellator tess = Tessellator.instance;
|
||||
tess.startDrawing(GL11.GL_LINES);
|
||||
|
||||
double dy = 128;
|
||||
double y1 = Math.floor(entity.posY - dy / 2);
|
||||
double y2 = y1 + dy;
|
||||
if (y1 < 0) {
|
||||
y1 = 0;
|
||||
y2 = dy;
|
||||
}
|
||||
for (int cx = -4; cx <= 4; cx++) for (int cz = -4; cz <= 4; cz++) {
|
||||
double x1 = ((entity.chunkCoordX + cx) << 4) - intOffsetX;
|
||||
double z1 = ((entity.chunkCoordZ + cz) << 4) - intOffsetZ;
|
||||
double x2 = x1 + 16;
|
||||
double z2 = z1 + 16;
|
||||
|
||||
if (y1 > entity.worldObj.getHeight()) {
|
||||
y2 = entity.worldObj.getHeight();
|
||||
y1 = y2 - dy;
|
||||
}
|
||||
double dy = 128;
|
||||
double y1 = Math.floor(entity.posY - dy / 2);
|
||||
double y2 = y1 + dy;
|
||||
if (y1 < 0) {
|
||||
y1 = 0;
|
||||
y2 = dy;
|
||||
}
|
||||
|
||||
double dist = Math.pow(1.5, -(cx * cx + cz * cz));
|
||||
if (y1 > entity.worldObj.getHeight()) {
|
||||
y2 = entity.worldObj.getHeight();
|
||||
y1 = y2 - dy;
|
||||
}
|
||||
|
||||
GL11.glColor4d(0.9, 0, 0, dist);
|
||||
if (cx >= 0 && cz >= 0) {
|
||||
GL11.glVertex3d(x2, y1, z2);
|
||||
GL11.glVertex3d(x2, y2, z2);
|
||||
}
|
||||
if (cx >= 0 && cz <= 0) {
|
||||
GL11.glVertex3d(x2, y1, z1);
|
||||
GL11.glVertex3d(x2, y2, z1);
|
||||
}
|
||||
if (cx <= 0 && cz >= 0) {
|
||||
GL11.glVertex3d(x1, y1, z2);
|
||||
GL11.glVertex3d(x1, y2, z2);
|
||||
}
|
||||
if (cx <= 0 && cz <= 0) {
|
||||
GL11.glVertex3d(x1, y1, z1);
|
||||
GL11.glVertex3d(x1, y2, z1);
|
||||
}
|
||||
y1 -= intOffsetY;
|
||||
y2 -= intOffsetY;
|
||||
|
||||
if (cx == 0 && cz == 0) {
|
||||
if (chunkOverlay == 2) {
|
||||
dy = 32;
|
||||
y1 = Math.floor(entity.posY - dy / 2);
|
||||
y2 = y1 + dy;
|
||||
if (y1 < 0) {
|
||||
y1 = 0;
|
||||
y2 = dy;
|
||||
}
|
||||
double dist = Math.pow(1.5, -(cx * cx + cz * cz));
|
||||
|
||||
if (y1 > entity.worldObj.getHeight()) {
|
||||
y2 = entity.worldObj.getHeight();
|
||||
y1 = y2 - dy;
|
||||
}
|
||||
tess.setColorRGBA_F(0.9F, 0, 0, (float) dist);
|
||||
if (cx >= 0 && cz >= 0) {
|
||||
tess.addVertex(x2, y1, z2);
|
||||
tess.addVertex(x2, y2, z2);
|
||||
}
|
||||
if (cx >= 0 && cz <= 0) {
|
||||
tess.addVertex(x2, y1, z1);
|
||||
tess.addVertex(x2, y2, z1);
|
||||
}
|
||||
if (cx <= 0 && cz >= 0) {
|
||||
tess.addVertex(x1, y1, z2);
|
||||
tess.addVertex(x1, y2, z2);
|
||||
}
|
||||
if (cx <= 0 && cz <= 0) {
|
||||
tess.addVertex(x1, y1, z1);
|
||||
tess.addVertex(x1, y2, z1);
|
||||
}
|
||||
|
||||
GL11.glColor4d(0, 0.9, 0, 0.4);
|
||||
for (double y = (int) y1; y <= y2; y++) {
|
||||
GL11.glVertex3d(x2, y, z1);
|
||||
GL11.glVertex3d(x2, y, z2);
|
||||
GL11.glVertex3d(x1, y, z1);
|
||||
GL11.glVertex3d(x1, y, z2);
|
||||
GL11.glVertex3d(x1, y, z2);
|
||||
GL11.glVertex3d(x2, y, z2);
|
||||
GL11.glVertex3d(x1, y, z1);
|
||||
GL11.glVertex3d(x2, y, z1);
|
||||
}
|
||||
for (double h = 1; h <= 15; h++) {
|
||||
GL11.glVertex3d(x1 + h, y1, z1);
|
||||
GL11.glVertex3d(x1 + h, y2, z1);
|
||||
GL11.glVertex3d(x1 + h, y1, z2);
|
||||
GL11.glVertex3d(x1 + h, y2, z2);
|
||||
GL11.glVertex3d(x1, y1, z1 + h);
|
||||
GL11.glVertex3d(x1, y2, z1 + h);
|
||||
GL11.glVertex3d(x2, y1, z1 + h);
|
||||
GL11.glVertex3d(x2, y2, z1 + h);
|
||||
}
|
||||
} else if (chunkOverlay == 3) {
|
||||
int gx1 = ((entity.chunkCoordX < 0 ? entity.chunkCoordX - 3 : entity.chunkCoordX) / 3 * 3) << 4;
|
||||
int gz1 = ((entity.chunkCoordZ < 0 ? entity.chunkCoordZ - 3 : entity.chunkCoordZ) / 3 * 3) << 4;
|
||||
if (cx == 0 && cz == 0) {
|
||||
if (chunkOverlay == 2) {
|
||||
dy = 32;
|
||||
y1 = Math.floor(entity.posY - dy / 2);
|
||||
y2 = y1 + dy;
|
||||
if (y1 < 0) {
|
||||
y1 = 0;
|
||||
y2 = dy;
|
||||
}
|
||||
|
||||
if (y1 > entity.worldObj.getHeight()) {
|
||||
y2 = entity.worldObj.getHeight();
|
||||
y1 = y2 - dy;
|
||||
}
|
||||
|
||||
y1 -= intOffsetY;
|
||||
y2 -= intOffsetY;
|
||||
|
||||
tess.setColorRGBA_F(0, 0.9F, 0, 0.4F);
|
||||
for (double y = (int) y1; y <= y2; y++) {
|
||||
tess.addVertex(x2, y, z1);
|
||||
tess.addVertex(x2, y, z2);
|
||||
tess.addVertex(x1, y, z1);
|
||||
tess.addVertex(x1, y, z2);
|
||||
tess.addVertex(x1, y, z2);
|
||||
tess.addVertex(x2, y, z2);
|
||||
tess.addVertex(x1, y, z1);
|
||||
tess.addVertex(x2, y, z1);
|
||||
}
|
||||
for (double h = 1; h <= 15; h++) {
|
||||
tess.addVertex(x1 + h, y1, z1);
|
||||
tess.addVertex(x1 + h, y2, z1);
|
||||
tess.addVertex(x1 + h, y1, z2);
|
||||
tess.addVertex(x1 + h, y2, z2);
|
||||
tess.addVertex(x1, y1, z1 + h);
|
||||
tess.addVertex(x1, y2, z1 + h);
|
||||
tess.addVertex(x2, y1, z1 + h);
|
||||
tess.addVertex(x2, y2, z1 + h);
|
||||
}
|
||||
} else if (chunkOverlay == 3) {
|
||||
int gx1;
|
||||
int gz1;
|
||||
if (getOregenPatternName().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;
|
||||
|
||||
GL11.glColor4d(0, 0.9, 0, 0.4);
|
||||
for (double y = (int) y1; y <= y2; y++) {
|
||||
GL11.glVertex3d(gx2, y, gz1);
|
||||
GL11.glVertex3d(gx2, y, gz2);
|
||||
GL11.glVertex3d(gx1, y, gz1);
|
||||
GL11.glVertex3d(gx1, y, gz2);
|
||||
GL11.glVertex3d(gx1, y, gz2);
|
||||
GL11.glVertex3d(gx2, y, gz2);
|
||||
GL11.glVertex3d(gx1, y, gz1);
|
||||
GL11.glVertex3d(gx2, y, gz1);
|
||||
}
|
||||
for (double h = 4; h <= 44; h += 4) {
|
||||
if (h % 16 == 0) {
|
||||
continue;
|
||||
}
|
||||
GL11.glVertex3d(gx1 + h, y1, gz1);
|
||||
GL11.glVertex3d(gx1 + h, y2, gz1);
|
||||
GL11.glVertex3d(gx1 + h, y1, gz2);
|
||||
GL11.glVertex3d(gx1 + h, y2, gz2);
|
||||
GL11.glVertex3d(gx1, y1, gz1 + h);
|
||||
GL11.glVertex3d(gx1, y2, gz1 + h);
|
||||
GL11.glVertex3d(gx2, y1, gz1 + h);
|
||||
GL11.glVertex3d(gx2, y2, gz1 + h);
|
||||
}
|
||||
|
||||
GL11.glColor4d(0, 0, 0.9, 0.4);
|
||||
gx1 += 23;
|
||||
gz1 += 23;
|
||||
gx2 = gx1 + 1;
|
||||
gz2 = gz1 + 1;
|
||||
|
||||
GL11.glVertex3d(gx1, y1, gz1);
|
||||
GL11.glVertex3d(gx1, y2, gz1);
|
||||
GL11.glVertex3d(gx2, y1, gz1);
|
||||
GL11.glVertex3d(gx2, y2, gz1);
|
||||
GL11.glVertex3d(gx1, y1, gz2);
|
||||
GL11.glVertex3d(gx1, y2, gz2);
|
||||
GL11.glVertex3d(gx2, y1, gz2);
|
||||
GL11.glVertex3d(gx2, y2, gz2);
|
||||
}
|
||||
int gx2 = gx1 + 48;
|
||||
int gz2 = gz1 + 48;
|
||||
|
||||
tess.setColorRGBA_F(0, 0.9F, 0, 0.4F);
|
||||
for (double y = (int) y1; y <= y2; y++) {
|
||||
tess.addVertex(gx2, y, gz1);
|
||||
tess.addVertex(gx2, y, gz2);
|
||||
tess.addVertex(gx1, y, gz1);
|
||||
tess.addVertex(gx1, y, gz2);
|
||||
tess.addVertex(gx1, y, gz2);
|
||||
tess.addVertex(gx2, y, gz2);
|
||||
tess.addVertex(gx1, y, gz1);
|
||||
tess.addVertex(gx2, y, gz1);
|
||||
}
|
||||
for (double h = 4; h <= 44; h += 4) {
|
||||
if (h % 16 == 0) {
|
||||
continue;
|
||||
}
|
||||
tess.addVertex(gx1 + h, y1, gz1);
|
||||
tess.addVertex(gx1 + h, y2, gz1);
|
||||
tess.addVertex(gx1 + h, y1, gz2);
|
||||
tess.addVertex(gx1 + h, y2, gz2);
|
||||
tess.addVertex(gx1, y1, gz1 + h);
|
||||
tess.addVertex(gx1, y2, gz1 + h);
|
||||
tess.addVertex(gx2, y1, gz1 + h);
|
||||
tess.addVertex(gx2, y2, gz1 + h);
|
||||
}
|
||||
|
||||
tess.setColorRGBA_F(0, 0, 0.9F, 0.4F);
|
||||
gx1 += 23;
|
||||
gz1 += 23;
|
||||
gx2 = gx1 + 1;
|
||||
gz2 = gz1 + 1;
|
||||
|
||||
tess.addVertex(gx1, y1, gz1);
|
||||
tess.addVertex(gx1, y2, gz1);
|
||||
tess.addVertex(gx2, y1, gz1);
|
||||
tess.addVertex(gx2, y2, gz1);
|
||||
tess.addVertex(gx1, y1, gz2);
|
||||
tess.addVertex(gx1, y2, gz2);
|
||||
tess.addVertex(gx2, y1, gz2);
|
||||
tess.addVertex(gx2, y2, gz2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glEnd();
|
||||
tess.draw();
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
|
||||
private static String getOregenPatternName() {
|
||||
|
||||
if (oregenPatternName == null) {
|
||||
try {
|
||||
final ClassLoader loader = WorldOverlayRenderer.class.getClassLoader();
|
||||
final Class<?> gtWorldGenerator = ReflectionHelper
|
||||
.getClass(loader, "gregtech.common.GTWorldgenerator", "gregtech.common.GT_Worldgenerator");
|
||||
oregenPatternName = ((Enum<?>) gtWorldGenerator.getDeclaredField("oregenPattern").get(null)).name();
|
||||
} catch (Exception ignored) {
|
||||
oregenPatternName = "AXISSYMMETRICAL";
|
||||
}
|
||||
}
|
||||
|
||||
return oregenPatternName;
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
KeyManager.trackers.add(new WorldOverlayRenderer());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
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;
|
||||
@@ -10,13 +25,16 @@ import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.OffsetPositioner;
|
||||
import codechicken.nei.SearchField;
|
||||
import codechicken.nei.SearchField.ISearchProvider;
|
||||
import codechicken.nei.SearchTokenParser.ISearchParserProvider;
|
||||
import codechicken.nei.SubsetWidget;
|
||||
import codechicken.nei.SubsetWidget.SubsetTag;
|
||||
import codechicken.nei.api.IRecipeFilter.IRecipeFilterProvider;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.config.Option;
|
||||
import codechicken.nei.config.OptionKeyBind;
|
||||
import codechicken.nei.recipe.CatalystInfo;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.GuiUsageRecipe;
|
||||
import codechicken.nei.recipe.ICraftingHandler;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
@@ -24,22 +42,14 @@ import codechicken.nei.recipe.IUsageHandler;
|
||||
import codechicken.nei.recipe.RecipeCatalysts;
|
||||
import codechicken.nei.recipe.RecipeInfo;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import codechicken.nei.util.ItemStackFilterParser;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
*/
|
||||
public class API {
|
||||
|
||||
/**
|
||||
* Register a new Crafting Recipe handler;
|
||||
*
|
||||
@@ -62,8 +72,7 @@ public class API {
|
||||
* Add a gui to the default overlay renderer with the default position
|
||||
*
|
||||
* @param classz The class of your gui
|
||||
* @param ident The identification string, currently
|
||||
* {crafting, crafting2x2, smelting, fuel, brewing}
|
||||
* @param ident The identification string, currently {crafting, crafting2x2, smelting, fuel, brewing}
|
||||
*/
|
||||
public static void registerGuiOverlay(Class<? extends GuiContainer> classz, String ident) {
|
||||
registerGuiOverlay(classz, ident, 5, 11);
|
||||
@@ -73,8 +82,7 @@ public class API {
|
||||
* Add a gui to the default overlay renderer with an offset
|
||||
*
|
||||
* @param classz The class of your gui
|
||||
* @param ident The identification string, currently
|
||||
* {crafting, crafting2x2, smelting, fuel, brewing}
|
||||
* @param ident The identification string, currently {crafting, crafting2x2, smelting, fuel, brewing}
|
||||
* @param x x-offset
|
||||
* @param y y-offset
|
||||
*/
|
||||
@@ -86,12 +94,11 @@ public class API {
|
||||
* Add a gui to the default overlay renderer
|
||||
*
|
||||
* @param classz The class of your gui
|
||||
* @param ident The identification string, currently
|
||||
* {crafting, crafting2x2, smelting, fuel, brewing}
|
||||
* @param ident The identification string, currently {crafting, crafting2x2, smelting, fuel, brewing}
|
||||
* @param positioner A Stack Repositioner for moving the items to the right place
|
||||
*/
|
||||
public static void registerGuiOverlay(
|
||||
Class<? extends GuiContainer> classz, String ident, IStackPositioner positioner) {
|
||||
public static void registerGuiOverlay(Class<? extends GuiContainer> classz, String ident,
|
||||
IStackPositioner positioner) {
|
||||
RecipeInfo.registerGuiOverlay(classz, ident, positioner);
|
||||
}
|
||||
|
||||
@@ -100,13 +107,22 @@ public class API {
|
||||
* @param handler The handler to register
|
||||
* @param ident The recipe identification string
|
||||
*/
|
||||
public static void registerGuiOverlayHandler(
|
||||
Class<? extends GuiContainer> classz, IOverlayHandler handler, String ident) {
|
||||
public static void registerGuiOverlayHandler(Class<? extends GuiContainer> classz, IOverlayHandler handler,
|
||||
String ident) {
|
||||
RecipeInfo.registerOverlayHandler(classz, handler, ident);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the offset to be added to items to translate them into recipe coords on the actual gui, default is 5, 11. Primarily RecipeTransferRects
|
||||
* @param classz The class of your gui
|
||||
* @param ident The recipe identification string
|
||||
*/
|
||||
public static boolean hasGuiOverlayHandler(Class<? extends GuiContainer> classz, String ident) {
|
||||
return RecipeInfo.hasOverlayHandler(classz, ident);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the offset to be added to items to translate them into recipe coords on the actual gui, default is 5, 11.
|
||||
* Primarily RecipeTransferRects
|
||||
*
|
||||
* @param classz The class of your gui
|
||||
* @param x
|
||||
@@ -126,29 +142,44 @@ public class API {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide an item from the item panel
|
||||
* Damage values of OreDictionary.WILDCARD_VALUE and ItemStackMap.WILDCARD_TAG tags function as wildcards for their respective variables
|
||||
* Hide an item from the item panel Damage values of OreDictionary.WILDCARD_VALUE and ItemStackMap.WILDCARD_TAG tags
|
||||
* function as wildcards for their respective variables
|
||||
*/
|
||||
public static void hideItem(ItemStack item) {
|
||||
ItemInfo.hiddenItems.add(item);
|
||||
LayoutManager.markItemsDirty();
|
||||
if (!ItemInfo.hiddenItems.contains(item)) {
|
||||
ItemInfo.hiddenItems.add(item);
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public static void hideItem(String rule) {
|
||||
ItemFilter filter = ItemStackFilterParser.parse(rule);
|
||||
if (filter != null) {
|
||||
ItemInfo.hiddenItemsRules.filters.add(filter);
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or replace the name normally shown on the item tooltip
|
||||
*/
|
||||
public static void setOverrideName(ItemStack item, String name) {
|
||||
ItemInfo.nameOverrides.put(item, name);
|
||||
LayoutManager.markItemsDirty();
|
||||
if (!name.equals(ItemInfo.nameOverrides.get(item))) {
|
||||
ItemInfo.nameOverrides.put(item, name);
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the item panel. Any items added using this function will override the default search pattern.
|
||||
*
|
||||
* @param item an item with data
|
||||
*/
|
||||
public static void addItemListEntry(ItemStack item) {
|
||||
ItemInfo.itemOverrides.put(item.getItem(), item);
|
||||
LayoutManager.markItemsDirty();
|
||||
if (!ItemInfo.itemOverrides.containsEntry(item.getItem(), item)) {
|
||||
ItemInfo.itemOverrides.put(item.getItem(), item);
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,12 +187,15 @@ public class API {
|
||||
*/
|
||||
public static void setItemListEntries(Item item, Iterable<ItemStack> items) {
|
||||
if (items == null) items = Collections.emptyList();
|
||||
ItemInfo.itemOverrides.replaceValues(item, items);
|
||||
LayoutManager.markItemsDirty();
|
||||
if (!Sets.newHashSet(items).equals(Sets.newHashSet(ItemInfo.itemOverrides.get(item)))) {
|
||||
ItemInfo.itemOverrides.replaceValues(item, items);
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom KeyBinding to be configured in the Controls menu.
|
||||
*
|
||||
* @param ident An identifier for your key, eg "shoot"
|
||||
* @param defaultKey The default value, commonly obtained from {@link Keyboard}
|
||||
*/
|
||||
@@ -173,6 +207,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Add a custom KeyBinding to be configured in the Controls menu.
|
||||
*
|
||||
* @param ident An identifier for your key, eg "shoot"
|
||||
* @param defaultKey The default value, commonly obtained from {@link Keyboard}
|
||||
*/
|
||||
@@ -187,6 +222,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Add a new Layout Style for the NEI interface
|
||||
*
|
||||
* @param styleID The Unique ID to be used for storing your style in the config and cycling through avaliable styles
|
||||
* @param style The style to add.
|
||||
*/
|
||||
@@ -196,6 +232,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Registers a new Infinite Item Handler.
|
||||
*
|
||||
* @param handler The handler to be registered.
|
||||
*/
|
||||
public static void addInfiniteItemHandler(IInfiniteItemHandler handler) {
|
||||
@@ -204,6 +241,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Registers a new Infinite Item Handler.
|
||||
*
|
||||
* @param block The block to handle, null for all.
|
||||
* @param handler The handler to be registered.
|
||||
*/
|
||||
@@ -213,6 +251,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Tells NEI not to perform any Fast Transfer operations on slots of a particular class
|
||||
*
|
||||
* @param slotClass The class of slot to be exempted
|
||||
*/
|
||||
public static void addFastTransferExemptSlot(Class<? extends Slot> slotClass) {
|
||||
@@ -221,8 +260,10 @@ public class API {
|
||||
|
||||
/**
|
||||
* Register a new text handler for the block highlight tooltip with a layout specification (HEADER, BODY or FOOTER).
|
||||
*
|
||||
* @param handler The handler to be registered.
|
||||
* @param layout A HUDAugmenterRegistry.Layout entry. HEADER is displayed before BODY which is displayed before FOOTER.
|
||||
* @param layout A HUDAugmenterRegistry.Layout entry. HEADER is displayed before BODY which is displayed before
|
||||
* FOOTER.
|
||||
*/
|
||||
public static void registerHighlightHandler(IHighlightHandler handler, ItemInfo.Layout... layout) {
|
||||
ItemInfo.registerHighlightHandler(handler, layout);
|
||||
@@ -230,14 +271,22 @@ public class API {
|
||||
|
||||
/**
|
||||
* Register a mode handler for overriding NEI recipe/utility/cheat mode settings.
|
||||
*
|
||||
* @param handler The handler to be registered.
|
||||
*/
|
||||
public static void registerModeHandler(INEIModeHandler handler) {
|
||||
NEIInfo.modeHandlers.add(handler);
|
||||
}
|
||||
|
||||
public static void addRecipeFilter(IRecipeFilterProvider filterProvider) {
|
||||
synchronized (GuiRecipe.recipeFilterers) {
|
||||
GuiRecipe.recipeFilterers.add(filterProvider);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a filter provider for the item panel.
|
||||
*
|
||||
* @param filterProvider The filter provider to be registered.
|
||||
*/
|
||||
public static void addItemFilter(ItemFilterProvider filterProvider) {
|
||||
@@ -248,7 +297,8 @@ public class API {
|
||||
|
||||
/**
|
||||
* Adds a new tag to the item subset dropdown.
|
||||
* @param name The fully qualified name, Eg Blocks.MobSpawners. NOT case sensitive
|
||||
*
|
||||
* @param name The fully qualified name, Eg Blocks.MobSpawners. NOT case sensitive
|
||||
* @param filter A filter for matching items that fit in this subset
|
||||
*/
|
||||
public static void addSubset(String name, ItemFilter filter) {
|
||||
@@ -257,7 +307,8 @@ public class API {
|
||||
|
||||
/**
|
||||
* Adds a new tag to the item subset dropdown.
|
||||
* @param name The fully qualified name, Eg Blocks.MobSpawners. NOT case sensitive
|
||||
*
|
||||
* @param name The fully qualified name, Eg Blocks.MobSpawners. NOT case sensitive
|
||||
* @param items An iterable of itemstacks to be added as a subset
|
||||
*/
|
||||
public static void addSubset(String name, Iterable<ItemStack> items) {
|
||||
@@ -273,29 +324,38 @@ public class API {
|
||||
SubsetWidget.addTag(tag);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void addSearchProvider(ISearchProvider provider) {}
|
||||
|
||||
/**
|
||||
* Adds a new search provider to the search field
|
||||
*/
|
||||
public static void addSearchProvider(ISearchProvider provider) {
|
||||
SearchField.searchProviders.add(provider);
|
||||
public static void addSearchProvider(ISearchParserProvider provider) {
|
||||
SearchField.searchParser.addProvider(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new sorting option to the item panel sort menu
|
||||
* @param name A unique id for this sort option. Will be used in the config for saving and translated in the options gui. Note that if the translation key name.tip exists, it will be used for a tooltip
|
||||
*
|
||||
* @param name A unique id for this sort option. Will be used in the config for saving and translated in the options
|
||||
* gui. Note that if the translation key name.tip exists, it will be used for a tooltip
|
||||
*/
|
||||
public static void addSortOption(String name, Comparator<ItemStack> comparator) {
|
||||
ItemSorter.add(name, comparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an additional item list entry for an item, sorted after the rest of the items are found through the normal process
|
||||
* @param item The item to add the variant for
|
||||
* Adds an additional item list entry for an item, sorted after the rest of the items are found through the normal
|
||||
* process
|
||||
*
|
||||
* @param item The item to add the variant for
|
||||
* @param variant The stack to appear in the item panel
|
||||
*/
|
||||
public static void addItemVariant(Item item, ItemStack variant) {
|
||||
ItemInfo.itemVariants.put(item, variant);
|
||||
LayoutManager.markItemsDirty();
|
||||
if (!ItemInfo.itemVariants.containsEntry(item, variant)) {
|
||||
ItemInfo.itemVariants.put(item, variant);
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public static void registerStackStringifyHandler(IStackStringifyHandler handler) {
|
||||
@@ -303,10 +363,12 @@ public class API {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel Recipes)
|
||||
* Allows players to see what ingredient they need to craft in order to make recipes from a recipe category.
|
||||
* @param stack the ingredient that can craft recipes (like a furnace or crafting table)
|
||||
* @param handler the recipe category handled by the ingredient
|
||||
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel
|
||||
* Recipes) Allows players to see what ingredient they need to craft in order to make recipes from a recipe
|
||||
* category.
|
||||
*
|
||||
* @param stack the ingredient that can craft recipes (like a furnace or crafting table)
|
||||
* @param handler the recipe category handled by the ingredient
|
||||
* @param priority higher priority comes first, default to 0
|
||||
*/
|
||||
public static void addRecipeCatalyst(ItemStack stack, IRecipeHandler handler, int priority) {
|
||||
@@ -322,11 +384,13 @@ public class API {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel Recipes)
|
||||
* Allows players to see what ingredient they need to craft in order to make recipes from a recipe category.
|
||||
* @param stack the ingredient that can craft recipes (like a furnace or crafting table)
|
||||
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel
|
||||
* Recipes) Allows players to see what ingredient they need to craft in order to make recipes from a recipe
|
||||
* category.
|
||||
*
|
||||
* @param stack the ingredient that can craft recipes (like a furnace or crafting table)
|
||||
* @param handlerID recipe category identifier (see also {@link RecipeCatalysts#getRecipeID(IRecipeHandler)})
|
||||
* @param priority higher priority comes first, default to 0
|
||||
* @param priority higher priority comes first, default to 0
|
||||
*/
|
||||
public static void addRecipeCatalyst(ItemStack stack, String handlerID, int priority) {
|
||||
RecipeCatalysts.addRecipeCatalyst(handlerID, new CatalystInfo(stack, priority));
|
||||
@@ -348,6 +412,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) {
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.inventory.Slot;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public class DefaultOverlayRenderer implements IRecipeOverlayRenderer {
|
||||
|
||||
public DefaultOverlayRenderer(List<PositionedStack> ai, IStackPositioner positioner) {
|
||||
positioner = this.positioner = positioner;
|
||||
this.positioner = positioner;
|
||||
ingreds = new ArrayList<>();
|
||||
for (PositionedStack stack : ai) ingreds.add(stack.copy());
|
||||
ingreds = positioner.positionStacks(ingreds);
|
||||
@@ -17,20 +23,26 @@ public class DefaultOverlayRenderer implements IRecipeOverlayRenderer {
|
||||
|
||||
@Override
|
||||
public void renderOverlay(GuiContainerManager gui, Slot slot) {
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(770, 1);
|
||||
GL11.glColor4d(0.6, 0.6, 0.6, 0.7);
|
||||
|
||||
GuiContainerManager.setColouredItemRender(true);
|
||||
for (PositionedStack stack : ingreds) {
|
||||
if (stack.relx == slot.xDisplayPosition && stack.rely == slot.yDisplayPosition)
|
||||
if (stack.relx == slot.xDisplayPosition && stack.rely == slot.yDisplayPosition && !slot.getHasStack()) {
|
||||
GuiContainerManager.drawItem(stack.relx, stack.rely, stack.item);
|
||||
drawHover(stack.relx, stack.rely);
|
||||
}
|
||||
}
|
||||
GuiContainerManager.setColouredItemRender(false);
|
||||
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
private static void drawHover(int x, int y) {
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
drawRect(x, y, 16, 16, 0x66555555);
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
final IStackPositioner positioner;
|
||||
|
||||
Loaded 100 of 250 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user