From e81976e5504cbeea28e448c56f0e7ff3c4eed9fe Mon Sep 17 00:00:00 2001 From: bombcar Date: Mon, 7 Feb 2022 22:26:09 -0600 Subject: [PATCH 001/132] Updatebuild (#10) * update buildscript * voxel * fix CI --- .github/workflows/release-tags.yml | 6 + .gitignore | 4 +- BON2-2.5.0.CUSTOM-all.jar | Bin 722773 -> 0 bytes CODEOWNERS | 3 + addon.gradle | 37 --- build.gradle | 259 +++++++++++++----- dependencies.gradle | 28 +- ...sWorldMap_1.14.1.11_Forge_1.7.10-deobf.jar | Bin 450036 -> 0 bytes ...os_Minimap_21.10.14_Forge_1.7.10-deobf.jar | Bin 743441 -> 0 bytes gradle.properties | 2 +- repositories.gradle | 4 + 11 files changed, 223 insertions(+), 120 deletions(-) delete mode 100644 BON2-2.5.0.CUSTOM-all.jar create mode 100644 CODEOWNERS delete mode 100644 addon.gradle delete mode 100644 dependencies/XaerosWorldMap_1.14.1.11_Forge_1.7.10-deobf.jar delete mode 100644 dependencies/Xaeros_Minimap_21.10.14_Forge_1.7.10-deobf.jar diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml index 25c354b2..c86d8889 100644 --- a/.github/workflows/release-tags.yml +++ b/.github/workflows/release-tags.yml @@ -43,3 +43,9 @@ jobs: prerelease: false title: "${{ env.RELEASE_VERSION }}" files: build/libs/*.jar + + - name: Publish to Maven + run: ./gradlew publish + env: + MAVEN_USER: ${{ secrets.MAVEN_USER }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} diff --git a/.gitignore b/.gitignore index fe92f881..75c41f65 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,6 @@ whitelist.json *.ipr *.iws src/main/resources/mixins.*.json -dependencies/voxelmap*.jar -/data/ *.bat +*.DS_Store +!gradlew.bat diff --git a/BON2-2.5.0.CUSTOM-all.jar b/BON2-2.5.0.CUSTOM-all.jar deleted file mode 100644 index 0445b5edf06cec634e4dc3d773432294e4807aca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 722773 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%0A-sM^c_ylQ=fF2RMN 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�jw5*Acrs;4l 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�}@ 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

K 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 AmjD0& diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..a6b5f68c --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,3 @@ +# Any Github changes require admin approval +/.github/** @GTNewHorizons/admin + diff --git a/addon.gradle b/addon.gradle deleted file mode 100644 index ed7fac06..00000000 --- a/addon.gradle +++ /dev/null @@ -1,37 +0,0 @@ -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath 'de.undercouch:gradle-download-task:4.1.2' - } -} - -import de.undercouch.gradle.tasks.download.Download - -def voxelMapFile = file("data/voxelmap_1.7.0b.jar") -def voxelMapFileDeobf = file("dependencies/voxelmap_1.7.0b-deobf.jar") - -task getVoxelMap(type: Download) { - onlyIf { - !voxelMapFile.exists() - } - src "https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod" //direct link to VoxelMap on CurseForge - dest voxelMapFile - mustRunAfter "deobfBinJar" - mustRunAfter "repackMinecraft" -} - -task deobfVoxelMap(dependsOn: getVoxelMap, type: Exec) { - onlyIf { - !voxelMapFileDeobf.exists() - } - // VoxelMap uese Notch names, so we have to deobfuscate them - // Source for the BON2 version used: https://github.com/glowredman/BON2/tree/Official - commandLine 'java', '-jar', 'BON2-2.5.0.CUSTOM-all.jar', '--inputJar', voxelMapFile, '--outputJar', voxelMapFileDeobf, '--mcVer', '1.7.10', '--mappingsVer', 'stable_12-1.7.10', '--notch' -} - -tasks.setupCIWorkspace.dependsOn deobfVoxelMap -tasks.setupDevWorkspace.dependsOn deobfVoxelMap -tasks.setupDecompWorkspace.dependsOn deobfVoxelMap -tasks.compileJava.dependsOn deobfVoxelMap diff --git a/build.gradle b/build.gradle index e466de0f..b85885a0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,9 @@ -//version: 1641429628 +//version: 1644278435 /* 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/SinTh0r4s/ExampleMod1.7.10/blob/main/build.gradle for updates. +Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/build.gradle for updates. */ @@ -32,17 +32,24 @@ buildscript { } } dependencies { - classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.5' + classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.7' } } plugins { id 'idea' + id 'eclipse' id 'scala' - id("org.ajoberstar.grgit") version("3.1.1") - id("com.github.johnrengelman.shadow") version("4.0.4") - id("com.palantir.git-version") version("0.12.3") - id("maven-publish") + id('org.jetbrains.kotlin.jvm') version ('1.6.10') 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('maven-publish') +} + +if (project.file('.git/HEAD').isFile()) { + apply plugin: 'com.palantir.git-version' } apply plugin: 'forge' @@ -88,27 +95,31 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") +boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false 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("\\.", "/") -if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { - throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala) +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("\\.", "/") - if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { - throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) + 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() == false) { + if(!getFile(targetFile).exists()) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } } @@ -120,15 +131,17 @@ if(usesMixins.toBoolean()) { targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { - throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) + 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" - if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { - throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) + 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) } } @@ -136,8 +149,9 @@ 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" - if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { - throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) + 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) } } @@ -150,13 +164,32 @@ configurations.all { } // Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version -'git config core.fileMode false'.execute() -// Pulls version from git tag try { - version = minecraftVersion + "-" + gitVersion() + 'git config core.fileMode false'.execute() +} +catch (Exception e) { + logger.error("\u001B[31mgit isn't installed at all\u001B[0m") +} + +// 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 e) { - throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!"); + logger.error("\n\u001B[1;31mThis mod must be version controlled by Git AND the repository must provide at least one tag,\n" + + "or the VERSION override must be set! \u001B[32m(Don't download from GitHub using the ZIP option, instead\n" + + "clone the repository, see\u001B[33m https://gtnh.miraheze.org/wiki/Development \u001B[32mfor details.)\u001B[0m\n"); + versionOverride = 'NO-GIT-TAG-SET' + identifiedVersion = versionOverride +} +version = minecraftVersion + '-' + identifiedVersion +String modVersion = identifiedVersion + +if( identifiedVersion.equals(versionOverride) ) { + logger.error('\u001B[31m\u001B[7mWe hope you know what you\'re doing using\u001B[0m\u001B[1;34m ' + modVersion + '\u001B[0m\n'); + logger.error('\7\u001B[31mGoing to blindly try to use\u001B[1;34m ' + modVersion + '\u001B[0m\u001B[31m, this probably won\'t work the way you expect!!\u001B[0m\n'); } group = modGroup @@ -167,6 +200,19 @@ else { archivesBaseName = modId } + +def arguments = [] +def jvmArguments = [] + +if(usesMixins.toBoolean()) { + arguments += [ + "--tweakClass org.spongepowered.asm.launch.MixinTweaker" + ] + jvmArguments += [ + "-Dmixin.debug.countInjections=true", "-Dmixin.debug.verbose=true", "-Dmixin.debug.export=true" + ] +} + minecraft { version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion runDir = "run" @@ -180,12 +226,26 @@ minecraft { replace gradleTokenModName, modName } if(gradleTokenVersion) { - replace gradleTokenVersion, versionDetails().lastTag + 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()) { @@ -223,7 +283,7 @@ dependencies { 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("org.spongepowered:mixin:0.7.11-SNAPSHOT") { + 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" @@ -231,7 +291,7 @@ dependencies { exclude module: "commons-io" exclude module: "log4j-core" } - compile("com.github.GTNewHorizons:SpongeMixins:1.3.3:dev") + compile("com.github.GTNewHorizons:SpongeMixins:1.5.0") } } @@ -317,15 +377,6 @@ afterEvaluate { } runClient { - def arguments = [] - - if(usesMixins.toBoolean()) { - arguments += [ - "--mods=../build/libs/$modId-${version}.jar", - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - } - if(developmentEnvironmentUserName) { arguments += [ "--username", @@ -334,19 +385,12 @@ runClient { } args(arguments) + jvmArgs(jvmArguments) } runServer { - def arguments = [] - - if (usesMixins.toBoolean()) { - arguments += [ - "--mods=../build/libs/$modId-${version}.jar", - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - } - args(arguments) + jvmArgs(jvmArguments) } tasks.withType(JavaExec).configureEach { @@ -362,16 +406,16 @@ 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 version and mcversion expand "minecraftVersion": project.minecraft.version, - "modVersion": versionDetails().lastTag, - "modId": modId, - "modName": modName + "modVersion": modVersion, + "modId": modId, + "modName": modName } if(usesMixins.toBoolean()) { @@ -480,40 +524,63 @@ task apiJar(type: Jar) { } artifacts { - archives sourcesJar + 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 +} + + // publishing publishing { publications { maven(MavenPublication) { - artifact source: jar - artifact source: sourcesJar, classifier: "src" - artifact source: devJar, classifier: "dev" + from components.java + if(usesShadowedDependencies.toBoolean()) { + artifact source: shadowJar, classifier: "" + } + if(!noPublishedSources) { + artifact source: sourcesJar, classifier: "src" + } + artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev" if (apiPackage) { artifact source: apiJar, classifier: "api" } - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: group + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons" artifactId = System.getenv("ARTIFACT_ID") ?: project.name - version = System.getenv("ARTIFACT_VERSION") ?: project.version + // Using the identified version, not project.version as it has the prepended 1.7.10 + version = System.getenv("RELEASE_VERSION") ?: identifiedVersion + + // Remove all non GTNH deps here. + // Original intention was to remove an invalid forgeBin being generated without a groupId (mandatory), but + // it also removes all of the MC deps + pom.withXml { + Node pomNode = asNode() + pomNode.dependencies.'*'.findAll() { + it.groupId.text() != 'com.github.GTNewHorizons' + }.each() { + it.parent().remove(it) + } + } } } - + repositories { maven { - String owner = System.getenv("REPOSITORY_OWNER") ?: "Unknown" - String repositoryName = System.getenv("REPOSITORY_NAME") ?: "Unknown" - String githubRepositoryUrl = "https://maven.pkg.github.com/$owner/$repositoryName" - name = "GitHubPackages" - url = githubRepositoryUrl + url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases" credentials { - username = System.getenv("GITHUB_ACTOR") ?: "NONE" - password = System.getenv("GITHUB_TOKEN") ?: "NONE" + username = System.getenv("MAVEN_USER") ?: "NONE" + password = System.getenv("MAVEN_PASSWORD") ?: "NONE" } } } @@ -537,7 +604,7 @@ if (isNewBuildScriptVersionAvailable(projectDir.toString())) { } static URL availableBuildScriptUrl() { - new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle") + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/build.gradle") } boolean performBuildScriptUpdate(String projectDir) { @@ -575,11 +642,77 @@ configure(updateBuildScript) { description = 'Updates the build script to the latest version' } +// 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 = 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/" + String.valueOf(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 fileName) { + String cacheDir = System.getProperty("user.home") + "/.gradle/caches/" + String bon2Dir = cacheDir + "forge_gradle/deobf" + String bon2File = bon2Dir + "/BON2-2.5.0.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) + } + + download.run { + src 'https://github.com/GTNewHorizons/BON2/releases/download/2.5.0/BON2-2.5.0.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', '1.7.10', '--mappingsVer', 'stable_12', '--notch' + workingDir bon2Dir + standardOutput = new ByteArrayOutputStream() + } + + return files(deobfFile) +} + // Helper methods def checkPropertyExists(String propertyName) { if (project.hasProperty(propertyName) == false) { - 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/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") + 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") } } diff --git a/dependencies.gradle b/dependencies.gradle index b4033245..ede917bd 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,22 +1,16 @@ dependencies { - shadowImplementation("com.github.SinTh0r4s:Enklume:master-SNAPSHOT") + shadowImplementation('com.github.GTNewHorizons:Enklume:master-SNAPSHOT') + compile('com.github.GTNewHorizons:GT5-Unofficial:5.09.40.32:dev') + compile('com.github.GTNewHorizons:TCNodeTracker:1.1.4:dev') - compile("com.github.GTNewHorizons:GT5-Unofficial:master-SNAPSHOT:dev") - compile("com.github.GTNewHorizons:TCNodeTracker:master-SNAPSHOT:dev") + compile('net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev') + compile('curse.maven:journeymap-32274:2367915') + compileOnly(deobf('https://media.forgecdn.net/files/3630/490/Xaeros_Minimap_21.10.20_Forge_1.7.10.jar')) + compileOnly(deobf('https://media.forgecdn.net/files/3599/504/XaerosWorldMap_1.14.1.13_Forge_1.7.10.jar')) + compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) - compile("curse.maven:journeymap-32274:2367915") - compile files("dependencies/Xaeros_Minimap_21.10.14_Forge_1.7.10-deobf.jar") - compile files("dependencies/XaerosWorldMap_1.14.1.11_Forge_1.7.10-deobf.jar") - compileOnly files("dependencies/voxelmap_1.7.0b-deobf.jar") - - compileOnly("com.github.GTNewHorizons:IFU:master-SNAPSHOT:dev") { - transitive = false - } - compileOnly("com.github.GTNewHorizons:GalacticGregGT5:master-SNAPSHOT:dev") { - transitive = false - } - compileOnly("com.github.GTNewHorizons:bartworks:master-SNAPSHOT:dev") { - transitive = false - } + compileOnly('com.github.GTNewHorizons:IFU:master-SNAPSHOT:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.7:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.5.36:dev') {transitive = false} } diff --git a/dependencies/XaerosWorldMap_1.14.1.11_Forge_1.7.10-deobf.jar b/dependencies/XaerosWorldMap_1.14.1.11_Forge_1.7.10-deobf.jar deleted file mode 100644 index e2a0822d6be7a67985cc5b71af62c961a9249900..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 450036 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�P6$DYkJ*8Z-+-kpk#VG8C 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 z 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

`KiXm=TmG5g>|hWFY20fUFQ{)+N% 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

p@R%tcj>MAh)kdG;&ojUL542nWlyJ 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�Py#Ywj5bP0#x&@$*Un3J_8W{!6&4hR*&(3IJZn}{ckRKb? z1r1?OO$rvxN&MotxrL55V_0UTc+UDd54l((WQ=f=xqFG6W_1ll16ojKv(5}=)>Q=A ziT2UzP}h6CZ1TQcd;2*5IVb-r*F%MVQa7FdkExr2KZULT&(O60D?KzfaI`UX`L8?t zuRHv&JN&OZ{I5IwuRHv&JN&OZ{I5IwuRHv&JN&OZ{I5Iw|Ft`0{*OCsR)6J2on7fc z!O{pdp2BBbTOr{lerHMzHP#a=E+S7kR&snFp-gQe7dTZXk1mdhDA{fCX2KL?ikEM z!AZrzTJmDL&O7H@w!e9YXzCmwgf~L6?>G?#v~8TqgFWSk$XAeclA|gQ}C>F$p&A1I?fvOMu#| z07^jIidX_dK=qyHtkNJ*3I&89jtb%UmVmYSd0j~Ji-C|wM{jWaH-D|V+~2+iV*COe zt$J%p#M$U37{uq|?mm^l;Y6{Wre2QdDj4r(}(e&HWPq24Xm4@ZxU#rDJ#wY)t z{({7#%{b#S9kS%n_9z7sycUP1UgUk86>pv$nRG`_jb9>A}WY~jaNtA8IHm;E=c;fjsD9ZROwRLp#u&@wn)!7>Vi-9H~(z?DcZ-x*T zh$@HhbexI)B3xW8+%$@Ctl5L|aL)n0t?RjWbMBVCY(dLRG6M}d^l-Ng& zo`C#^JjLxY7!^w-c%pCOTnQ@_hnhY z*WCFkl+)9#lB1h54mEMRdL?F2&c(AoLM}_leVbRA&BRe`B@#$3UA^={Ej^ZWwVKOR z1h$Rn7@=L0br;EdtxPgVI37r!ns_AqLTDGo#wpCgFDFMre3z-)Rozl7nT!?J&URco ze*kkwf4%dHUN;L@EF?#a-9&;SOqKAP-=dQB4Em_{Z(EWu@5v!;2J%RD3fIfagi1+z z)*5vXX|1!8!#K7Ma+`{3x%0a)RKqme<4mgv9Vy3?&tKKwO7k9%3tNhfZ))$cAbCEc zSVAlgX|{>)<@c*j6&6}2T9~rt7jDtEzWzTVo=4l6J?j?kz>d*fIr;p=I2Ve)>LVso4)I^|`jGOBnNu6XkI@Se` zlSke_x`ok~&^Oac(l^lGUTG?naF=`f@UZCkXFYVBHqtK8PtYiF^rR^=&&V)lP)@RS z(%`tsb<=bX7X!aG-b79=puYYxnB?;GFyWLWR@2eYM!;9D_VnxINg6as=LyHY(pu1z z(Iq8*nVl752yqcD+_SEzmRDuTLa-Y0`t)u|FmIt_hT zk?5QRnz$M=I29RrA7vI*G4(w8KDi%hEe$epoi3F{hpzMXT07XqvE@FHyoIV$EdSDo zsT0nq^onWh@f6wLDAO|~aX`#;{^!zAm>i**SSzItvX0wEa&Q50%{5?#p9~}yYN?0+ zpgK;Kif%l0C4MTW9V;X`c7b0P^bT{EqA*GG`nS^InF0c}BYAp^J)*c7B>M3d;xT0?TK0BwnK~ zrl{;~?I~Vys7qF*Sguc^&)rAVO9$c5<{Wq3_3RMONmtKk&&k~BTn4oOVJ~&QS-ow2 zilL!=njf*Apq^mQ`N;DxPX1xO(NZeOSgD%g+Tz%<{h!dh*KL#v%Iep%YNd8(`W?rr z(mjP2UXKYLn0v2f6}R#EiQ2fOv?UB}x^iY|2AVNU;Z~pZiqi_pN|W~{9zjMO-2(*_ z^Eg+1!4=o!RvS_lGEiR_Z=X`o5+6<|>b z69}?m46E9QEpxwk+f1&)5L3YwUZ{%;>1-sm7;%Pie0ErVT8)t~_Bi8!%Z9++z26laMF=vVcU@ zuM?g%t`k}ms;0}veFM8;8>!sPb^X%fY_C91QYjlQM#s=Z@7PovK41SlmchF28-M?L z`GTmoKgeHd5G?<+dp~I*!0x+A+bf4mQJ;~BsuE5dYvdE|VaeS^8VPp`UsG->PVf#X zudR-EY)H@APu^tDu%pT`q)Xiqr=6#D#y@iyje<(q@qVa>^6O}Sb|mx(@SMv#>UM8! zKEA*BQWbIsa!SAq8ohL@d`k#zMgA@lqgNiqb@F+RoOx8QJg&*EIkDOoW)CAGXSsrL zz`C-8!FuWbMA;#D&+ZZCk~40<3elg-0{7AU%vjvOnxvd@=P6FMW&a)89piUUqC067 zFCU~U{_X0qtagU0D|z9LszW`U0($9C=c(j5rJ76!LW9LAoJ~b&o1J`?5^WfS?FaTw6I&x<>!8}kFY)3()Xd$H zRA$+xlBUqP{@-^xrhXBpHeWZ?w^9m{UO5Z?6ZI48*BW!M)T^EQhdX2S;!R0Pdgixo zJ=Ry>OWEjhUqE@a2vu|C6E>$}>s3*W+mLl;F@eHW`2|CVp0n?GOniVA35ze9VN z{KU#?u;HhZy)sLu2>*c>(G^XTbCIh+P#x7puE6i)xT~jOdAi%UCcq`-2)^pG9=Py} zbB3i%O79N`vp4DMY|0Ei*!)sh&uaQtx4?z*!h=KYtMfm z;uP6gQFc+fDak6s+2C0JX8NGxVQ%fSe64JinMEffHh0&4m8&rmRM9+}0QztxAnmE> zsUN>ON8fpxjs1-_;@gFTXZnuQ{rpi+M(HV9AXxDIb)|N_HGXQ@GC&&E&pdSP{;_r|@-HW0G4EN+vJx z-Sn~pjy2jsPEC%s4Da9hM7H2g@+?}u9&e6Tr(0(+DIlIc`^59PW1oe-z$DO?U{GYv zwfAl%af`WAr|z+XavQ^+{Om_3JZ$h@q*HHgklhMUz_}}6(-#2%^RLEcB*zI$vnWWO z`99|@$=1I;&h%_tgqrKk%~blNZRrg27+r}-M^yNN4!tL)<3)0!0L*eFFp`D35ey{{ zsi0|@=V5M$Q<^85JH_&ln~cX+)Gh`L4#O3m*SaP9IIsB9xO9!CrEU&!hOd^Mb&vn$ zF)8pJq!s&ISSgupw*hg-1qpLio0khs*LnP906j*>5jme#nw%H1 zu2*>M6Os)wqq0c{|GfBYxXP{4r1zqa<$Z-S7iSte%Y*PXt?&Tqy^wZcl-y zjU|Fr8Q?RmO9xQn#6!)zUlayONY(){kPVwXMAu0-*h1;)}nD! z^eixUx_Ckzc(46Z0d3u!gW?B$l z?E4rmO1dRC%q%C5XDeR?{bg3d1rJQ1+lXb@`RC#|A}ggNc~}Xdfh86HzC#?#eccvx zm>V`5??9@(<&9ErR!R8I zY;#y2h`&vGf;W?>tx}NkEVe17l`*`}>R*k0$o>6uFNX|?*9kdowFWc5;`qB#_BcZ{ zVU5le{55AbhjY?~mq}u1=}6Jm?rJ}coV84n)~@9XQw^$lbQ89LBmQ?UTbD=XMIDq} zIdDE^u|yLEgCE(N8u&J)12nmWY9_GrRXJQSTg1fIx|V>#sv>lLCSOwT+$_}kQ_`*j zT!`uuE;GZIDlDy#2!nwaB5|J~C+M)PN0@xG^PjQP@rTMr_6#fV2$O1n=g~|lGs+nF zL>9t}PIhMQrQP9&#h@fnsnn>p%W0!cqnw=61=hb{fb20AhwY6068~-Dh+{7ZZNjlz z6&Jax2Haox0;s4AiPfI=>KATXcC9MIk>y*28G^MMt_V)^G7@8z%=85FwrrR95YC*g zK@Q$+8ps1dB;(o|39|L_I}aw{{_lM$_wuHUejoYfls^ubq|*Bt>1aMROge#EvpJL*z=nQ< z3fm36ha#?eK_Hn~GE0AI5vv-7QaOX_BSMo}z^B0wK$7Rd+|{9(n<5Ox;Q%xOpXwnQ zxD}v}x7$BG%|Ojq!1OMK>n2G-^-7>5#vj9?E#TfSGOsy{Ycx2)p9$Hr7xYFA)c36u z7+@-S?011ms`d0e#P0WaYr!dG@)X(yef+`EEUZBdY5>ZvG1gB}M=Uow4I`$Hxu02m zB7pFnHIaXKVlh;(ej-m#BOdTu8Nke7<_Ircu|F$|$(s&2MUH($8VK`iH^V=nFU)=W=B&9h8I+_n@Je9?rsW z?2BryMV2v<0|uzt$|66p0ru=!N$RNBppZc}`;c_|p|#kRgmO)l{B`g4ym+U?vG12q26K2$>DiQ_lg zGPHy-c;uhM|JB}k$7B7ykN>U|p%hU`$R^o^knHTeL&i;H?@gkVkgV*zlD)Fa$Ozda zBRfJyX2$Q(@~Zn*eZK$v{&>IMkGnUII?r>R>s;qL*SXGlom)BkO0dgj{g<~H53yzh z!zQ)r*+jfTms1%JCckgc#C!Mt87o}lsPizNGhLdyc?uI>&a1gE{ygEg!d-Gj>1E{E zBDv~RHae5TLpt2_#J<#doS8|q=oz18p7XbTiGJCRI6aqq*s4&=DnD6lC@dgOT60T# zsGqGsw*G+5u}Lg^Mh&OzzKi1ic=~)piBjm)gg3G%y!CR)`ya5*Vv}6Y)PC|#H+)zT zMuk!k{N`*5!(hnO5%)wmdxQEF-`N6IQaQ0Y>L-||UGW?4ac9rRr3rlI^w!6oCt6H$ zG89uAN#3wk$f?9a3*yV+U+Q`B<Z%VQwOONSYjah^pdk$0}gp%DOTYJ@0r(zZXw| z^1#y^5(cL?`~5@-W;4VMOu2bD+(d&y^?EK!DjZoIQ*x_ysq@?S+F)}kp@;Xm+C86k z+WDRWOxjoSdRff_RPs%^R+MR1UP~`$Sx@qN;J*4L=;$Wp!gJuV%m0d*RzZ^PmrW0YVZ@8&>VR)qm|KXA=m*ha( zQaEOSx@`Qj1f#^x>lA`LvK6h~EQvQa2GHT+9~_FA>;_9VGe=;vQ5gJauwYp8p{tAg zVVJOzRhNq!QT8>L=~5rvuDKwDgBpaLy0xid#d75M=%jVb)`9IKG2Q39Ri;nCU|!&x zh>^dw&Hle0iTUpeuK%v!`tJ&^|E}Qr?+UK}uHgFb3aMr4@_V zK4NyteQuA}9o3(veW{6_Z_TnthdI@h^E{>zdvg?)*FtJ#r9FHvvMf@P$liYL!_(9S z+g015EA~VCUAIoOVj3IgI}7+R6elGT-MQAX%mR-YVU+jcW1#GFpOs;pte(Xa%YKr} zsBiE%Yk8#R5d|5sdd?Hi=2tS3QnYhrqMlR_?@x1Wo|gM?sgqx6f;;W3qRNFD(p!h9 zRH*gaEXl;w@O zrv~<8p;Rac!uH!eI?ccTnXIkywRwNo8+h=kBePP30a(3W9VkIVu5abb51>;R?=w?- zl6rJS4pk-VAxnqrV?58WDt`2R*~GKa_o4=fN*YiaREilqxGSh$$=4PpF{R>8X7F9C zOrtijlYMa`_PU#rnu4b8>3bMQm1$z9_l0zkRV17mn;Y0yE2+g^fG7F6rZp~8DFlV3 zbR*3hZ=U&zP)&8)=xru?T$uCP-J=l?JUcSajno~VN%~}L=+BiKSLY(=X_2NYm2z

W#cLw^<>+=%Lwf5e@R6`C4OA5&guVzCQ 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«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

-yV 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 *0X<#OuE}(M1)aI-z#g2?L z+UAmCpslXh*yFP|{Ug-JlG#F1gND63X8hRVPd0J{uvYglv59@Up0Os&Dq4XH#f{*i zh}m`_PZS$aUhKmd6Lm78V{m~)rJT`9e%eMUt>#^QP5w)5U9p#D9lWH)gE72ih-GHX zyT@sD1L0pWTdDy*W*zrB6Hwc=+2Ab~ih^r7ZsTEe{QR#lS%V*oUZj%qobr3BY`^mNM<{H*r$!5GC6!A_+<(@|O zZ|G`}WSO{9B1Zm<4J+1cnvy)GPMQm$kVq;ah-UteuBM;$KgU2|IONI=7e`^p#R!!cbh zO{}4!v8mRKDUj$6d5=vtMEGFpIC_WDbyp>u##1dC&J&Rh(e_9+qk4PML*nwO72la- zzyxw0W!nN<;;ZscsVOTKdYFc` zwJ-&><=aAi#3UjX@X!?B0T`13A0%0C%!r2IqXD-I3sBqW`VDtm+nBA78jS)!iZ@c2 z3qJd07O#som3{%sLC*dn3I6>w{vahu?pwg?r6cr(=#$#Q&(xBRfF$e?7v6xn-?nvm>7|d=Et3D?WlWbtFS?bR6Xs7RPXRX)!W)# z*YOvb*5-Q*lUwlRK}(x$(0iA}ll{MDTvG#HY^^a*kZm(mSU8P-dyIyTJ8v3w>6!{l z!hkR1oh~BU0oAe*V~VU+J>Ho!B^k|_pMr5gzi6C!xXTInxm;QEMY?WRJw|aGBtr5O zxntN*3WRn&;o3B&4q{6QlVX)=@>Bao0E%frke%l|=xbt^y@_=BlUo{+*#^1a3`YD1 zg6pUGk2KMMPIw3B;{(gwMcc_r|LNBUb3MyiyJ2B(KV@GAJ>f!Z zYxzYV(u6$j(2~xQmS{@6&ddO5h^7AVOoVB?b!R!0RYkLXI(Hyji^Es92DIu;v(=-+ zs*neIlTc$VoXI{{IlBI_QK9u^iG*S}r8xw7+%R?Rs#|2%X^rS&Y5M{o85Gp8b0s5~ z9;q5eV>QA}Yea>Af-J+{uLWvJQSzR0{r)BE@+({1$^IYvV{g|J_lS1;`ObE|n-3Tj z+EC{x&7KrR9k$6$;tpD&;9L02^~F#c_4Wi+Bn$eONln&!js{dBLzW#8m%?h8_9-7Q zFakIAdoV}HVjeZ@hdilVmtUz^#U}mYw^vh-c+FgQm7*yL&t9)zW{OhCgrC39^ znCFP4>-M0b(=F~D263g=9)N+75n|d!Y`0Jur1-F@J_{4c;-0Hm4=vr}Y;X8%$0Yw# z+AZ?DPpJO1>yUbTG^Bn`ZIIv-AZbmIi-*)}Sr05w`qsZ#Cr>$AiKfUgZ4Fg)7I`bt z+;xbqEr5v!49|6CK7E9?2<1uzT#8tEY1d@;UOeKSZV)$$67fpncUR7ic9_l0Q7i90 z6fIel{#mYK%NLDIBBy$tbdl*-JL#p?L)5lND?$$c(8E`^+iIubA@*IbM19Ps{Ipd0 zLvtIw{v{l*(tOXg7SJ;z1b=l__?^$`N{l9_ly+=2e6P~UkUjiPXu;f(#+vxL3S>vp zN~IMaU?UZy6c(!a^KB6^S$_Wq(v0+@qP28e!m#FEV%#}k_IjE7UgAr(@(xbR^{ zc8jRU&lOULJZocJujZo+tCP>q^f{^VYdfcaRm?J`n&H6OC^vp6%ye~aNiWShRoFtX zc9_erB0eRaeqSk3$jMU4qL3rL0_CZACBAJWIJYxTSaR2RK_Mhvx?=B~>UnGQ9cL_! z$Hk3;c|OzTF2kX-0c!dTaqp6N#TJ0*@$V9`lBeCbVtdyIIh&<8+m)9hBX!Ua6;GT} z8DAM087IgY>dd^2Vyn(D85qrbQ<&36aF`P?&8oYh`9>h_x~Qyt6Xd%3VbLbEYI@|r zaO=1GT0q+ONq=a<2Ff(Thy4Af-H+VnUpU)62OT`Yj5oMrFJ!_Ao3F6lG+s_S*L9$= zta4<(CL2YGws#6>W8bkx0hfY|cj(!o5``reH$(}OtVUR33Aq$r=em3=5kK$PpVDR6 zQ5kM6Y$g4sY zn-AKQ*?g8Zx5;C%rb4#{Tf|UxW{iw|8Bh1PhSFtkH|JA6@i~~GU6;1cMgD2V`K8?b zb`F_Dnof}UwF?CqJr)oq7KE%EmU5nBrc3hV`qhulZNTJb-k9t5Ih6)39t^?=dtgXv zJi@yt)x`6D87Gp?)Z&hHxTl(!D#O>LiEbYNdZW^th zmEIl82lSCiTo@yr<}irVKl~_6(Au?6W&oA{bX*_g8X7KirI?l4(uzMW!8yfXuGK92 z^@k#snsI@%!uj)0QML8SL2JzXF0yk{GQ8zFHLM9`akivFX|97B@)V$%aNIy!+caOh zm`2*mL;p2{OAvmWQips4KEH1mqP*MaG%22qPX05-sbh)zqz2{3-l;YXo_lzEWm%|)vx-c~q5|GnK@ zq6R2_M9*8F5#HvhMPRPSlFu$-xZ|82k?baeL3Q2^xNB7-O;MPeMNq;~oAEy1`F4^z(bABNpVN zi`r7>Kewlryvw~ZYTXKT^H*H>A@z-1=*V3yT!1&?M65_&IWBmOqb@3q24i&!TICap zL%M>H#yb^Qzu?)UeR72|uVc$QeGEadFExOS)!!uhg`DH^AdIXUQjzvlL?`O-Z#?TL zz#juMKe>P8bi3Lc{5RFp!J(MH*=>9 z53yu4$bXvDw+fZxWwpOsiMh&zJIUoV^Q z98EFn6{_LVIqZh8N-J0ly=jV1$M;r)v7%TRP(DGbTb7SydZ*I61KUWQwyoB#&tA+{ zaTF!C$w)2aTMnEF>>(eTuRS+|@)L}hPMy5A+E6t$LN4yO3I^orQexKR9owJ6CR*Fk z8zi)^_R$~FRJQMeu@e0N4!oO-O1N`V?)Ik{(}n!geTp{X!bB~k7ng_fswd^gIaBCx zKPVwG@ujrQ>Qtm@)C(a%0Iq4LSp;ga~SgdxIHc8Xf ztw?A#T&SFK=!TnDbf&0@zii*yPAK>eCv^SkTZ^XkEQx#Vxh;8@F5Bnw4eSMXs=eI_ zc4mdu{j|6ver5{_C*QUH({<_6)G}@jy3{KDG8*s{JgQo3=_mhFpkuXp^u_q718#r2#U6ZsbXr|tse-skS zQr+>r?rk(^$tV^pw^A?b{Yo*4dzy53Byt^we#B?LcO?MyL)!h4e3vZS|CiSmRK8|6 zU|U>>jshqW4Ig}k{Wqv@L9%-iE76ByC&SW;c7O5ulj`7rcd2`b(#2xY?42zZTXeri z1UD1GAz{mu+T?A%_<8FZZ3=MNw3jdn4#(qYv_?eKWsywN$eJ?LK<=@7`=nTOGJp2$ z@oed;s`I3sLv&_cpr+%bVjESlor-PSwr$(CtuMB1+qP{dUH={ST74%yIqRJH9-RH^ zp=!9c$nNR;A(|=+p_eJztTV1P;tadyacV5Aoo}la6I%L0uP-*gZo%$FU1s*1M(>h) zntDIj+sM%@&h-RGU>8_YXKJ?iWZEXAC;Zy zw4KOtqAm7%{03-Ai!6~g4 ze!2j54}?x9G)8VvUSA_jX!g+BzcXcX>9_<#G7dDm1H#Ki9Lw*a2lj1bUUlUshYtr;BGL6<*t}Mp)Po? z1rcY{4WB-1XX6vx^5P-^=_sks=KG;n>nAkZ@0B|Ge8D0%<+fl5msaC=Wbza{YK$?< z9=kPkbBr#T6yx20htOtsYn+t=d&cF@B$HRRxfDb&;Qb3%07yK?kJBa(r;p~6r5-0K z1NMdD;urIZ7<=yfzsfDrDyFoV3AHyk?sZ7rh=NfZM-v_$>s(+5AI#yd~s4k7n5 zSPG1AK8y9Xg4`RD?>ps-(WtV^3Qf*kagMh_f0C{s*tt8nREwI+KH(tZmm!GtfHXk< zmw@jVOH>Q^xUVr5UGr#Pa2a8GI02^1{f;hwRisMB7c{Or3=e@%AtuG9;`1&o8r~zc zM8AkFQ)=DH_Z4iM0*_%B=JZ_VNGso#jhrC(+K>5^A)5A=vX@$r$2?@g)7@m)HhD;? z2dj_6eY9to1d*NzX|FleX%tBkJm5PA83_IhO?aOhTPHQTM8{@Ay>qvs5oDOdZrQs- zUsbu%E03jYpu|nUy|;($Rrz6FAGq=c+>xeqKCY(#FcgL7d2|KqA`Y{7%pC-)a1G%84VA zh`Nu|0w2u z?N2UAu}u!CV0j;F7tKY9``w6A8a$&Sypl(z$u!9C<1!mgMZA1%JI3O<$R_Bm03?=( zAGKAxpBJtPQ~^GprW39a{EqH<4EC;zqmC6&;j=!+lXz{-U#x3d;soU_L?H!a(#6`L zylB!aJA@+b0D3=+_@`hB(c<55GXS-4H)=nPiSYHZnSR+810)0|-A>(+I!CuJbA0?S zVk~#HI;Fy{ns8ad$IYX749f;kl4zF$FyTuUGdC+VAyh`}eBG^{zAn)HF)}T-NV5Gv zvl=pieNbuzO}HlV9a%HWNYmH1EfLm9Hl8KYg+lMmh#SP&{Ce67#M!Fehdo<8CT<R_SZBsPLStgnew}Ui|zyt>~Iog zZ(#d_>gCcajz#wxcgr;$2Ia(6UN*gAU;3nXdL0|hv(T>QKi zo2Eivb@f*?MR&|R^bgm;;}FhVMrfkEST`!5_e*Nrf^MI$pZjH?G48v!Tkd!6--^i4 z4UK_cTAR%);R#wMTOJXp`G$wWPHa(sEtRxMy3&?RwYpR>JmX!IR*rYu%ee^L>|A{d z93JAUWJu$l!&LJgk@9I?7u8#)vBwgU@?ft zHwCoI5bhT+z23JI0YT2!{1@m8?0tv@oixNnbd;NFW-4_3Fqzhw)>!P zq8NT;nkN`pb3*2CpJXmb?ws+uB-GPhGF!V!Q_DW;K{0Uq8?HohrDSt#Dq!C9!}IKgbmlb{%jl+M!` zZthMQo>h^i=yL)-J1Cl&k5h&MnJ%t3V_vql(_VVj4@IrPk6OT|StL!@XHR)QSP)?u zYsBKyIK{PKlo;jNcGFnFZ?RYgXVzuR`%O-<5KW+!n2JVgj3$tT_mp7F<(nK$xc6Ii zPvpe+PK-lyF!wrRdY82D+lLr4v)&c{Y(ihiR&6z?Jc! z6l|2;bUF*p4KYiy3y!qSVX(HGc0iWPdS#OJ8&oj*^C!$XqjGN1ob*THb9kYxKCq9K+!0B^S_K{#DVOw6WKiMkqkVRl z2GrY`5%i$G1Cjf$mWre|pdMcHnzL`M3ORYxtZZuo$2B9*;`3Q4deT{nVJWJ%+fQe( zd6r{aVJhc;h%Wxz3os5ucG&CGnRzx zz>%~ZGHOyK$V*{UVXodO3VB}klnrR6 znl;u#dnt@@sh8_m`QyXRy9Hi)EngDO9h++3G%a^$IO&4_#j!20ZYWUiq%C;mL1gx; zorsn-dZnuUuL=>VfJRt*;5!c@?Go3$*}{}>>!)F!eK3Qh7NOzhPoEnqLmqI02%k8?%71j?oL60DG=k zkd7Mb4|yoj$Eu1yDW{I^(k~id`sw|ITl6p{o3GuQ)uf8SihZ7$&cb-0)WssdAZWby zJ^?%vV9w1!wJeKbXPc=xbk2Ly^DFKlItGa{MkakSpH74~FJzn0m**5kG@uf!OoJ*# z-F`%HcRg8;VK=ljxG3hFfuJ%GzYu#{6@2KZK~npR(n8h+qPv;WS)gRz;8|VSeWn{m zq0cKQIE3%S>GHdQrLw6?Ze5hzKUbr9-NM_!U(Y{iR>ii+v96o-#1XW-^eMCj4fps# zp~Xkk3_qXuYDD?P(#R*9@M?rVKRynMib@7&^K{JnVHa9NPbvGYgr?0+#V@ZDL{{f9 zJNC>pQ|qR&$V6j(W~4M4PD2)EzHg#i?`jKtn5JJ?vPS7yv$Bk~EF-Rmt?#E?l2};Q zLT`|d<>!3`dYIJGBf|~G^ND^j!Uq2xV!C+1$taTNdCp!RTuZ2A4f_oN!+0 zcENgwybYc``PVkR!3dZu(9@oppT)prN&Q)>)6ISia+LG_r=DAT<( zZ)>aT4*=K2yC_ep$(6mRU%pU>)P>@!BIEV)%Nb6nbqP!R-tE3g(PVt?JDzU;?J(?j z=qx$Q=RfBVjW4=K1I}bV6OB1wSPrJf=ffk?LzKVzMRCn-&aM$O>jNIYSg)>wag*|* z9DSJT6cw{z0X^-EGmbSiY5E=(a5BVOItL=zqn7Tg&Br9~9EsyQFZq0~!e)F|Jmt@0 zjjZO$rbEIc$p8+YghhLc{$~K zd7(ZKjza@aDWQBqO(}Hn0>w_eY4nc<7uT4?ekelIPvS)+8uCzcg^U7B4kOmzkm0_V zji~roK*TXUG8L(Q24LHUVxYSD_pdAD`+77sCEqrwqm zGh~K%)4dFy-955d&DYa72YDR+?pwD66{e6TM(*|HZC#f@`}lQU^W6mO=DyC500NC8 zCWv+RMN7zC}BvDuao zuP3ut6!&FUfhT1-@enNT5D*mRCq0)(O!m$o6JCGp;cK10=0r}yIbn&Cm8wIj7^~Io zUT!a$Zx>B9sc6w|eI$w%Xc&lK7s%0zQ~&9_zhc^_)gA@isC@l)%_`e~@N7Lmlxx<5tnf}3+Gkce0(yNs$fkEhD`^mu^{&#o7g zv3n&$sk@&qcz6+eE9Wp=^fhkcWiWxe#KkqLD+;)^DeR@*gb`h0Si`#-_yn2%iu>`l z2KxH$5O-Lx-+Earaim=3s*-I7t7SbI-%^omxEGk2)zYX^+}DzH9HP<$?-9*_Nlx&D z4CHc0voCKvf{2hgEFK$--ED8vY2r#f$h{x^vR-R8(PegT z<7gARb}DzMT`mFWCjLytNdfjK?}0koam6(y1V_ZK>8>bAQyoRPS1)h5bJCSaGF44L z%QwfBuPABw1IMDPhGkQe8<&7PWh`XQv>;3!{ZgF<5>_~A@tX>(ozOErUOp*Ht3O(~ zi&a&vdbvi|4Tc>nT(P_KM-fM40@=I>$Fh@wX&`52QZXtWOv zgzH~op&zGGj}ZFJ0FeFYy+8#)97q+G0}ajAb7(m3K&}bW=%Y&&uoPDB-JX=s%Cwvt zv$B#)vDSk*118qQ7)ZFA*mEj+LG*>0b8A(L?A-r?tqQ!xL*i(;;}?%;NKh?4uC=4W zpUC}bk5{cN2@=?KNeLqkGRb|AAZ-faK&{sla7n_#KTm}RDY&lw$g?95;v(L913maa zruI4$N|f;E$D`9NZBpUfbPnc?@RU94cSGeL+B~JVo(Ey7WeUp=8s?CTWkJeS_$?N$ zlMr{$EPq#8ZG1z@qC%qDi~YJ$63N@%c7*kEhn*{aGFUspE;fdyynluL>yGYF$!I5! ze=;0?xL4mtf}Ee^ z48;k3=<$%h?MUwIfcBOL#6Yu@_wH~U4L3Ws$6vGmOZrA^RGDrwaXp+mKtE^83Qes; zz9b1;4zRx0wDndJHJ<3X^904GgI4XUXKxq$hpiZMmF^+uB=92K7_bO5OECR} z|MV1=Y1Eu0kmX4hm&^0EA%kw3spIVo0(>3`PbS=0^SUw~*2 zbeisHHrD(1x9+LpWSChlD~8>b8D4m$hFkM_@$L~4i1eEOm?Ep;#XdwhNFE%}l*@rUh^I*g*mgy>y=2_2NH{MZ0p$GG46AZ&YX)a-#a7|(2 zkiK|5LTF>+iN&dRNsG%Ylo(||eL9v$6ZG3-j&VGptzpH1#YAdnc76=};W;^7-!wXi zW;FFV!W-nL*pI&qqj=1%#?_AD7i(~Mp_nUl{EC5G?NK1EdyGFE?0-lv`@225-_7FK^?Qg&{=THz%gzi2X(0^5M!>BNc$WY&`<)k zeSw#m5CORIDqL7mu|c0wt1?o!16VXpy~5L+jGn-MQq*y_wo@Ma9`$x(u;|U{k0joz z$L;cwoK_w>ffu(I{i1?g;(ik6hci=4K_CcZO$}zXK6DLBOuo%yKCzCIRx$a1csNZc zopuG!JOx=qSD=%9mL!>MAm)4<(FTAA_VP%?rqj9R48X*f;~SxjH<_5z!nE+PJiR=@ zd95<>3KG-bpx8A4mNYQGtrQ;{2NwPVN+PpcZg9KQGSMiq+W7Rh8q@9JYYv<>w-4fhF58M2<}B3! zY0Y4R_i6IY58-VQ+0+&fabs&sb-1ljhtxHEjD=U-{o67V`*s8yVl}&$o1A`hD|Ltw z8|g8;SijG}x!CBaWh0k{SIeX1!!q;~a#E(DDFYnOJftZYjYno~4YnASq@Q&?Gz;ST zw=0Yi>4#Im`o**FQJ&JK!~T$OX<)%Pq)6wxuV`3z((gB4kubuZjh`QrSckkV-u%wd zw$i${!};H@`)_0q!u-geW50KOf&K&5hfM-oYWV;Go%sH5zfsahtkWs*5gb+o{+ z6?NL>cKd8H5knU2UMB^~)jhSeo#d5m z`W<_sRYQ;D+~T1NQ%-5!X*Q*$wv~sHLK{y3LyztrDfqH2C7k92-z+QCFfZ2z@6_47 zu42YqTYYG??{b>TFCcVx=nJ7|<{VBBJtwMmSs-@*Y5wgdP+9L`Em&@LQF(-nXe43{XpZ!R`)ljqaOIVOc`5ER5Zi-^@; zIVfHr-M=@{z5_=#L9g6cw#wVd0b)LISIF-TLE$^M+VQXYoGH+tk`T8y;8vK7q3a>& zoidV6=nFStvD-9iu30+R2&?yoageuv_@U2`M8&si%BOYZw5bkny6RDk%S%^8GqjJ`fHNX!GD zCAhPh@Awa}-qk^zv6F+;+C!hS124;{QzV60Q8x4QUPk?haC%L_Y}Ou~z4(M_1W^C3 zajO@pXN4RyX-x^roA5sgxb}`jfbrC2@4aUKv^&njrCtwsuhhN zC~DH#7@-;$6?1!UH|gSU`D!v9sD*G9PMw3N zKm6MC_|_El!L8(8rkK8HJJ2Hdp_+iR?=3}XiqSSLw`I%R3H2H;#p7k( zGQR}*FH=XBj`9my*4MwXG!XiDqQDHyXM{3rhLJt)*OU0wUAC*vNrnV3i>@ZuEnV9# z!f6ojI<~whhR||XqR##s`c8O%T4boik5{+~1T0+XhEu>Hf&nCyC&7`A$V%5>ET6p2 zLZ5C!m~f?sN0e{6Vp5-!saez_pAbn%PJT^@Fzz8FE(py?@}B`J7q6cUdy+wYToSam%x88mKE=q&Xn^Z zyY~!f-#_ydNe1f?9j%HHhN{id>q*tlk~uyVFagiQ5*)g@5Rapuoo<73W(FbWtFoHF z%fL@U@x zKuc9^_YX7N(U!`MJGT`#tgDU|Of83>;fFGd%0t>smxyH7(?Ger{1qLvY3(s5(!7`M zfj>pf&%~ZF?u1@;8Yc!`PIlPXZ4w&na}eAeRyfWii6|d0{HJAHuYl~-x`hHra&eO$ ziU{?0h9N>Pbh6RkC$AEmaAV%vM7a5pGkjsx&ItJYjIC#Apx?i8F+tOizUd=x)x&0A zT#q+62~}k*-b?<8C>~@`hH!|}C5gd!pb-7d8k?|*St80(og#AuluFtQfND$D0oZ>f zB;nxCo-^|Kt6}lgdHPeqvK7aDgXMogQN%5vy=}*Psq`Ez>0a!;kOxmgZT&wiV~dqm zn3X2M{U_zBpe-1M90o-RZV17=gxLfIQ`luLo4*D{Xzqk0v+H_K?}122pYYT0Fv-fi zUBtMLPo;6CJX5S+Q!&m`=RxmauneD}o7kE<&}dbyrm`E2GjrXl%88;?Yqy!DGSu+v zawGN`$6a-U^JcUiQG3K<@=ALff#iDdTWQaIEwqqwvv|6X#Wc2Scb>cvcl+z9)uV!#@9!kz`L{5 z#!gA5u0KI%7e~TV9t{@02ME9u2k07Yb5ew=xPSQerK5!RO|2}~&sn=88TjS)MQ;f*vDm53Yf1H#YQoL3HQw~%*xGsV z2-m_IMW#k-5<-m{DY^S=)pQpfEq&QYDno=MS!c{62sH{US;i0vgDB&Sk#@MYf3=X|~fR*cp@D`dDklgU79FI)=oxRCe4O`)ss-v^ZXW zS2@3M{`(qf|JY)8?XleY+Rp0OX}I?Bo!+|9boHe_xkiAtFF8&eVBd4|GZt6rj*K`J z^z5f)g&13`-b8Mm1LPF#oaeG&zwYtE5P$|q2)s(($mB49QJ12ML%~<^C!b&}*5)m~ zWob~3EFZ=9%rh?wHYTu_)d>Ql@cs2)`BfO?&C#ABx!z{2j=OU0f#Zk{iAHNTKwrLb zkKXwh6gge)WMwnLK?dgh8ERj3%waPC36;?lJD&MR%?MmRf&~R;*iW`L{W%CnMBP%~ zB({9q7OgLQEe$QMhwmNZBMk_>V>-ztb{CRTnKo$$y#SKXwHRLObv?Zd-a)bi*+Mp0 z!p?R9Uj2^v+!7n_&DmnxFlWP&=X=#iZ)s%vN|eC9FYq1L<2Q64U?a~(8g-Ci34>IP zV(yP=Y{U9lH-r7}gp$h*U)#S*El}Au=<~x~g3)>iWSg04b*&bG6#ib$Gj7W^AJ-Cx zD`g1L;=pSU48;WhMl2cH!OGH5T?^HUhhEmA*N`kyV7bQad#Xo+o(U8eu1QpZ87V`Q znFrYJ=2CJLrm`s0vcgeg?d#=nKGIA;%c3)zBNqpxYZ2)#cg-vnhYB+~+Rj3W+t zv-RG|&SFqvH74MGOxtkv9=c%NVP)0!LE07;DczL->cN7&v9T~)B~U)Ji^e&q><+QU z0|?WqNzGg@58&Z(WtRS(;^bA>RmNZjBFc7uvV!@}qyZWuZF8c@SONp%enc{7@5h$t zE)H_K?yCVp+yoky>g1Bdi`L5!9hzbg=)rNY%#M5JBL((V=|)TSJHE?^Ua7fS~7ObIHu0#m$l0@-wP*sID5J3E=@iw&S{$WsIeTxKl90MU%8{kNP z@wT^iV918`MeBf=YT`~x2>m}lkJ zW(X$kk_(|hp@{mCKQsQSNgu|#wHJoTn48t7NGDAav0gmu?q$~&x(wZpkulA5GYN)S z5JM;DlKB*U<=f17tT=$p@s-iUs1cOm7X(tKAi{i)L9`N!JZwbUnS}4Ot1ENU%c#<4 zf}5j;!R`*N$%%)=7blOS3rY_@xB$*Vs$#+pG{PK-Eb*QjF;?+I+(D54~SPE;?5#-}xrYi`7F(ePx?bm6BiL7E)3_57IP6C+n&d)$! z-zz1r5HOPMc&W**TxO}W6$S5{d`OofqBak@^O&nLbv)xPkY{J} ze5xp-s3UG#uoGOZkABB(E=QxO*cTjsNN1;r?tAT~J9j%?0249scXyA#Q#x=BURxXp zmNp!WC8Jm*FL>;=++)6ug5T4@41cfm*VPNhVOYOt8Etu{;hYP6rULFeY5EyBK8u9{ zFUZ~o1>g&(B>cKPo*gX^m8SmCW78~Lg%Lw<+VPhdWF|8+|iK?~z+;3YEmdIc_h}9rP z>^jIFmQY{;-R@K#lgPWb39Ms?A?gNw7ZgdTWO)wdCty>DoTe-ST^f-B^2~TfV~!vj zW4d;3?d_oT0=Z?ZqZ>L|jHehI;KRL}G9S6I8O;CZ{A2lZ&^m=t*T!Zv-Q;QGZ`<;Q zKsvSmd5@7WN!(_3T5_?Ju4emO^~np;TX2~Yr|K~ zmg$`4k=CEU z(qHEHs9h8{R_>*N7`(Y6ytxoR6U6Cq1zwN+sKV|u2R14RNIpjm&>t6cTy+T8n>*F{y>I=wxN?m$^mq zlHB+n9FCsjp4=IkGL`_)orBpVSoe!OU@JVo&(gUY|8D+a)tOSF?qY0<9N(!TgJ=2p z!!-=DOnb=4QQ`Zt&1Mvk!j5$bo;kj8R^5X^nh$um`)XpN+9B!EW4Becw;m9Gl0~n$ z*M7caDXty(_y(}I2(@|*nvRoUy#ww$J9D4Fzglv> zPF+sV^v$$BBu3k@lo4TNYO0uZ6iT`-7QPrgT?MPM6)~t5KuewSJhZthU$X2Rl~@YO z5}s@h5Tcffmk2FH^`}IrsK2KJ@DERm+fqjZ3WiH^C!I7dE-d-)X~><0-|%BQ4YJPz zn8%TAzvT3#I+;D17$RZnUc7F?Z!QAGU4`8vAJHk3g|$JFGhc=@_IIhbx}aW$&+lDi zgj-DuOql9d>(^2fPSJww4rj~4&Z8?jGg4b>`QW0}Cidh_G-x&gac{Wu$Mdb#I`4Qk z3p(#)bE>F*XJTc7onTX5`{m1jx8KhXw3h;Fh$T-*72z0W^I_UtrD>j9V?&(*`7uR5 z_?5?9e!-cop_Hjh(MTm)-2qawv=p6wuR7U6|I29vTEhqxvDjo@D_nxp6m01c$DYS9 zC~1ATS>G@BRN2Qk_rPt(P}usJ;{-tDdxTLh3Hmi@s}ijY@Zp0TxhO-WA=G3GWL+Ay z!C!J!=7c{yy$xL8uCXkWjE|LxP~a+!hKLfD2Ip}VgSB?&2TWk@4jsv@j9VqELV5Tz z!*4CQ@T@d z9XpnGGq&~I&fCdyd722umaiGCH#cA-?!d;90w+-%2e&YRiyC%8Z(mK^JaCzw!s#eJ z%JJ*T@XJ6tTjE(FN1f7+{Lzo92s_ca?K_sP8OsxlR1StyHmx123z=jKOU~_ zAvw5VaTd1Wm^UP)i|1|K#9C3XTX0bATx?mtcfFy$iu~Q#)IEtRNVc@QPM2WS$`phrR-afJekj7(XXG}^6!H1e=#cA|29zr<;<4{r0=&QZF4!w2Pn&Br%+C&H1M_j3X z2UJuzPmp}(*e0dKGQO?C0L9iGN!NS&RTwAMgC}%dLlmhOpZs)bG1BTAHs*6+6xRsC z&rtCkR`=_wQcjaniGrRC%s4{;Ne#Hf617}g?=KX`s0Gp`wS>3!Opo%Sox}+ysl0PC zP}wqe`7dmDdVp%^8xQ-h-^_RP4-86Ol!8%hcI!2|cA&QmhCg(^d9sepbs(x3G}o)N zcZ&Csv5x?^SX73!PrJ2mJkFYQ!+^Evwu<9&k5@E5eun$vb{^TZ2BqAy?l8B`9W}VT zF<>7bWUm~OG3~xX9Kwgd>JD!LlyI|E;3SQySd;8YO$xr-du_p_pM)&vEo%2`!Bbao zSCgqcl2~&Rw;BuRe(M>7!qvo;jdC0ZaywPs)C8v`!y>hm#|%9xVGwH zK|R<7Lwo|;w`*7&1T3R{&8NIVs!0DzK%uAEq1iYP@=-tNy+MQj4Cu$8yQz6`K?`R0 zY+`xQJ=q^AcX)T4A9rt9H6Lm7Xk}dvwV@k&N#CJMgR%w+HgeJ(7cYuc3J8WSGj$>G%7 z7mV0I+rZzZm}V!=Iycnr(jMU*Z9gSj6mieQdWrW&H-Y9bE+Ift%t5!30PQ9~X2E9} zH!Y@!mP8+>E>JZ?bsiiJ%b^4ixtrPnIrONe08LE^1sLWv&t&lYvfi|h;ShpL)OtuB zVleg=4sXQTuA*;EalK6qEo|6&DI*!z^ao*5s;Bznt39Ry6n?vHQjWPW=(Zh3lgwiC z^5tNh+TI{s_ymDW5hmiKXWadZKtp|xu^Bh3!bkPO0W|)6vDBOBBJtbvBy8zySat}K zV~1VbF)Y>l!XIm0s~^`$?)B3lW>G-z7|H<YYR4+>=Ucdlg2bdI^O^o&R>6fC=Hi8ZP({$mo+!#QJHIC zUlg)V5v(@l_Gn{d7&T&LlWH!;!kv;FV|*7o*zmBbv-ZJ$%}I6eIeZ5*T8U6t{anU1 z|G=ga%P&LM45&3$fyyG2SK89nRuIvckV>znMcBKp*w84mdhf$Q#3757DN0EeI)dhm zD7rY0%x{^G=5GLVPujHK;+m}pW_7C}=4Q|+MJc;N_X;>^L_L%k!$H>acPsK*=o%90lZ?OJ=V?xmP4nhkq8^Aq{ zqsTQKw#foO$=|q4xCe7_&ySjrUNI+~DHhc(YYGe=+9qW)2LiK>2HM#DcyqSChz9UU zIT`ZLFeuk#fT_Nr`LGCCNVv28mVpzg-q=0~*ycmmGP#m5L3nr;5sWEcV&Z16l0#M2Xgy{5Au6AQVlYTPUUG*#B)-=%^U<0<)x*eCy*rxdUOlEb_qK5(uoT%0g;*W%giS zxA=(#KnNfT>}wQgL`Q~i8e<%71I8a^8?J@lcc0Gaht-(SGN&mdlGD83!=Cb+>f=7{ zd-b0aDZldCNxq*^r5wsAPvWHyd(f!9S~xE+(_RX+OuVav=LmPt>WSc^W%^@#%%%5S z(LZkP$s7Zg5dW|u{4I3B`0ezp7g?&kSWY+l%#=+V}6>%MaXd$WTrb*>~A*g#WG! zd}{=~n=n8?=zspV>jKgL<*eH2J2@EJ+Rz#5+Zj9l&y$(f&c?J!?S&U@`-hj%6P?0S zsWoV_y34hhRz1BXA-%pW0qM`$0k*i2)*sd3rh3Aa@lKUzsH6ENT7s^hkeioK$LWhZ zH}2_+PMw+uuV_adEF6mk`38AVpi?JjW+~v`>}0?J37=j%#XQuS$#4CWRIbuWh_aiqk*bsEybW``AI<*4tvCBw+0 z!mqf$v6N2#E(@uh@mArfYS4@jS^o2zD9jg}{uNS@8VQzK(~gPSIoo|`!^?vdbzeZD zl31oYWy3#-cYiDK^QYA$7huJ`#?HzGEO)F`?c>gw!s1x`8-@-`C9digcYUNln&cy) z=f47#nU81eUVzx2D_!3QcMQY_FYG0spE5sZkfjyyTaF9+o*M1PxsO`!+8$cZZ;J5^PeV zgFcwIpL|&PpXtt6fp%Ua$TCnxVe78gt5={Epr);&Z-NyH1Fue5a0Q&cLfl`Bd3?76 zJSuCz-hwXsI5J;YtCkMN-1SuzjegI>BRVp)aOBTOhX&;H9s-{o5w=wO=Wq<^y7b1z zDv`UfaO|Je?^tCbR|fuep-A7k!ne2C=Qs<&>o(zQ|Kn$j-TkyLU0`T-g#tPnV%}FEcyp z5uHlD?^*n;0(cm{O@HXm8f7S(&tiUkR0}62KT`>>LOIj*1{RUrSq29I>WI#<<^`h= zM?xU-fq%`uB1dU@umuXLxYo1!dwDmBjNHO1dZzgeu+H!?gw!pe&qL4ELq&sQ?5noG;Zy~bQNF>#Df~! zWa=rhp`}|O92rAymti80s7Zc#;V^*k#2N8QbaDE}O# z4Yq7n7>j!=yJNE}J6FS2!*rTpJvRVsGv7Z zob9GtRRCnIVUDcrpnk57-pIQjQSBo?)Uk-v99oI+E0%J_3n$G)p$&EcQh&hvV%_r0 zvdGh?(Mg^fX^X+G&vH$bqPoB4O}lE6{?*Q!_*$c-t@ZM1Dr!k8L`oJ$5(*o6GGS3N zyFAr{DH)H@ikug%C=&l5-1M9QUOWcW~ zb8tcH%^QGrht{^F8dxK8ej|Nfafy-H?q-%%z4RJ++dh{p%ng%z-KxICi}i^+pT>V^ z6{Sf1r3R#&x|kTWl(w&^l}v%o)QRBW1y`m59=ULrU)M0nDF7pINl*lPZricinp{#` zs-AL|l%8a6YhWa&IW&rZIVDnYVCS)9!wrlBZ0$z)Oz5y=HE>*8V!KE!^gvWLBn$ z7k6iG>Cylm$E_WM)3UUq1Y#>Hq}e2PcSEn z9a%HLUld=$kO|jg4OZ1zOa>=U ziRN8NPqOiQDQ}bH+~Uc55!t-#Lns%N5}JR^jmtcTbFE*L?l*=RdY~H9podi#2z2e0 zXZ(;VPlOI~yrd#S7(-{`y=F3!g2T~M^wxwAD>49doqc1^%RrD(kOAfVFCy)LHs0t~ zZ%a=?MiFSWs|0#D^-2%w>ubrF-?Sd7Chd#FvLn9hFJbn{tFRVv+s-8k_Z!l}J)B## zl@sqH+W4i?Y znzNy<_^Guq&W-j(pR*H9C;23vOZ3ts=#o!{MvXpBAknT-2YI%0eD}8gR5j*7??r$W zOiB#&&?ao>1-i}3@<%~c%Aj@PaDWFpqmiSB*TnLu!lXs@@*X+#SoPpNCHhd5p|t6* zOvJ2bU6a`7OY5;LnYYin%EE2;UguS3Z{uf`Y8Gz|^LGi3F37FJMbq{+&)k;hAB+9L z`44dWXe6_z_kQ$XI%(RWo!YPa@#CARm&w>kIH+FYF<8R-`bA zoeX<)VsuwgZBgwQ=U7Xqae!*^1*G}Nbu(JX^|t0#(Lj+9w2#N5+gGgow7#(8!XU$* zwDr5q^|9h%%nl6)7Dwc3RyDW}U9?}ZGsqIIf254f`P)U_eJ(1|<_!B@mO<=Ny-P!5 z{ZxHS6kOLFT7>WP}Ml=n4z^x&+E0yK?>bKcW*uA(d8Da7b~hvqG(h*jw5!1 z+|ys1rw#wK_1~)f9G=zGE+z;lw7j5J|G)t z(jwB&o|Ky9iRVmnh2zVm3n-im`mvf{_jiH|>tOezVg3t6UqTR1k>Tm#-ttcJnQg8~ zd9&cg1pDveb?<%;y;EAt3$CT!HbV;e4>FEK6apCw;xuFxl#Q7HlL{a`cr_$pVKaOebNx{@+HL_|})xoqOw{n;;> zTrwObuE0>8_S>N%Kz42}-PNGCQn-H6kU*oxK)vU0%iW4FK;x?I*yYFHial}7_>=3C z@i}X}ZQ>-1Y*>3*w(L7XsSoE;^BLWAC+1P^n$r_`*qQe@eUrkOhc#u(bwHVEVHkRB zqiR1EphTT2n>Lv!((Sq9YACh@uhEMpsF>)}N=nlCQ_4 zYHDT{PPiy8uWz_tpGI%5^Yino?KpCuUNE7rOKzREqYw0xS{Y@Z<_&nPH0&q~xy80) z`1MAvjq~v2{`qD>z~Xa>+3HeSQm~ct*IG)ZxEF8R&tll5CFL0zNC!KO0;gqXYy+FNZoHa7iUUTQ^LR49t->R4NpvAvvLrX|E#+n?+Xrg>?# zzMV(~YU*UQ8hmccR@4Xtqs|B_gqM@Qp!_(2D%oc%9tAi8zp2g2Tf*1>(laqc7h26c z(fu7y)XyauOyHoDMd+qP}nwrzKrUB=Wo-^9$-Hzy|M zVs74y$lMn@az|uFM&$mjXRY-B5v#yM<|{u6vmYED7KQ`|4Wf4*7{gx+xa%zJoGGvW ziXtaH2p;WD@l-CPM?g;Pe@}?cW1h*rlnqFQ=?_9aITX+3!fpD@%O+;zf6Zl4N#a5r zXukE1^jj9~s;hGVg8&x8p)@u}8@b}cY^Zt&Wc-?HOiE7!mJrpWjY+d)?WjFD| z_ba5k{c1kL%b!Tnf6qLW@vZo)D)bRIJS}JwJ0WZptNzy59K(B>5sy+fgp`5T<&}4p z(n}=YlHSJc_IHgu90PFhg!($&92+i*R}z9bFXs$PY}(+d+CWJ+kjAn_uj?HbsKVq3 zh*pO#xi=QUJ0gFs8hat8BYz46f&lD}O7?Ivx;7hXrkY`X|-jP4*^h9qAX;VF17Y9vhFkqM`581!4Z$ z0ciIRUl>7@A7 z2d?avy`0$jmC4juDwR?1NqL!zf{ya8QClwlfKd;xm7iAzWor ziW5O8$(loSAG`7ea))`a@-SI>dBojw0at`s1MbEwl=d0JpuMZv=e$|?&#TIUl-mFbcjuTWIfgh*Z^{B#=f^^kD>T{ANfxyk*ecu- z`6~ob*ioyVO(})ck0191UqqbBI|gW(Bg7Jq#Y25|Y0rqHfQ6i|uVtg&2s&mr4Q(E# zE)IHpxNb(P(ZB=e51CsT^`6Xqa74LaP44F*&)V01izn24dc8e{vpdmbDsk(ONQVeKoEARHZ=)#I9;~Z0#>$Dx?es zS-_sfr*PVkpqHaB+gv_1C*|SO1-VT7S&fwXGte^+LO|g^?IW0LHj3NM^~EnkV>=D( z__)H5%f8 zR~bHA#X89cBac2fTzFYg6E$JPC0m9H&2|J6-H-H=IurE`*)cJ2k4U2I@Cf7u= zDesQ~J(fEb))@mO<_?3m-m>=lTzcVzP`QaYGi-s28{GMj*<*~U318iXLF1a4%%td#YC8tT~f61udf$2P3@-Ko-*8A zIVgmwYfpJ5q1$I)Vgf{@B*0<(+dMOxKb3|Q6Yn37 z`gv~ao`*Qe$m#J>DvKqp*ef$Zs=0^bxI>U|1&)+vZ3S|7N#hBl__XR0ppbeu;`KOc znr2R-__1uCjPH+6aCKGbTceXNhe9HLX9qhsF$+ufWpE&FNm0@SafEEy;?KZQSv?Iq zmho>`zG}Uh6N(?t`$69V8O$XPw6TuZ&~vs?O`SNX^eKP6Tfz0bahCPDdr_jJaoZ~D zvs4F|9e>^|r25Nd9z~<}{E|CkgYvE=hn4!XyK*HjYtMo$Ps+|)?@;HblLkS^AFDS^ z4N6X*l+BzP@%ufzkYC2T$3wbu3+o-Yhg11j$Fl%D+L!psVT4FA%l?6Szbnbc$~%Vb zr5}}>SqWd2(>PuALW+T=v`&aLe`p(>Zk z%9!%D;?#D{lI)VSQNOHjJrM9Vgo-Z8bmV1A@%w&cmQA8pL7Aj1223vpL)%-1BiMrM1JMN#WI)s(Hrw_W)_m{h39 zNoLbhsgngcs6fcSro~HpPT*o_Vw99)tVph|1%u(Jp0K|vw|CTk=<2+RA5=BPG>u4A z)ig7upgSop2W^jwi>e_e7ku&xYYI7ybtF(lFAXjb%|DSrvzcXSm8<+RmCDRQ=%pm3 z&Z`qr8#ni|E2`3coErG6m15$sRKB5PTWI~~H#&KtT=EOHWL{o&hom;p%o~A;zAvHf za6$lkDj3-}u_C5ZTZhKspjy#zVFyhxm57)TR}KkoxU6!@oU+_xhvIFjFQ|-Lk+QM^ z;St>#+?pR7Cm3>Q=Ze`WENu-{@Oslm7_gBaKKqV>F6)Gylrq#uB<;|BeIH`Q_LQ7& z(+!Itopiv9&@2L*N%sL*&!Bn|lTPJqy`{@s8>s>O@ zNZKVJKr4vz(bU1Jaa7zJ^%{`|P-Z)odr{%TITSsex|^6JnuS@%?pZII)F0jxIr4qN z{*>JxDXVsj+!;-BgwIzLAF>p;2u)_m_bKVJ%~9gNkii`$wdfbTOW{;1z}Y(Pr{3Z+ zvhEmwD=Z9eIgfn{shrF4kEWLQJ*(d5xQ>)cPy&Q32kSm=r0bUrcrz-Ky*s|G3m2vf z>XUFAZ)l5mx)LNPsWF~_`~`wrmklV;;RhO^`W6e>gG4e+|NW_Dw4<^n!ZBZSbfDgx zh<@$lh)kXIXx9pS4Fv8z$07(K9`noq_4KV;MM@~Qxw?9~S};4!u!-0y>~cCnX)n7?r~dhVov<~!H^7GB33{NB$g`i*FeGt}Y|cd;XeqKC6r$K< zke?CxWi1`1*V0lDgsCiDsuaz0oYy^24x4N=53<=>NPXTc$2bH69I=EN(N$ckgCu+k zTlo||;WeX)jQ@Biyehnn267lWy5X-&ch|Fjt-(vP@RuC~roat4OOtcVRCBwi#>~7a zZMw(aTGJGZD+J71<6MbIQ^bq-X>rGapAEZ+9jE!t!pxLf+sd?RSdKm*%0V=d^3-RUXs3|d zM`=%U@)1KsIPf~Ap>1&wNZa=&LqFdNnMCg~zNVI~&f^1q(bYx^@}dTV-2OErQluv= z+IiL2eGKj?_E5N8wR3XRw7)IOKU#A52B|RP@Xi4lnur06j$#-Czc$BjJ3DSK>EjgA z%7$a2Xk%{?X7W{IKdN=3QZ5i5pNfH?`+x6i(GlzspU+%JMpAS)-8uU%CXVB6UUcW` zOznm&b^{uAYee0JK;4~H`ao3p zV3fWy7Pvd49hL_gmTyGmhd|~3nLt+fVD66zrUnT!APiT|DrJhk2>+GAPr|@z>g45x zPhX`ro@>79Xy-s_XnPOzcWj)b!Cqa8Gtfe#{RpLkt`l@_b`b!y3V#Mxyo0ZbunF*x zO)l4U+V)PLV)oRL1?otb-O2d=Div#I7@e`=EA{iOTD72mzj^0wAhkj; zcfh8>k~NdQ>N2LKMnH(?;1;hZByl`{J7$9G>H!w|Nu#lXs^;uyoyyie&3 zXV9S#eYjv>cG_OgllkjZUCU+6z^@_x^0r^1R>gxa8JC8NVjbv;SL0E5eMFQ&0Uh1a z_qU?JO}7-89ZPx;tdU1$KUA4L>FsHp$+NXFsM6)}N+S@1IG;M*3Cu^)Y4xMb3t=+Z zIW4~_0Ok*jfPI^5y=4mLhBk4RpmG2*w%_<98PRV$V#GyFlN*$S9>ugdZZq3mG73A; z%_7nhvHP-$IdUq?_6@#~SoP8E+FNQT(W{~NkhwocHofkQH+eLj=hXf9@Mbv-oYwkp zrw5o8Gy&AEIH}VaCegPg(P*s`BbRDy6O%Yt`W#%N+d|!169(S9es3+f{%*m!hA8LO z9)tyljwU}nz!=gU$`bX8_d|W zMJDnHiCqfuqlh-juBSQEfmTSHtR)zXKSj1>j~nf*(Xvo;TAR+)s?8N`$Gel(^s}6G zNJ{b7?&I5)vVNz(jNsRD=y5Ww)e*SczNdz3^0N+?{LL2HWF{A`#mrG6ArFsD@8J%L z4L%<<1UzWxsVA9)2KaFeac{U~fA!z?DB}{pextQydxv(+-pO+RcGc6h6Vv8B&FBsNA-p}e=K`QM+GJZd3d$nx7zv8_a zto3)KuBDxiP;0%WW{gebLj|ym!me4qz($5L8#K-4-|!IS#DzJ~oSuPbgHwJ2m&MU# z;SVP!#Af?^K(vm@8~yQrS|hZO8WuLpAs>t&rWosS#KXm7 z#>YM(Q`gH4u;iN}oXIQ*qp62zmp-yuHF8Pv#F27kGN~-I`CxJ)&Nya@TTf zX=TE;c`YzLlL3g?m$p{o36^Wyn7iGAPos(+ zy;85cV*ZbUIYL4e70qHzlI@U(d-9X~#bAaF&BDP}uL+H`=60m0y&He$(PjqgKT1gqu9;cE;{n)iM%J`--OKiWOXvDu2Y3_CW{nhhmd%QWR+dNf_+ zG*u6EwgoC1Bd{$l-IoyRzs^0EYjinZ->L{{mrBaY^K!wL$Hf#kGnepijB%42E@=&0 z+vY@&4WKLUC{KxSm(+1Xf7amP_Eo#(kf;gRJ{v(OmxS2;9a?N%%emGKXctTxT+1N0e99@fMHTHPcS+l8B zZRB0pg_XKRfn=MM3HM#wJ+;XW8u&?(JA8Zd$K$s5QB|?58CEgcv;o}*?mfos`eZdz zhxmbcl`dW|d1;9Rx=vf8*+olR%QlDPc%%@J%h9zrKaR(qZ zwj`-T7KgWDmdEufBbfSdwsnJphmzTy^=|8;r;!#ATM~fPh7>#Gd#?5dwVcBY1S*v5_4?7P$MQS;*Oaiei^2u(5R+gO zTJ$S2(L60(_bi4Vh&1n#yZo3X&cvl~=;p!3z0bZ1(3Eqq<_;45cx|m8R_57nUYEK6 z4i<@kKve7TH4udn4z{@8)RA>cdw+CmM zV?S4|*FtH0*oJ9_C0I~Td=cpa5kP?AC{IzWXO{yhiJb<*rVV~QM6Xi$wb`HUvR3>f z%w;t6Rl2-SL5eg3MLo-w4FvKSDERy*I;KHPmXSB@;D#s_m7d6xB%5;m2GAD|c1Atn zHwpZU$LVZKJ56Of<-{W`;)g|Ka9~mBHj@=~7EciBOo}W&!g@gP!XloygpxsEggEPz zC(e_KteWvYzg-*6f1VXCJzaf=BNQwdo$!P&4H7=Q2mt(EX4KU$%(YoJD$7ZYJyB-j$=AP=*5q+QtI%WgkTSnf-?x_6Fd^lH`o}1Ogf9%Vt z(Q4T~&o^BZaRK*lh}0^)rtfv1D{C5Z#rk!sOTM58Tr>jhdI?P4h4mvmAw#-0566rF zxA_ndof$ZVEk;F3(Eo^`}+&n?*y{)_g>81GgRK}2sS?*=Nt%tY6eiQdeFSJJo_ zE6sx=`NLh+6h-r8FTK>M9R1qJI#X!`NM0~6h`_KhIpG&g&HmRiL%2#tT-t91^K$iN2Wdd_LR`+d}(2QHyX~ zoud{1%*+<8XAc(WNFEEdEY72@hKsW`U5|NrBXAzcdlj*$jcxGewtC4<7R1A5Ai$s> zBHe#{-x?8mqIGk!BUXqnfXyB7cW;wmpc>!JaoWyr;C$Nbqg>bu^C^3+fgPPA%5gfL z1X^Ds56?6oSs8<02fn?89rb;rQ?JgK=z=wMHg?F_e!(Mrh|p(t@d2FYV3-Ax}QGs#k}TO1+-yaDPf#SUT~lq+hON90??+^vxloDCjZXTfj(R)6W|Ob}(IF zGmy()WT{cxrvC-4g7P^>%Z*NNpj)z~4%(+n5X{C1mUvvHoUyzOb#6iQz%vPh4vQj$ z_1Inmt4ovUDW(i-4m!#B_kVjsyZhpc5g&4zRFsHz-5X@$_$wEb1S+{;tbSy)qRY_? zb@n<#gpBHvxOkOjOeG4#FtxRdWwi$HbRQy|fw*LYsY433#`aHTXc(_M!!#wPn0K%^ zyIqPFmKHr+f%A1?@)w^>qLCfCiC<)?-9-%&ZSHT!5Q)uHB~J+){IQSmNtu(70dl*w z`csV_gjuI`dL&4zRLWK1*nP=r)z@r-bOL1gaEXH~;4m8~k?U|5m{ExrmLf%r;}aJR zs(p|tH)Wn!!3vtxawa}CWSlzOMT5S&?|Mj7@%wv|Hf%+Sjmi(9o?_qV`8 z{mwOl2aN~8zu(W(Dx=c)KyT(?rI+3byxawY`M@_!2P&O5oD6MH$Br_X*)#dxRa!i^ zsHr~mUP2C+K$utv^1i=F!ZP*Wq|*Rc(ty#rczuB6ng5W=`<_ z7{xU*hsVlaUCyI~GEv8zLOfBBJ~O`l0Vh`O7voF9F(D72Sh_ZQegK(}{sR{HulJG; zEkp1|!-v9{w3IT?wRtO+3*F-ZoAbmmLIb+D@g2xFS@mD7oUPAzuL+JzMsR>(7)+_a zguDlE_H%-yDkq+XWh8pmeY~ta#4oF8H6`weOcH$E<7VQxFvfw2u=<;1gm0R-7D|@H z77IIBJk0B8Hk!Vr@u&w?hhTWmER5_)%v2o?@-F(YLWiiu`eeQWOvjm1Sp(O+?lfPH z*kr26ds1rNZAC5oiaS2!D@ z(F}cTjzQyFzlCK4q~s;BoMyXL<;7BK6LakDNm~U8E3%5okV!zq4m(mm8U9P%c(TH@ z0sjGuxBo9-VdFcBixnfZqVHh@|h}JKfKLbLOxe|#Z)TPj;#bytT(lJNjvW>Dl7NW(bVM?BbX%?3ljT*S8K zx={?DJz@Zmwn%f2AtT3?6I^7KK#ebPQa`Xq`vigjd1w^Y~K_ z1t+`hpFO7r@rUdrq1UBsp*82z)8;gEhA|Z?e4Ew*kRa3WC>lWCzy{KTNoKO8+JfBp zSH`1?C!j_!bBKRvFxQ;3alMR45UPLqd73rz#(jT~y+e&B@V4Os=6Zv(ws~TCX>+^* zNANbu!aZb^#k#DU!XMf0z^={R5oSP11|5vgYP4)oA3BY<;cO$C?K%T8f2UC>4Pg5l zA#>`^&v$IPEQl60G=vSTUJ>Iq(zKm>``}$fpyX);o|u|>l;ps!s|`$;MS_)IyGhev zxM5Cz<$F4h+^ThNZIZ$2d(B%a626>^SljxeL)y8 z5l4(5X?+A8@xIt}H)D*!Vh%I4pwiVTfv|)lM`2i5#^fuLGE~oHCyuhpqmjc-w#=6d zv%kdDmC|Yh+k#aI#R)>TG$6mU%(I_EgZxmG~aWN%avAi^N4&9AT-RjZ{Zr zcQf+XmES=^cmxDa7+J$u*I2MX<4_O#XH*C-4exA>ai64JLM^2UL|k35JVRk#2Mp4q z4g%#RTudemYIgMr23;-?(LL??$yZh%kJD%k3T}y>-@_zS;0&@}I4x5PbYzKE z-s@sdcQ_tP`Gpk*JiG2OzvbWazJysNP&P#Sb2*;KxV@3074qyEFNDo?Tosiu*3^hCA!WytW9O|;uykN6FBJwP*^C?fR zdq(r|w*8ds#lobBnJv)iynbgnxGZ*#kHh!J6i_{LpkXW#aGoPGIk}j zCwTn*Vg_D(&A@z4%d18u?x!vt7T3k3eF`a+Zj=c%sbAOmBx_ZnlyZ`kVyeF_kP6IA0W1*?NNA1{?u zYPpA;_CDWlWdtBoMs^jBg#I9UL%8!Oq!w92^%-%9O_#r-RTMmWl1VSCegMb5G@`rG z5h*7rNM_|To5;AuTNRs%12Cu%nY<)!@`p>QnG(l1nm)GvG7+yFzSJzCaHBP8)B;6e%-8GTyiI(h{PVmA=^hzar{v~5$#rOSa{$bcGR2(-#E>JC^qQr=9GAXJ3V+fb!4^oZG zUkgPQztZ4g!F_DGzmu8vB6A%NPXz2QIys^-T3cRkEh^2xHR0+=L*QOg|Etf#Fp5rm zjlY-!clZj7lDZyf=5f#5Sn$&dJx6&XVbs)(9CJ^a%KHZPb;2J#D<)x|v{p1rZxW1b zHwpP(S)ZQ}3wFFMYXV(CD19_9GESbiILc?BEY5I5gd|@vBYHbc42jFKdct$`R9CUf zg#RZ!wx0mjG#Gi2=UOiVlduF zF#i;M{8o%tbmhJ>CId38>sRa8ZM= zh`AlNWL7ujQVLb2V$>LCt$JYrL4RS^ozaAKQH8vSk%%C(VS!>7^^lL`j=TXx((Q@_ zmMoGnpKTZm;TKnzCLJ7qd^iQ!znMf10>P4ebfrZ!D@@8}F6twN9<<-?A(n)ODrBi& z=@P}uV_N~|ir(|mbM9G^u58;3T)R;Zy$c@%A*q;aV5V-!qmV0O@Yp&8GLmtL3K@yy z)iegFOUVa~f64e_HO4=s6Wgg5fI)loT4~lM*lwZZ7xc~C1wF(?25Pvi{*-M6tK}Eh z-O^n_osN?&O%QwXNn8@(p(i&6T`OEClzT|5W6P>jp}J;4+R{-w3qxFv2kSlb&xo-x zgUVgpxJGy&}}5ZWMF_- zteii1(`{}oCQ2CgeJvhklE&Vd`mF~dOHm-F3aPgD;G z;()mP*m7D?#~YJ4PKI0|^0}`FNu59JYnNoruMWaY<-n)jfA`G+;#SZq#f43-lXcY} z;-z!5n0dJ@7NrZ4Jrk4v-!_J^wP}jpVW`N{10#iJ?#A=>m#4+_>c@`^>fmeJXQlj} z$&pq09SgLF*j&5tzN*1V`E|w@v`eU*_tj$$Jhb4B=%(}Xg^32YbvE zA9HXSizMAlOpPZw?*tmK=F+WarP3jmpoh$>*TA$-r;)QtY5;XbRQGj)-+T{*_VzKt z&cbmA`)9;D%%USu#lzdT$?FuGm)s7AjJLX@zI6Tmqk3WBC+xR^o zRhx-X{~4ehBs84?0GOX7G8hyfKt>iO001p-DJ-m@U}5iK?`&c3Kqx6JOz7ZbZ)Ry@ z3IMooWGkDiD4(J8KJPpVNr(9*N!u%-K@utnMf#z}lT#BxAxec2<*%bD_9Kakg5r$j zg@MGx_(h>9(!xeSuR$CU6~qJ>AWU4<_&TbEH`Vf>sk5-uP54=UxrviD@U;F)T%%_!~Yr2*1Lfs`-}ELv4gq^5gOtPN@&Pv$gN3~5#o}v zB5go%K!F4)4p0y$mPt2}cObnEVHzPJa3#?a(u@TkWgiV5u^izX5#4J;XB!DP7QHAR zP%2GWNnsr$9(YU=os2J+I;Xxcc_#ih^)JYy8!TK1THt7yIVDymCIqHAmK$bmnoJ4S zVkFk63L^*8McQdPLb|=G26YRy7h3!Tbh1=3c`^<)gGzZtNySbDjOv5xq)KeLp0an1 zm@13%VL8-NN~LN=w!(!nj2qBCy zR--#Dku_Xp$ZvnPA@cg^buU-y&a_Xw&Pd*h@_a5~7AY3>Mx}=&Gk%D}G{=`L7dfa? z%F@&apNJjQ8>#~;oDx=xz`r6pc!WO2ta?i*ELstJ3U}ZqZK7cYk=nQ7H-? z3UTw;8L;eA<#pxlQs`22S>9j&YUnGhi*fQhMcjJrO0Uy$di4BqWb8|KJi1TcaJ?Bm zRX%OsO8<$&YJfMwl7er-&S3HkvpL%H;4zGD-YE*}4hjet8zvj3?gz!U&+`;6i$#ke zL|KmL9FiW|j@XVAl7o{IkxR>-%U)+F$+nkJm2k^&%ZyG>O&3hBq_bu6GOaS7W}arQ zX708cXt`_Awv@HBnMyVsX_aVRw{+PBYjJ57Yp81JHi}heSCg%DR(F;nmA1DuYqsYwAi+I8=4zon70ns3|=R8Cwg~yM}P7{z=f{ESK?{m`8YQ@ zq5e|)wUaTEb_#NuSC` zpNTWFJ=T3B-2&Dv}BYs>4VR?V^=2H>|V}^M3>eaf|Vz-KC!y62~CqAd#L%u^EjveM5P5mj3zSgnU zN%=wh9R1*3VPBGOlkY#@^MF!6G9Yu1aDPF6ZQ%EpKVC$=G5o(aO`jUpuLPs=+6B=B zV*{!Kj{B>LEXFS5s)?RY(`MplEa8I{eEzP?K^UGGMh^PGQUr$vtB3H%ID~0n&oia6 zxy^40JMW6TiKK|^WSTR{bJfyGu~G9?&|C3raCESC@Q=`&X-+L`WNS#;NaJ$RQ`fND z+4SswTs?#yWFNpBdSaw8jOjXfMtEt9`%{Y#%o80d!~e0jg#&wE3O6} zM~_YDLo_g&5H;{Bp0Tdi@gt{mnqu7ci>O$HCqgTdP;P z@)``9yUm7gA=x;5XyFkxsGAt6XufNdTkgj=q4pEK>03!n<&{J2CbMP>W@jfmbUE7a zDHW+Fsql7i>l;mQyJ}5W|DHrQ8B(VyH#-Acgxd>ydD^;6OUGxXx%pL!R325{RM@W< zwwn!CU+m_uaXh=8STC11wY#1_`Nn%TRe@Axm(7+<-zDE0pZROTE6!e0-feZOo$c~m1Z`eFW zQEyYvsQsmHd+u`1^Od+LKiZkqnNicOW8HrJr@PtH?D-5Qhht{@vD@Pg{d;9Ohl_W+ z`{9rM^YHV(UG!}qCyLLR$ zXYk;_*{}G2u?WIovFWjsA#foVIh=f4TnGG4pJyMX!m}o`FUuFJ zGxKTl`KkA*iM_U7#h>SW7g)8MBLgG&J>%{yOnQ%M?^pe9TW)wag}VsyM_z=!l;0Mw z_5YOTO5YQ)5);2cLDC*Rj9KV5fA*V%#u7@h|7+jt7YG2neggo0XFr-SBLHx2008_- z0{}4W6ZD70007`9NfAL6_l=+>eFOy`FUA6%|LobKWh;x?t--ewMksE@%ge#=cj|pvBd2mOzw>sB)Ch;(vH- zsM+C3;wwRH4HPY5Q}({dH;-2@Ce? zHtWWbS1v{L?&QM8ygrkI2G98=X6wy4FWGTjGa&~m=u4dAp}&o;()u=T@EM6fC`MOp zp(ZD8=8N!O>EnLZIyfLs2*=d>rr)xLDD``st!3T&Dxw- z=N-!Um0=V4O7j7pbk_YI-GS-Q#UqDB@85cVLmfSag?7ZdSbuEjiI>{X1g)DuRm!Hw zptYf0qKA3b5ZJDdjf$nQu{=C~JwlnZy|PWxP{+Ea*oUR($sEm;r#3CgH?AM=-EJb3 zFq<0#W_U`0Oo_|+B>x&dMfDcU!3EnvLM*a8I9r`p3&dJ#Xb;HC;$`xx1&(ZK<>Un0 zIh%y$WDVY9CIAVnZ_-l}PIBRH^GlCju6}=QEr}ZQ@-qrT-MRrl)U+qCYLJ|MzF~l* zsGLZRkU_wI2~|`&y!K{rKb-b+{_jan_~)+w7bItF=xVC}Lwe5oMy7VAW|qd5hBp7f zy8mF^f3WU9Soa^S`w!Or2kZWWb^pP-|6tvJuWRF> z3ut=LR#yKbnK@~pO-)FkUp!-&b$pg*x*3fK`Tj1`iFK*c-XrUOZ)>1cwo8XeE-#vj zsaK8pj3x?c0?AP0$vfRWng-3f6YNpN2r;(?<-No#j_>BEv=3+!;WTmO+q>qn^(5Lj<_3ct{&BFOAT`dKT2 z@9{K&h|~Yye5+K#!JsZ9J&K3f08#e>xpZI4lr>q;=Z!;Uy+bjqY>MIFvj3z~gscIa zsIK(>g;bnPG!l$bZEwBJ#f&-QLVJ&6w#;mR%g^T?n%;}<*f@#N0df!=Ib~N5`q#br zHIj-m0R>acP#9_u)%^^YK1$(LIIZlm^R`Alj9$Xq5i=)WK|BOeQ+G>9G;!!2xYX~dzb`cz#`rX{Zc8=W&GIV7Vd`H z6CRI^wK@GpB@*Ga;e6Idhi(j+d+CS8H~dL3*4kL_jCSncZ=kWgj<>e-rF}BsxVP(Y z_p&zg4P=csVUPwBL){cc1j^#JkAk&ZDCrfmrrW3ZFMJNAIbJy_Z&>A*$rsi6H2g>L zV%dwL5*ToPet4Xgp@x4ZNXyhSJfs95SXY?2GBi32k^VLXvXBXgt2|ByjKqBgIn>{D zkJhn(Sc==}aqSAYh)e8V2zYC^>&k$XLvUL)=cA9$E1>2DG5G_vE!!$aE{)3YcAxZB zu(_S+I1|^B+SwicqHNd~)VS1c2VO}{sYsAM$W6za z!GYshv1WyZX?e!rGE;D^V;`0+J{%1hsdxd@RDNhAW`CD`ULu&p z4#j{MSd~w-L`EU#0@Fz_=tMQT^ zIWphGq`@6H_olx$9UeOvb*=~*XD_LWwEd=pL+Bzb4tIxd7$aB|0H32GyqgI>=vTFiSDwf(dE!-^j zaHV4w7_>H7M3QlA8t+ffRxjF3!ys zEFPpQi894=BeE5ilbD)!))IzVqbLvo+9W#mo`Z?AQE-bGn%<95`^h+00BRBK>n}+?*?m6^6vCT z#QUM02qhGjW31s9eTO~r4ixAu-`OHL)Y;b>lXsN&9v3i5Pi7YFs?OD<UmCHl4r*7ND4Uhw7vZ$DpVeEiUc^k34F~GR0o5qT z01uSUOCDl%svW>2nefpu3}5|2OMyD+{LhHJC{Cz46^mz$(Cx~@h4Y{dPCMEhlj~f_ z)4Ma*Y?K{10Pg|eh3aNwyLVr>7VS6j$3OP(`Wp^!*%$vWH=^GC~#ja*g?_20hRO zY(Q~DAA<_&LxPg#G={mWB1pUg#aaa6RAGr-bUm>qeg$O~vG%AH&0R zR}9d=G**R=675iyS^%uGQsJDZV=~+WN-$u5R;J?(0pRkCP0X~Ic(<)+&wCwf23#jF zF6OzDW;|)tqqi`Ul828>O&HhchA=2MGzMehcqU3P{a9qLq!f3IF4cy`jr!5!a1){7ytXZ>Q2 zBHI1#e9Qf?ixCtyeZhGQKfVgUXPxqp6USdX)D#+*fD+pDl1(CEb2G#uw$lW~$-k<6 z0(aJ4+>K0tBG#1+WQ9gP=o^FB8L-^q&`uHBzV`cZVsM{IGWAJyjgD+_F0b-Ly)KwQ zxRQXe?i5pT+2<6kSuPa)Zzvvk@`^7Aw1IsIC&?AMHrdj)%EDQ7Qu_Razk*5y|@4uhbz$9mf;uT7zt7>S2Gs52NAj!$~MRR@1&PF0d# zAZhU~F~fx8?JBv4Oj|b1pOM!oj|ZeFYQ(=7f00@XU~5cSPcGQyEfOl33;|&0lg20d z3@Da`l%pts6shPfNxOS;O>_r5x!69_Byw(v-~!X6(ezcv3CN%9T41#eN&2|3o*F-j zH*haIu`XIw*Hay_Gx;SlBd02&oeQ<_ClKSQLBA_0TSd7-DMhPc^!6uc0u3~cHp4v> z^8?gpd(W$xUPAyotH*|~tIKF19;q}BTx~Exz;gD^6PxMJ&nK?EM)(}D()fJioO+aD z;ib#_z%|_n8u;wyw2~rLpW!{JU&paVSIsj=5oRCo@cN;vJY(xlN6iy>NZ|`%!`l<1 z^-xc7;XSN~cJo<_b8AdBEGH!0Ims!XQ0Sb$AS_?UI!qvH!_~;F>o{vjuiHjWVewm4 zuA!b;h$)g?=T6&MuQL|ZKM{Eq7w$>~ixG~mG#;>B;@mp>b{Mnm7<5+J?9-c>q7};jcu^b7MBJ0t zOg>(!SVh8Jnx!_elAP4(8N0_qbT2>Dha5Pnaof&4Ii^~44w+F*)<0od@X4g3tpvY_ zq;47U@KBaO5i7JHZcr1CE=r}50A3~FG%?Q*L5uj}0epBoxgs%@>!05!gpqWt*lTfi3jc}(w zWeP1Le)2(tA;U-}ybpV#ibBMS)i2M#=w+RDzebi=fl$9?RfE4A8kqQ*0( z)*+TD-?TNs&d_ATyYN7T?MnejOZ7U(Q7K+DN)c`P@W~-#P#X1#E1#H@db%e%+Lt@# zTwU)Y2%l_adEV@izKX1Z@{Y+PY+=rQ&`hattx=4N-rX&bgFpY!a~|ql4ht@J?+*!o z;ucrpi<;lw)cF$X`ZpViCh4AzuVrqcPylx+Znb?7gpGuJE-{Al>K&4u53V^WTi}L@ z#>beKWHl%)NH?q$F7hHOHrRTRD_`_tTSo@bqOpW$RxoE(sIk z6#u}YS5<%@{b)3`AIA#j#zO=R7ro*e4Z;g-Mi8G`T;(;}i^#9N_UL5(wThqZPI|r4 zFRv0;UVHW2aMM{CoH3JYS+2u$(R(4W%5$~rqf7wC+vDnK_ff@0jOLJk_9JeZAnY+?5`@m1(cO(4Hf5x5S?(r6c2kwzM3U)+ys$jW-M z%SKD*7dZEU3PGWF*;#QwOVW{+`|#_36fP;r$QpbJ&8Z`z1p#s8r7vGPbV!{#?bsFGA}SuC&12~QsD79Cr5uO%I(pCF`U*|cx4ix<#rGNNb2VixHcwZu z3Y46#$Gw0DixHWunpZtNmKYG;Rr4M(13ABu+@msR8K7l^RETjUttaD)e4LO{sBtG- zj2yrK0*S}tOZ=epE+Ha8&Qu9{s57%TCfDa12Gv&koJX@mzh7x_%kADFx9NtOxorab zbZzSw%32ohDvX!+68F@H=YZfvbijV6z~gnqSIx2PtsfjF@Hx2ULMZ6h>@JrN=5*jt zK?bZ>L_JT8=+^NR3a;bOUOhIfrS}__`^%1hP9}qMoq6yDw5!W|y55mHp=BSncUz=9 z6{JuLP=jqV+u~Y1LUFBXapu{#Ab&D5MLmkp0RB4hnF2m?>=tk?N-V2!f))|Q_=6Lc zF4hL0wb-LYij2yfXBKS8M$=3N>8pPnz@Cb0JNFOxe{c^O{a6|^|Ka4x>i;wDf&G7v zd-!YMZf|E{>+JLkJN&{9zp%qE?C=Xa{K5{uu){Cx@C!Tq!VbT%!!PXc3p@OugB=9^ z_x5uCuZ{dmu>Xq5zhd&QnEWdy|BA`KV)Cz;{3|B^ipjrX@~@cuD<=Q{LQMW&5$uk7 z%8LIt!5*zK9rNFOz@A$r`_BZJISKlId>F8E*~SSX#Ebpx*wQbCb4WJG1>*1`9PxVk zyZW+`_YA8~q@_LU-@2cur0YdRHy{vO^~%&}m#3cY zY=TsX5a#!;A1SL;#LZGW5H#y{WPkHDn!d;nc2_>BR?aB}ZMM)#8WtBE)RGq!+5bEj zNdGkUHb}h`HK-`mH)d!JU;j{Ye=MXaO20dsfU1(tzJp1vHExS_cCK_@2FMKEe2)R~ z1S<^8xKk!DOG732zvBK`geGC z7`ltNqHvozzUo?|@dt zjZ8hMW`bxzDi6G*K9nKwI#LfeM>)`ke@YT%XziUqJ&yNbpG(r{345+1Z6!jFQ4m}& zY!P3KNba;Mf=232F|r&k3*X_Fs5jwIvu}az5?gurevx%j62MH8Uy&ePuet>=Qkcm~ zsu|vwLJr)I`4cObR%zRU>YC$TZa*kJb2?zy>#7t_da6vZ9WtiIddeym*Nr=E+p(s% zZM}XVFAWr`If1Gj4mt=tovgj>lV$y?U}pcs0QIML$HXZWmj)$En#iDRCKG}@zcBi) z8W?JVhlE--*-@3kr}3C+%~Wb)XkV8mBr7U#3{uvw_tkQ?PHJrMRT)g8tXt5JxRj{C0V>NuWbFtQgF*q{o!)@)pq=0~Tyj zw4fu1pwu^|aQi z8}3LzxuA!!8_LrP9!3A~Oq!V1BM#YWCgTw0$l0w%Z4JY>k_Tv#Y`NN&5=g~5sl;xA zfPO<7x0`&Iwz56Us#0N9(7N>dZO?$qtXjVyVG#u4G?BVbOCwz{ifwEEJD6byNtZ3J zK;EmQ+y>Nm)Bbd1sUUn*Sz67&O98LD9qES5>M{yA>7$fHU%^=%@m{;(PL+p=DmZbd zV)8xAu?B}ld^$O7@15f?WWo{t@!VwTM+=pRqjU4Qvhs-x%U6=r{*u#?>9+3Gpa*h3 zV33oo(FQG#3x^4oa|Z|kyBgA|yUOI7=4(nn#?lABJH6PaI-LTn9i$Sk`$w>wJC=SfnrO8Gy) zfVyBfuSx{`)bg^6M?Z(2&7<#h0ja_cRMb8T3F|kSs7W$HppQpCwZu?ZG3hga3oeWT z}gy^luDy>K2+0hqKg?pnKOp|0gfi#%4^>DLpv_I`-ZWo!X{!)A+`qwK5Vw)s0DsJeGhY)e z)mume)-FJ4&!TdQK8Y$PYLv}_A-9|8DWztTh}Ukd^zuH%bJh_v@3$@^^ga?_;MTM3 z?3sNl;(^~Aqi_p(1gyQHPv*O1$h!5rbck~2a#y^NEfG@6$lU`&C?jcAD+Ja3K5w~C zl^GRmX5;L}or_m>b(y4;Guq& z(7jBTt+jgB+ldYLTt<4cQNDQVU41Il<9`_PMMZqCp?}tc3n`Ur1?A5$j1={hm1`4x z-oj4v0!tKzdjX2HJriJjauc!b+}l ztiKZO6DKCdU>6ThuD_v=fPAUVtmdo1!(K0GFSEnkJm0C)fjJL!|dsZffFJN zwk9ukAOt9l7b{G)Bs?fJ+;3ik18n=J!l&*Zz@**2E6t8U8uJFy_rC|Ju4BywmGfCX zql!5SumFT^7)pNPt;wT;4TK(Td1%aSO*4RU6DPuG+&qx$zYHHflG0C2L6CnT6mmuB z1{24|u9IibRZYi@KJYic)zmXgh2?5UT`$6^oSASN17jX?j`H>)7eh8OohHPiTFb9*4bJ5Umcu?KoBO9-v*mp06AFB15UM+t8c)lUQl3B zZUDe&jIFE?FlZ+UkT>DkU15+yi8gL34A)CKcyUe5Y%(T|Wljl(+dK*H<6Rsuc3`Vj z4e1Pk@|~~H5b<1bp1Z0L%|#WTn!Uwge~Ul_Qqd{CT$0u3uGc zAzB*Imv&XbOjDuk5bRYgsLRq>N%CVq{(r1H|sb3)@(@|CL&GUEyW{ zCPAPNVq9pPYj0K)B;vRD0?cwy4{5UG7D*8rDY<#+$?A;I6otm%7QO2H_gr($yZD3~ zs5;WM6yLZjU7u!ja3RuvZ@BS0HG;Rg_QPcC4uGISW~!pz@m?jRQ@Re+;BjYI_s&R7 zVa)DBJeyM{ArV0)n^B8xDECV@s^=}7q1kgRPCVxgjQ|AJ^f|MzN)Mca4G}=pR&_4z zC*S`8xiNi%{JH3@N_nb_*7DE;4<+cl4c(-v#WZmZ=# z;DQY0D+&obDko#@L5XorYa3$;qw#xFv(^p*r0r?c%&WV&rFWrs{CAU2T0a2DmgK1` z1{E!nN{Iu&q5C^qZrTp7e+ro$8O16bvzIE4L%sjL7lGc=4gSn1GZ93f(@Tx8^yo4H}hOf*!Y)6f5# zaw$*6QQ%p;jJiF_FLh>Tbz)F?Gk?6If}FnbC5icr%jz_wk^bVkHm{_(`x<`ax&8 zyts$0qI#)X!M*&he(QWQfR-z*(A5IPmEQoI_fgA}UPQAxYPCD|3#3w3O-mKt22@HX ztx0BPx@%i1lDm6w*d98FhCXOw^V{LNY9+GHw&V_TMN8$C%vyR?Ma{I{G|KtVyGMPa zB@gnG+nh|1k3~I=V1~u=)ExZsfe932G1)QNsUJ4Ox}cjncUA^=Z=qy7!757veEZJQ z;+P;gSXo46Tf~En?xFd5lj0dR*M9cw0`j{dlJrwiv$JHS=T^TXB6`6hLXIY`;zZ6) zqvf_)y7j=*rBk5^V-BymnQ3j8>!QVKvm)vlwS=O5qSL*__Ef3Zyjjc5^kV&E=W^G|qon4h zwm=0-X;&zj+AdDkcpR37l~;*sODw9qMV%#VGys_&W@!t6FjxiVWXv&wtX`Yw%H)|{ zOO2Ts_$(J_E5CPe-{exz&YoqVW@KByZT(~pv8J?W=cjHRusYYAh3*tJZn(k<6n;w! zucAXaLmfmhzl(*cnOUU7SxU(EF&VSFNn>>kt@a!|-a-Qvv!|5OfOa3~?3O735=|$1 z@lAU>J-TCBDhP{B4a++f2TkO8PXAvRfEu)Qu!q#~#lyky@j1mal4$3C>DxkRm(IbM z{x(D|)dd`Y?S{#f3*liW^=n2GYl(8d6H6#&`>IO}gw!>2XT|wK@dB)T6?htnPLmV> z1!v==9Os%=^S>gGE$Tc2_XG<{aBare%L2F6x8WsCLP{T)bh$uv*|~L zQ~cF&?Cey(v^hTWqTvzgZ0xmOs8jS0c+$s!6`fL-WoE`m<_U#BVKB2k%0wZiHGuDDH26Qj^1wq(x|G|^%TOiM%b@y7V!|~VnJA_U5S-JOmcu%Jh=P~# zpjLZ`vNTu3@Li*d1LD@!dflkXLPt*@%dclMX)Mk|1M=wR-0xWv_KS9c+ZwPX=+fe3KO{1i^YK4ZS8IA!4-AFZ)tzYxxps-WiHj}rGs)x7kA(wl)6TU2qe=Ty#@MyeMk~rLj)Lr# z5qCfh5fnSS#x`XfuV@8C;nSEDASbI6TBVuEhHsBMz)d2UATP=yDjf`SrPYWwn1nVC zEw8)CJe*-?T}!BVUvNKHsa&+xF69T$u?S#zlz0n1$%Rb4#-_CYg4&O~`hB2U&l~w5 zR4*V`_wFTg4$A!GLq0)aECy(UrDAe}}9^xy#dUqXsVw_cUT<`Dn%fLWL=)wm(A%j-h!@xy}9tD2O zt5hEC?#U@*O!)#Zp#B7Hf{ZPimiQ+XEJ**oDA3vtf!#$bdPf&p)?586zvBM_uXe$r z9UXx_HqiD3s~ZFG^qPJ0Ak>D1N}OJ_@Jfb_TGNR&#*?Zy-wfXX5EI|!&(}YwX_vru z_h&(gJU%95n0aXb%uTa2|5gWxwgm6NZXSmc zv6@898ym_}XL7l}{bL8*(3WfZ|M*%6t#xJ|f&GAZI)NStI!5~fUjZd|YLVWajna`j zcl+({@8;!_zc88nvG5gMNtXrCL*sNP2sA`vJdng8f zFu^%$#T&CbBZ4 zgn$Tyae`Dd04bwPoQ&M-_sa2Oq~9YNW5xLgL9b*S(-IKPU}sRi>PbS55$a~ymWcC(zkC3b=- z4i*8~L|J?OfecNI>gG^1vh-0`J!dpxcD#elj4ayjV1YNU`n6WU_s{+Az;g*Gk?$LF zn(Y-(r$Qe(scvub2#1#DCSXZ9RGA(atI62tfrHi%`XD+7D4npf9VFTe8YWNF7q>=0 zZHMLp=LxV2=p_+6l13VfbREtZZhwJfB1B6xC?SkqP;iXmB1?lIMKC2V>BKL}?)|Uw z%)+=hrGZ7zaRu_c6Okj+L%oxHwTSJHDm(_o*d$!g@iAf;MR<1J5cpu}CB}UEu4)+_ zNEO?h40mTiZILjjYPmYl3&$NY<9Qjh7uwVi*3vYZ1n4)ISK}C9zD0QE5tbcFwWEA5 zRX%_zhZOHxW!^gx^xYZuQYvmsG@@i0$xKS!*qE`uIIQJ=Q{%2>;r2~$qiEBH zM~v$R%*R9c!~y-gK{**IF!<%PnzD(mi=l(Q+)&K`WGW1dV9F8f0dW;CwF;G6Oe06Id+wlbUDDBmWqXcy{p<Tuen2F05?V(a&1SeVtqm%7%iH|A;ViS;uL%b z(cx9V-DO7cpB)es@vHtfUX{hU9af9GZ-=5a#=5{VmBSr&30Ru8BYW*{I_M73yd|=N zX<+M8-7ZWI*_}LG{d0bWKepFUuflrZH@wZ8;uS=49kI)rDg50M$061xna$RTfFn~@ z!A2fN{5s?ncA>(J*qH2WSMZzl@xDfICya~IzSStIw7Is7NM;)-SKwuup&!Z$1sL*? zs($z}lzG-;$+Bg2rm1TF=e|KU&V6@>@amu{u)j&UDpr>Dt4xJI}(!;)W(SD6e9CGpV&hKb6}jVkjsVYzAcr#~Is4%VoKr_`EACFD&`` zn&FaRc1MW6z~4vbn=(n5nrMWCGXn3=#+42G%)W8ueN0yf z+>y=dK5=uS(w@4gpsZ3jgRRsZ(ySS=eu@{BowUK*ux6l|eJ0q53C_VIn1js>i)sie zX$wd)i~C~LNIuF3wU(+3$v2_l;Cc~t@((-_y8X@di{s2Aek|VM7P3&y9a8?0SLO{o zDfPds=9`Ay?AX+jwCh+GBC9IkuMg>2IK%}0cRtHjb5fF430uy}F)chsgx;s#V2B_p z?2oB&pQ!>GNTi#fy~xrKUq74%Q#4~(H8h5p{5PKQk2&5ux_9lXEz4NS#rphm=;?&l z?(yrK1OfSxamaV1uIU!EsM*Rr^<;bHoY&pSR?8ijmS1&ut$5A|8wCk~c$(BR)+x&} z5=daRX|l!Kboq%6g>V6oVM@!eDZU6dXh52iJ+WNRAQ?H5lNT$JllVA+f><~7Gc+^PGXZ-d9E=&?K+0-IwZNg|GZqVN z8w33oaaZJ?dNq^ICT-7XCWSCg+dZ&KjlyhA?UIRxbq-&3$DU;we2hIBhFkTcV%awA zZZt(Us8s}1sP%r$xoee99B(t&NsKMGDuZp8n9zZYuxFP(4tu}V%Rz>10PNg0qc&KB zQg}|;QAg*t(VfvJb(uiUp1<4V&b|cX`ar~iwb2kx7x_ZiBsr&TwG;+>6+|Rc->6BB zMv$@P4;o%sW913xp^0!gTk%+;F;Ea$F9UW2I98v8`hW*ccee`IT)3K0 zJaHAh7E5HR|K9zxt3Ki%aaTLMxr0**0m{W{u>At>zPWG${fLs|;Gm^ENJOc66B3m( zwp)IRF*O~)i&#wy^dRPWzw3pb0z|Ix^BRzY?>(t<4VI_Y#k@Tk8{RDT(2#o#>?QY! zEs=_^1*RE821u^>UI*Yamq$gpsWGH@z5b0l9=ArO@Bv-%0!V4XDQ z*(v&_dMVxDdrOLVzZra=USEFy8FV|1gk_iF7oTU_ zzdL`(@EzTiK%f!isuY}WdQpnMm}n=riE5#w4sir`uRr*c%qV=7yM`mI zmBGSB6O<7-T^?w-qo%^$(fGkoUkS860uEdI-Y$;hjunZD`t&Bd%hOOaNgH zCR{Lo97roW{+wK36Fo+okGoA1pnuSw(?>$bb zd3Q}@xE=9}KrP0OLB54<7u1+x)Htzhix|04C+H`}c9ooVFUy3y-@@2_au{bF#r1ZO zBnuhMQ*)M`?0`HtasVf5=O*bdi07SQ3w;;yT6Mel7@=U#(d{D*H66nV6gVRKgDK>K zhkERzH#A5*ehv*yqDAAGYitIzPXJlv-yQ?h5=Wf!LhS~SgaU&!!f~%QNs5Pe#7HO~w z#^!~nO6B43DURpJ&lrXdmepxkqOc;Q3UgTH%!qQk6 zTV`fu2KxGq??XD&`OdoM%Ysz*km;zKkU1C-DFjUXwTcMjRFU^@cT0<;-^CuU1< z8{nT{imcd)!m=Opq5;R#_fg39R6n8kPNDX%av3mO`Zs3f z2_F(_6edJ<)J(6Wj@HC|YiUXMnlgMXL8=<|$*>IN<>H!tErAx?zu-n*0kZ?zSCWKm zq8_*EiVoaO!HgRf$P1K?(M@a5*|ivJjQ?gEOT~31sQlO4?>ZO#Edv%)gg=LZGJ+Nv z$)Z8vpP@h0*&8k>m38D#DlWldAa(Pyn`@R0O##9>fk(o}^Ia8bs7=dBeelYINP1l0 zH<%Fy{5_s>L>M&@P?#S7eJX|fpqDG_W;ZtRJ+F9Lf5W^(M)z+X zs|Fw4^4Kw$o3vAqeU5uFg7gXNdvU@{kXj87RYZN{lf;cZUw7u>JuUAPdD*{x(yjr9 zkw?=Mz^0@+!QsG1d;K^Yz}cAHn#LVi!Ww~iyvrXmSX{dzI;MCIQ9AxI22OOykm~2V z`fD{r1Z*WfK`}ssS{-YhB`sG%;E&54VU(CrH+fma4eG;1#yn)G2tEOokUTXcP+8g# zkNnZAGhwioQpy`d!|;M-!OP~>u?6T^O@=$?g^HlF`dXKr5k|N-U7&)SwzB3HtXv+< zfK?Nu_!gIE)Egdc0Dx6NAIJU(56si4?Q^^7Zx?P*hwN=(=)e&~2wxIuK#JWZ2q96X z+Y@`*(Y@JF+mg^jBEA6;=SM?jg6OH8K+2hkvrfQj} zmtHan=5R5YNg&vx`xr6WDR1#$hyZT#sqy}lWCd-LEMVUgZtEa9A_hU;K;PmdQ-qkg zzhMkUBTng{Cz(e020N*}g#l-jZ}k2HFVW`OT00L2J^(LRFcR#5ILF5&Nv^d%=&zew zoHm{EV}IYp9TTik#O0({U9GML5D+IFDo>S^%t&%}XS$siu(DNdR^`;I*z41Si$B+d zdoS&PL)mSkyAQ}9DYS>S>`wl9@AXXqlHrz!F8m?2b3_ht;_sj&S*|~Jr)PJ>+)kWQ zCinp%rU~z~Jx+SgaA$qu5rYVImnXECf6^t6cD1T4Ids=m(HKnr!pfBvhss7 zTnyCwYW9b_?|5lsSFM)o37)qv&Gp*dEwa6NQuc7Rp2C!tU$Gi&t8!Y}n6B zYgzQjy8$D69+`9=!A_??jyBdxu>p&LzJg^65nu0Q3N|{^Ib)`0qlWy5D$Y+Jr~j>^ z>k8L(SaghAnj+wq$_rNW5jzR54vnH+s(U01p{#@XgE!QYAl{@6&e+tXhqy&)-c6{L zumf^jm=aBikT?yazI50{(cT)ajErfI5H&s*jFK0 z1dme=kA$KlQc7|Xg5F`9K-wn=bCz7DqhqfgbWmrp4nX+ve;ure!%Qs~q^nO%uqh`l znrTO2K0wFu1@rv7+GozdSbu(mCt7hb2}B%163N6CmpHUz3Db%rQaETwkc-fl*<~l; zA+nmW)8et;9xaiEn6{*W<9ovv1idb~#TMsqQ&Svsn6rcPa<+%3}rKKbh_A@<9h3l|!i);3?oCF`8xs5=S zuBRnc?|X!HvRwG-THm;wtdGDrjcOUo9jNfJ|UGI>mWSW0#FZ=>yTto_59%|&eEe6o06dUh<3sgI% zt9E`!-N$&XFq*}}<6G>zx=9t&#lKC4ffp}=Fk?w+AjLM7 zx&0Lyqhh()QOjOwd+^a9S?gPdXYu{UkQjU?@26SQf>KPa?}mVs1>V^%Y7OCP8K5wZ zjrwvt3ph_ZEXwxK^7-5cHavCTo7?JR_*!w{)fc08kqj@Q%$gDOEtKK53~gZ|ry{mG z?d0Ev3&4W5=ns~~+5+y*h>5$f9BAZfG^4Cal1+<~cI(Z4Yef-&UFGnbi^JGUrZUmdbFpGunw>I z24g!ZKS%cC$$=Xed?)hYg*XZs-#OZO>(NeycP*)uZJVOYU%;)`39v_kvh)fB90HyZ z`_Wtk$Sa@17Fewbk%;vly&SLKkc2Rs(+RVBKNb53dobVjGsuA;tV&$D_+J(4@6z8- zhy8MVDZV^Y4gb~_($H()lT6boync>rGvs;!f({xy$h+A9S|$g1A)FD6R_e-ekBKwB zgawa+bBF{12Pr(2NHVSDJ?aTxa$!k0_*Y$(-cFCOU83a<>^GSm;V;5HzON>KgfCJ@ zwf5jV+5!P;CQUlM*|8@+&NOU}t!YG7;UrQ0t9gh@viF8?| z<|wB*vjjysl!Ni(D8=AGmgOd8UBGyw5#?}-**s!7iA!GGSCg;NRg10X+?*91u~e)c z!=`ZX4|{@wB3(z>Z*kcp=$am|GFlIFH3(E)t!kjd;)CV@qk9Hpms)pQ5x;o@>Sh5Y z_caa-Wg9#JdPb3=l9#|HOA7)o(;M&XV%xGMS;J|Jxa^2EcU0`*drrKy-q>h5M=FOq zy(^}rs~mtaCUAtS|18ruc~sq)z{GEVUpkk ziH#NG*U}!tr?ZU2n@BSU?C+Z^AI_xm$L{=(=_#3$u%o1CIN~mh-_X`j9DO{rq+$?smC>V>a7htxKQd@X{ zqXgTQ=t@k-mU8$4q?iWjdZ*B3{s*9L#a!^Ewcv4U>qHbHV6U%8 zR|Kp@v4(=GAUND010_IcuwD0fx6g>4T@?1(L4A?l=l;;x7R&*-A6Kb0B^Y@*w`o@B zCGrT8DOxGpth8dQHH1&s0r`~k647y@L)s(*XycP?%Y#9WSXt>2nv2bh4bD3M;2 z`OHka1J_!bky4#g-K}*-RIbjPYHmZG4MK`0a7>JxtYYe%3EE`usPSp259@6F6uAd- zmt*DAKw`TEO6|Q<%BpoRrJ;jwH2El2ndt-=Ye=EnTe0EL&n@n!aFm|lP8-aZv?AEY z2gK%YXBG|!k$CO|R`nQB882u_H{fGzC|<(h_mCYKFX0J}ADT8E(w=J?gMoe~x-sInOVD2W!5O)A!TEfkX7kEgv2LrDNU6 z;g#hztTg4-w|lbpHUc6bS{@$|8xHf8f`nl#bwc%wE}54C`4b1&C-_+uDcAB@fw)^f zqHzb1`Ye;0;EsxoBl@qfL4=UU&;WTyzO!ot`#3@`>@)3#s7~iYIrG(6KzGSaxnOvv z0=vK=as8PLS4*0Q)hUMo9LqruA6k)$cAor#%GFZkf6kXLZYqo)dy@#|86=_$AE^my z6ZUyin7dI#CU0d1RU?Gpya%guB>U7J-tT8g+^PUI8zWlW^O9U-_H*D1GqCoU@EPxpOdOu0Go&&q`-?Vp1WA~XDtVPc2q$5A;SflWX`Pa_wpYZi)e;VxpKS?7$C z^nPoE;S-Kr7k{u}=KC$K}z>yw^_Sl-CO z!tOqjt2BlSX&|O$)DjPjEd9(fQHtW2X(dXio`n;nKNd%mJH#!IMK+7Ta^8AgP)jVn zwsU7j7IK44qyMCBaUQjub`Vvuu@O&`3}8QhQWcYD=b;7LVoNp(^9-Vvlst?#`RaDJ zE|*&r@O(0L7kWV9*WLK%H2plQM%n#0H=2nEl0VgnLc(LHXLR=}SGUNOS0Z&@`$QQ& zVaUXUsHQB8s#gm^*xE*k_hO9V!?ExkGJuWsoI%1-jO~c#g$>|euPTK^-uqF_npLR^ zCq;WME@T1x;q;D5;1DpYU2i}r0sNF&WB^V<@-)k~Pgu^;S++1Ao8BAL{q7eYh zm3!D|a$`+_4S*fF1S#w)us=K}D5finhplkuGxS}wtkjX}zI3DuOFRjT!FCtbUNsn} ze-HO?@2b$fzIll#sls>GAx2DV0`u4@-8*t>#LehSic)$|kUBc$wxx z_2F}p0&YaQCu*mEMaC4yrIyx{+^3BP23BjKu1j(pfSl@dQ>X0^T%E5qV<(!z=QVC7 zh~#gxBgPx;i9RDG=?A8F<{g%kTJSYE>jn590f~mqDibL(008*V|5-rde?g~N80$$0 z|348n%}vKGRwVCPHT~}-WevyS_R<0CXzJSQD3VTU_tpkFC4z9wfiAy(k%gnnS7z}U z020xi)OnbBb7rjVQuvGw4)>q2VAV`P7p?M5Yo4!TQJ-cmxQ7}98P|RqJIftVVh*|s zYnqKLw*4SQ=7ESSn%ithyk0%C+tq$M-4tvE$;@pB^D#Cz}^kXVUJ2ikL!!T@{sZOT%%5y#7^5eO@jR;H!}I63CqwQBr< zB~jPnOV@lk%HpWCJDFP05>tF*Vyc$Y?HEioLms?pmhiuIYf#@gIxJ_E2ybDt*1_EEfpy1 zEWG-`uJ&d{dafguYA~W*k9?NIdfNI{^@Q~316(^1*3-C`!L~S5?t@yQ@acm=8O`i| z*_Z5s(Zg0h#BcLEQ!Ul~l#8##%nUx{^_o8*0 zmK<4An7GsZbty40KOA~xlq|d1ipqw>Db)I~qalAGFudi@qm8;57lNe7R1r$2kHfC} zJW)yUF2~imeI+dj$#ELF1ZMDDcs-x5+V;2l3;q9i1sO%C$?~=&(Jn(%N$G}uNVRW6 z!9E{i6-?2B3?#mCFR{HfrP#|uXB!8ru~UP*YbQZ=wnkr>ss5vC!g5m<(~5=FqvS5~ zt$KRV*i+TT25iN0|h~I zS`cIAHC-?=thy}ygyw}6<^k)6J(nV?a$M=dxK)Myrhdk4D?zo%=#CKaJbw$3_tCW{ z>YN32lS(!W9Xz6cLaE6sd(d}Iknnl>|6=c*Vg-rXb=_&(>}gv)ZQHhO+qP}nwr$(? z>}j4}|4GhSH+!$_t9{dzRAnUNu98Z|lefP25fCMF%hrZYKtYuzF?ty%+bj2x8p-5U zRjou{t?YCKZXwKi=YzO|A637Qf^C$2ga~unwiH`xIFZneZMrRc^PBWDHgk zh^0jjODouL8P19~y<2r@ zVTQ7h)2rl*stTVcc5^fHWGbA6?dfgDTVDL)Uy0!GAxuDK?ZSGZkL9FG97ZvhJe?b> z&HwXWr3*F;FPz7GTd-zu&g3z zdtiN!9_%(s{LF7?%tV9}L~BD*e+peChD0MJ&c29USgk+cSAPptQ=|yy!Nl!J9F^&y zb1_;-IZ9k#QdkO3tfShMva}^LOPK!bcN|_lz0wz9^j+XA&)+moo>RetQU)O-cnY~; z1QEf9!tdp3D_n$-ay`R(Iag7xFUO6_!}kA)<~P6z%GrjK_o0xdz9Xp!3uX#?dK4DK z0GCov6j>LpggI4>pmBwr=zkZpS-~*ZMqY_EJkbR={}Ul5e&)0E7MK`Ynto>os8G*; zl}Yfr+h)grGVtrQu|A+RvC_-)@}!Tcu+9J2Dn!J>EC+O3^#x$W3j{mMsnnlksHs5|CBx{Ve$mI(5hV#qItu*+I{tpu`LEn!9m*zeZx74c>O<4>{sAuU1 znC6v>-w4T4TC!Zb{W4>NT%B&5iVj%z-3?Z zvMvZTJ7q-f@8k%K8sKLp#6stS4#M=Tg`66l+r|O)RLgW3@*7bdT0n9{_(4F{Ok1-6 z^bmW7T$#)kQWmsmf`lZ?3*@`(6P58wCg`Ig zSw%iAnJVX2mp|1<*k6;E9oKM(y+032IZ>jM(?y>px3s0h>mHmOlj_kW zEf}i-tvmt@uZ#>hwE{~m;@yIT_1wWlw0gCHrZ{vxkW2vPBpIBoB9KL4^CApz=f_YA z3!%$Jxf%#&6C9WcqW^&^fb;-QBd}n2`3Ch3BcM;v`PHxGbGBSe$@+9Pv!h3UvC5+X z5TDZAc=fV-=zL4kjPCmZt3-w#4Lzw*i13UH*FuOvOZ)+Xgo{fMSAnI`Zt2?}Qts-v z*^$6O(ULFWgwTCpt%1$rxv@iZhmYmH>-;1$$><6E$$W+SrGw^RPzEPtd{FjBfCn)h z)cd|Ecnm6V6s88=9VIN8QAGhHVW^pjmIF=J1P#R`kG2rj5$(5veuXn6mQ*Y^s0rTJ zHOod>Eq&%bSdk+ovpMnl3DhXwefycmy;7vN{V|5A3j{;r_8!Q(rG*RikrWYP{&$nq z34HkWLLuLfvl~Ee^18Mucz(IEHgrOM%$P|$ob?i|*a8_4av5t9b>J!BU zxJ7hlDu~B^LES)Xf#yj(kxW0d2bxDWIX$+Ljj+Z5O6O^|6;{rd=PNc45+G4F zQVMmL@JOn@dzbvqoi&OC^T~M;pFp92lNIeex$6OIDfh0cN|S}8y2J3|SV zFvaoRM8B&y{;zHbjG7uB!}v_-=py7ITtgSMqCe=~@Djj_bo`5o`HU3dDaEdFK7GBR zMx`OWd*$cW6N)w(l%D6UO^?#z*lcBNx&agQD>(rv$mLp;5*Qu6J1b=~ZQ+5*#FPta zZDq^QMVl2tV?sZWqOxi6A{+JvbeZSw=LQ<&descr!e39JJeu+(Sb3!J&x#^aEQ}qW zbP*)ZcLUsH@4Je?L#@4|Be<1D=kMy53m)PZ0|zOQbltTVr{=e$liQH7qKniu!%FsG z`Uu(VQb7w$d|!@dJpTBPH5?4Z$FZ4E?$H?7*a(8>quTU0svOt5yT=Lya9*%IeXD1} z&5cF2R$g6rngjRU`#)oKhO(7t`yb8uy-%}>?>Z)~L;0bFiBr7+MuLl7Nl*Oe<$wCK zv*qlFd2$vS-oCai$Qa)tB#CUJ#y(BSDcm?KgE*M=ezQS zyghGmS$GL=ca)?*C4TY;sE(L3i4}4TM>j(w36Y9YF>_@=m1u!El?iMBW%$(%x-zXSU`MpCTRNjnHyD+g`MeR z>Z)-y14G&wl*@|J3IO0P3B|Y>5a8S#D#)OK_et|9`UghsCPG99z;E}XmY~>SPZ1cP zC4>m1p!|IA^!wWj>-px;4Je8P*j@sJJMuzGQD7GdXHVF5cYo;sK7N;(F;0*%$ zW$$-g(0yhIMV?NzYiv%XPpQAp0932Sj<`~r<&b+34|J zpBWV3@5hGQx23}AT$UM4lyMe2W>_R1NhmNk7Ec=pe$XjX#Coc8P z!TR|VFa|u0Mp{uK4G}CxGJV9eQEdiS3PL0?hWZ#0r1J&};%Ev-i!sZ_bBaaWiFZP1 z(Twr7;%Imvue-a#Efja&aFz23uhE+D=Co+}P^mu=O!|k@smWp~x!n8eq9ph7ZF;T+ zOa6Kc@<@z*o9&|h1ap^DliRz%H9o`P$p+jC(@G(l8?ws9x*-c#j{30G&-^5CiI+o2 zB2R!!Y767!SQS_mvs7qIb9E3%GzQ^%`9YS>jf}-8l}p`b1RXcUbqA-Bj7mpFIV3V( zBZ3$Ru;-}y1Tp@1jlanVsFZydvk7w&avhdUc1}OjY0AWgvlyGq4wV84-qREP4e1T2 zOe;+#^&&kY@24<0M>3p*|XH58S0q(1{pKc2@B}kO!@aWUCG}P9m_Jlgz1V*BZ zzw6^~W|ov@|R@h5O@N6;+sFvyHq$_L@HUh z{MybX;gwL4w0qq1AnFL`opuVKJbD6g`t57*B}27LH9pU^l)qB{L!pDCY@mBpLiI$m zcE$s?T_)Nr3j82V)w|)p3jploBx)bcLX3)A>|NEG?`6>g(#UYwQn7 z4?T)&3Vs^?`xhh(H+ksS;-*^j!0rn!@uA0ImBx|YzM_ElnZ;-KE7<&?Id}i*5K|&L zPh3Z*hEmk4@$1ZPp1#6E1ErliwTBcYQ*#`bME#*VkT%@35 z$o8Y+BGa9cBT_M=WZ&g6FQuYJ`#O7}!cm%4E(2JkflsqPXFqI^D8W3U4Wi+YiI7Yp zJ>3uRMpt5SNSY1ZRqAXhZ)v;Kf|QA`J)d7Ls_cb>d-4kGLpL3Y7ia8*vs1blPL44wwhcq@F~Xq@5Yov!w(Y<5Z7gG z3}ot=&6mxdRC9kO5E{@Ey}f*%r%v60T69^hTe*>Ei|&jbxrTzWWxk~1wWog;{fEctt;FrsMZbIjnr>3v|dSuHr{x=BxD`{Qt2y-nb+{vZr8f8DH@~8 z+|L}NEsydghcO%~q$vfN4hC!he%2Pfr+<&e$Q#;P>a8-MF;QozWK1%+aA|OMB@sUy z6W`vawPm^;Dh|Ggp#sxt3}!z!uokf3!}pS0Nh>hNhon_Z>lCc7NcEKBs9KXqf8p06*oY2Q0~2PinEZu(|Zu9e9RgGGTUQyo05M z(PkbaIV+1>?WtE$t$^&65Q6bRG2{}Co%W_TSEimf&}T|~8WQTHN2f*YeFLG+lDp?Q zr0=>Yc+S&M;)cOSwM*J->!@n{qsqkmBb`5yU!^#$ebWC0@QlD%!!Ykj(o#jZF|%`nEJVYIVc9ojwyS$Jhi{|YBXZR|E}&K5h}U&@)0;AI5AQDedE)iE7$|% zWpeu7I;zbx$bWo< zx?pldXoKE9)PkTAN~%_>Rx2x|N@Tdd7yt2pkp!ClGB2z)mR->2flMsXYMs2 zL6*wDR0a$CKBA$4tLRM$gqD1tF#bF zCdc{8&Q&M{s71gzq+>(^e9P%`SJfqRupX$wLY=yhILTYR$hm}Qa5$6Z7CGNn-*jPJ z3XEc*IMB7sCZ!)}#11_$ehG*rdCBvVk$qUt`1#d@RW#W%K#%r=e*xN}EGVYAL{oi# zJdCYJg^{!OEL}tT?|ZW$C!X5G8yy2E*`@R}B&9WU9j@6z|0b3TkO*!K?%_F)clCH9 z;?RhzlPeN7W>Gs8?!tA}k;jOphU;!ee_}#jsR8d?X`_p;t0Q1)G{5k@cAleV!h*cG#IuS#wF*cNa^@yaOTKC@cLQC9kcoJ;0m{rpTGJOyGPWEDB{Ya*gbYTEYeC6aLJuFredhv0ml5b56gyO^`^7 zkP}n_58}N=+}Hm4y#K+B+I9FT>GbFTa=Pq6JF@8G@$hR$RJ3(FH;BvFB~%Gs-AhJ} z?bh&+8&=NoZtJ3rCeYk8<=~xG;1F_TYUm5vBIz}NBXJ~!Iw?(K zBeYfMhkq0>OpH`+s_|#~{Zj7j2}Z=wIcAn&rI+=Pqql%QT1k~x!i6UDm$seCVDFP-o-Luq6D(R!zMV1WFWCyHhCAIse0 zK_(Rk_9SNL0?Xy3lR!yOUJeRWxH>q-f*z7ExAX>r&$R$?DEbYQI3Rq-Fd+!q{;c!M z^(Z~i@ZhTnPt?o3T`^sa=xRhx33Ozls(0)_N(BtG!LfG7JZ@W0Ty=H*#&p3(-BXtN zc~TKT2PA^nToP0Pu~6uPl3eq<@)ab1FS8TSec!LuonV;oT6Y5|B98TNWr_4eAY?+G z9#IsDTr3ea7iYV``67mBoVkbd36ql3uh!s0Q=t{0dk1F=^hm8zVZg7&$*wj8;HL2L zC_RaVK4x~rvdsZh<7rUmj-05*_Iq#`5Bfu$I1w2~9;f%$y8u>~?J5MAW+>`oZ8Qjc zdYoIXy#5tXol2&wKuk=aq7>cP>xGSK9V?Ebl*5g9Q~$zffMElGM1~reJsf+)jxRY$ zco*8ut@(QQAu}zSy+dDMSzTV5g1d5J6gn)g?+Rc=g21;0sU@&{yz#8(nU)<-ROtsRbEbjS3E}lqNTB&3qCsX`$Rdz(o^A(!#i`xY9CW2xh)IU0& zu=(VB#`bx`#e|qx!lqcv2gkHt(AKYjG2x(Ag$O~& z{OsdR%*eP_P}ni@-^q@0Ips*UofMyd7zcYQs^jf3+WYR&SDjwsHJ1g*<*R zS*A*4^H?u*+YN=0J)=#gl?{XkbkpzA85ibilfAt=K$H8t8}0=kUcxmtRsX}#y8>2t zPs;Nau#+wC8B|vUxr$>ashK7X zxejz;QsLS!$)6QBHH2B@b)+B5%=CwkqG_PL+|5jkUu;j%nMMn947pu3zxLs`q~95i zpbf+ZY9VoXX)_~6Oq;G>wylX>>Kvm~hO2Kc&G0b?IQV@CR&!lxJU(wQu!}l+g4QXR zdx-smt``_?<}_K46k4hF&>d3BT?Yyfepyn_zgR>SdBacai?6Vg!|XGQnZcl9TVVTi zr<&TX;M(UcdJkU$$t5an9zIOK-zQ621Fj=FipE&<*JGC4Dh~F~uCCKnT*Pkd-YCiT zls=IbH^z{s`6=2C349K;b>h@AsvftjD$(m)my|JniMFO(0R-s5)xZUq=#=>9otQzF zl2}+rfcW7*ZG7aMipB~t5$-rn{d-bUxIKB`S-PrZvKnJ>!_aV~rPd0X+ydz=` zJDWG2oU9}4y~{-OL7k8(v#|}Zzn%3t|phD zc=@i`SXW{)m30K?2n4J9d6B@nEULlstNS(%Ca>5XePD9y^O~1x>)&kLlJC1U_^N6Omd*q)QlMkI2W*)FQuDJ z@1JodxSohQWfCxK=yze<_@`)th%}I+mHSBCd4(&kx_-h$hItxvsJgEf0oIsD5l`qR zm^mnuB;UXO`Q^d>+jly(jv(W8Knd+-ZLmHr(r&&KMBgu7C%%`NlaWV$G?&x-sjbr@ z{JMS{quwJ3`3b}JbUo*ngn`+y;}#~#+6r$2MH?C+>R|#-0tA*5;&&mxyw%mrcRJ2{ zoAz!ex9jOx4^6G7r)Eb?qZS^61n<@NYrIvkNG!Nd#PbX|)+-T+$3TqBMMr;3!EmCL zv2klT<>3!A4m zav$jFUYf<6wBZVgXn9bzq?VTX>WWlB?^7L0@VQeVyf=zNyl>U|1n~Hb7@#sQSLy&D zGnlLI=NlRh`@998!SuX-sBW4dG7NO2K0L6p-_g^8mnMvh#>L9Td%0!f8k(|!F!apQ z2nOZFOBqY)4Ji|2bL75CxPD^**TcOI+G+s!jyft>Fv+?x1QavOU&M6+UDmxG^{lC7 zwE4MNHN9Vz9fnqU3pF5hnZ7ip*^O_mdpl%dx)ot!c$zx73j}BBr6I>Zgl56h^skT- z^uV`GIv*!wmgiT0hpatq$Bq}2n1mdybQMzp2M3_1LBQs~9Cl9D8EyAr#)8ogKQD_pSYbr>mMSg*&P$;rMz}z~*qtRf=2Oxi$-sbEoeN-X- z0o7PRO0`6W9doZoc6=iiv@CjiKCqM-r_H}DplvqA5&ZQfB_iu0FWo}(sOOFlQmu-U zFOS>0RKU;b+;&Fp;~9!ox=v>mCMKAD)R0lEH9L6b-M zWKo%7Q47jY-;|~)eNR;hmXwpRScj2`;(>7zS#rll&eHGK_}7dor^bnZ%`Yq(hCtn_ zGtp{s#vEqC_EcUo+PLPKMQ2c4*eju=)Z(jNsEiE82lCKmznU5a3m~(b;g7W06Z>R6>)re^wiE6oi+_?XO1EZ0*vZ?8rjn?0=qrL zCKB6a{S5{}hFch(r8@GV0Sg+*7FsYL!xWbJO6XR3+;GEusVn9Rc$Y@NyGmTbnlbyD z!9#xzM!1#UKn>j?Bv~`eG$ayMPF<`(%Ya&=#pRzT@rl!l1<2PuK*~&OT8Fv?zJ*0W2vU%l3W? zZ$GOeOTSCPW?R8jE`@an7}i$zbNakD?oNH(!zg=7urI@)f}E*9fjSTVtj^j#f~G8*#uS(lv7pb>=3;b=(;H0)UVV31Z)Z(^e)mJq6-IwC^@sv+`tD{mmm64V?Q!n&0b2U1Uv~Nr zUDR)&!S5=XnX{V5nXm}64GvfCU289S)+% z;O{Lb2@HY)00993U>Fmu_&09)|1OcgtN)%oS)1FKTkG4=IT^b-IXnD~pR8>Sbd60+ zj18UWY;1M^dwI34fw7ITiMgS<{y#0zKP}NeEzv(M(LXKGKP}NeEzv(M(LXKGKP}Ne zEzv(M(LXKG|3xj4;Qtxf{r{@je^?j#1Aifqt_A4#59|J6-9N1Rhjst3?jP3u!@7T1 z_Ydp-VckEh`-gS^7qRYtD1b0_)D`}J^+d)0tpLJEmEthMQ8suTYf|Ds+Nhj*bA2O~ z0tRx14+s(rUnEs_-FGdt`U~V|EeDJbj{b-|a|0cgF50A!u9R+WWPBJGU8GiGdu4%n z*!=bQBysv1*H$t=Lh&cDTm8>Ni5t~#k+my#lB6?X`w}Cf&8z8Qy5V8EaqilRj5fTH8yYFrN*1+r6P8NK9Q}EsP$`!prnpYTg)5j$=B|;R}&FEsn;WD zla{8Q{gnMFIeyyi0ZQPSe>*epl|#EDa#~str<$Wei`}%sHCh@Lm?}3=hY(6miZN6j z&~mwpI+wevjK@98H8s1!T}f_)C}Eo@v3F2UUya-L);Xb>D0ZN(smae`Y~Y%g&m>Sz zI~JmriWRdbSDr_b`NLNCNyqNI+;1s!pkW?hZH4Ydk_H6sQy?WT&}on(v^neNs}4h$ zOwY>=V7--IW4}rCovD<{vE#*F6e3*6#7d*6QpPf9H!n7I29qR`yziNO^@+#2m!%0ttWLoup$SSSNP^qsXlw1>8%A-m)_bW___%>IC zqUM1-IB)8cy~e;ydJP59sd!M@RvWQOd>AIR1ayEZW?g5=aX-HHhI6Q~gI)DKQ92wO zhrcrIl{7^&n2UGt_H&6mFN-nb?HCR1X7ACk*Be-FU#4)ogTUuZT?O6>-6tNFKmnz8 zsY@bh)zdiH1QZ4VK;e~*?E(LuwVPsipQVp3%ejwwb%2N~k`KDY^Ph2A{}p_NSeN;M zB6&|Y&4G_C)aQwW6l)qNXT5xeDduQ=;ZJlNQ%`-6D%ABwsPDPQ+ zeqm<+l=>j{q5gND3b~vj*8~8kilH=}#HaVgWCX05;Q1`6lt#a8gewG^K9)G4M;j_w zs@LG8_1yQEmyx8dzZ}^<>>KCvJV$+GUd0ex7TdkM#Sq-@-P++9@;HyeR zB;pn%_aT7`Xc{WO!7YlMyUqv^7zhBV35~F1%)oeD<#zg-ek`=TjW-dyBUaNo$$OCiiU95sInS-HS=*DrjcTj{Zu5sYS#tzc@$s&W!V zi{-$Fl5=>EF(lytdSHuFKqJRl)p{kQFcw)|48+nPhT=CB838Dee>-qOinYcEn*qDU zV!o~iXj_Om&|s|{a=KKYPJy0lCSeqPB0t|ucOpwXy>F1M=>U6=su5qx4-0%G6F23g zS&}d9w0f>(32`b*S;x|-9Py&0g0O1ILzOq(m&8$=GHB+8Sp8@}#5AO7Cl4!jsMRf+ zj&n+k;ih=cRiHagUg)pK&cf}4`zRABZlSAoq_l`~83o%A6ZqCQP|Ms?O=1E;FWZBX zJ|-?7AFHH&0QSx}lUExc&=UnP6{lg%9TpI2#zg=bU{EaxvGKLOY?(0UpxYA zrl`{h;S0z4>UKq>(u-x7YIpL3g=3OcPKO(Zy(aZ=N?5i#P+TIy$JAg@G%!OBN#O@q;o`=kd-hz5186uY%Qk)%sObAe3k$}!A zeILDXPuO^CQip@rEF?HVpHk=)T+PH|K!TA{$GxAW>Xs5V!=1wbc&{+}rdz}Cgxpp! z%>s#Rp_gvrTv-Qd6t)Q|g>RK(JwDe^%-kpPhQ5LMB1T zIGc?P7%s<4l(Axy7<913qLyr{ra7)Py~CU_=OKMqr5p)MJQ$=L{Yg6dqn<#gkU(c5 z-XkU6lST4IN%Cfqa&(z=bg7WxV0>v1nHGd2UPLvH=Plm=z>SjA&|WwZ(@}pd{rLtPd)gh9{P2!dl+Y!gsuHD&NQ%ty4Pqj%@-$p?RBfi9EJmVlMWEW|yJjhD`Q7Fd8=Vh?=t>~PTuWb+JY*TM`MQN2QGlbiV0iLVM0BMt7%V_z86QTB*4fRPK&GLCY>8Q~nh!eBtAY-pzwau?b-Bq+;=I?aJRDuYf} zB>KWsm$p1+Ln+@!jw@}kfDl^mL`kB$(F)ixBVWtJWtc(w#cTwW2yb;||W-Mxi8Hfl$XYUn0^&!h~^BfNDW}ZV#&Z zVfP`;goq58cmZ>l%q5j@nuLl+HBR=SJGczySjbfeKhdlYvye?O~vxU}9AnU-dEe0;qcu-tg;EfS9Hw@}DiRol5hC z3r20}wyrxybzT_^X(2~rne?GtZV@+!> z4l}0YC{zghx9}Cy+!CgBWv;Hr(}sQQM&_T?f)Xp8xjt^WL=T`yiO_&qcS}#wNQ$B> zCTA#WM~QOgVYueT4;VMJ50x1ZVP&`{p1(7~I8~O}akEYEAi3!vz$FcS^@}7t)4!@9 z)X}32-@_GHaa&!A&w~zH3T;A6F!uKxTngu(ULc)#1=A#pn8T%9GjZXWeHhaHc1Xa1 zebji&WP|HTlvl-0a33WlW$H?lZglc2BG!EwYWD}d+Vbee%AU;S!TG@iZ9_aQi$hfx-71lx1#uvXv#f85C{AxbYtz^_t)p_$@l5eB*h?G8<4L17#8yu zbrnHfg$>0k0t7E}+nekOZTl^1s>U+uGpeRnqI^11miKxjcYg*)_Kp_W^^zKqa3jv( z$$2>nEdfRhc5J;ys!v%2V?4kT)}n@xJPc{*Y;xF#+|S4tY*BRFJ4 z=whUV6l23nqXQ4AL;no!amLb8^4zJF!<5G4exmeK>56#IeU+i z_w$2pb5T&mv`fmjYO`S*{AHDzYT?5{G4jr4M$*RZJ<|sM2g-)mJBh~|MXQlZ_g*XQ z(SK_Fd(ro(J3MK%OVhc^wx~?{UC71zVM`ZOplFZy*ok_aL3v!Ix=FuenQA&3@kwP+ zWUy{qqi%@XB2mA(2x0%kRl%aipi;!1S}OO&lFdwP!=6SLp+?n>R~0+u{t(DD^!7>G zr5OF0tUW73PLk+1p`pl_#$gyozk|AZCvdsMQh|Z=``Xt?EHhl45lbo!1qShso7;G4 zPL=Q_4rQXX>K>5;=x-Kh=8=S?x$u(M? zr79U^MaksWN#X1yL}B{C)=~HC>}imDZk2Hhiu1hnUNrM=lP94QN9uWh)|gDb*t^;0G zw;>+ml!}{|gH%iH^4C_z=mjD2+v~M$#O`8&B0l&{hd(Qt?lMj}alr+PP`d^TT?%ZM zDIVD=-Ao`$MkTsh;^E^8Nu3Ma)M-O}yH+3}GS^KVSeqwgD$J`m78t(GMhBk}8H5K~ z&iUB+8Zj}<7KLS@k$PxWbBb!E$i}w4A9vv6AR@t(FMcRTXlf5BT{On^KUu4yVB$8s1zz3Os6ZGz={NkVS*RfJT*l(0 z2{WCz{>J7}_=-(^)qAc9QU;DPNjLl^)8Gzme%H-hUDMQn&nsoWqWH(|Q>I)V;#-Q8t_g!B)DOaa?9 zpBoK8ZznkbBm|k4{MKeUC$U?@Hm7K0iOAoH7mw+V_m&gHph?%CX^}yzyC!K0a5K^T z>_%0uw_pJu1MfrWpTeQVDscyFLM(8uh2@R^4t2#R67AVp7pkvfX)q`W%{5P?l~iyT zry`J+gse*}ARHF9j0JTYHM}b>#e}Enah186P55(PrV*NpziE0zBa0F5%evp%u9XD;}}JPwjGrbM7WCMTz!GjYMyZ zO3vIsmGhR@^TF!k%v>0GC{MVVSxoMG?Cza4tlJrnlHH`|l)vZl=a-n=%3LLNceIvk z$`(9uc!O48v#hmFqU7aopKaM(sbBVu8~7BD=ZpRjb-BDV5+%)JazymfqrLbA#-wWL zI%8I`_^}{3=flQ@FE&crCY&|z@;5j;oL#a)kZXr~6a{uY1fiU0@4>7}Pi>WV^~TAk zF%lwwyOYK^HW}o8XM`(MJhmo0ip|;ZujYTT^VOjh({sz1fMhgNPE}iX3ya)ik{2Ku z!0SmPr3|7@M=uD%RiId#U86z>f~VWJoQzS(TLc|R+{)eUG(|yFf-1>Ip;q;Bq`&fw zla}PsyPE28sb@dXZOzyLOos35lbm9&q=*IdE|4^g6#8aK;)p|>Xu<2_!<1d@gK>*VnN=Oo4dc+qocaWv_IXWjfUci4OwBNADXA@Ij z2Wg-k-v26!yCtpHs2diB*8$26|Bn`Pyla2eDFW!m9pI3L{^i1bD5`oLg+F zpok@%M@8k#UsFkO_kctT`;1+@@wX~5!MaASm6Zj#dd{W3+O&RiXi@E)HiiCZ)Xcmc zw>|aJ$K$5-TrUp&ksC+6F5U!mI_Cy-h;p(Q4u{=~f5b-nv>rxP7@;G?UTKK5G;S26 zgpP+bI7e(Wwmhh-RZ~CUfglqi_W08x0q?69Xz!OKWz8)%xY^=q2ML-j;J`3V8WYOK zloC3Jf=3lHC)B>3@+r$S8^5TMi`yLC^t@iMwVl4TE!;k9>X1t};mwfvVIY4qnZA`8 z>7YA()T5E~;X(THRItU$)NYG*+><@-&ADHdTs9goh2|&uXnbsB856)btIm#?z>;mI zRx>^wg2B`gx@1E9U9Yq*Px4#-Fp`7_Q5Tz1N3P07-jq&R2|>Z2lc|MM8v#2JP60In zyIX5JR5WI`NXb158LDG>)hYwIi~>w~F?O2}@J$i^tlh{bDgH@8qc1xPZ&Z@s zb!5v)qC#cUWR|YY2UU4kY)>fiY%pTj|wbsSzshT2U)^30qW-It`VnTT_UwDT*#}b>cueM3VE6y#{9VQHN4IEs&0t0&Vm0vnjv#(8)XqCE7ko+@}kVnhgEqthFj#0O)Cb{U4F_55B7ZvVu&|!*SJAih;?^uH1lC`tnBlI2%t-^i} zS`M#Ig1RuY56}E;0%)x=Tda)Ooy(KCVfwsS?mJ#E^mE(PUemcld`rUV=&UpFUP${6 zWk`mG2=DpLZtSeP?!__lQRoOU9f#t%bfkmA?E7qOxfJlGB{pbSgqMNeXeAq%5+DO= zpK^`H0amcpj+uUF#GO=Saaw7ml0&nQR8qU!Hf&FC(qNIcLM6V-(*YL6x5}2Vb)6=X zjcgZ%=qNS7-{(Y2@DVKxThW!lX7EWnpS`l#h&D;vA;@+QY_=`-k_>Ow4*U3=jF;fm zaP>Sq<>3|Ec1}(R8`8cc?p}4f@g?m->Mj(XA7ku*mj))*dJP*%>C(L6j}H@F3Kfmi zUSvDqBXuwmaK9zJ9$R8b0GQ{@GTk&?!Jexav%7fMvh-#nf99thE zb=ppjar|YMxYK#g1U7MPnQD*3X`gyFttGU{wbm~GEd8ry(?a^`XmE|YY+N#fd}wsD z5sobW`rX{nRB3YirT2~-Tg4*hI|!v{FeWr4U@_=oG(dinPZaM{6@In213$AqVpm}X zd+Fy85r}@(c4eXTB^aR*bf|=8(mtidFZJFMTJ7#J*`x%xJ*A7Sryai|t9u+1 z;eN^_%gvIGGAxLA2)`eo=;U7Uxv9}pj6|8o_$8t8d(8(n4uwyEX=X)5I$EgU{=&xV z%USSJWrnt$-Xs3ffAc8e_py$Dpf%AwW6ft86u6d5aGd4cScOuhv9n?pmNsE0s`fT2Y>7 zV**O#z#Cj8?CWA+2itqz3_~NlYdj|Dvm6y>P`{+u27fYWm@2Sd2oqzdcHDVz#Dz6B zDMwm_21a+6ft1>`%^GB*AYQV2`zzy@(pJNo0G9vtI|IJDL!zMdhqLVHBK50CTEAi4h7M>~*a+>B1qqCY(_tiGW~H;{dQV|6J5*T{eyfJ0 z;6?C9`gSd94DCnxu~F|=R&dK=b8S-9V6yLewU!D7N+V+rD@XP^C))Ohfa_VH|7@rK zzC62*g^3Gm^H5l)uUd+1|9&;;#om5bA|kzFo6f6E4RLxc)|IDi1j!2$=bq+%9QKVd zrs|wfZ_82MuOnn&VZEP}z^8ZutQx^|O~B?ZVE^ZAWI2?AZJI`e5*&a55)R15vewqx zhjL^?(@iFqg2=pHRIti`L(Lu~yB9?f+dZPYfs*5iH_mMFD#VQt%S^D+zOXJ96;IeR zLM08n9INMwpOKqhjz;(a<;zLo>g^g(87;W|#r}_>Vl5zbYGf(_&`bWgTjSqY#BfxH z3`Wfh5DeK^RXRY~FY=*?UgKb7YfuX+S69p()v&|cM6gYUu^uEjovm&mM9bUyj%LH^ zL=MB}#sn&Nkpa9oG3z%bR7*wy5_hZX>GUKk{SfF+hBEX24{7fZC<+&IhaTIuZQHhO z+qP}nwr$(Cb&qZI``hvB8+5ia+QY0Q3&7EgZy&&8>pc4r;%Ww6>0Z5RM>$;wkX(Z7 z?;E$~x1$T=uASbh$EG8KZ`_H|r3}RR#g3dG=mPayy_-;w5RBdIu`|7qY7u7enWx?R z4+L30Jd>ue!?fudHNlf$R}Oijzg}a{NqCudmdc>Mqc&3N*5UqiSxK2%ThUoGf8}at z_2{*zn{Nn75z?fgi2e5MYx3FSjI#EsPAIfU?Ken1hhB)7d0!7CxY<u}dQfow_hPJE&dI#@D$}Q=D?msK{bQ&mTmootk zW^VnuMjaO+u!8p!;4Pcwg2m2FqItXZvoW}#<=IEtv3m2mJkl;&A9DJ97_AXzjX-ev zrt>Kp!=fWCxinU$a9EAqh4emDMy!n&*E;bNF5n!vYCPFN(jw}P*E6gC^`hZBbqLP} z5*BOXw7Ymm2R`98%|d7fgwDvNu!a$0uDxSd5xxUy=}HslR9x@-IE;T~wQB;GaHrf> zJXi916dL6r--9sdZjkV;f(MYLzQ-hM0#=6X1U<)eITFAqBrrna3#U%~Y5g&9z8B`T zql_>VFh?W{)5&b`1%*XDnSf?Js<4NsH6Wp-B5w-}@t6tx*QORC3E_iUy`$x7Q-exq z9ARwSgPJa7CF%j83aSz1tw-w7V)srMGVL599Bvvav`R~r3z7>+%h7sSzk-TC7rHAF za5|T#1nJn2`D~M?Nm5{f;9-!2y9X8_-b;lmt!t*Q?BCK46rQwA={Snk#qbW~LM3Nb zgNSR0p1JcL;n#^&&*Gw;-0ybCmEqaz7FLFjS8BXMU<+8hcKXq48fEzc$ zCmG?#jq=Gv`LdvWQBb}*o_%8OkzC8)C5N7@2D)*F{N-VBg{gckLtCA;aG zo-=thY7KrA2}m#II=Dd4C`SPfm5xA3IzYdriM)3$NhqyMypSc_RN+RZKpqN3YGspo zOTLJAl$VxQFmaAVj9NRk#v?=K%(b$O;=TTpBq+rP=0Eif(EXf<`{KEK*zuJijjovo zEuMXah-VMIu;x+BtO)+3NFiFO8x889WNfy%ZF+X$ty?A&2+Rml{(Z7?O@HKev=0#U zvjWiX=SK0T{EM*aN>}+EfM!s6{WyPU(UvqFpXW1nKAOv*3&DlOuQynfeJ$;A@dV)w zMNom*v+?P4e{)|IFrT1-i=@$k!NkMNm+M4t3oMDPSx~EAKd=o6&&%mlSDaiCH!W(A z_!36qj-BGA{oooD$ARa(goJo>?gbhTU=9_+w#9}t-+oEHZfMNU?pZ&G3@ zFJ3_D*HeJ1Ub^PA%SSq&3XKn~=65EMjVmMTn6avCE@$M7bV|^s=8HTUcfmPH9;i&8 z7&6z*-wcH7I^#4&D}RXa@C7;9A zOmyj@OG<*`_K~`Xe*`4~+)?^ufX5qZeM-GQeL{}a5FBSR5`zL*<= zOuJS>1h5kpoxH}-cl&dBF}=Q5&EU8R4xH_DQfJWV+yY0-3#cm925e=S3$*QqtT0V;V%OrWum1WnsRr1-M+ z8GMf3{^SR=zUHxJz$Kl#bql@4a<_-lR}n3*U^__G?NBxpV|N4tmsueB^-DwpGSwxC z7z|~LKqt3VC7BGbzhqymae=dIb7oW28H!a~xm2mZ`-^FM-Gh+Uq9MbWveon8|p z&~j%M6P_s(Xo}x?>Jv*}5-9vvp@7!KPg#kvHp*Rvk8HaDuDrlUOi=L*k%B)qFSjwO zMc&Pa;oz*hwzCylcJwU@3&T(p4GYI$q;sj;6`yk~a;Ej&XxM@)Hq03=F!&O>4JQ^ zC39yOkbb-8K4der8_a#}&#~D2!B?7dTZ+Ic@sYVmJuoBa z?&RpXO0~LPo)_K@fGh}7U%=O{M9j2HClOV~#Inb@XRXW!W#z)jf1>Sr~P0!L*CJd(Zi7*i~oAy^OaRpX*%iF9?K_{2A+s zu%@zlS01ESIFTP0VK{RbP4{AA&P6n5$E}7!tAZK^epP-;wup{rK~?DB+IzYY{FM;hfNS%BuTo6f%FU=<`zB?Tur?eF_~ zQ2S+%`|$cU2Cin*K~pwCg4rr^I;*!vH7n&FXHY{8+=Tb^t(7FM?R$!x>kGfO1POp^ zZj;$PhFt8KAM>8)@xk-WI&fipyA+*fz@MtiPzbBh<@@HL(HoUn!<#VM2l;6saMaa> z?TkCvB7OC>zaJ}UyZz$mR^`DL%|yER+nG3ekCyi&?~L|G4xy;joI(!VF^je;4t6d* zMe?=%KY|xFZsh0H>$2D972B^CN0x%qJ&-)&{cI{`4%Uszm1DlB<@()NkKt&2Vw|)! zF&o1T7?j+CmWTXqIVCSRJ{i0}nMnF%@!Elv?}TGa#h?glM^UP2^-g>#$MNv*E5E0c z4gWVT60k9ds|_IY0;3{+P)qHcdp}dVG=QG<_HJw<1~TR4?fD`-*Nz&aH8K3fnwy@N zcs_sGw#d0Q%MLx^4j1y*`r#ewZ-tz)@gM%m7O5j&=k@YPupO2ZIm#w^%q)v+-|8Qd z<|)Hy@^uBN%7Xp8LpNd1%~39CjtSLIxO-ZYtdV>%p6 zH9WA~HQ)dMG->}IMpaW6eNoZ>J*wX5?#AJ?r}n`oxKqFzi9m_fTHugJB}5UDN2y~; z;(3^W3bI)=bZ_kD82yw)trkzZ>Jhqkq8yMb)P?jq81Gxp!)uDFHJXh%HAtXAlc>qB z6Grp!@SJn=o7i)=dJvl^)2^#_D#|A2RW+%Iecyv`A0|?)E0x#7-MLr6;@6IF$?Hef zTBQEDlC`oh@!n`Hhr;&p$oBKR^do4trDQVwb6$=55?wb1^rfUvPd}=vQ?XpC?`C6E zTGP$M&X*XBNL{G3N#*R>ot*KH$c5MK89;x|{g1jPtLQq5WMF4R0@XRa%`W(_M)RB)+sQQY9-AkTaKC7>k zB%_D6ki#DncV|kMuBsCD8ucc`$jgS&Yb2r@?h9_}x>-ypca0^G_Q2&el{N+SUsEf{lRrlK*xrEIU)cV4(u{mW-OiL!9DovXI`GA?^ zFS}1}{?aTJq|V}D0o;vB1y|%P?~{m9FA!t3@sYNM|UfgZem@ z0gYSMif{~E&NkIqh#|dBVnKNR;SG~nC--bet2QN*h3gU(G;Xyc?SURI?ux3~syceO zFSb(oP`_ebep{AT?Wl~o=0-0Cu#m%Mf-SHTG=f5SwK5wmIcu|9eCMgE%4OSu*Yq2M zsu{4K(M`l|+^7<@$ho2Rd2LBkisto!jiCvdb4Zs;sA4L(*izpe--ah%40~@x0$tlc zPM<64;_PMN?4?u03RN>T;_7KcObiGkzmeF7P^6Oi9W*fOXj{M3KmiTPi+BSn0m%gZ z!z-S+&@BfnCOJLSO%~2JtG^dqXT4w5?&Xz(yK~cp?S^>sh|MXuNdaK@M9Oji^;spu zO5OX7o46%2RsF}!)Xk0gmW}1sJ<%1@s!2yB%#@+7t(kCA%{07gRuz_>;iWscWsxb7 zcV4p2?{1Y#Z-_vUwOywWs}<>uwWmBJ$JG;VXKJ|K$kgCnB4RuHbGO?>xNfC;x`HLr z!dxH-k`Rp6&JCKH&pMUKakd&{KfqKhYZWr`19v4!1pe2A=61yVm5OZ9DvJGc>s2YWxgopxm3gN=x+9RQdw?_r+^{r@RAp2%v?zl_(sy=m0!reoE zSRAz3otr-Vg{<+ulZ1hRAi&ka`whBq5DvLbjxn{LQcK011Q)7f!Icw3@J%GH-NRm1 z-g`KM_W@$zx^>Fc3*2Uz_narBkYZ=Y;9m zu~uZe%Eepi@62Fh8dFod7ST3u=$VS(B{E#KNY%LByOv#`zF6bl)Oopz+fZG+8=Vb> z-n;$Qfu~91kVbU{1c;fIyNyMCTcz zq{&zS4Txzd?qP(BO=!>vMJ>a>f6!|@ijQhihEf6UdWXx<5Z}%MJmVH%Iu6nVkS&GcO-99(1Fb`U6JP;IT};AJHU&@EPz~P;5g= zfcycxZ={s$tlNduF#`ccCw%6`llzL~%6|hI1KvZUMd#aMQ%Mk6R^;PW;SwYH+=3{R zdULM9Q>c;#ydo!#yR5BejuxN;3*;MWT+&Z+=7!z2#C1!!8if-HhmdZpep1f4a0%rY z*?6-wT$DNUE_7~K3yUsT>H&+@(=7E6Rp1S7;L>S9%}ub}$*^0cEp`hUz+{jQ+;tEY zUK;=GK!RrJKnbGd-0uNcMpV7Z2E0PLFbl%Ltnb~PeF5!!)DuK;?u=-&Xs3-B^q!$> zC^zzViG>+d$qTL|a-YX|F^pPwtt@9po!O9pC1NkjPJu7ys!C4;b1p~-xFV5#kq~^5 z$Uij&o|`!q%K;b59gFh8Mfl^9e~1V^MRP6;1)dq?o~HvY(v5qYRY)uGV#GCQM(c({ z8ZKu-l6IlVV(gexK}EZ&PtCALC@vp~>kEv0)(K5QDWrhlDs_(tM}^ z>D!Z@pUR-4n$+e0Ey=e=IJ+si-G?XC>Ixs+64V$*b0;_@cbm*|0Vgvz*GXNA_zyZPq z01Gb?B#i-3qL791o`$%Fa^k<63LAH2S$S1pp5pjRa5=wP9;CbLNhppVia35_$96563YV|0R$f}f#bT8Zb<}JfVA`s=mou9 z&>+yI^u?H}ER>D$0|1TmFj=Q0rq7X#YeL@R=g5<4IdzJ_DG0kGt1H-)$ilhI@|^)@ zh^5?sg&eD-G>9`?BYF3TYz&cn9Oh2($}(6suPL#hr1ugiPE^}MG_k`H*t_Hjr5I9u zGo`@7SOiKKGz0{Zh+PZ93G@K_=lc*v9j00U$*B^wjp&&zx z8jDs<**-DH;54?^5ZRz!vA)j&u*@FX;?_;#5xZk0(EVV?$QFl_EsE{`o}$f+3R9ELzHO4tQ5Ng`0{$c+=Ztfw&=s3rC3g3p5v64rrqz?63v|>kE5$OTbbPjOw7;ak^Gb z2$MH`&2A{cK4>Y&+KTg_sjmDGwwBil1Dj7wCU9Nxu%3Ao4z8*yM7QavWh!*m8e*Q= z!Arprv5lp+aOdRmhvEP%#>TkPZEDIfQT*GMWxxpuj%(PMhj7SmjM@##h!Zqs9PAlN zd9l?SWt1020@(jzf)?E51o2ia2!GPbV`P`0&K8^*3V!NY|>ogI{ziiszcVtw=8&kbu zJf%Yug)cy;1sRU)V%{y{$W6l;ZDP6!OQa||0O%wU#u3v0)mfq8T;OG%$(5lSp=+qY zjFvJjSYT{l&8|Vm+^8Ci5ksIxqXVeIuoB@!#GqzvXqq&E?aVEKQg@CHIP4q~LHGV^ zacgW=5AY|shLLep_?;`gX-jlC2aCaEy5z)=;XGd6?4XE+MvQMerV1$MqGRl>G6UEw z=S1W*s*76cRD5g24Z$zb&4^8e1Ft?u!1T_X4V=cJHh37N|lq*A&1S#=!dx9A`3h{CUI>FszqmnkP$|@ zfh606VyiefGcgeW@3g2Wg;JnSafpIY-cgT_Ku(OJae&8G9Mv|ld;}wv#}6FX8_q{n zc75wG(O_FGwtJIGRtc}Qe0(ykm8Q?r4r}6Mz75d`C^0{Gt6QU^LBc06UWLR!RwTp6 zABKn8hpHMaNGp&~Xeh3jEjmO&F>#JvPp?2DJT2<j~yB zk%5awU85qSg1xW>3!lO_2YFUuapJyNS?Y8_cF(-M?#>LnV3sN7W&+c|;J>`+>D%pCglLh8r6Khg z8z-iGsz!tOi-aU;K0Rjx3J9!79XiZ&jMlM4?H#-HC}}LTC)qU7ZeIZk2p0fjf=d4G zyu4m;9aP|V7aV8+40SUGbtr3K~$fq3|O5R19akWYv0hrhSN){j|FzSh(Vh)%HY!< z$qewB6};FXTC6>I?AJSzk3!Pj39_4@#>OcjBGZlTb40(P~Fbjd_(Yff( zx7-+4tjWk^{Uj|$?)YW;{}{ek>hbqF6o+sOv zbvL~KyQ}3p3U-aN)kv+WY`@>IUo8*s=lMN6N00COHD~rElpo)es~zN3hxQHJ1AbS6 z`dvPG2qF|zR>@Y4vfVFR$J|5bsx7D$o`A*icFbW&ljV0p=P&ZD#;l&=;pk)YqFpPB zyP2z(`}+i1GQ(K3`a=!7q?h_a98nLMvyFs0!2+?5{BdaDP_*I=y!2hvoabf@JiwKa z(N0o^bBxb3u7^}o%hW2qa-xrQa2itx-2kcG4B`jlHR7>I_y36HLGzgjIx!rmRvC|D zX(`}y&Lm3RgVr-^I8c#qslzs)zRLh^Akm=CaO<2E>D6Ud*`}A30XbgDxOhMSs*U;M zfBYC~ZP4rcNRB&dL6!=W(g)B#cJR^>n zi(;2qms~0B(%$s2WXoaQ1c0_w(0p6u86N)SBnae&2~iEcPYT=OYzI?uGvdwWCYjPm z5*5cB2^~Sk@9F-mh~vEj<{G}`x)n8bPxfvBEvKFh1+U;%myGNxZM9bkLtvX}u%p^A zEzm@VEbz2C3lF35gngn~e5|4+)2N^eqV=Hsk*i1pXVcX{GV(kg3Z;{Ir$WM6DfA%n z{`pP|`8AwZ=&hk<#y9ayj%BZ9m1LzLqG3k6LR7voGGR1s}P1O>n^8G|55Ud06#0%IQ8vErx#z!=wHcf&?;RaikRIZh1>wW!H3Oo# zklO)dd2i}M0{)~l&xauH7BD%=bf_f}hsY@~Ll6j>3bhRV$1rc0o!8J*!}t3?wT&JE zH7R>Q8tOx!=HxQrz95t!jYFM*5~abngg#b5KjzK>+Fh+}qloZC)VALvg@C|Hc{||0 z0i**$VwIaZ>!rJv#Sk*qDLuF*Qgzr|aTmLJMZU^24x$Y#PF6H|(hbpR+aCzit{YBi z1=@Qe18vBx?YY*A>ID`kBtcf5i%45KVq96Ym~!47RnPU_=B`mwmiF%N@vo;>n!XCRpNv zV}ug@HswSpCwRZ1j=O;=(NWg-4tDDtb~Ji|;mH}Ph4;aYk|yypBUjiA?z}a&lRd)l z&MmNRKpOvr8H~m9UB>rqs@Xz3xFQjSR%!~?$JoH%l{T6DBS!H!AA&dxe2~WQyh$N& zLSrhJ)1rj~@4CN}t@#5$LjR%U44z>wZ-ICtviVEf_Xi(I5|608lH4>Q#xj9-#$R2j zC69N|wINKTu;MEDy#cy%hxo{x{+!w3JS`EFO_$(!PN~MJ9V+r@P)=EOsjzsoxfgw| znbE!!bcaJL_}TNjf#abX^XM$p(4`sNT3oq1`Ujj7JyTqcb@hX(vm3dXt0tq_3c7e9 z@)Q)9VuH4~(bakxr9z9;T{k%7qC}CEiyI%N9{x3yv3}LfZK|1YhTqZA+!I%2o;21e zBJ2WGS-c0i3NqV4b^&4NfU%eeo`sn~Vhr3e3ntAnc?t?GH%$WI8n8w_jVZo> zM^DQXLZcWjeUXH?R0_BOs@%K87I5TV}D#|Alkf*(qzvxKF}ixrgc#k=YP zigoQ+4fu2Y0{>#&XQ{41i(sDyGlu~dy1lEB(& zL^Lr@^hwEuR0qqA3&iS>TnzKtzcbsp#aGebBMOz{EppW-K`2K}? z!?C`2_-4!|$w7>qP#$~|ao()3{4huX4QCZD7+&llcdvy6iO(%0q>L#)MW8dG!(eBJ z9)p~O5mEh)?L&9vnHVhg>XWlA#^ay6KM{GtC|8S01~n4DM;|*XO|I{>G+~jWG@lUR z;1o3`*#|I$y9a3RsnJg0Tl5-*!jOlr?ujnD$r5*fL9`3(oiZp$vP)~Eq#uBia!@~? z(RrPb*A;>3z9K*YF4SUKKJbYudkwT~WRo85jZD3Dx zC}lJ{ypoFf`XC|JpCfNili5JUPcKO9Uz6&839crihr8>7b*Mxqwa&(->P>Q@PjJ*n z8fU;5hEoIgXx*!A1=wrMLy;lFV+YvMw@-IfTE(a$gB*-v@6gvcPg5ubtGg;FATVbP zv?>|hyC&v9?iNms)Y|K#K|qstR?JbBPRu+TX6u)V8R)PrA;4cL8}TK#f>GUhVU|y~&F`L}Yuhz9gIufHye3dGk_(0L(0J*On^f;Ox0|_Fc>wTkzPi+EXemXgk^akwHEL zoZupRfPZ6Iy3SIRm3C!ntwjWT6GDwcAAN8up3G=W2|4qdQ!^ODU$-XDHm#W(V}Bc} z?*v+<;6-hrwd_g60_w(Bcdt~B(@q5}8L)j$Kox8ne0kJ39JMdbJ~#`f{YHwY3CKW_vW}Hf zp?uc6naH?_Q*=yTF;SD2LCF*ub$}{3o=EW$=X}xLuZ^qMiGY>h&$Z1@&2egO>{;JX zWC9H494_`oAh46lCa$l^E*ke7hpy!aS$OZ^35@>lVF|nz`6AW%La-EwZQqp(ykzuk zm_~8IxYn97u=Zi-i zZe)`>M&aT^DJTRgg2O{}@zAgF2Bu;`2npnLH!@O#Pnlp_Tw;PfD*(pl6B-GrYXaog z=biHRUmblQJs!{dh--}h4^IbBu+9W)2We|8-@fn)=Wv_*>&x)jceV+CG6tXXGLV&+RN7_~h_EuiMcf{VDaUIE zR73hd5+u4{?uH{Kp4z8U_nh=&+4*%axO&HQs3fb=ISgEoUj7Fc?}I5OYMB0bpKB#5 zxO~N|yA4bCxJ&I(CimOVi+sZMc<(}|IuuScYMPGGA&?e_1NBNF554?pXzZbY>yj^1 zl(K%g#3(CL-0kEPynA$KuzE;*)KAxxSyWZ(=dDKNnej zJ;ciOYW?8P2Xg*TzWP8lQ&&x|J4W41MM;tG4Gc9?=Sx69Y#Lwko6HJ9&tj>xnD!px zh+8ak8D&3~p>%?+GpYD`5&(9wamadjH4m5eST7p>$*{g8c|UL1(@1$wBn7uAJ4N@v zPm~M}B)L}^d9IiFXjUS_PP-AaBZ}8M&(R>sMiV+hD7%3oMu{3&O5h)dFhq%sbcjD@ zbu5WAoY3-C2CfwdgHq?M%CKdco-1MbLYO+rQf&F5=-Do}@pcOK&;?3e52n7Q)ua~d zp8SQdWM%9A+K;%!`UWZN9XMEoJLh+qc1YuImidQQIb>_+VL%nm<(w=rJ#HOylDCMa zPwxobU+dE`Q+tiEy}?vMRWo(!<7xq~@B`FFh^{6M2%RjRJF6bRs4-DJ>~B$aI^~*y zx;?cH@1hS<-@lR&#?P9MXDUmMnYRb%e2|>9^*;3?_0T*TPMr)wJYZT(xS*}&%zHnM z9Jk`3%bi>lqfQ5Uea~J+F6qsNZ-+uIi#*!#4MQa~EBCB%iph?^;Tu1ifN+yS4ozYx zQEDvH>$y8j$41S^XAL%kWdq+AbsTQY?S+5|u$c@OB&sK3X1)&+0b$xN zd}zlqM+lcif_Da_G2^2C&jI?5wHom;pdLo<|AK#hP1~&$;GSI;{XD>Hx?Lmeg?%u+ zNer<|ksYA&W<%S>WN{e@yBZ8!a?{5rlaEh+ zI6i)L`~Jr?k@D8$g^7*y{m^4UPqd!@ z>D;m|kh3vt<~Ls;8;sGU{(yn)#Zx1GWs5_l7Q?$tkaPQ4$9)$Xz*YO^q2t~c#rzO0 zHtDEvDVv-T#bjrX`9YhQtrdHVXV$h`oTH`cAQ~-O#^)OD`vISAvHuZdzSZ{Mm{C8V zw?p~q8VHx$yE+;^yK}uaq`BwHI1EyUocIUDlO_ALPDVS?u=qPca!y<3&i6uB!b=%- zV?&wnpu5K4IDAXKPxm_2ndj2I!GgK&ovr;m#1D6u=6ouxUbh^m?PCA}kR-Q3F8S+V zPjSw33;z$CRIUyx$Zv`wku>c+WK@LAYr$Kqjvu{?J2QTF(K6%revAUZaTYpkVngRV zvE!qpfAMrUrMHXm^(1M%QLbM+T=|OqHbyRJZv*>>NNOj=Pb0if_T}grM*Ih36X7iW z_26rhj%~h=)n>8yqak-bulTrNhLem%9L6`k4mqR&X-l`hrHvblzIFNeE9%D+YIM20 z@SRj7aQV(IDFFT*nff0mcp%buYno!Iltkp}fOTiJ3)!F)(2Eh`D1|pE{g1w`FyE76 z*yeVnm^#y=WH>fvP}rGTbZ!y$=ozq9hU?h8DJIsS;h&slHL)*hKJw4Cms80(GKiY}*(?=H%LxDu5# zbjmuMRw#rlpNgUzuqjc=5c~X}hw#7P|0BT&fW|NgCHgP4-sS(sYhnBUuvq>-DLM3( z#`bpfCjUj`*jc(*{`ZtOHnp*Lp|f(fx2x5#wcln#_}u~efe#53f;^a#%PPs{ud@WS zpJ1!m4j_a8(&CxcAyp!-*G#JLeqz`B)izrUdpxdf$+pDE4tVAf3lB$6Pi|8S z8|1fOSoNAwGp=eDQ4xHn1J@KmD2DvuO22bSgmz^iJ?~&W;Q8J ztynA+El@IaN#crvgDXBBq(-s$#~g4!k#}yh9^&l_p8qF;MAJtXz)%eXR@?ACP7)Q9 zPp%~+j7rfY+t5h{klgN7SWDGh5o33LrSZZ3RS~`d#cV+7A zMDu&kR3?Fl%1pQ>b`ch1Mk1fTO_??!Tk|BY3H?^l-5`~Y12YegY*jN~WjmIJEk+%z zW5YGnAn{L%yU3?R=Q@Q&RZk}#iW2F*pvmUa-jAt99GWgAJU~?&jOnw(cFaY%L$hXN zf&i*^t;xh%)3Z0%(ohOqC22a%fqFwN#WmCpmCO%Zp2$*M7iZjtn(;wxg!(epyl8w# z9ZL=2r+n!YMpv8Wj-<*NfBDN-UIQjuC}nUCh`!l38RL5fTeYvp%f0jahN`%0F{3Vm z4>qEr%>0?~2_J4VuP90-Do{!938@P%8P+CT258Y#HjA8)3(BF#`okihshwOI4F^uL z_oCXWwpz-*5{z%?Ry890u>eR$L8@3|FKOig#c;WB%>bL?1Z!K2+(rB!L#8kLsGYsA z5b9QeT5Oq;GZ*5gY&>LQ0^@Dq0rq9M+X81M%83bW<9ZxNY(O7}#IN^UK`u>OK8@gy zY&@3(dtCNLbc_WR==Eu%z5B~i=GGIl1(yXVq-61+pN{GByYWMoAJh$yN_6U(0V2FI z$tK^;XCnJuA~-o?da&trlg_4Gzu;48d%arDeRzln?6p{X>cz3p#o;R7b6ty=$MWt~FQ$e43Bky)5 z{j|94C^BvRdzEz0M_Lu zg!1zthJQmVty}P}LBcBRXFF`Us@M%6*w@ZM4#W@NSzJVYZm3nRQ15%zihZ8QWreQ& zshj_E8yKPX->3xLh@*D`Odp)`i*H88PD=$Np{??R?loW^KV0cmm{B3MEKZ@|r`unu z%Gx1SA`%<_50>%My1WpkD96zFN54zT=yyQ!qTW$+)Dkvl0^fB*VvER#6}l&+{I@_X z@KinO;Hvf?7CX-Kvc;7-aW;O!%j$C$zpP*Ay}TI27u#XVVM}Jyq6vni4iSyhCA!r31Xv+Xb;)jE=t$$Z_>*-Sj~n9wDGTAsiAk zI1@fheHdk_s8)0P2KP)7xqpJPZdWoLS1;3Z9*f1%&tqJ7cQuDnnI3O^lN?;GDd0JD zrdH`e2W@}DBZ1)rKijY<_`q~c%eCt9xl2X!+jdI(L`%Q!J#l}Q#}R2(vFsK!+a2Pf zJ!|aU?}@wiR>K95H>`X;o)6zo{QuKJmUBn6_CWyvf)W33E#&`4#b@TEFZO>_e5IPx zPTL%4yYuP>J&x|Gc&q>1)r-qbrsc?O$LY2wjo7F%KuAYO1_45BOj+}prakfh~~|i)M@j5R_apEPCMsR3zOJdd-8XqRf|=3 zAKkZTOC7G0ej6)I?nabmMXOzKSruEYQYk*N9b)$s%(d-(?e!hWWkM0>Y^b%&&DGj! ztIpH(p@^$q($^%W%fge36gGusNOv^Y7*mIzJdn_}v^kNR!RAe;%bNr;!g}jBOEvkk zUeY}y*NADYV!)l1BV-QqacH0G3;E;DNJh0Fcpb9SehmQ!PfxRsjprnV&0 zqPO@qJqqu%V__&v*B+0Re2c`ys?#(t@uQnGs}PhZGj#crIC)l=dNv%>uo>@kXG5pa zFqEesUyPN9q9N_6Ok$K0R6(~FmOmA@b^)T5SS>xubv@dL z%tDm(v5(54km=WR(GyKI{CHT41nE8xk^xy5Uuwwvv98gV}cVKBS{a`0VvOhPWtd@fZ0}^`H{X<=&`@?AF>|@{*GF$ zlisfzOyTpS+{iZ84bA1R2+>9@+S`XQK#Y@uJ6W2|I>}dv|MGO{=!?Y!2txv{+mG5r z=JE;oFA&R06X7OXR;W};1?Xtj<0oGGs1(L(7F;I~6|2zHJRqRqWgc)|Wx^u9P3c2- zFT*v9f9^@4n1rL>Bwy7k_=Ty(tEI?l@0eQ}V~S{!gh=8kw|Nc~RzulT3(^y?!-tfS zw5QfQN2uXnZp3x82_72op$P%I`d-nem}k7D`+WNhAHAMKkq7~P#;P+rnOQ#eZ#}9@ zJC2b}$^f++Uive6MFz2NuxcQM2=11G1N_Hm7KJnzG2ZOOyYXIMKxW;Z0ANO0UN*MQ z0Xp`VM1i3qMW70+%>Af_y_UCVQb{_X&yWpYQ`L*yjDd)Mc?L`g9aA7mDGwr?ui^}Olj?SRYvxR z=3aC@wV&hOC+3)bV;;=L zoCmpMI*`g~o@?vEI^U8$kR}jS@x10Xk)VS1Io8Bg3q^V$0%x)Z}x(d(&0 z;K?=}E(4zEw_jy4ScO@&>O`mFyNZK^xH7p{077`K)}$6)^#lQ4%#h>Jiruu^^qu~9 zjpgY_A7Ux;}Y-{cu*Nq4qUom(TbZBc)U=2PJLnLJHHPFk*5(#m%tPOM1jwp7o~oj{5pmcXaMW zYK*G`#hjiYt$6NOQF4PEn_2Y%fUOh&#bXaFl3Zf@f&;=}5F7zBhG6lk8zXo816?82&4BjqI-D zFynUEa6Ev}VjYyA9D3GZ<4Ees38}7o>|>1vk%!m%K$5OonYQ`Q14he_IvpAFTAq>s zrIvpY_%?)z4;dlC&4X@Jmc1atMWUZ8VL+Z%&b(K%V9v+fcZlUG@@2sn&0ZhA)($`1yT%)!n(+iHOO_zdrfG(8&yEBj1H-1e$*>&ZYfjjJzAE zK%J-CXgoRx(o|lEIJ!Ve5ZYxY=fqZlmph0YB3G~KCTzjdsc6(aVzVMmjy29gKBvmD zDd2U_lhk@%l7#TXL~f*HX0N&aNbQMuGs?F+-`8B*7`w2}FxI6cIWmgRC?_Nszh=L# z*G@#tI~m$v_Hrc+it{ENBl?WqMafAvo|swv81Rhq++NB*okK8=v=ilVwuz_ z{eqvKbX7qL@B>CAda;24VGfx~)glpiS;a7+AX+!z(ut7S<$Y=OQLX)!j5+eCTcYsZ!z0sJ=c&5RD}pv*L#ma|VCerC9O6U&fL-zqJ+|Zr*z^vpQ1e z*6%T8A{H7d1e}*k(%KQee5a2n;MSm|VectMN%-se)1JS3)6QF>PY0y8rIFdri0~Xt zm5NgNp)<{>%bDY1MjBbRbAxywJr3Z+s9Y`|3GF|g@uX(C;$L4g8v7|Y-Ok~rSQMiM6KG| z_S+Ioe*5}`$>lSi9Kj~$_JdCNuK>ZoG;YiTzW{-06xk4@R+3b4Z;~lK{UeS!9B$Vm z=^TwV@uu?EBXRbCuk{NgrRCqD%Br$byC&1GoC83}+=lKirCpcR^;O=V)Sv#mimcN! zXEREI?NL*!>+HXKNA;iGuvV1im{IE6PnUN+pM~n&PnX>~;e4!b5|Cr_JzFSmto4{# z|4FJwOuQ|VzkcuOr-u6-{?wj6YSPwmOJ81w@^!xWcR)+Up;oD~ zP^qoCtCSm?+s-(=D)-g4qVazckJr42cX(cQ%&HsD+4Y~Muo+~vr>i!bN&^#)R`oq! zaFq;mXII?hgC^UN5|M0%7i)sDmQyS&TkG|HcB=bFNQd>U^i3Xzq>4e0mMmg>^kl{9 zFF02hXOW((`{2~~oo7WAj1*~yqttspQ`G&Xsr^Ww8wMF*T1zq+63_brHS6ZklDg=! zJY@|(pD(dn0wE7;Y{sijHmLp=W$zT8S=cR$esMasZQHhO+qUhbJL%ZAZQHi(q+|2s zUw3D(XaDCp7xS&_Ip2#hW{s*Eoo_^|$sDki$Xt&VLyHu(?-jpmvboROIw5p$w{X+LeM&e(cf z!T3DWvk9bpk)7goI*eB=?arQ=%eweCR|n;#B;g;ZzBVvdHNZyl5u3kxZ!)gaP3mO~ zudUJ4dFRd1%XnVdSQUxW5@9?K=+Y^M-iMoNZKjB&VJm)17|lN`bJ>62fp1xt@$HW zdp+k&`?zF;e~iRt$_oa`b4%?Vrk1(pDN^SG^UI~AMy~uH*Q)w`jTxRF_(nz58<>@e z$5zgVP&Q1)C&KIfC0`@>QdNlbJsxgg2d%ifAN6s9&01l!^)4(YN?smdN*+kP{<~dh@!Lh=?ura$DbVOe2|4sQd!?ZgG|8= zkgCh@gq&c+RnY}}d|_6afnCYys6f(9KHF#?Akg-9k2ik)zH0{`79Fmko=V{4OOGoy zm=q{}j@g8IB)@b!_T$fUvejVzj$Qq3B4dC=>I1t!A#Zg&Z0Eirm5<}HUxTA7@Q!;C z@pnP~37#o+bMdCq-=>qkL(cP2+kj^}@mN7LANJt*~+r6#u~Zaj7yfDNf6<8fwl0omHxsqy+)o^_R|o{#OJ< zyVEW`{{CeXxUI=zMVB#un(Q`d??>8GZRE0o>$lZYpZr|Vtw7JgnGBAuhK*-0E1}ND zTBZ|wlr}Ey{T+tTIKgy~xK?NG=I1SzBN|dYSinBvk1dc3h>@e;vt4^y!B%^QvT)P( zJoHW0y>SW$Nv6gPv0#Wh4n@2cNiYCK6?8fod$uyKm3sh#1H~!M?B*^&d_m8k_t`M! zx8gs*FVvGh9$xAraFt%k-LEi9%GwC0`#FBQ z1A0Y^@B;Xup{tLi+q|=pxKP1hlKB55*BET+C@2w~MrVbBpDK9)Ds>BKDk?Sa({2RTv1oT%bc0f8*+Gk+X2cSLKly@PePl0%sSI zvZrz=W22_y9yux(=>pnK`lk8{W46P%D}cWnCc?N9U0IqesQ+NkI-KwVE7J6auB1jG z%(K}?HQxeWgd1!~Bgt1LHCf(mz~+wA`PvIm6@NU83#~0@0RxeP6l;$;#hM|vas`F? zT*!R53AfCjIarEVsm*RwttlWe@v4E)3dLz5ONr*sn5mL2GuihSs#W5%3Ui6O*0{A@ zpJYqx_Lf?dR&ak$;-}8}sjL>UaBxUJFu4gh8lIL*rc8|6jFO@~?rtK&Tm2RU=vsoq zBVxV!TQtvOk=h~R&q^t==+^?-sO;kY$!(%2hUpoWIE7{!5*1UZM5lrz0OXX*m~XxP1jkhn(E6=40J7TG=bR4^KJU8U z<%SgdEkq=RNkn3@R|R=mpXvMdcDL3dMAJsVKgoGCg}q|RxIi{R3seA>9-fAtomo3f zJ}y9VR|yG+;;|l?tYcyRvvU5kJ@wl~;%Utf2unSLZ$y2Ok-la802}Gs#t+buzIFTn zAL-ls4-k^Rg>)=O1ImX_hJ;nok#M3z|nrt)HGxq)#6z1;cp$#lo$@ z7W{}#=yq`KJ(Wg%-F`X&>K6}^D0W-mXF|YsY+->zGZi>6;(8t1c2il8ByqVtzk7r7a-X*&9<(pJ|8cNB*vOeuOc2-@C$7(f%p(cwh5&>5oc%w zOaC98Myx!8rhg&bX~}&W1a(BOXDuOBDqh2fJ700k-NANShX%Ep+T#uRpw+XC$5 z%SJ?an z%^dk^)B;O3hOvOOiv0>co^jbmK2$q!5elED!I=VS0V>>XRyDX$IkA?4C8Kg1Shu?I z4g2DhITFyAUvw?l?g_m$GF8k>N98_CX6tt7^J>>%`~!s}m0#IcGYqUT>%f`Cy?%9E zO{W&*h$jv%3++7e#z$$Z{;&wQmk+(*fnmt%(L}>W{7*uU)%{(!;Kk#jWzoxP^1Vz@ zaBOqhu4E6A*uJ$RcF%NMq{mDYQc^`+<~Uz79r?5rn!yRn0nH|3i&-9~WKL%SU!YJ;@kOVHi! z$ybA8=c`FdzNPC**n%i+u>=hESX-+nNA>IhiHVCKMz3Oc;!AQ=wXL=CWpa7A0K1)t zP%3vV#=LNTDc=|z;FJJcw@j!O;S|MyUzhy(j7)E7M(>Rpww#iWcw!@x>NgT^DJlfS zUn$F~I$XvXgGj;4KAp&L`#7N=ZkdVKf5wyR13{xROe9qL;jk8E!FOAaOhhP649auw^3Cg z1l-bs&60n4O1G>!E8C&iQr9FAZo~;mdb`H~Xncc2M4(UyA}X?0^qqpxo3IWjJtKBX zCzcBrwe#QDX_3yd3AGDFs*&Z0)V4s>iJx4i0B$R$g~2X*K#V66ZAv=)5e1a}I*PPM z36G#b7sC6a;di5}y1$NZ5C1?k^j+G#?9;GPA1U5Z`NL<#*wq*>3}0MKJZ4mK^8&~z z`ZSm7cR4U|Vb$3`(t`0m5?oE1cm7eXcj>YiW}y69lg^-MhA?+V@L~i=TM@gk3$gmS zu?IOIqQ4g~%SORijH)&y66%`!${=ilWp44?2^AtOluBqOr>oPhaXd2DhdWapXFt#0 z+2YapaO0QIhgZfzR{$JL@mggmu0LkWb{+k}XK%j`FN(*t){E1X4L&AT+cTKqkD?$?+dR66bd-M?( z#@_=c`@K#z=%SVF)9}mUKBX+novfoKMEm#G7sdM7x*~(3D2s-d+@wXgkvxKEn4?G`B*L3ugA4dd~lSP0pB)ve}O>$Ab%7>w6bLc&``7X*lGu!h@Qr2OtRR7 zCt#f3{D^2rmjZMCmBi6dzdA!ob#m3-aS=mo`~sD&h?}|+?9yD_az@tRE_V|!k4%8g zDbp6$i(gQmFZam>t4E8V-e@L+o`}^OSvOTxd)i=d6Qoky*};3d{fVnP%{W**01Jb0&_8Kt@1d@X-E3KcCo1IV54wDvaSVP zTB8BK;wDb;Y$~}$7&i3}Mo5(f%qad18ui

bD8&+lD+zFFVwua$VAwtGIA_(v05z zkKmGCJwu}JBO7eSN=&*eA-B+9Yy09ezH}3=#8o3Mr{6NcH!of)BwX@Ao*B`41Vdmu zo&D!+g{#xrb*Fta_`Pk6vE;pwW> zW!+8%Nq$SPLlo3Fn{0M`(G%0;NzdNVT?LD7w~?mwEckL=%DoS8e~o%v3&GH_i^6h0 zo>xO(yXgxU2?Fqm;wcB|MZLSR_ZG)3l)}m9C#=NE!;Bl^DR`ucXW8KxE4#pxCdn2P zQm?-ybB2bSM8K}-MD&0Dkt2{zRJ?oSLCqX+%;C19QK zd1Y&-mtl3G`=v~a!nmZ=1Jqcr9BJXJ0r^+|r+51>cdqAwM_u9;zc95@bkQnlfAS8R zqop$#w2K2}hg;iS4L)O>r(u?oN~f%5q#gwnhSFmxG7tY5JgB!8hk%Y0lh4s+&%6A% zhL8Pq_&DO#osTsfyRTmIar?|JF?)~{H@t-T?Z#KWM_DN_vH_*^g`sXk^V}%sj%=1S z`OR<(O-~=hy63j&(!Q3h5XELo5Y#@D?Z||!gK}-O`p+y;XZYECY#sO79MXoFW&(kl zBX%Iw<1zR6HY(3Xkjj{o3l)otZB|Cddnjhn=HI2~)ynb_XZQTo@ZK3kgc!M)eMSXq zdku!EOj*+>;S`wPZ5(Bt)DQg zn{S3j`R>o(zo4(*2XwPfc%FHleWp(~-`k#(>hjQNmsF_$fT|d_eo(;ZD~bUn<@9^e z`MQ6YboP3(JRqRy+d7uS5Q7__A_mXG@+VrCaXXc~8bclr7Zw(8W&|Sz0zM1qCQFK4 zG$ZZj(r_n{79WY~BE2w>$)xa*A1!E%I|C4|Nxiltwl5{gOeRcaWu2a`DkbVyHEdvz zl|sm(tbp4GGmx>9u`!ptnXYp#_?8`R-XZF|bUce(=)0@{Q3ZvbCA86rL-QzQ&bryq z7gpDq`bf&KdHc_x4~eRBo$}K!1iK6pii$5-aOWKuXgDRj1#JzweFcj3lWzISU0y$qm2;wLomTw7Iho9G#G`A24X>{}kJ75!k z)%E`NH3%IaaFC^&xF6%d`586Ksf163dhv3^DqKk++LcR@h=JazA1<1DTl@+3j-pz( ze1gAPC}eVa{L~E+i#p?i_isDRp1-oQ=iAH%c2doyD=o-ns?RX4l}BN}463)&eHKAc zr1P9gEfDxZaI&pi^vX&&>+ykLy(nI;3CpBPHt&h&+pr+*v)Inb$sg}np;kwX za8@Y70a1J(HCh}}19_7BzofSfY}}P_NjYebIAkW%PMVj)Vwl^%=(LS)B<~gE683x1 z+8h9b7QBT!WI4$&SJ({v8$#QPOiNQ;2o3bC7Cpc!!OKq$bA?Jf1(1MAD5S5FF?nNc z)Gh^w7TuRs9$!<(t58-?mui+?*7&c9+tn*E%Tg|${Sk6GLhjp~@=PXsS)kuJ+)U_Xx0AR>UV_!D-e?KsZKDU; zr~F;l#4RMz*RuG16U{iNi&*mfchMr{z}%yVkW}OOIB5Fhuh{_1fO{Bz+D%m?O3}E5 z{*m-)nv+va$T)e_4WxTGeGz>Vtt5RN{q2>OVi9+#moE>CZa~IE`&m8h0{sMyGDlB} z67!5KV;bcoTL%rcyL=Z-$8aI=YyC~s72T#JF zX(~?y)|K{xmaHBr@yqP27(=M5X#So}S*3y+O9s64koTugbDTvp9rG{FvFK-N{8K)I zN!k#r5a85(@3MH81km`^(7~ywsQcgMzsshcC*LRcqikeACazPZGw9HC-(IT+J2|#I z1`@YWbPE+;>M?X97?oc!Ogx{W`s-zTrX&uCnJyas83~iaHxX+m)j-y8+e!{DAgs9s z&hV3gWdB;~;XkPSt42jPp1cyfoFt~2c1hY^DuBM@ja%%At)~@;PI3(ltSqtV)z zO<$l-e&(~&^`d*n{Tt~Yl1b#U*um7@RM5kR*p$~q0z#@*O7*Uz4Zef^fM!8tFZ@ll_$M2VR!lBJM?wae_A)eFDp3$DuxwE-6 zY5~Gt>Rj_$yV@ipBZU-yVtqks>15Rn38?#e^;;D$Yqq3 zujiG@Z7%dXP8G#_iZ8sL6FkuO-pi`)m0#+IGivZ-f*{{DSjxi zEdzB!*sh8!panmLAS*<-u723E@Q<}i=gJQ?6I|i_wekCpUlIB`d2%I9^7uCA!d7eH zMc1_{?=^d8PPSIkdb=ivZk?<1Mc?v-e%g*Hlf8+C6hEfT#d4}J9ekOBIhkbZfpqX6 zmOnzXOVmF5G5fcr^|$g(o_s?PPa8Dj{z>@ebX4?I<5N;oTI+r(150izPnb=HOg00z zSbaVuz^mGnAd&d?_V!p5VZ~mxl46|rJwfir_BUdeK#q4rI1M)GZMcmgyYBR`Gk8|vUd?j zB7Vk!DvgD4KB1-6Kf|HA)QtVaP4+Z=EXYH)*>HHJHl)_tpALTin2$q@3~KDNM9u zmkR5O_CF}no3xHq2-Xw-cJo|TKgZFNy!1fPrJha#{pVQYrR+7Qlvpmt>%Vk~=c5Cu z73n6{#`5j4MEzY&BK$IP{9L|$#_nXfkya=hrWW?v!s?0WMWHD7dndZc?k*`xZ>FRS zEsYLJe6xr`^#ej>`r9M)M4&DmohS>qW&hiY_wk)jGULix7HXOq418b*|tsbFe zP<;bmys&|qxhsmwJkw0l3@SU|`%c%)Kl04>>xTMPT2azFYaw8wc4GZna}I`jwPXKq zXRKDdF+o}1;?}*#=IVPX6HWdLD5n~}Vy<+;R_$YbS7&zNTUc=DvH-L1a`p0f`9`Mc z^JT9fkJjxwtcS^8tfUGHZaUFBy?Bc77`%Y4V49qZTor=qs3vL!ZYRq_BL&mT!`3Yh zHX%#!)qwTDm0z4QJZbVL?mvXR(Li@ocJRR#UvWL7@wjGz3;l%$aVBLMj&2XW)xut$ z_xCM*R(Om9|AB~eR7Y9KW$~sYt1M@oQ|+7CgRZBAjqmccigkJhovhg0UE5W*=1g!| z(`+2*!^*%8|Ybs?)NOGlQsdp@2mq=P(zmaoT$qs95wMNArqr_Uk&V(!Fu zp)V)_v^fM6iF56}OIh4g6-w(dH$~wdy@ZcVpu%!Ie|{4VOBQ zu=nndPgnuNklRXPqMNjil!t5%Yv-i^Qm6+Ri^OJ{zHWt32tm=xcRfCYY-)y&j7GWKbvx=djy; z&?$&?y(2Z^75CMYI*qRy+jOCX zG-HM@_4Lc*XU5L)$B$)VW`5oID zQ$8DOxXhfO{7LTQi_{L`GkHSVX6iNxH2+&%CMUl$H=b}fcjVN*x7S_Rb<8Ytf_|}l zj*!7FzQZ3*WbjcpJKo@c>`+I={IejWJG}MSTb4#+u)O6z+mr@)wOq2Dk3qaAe}&{) zWa-Gx$8*tJKbKp3yO6HASjPgw48{O%BiINB+rH0})-Icv=46~Os=X+o>>64^S6z?o z)K&?H);I28W+T>}SkeHdwi)(}7k0KW!?hrZTQFMTZ1oO#w^rDmSkYvupj40gXPCVb zSX?SJp!Oc>2R-(-D;+~IYc$H&rD?Y;Ht2CS12`wHa+z|bG|+I3J28A#l}HLvEqObB z4z8qw7Wb#1v-%>ziZt+6xCkYznrTNh>^zt&+ZezAFat;A)Uk#Pkqt6>bw(R;^>qfl!*f2^ zz;C)xWE;`HQ}is*cY3%&Nf1xh4UVmK(`S}uyQZNu|-yjNpdjb!h(v* zj=w{lO8wjybeZcm>+e7+eH4t7Z&ok~on&sDasp+Jd8Q*d<`W+L_HUgIuiWfsziyqo zLVbW6TKpI)d-N7-lkUTVRMr4s5TVsjLQ?n0wpZ480$e2opt9cguU0@; zqtN8hyE?LVgL|BHLhvvcu9E!8F>tRA_M+KH#0r^pZ(#7<)9={vGk~p>sh^Ry}Z2hCFXGmK<)&S!*0f5iT^f! z#HkmAHtxi|f{R>D6Sf;J@7M1%iPfIA$`@`scI^tIk>y+X8G^Mcu1HRc5)u>D^wc9kNn4&e=b+J>Jq&o*Rd$n9D2 z`5f{LV8ftJmFX6=YPls&Y z3x1;p>igCW3N({E@xMeN)qeUOV)uW%wd52seG2P@I{Dye64s;!H3VhX9P6j3A(kJV zh88ox*iWxK6@dTFn8-amwH(S@KUJV7@>T)apm-VDGH!RQ;&Zk;Gxmdki)2wMsW)$4-;y1H0?dLFCZD6o5{sIoc{O_C+<|gdd}O%_s6}`cT#sBj&B@up=f9lst56$eV#}k;2g2BI_Gg!+~v|44K#l2 z5GEn<#36;c3?*R#9@TKDSg-6*5`6*X4+Daxy<`mDE3vc^ZLm@ z=Gz31J}53vg6c-n1J^bq*XB~0{fxu{MZ<67{cVmG<#7-bgmZW-Mt$Gs5Ha}90LMw=+|G| zsU1zSoGfj=3~3KuMzH=o1@Ox6EIehxBN3#@LeC|M*%AR`v z*fI7xziJNwH#yKEkbo4xEV#fUFaQS7`RdR5nd3FWMOP6UI6^Cq43Ugf@%^Rc$^wgc zbnce-4e}o~-6~81}bbSlkC?F#K>h|?}hL_O$wf*riw4uKDX*j@5}{EHCe+-J>7fg3~`iU(N( z6BU$|O+cNfuF8ZaO)44~b#Bm>jqPivP#2djP(x~^uwI0ki?uZV7N)BCZDK7;ref(8 zXuKq~avYih|J(^??#Em#M$_0sk|lE;2%>QV(OjpCWu&eLS2O7Z zDI+4Lk-vzAe~>Sj6CYGhaV@9z`fc z-c-+NP4|6DMAk~=H3_bbU4YGk636FfbJ8SWXBNpFqt{8=L#)z{K;z+sqk`_M@UOXk zHK-IO%4vr*i1ds4U+P_)OP%sl+1>PGX+%EKwMnw<b=xg zF|(ra9&7TqVkf6D^M(xX zR#HpbVF6T)g!-)M%2Q{9b2HvDAt9l^;6vP6@zw>8KsD>*n+mnK^I3r3Y=~cn&bjYg(-G&E{;ICHMRn)iq&JC{$KGU^| zZlw&jEX6dXe(E(BWP zl|EXV_Q@Xsy}m^>Y#?x8LrATsxm=mcn7yxL?={dkFhcFseEpjvKu2#!PoEptqOpdf zN6eN#uNF37@fN=;d>`S!xj=^oZ>4sL}3iWs=UG3*b zUmeqZQM8E@v%RP>zPy7G8MmH#@Z8s)42&J#Na%8C)Sdw+sm_a^1SP zUVoH*X`SF}9Z{**UW;WvA#ZeZH+%m_L?wOL%7@=Rb*ev`(CYIq{mth$z6EB&wt_~f zuPrxTGPE(((c)POkv$4@aeTcAYWsJCV%ndU$Q3VAoGb50o^tVCxWU4L>yH)} zSRM5}Op{>fVM=gK`|zARx8Y>qEs$9-T@1aT*?#@gjf7OW^vhl z2Iy%ne_VAuZ+o5CXBezd89h|m_{W8jdfO;Lcd^m(H6SBl zDB`4dhx(ku@1M@&fBt!*$%d*yk!G`Vh{^ufuZqvT>W773!jjjg~xWsn)VX*SpH^<35F8s^3(FGxivH0il-;rVc`P8&fOx3>@_pz2Hl3W<6y%o1L@Z2 zC9S&iTAWR%##4P>(-ooOa+K^M^bBm`Y7OrBJ$dbN>jH;Kr9!e-(Z&q-%FAYJ8QMf< zgQb0zu(Ev<7Ul(?xR1gX{H#ADVA4(MeOXZ2c6L|?as!sXo)8o%!JWw>mg;yDBkk(= z>u69>)W($CG+Xi&legY)@vH|8rlu2R2(u~0s%i))PMq`d3}%Vy4=Q^~QlDV9)Fda5k8nLno}F>J zd%Yzzs~eqUy1R3jkIqR;0KpzgF$_S*!!0C9Zc|!wU6R{FDb{<>Rd%D-Arg<7MhahN zE)=c%xvb7zFe2?Ph>v#Ro{KexoKC29@iDci6%o0^MoG*Npq64P@kJRAXt<-p;E+9f z)IK4d!JS4{8y{G(1eeY(v`1^ZpNFj#W_dVc{L>=-tTdKF4D3KqHr>_Ttn?m$nQSAFE@UcEaiXPq|s^JT4Bp!(!kz*#AVWk;em~m&5Cok)Gf1=XO-Jcv-_-cw;s*8ltkM0&BpS9j{eE zl~`pycNz1`;P}qvBRU){LA`bci))0 zE+!DSP9h8L6qB)~5C=1sCAQ{fCmA*ue zv$G8R%1hec@c!UueF#&4BZBIR8+C2=C^H1WO+dk1EFRgg&lW*4P=>Wt& zv9)4&G19nVYW>iR$I~zM<39N3cc|Ezz$<(nlrT>X2oDap>`*qLWS1?b#^~OVX8wm~ z-g3@o6AC((C>N*b(ZjhJ0arC`M`_=P)a5Ec8UYCWEHml{bFvXY0QvJlWOZ`?Rl|Qp z5Qw9qP9R5L@o7{qm4c)2yIYtlE7NI3osP(mcn}=YgnZJ%6|G zB+fLQg@eHc3g!mMjDjh_5_ThS-`nmj7V7dMq~6;(1({{A*?rz6(Vcq&YaVZMr!RJz zD8A73GLR4*YhF&ok2}6O!TBNNn~~dzcwE5lx-qqpNrFS)t7S%`E4gO27cvbU*5b?cs~)h`R{!@UDu*bPqX>jL4ps_KM)5S9Z~I`oLjV`s-= zVd)`c`$FQSr``sxJ&-L$v%4W1`~r>p77k&f(%CbMst8tq1h_QH`;8URS`B3<;QGlrLuGLqbqF8VcLF zUgQx`aT9n8#W|c^K&8HDs6ISsJ~*f!J~S_$DmTCDcF`64=tqL|#lU*7p#4x$KfGvO zTvcu|>UP-``|L-8cD#b9!JNja-ILgz$>XmPC-5fn$Noj87j z?IV_i?eea%+;kF2^J(IqusZKy=Bn9vbBK>^0Pi;`I^C1;se(wSXEft6nl<;9FFd!( zAo4T;(==t*ab4wEeN9hy8L*hPx+GGpe>dEI%A%;fLb;1JPE>5~88Mj{7D*+qt1|%v z<%XMaABR_e_fHr{AI;~X@$e=5jbF;J3|jeN=o0h=aZ{=-KKH^Mw%AIzXRdq9L+I8@ zCE}qx74|w)I0EV&Ol^s^@`AnX?UFxX??qVWfk>>SZ1b6vjTje?T+-Z16cRG$^=O7c zoE2QvhJ;Qu?|_T4%&xwlK3iFG_t*0`^X}SzCxLf(o#I!++`&&J@!x=J;Q-|*4j&+L zOwwN`FJ>cm<)Obcn&^|s8Z{~EBlGT{`gFwD>g*uv@;Og&LJ}o>u`-pv4OkQ=*5L3f zlBVnA!!cY@(FXC}r%B0$-l{@WsXU~QcU0q~SMJh)gP{_!QJ~a}PjyHQy)miYC#K`J zqLwG4NK+9EiXB7xyI-DOoyy~bbT8P1o;Yx?>*PtD*98XwZqY^7MO1+?ZBL~_f}HMq z4oa~#R$p&w4h5=ocG25uPQ^+5$8wqwb+9IG;m zJN#U%$Z)Yrse(@4ZEiCHs$TnLjQ-WjagmZkmX1q=y9hlS4qJqCmDG)Ltz&QO^_rN; z&mxN_oy1ZRs3U!#)-Om6o6~K!HUL~fR3TLNX*3t1_XimK;9Q}O7wNa4&pRKm1#`HR zVbp;pBq)#U98W=Dk-l|R zw?*uQLE)&Fks>89*O^QY3<3egYxxmM{aqVko}bK;CIM17nKvO5aeIcd(J{NkTG;`` zGCp#tF`9WY)D2ea=egPr2I3nrgO5*TEj;doc~jOHb`~iENaM9hvvJ`4*C-F}P6s@$ zhf`IB^0>?(HSUM&rJPRSF12)xB3S*=s|xga*XiID`_GAWzrn6r-s!O5UfpWzH_x1# z4UG|FbBI?lm}ry>&>94R1Bh;<#9*&%b)W(>bx8-WR z!%2$@THSZfmeJjs*kDU99{uC6E7p)g!;%9+J}VNWy?TK=7>r_5<$-`m&Y3P6O;k4x zMU(=`o!A5eNV)=nD@=On(k^51>&_&vtUK-#>+=-r1R+``39SPKqT^eJ!)*^gNBbBIeVA`H0a% zu@#AvpTL;E(!gq`1)oh3*Q2=Tm+B$!pB*`VBJntODFUgiS_8=zoj=i&ViG9sHqcV0 zr~2RzB#@6c;Pj;L*Blzkvy=tUe~>h9+iUv-Lyv+sh`cNnv3w;Fic-Wnf>?g zOW--rEw86z(TJHu;IDYm#&f%k;)>F5=IsPhDmx+ZaKe-~(3Li0YuaI`qqVL!MefG> zoAM~~#nRac@h$bW0ii09?CP1d>Fit<=KO{8k%0%AFvA@?y>v4+v+AExA|nHzoAV-F zu_0BxX=#C#ISrULT0^vh)fQD$PZu-ZZMh+dcUxR{oNPt{v6t-3@41zk*9emtfXU}i z)Rb3j8hDtl|FiQXt4VMbGI!vj$)}}GWj`AObb7`^0KV6v8d5s5E zTZ*O5F`Uoxfe;A^40r*D@bkP2RXH*+N=?biCJ-s)+!?m`n!lKd%yLKOnR#Eu!nkeN z!?Ks8VlYL(%Xca*8$Q2e{=J@|;wA=#94;I1svStarS=rc8~TKtGc52-E*RFEbi#L3 zA5C!`DoREjQD9cktW-bh*SySM{U#;urtOYcoYM zrH^KH+;aHs4Ir{#B!@U6;6~Wk`gVHmG~J7BY%rV$$C$xPRADs2QrL3V$lhWh@shfM z!$)F^1}@_#q7f5J;?$>+s8t!fSexd831*1baQtcw(^7+N4R%0@R-6Q@6LZE2MO`bxE1xSxnRacj^~mpIMSEhFjk7w8McXv z4obmucD&hZYK3WjHiHw7;@|I2P*g&X1uZ1j`AQV#-D3Y;rMT6*ZY5!x7FNn?Auw{8 zwd59Kw;AaShn;P(yu0v$WNOC88BOWFh2OWs-&0KYn_lvkj~n-XPu8Vo!gNUIrPFjJO(RyWNOo=cL0>JbGlQ_svRC3v^`{dzDk3KnSBbQ*);TI)0i*i@L()yV!tFe13;xQR81lNcj?eey zS&2X3KQ)8iX(?m=hp>tGuc=ZT|CgHKV(Q`I>hz2y%HXWn>1HT+3G@SteXypGq zK!Eg23;+O1-cndtLBYb_#opP%-hn_;SeU@U$==M;#uNbXSkF>6S5ZDg<9*(K5R#4v zNR+l$LWLwy68as05=TZw_zOWQf-r9lRk06IR1_3@G&ceyCMMtysv-?c6x1rjAz^+@ za6v@W`1_uBf%S6d^YPSI(+b~7<$YGe3`8#^OtJ*CB5MFlnGhc0Zt%$9@ZKSvKp+%} z0{{WC!GzHHlNbo_;>W{7P1Fm~4FK|3fQAJ0%4YO3;Dmp}p9`hw00o2q^}57yNJ9po z00g{Zgo*(IVn6{|sbtE4Tu^|)gt5^9K!FxuK<N%IB*XeSb)0_Da52#`%9 zL;x1tfXW%QC{ch00|3QLdXN*aN(*3+R5z0V)V2V6rxBp*0gx~N2E~X_N&u)gz+jY^ z*aHxf_LKX5r_OUrU5#+^BP#butLJGW;S>$jhNN|bP*!R1`n|P$|t=7wa|mkb$$MARu3=G1js#GSHE}o&$kiHi)~w5J32gEl^PV%HXK*? z{W9;@?^XY_dG+J@cz)dN-X{rU(hU>`ecA1we2^)^nTh`uVzhbuSNx*|`uhWSfoM?D zs7-?kn{ofX=KmDWB?SbSNya+@0D2-MbSmQw{3DP6fJkm2RjnZQ zLmviBFE~yg*k&K}hXGrN5XoS_5P}etNdS(M0cB;75JlKjEiRP-{h|OaORu6uSb_r_ zUB7B89IpfXn;~R&A4O;2FHpfzNMu98^#~xNC=KEmNc6PO7s5UXP^8}^1Y;2>ibT?J ztP+e$Q7Qzg61aD~PQaYuI%4f{+@k=dppURlamK{JdPUwvm?q)2Qg*Bmv3%%R6Bowx zzi7D`vrdgzynop8PG&1C;Mf2136C)Jo?<{S585!$4G##_anSrqFrKI*s)VT+#;R4T z1nG!;G@hw*2So}L?fu0D>MlfJh$kqaA)_I;Dp5*+L&Ac%{)_z=NQh!TIZ;BXbR$_i z;_D!W5ffv$h6D}qGSXjUdIawX;X!s1q)1^V^0ruD$+|+7d8B!v{;zL>dC>(a^)J!+}HQL+nGsJ8h^eBLT<47v+5lrEx1M%p-&&mLqV}R3<^y zf^?;=(mWMJ*1uXpRe8-yHHzV-$SkhuoKwMQlF~(0`AG{{7U&kwmNlm??TA}RcycMT z>hlw4;-@L6AP?>^uwkgdBN65lm>C!l80MJn7&WOf#h45K4{6^RBU-QqIks)vwr$(C zZQHhOd+yk{W81bpdtct}@BQ&QIq7^kos)FZ$*JnDu8PJSQ(<6dyv#VwgwM2B)u3vl z@JoqF1S`Dy!P5f>wQ0ol=Rf)Km7Y6H{eYKCFaXN~>0_%2l{j##T13 zGOw^#;V<#i{Eh_E9FiH57cNmOXw*OaGfDt$jM?l#Lud_K9p)OyI!xC1ciqR0 zsypKww>z4*sC^hg{q|eg-u6RC!%_yBw+9km@TCIcfQB$JlC zkiE%LlI<*`EaR5pmKpmy{kQ1vN+xSIFXJlHY4&OMYW8lsftH6BOvbo2Iq$&NS4J;}aZzOmoD;IQHAaMie4xPHzpPAFVzTsv7aIXC>iBTs4P^yV6~ z2(xR=oAozrH^n?5n)=i1{q5uJQ}RRhdHSKd!v4g+Ccj?4^8n=m zq=4qYk%5AN+CZOgUOt3@jS6qG4iOqy^Ni`N?(|HEf{G)Vcn$yb~xf+r-(m0%SRCR22Hod!F*N@=`xd+gP-sl zg)@Usq2*|mbVxK@X#z44avUjlf(TRZ?}Y-e-jp=G%d*fQ~Q^)Ln}B_=ouRT0W2x0zp< zpP0E#)tH7h{fyW}x6|XLf=^gCC)9vy(n7Tfm7S?*QLIvdH<_ENoAv#Toa9Wa&ZGW& zJ>5LHnZTZNoBw-_G>EjH)K(fMtxk)pane&`#o5H;=(!1Xhzd#_rUq8S(-GB1WxFh2 zeXX8e=hs8#C2Jk1H!vAA&c2*@<#CK1Za>+Vxs}pVSv}loGHbSAc7C!$o2LzzR+WB|4rd3uzR?1^tJZS;{35zZ zpZ=F(vpcv=xU;yAr{j-l`NYg$Zhn;#l_!-C6}Fp&?N-CpH@o>8Z0|oWELY2$+J9cZ z`6hZdRRL9Hm(7+ckIr8qcVF>fxi;KlyleKs7xCS2&2j0igt8v8 z#IlvMKDCXsyX2?&=2tFuyuQRY@!@k=cr-nw9#tkRH_n3=lg%GyV{%h-ef{X(w+uFm z+PqJVXLhaN?QgpfT=o}4f1^*i|8URfJao7`G;JOut9Php)pP0FUbtNF{3I{Rk9FsC zXVrD;Sa;rd^|X4My`E#|vCnKj^?2T+{jMzMaq@2WJbKx`j=VnaqHX&*k$=xjb+5aV z-_-t*|D*pTa4onlydA#Gul=*NcDvybCXXVxC@bRh-`}3}IA_x?f(y44l2*ioWJBqYxJ`y`MWCboG^R64u6yBqWBxVLq~z~jt#a-0s`e);uz(@s=X9Rbbx zwjt?)t^)>G=JUFs9w-|7Un_%@*1}o>QYfOxQ9y}%@z_wY!5!7sRtp+0rwQuI8YioE zQ(EAFiV^~7VClal!+vHt0t5DQpCk5rr7IJM$^fRrxfxk1d`-B|$HS<>L)O?06DLeh z_0}-~*iCmR8eM1fZ`|TB5CW5rt=d9PP2SFz;Jwo&{QK6y0Z~#U zhTbpTmNj^Jz-R5PCKPStl%g!S!TuP^!ZrBj8_zXL#MCiSl~~6dgYbDel>$ofmVip^ zp34d0CP|u*^qRA2pl0!W#&|GVbaKQP0EMmUu(Q&v%|&g&p-eyp7NNg1AHa*wdcczh z5G|T`^oZ!gN1rR?(NjctSE7sc*M^>Wx&2JYx(Q^pY?=&e2kI4Cgm)dj?fUqbSOzQe zl8Iryjz-mL}r1^(M)A}%aVNa`tjb~CVUx_xiP>DPdT6|Q6-<`nc+)J zU(phn_9SKz?1ZI3;M>UUdj@U7JCU^@Jl z*AO46K$PARh@|HaBDE7G?VqEjZt1DX8qD7q-AmgJ zYTSV8VHbaMamW^-V6eze8LlyY07YaXLMUtIvTZ4x|2d#}!{yZTYlkPt@1=Ba0F+2- zZc9bCZQ69(@RQqsZa1Kf$Zf@1C1Q{1c~e%A>Cd$7_n(eSX_&EWR`jobHq&PGLh?Hn z6Y_*?J6=@Td$@E6F6DR)gpH_Fd=gX1%^*3YZxm8K8s6SV>w~0hSMevBi8uA z6_ZUg0NHd%r|b zt$#L5AY*Zb?#7Xvra;nm?4&JLlEoV&yRMm7{D~82^DVyylYot~mfzCaMF~`!3wZpA zZd)7FCIjrBDi1y}8BA!Rfa`V@d<8D>l1K(`j672S@l}^i3r_6_;C0;nj1h|k z$zBJ$+852`8pag|B|YesgRB;-pOhs?b~2q3x|J3?r%AP*&|(_`{s)>Kq&l{{u=JC` z2?U<$N85E$D1ci28^jTrk1P6Lpe|sYUkQlQQulwV zP%IgGAY8PB%THqAA00tMfw*sLWJo? zB3Axm2qDqyskUzTC?1Sq$h)XtLzm)OE6zXJF&m>kCf0jXLV+NL-Y|n^`Mq=7$`<9*Nz6p_L5Vu-3WR$KjsgVXAx`?}1G0PD9xY z?farLMe#2Ofph*xgi|nWWEs)!rbb@KL zX6T$lP#g-+X(UXc$h*bYSgPxdCq%L7X**OP_4w5@YM5EI3IvT5;u4Pe zHDH*%xEa1;ZB_YlgT=)$iQ8+0?!jw8!)R|qai#$NfR4~$u3!>AYzK2HnFLC4a_@p= zf*wb-hy)PAabMi!Q(0x%F_b~;NywiCv<{~o^JyS@#7t4*CyGUK5{5(S7UQ9^ljkJs zg}rsD>9hwR8IV6u2*D)9)Sa~(bgK<#DI0jDO~fv3uArV;|b8c;~IpBQL-L$NYtTR=5;?kx_dKH=kj zqGO{bY&9Ih`#zF^NG`1`Nv7Ye(9>O?{yfK;MdNaHhxg>W-eEk0+qavDLQ;*@}Sx`VxhQ7}27H!-UJ25SoPKU38&^ z{sSIK5qO3iN_MHeFdO{SfDi1cju5iNT0LHv#ZW~!z6;&zDTEO#+#L&nVdI~fy3_P) zENEZHsKyc4t62c2YSk0$LOCAWC9Ngv(dR1`A4_|3ajJ6)M%>zW|7q#Yuio zG4n7Pd`Atjx92pUeCYK=0r&`k`OK&jfLI=CfKl7sH>CrxL3fsLHy9&F6&yvdGN*DM zEU(I*lD9A31WN>tgEFIl7a0qoovr4b5VX-W0uc7`OY^RhnwDroKR!_!@)3Q$o1>~O zw<+MXtQ4r6dMV{(=Ep%DfuQ||Y`Jvt6R&#v{U~2j8}pOa1UgmH6m+&v8J;2#KDc(^ zu}+9ja;)COGcl@}APcpqjL=d$@}n>?z=ek|5DZuP3&b?bocb-yV;dy#XY3$K(OrGa zThY4ZrrNNZzF|&PBrf|EQD_*<0SI|8saj}HlB@UO*;^2XEhQiJ^R><`K%>(vZwHj8 z4Cviz%iFe;1{#AsFq2hBe3Vaoa6oFU9@yRX+aT6IF$|He!d|_l66PmK?_>-_t>8k~ zEpFf><|rwIFev8s0&g}{XrC*0fPz9KMg9`7<=lb&x$W|ZHgdu?&k8qYJIu zTnT5=Bl~5Vpuheqy$tXL10#rb|GRo+w;Veb5<2#>%(dNccq$<}RTQHG^#!(hX3GS# z7roS82z>J9++<$-b$?gd=H*A?eCZb_7{m?^dSxKzBj*QBoS*oTrW^%oo<7!VpX0Lp z{A~cbz02syy*=e`r})bUU}Jb8?>BJ@NJA*XtnrJ5IHF_5ZfAwSJo+Hmh5E{^ybIqf%x%@IVZQz_8dNJGF@%9hHve8CjucP=AeHGCS1(1L_llwDpeCt=G`8 zOfA8n5dz3HwwI`Bw2tK^$t)D4pbY>8={gZ=MDfC`FL2Kic={?o$Lxo$jq3 zdn|i{6#UpCtee86C(;b}pd5T>2eINdv-gYAM9;+4Gnjzl*(TTEIv?Dol>AG7Y>s3N zq69x;6Fa*;$uwcQNzpKmgeHjj(}?2LGK2{z!!yBMzHe)HBuG{vwn8lBmrx7)l9!A|$2E zUd3c`6@p7n*M!LgQ@bRZ^+vQ8+)M5NU6p^>zhSOYeZzLhxkKHOYGUT9Y(-2}W)4yJ zqmo(X=xf0Qq8cGF|3%pmLc0VXsAvB9xFP%cpW^*I3NMAXz$x5J;dy4kp~wz}>$)Pc z$g^(_e3Fqh(7)9YwSzit>>XhgQ8o8fm;8t;&O#7iR&ZjCIkx;SLa~xuj*SIR;pZF> zK!6Brf^7FbLc%1aE!tPd=Pd7=;CIPN|I26 zm0hft4xS0MWs$8xTq?m6r=)KBwjOGPI}Rq)w(>K)iHf9Y(-U!bBcmu+dUcRgUc9cx>EJ>y; zoF#FC=9YncQtP@6H02y>4VHy|^%;7Px2kA^TTf1iQbfQ)h0Wf|lsJebVr*fEiopa# zceF)abkI?X1;tT=THztn;7Z(J?j~(`g^;(+&?XGJH?>OoZ|yOVBg1NXr{SH81G0+U z0IG5nRM$mDGsN;SDC^1&#qC_p$T}OeR3mmoawiwKZd;b+8De7U4$L3LZ98yfz%(uv zd4WJSl@6m+qUY?JFF&Q0Phys=2)J?CDrdD@EKAM_?=i=DM2E=s1gz&{9(Fem%=H9C zMiSwo7-Q`<_jNF+Zx}Y%U=0925C~7`*1I0R!0EF5C9KuesuM&3GGP;GaLRgAwFDGF za-66Q4`63w$h&g2GTzloY=UVDon`{R!c&F==lK#W<1G|rQqTHrIQ|IaK3E(2JgBs} zqxu6K{zI5u5M_8uyC|emCh+TRrYzJsE4K#tc&$JNkcNcQ^f}5dGPITPp#(;OR*QSk zsP(N_mTDb%n3%gPKVp6ID3GsD*r#R6onJTL{vAq$^SMf(Rzh;=QNcyP&?jZGMho+O zyN;WEAG*g6^#*JP`F-jY$yGdU_2VguD@9<=c0=_LJO*R4bq}Oa01hxrt)luhFpG8z zF?e20pzbsuzGFVYTS3WB0TuLX2H7bN5=mT8PRyd;eU^)PPF$DkEkBOv#%oxnRt;wj za^=8Mw-qb(a|8x8Lg%Uc`}V1?IdOTa3StzfXfxOoai*I~ame9<*dpbJVh`9bJV)Sn zTd*6RvXHr8W}>|)?z`Ewv+$AAcBj5i3t~|@c|Wv_Gn6L%fT;Zjk4ft1hc@5Z?js?*vGC#cCQv7dZljDy!mv@2c{GL`e}X zW=jfkO_~MtxX8)2sOm-ARz*Clo+hio3cJUfu@QD#h^yRvWRC+HEr6xc&o#fLTMkB^ zO^F@amK*_-bg#5byjZ?(W|Bz%z7Iktt933*>YnIzRh*iwTT6T+|9Hh?iqj&y&mr?6 z!10W{9oXIBulm)hO$$bBFkNl!$Jr~|B-o~aZ!L|_-jsgV5EK7Ja1nuar)yD+hMIv* zNAQ}8Y;0E~ldhCRR<=PEjcQ}1)I#WO#hAN{Ue%gkkTz}jsa>dCU7QmnBNbt(Y&mHD zP6IqeUf^B7SZhD^rfp?%6z;6AdArx>?DztwKq0bfv`9-#bo14oNGFh|)o(o0zsOAp zCh=!$_5Bt-q11LF?mGt4SO_PPn6{;>o2avXuxofzW;NL`dd>7B?l9PqtG*o5>%8ix zQxTk%K-YpvM(c@Wa<>W9DDcv#ZDnIQNL_tK7o z?;vBE3f|Ic839Zi7p0*f^pu3c(+06}MCd=~1_3%x))*F&H+}ZG9sJP)oE~91ZuKyR z?wyNnS2!Pr0Rd6BWoLRsK$$VDlJcP~B5z$HHJVM^IfD09fe$vCzgKUZQP6igu<{v{#Y^zgc#cQ1)z^bHojA?mQ^>B$ ze^*Q&sEineJUUdz#DS6;R@veCpYY=& zw;@%IF|cAq&k7tqoV>I@rhno__yI-ykdJ75)o18@GA)y{Yk`?J|7b;OwH|*89 zkQV!<=vHh5T-o?uGUeT0Ajeq!4}*&MmFrQsf3_JM1xyebdUE;G?)?|~e|8;}2y|JA z|6L3Hk^CQa9i5%@mH!*EkgB<9w<&?-n_qwSR~d){@`Mi=20Y?$+GaG8Hs;!3AH7gC ztpbhyucg~!n;!vvcKCPjeYj0t&F_Y?tdfAws@?85QyC9ed!~**l>W3yj;Og4Y4V<-5T|C;jJa6tt?>Ed;@KBVN4g|a zsmS`72)Wby*W{eRYLZz~BA4?VUf9jV5ogTX%ZQ_Z^Sxd@L!S6OAw zS{OseCo@uWlN5*2;bajNtgLJw$>Z@NB=ZK76Q;7igX}+$w3otcV&O8Bt*Xwb($y}S z#BfamkTm-MfeL{2s7+Bjt$jo4tb@5zNi1%hV|JZ8&z6AgBK}AVg$DKg&G5eia4Zng zwz1LL)OA$m)|=y}$hv3Y@WR%FS(8CU?i=IJJrX4uoG)DtLZuF%{0eX7_x*3Yxb_zx zvcHHG-Gw|WprC4bXPNVndb_7q%|Ck&p}mb*^Rtv~^V(J^<4&oNCAk-e^O?m6{amJM0r z^>~eFel{tuO+nm9Q21}asfTT(R(#~Z`*O^r^O&Yq)G<>+bh#2S(u!JEm2BCmS2Zl< zCcD#~byfZ2yMGcZ(nnL4*4Hpd9@3{ThgQ(9#STMPIhd)B;EJxDtDvO2l&cqKyB?!O zX=|oi1YBC;GurVaAJ6WfFisYN#N-0KV(IpTSI0?n0#hi@6Mo=o;Hj{MUL)GV;cF%@ zUDP~tbMGQ%;8?`w6GgyDT_B{|rg+K#W`hNA`s;xOd;pfr5XhKovmB92IbMK_7G(0m zF0GhgS4gYUn2#)7_HRLFRL-8sNfPKP=PJG50uHDti3^bx*}Wzbz%oq|n0R*$>=j^J zRgk?*%k0ZjU&e@2RADAyH=zEafsuL8_D@7MpQfg~K>1 zR8yU8p)jd+tPQbspRo6R0;H(!MVK1_fHt~U0GIW!3_6D7xqrzj8QJmR0N29exlUwwapBvpOL@V2-=iTF={z z(3E4CVIl>T*&iz&>mj|tztO-_9ViBGZk-BPoW&)I$LLTZ`pU7%%0gV#qy-*jxLyYUaEd8gj@4HNf zYG#KqPt$>@`_>GacfHA)eJbOIkJm|qNQ{5y&~vAc5Xo8WJxQqICX?KBdp7kNnN2lT z?#2^efpb!-pUK0W7CWgrcg(JS6b{3j^`BF!^g-$~b1y7$cQZxbiPC?*Ys5jUbe;Zw2lY#1!k21c;JC7w z#OXhZv5#M zPH#A;Jq!gYF_xNa4O9|&#Ok2y?9mK~O=5NmBWiU&L*v*_5QSa!<*=sF$qcgRio*(; zzU_~72+>qIbXq-Q=F}7>wg;qk?avxQt@mETR3bYnW2JJlL5vh1BNX6;QroeE1%}DR z&^77BgK$sX`UK z74)kh1o14v2JtAQD?_4%f_hYWE$S`{PClUVG7SSvAREFKpD(59$4bV5Z29D46)`1u zfaO?QCHQq>nk&eUi)LK=r(K$Zy6LOWseIT;X_p2c{~4D-9xvsRFS^v(7_bs~r0Y^J zE;|&hwm)s$@i@bVj5)x*Po^UXXihW^us1Kd?0Mm50PNq2)+F z0T99oEEBE<4qLwIPD>EZjf@|NoQoeNK)xb2Fm)|f_-*GIakN>V9!$T{&ejz`|0VNv zSwBR}SW?jZeT-ga(LFb@C+t?2ctJYY9Z_cr%``p-Z8Z+V*CX9+(dR1f5*yob-AxgL zo0`caSa{5qpIBLZ!$8CMZw5nV9C}DShw@cQIR*|R0WWX+yG_#$sBwt6_s+LhbDM8B zp6O4YqvhA`gS8)g=8-hh>8@>kZh>IhgvhfMA2}MkQ15US3PZh*=e<(bl=j)KWP`8Q z7PGV;4Z^4C=2fErJFUkP#nvpv%olVSOqgE!oCGcEWLlvGyAd)v_I`7pNi3VH`8=TkRyJQ+F4pXx!z zT7Ul~#GCopNe$&X26)ANbzISbF-!isO~y{B3F)wqz!}))B(r?)j&;?~3(MpH4+@9` z9|8yVe&GKHJ$6PFoL@rzvpvTCAJC(zv%cW}O|{k9blPG=^4+Z$_##oKOpbDv50#W` zI^bxeNj2rx{$vUzWMobd3<8XpKhA$Kq|V>N-&_Qc01}R4tMr|}Td-jJaQXnU&C%I% zG<<4W`m2@I#R1*7^-nU=dnik(;&|fU#7?c}N3jzTi^%4!2T97Mm_w~OMdt1NuI>1) z?KE3$MM<@eN)B6J@_vQ0x*jC9MQ8u+TWz|CYA)t5AVl*?DTbO8T0SpMQWJ;2N{N`e6Rq@)mO=IavLEq?(wYl5l}x&I**r` z!GWNXe(Nw{R^nJ4NyY-2l>K72O_psF>4_YZh zL#oSVy9|pAg{#rXSTkDo98PI@)avu%LI0=ZkmXv1(mGM1?MjrtatS|}>NJV0x^2tt zxncLI6x|2tKmAgq(q#BQ4oVm`4PK^Bn;@27P#dW1QS@Xm)I;nepkqm9`NjG(vHJ=z zZYfQ9`@}Dz)gg!uMg3&Ga86(FYNZA0Bc|3Sv}?)D5 zVGOe9n$cApir6%*Hg~pDTpEB<1sx5vZb7%>4bx*9Z$_o%4|SJSYi>zYam{N5fIIF6G!S zM~GJ*OwI7U$Rp5WvZx?*o;^t<9Y)$`TOi_)fGB(li38p&`TH5gAG?NFj{>922UC0{ zNn(h-ztApaQ(`Dh;Qe+t$}}T=Eb@UW8K&LRAWvQE98TZLzgfE1bxEvh8MrGd3lFJ5 z`T5jnc#Uu$>yQCK!Gi5Rq2dw5Iuf7^k8{XEM%P&YL4wd-QmiZH)Y?y;RNLoLyR_QZ zuapQ*q~klKaghE-4p|$JK`8dTf+ic)g8PTHal0o0$GGj$yf>ano-v&^D_#TRgi=BH zE1iUhjoxMI>_CWc^p*cSPx3e{&3~QI?!_^6unnkDDk$+x18}Pw%aBQb@KXQfLOzuv zlf~}gN3}zs8Cppad3B(IrTYv`+0Om+`xr>;2P%y1!@hIB%yTqG7gPKG?5cczy(`AjJk6K}Q#2iM zqy#_|`)oR@3ymDOT?=-jlvJXQWXDNqn`>ZIu;6Ze)P*jL00eZPWuDwGO zEB*&$JY!<_Q8SmFA1Y8T0y-8R%W;e+0Q=j^mYNJ0-@z``BO#4HM&)22kpnrLxQT!h zm<);AlLK6^H6zFZUK0ZI>DE%iNZ5wIT$f2!4A#@aPQ_SZ2G-f?<%D<08x8w>-j$NRm@QYjrK z%m>V$!ak<2kM5bi%}_nk_7D3yw*9@|S)pK$q6SGD->wq#zP&gA;y*WbA;4}CsqkU? ze#7El%BnbBZ|%z|h}=_&3KQW$!K)1MYE~pNi;31S*=QWk2`)cA1*pKwSUYVdnN>B0f;vQzxRWm!ks`L|arO=fvvoC6vp1e`$bUdz`R3y{S&>M7bM zV1f>JNRWu^9TS}U+Z7fu`(~!-tS@FJ-FY);QVdcp8*UdiX@z=&OS^jR)10oAZ586- zcWptHAN(n0B~aRVxd&fc#YwaNM>VCds>$Cgn6E=fSRmm>-!&Bc3BtnhMI6|Lk@__MuH;hO&BXRvHeb z68htTO<$7f*&haoR5kcBl9toe;+|? zTkVStOmSl|DODLqM-pppXFeJ-)Lcs2i52CIvgZ)CN=(jNvWUeeH%&c?AhqU6iIeN|5iW-*EgakEt;UQ1!TX8vhU_+F1;3(D zl-8Xv_SS&8oKW}zrugG4QVDZ>A%ZZtHxm8@R<@}Kpf$~20{uwQ595#-n#i_PR>m3I zqrObD`tYKBY>nqpNRwX?!$zdoR4#KEKSS+ZgMw{R#fLcQD~0_#K+pm5L+E}3o+X%M z?sQA%T@5=QIZK9K7*$9|Z|>vj(Iulh<}~+5fZfM9?c{fHC1sWw>kqiog5sXyxxzE2 zz4NRoBWN0J`I~K5kOz|OwAzki*2-CK$n~cKe zhzXEaIu62Hp=UiW>S(%(5pikz96c@PXqHl^H)9+(+9TG^Y!viIP>fc78ru3K9IShd z@~awv&2*qD^PcpO&@ucpTutTswo|k~c>VmAabVEvOnl0mC;!#4Awf02psplKK`^MC zV|rowWrQtGTh5+cUms+t4Zhu}UY{G5ix@$Enu_=k(!R@axv);2Cz}hKR6@)MQqf?0 zjfnBx1R-$YxxON+yR5JjRm2bqfwRq_$WCl+XA{xwn8gg6HvfmFwp!e0nD1A3{LXT@ z@&JW7sn*istzuM*SUn(iwCC;py8CrXmP{j;?3kZMi8_1q1XM|dOGvw#x2P?SoR?;W zh@#}te%SfO+JrUq25_Y&El0~rG$ zbe`JR)oz%9DkjC6ma#D(=ac6E7Z;IqaOUXvP)!P31HUNVq!Q5L0WN}CT96Y#r3JWT zrJ#qF%^~VCiR{~J_Fd-HF9ZmxxAZPDO1%&}LP3+W z89m}vIzjJ6`NU_&c)6K)k$CNQ*w0M)+7j=J+|=yY;@v*U*SOyoa-*B?^Ar7j21ioH zLk`NSp^LCM#qsxC|7Y^}Jt)vi-+u_({7c%t-amn{7y17{*esm%CH_m;T6MOawmMRK zcgy!aCgmoSVwok$l=o#~$0kz7+Dfo2by{~eE`-<%?O6Q#13*llp^vE0AHgoGc|=c$ zOnX-SP60>&lW67L*j3v~$l&1uoZ)8py{wndy$NIWY+YQ7Wis_H+L$vx+OOZlRIoMo zL`!e@TlTYC*N)CREn?Te zg{eHdyHMR*)l{?dF6BsCZK)GmJ`VMr5do0m5R>K^DqIWZQ_7ZBYO>T?+B8|4Y*kxr z8~Az7oig{-ThSwDpmoEQZQQijok-PM6ERZtOpIt@%LYtBdw(^Lp!=7hE)!40Y>pTT z8u5RrqI-DS%ATUs2u`UhT&nGs#9E}(VIgR^TGM5Rlay4eP+UL2`jT}r)I{j99hwkQ zmokpQ9V?zvLP}>yG(PU@tE6fY@%@!>6^Q|qRTr_k9j)IGS<=kYyO!{Ok?2tzv=t|x zV%ZLUgqzfArEH4Y)_w&^I?47eNNt-B)SJe~zQcnQ)S5@a zirqijmJOT;*=;|tjxGe!gpM)NRG3yxi<S!=&wR;sNxgS5BMjcT3p*EVP*%Pd?K=!sf61SHoq^} zL8*d6e=Zi26gP)zk_-z4hUNwe9NLR}YQ{=u8)M5~2HamD&fD0+xge=7Zea2371KyD z68T2>h{LlqgD?RZu5UQy@?-_`Xlaz3nRtOFBmuZ~j_H|a{K?bB;G1uUFLXdagsTTY zd(v932Jw_3jR}@uAJ2<>h=9_{5T-vbVeK!`T-I%kn^ODP_B2anbj@H=52CqSL6a06-U#@HAR=xEk zRx&3TmZ1I*fsp<__%Jm(cyymu1bxDp$WiS@fXvSLA5vAdYPF;JKOt^KJMjjlzVh(P z9DpxE=0lP?l-d+L6#A^W1%PO4J=Vajf>OlH39?^`WU&;i5^3{ss<2qRb%ny%%je|G zB&jH#Ui%Re&`q9=V_KTklg!H@_{pE}XyK7Gr9{b{@OU?oq>{wRtvmreYtvpDNe)vP zGrrR;i7ogd$`%?A5jq9I94JszmJ=rKg9#4SH3g)g52i|nJsgyw<8p8Ixi|$q+;iU~ ziJr>n9|a9q*)`Cv1;v706zJ=B-Hzh$E7EFT4J+E;_vAhSfWsG1x_N>lGVTw(a`{7C z0|Ew0($vn-;9WBHgq0ys8w(4&N0f-xja_ZQaZcK~`(Mqf**>P&6{r>*4yhIpP>VmJ zpp;t`ylx%gTM@AjL?VyNXio@{4YX_vNQgpH)yzy;H8?#Uh`d>Hw}Dm6dj|nbM z68#<_TX8~{8n_0$vN^poq8zsLiC!rjS}d3{3lJo)vK>24I;4(R0nvg5Ycgt#_0?LDf?`e5}F60Fs-9~j(Hy}n3)2$8jo zw?t=PG%#Eb#lFucj$&=p*&Ep0&%gbRxjR{8>rM!=g;-)YO6u>hfzUZ)@k-{gNu!>i z`d*462y>)hb+sK&CcZUzBL8?8vTZt_nvkc^jtmZ zzvZQFkbRLp^81VC8CjOy$kFj)^{g}3(v=b?HxF-c;mU)i*V z&OeaZEg43d(V`%^snZ8}{<9!Ty)CTB>R%HB2IED`)()u6!u7fHn=YObOk|~6FpU>W z#x3yRuY;dyyC4zq!KH3haJUypPqbHq2=|*0cOXihz&3=&SZ_c26|6KNO3GF|S4i6yv(20jCa+vWf~Aa+tm7m)6O+q=VeGp*(O5vA!DY7MD=Ino-e+RTl{#v!?{ zg2-g>NWLIgY)`tTrCtS9PjcPZhWZH`3G^xTHmJWG46TEn#PPANvUnam@-Q~_qLtD> zq-n_R*~OxyhIbISV;Lj(u?YpYNS#m9*x}g*%tGRn@n2}c;sjI!p9tU1D7o=4hFv#SPCrd`$fQgE<+Jb z?9Gh81M<@@Q(x1msfRXflf!r%pHcAGj{y`#g)Zy2M4{9wSNxL+k6zIZVdNh;f#I@v z(cJ0wVS{+Lj&rw8v{!!`(5DCT6cP~6N7C&Fh1xu6AuktMXYMHqbNZ+QC#GH9MW-fo0wTfM-pl|{n{ z$l()4m6rtoT~*k8qVB;kI%mcQtm1S?gClIONxK5cGeL?gnxrhaa5kori;0Da+|tju zsSW8~qj17dcG4VwB%=Wb?OT|Mgk}}a19#pB^$ZYS-y_7O#yLwtr!(}Nj_BSpP08}x zEmH@zL{uPtzo_tOIQ?UA?M;75%FV9Ww!zKnEtrWLwOUU1H_nL@Vb)obA7sUw=jtqknFIVZ=qrox zB8tcHv?ZC52OkNnv3#cw8yNx-at$Yu9}>?M0hGZB;ZDKCekH3(57BUN?#zSKh*9Oi zm^y-nLR-qI#mV z<6wY5+YseUQqriWl!Sp?Ye+Mi2C2tAhzYokfjNo*#EmXu2L)Nv|H-o4v}tfx{HPKk zlStzo3_tHBfABjJ``ij#-71=)?m;!!L5RoJZVgjxZJ{Dmo%%uP%Njvk>=OcBkr31b z4p{*R+6J~1Knr$-a)a_oQDQ~RECDp(*@|9zU0ph$O4ZP077_l*N&5WYX-r0dfs^d7 zi<4)M1y@#Vzhc*esl*KXkr zF{;e8m+|3XlETygGx_c0k%5TLsPbW>>KB_*16MhPh5|uTJLEDM!f)8nz*O}J1)LN} zSzl7|_f@`(r_5An{ss#W-1#dBssdANdc$Y_e&LRPf%rzG5ciR*CRMK=#5S{*j!+n> z5lZ?z#P&Bh(*TnqxDYBSjIV)gIc;18JD9oR0*#8)F)M>xtMOCgXvcC`4PV_1~MQaM?Bj}mw8W!C&1Jl5&H zaFQjLG74rl@o{8_2~ba|%5ton{y{ipVLT=32Jq&)mj-3L^}U;hpA_xqyv?xqvgOhD z>{`X^<}I?(Xhx=}zhHPU-FrDM@LN?(TOx_sl)xj5FRm{}1n% zxsGGw-ip6-t#z)o&bs!s@OY#KK#bo@&UT@I+*KSvB26K^c7+E#0Pg|P-ah#qg$)7v zB3|?%rBYp2>i+1ApdXdVt{QPz|I59l+t1L2&v>o{)`v-J7V_lKD+51R`jOX~cGlEZBzRsma@R2^a+tjestPh)4Fim&v`LZP|4Bbq2_K z&SDPY*`B5g9=-$J(p_D-!8TLlxaOIpNGm_kvjPSX% z0~F?4UEY~8T&+~rVL@<-oK%!1qmSNe5C)wl5Nz+Nl~Kn+RuB1{o?jZMce#sT!(W1i z%F2?G88Qr`m9SqoAtm>kzH)Za*F)w`tra7CaL43eV>pWsl~Iad@Ld=g06 zUpdjwPg!)RP8{9}a%9wz>XdWi{#y7H1@-REM>y(*U|+1UJ6EJ^wk;%C_}Vg)Y&x6R z2q7tae^~u)+HB>RzL=cV(sSJ02CFZq?v-c_>`r$-v=@?YFEIMDmC1vLM@=DF#8wWu))wkbr5pV%R9MR|m3O~6vxljUC-*wWjbagcVp&gANr9|B(KBy6hITz>} zSm=Poy;vC+C!vSP?P(F?ph7(dZJk!0kqO+~r&ht~bus+;t@eZJP( zt+&0re>0bMzfNFp*?|7-?4-r@4Y#GW2z@Uc*ot*T3CvYS%R2+-@VYbo7TXl>QYj0- zEsTmg@NE#0g-EyR_hT?ZBYV$H-sip*OPvpy*J#@Dv41NWJI&C}MV-&wJ-|k(CHxuK zX;(cH8)rv%j~ai!BmEKIvo}XT7wff0BA|5R{pR*Iz9b464DDfZy`UfS3A@4SzH-R8 z&L{>v{uFW=e6=sEQ~dDt{1+LT2?{o`5+yJvmLpY+=;dTeaK zi$4qoGi{<=dU!b9N9EWT*N0-P4h6q!xpEc{*6@1lzVvXt|CDKAZyDUDf_o?37fReM?a3RNKpgDkEXhGe>V ziwuSwg=RES;`zS(cNrLg%zkLi1f{$|zS;fN!liuGIbBE9l^%Kh&^j=ALgpw%FY!SG zWkR=3aAl!BNLal}z&XIHgFfL|MV-`i)?o2EPdQkg723j?S)pZsA-%)H6~Ef~g8UMv zR?~*yl-AeZN&TYa3?cYS(kLI3*FIC9MU8{a*Q9 zHxGGZh0bt4DJm%MDzjcsH}5fT5Deq3`jg-nUF%3yKzwzPdo&6)8$4ONr|;02$Vwwl za8$;qOB*h^=(?I0;yEl12CAvX<6>4h_P2L^Z@RJ#=`KcY*t{lZ1_o`rF^Hvuv`dCc zAk|;(mUN{i-mRRKT$jEVY42EJ?u)vkO|#{TFyO{&5K!E|HvXhF z$kL>1`mURWz=OuSN)m8anua8Zr9rxJt@z+7%@|&cPi6mevoxSc+vK1;QMoSUO?EIJ`N^q^T&ZJDV zy3>&*5~V(n`t!>wf*2(EME&U~)h};wUPEcp1gWm-(hzD{f#`o6b#>`UB|`jU)9qiD z9k|F++h0Yi<<4L{WEOt+7HZant>IMmq7zf#)XBP5W^3_Nsxy~Y=|`V3UtzwpFXdv+ z6C2?yuUeblXIy%SCWRvmdh~bcq^3CM6f_4gywvbqnb(Rq)~&;4>qGOUN_Ko*JO<~K z6rFfOPAs|0tY&H>3xWXJvi})c**@*g|Ma~P%4E5~Yj4fSv=P{xp@PIL60A?qwh&gw zj`5+LRW#wYghMG;WOaSjl0kVv>v;pmkb#3OkQFh9D&Vzq(y6g!Mh6w4n9{Ffoelgv zOFY3bj_N9o&Z}}pnc&3dz-GgBQ3&^%swi{r>cz2kt?|~zUQX9D*>e-P1emDCicb*W z^R)08dZsZ}f62#a_((S=(d!(?oUxkWb;1xcu>X8sX!YbHL1m9f)_1zMo;nk5#Tq_9z?!Ff#RA~W165ajLfoR98dT${pWkC;zO6HFdya%+hi zAE&xxRzvD~h#XQkH8`98bi z({KSgEGU^5GIO!eb+0V>GI>F?$LT9OLdwq#^mhCQU&8d42|l8?FneC|I=CYFLW8q= zoa0!KenQzi!4OBOa#fjS7*y%ywj4zlT7J&%zdY@knsPjWQY+a}{`11ZoY* zupo6(lt8v5>W`^qUdet=ukTQBD31v#lGo3~vT*wnA$8BgN|HJHqjN%gR$c}gia{iz zQ_rR9Wn5l;z3nQt?u_qlfQ}bt?Ro!1nX^fFYgn@QUZy1RVt+aaSEWJ}6V;kdI?qR1 ztozKA!1f?t@jYZ)`=yt>aPb=^1vLa&!m~XgL6oj+ugz&P`A6VnwqFE?2@}r?V{Efa zhly&8BZSqlO%LIc3dcm6(4TjGRU9EyK=hszTs@4ixuC0CnR}JOMt0neQgF%BF#deO!PdF<1b+(^KQ^5j52s|uU*8$>a~s`$Ad+Rq7nJhoFBk9n zGsjD~ZH6LMkJ!grWXCskRC7~&1=e+|ysBU(7QFOdZ1}P|hN^Ei-ae)Sb-fJ9*sgys zz`oq1Y>&Cuo0e~{f9qxUqHe&0l9$ark8fpKmluIt>vMilk}_uvIYnVEBDRu2GlQb# z$PHb_aWe6IqXqeLwi2p8e{pWkal&HlVzVdEJGtfVNEb)>r$2U>|XVjk3Li87h7YqUTtY1a;KE$8ILhGsc;Rc zOMj}H9#bJ+2%|L!>xHTmb<{yK17rb3ayg@qwYStg_E#Gk<$2O*e~=~`2;SmwpNkQBtU8lmlU-H2Y!i$>#60)}y#TZuwgY!WCN+M3{{&!JWP%D^tO2n z=5~=GurCU*`)EDoz1banmgZ1-N~@mvVW=2oz*5kjGd>WEBz02|Xiyw%I9(7r%sECT zIE@aZ?JnEmqc`AAgnd}^@f6T_)-8`Vayx6p1pF&jdaSh>D@APYt&Dv{(NN|o_dp^Z zYR1|mD--9QQuDGfi8=6BpFHDGTZ&gOPz){iQ`;#iOfJ#}=gg+$->pG;i*6@y!Qxz! zJl9Zh5-~?0Ef4q82lt2jN;Tiuooi=;WcdlxS^_@;XYj%$;DJpPlkEyIY74AXi09aG zQVX;E>-~MPe2ICo-`M=aAiPOPuclkHjpI9Lm7t&x2pQGB*O(Y{ru4oKCYOZJHD8^3 z!N5V>i!}!cX+HY&v4!0OaYU$eUd=d|WD4mCf>*8I+|Gi(OdLtwNpuhi-q;e1R~g$_ zMnm+0U3jk*uBcM5-0Tk2SBIM%tubJFVs+aVU{tnsVfrSBi}|a zBLb`r3dQUjB^)U~u>eZGg%p&ZkCvPT8WmyiK3aCY2&(QSQYaI6hQibfr$}@Cl!x(l z50n&Kj;lZ~2Tv9@C8WBlUf#9$FWYK%*jn~Dqz7AykK`|f z5It}yD2j9`_*(KeA65_f!#J4RQ+JcyI-y_Mn(9F04z(fja}@*^)X?q zm!gErbbj*AUF(Gf2?CCG@8VdRu79&5o)61Ggs9q$z?r9GTK%49{0s;P{XTqGCSf-R zMF1i^0gD*YvEyc+tx~h3J$#NRQ^5m1`-01~%g5}kq6rZs=tX4AcI2?_ z_Jil1u?leL6ehxp6|*$GYV;~~@Qe1*<^|RHxHH3xamwIG&xPZo6NQd6SYJPX$Q@{tzDxyzM8BY%8;92{wprck+l{iDHT_$XrRNAd+}XvB)~QaE(Y z$HbPrV@(Jb5P?3tH!xhi%~^wy5=>2{aB_ShX|GP!O8ZrzQP3oY?Syh?#Px;urof)# zRTn5OTY;Y0wgK+_!?Wk(si7QHb~X8enr?E;yJYm9@`6|SpkMYtNcq4)rhX}B!<{qc z)=l{UMy8%Kd*gvQ=2l1fKmza~XXD{*%&m>`0kuqht7wH0?q}TTOxEX-25-}{W-|9p zDPEE>p_n1TaypkQ>lrL`)xusLMJ`Cj=8nm+PQ3uuRjFGT(6@l?mr#`>q|DY+dO@lI zFGTn*K)8CQYEJ*KBU~4~S~2+6mh7{)$6`$b%`D_iRFKT72Z6j~CKzHKb+(J!1JUGK z<%&TjKW$X#*BL>Wx1`Tqzr?utIY&{a_QP3S@K=_Q5X&Y3yOXxzxm6fd)n<*0^Gv+Q z)uuETSwz6ZT=;;qec2s6!qgK7+&lKTBMB{PBpb+<)V%010H^`>a8cXe7C^CF?{QBa zBcrMG0ncQig8|XLc|g6EYFD|x@fsQE6PbpZJA^*J>k8I5F&()y_Hz`(=8+u>xEBi8 z1bj{SjK1&Ic$dI^LX5(Rw~Y$*v3jCS<=QL=R$WMtWNVp(PhQ?-w8;{pTj9Rsm> zFutDMOKVN27q0w{&4Rp>-L&{#9-lf5!5b=8$KgTK<) z9hc=uHc~vvi&~$ymyExbzWo&W;6M>G8F{1JYN{P^n$ zTW;x4&lkFzQN|)EP22rPe1kUo!ck(JV&95T;vKnV8)7kVW1Is8IGH&95kv@Gxur zdidm!OUHf#P+k&)Xf;Q+s0JohR#9w&$Y%_}lH-l5AuZ&jVApBQEZ1;w?9RjdE7Yu8 z?41%O1=6%YkRwu;d}D6H3B!~n`G8GOa}Z22zZthB1xf7s21ubcdML%5c6`gG2D%gZ zaxOCQaFQEXZ9#O-*VSEsqs?!*Bj%*wGyidt_;Fa2hdL%-V=s-YF?{iiS zgt@Je%H%^>^zg&L4Zk_wq8XuH`5dj+hBd89noAueKR zx+1(O5onHmN#6p&s&7YJR|U3}#PD=3AcSL$M2x=^S5U69yBx)(BF<9&OCiDiWSM;k&Wz7jUs$ib8IGD<$k>wl z1z8mCY`Xnap$aeElZ{iqY=KT(=Pe{P2`)$9)gYY~!G?bjH3)cSI%Hh!a~=I`w2atH zz7N|<-fM5E2uSiNd-SeTLj&^P>OfZVgCwV(AU~3uT$bd!(Nnq8sD}1;}X=Q4w;?={bH-nE^ zd_}SuF_lLS-L$P7KPK@MdXHa=U(JJye-6K=^yv#|%t0Y<3q?!`(VJd4=@Qa73(o{q zF*+stTFy?8hKZWlM~=TkKjh2T(25J%gdx47>&{@ZC2H^`sBS2DJ42W-cyS82Tw98& z$m8xbCc{=!Nia4{Ov;l$y}eRB-@cN}Hm+>;;nX-M_cM@3&7=OB8(CrNQMIM1C%6)a zJiCpAMCX3?ni+B^sYiT705&$VM-;n18%oMZ5$;;Xt?0p5o>pF8a&36?5GuO*YdE57 z7IY68-kZ}xcc?UqA-?TVZ2Y<+wXF%BBA{eJ)A^eONv2Lo4qhN^)XSjH3~KvSfl}&L zFBkczKQU_31S}Pvqrkkkz=wYk!k-LYFt{yBz4d8e4D<~79%)}9(QW=U0s8$-3M!Ga zD;Q|xBmJ;{@o~h-1<@nd0Xp8Z?Q6MD_6u$wt$;nOS7iCGxwWOjg_=J^y1N>Zd`f7I zA%7IHT{Y`6AyO@WeQ~UHtWlQKF8*42KsVbX&-g}#&F#GQ$TtrrtMJg$jb1EH(3UZJ z+j;s#6j}A03aJ=opA=PeZak}u;cbWudFUCFGO}t+sq_{&+nYdn5duV}DCn}*aR^LF zZFrco3s1hOf&<4;=;7jWp@j1t#IY(CX(`KB#-H}OD95AYs+JB6c2*k@96n_334Yxz zNfK&MS~m=qHBMxSZ06Bu~KlI=rE$^EMiPk&5}K)V<$ht#tco(33G z(f*4~V`L1d&;8PRr59Wn;?q%fc-60_a~C|FW#8mstGb6O# zBGyc-?(Lwi>q|P)Ks|+tA*SgPTBJBum!6eq6Uv4FRA>b!V5V0rp{>S`=E9O{7Lbko zpfMP6zFwOm@e_^t5gRb+Jd2;P!|IeO*Wm&O(_gaca9rJ;j=|BXh(E*8uX`Y=EgO*@ zF5y1HD6A^x+|%1sl#8)tMHnG>+qakXPF8n%U)sC1d~#eSheO^T%%KL(KWNh08pznv zVsyA$*Cy1RFx`U?4HUX*iO=46#6JSnGKI z#?=}{qqv)_Jdd9xx5(a5_Am; zM9t=apDp9;=cU45zIkX)s1qYNP2cQ_8libFUBeS$1By3j5hc$Zk912-=EMwJN|3D% zVQzXsblw9*RkX)?ZVbs2zmUD?xO)JDTdE}&pk^!&EmBNqXhSsD4`h1iA)YatONW#q zMM3Hc1ZL9E?YFcijhg+Yyaf14pUi%7F=q~odO9TWp7Yxt5SDCZSp}f{$|Io4%HKb> z7a#EaUM(9NJzE=UM=d>T3rj6qYds5dY8@?0K>d|(KWV>JTWNOMP?%Jkys&tV#=|3x zPLLBRiH^pa!yVzr9f_E&wG|yv`i!qZrGb|8zqy5yCxnfG)B+YH# zW~#cZ(!R^Y?uDx=nJN&_Q4FG9H4xC517ury#ly(_dFUe)vv`mn_OtitmrFo|R`8M_ zK&3rw;OplmDuN2V;Wc66P{Od_-XDUqh8tm~fR-!bb6$NOTO^L-DpnuJ_vwU}!>sNr zN2}7!)XY9E#tdQR8(0achty3}3*T6$DFCzSpw-sa9Mery4ac+EY@ZL&(D6Fy!1q63 zY&zZ3SAlEH%D-XhZ~houJZEJ|e37Ng|4a;bCQBQwp?8-Xr1>6W{_Xg)x*>5OIQtT$ zH9-Od@Va9Jlug$;2y-y5*AtF2TzSd@#Mok}iAP*S!>G>zPaJLNX_amFiv%85r+xF{ zebrm=*qDLBSL>R<`kk@JDs3j_Z6U)R4(RXo7P6hZfwK4n-bjkSZR66$qJo?WdZxGL z9BKXj88(-3);KxvkPV2d@C{=SmmK~mi-3;;h$biS6@4df>a+O8_p>+%AHZOfK_dpz zc7xNbyq z#O~pB$`(ty(2fs`T+dGRn_bqW8PfFcAjQkOPt1!u-0)xDq}tyYl|}J?cm}o|OH^SK zV(NU>eR`J%_eLZ2yh1digmJp=fQDe&=Y8R26waaJL1t|%>NJ@tA82Vx5;zdEh1K3o ze^}_V%2#u!4uWaIxJcHDK=GmDC#ik zIjk%sL4Xa?T-p!9_Ae{98>$Ya#=ICP_YadFvyMN0h|WdYo2+^zW{J1FJ#{aRv%=?S z687p)+u~JQyDLM0nD$5=D)h$ydd;Br+;@=mT6@x61Yz3xS8(Em*Rq7_?;@sHay?OSGd|V&EOopJ>sa6^W>yW7m!)q%yNDwGX`0xd0pm+AYXd7U9rxBhCpQ} z3qRIT?}Ct1;}cvF74fWPL_?wtxEcG(@y12BP{VqKKoMGjlhQ?YPC_n6!EX%SN{>Z- zKTHS{XF3o+WSgo}Q~XkRjO#O(n|einr=QZ%G2RFyW{Bpnc}*S!Kbc+eaQNdHM}^}E zwtjkFH@yg^NQcNe7WB4TyC~)}r;#bdORj>Oq!Gm9=(}id5PZF)2aZ z*m;W_bhH3$O#XsuBD<9rjQo7XlX>9U1yVAOU6e#jBaJSS^;{>Y7OF&@-$*7YV<=O| zBgz9)T2Dsad^HFNX?wFLwLkXWbz-Q1alv@spsg~y_N=gcb>JZ zu3bhuP9kL$}_e4su^XP{r!-_=?!qq3m#n z2-fz9c^g=YtP?&>`;mU@NyG_xrq6qs#DX@5`#fTaL)@n=n!20xmMoUidV{(L`U*4c z)9s^5bEagEin&DPMC~+fb&|cDzOU?N_rBS0{OvK~oVYk(IR$qVwnH(pMB!c{{}`g1lDvdY?z$PD%57 zyLp$fOnL#&%_xl7M2*HS&+px$kv{8zQNba}apT>+tQhf?m6fn%aHBZo8>l^e&;#9rCO|gPZe-9@Z1^g7T#Mj9zx4_V*V&%?*yzlORF*IjliS+#t-EidvNW029~^@;Rx*B5q85VLZnT51RRakZ#Z8C2mn>NhX+na zF{!t@mKM@3H9yyK7shp>+>UA{tS5ZXKEE!^*zOA+>1prL3VkhDXViz@l?Gwvd%+_C z>`Q|Ti-?c6EcbrQyAgvLyC)2lbc}F!H_>-ZVT?trtWUigG#2c@Him8v`gL~<9o~g> z?`rQNoKMrmEd$###wCXEonx0SWO(FEY%-)ZL~|~N{xrOGj(Vu;IwBYHB#OqwXB*S7 z1?%$2s}U3{PSh<|nM&nKg=xJ#mbyJSgIwF*FGIm$1bxdp{V%F-*MiH3i^ZBKErMhh z+iS&B>vb05aDCUi-*%~H_Kz2?>`)_kwBoIj;Dzh65L+1pwx93i?)!0Uq#&k3rTL@U zj25JkTjx8uu>@Hlo#-AQ^li==z0@ZUGm-07Q0s^F{gCIOUG71JJJ*AKM#wRuldQ?`_SXei%0VuXPKlu$LlwFVwRIzRcP{I0WzE8sxv0Pq@15 z1BJdt3mwOef;aOLF7vC1nD_0DSN)A>;fW1)`$ zeJ{regAm_5I$h|6W9`uNW`tF3bTzDwF9PoUN+M0VUyw7egX6Xq8Zdw93G&dPjrEYI zzHt1x`U||p0LiVih$KihX&LXGOOf45c!d-#X^I7F9BVCW2eAzK`Bxhz=nuq`izU-u zf^;GRCE(fX;TMEz5v6k>!y)G><7$*Vg?O2|k3`oa4`%fZ&8NpeJ&2(2Lwut&(`Pn* z_QE`ZI!&;GRmAmXYFapsO`mOpC|D;!?h2S60p^5l>2DzE$9wak{p!>b`6XeCGO=m7H{N zI(+lf$Jy~|&_njYit0jDRdFB>g;;x37`0{IpDoy(uXYVKv+a@eIDyVzB^~OsZAXZ-H8q&yoT{Ew%KUIsg` zsycIgCDl?W?Cht!=Iu%nH!-AuG%98#=y6VaV|Qw3`AVAT;9xpn3dSu|)t%x+;G{-4 zLU6nC7&}G-HM1KuluYd$ynHGxWmtF_kG%_~{?m z?2{7O>yUW08FCG)7tcSb#^mbkrf24{GZ@Q@Z64v@r}|9hX<_)DKCC$SWyuV}@UxLQl_eB)649V~)ek{T?Yhy!A45*9RpRHesxl#%le56lXRi&87)L;k z2UE;aedv^!YxL-Q-l?2{m|wr|vH+w}$Gh?8FHj1pGk1RrajzKIQxJ@MZLbN*mfaFmPy7duh0JvBFl2hrS%b-?;TXq-Brel~h0$1*0+l;0#2#!jm1qABBDj z`Nm$Bx9CyMY*=MPj&<9xzq^ZESJ9QDY=c-}82>d26u!qhqv?#2M&K~&o;pG|_~Krb zBAAxIOk6e3^(hUJa|`4;3(uZh>Rs$3+KKx*qk9_v`Rc;Pa=`kK$(&$TkLdN08{5X? zf(vDQAN)Yeb>9(sh9>tuA>)XVcJ!BE;82Ym5|x5#C}4?Swh3%joFb@# zzK*^)lkk)wLVvdLArR5ekA3G3t@#t-Y~{3l-}~L(l_OZ{!liLqPAhjeu*a28HE;R| zw64I$h53N(c_W!YXE#TcUg2hKfGyS6udMU#x$$f!B|-RZ5OD2*1&KJMHR>d{2m8l- zwEhYgxo``A+aiWaI#_X^Z{O*ncmv(Buel_jB9-xRf@kGO=;p$ApD-~0uH!T1n!4~h zr)WYXJ&iE@1zd?DsP9B>cNM-CjC8@Y*>v&QK>YR+TkJ1H(wSISp3X<1QO=&m=c%$61&u;@8(mQH- zA~y}vO7|;jm`du>BQD6Oovl-TDX(9i_Y+0!G>y2hFINh|Bas?c#&vT4&7_SjW~UX7oFBiCwr%m)Jj{KA zUJF$Or}4Bxxcx=_tbf>Lm1VN~97LC+%6q!S!U5*)g%4@nWQl0C zBcOE1L!a8nZ?Du|vKjZ7eI=rW0e#lcPy2XhOT4ymP-Va8R9$`OxeB4=`*R!u=zRCR6n-9F!3hidBPU5fKL#}8u z_nmRk#4(>a#9>Wr(e&&hsNiD?+@QjGv$<2SzT2@5K6;U}suM>7$2Bdepk`Wk!V2X% zy~y>b*@ixRUtee8YHcX}4&(TsDnkjgZ3GXGVZ|fizT>< z4`Fo<$TIIMcM`2T6qQ#Z2tS4uf8ZVPuvRITfr&sXdWP_-YRbNS+;LhbdK`zTn;imx5UA`b3QB^ zxKU&bW_?^Ez=CPJR_T#7>A*T~qjp}2I3w$`XYnFhijs6du&(Dj?Fkf% zt`1Fr2+Nu>PuznXT8Xd|U2av)Y^3S9RwHf=o9Uy&6iLvhqsBViXL+pH8bl}VUqPwS zN)m%q-`jM<%27~sp-!w-C$m2QyDtxTxGScDxDZOL$HY&js50pivl=}@U*^6au{pX> zCo3yPZ^E z+vUcK=_IFnpkjHZVsw%|P4V%*Z!+|gX`1%#W%V04sS)Ndzddk28V(QUfp&=ck5mKe zXxdGV3;MR4x>+<_CCVA>L$g`ZEJGyMS*R%M<Mw}X$x<*^f#5MdlnFCES}#*?k`R^>A-`lIJCBr zR`lqIq>2x!JIV#nIX)+C)HC;HvvZ@g10`Tn=+Xe!-VL%2rUnWc2a^azw~jw*pmrAXny8u1}x*EAloQh1m$f z&S*7yCu_-C-{GXcVyTW=d2iazM^@yReyEWA0_k9DicgCR)iwcPF|nMg5GU)~rYAmh z*;LPW?XmJe-CvF*2$r}7Q~I?6e|WK1$IuPRp68Z?Zh*A|`rJSnK^W$2NQyP44)7cV zcS0Xn4Bz3152gplwpW|h?#HgAiW|Wiark0Wv16ii_^c}7Gn#q((x}wFMb-%??Q;6w zywTgZ55P9L0**B7Cm=9G7h~ZPwSx9QCs;#Cul>x%iD}9zuO-fD7aVbI$%<4^kl4+Eo7> z!qAvBjY~#WA0>h1SxCNq0<>S6=_m4<(9c+SsCHzipP%U~#k!L(^mWXQ3gFZndaryD zNvoFI4iGt8{MeHTvf+%kA)*&<$d^gceP_J+f+#f}Zx7j`UYeAbsuiJ@y@O=9ClW{( zw7SWY?VM|iHp%E%-y4#JLXIaxKElP{7jq7DHSNVnyt)gekw>S-P+Y9f&X5;qJ zKf18zW9%1bq~FPZVzgh548XOBy|Umxl=l}daed9M7HKpN6gY!0k>`LkH8ZvBJb5^6 zw^L7<;Y}ay_vZJ(xE{Pc?Zgi&W6$j`}W!0Qo`f(h|&~aGZ5c-;E1eF zeDUMCZ1no19=Yxi@FUo_Y`>rclaW=7^lfQs|fKdVTuVW?$o zrf+BZZ)N&_E7Sj5nf~9(^#4|-|F<&zzm@6#txW%KW%_?B)BjtU{@=><|5m2||F1H= z{NJqU^vrFIY@Mi$bO5)z>FVhNR(iHZfVX;%T4t7}dKzXHy8nIupI_CmGuN>&GXs3k z)1@-Du`o}OQIo)ysV)){5}%r?5?@__%X{U@92Z3ir>EdhhHCC>C6xe`tR#@W%yPo5rbu5$ zu0C8vey+$dMX-HMPj>@uv&1!S*n0>vvEg^=RXhnfWmcQ0a$8^C8B9%&TAEIRw1^}C z1)(6TWP6L6aLF_?BB8#+zo|=~GQwJUJUg3KG=j5p!I$snHWhjXY?F^@hRgodbNW3f zcg4m0mMT?d{yYs*48sgNb5kFe7SK)8w3wa=c!!ih#+}8nv%;}{qv6RHT(xPDw5!Zg zQbp@t_?WBFuNCly{ryKXopdioj;&6J)cOg4{O6cOsqP*{Uo$rDV&5I@y2<1F0%_{w z5_6K@zbO8&Tv^@{%6C@_tW^ZhpQ(bEU0b$end8cJ`I+?juDQ#?LvnZhbxj;X1nU*r zJ|^k*;RRc+AA;NTWSYC1e5~jhXP;G$?3)3R0dAJ!jb&G?T$?i`2s7Oxu{bY-D)a1U zC!UISU__f1x=-vJ`C!(PFzbuyJ(Viwx3Lej77Q9ofZHL#z~%DS3+tW%0ck$}r~QDJ z0N*jw0k{H{k-5HwTsXH$Ck>SEr&sHos2cXO9dCLx@1HgAPj#g4b9Wiz8;c0oJCoiY zimZM#Md`d zPq!t2l#7Dbzd$A^!6%P%{M00qK>b%1g%^r!~3A?@hNH= z8Wh$}LB8oP*2F2+2hffOV1vKEJrqzr1L&9gLaD!bJ|H@N+YoWEHnP>D2KmL5fZqWE z{`LcK{XGf=@UP#Y^Z-x1v-~CGo`M0Cg!>c59uSZ=PZ9+O!1&`$ufHkv$Bgh4nXvyX zlYyNPwS$qafu1e3wVt`Ip7oQ&`-`RQwM>n4wQMb(h5`MrR8P_6^?(1@uRX3~VXa4P zYprE&qi)mJZ;4 z`KMTi=+6rM#&gheva|p|ZT>I015on_NQ_^Wn^H(z;7Q{AC9nP(El*MDFMR}1%2(G6H z^(|fe(ZJezwt%UdrM=~or1?GR{5lQ+zCCGcWNz@Z`22m5_gf_WpC(IxS)l(qMgWG0 zr>=_sA;h1&g#B|={BCJeEpvk>nfuRC@jL3N>yf`G_+N|vVyz!a^$Zvh2oVSz92`g| z%va`894kr<;6zq{7a|Z~=jglZzw>S}ZgC+2ei>ORF@cAHZ+jx&Q_d;wiWWeCfMURb zfN;JeWC1>Xw?`tR`0Y!%V*i=EQR$chy!X$vxN}?sRlp`rC}0cb+e-EKYXl(RceFpk zcukD}9>Sw#qxWMh;AvO$BmnF^;PpM$6R@%H_t;;yiT)l-<`igC4A9#h5JlfsK!3OZ zfBUys8Nm7|>k7Y)Lnh`(i4-v4CSUrhXCs3y7GXbK>yb^x|mzO8Y7ziH z*D-m2T|m79ByUqa>mP$H);_5h0sLtI&@mLhQvvT#04Dxtury%!wgDu;ACpbcGh>hd zR+R_Xg6umoCg9_b$^VHZ5j`jVZz<@<+%j=RFLJ=%5G@Sg^&K}5puqpa{YQhq>U3od z0mNp10R;4I>iPSHK>rs!V0Vibu*D^2q5I9)T1Mu7XAD9U|F{|eiW%T)EWaZG?-&5< z%0CGWpney-{|PrqQ!OWPJ==d2-g-L5EFS=!2fW^V*NimaoBTg%2B3wWsq`;fj(?{{ zduVO%D_9^Pen6;vZyaTSR)6Iy{viW>Gt`fJ^zueYR~+Djrhq8^-cy=|enyovwKFjK zn@B{Md5LWcV5R^fnfE(u=!pG@`^Sw+ZfzUDM;+VWZLeo7`};=bj}?KE1=Q^T_|7W8 zm05BRiph5OOCK7xh0?>aiA06&|2aB4GXWeMmvQ|5;1FC$Ddv z^&b!UX@f7V!BxJc;xm9}e4jYO1Ao@we|$m|Fh>2fnP#oPkDmdNy9sED^*amFh5xJ> zg>U=O|D!rp@rC#EfOgIS?cjdbj%C!J+WB=Of&Z7C4Vxb)90%DcLmdEa2jFLn-{BHt zevJEdI{0mp^&c|9fBuklvizIu>=9&6G7HGgB7jW#{nSG%{(o%a$HJ4@Q}LSug#Q-! z-%pf2B>yA$KN9~Kdd0C_D+(B78vx+%#}e7JA4A10c(v^H#I!7J{)tOcF67M*;8p{; zq~BTkD*f-czuNkruo+~#;@`xr0${(lL3HNdVWqzv8T}J93;2DkH~`uVfPUX&4B3AN zRru}T;Ge+vXyZIu05`Y-MF00j_>%Ky@PF2j0%D@SOy&M@)&jD=1S$ZS&Cvj6oZrhE zUHUiJZ)x%8;G1E60t|o=JOJ+d{p6Oe<%9wX{3Q^8fbv$8N?+U$=w_FmVgu z^*uSi?Qh94fb$}A+n+Z`u7S~@0nmISmv zmX<%tqVC(0)#rSgCCXNR@xH80pr)7VZLg zf*v66exDYU*8UFuYxv6QIojI&-PBdUHoNQ$U|9%&Wl6ph+V1P$aV3o$^-Otw5%zD= zI*9vh@+iQw3ITrbeO74Q{WBGCt_qkfaO>*+7Quh#1l*DSx9c0*#JShQeKK6ihzo|k&e=NDbhs{P(XTDibw}R zM2f)opV^(woY{NtZ2ZP&eXz{$oO{l>=k_~(qmME*J@l78^er}YUee99V}P!3DgIx7 z>qFbHq5YDYU6zXP3a$H8ANn>M8h>-{$$NlabfN+{`PF>gr6sLpMnmg?-*^us!&`P%0@2CZS+}#(wN{t z(xRFArav1QoNl$|nxe5O!^D}~$nQ|wcNcQhWQ zq#M=JD~nAHP0g@LLoBu#C)KM^=@)4D8%#;F=i*@;o;Z8kJX2AQt}1=j=knGp_4w)hjLQ# z#1`kPjR4f!MbjY@^`V@UJTU3)UBduv=mPCBSs%(t$z#^d_|6w0`Vxyotx3(SHccNY z2Uc*h%{0)Olh2OXQZ-sEJByj@j>spCiGZ)>=n7yXFYl;3@jjZ62=sZq2=eeZY^11? zPAujZxD|b}{^*m@yj*Dwn-*cgWM5v2G^fw$ky#cr`gkwWNq=Zbne{fXnUNU-(``}M zGl;nkcB$7LyW4UuTz>-IqNAyHo7hZ8j}%E%UNdB4_peyGGXScd!%y0fS@<-=Xobwt zI-1Y!8M!HJR>0JW9WTI)?;)7H3PJeOnjLIb57SU?jxRlA_>*inrUHo47K6g)`~fyC zmfuodI57CeWwbuWFlzytBi$j z97G49qL;R<+*`aDGh!5SZX;=Sja~j5)2?@~g9LFiQESi}RdlFq;LK->Q>5|RPM3P! zvz-_S&vS}i(6LGS1FY=^2Wk69l{<==xl!`|a}IY}lPjK;QLlflr8Q|%A2C;+P2^Bd zJqqaR4+|`I$r#(yI8=Efc|taJfSWp-&1}QoZeJ!{>M%S*-Si<qK(baoMW z9g*7sfj_6iS=F&#OZ#9gt?qEy+NR%~I1+QE2F&1SsJF59;-YOth@+nvoNP7^z%&V) z>UIC%j1NKl5vq z)|R)K%>1B?fueFxX!t|hxhV5@7|3`**TSdX2P_@)g;le1tJ&UxAXUMPBhr)VDLF|% z6B)5uy=9}XqQI}9z>QQugJI5eCNeGy!6+)S@1>{_QrGYogb%Gchi9^hc^I_BXISz@ z)MD5B`!t6keNlYc#?70>r0M~S7d%>nJZZ>BQlgoo7P{arb&>QgMT%xNt(x5eMIVRu zt^qOVs?Ql*y~^11+rVHc!F7Ru=rGIYzYLtxx=CX>b8W!;AP#6(_S>)dc&wSFWOkOj-E3>vZf~z`M8fk2+LwgE_?3JtCWP#! z5JlLWhQ4NLX`mFmM>X!WnvV|0WOI&4<9CNOe;$MyHX4CTv1``yu@PA~pCoeM?l+gW zY6EO#RNPj?5M4L8g%x_Qep5?}FxcS<+G^UfyntAAsl|>+j!Q{4Cl4?S_5N;AV9E

u{RHu3J{7$|AX-Z#Y?lE2hK0aKe?qI*JY0~`rd;}c^8>;8!K|P{S)yij&4O{};4g6@> z6+fy6mMgb#*)Q_f(4-s~;yQfyrb=mpq0BKodL+(RVB4&aAMW||S{Vf2clgm1*gz@oJ+zKKQHnB}Pw; zoDFI}WDr^tXaBB8O~^6pdvkq3oo&dRhGVERbPvjO?5*UfEpO*mH(wFbNqQVv9d63u z4J%?wHOfDLqP$X8yH{h`oqs2Z?dSN(d!jx=T;9Qt?&dmoUq_DJ8>+IfCCtu${EZJv zvH~`1OKQNW2Yd;R^F?Z_N!5YZ!++9xNnT6Ltj|X$h3*kad!#Ew)iQ}>-B7{349i4ENAx(fxaKtMl=WLqIBLh_`8)pETbBZ4E z3@fz~0(>B#B?+r7^)&)iheskJl(V}chi_aw{Bmo!;v2Yvb_n-)3D^pnmjidzyRqXs z8i*gT5QTcJdZHS+fn}$o2W{8x{s`W@i1?@7o~gcWK&4sqWJ?NXscY=4Vs$TJ-_UR9 zVNxRxZ{-HOd$I+6WX|r6<%4P!Jb?42z|gcywK0^>7Olh1yEPzVCWw1s4jS0cy6}n0 zNzx!|Zf>|K*=$RX#@SNtju-Dv^Ly@skO-(vo6HCJS0u1iapx)|EhSr9VTrLinCpvXel38VIuYX{Gu z4E3>QLI)nFQ?(-O$B_ISOIS`rvB7U_{rv7Y_;(%rOH+QiOgF*eY*evE=Fuyau;kG| ztN9&^SO6S=+ZwQujjj2RHCK)WU|`S%U3Z$8Umqm~%adblXw}!f<5#0X#UNSG_I%4n z9H??l2IC-!JbBL+l<%`(bq&PK8rYup+%Z*h#Or zB_u96O*+11QiQRcF>XZf2_8stLCA9SEJxqQVlg@L{XX_XF%cAT`o14k0OeJo6OP4IksG}v+f#BfAQz|idraKbl<35rR?KTX-o;-O1 zJ_1+Nu^ng(?-}|8vqqk;YLEQHe&V)7jkHj+iN6L?e9D03Q&7Yar~zF_#B9YTc1}{2 z6NkOBIWE&GtaHKg?ONiX`R4NGdM6-M>LDW^s-CT17D1>~#qHu`L%SonYU0(Arw~J} zupZe>CD&jmUraS27X*(Lyx9Zuy%WX7wpVrVi z`-?R}Z|N{j!qFyZ|8Do`_^O5841K`T!5&E{26hE#x(JECx-BSIr=6R1YI4QSXt%4T zXeSM8Tq?2Lpeq^QRw&8NSgxMVjkD%(R)y=tEWOhoDYzlJnUsIA zvfF$?xBt|!miZqdQoq2!C0G?q*bd`aG(HBU7JGvtoUjSI7B-_Yb_KtKPO~f?};!8%k#v#_LmU+%o))D#&c>k=f|LCcFLrLmWHm z`gCu9#ut6xyO>uDBxSo7sw*tVezmBQW^%D;E>7C!%oDAvASsMRU!KOu^8ip%2Ka?JE-I$zLRUlKcbhb3$?dSjZc7E&6u zPqklIa^wjk3-6fAu5Ljqu+(k%6A9RdSo?$PEE;YYk+Q9{eIY16%9hTHlbnL2$5)}{ zLgXq`Y1Omr7K_W@Nxf^xtw!PSpmeOSv5I3boPNY2Nn6;munL;mJ=vDdHsLy5vJ{UGTLl zwyJNhe7NZ$eDfRwK}w!py%dcq#~oBM)KQb;n$Hs=2-m29^Wq2;lhh(+-bw!!JCb? z-{0su8_c%OVPmhLx53{B)#(!U>Lx|wM?|qD)C{ToeQQKtv+mk`uHm?4gXD``<*GA8 zpm2v~lKIr-y<-f9gc=^2In={F1WfV%{sDQ}Po-lK(kULqx9YihSOYD*GF#4`J(U}@ z!>#-saF5cb?Wqb&*KzUWgd<#h4{82BBZW#~+j;S47p4t>>Qx}aTctd9ZJki~S&r#T zb#U|Ye49U3RQ?-TZ3Cu$ya?~>(;^;QJ5#lo_7)fyoBcGqo&UHeqS?9#}hT9#D=TTAL|L4x>xYXT>;`7wq_03F);>3Sc@VwBR;&2{iF7}r^JMG)CX!~ zu!^2u7%n#Ap6}{+eB=+6kS~76d?$^x>CaeH@Em4g`?2DjbFIf9YCl4c0*ONP+$mm~ zp=BYDa};shmw%e40~q51++IcuY|Ym2+_tWr#sTQ>0{pU~7|1z-*e<+Gmq`Fdy8s7Q z5d%5L4@+$f@AeUZ;V!_go?;;9=waN#e)-Z_nu?hFp-yRm4CWd-g-+odJN#+$4gXt+ z^a{|B#^U7$ETAJ~z!mkP+wHiSej0UX5Xw&15E?eoQdLXj4!CoX(Y`^0mkRItEi1nO zsy~M6bXU>4&5A699bs20`G0>8JzXEzx`C<&7z}AG6cNgetuTr6ybdQ|zsR3_uLfq7 zRyNgkOBZ(1;-ZsnIVP)x69-M|mbE!j!v~L+p1hM_97+Y;n*unX}uzNtJrt)?;K{v9Y%Q9E2^6?2B3D>q1kLjUnAy zN`KT|e))Re0BagLq{;XN6Q@KBqDUo)+U!?>T_m2ng>hVTe^?PrnvI=i*mAz^nVvOv`R6k@^&7nUct93x# z=t|U|zn>x%_3iE}!nd5{?>A|k`&qoF^{f~6N~3<$X7ln1Dz~sG1JNksmn(hwSIe99 zlSgLXQMi$8w00vwg}+5S`}hgh;;^9IH+((*G}`q~(d(lTxGk@YC<5~`jR~EZ_6|H# zf9HAFy9UZlk=G{(k?DEHaCQXxgiiZu6S8H0Oh+PNsvggeDN@Oq_FJx{zrV#Q_UFr= zkA4$jHXk&qqt{{zEcA^WW)`!tMKYZO@un@^7$43wy}Ar^*V_E26scn;=d?ac zakZ4rs;D*?GRu_x7v9jZQ|sp?n%+lqGZ+m!ji?wR`V~oE`c-2I$rJ4p%K^jY$EXIU5rlk&EXuEYR(&A2+ z{IDlQh|EYeMuaetQIRv>XkHt)%i;&B>X~b$NY}LZCac(L`_e_x>XRu@$D3;V>I9`) zCe0T2W*14Ov!>|?Jl}Wz1q-t31eY$x-bGZP*0;IFP>yd8%zFA4kkKxQdg59kGTUs7 zW;Z8^!)gyr#3r>QOfb^AdU%HzX)^|~>*|>DHQybNo=9t(7CHQo5NWa*LqnMncx>MH zy?-rxkME|_>BC=MPmsagre^VJ6f2HLZ!`POX zJJ#Q08&p1o(H%AJzGCG_-qj!nB^$d&Gc9qt!L;6Yu=X|uqcB<*PgkQz*Sgr6RTrD> z3Lm!{rhSCo8J&)*;X{Esrj5pS1nK*t+WzFQXXPLJAR+z7r8Rh`6&0W{LQ1YNxHr=X zemN&T$8wor5^PInmp68xNFAMfSkWPn`4Y)huo1zpI+*Zq3Uo9Y$!6* zB1EFc*_o}SckOn@XISugf`Jl6))^s0rso*L*~q%_>sGBnJiLUvD00v&Au`ou3}I)T zo&Fo|Y=@S)wX}83vV)IPEf2*S^P}PhY3?p&3Oc8p;&ZrXgV$>gt?MbA?9AZo3 zBu(`f<&-}=T3+qPg|(Gm{lQk`R@F1@=W?o#)N0?8{zuFV$qyn~^-Mcbj;`(~Rown@ zR}silg~9Tt7F76YR}lo&RrSdvKaZSmU(=Z|gvV`i1&>|e`%W_dfnAcShgJGr?qlCL-9}U@gD#A7=*jsL4 zo%k!B zrYOz}r9}){oPJt{e08?yeHumco$o8A z(^~!$rx4CgxCrH?vLyC_oz;{^Rl$@KuOb?4e>1c+Rr_nUf1XtYqx1Khv@pfcB=?JW zn6Obj<<4n}>S&VeTYE$t>b-a^N4HI*;rprceWgGm*>q9&INoJ-mzj+5cYu_pVcVMPQQJR7tGRVX@KE`m`fmBjU_w3bR+@kH-aWxBY$ z@7Uy1*kp)cbkpLeJecFaqlkn7nCiK#C8;Wyh(dkk^9zk4#p@yh#+Itb0s=9wUN?n~ zVpeGsP%46>{SoOw>-19%NGXYZVM@fINj>COO?jjsmOj2JLSRxr_54SR5WPzC`Cjd- zDz8eX7KK{S0I7;OJmMHtB@!t_6G9(Q)M=)0{>6PpfmRdeK130N4#BQD8A^n>)!CuJ z*7B0ZB#ylA##ohB<9sbhQOb?%L{-`Y65GD=@~6l^H2z com.myname.mymodid.api apiPackage = -# Specify the configuration file for Forge's access transformers here. I must be placed into /src/main/resources/META-INF/ +# 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 accessTransformersFile = visualprospecting_at.cfg diff --git a/repositories.gradle b/repositories.gradle index d943c8f9..6fa333a3 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,4 +1,8 @@ repositories { + maven { + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + } maven { name = "ic2" url = "https://maven.ic2.player.to/" From 5dc6709b17baa3676b8e82074ba9491014df5079 Mon Sep 17 00:00:00 2001 From: bombcar Date: Wed, 9 Feb 2022 03:50:15 -0600 Subject: [PATCH 002/132] updated dependencies (#11) --- build.gradle | 23 ++++++++++++----------- dependencies.gradle | 13 +++++++------ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/build.gradle b/build.gradle index b85885a0..be841eb2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,10 @@ -//version: 1644278435 +//version: 1644349045 /* 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 @@ -40,12 +40,12 @@ plugins { id 'idea' id 'eclipse' id 'scala' + id 'maven-publish' id('org.jetbrains.kotlin.jvm') version ('1.6.10') 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('maven-publish') } if (project.file('.git/HEAD').isFile()) { @@ -411,7 +411,7 @@ processResources from(sourceSets.main.resources.srcDirs) { include 'mcmod.info' - // replace version and mcversion + // replace modVersion and minecraftVersion expand "minecraftVersion": project.minecraft.version, "modVersion": modVersion, "modId": modId, @@ -422,7 +422,7 @@ processResources from refMap } - // copy everything else, thats not the mcmod.info + // copy everything else that's not the mcmod.info from(sourceSets.main.resources.srcDirs) { exclude 'mcmod.info' } @@ -539,8 +539,6 @@ tasks.withType(GenerateModuleMetadata) { enabled = false } - -// publishing publishing { publications { maven(MavenPublication) { @@ -561,13 +559,16 @@ publishing { // Using the identified version, not project.version as it has the prepended 1.7.10 version = System.getenv("RELEASE_VERSION") ?: identifiedVersion - // Remove all non GTNH deps here. - // Original intention was to remove an invalid forgeBin being generated without a groupId (mandatory), but - // it also removes all of the MC deps + // remove extra garbage from who knows where pom.withXml { + def badPomGroup = ['net.minecraft', 'com.google.code.findbugs', 'org.ow2.asm', 'com.typesafe.akka', 'com.typesafe', 'org.scala-lang', + 'org.scala-lang.plugins', 'net.sf.jopt-simple', 'lzma', 'com.mojang', 'org.apache.commons', 'org.apache.httpcomponents', + 'commons-logging', 'java3d', 'net.sf.trove4j', 'com.ibm.icu', 'com.paulscode', 'io.netty', 'com.google.guava', + 'commons-io', 'commons-codec', 'net.java.jinput', 'net.java.jutils', 'com.google.code.gson', 'org.apache.logging.log4j', + 'org.lwjgl.lwjgl', 'tv.twitch', ''] Node pomNode = asNode() pomNode.dependencies.'*'.findAll() { - it.groupId.text() != 'com.github.GTNewHorizons' + badPomGroup.contains(it.groupId.text()) }.each() { it.parent().remove(it) } diff --git a/dependencies.gradle b/dependencies.gradle index ede917bd..0f2ba024 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,16 +1,17 @@ dependencies { - shadowImplementation('com.github.GTNewHorizons:Enklume:master-SNAPSHOT') + shadowImplementation('com.github.GTNewHorizons:Enklume:1.1.1:dev') - compile('com.github.GTNewHorizons:GT5-Unofficial:5.09.40.32:dev') + compile('com.github.GTNewHorizons:GT5-Unofficial:5.09.40.33:dev') compile('com.github.GTNewHorizons:TCNodeTracker:1.1.4:dev') compile('net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev') compile('curse.maven:journeymap-32274:2367915') - compileOnly(deobf('https://media.forgecdn.net/files/3630/490/Xaeros_Minimap_21.10.20_Forge_1.7.10.jar')) - compileOnly(deobf('https://media.forgecdn.net/files/3599/504/XaerosWorldMap_1.14.1.13_Forge_1.7.10.jar')) - compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) - compileOnly('com.github.GTNewHorizons:IFU:master-SNAPSHOT:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:IFU:1.9.2:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.7:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:bartworks:0.5.36:dev') {transitive = false} + + compileOnly(deobf('https://media.forgecdn.net/files/3630/490/Xaeros_Minimap_21.10.20_Forge_1.7.10.jar')) + compileOnly(deobf('https://media.forgecdn.net/files/3599/504/XaerosWorldMap_1.14.1.13_Forge_1.7.10.jar')) + compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) } From c2b1f0de854b0ebd453142698f74011dbaa3bdd7 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Thu, 14 Apr 2022 22:27:20 +0200 Subject: [PATCH 003/132] Update repositories.gradle --- repositories.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/repositories.gradle b/repositories.gradle index 6fa333a3..7a4e8cd4 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -10,6 +10,14 @@ repositories { mavenPom() artifact() } + } + maven { + name = "ic2" + url = "https://maven2.ic2.player.to/" + metadataSources { + mavenPom() + artifact() + } } maven { url "https://cursemaven.com" From 8cf5ac9390186c1058763f2c46f1327fde81d60b Mon Sep 17 00:00:00 2001 From: Jakub Szewczyk Date: Sun, 24 Apr 2022 11:28:58 +0100 Subject: [PATCH 004/132] Add a dirty chunks overlay for debugging misbehaving mods (#12) * Add a dirty chunks overlay for debugging misbehaving mods, hidden behind a config option * Use IChunkProvider::chunkExists instead of guessing based on render distance --- README.md | 14 +++++ .../sinthoras/visualprospecting/Config.java | 6 ++ .../journeymap/JourneyMapState.java | 11 ++-- .../journeymap/buttons/DirtyChunkButton.java | 12 ++++ .../drawsteps/DirtyChunkDrawStep.java | 46 ++++++++++++++ .../journeymap/render/DirtyChunkRenderer.java | 28 +++++++++ .../integration/model/MapState.java | 6 ++ .../buttons/DirtyChunkButtonManager.java | 10 ++++ .../model/layers/DirtyChunkLayerManager.java | 60 +++++++++++++++++++ .../model/locations/DirtyChunkLocation.java | 32 ++++++++++ .../assets/visualprospecting/lang/en_US.lang | 1 + 11 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/DirtyChunkButton.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/DirtyChunkButtonManager.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java diff --git a/README.md b/README.md index f012a011..6bf140b3 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,20 @@ Does VisualProspecting run with other maps? - I runs just fine, but it has no vi - [TheLastKumquat](https://github.com/kumquat-ir) integrated XaeroWorldMap and XaeroMiniMap - [glowredman](https://github.com/glowredman) integrated VoxelMap +### Developer overlays + +VisualProspecting comes with developer overlays for debugging chunk saving issues, to activate it change the following config setting in `config/visualprospecting.cfg` to true: + +``` +B:enableDeveloperOverlays=true +``` + +The dirty chunk overlay works only in singleplayer mode in JourneyMap, and displays which chunks are marked as "dirty" in the game engine. +This can be used to debug mods that don't set this flag properly and therefore lose data or duplicate items on world load/unload. + +![Dirty chunks in JourneyMap developer overlay](https://i.ibb.co/XX1hqS5/2022-03-30-18-06-56.png) \ +_Dirty chunks in JourneyMap developer overlay_ + ### Dependencies #### Required Mods: diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index 3d76054f..77c5533b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -19,6 +19,7 @@ private static class Defaults { public static final int maxTransferCacheSizeMB = 50; public static final boolean enableVoxelMapWaypointsByDefault = false; public static final int maxDimensionSizeMBForFastScanning = 10000; + public static boolean enableDeveloperOverlays = false; } private static class Categories { @@ -39,6 +40,7 @@ private static class Categories { public static int maxTransferCacheSizeMB = Defaults.maxTransferCacheSizeMB; public static boolean enableVoxelMapWaypointsByDefault = Defaults.enableVoxelMapWaypointsByDefault; public static int maxDimensionSizeMBForFastScanning = Defaults.maxDimensionSizeMBForFastScanning; + public static boolean enableDeveloperOverlays = Defaults.enableDeveloperOverlays; public static void syncronizeConfiguration(File configFile) { @@ -96,6 +98,10 @@ public static void syncronizeConfiguration(File configFile) { "memory issues during the initial world scan (OutOfMemoryException)."); maxDimensionSizeMBForFastScanning = maxDimensionSizeMBForFastScanningProperty.getInt(); + Property enableDeveloperOverlaysProperty = configuration.get(Categories.general, "enableDeveloperOverlays", + Defaults.enableDeveloperOverlays, "[CLIENT] Enable mod developer overlays, not useful for gameplay"); + enableDeveloperOverlays = enableDeveloperOverlaysProperty.getBoolean(); + if(configuration.hasChanged()) { configuration.save(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java index cb60242b..b470c59f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java @@ -1,9 +1,7 @@ package com.sinthoras.visualprospecting.integration.journeymap; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.LayerButton; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.OreVeinButton; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.ThaumcraftNodeButton; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.UndergroundFluidButton; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.integration.journeymap.buttons.*; import com.sinthoras.visualprospecting.integration.journeymap.render.*; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.OreVeinWaypointManager; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.ThaumcraftNodeWaypointManager; @@ -38,6 +36,11 @@ public JourneyMapState() { buttons.add(OreVeinButton.instance); renderers.add(OreVeinRenderer.instance); waypointManagers.add(OreVeinWaypointManager.instance); + + if(Config.enableDeveloperOverlays) { + buttons.add(DirtyChunkButton.instance); + renderers.add(DirtyChunkRenderer.instance); + } } public void openJourneyMapAt(int blockX, int blockZ) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/DirtyChunkButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/DirtyChunkButton.java new file mode 100644 index 00000000..cfb61f5d --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/DirtyChunkButton.java @@ -0,0 +1,12 @@ +package com.sinthoras.visualprospecting.integration.journeymap.buttons; + +import com.sinthoras.visualprospecting.integration.model.buttons.DirtyChunkButtonManager; + +public class DirtyChunkButton extends LayerButton { + + public static final DirtyChunkButton instance = new DirtyChunkButton(); + + public DirtyChunkButton() { + super(DirtyChunkButtonManager.instance); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java new file mode 100644 index 00000000..a0d9286c --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java @@ -0,0 +1,46 @@ +package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; + +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; +import journeymap.client.render.draw.DrawStep; +import journeymap.client.render.draw.DrawUtil; +import journeymap.client.render.map.GridRenderer; + +import java.awt.geom.Point2D; + +public class DirtyChunkDrawStep implements DrawStep { + + private final DirtyChunkLocation dirtyChunkLocation; + + public DirtyChunkDrawStep(DirtyChunkLocation dirtyChunkLocation) { + this.dirtyChunkLocation = dirtyChunkLocation; + } + + @Override + public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, double fontScale, double rotation) { + final int zoom = gridRenderer.getZoom(); + double blockSize = Math.pow(2, zoom); + final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid(dirtyChunkLocation.getBlockX(), dirtyChunkLocation.getBlockZ()); + final Point2D.Double pixel = new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); + float alpha = 0.5f; + alpha *= alpha * 204; + int color = dirtyChunkLocation.isDirty() ? 0xFF0000 : 0x00FFAA; + DrawUtil.drawRectangle(pixel.getX(), pixel.getY(), + VP.chunkWidth * blockSize, VP.chunkDepth * blockSize, + color, (int)alpha); + + if(dirtyChunkLocation.isDirty()) { + final int borderColor = 0xFFD700; + final int borderAlpha = 204; + DrawUtil.drawRectangle(pixel.getX(), pixel.getY(), 15 * blockSize, blockSize, borderColor, borderAlpha); + DrawUtil.drawRectangle(pixel.getX() + 15 * blockSize, pixel.getY(), blockSize, 15 * blockSize, borderColor, borderAlpha); + DrawUtil.drawRectangle(pixel.getX() + 1 * blockSize, pixel.getY() + 15 * blockSize, 15 * blockSize, blockSize, borderColor, borderAlpha); + DrawUtil.drawRectangle(pixel.getX(), pixel.getY() + 1 * blockSize, blockSize, 15 * blockSize, borderColor, borderAlpha); + + DrawUtil.drawLabel("D", + pixel.getX() + 13 * blockSize, pixel.getY() + 13 * blockSize, + DrawUtil.HAlign.Left, DrawUtil.VAlign.Above, + 0, 180, 0x00FFFFFF, 255, fontScale, false, rotation); + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java new file mode 100644 index 00000000..dd8376d3 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java @@ -0,0 +1,28 @@ +package com.sinthoras.visualprospecting.integration.journeymap.render; + +import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.DirtyChunkDrawStep; +import com.sinthoras.visualprospecting.integration.model.layers.DirtyChunkLayerManager; +import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; +import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; +import journeymap.client.render.draw.DrawStep; + +import java.util.ArrayList; +import java.util.List; + +public class DirtyChunkRenderer extends LayerRenderer { + + public static final DirtyChunkRenderer instance = new DirtyChunkRenderer(); + + public DirtyChunkRenderer() { + super(DirtyChunkLayerManager.instance); + } + + @Override + public List mapLocationProviderToDrawStep(List visibleElements) { + final List drawSteps = new ArrayList<>(); + visibleElements.stream() + .map(element -> (DirtyChunkLocation) element) + .forEach(location -> drawSteps.add(new DirtyChunkDrawStep(location))); + return drawSteps; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java index a08fdd9c..ef6b35fe 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java @@ -1,5 +1,6 @@ package com.sinthoras.visualprospecting.integration.model; +import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.integration.model.buttons.*; import com.sinthoras.visualprospecting.integration.model.layers.*; import com.sinthoras.visualprospecting.integration.tcnodetracker.NTNodeTrackerWaypointManager; @@ -28,5 +29,10 @@ public MapState() { buttons.add(OreVeinButtonManager.instance); layers.add(OreVeinLayerManager.instance); + + if(Config.enableDeveloperOverlays) { + buttons.add(DirtyChunkButtonManager.instance); + layers.add(DirtyChunkLayerManager.instance); + } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/DirtyChunkButtonManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/DirtyChunkButtonManager.java new file mode 100644 index 00000000..cadcec51 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/DirtyChunkButtonManager.java @@ -0,0 +1,10 @@ +package com.sinthoras.visualprospecting.integration.model.buttons; + +public class DirtyChunkButtonManager extends ButtonManager { + + public static final DirtyChunkButtonManager instance = new DirtyChunkButtonManager(); + + public DirtyChunkButtonManager() { + super("visualprospecting.button.dirtychunk", "nodes"); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java new file mode 100644 index 00000000..16aaa8e9 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java @@ -0,0 +1,60 @@ +package com.sinthoras.visualprospecting.integration.model.layers; + +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.integration.model.buttons.DirtyChunkButtonManager; +import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; +import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityClientPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.World; +import net.minecraft.world.chunk.IChunkProvider; +import net.minecraft.world.gen.ChunkProviderServer; + +import java.util.ArrayList; +import java.util.List; + +public class DirtyChunkLayerManager extends LayerManager { + + public static final DirtyChunkLayerManager instance = new DirtyChunkLayerManager(); + + public DirtyChunkLayerManager() { + super(DirtyChunkButtonManager.instance); + } + + @Override + protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + return true; + } + + @Override + protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + final int minX = Utils.coordBlockToChunk(minBlockX); + final int minZ = Utils.coordBlockToChunk(minBlockZ); + final int maxX = Utils.coordBlockToChunk(maxBlockX); + final int maxZ = Utils.coordBlockToChunk(maxBlockZ); + final EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer; + final int playerDimensionId = player.dimension; + + ArrayList dirtyChunks = new ArrayList<>(); + + if (MinecraftServer.getServer() == null || MinecraftServer.getServer().worldServerForDimension(playerDimensionId) == null) { + return dirtyChunks; + } + + World w = MinecraftServer.getServer().worldServerForDimension(playerDimensionId); + IChunkProvider chunkProvider = w.getChunkProvider(); + + for (int chunkX = minX; chunkX <= maxX; chunkX++) { + for (int chunkZ = minZ; chunkZ <= maxZ; chunkZ++) { + if (!chunkProvider.chunkExists(chunkX, chunkZ)) { + continue; + } + final boolean dirty = w.getChunkFromChunkCoords(chunkX, chunkZ).isModified; + dirtyChunks.add(new DirtyChunkLocation(chunkX, chunkZ, playerDimensionId, dirty)); + } + } + + return dirtyChunks; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java new file mode 100644 index 00000000..bcdcd529 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java @@ -0,0 +1,32 @@ +package com.sinthoras.visualprospecting.integration.model.locations; + +import com.sinthoras.visualprospecting.Utils; + +public class DirtyChunkLocation implements ILocationProvider { + + private final int blockX; + private final int blockZ; + private final int dimensionId; + private final boolean dirty; + + public DirtyChunkLocation(int chunkX, int chunkZ, int dimensionId, boolean dirty) { + blockX = Utils.coordChunkToBlock(chunkX); + blockZ = Utils.coordChunkToBlock(chunkZ); + this.dimensionId = dimensionId; + this.dirty = dirty; + } + + public double getBlockX() { + return blockX + 0.5; + } + + public double getBlockZ() { + return blockZ + 0.5; + } + + public int getDimensionId() { + return dimensionId; + } + + public boolean isDirty() {return dirty;} +} diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index 728401e2..58af0290 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -4,6 +4,7 @@ visualprospecting.veins.prospected=You found %s new ore veins! visualprospecting.undergroundfluid.prospected.onlynew=You found %s new oil fields! visualprospecting.undergroundfluid.prospected.onlyupdated=You updated %s oil fields! visualprospecting.undergroundfluid.prospected.newandupdated=You found %s new and updated %s oil fields! +visualprospecting.button.dirtychunk=Show Dirty Chunks (Developer, Singleplayer only) visualprospecting.button.orevein=Show GT Ore Veins visualprospecting.button.undergroundfluid=Show GT Underground Fluids visualprospecting.button.nodes=Show TC Nodes From ce214b409701c8fc73c51978eeacad36e79cbfb7 Mon Sep 17 00:00:00 2001 From: Kiwi <42833050+Kiwi233@users.noreply.github.com> Date: Sun, 5 Jun 2022 04:55:30 +0800 Subject: [PATCH 005/132] Update zh_CN.lang (#14) --- .../resources/assets/visualprospecting/lang/zh_CN.lang | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/resources/assets/visualprospecting/lang/zh_CN.lang b/src/main/resources/assets/visualprospecting/lang/zh_CN.lang index 69a3868b..685b4c49 100644 --- a/src/main/resources/assets/visualprospecting/lang/zh_CN.lang +++ b/src/main/resources/assets/visualprospecting/lang/zh_CN.lang @@ -4,6 +4,7 @@ visualprospecting.veins.prospected=你找到了 %s 条新矿脉! visualprospecting.undergroundfluid.prospected.onlynew=你找到了 %s 新流体井! visualprospecting.undergroundfluid.prospected.onlyupdated=你更新了 %s 流体井! visualprospecting.undergroundfluid.prospected.newandupdated=你找到了 %s 新流体井并更新了 %s 流体井! +visualprospecting.button.dirtychunk=显示未写盘区块(仅限开发者,单机游戏) visualprospecting.button.orevein=显示GT矿脉 visualprospecting.button.undergroundfluid=显示GT地下流体 visualprospecting.button.nodes=显示灵气节点 @@ -15,6 +16,10 @@ visualprospecting.resetprogress.cancel=取消 visualprospecting.resetprogress.prompt=删除玩家矿脉与地下流体记录? visualprospecting.resetprogress.command=删除你的所有矿脉与地下流体记录 visualprospecting.resetprogress.confirmation=记录已删除! +visualprospecting.redoservercache.command=在服务器上重新缓存GT矿脉 +visualprospecting.redoservercache.start=开始重新缓存GT矿脉 +visualprospecting.redoservercache.failure=无法加载世界存档以构建矿脉缓存 +visualprospecting.redoservercache.confirmation=重新缓存成功! visualprospecting.iswaypoint=作为导航点激活 visualprospecting.depleted=枯竭 visualprospecting.depleted.toggle=切换为枯竭阈值: %s @@ -37,4 +42,4 @@ item.visualprospecting.prospectorslog.reading.fail4=[失败]: 我有地理学博 item.visualprospecting.prospectorslog.reading.begin=有相当多页.可能得多花点时间通读一遍. item.visualprospecting.prospectorslog.reading.end=我读完了 %s 的探矿记录 visualprospecting.node.deletehint=删除 %s -visualprospecting.tracked=追踪: %s +visualprospecting.tracked=追踪: %s \ No newline at end of file From 65b9b81064ece2f3ce5147f4f779dc1df3d48f6a Mon Sep 17 00:00:00 2001 From: MuXiu1997 Date: Mon, 6 Jun 2022 23:07:39 +0800 Subject: [PATCH 006/132] Add a command to redo GT vein cache (#13) --- .../database/RedoServerCacheCommand.java | 77 +++++++++++++++++++ .../visualprospecting/hooks/HooksShared.java | 2 + .../assets/visualprospecting/lang/en_US.lang | 4 + 3 files changed, 83 insertions(+) create mode 100644 src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java new file mode 100644 index 00000000..3c03a14a --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java @@ -0,0 +1,77 @@ +package com.sinthoras.visualprospecting.database; + +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; +import cpw.mods.fml.server.FMLServerHandler; +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.StatCollector; + +import java.io.IOException; +import java.util.Objects; +import java.util.zip.DataFormatException; + +public class RedoServerCacheCommand extends CommandBase { + + @Override + public String getCommandName() { + return "visualprospectingredoservercache"; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return StatCollector.translateToLocal("visualprospecting.redoservercache.command"); + } + + @Override + public void processCommand(ICommandSender sender, String[] parameters) { + MinecraftServer server; + if (sender instanceof EntityPlayerMP) { + EntityPlayerMP player = (EntityPlayerMP) sender; + server = player.mcServer; + } else { + server = FMLServerHandler.instance().getServer(); + } + if (server == null) { + VP.info("Server not found"); + return; + } + final IChatComponent start = new ChatComponentTranslation("visualprospecting.redoservercache.start"); + start.getChatStyle().setItalic(true); + sender.addChatMessage(start); + try { + WorldAnalysis world = new WorldAnalysis(server.getEntityWorld().getSaveHandler().getWorldDirectory()); + world.cacheVeins(); + } catch (IOException | DataFormatException e) { + VP.info("Could not load world save files to build vein cache!"); + e.printStackTrace(); + final IChatComponent failure = new ChatComponentTranslation("visualprospecting.redoservercache.failure"); + failure.getChatStyle().setItalic(true); + sender.addChatMessage(failure); + } + final IChatComponent confirmation = new ChatComponentTranslation("visualprospecting.redoservercache.confirmation"); + confirmation.getChatStyle().setItalic(true); + sender.addChatMessage(confirmation); + } + + @Override + public boolean canCommandSenderUseCommand(ICommandSender sender) { + // Only SP owner, or OP are allowed + if (sender instanceof EntityPlayerMP) { + EntityPlayerMP player = (EntityPlayerMP) sender; + if (Objects.equals(player.mcServer.getServerOwner(), sender.getCommandSenderName())) { + return true; + } + } + return super.canCommandSenderUseCommand(sender); + } + + @Override + public int getRequiredPermissionLevel() { + return 4; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index ef423d6b..46bc59dc 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -3,6 +3,7 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.database.RedoServerCacheCommand; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.WorldIdHandler; import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; @@ -96,6 +97,7 @@ public void fmlLifeCycleEvent(FMLServerStartingEvent event) { e.printStackTrace(); } } + event.registerServerCommand(new RedoServerCacheCommand()); } public void fmlLifeCycleEvent(FMLServerStartedEvent event) { diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index 58af0290..5dd34a58 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -16,6 +16,10 @@ visualprospecting.resetprogress.cancel=Cancel visualprospecting.resetprogress.prompt=Delete player progress on ore veins and underground fluids? visualprospecting.resetprogress.command=Deletes all your progress on ore veins and undergrond fluids visualprospecting.resetprogress.confirmation=Progress deleted! +visualprospecting.redoservercache.command=Redo the GT vein cache on the server +visualprospecting.redoservercache.start=Start redoing the GT vein cache on the server +visualprospecting.redoservercache.failure=Could not load world save files to build vein cache! +visualprospecting.redoservercache.confirmation=Redo success! visualprospecting.iswaypoint=Active as Waypoint visualprospecting.depleted=DEPLETED visualprospecting.depleted.toggle=Toggle depleted with %s From c4d3e6fddbe6353197931580751293de8d227e6f Mon Sep 17 00:00:00 2001 From: slprime <31038811+slprime@users.noreply.github.com> Date: Sat, 25 Jun 2022 12:16:42 +0300 Subject: [PATCH 007/132] Use Regex in vein search (#15) --- .../database/veintypes/VeinTypeCaching.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index 3005d8d6..f2642e91 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -12,9 +12,11 @@ import gregtech.api.enums.Materials; import gregtech.common.GT_Worldgen_GT_Ore_Layer; import net.minecraft.client.resources.I18n; +import net.minecraft.util.EnumChatFormatting; import java.io.File; import java.util.*; +import java.util.regex.Pattern; import java.util.stream.Collectors; import static com.sinthoras.visualprospecting.Utils.*; @@ -155,14 +157,19 @@ public static void recalculateNEISearch() { if(isNEIInstalled()) { final boolean isSearchActive = SearchField.searchInventories(); final String searchString = NEIClientConfig.getSearchExpression().toLowerCase(); + final Pattern filterPattern = SearchField.getPattern(searchString); for (VeinType veinType : veinTypes) { if (veinType != VeinType.NO_VEIN) { if (isSearchActive) { List searchableStrings = veinType.getOreMaterialNames(); searchableStrings.add(I18n.format(veinType.name)); - searchableStrings = searchableStrings.stream().map(String::toLowerCase).filter(searchableString -> searchableString.contains(searchString)).collect(Collectors.toList()); - veinType.setNEISearchHeighlight(searchableStrings.isEmpty() == false); + final boolean match = searchableStrings.stream() + .map(EnumChatFormatting::getTextWithoutFormattingCodes) + .map(String::toLowerCase) + .anyMatch(searchableString -> filterPattern.matcher(searchableString).find()); + + veinType.setNEISearchHeighlight(match); } else { veinType.setNEISearchHeighlight(true); } From 47eeb4441e4e465257b0d992ce5cb4c98e25cbc3 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Sat, 16 Jul 2022 10:52:00 -0700 Subject: [PATCH 008/132] [ci skip] Migrate github actions to GTNH-Actions-Workflows --- .github/scripts/test-no-crash-reports.sh | 9 ----- .github/workflows/build-and-test.yml | 36 +---------------- .github/workflows/release-tags.yml | 51 ++++-------------------- 3 files changed, 9 insertions(+), 87 deletions(-) delete mode 100644 .github/scripts/test-no-crash-reports.sh diff --git a/.github/scripts/test-no-crash-reports.sh b/.github/scripts/test-no-crash-reports.sh deleted file mode 100644 index c67e342c..00000000 --- a/.github/scripts/test-no-crash-reports.sh +++ /dev/null @@ -1,9 +0,0 @@ -directory="run/crash-reports" -if [ -d $directory ]; then - echo "Crash reports detected:" - cat $directory/* - exit 1 -else - echo "No crash reports detected" - exit 0 -fi diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index a60a2b64..3ee2f686 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -1,5 +1,3 @@ -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle name: Build and test @@ -11,35 +9,5 @@ on: jobs: build-and-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set up JDK 8 - uses: actions/setup-java@v2 - with: - java-version: '8' - distribution: 'adopt' - cache: gradle - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Setup the workspace - run: ./gradlew setupCIWorkspace - - - name: Build the mod - run: ./gradlew build - - - name: Run server for 1 minute - run: | - mkdir run - echo "eula=true" > run/eula.txt - timeout 60 ./gradlew runServer || true - - - name: Test no crashes happend - run: | - chmod +x .github/scripts/test-no-crash-reports.sh - .github/scripts/test-no-crash-reports.sh + uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/build-and-test.yml@master + secrets: inherit diff --git a/.github/workflows/release-tags.yml b/.github/workflows/release-tags.yml index c86d8889..e4c0be6b 100644 --- a/.github/workflows/release-tags.yml +++ b/.github/workflows/release-tags.yml @@ -1,51 +1,14 @@ -# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle name: Release tagged build on: push: - tags: - - '*' + tags: [ '*' ] -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Set release version - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - - - name: Set up JDK 8 - uses: actions/setup-java@v2 - with: - java-version: '8' - distribution: 'adopt' - cache: gradle - - - name: Grant execute permission for gradlew - run: chmod +x gradlew +permissions: + contents: write - - name: Setup the workspace - run: ./gradlew setupCIWorkspace - - - name: Build the mod - run: ./gradlew build - - - name: Release under current tag - uses: "marvinpinto/action-automatic-releases@latest" - with: - repo_token: "${{ secrets.GITHUB_TOKEN }}" - automatic_release_tag: "${{ env.RELEASE_VERSION }}" - prerelease: false - title: "${{ env.RELEASE_VERSION }}" - files: build/libs/*.jar - - - name: Publish to Maven - run: ./gradlew publish - env: - MAVEN_USER: ${{ secrets.MAVEN_USER }} - MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} +jobs: + release-tags: + uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/release-tags.yml@master + secrets: inherit From 8e990d8a3de22ed162db169b6ee776534b7e23e6 Mon Sep 17 00:00:00 2001 From: chochem <40274384+chochem@users.noreply.github.com> Date: Mon, 8 Aug 2022 22:26:19 +0100 Subject: [PATCH 009/132] Fix fullscreen map not opening (#18) * check empty * update dependency --- dependencies.gradle | 2 +- .../visualprospecting/database/veintypes/VeinTypeCaching.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 0f2ba024..53588654 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:1.1.1:dev') compile('com.github.GTNewHorizons:GT5-Unofficial:5.09.40.33:dev') - compile('com.github.GTNewHorizons:TCNodeTracker:1.1.4:dev') + compile('com.github.GTNewHorizons:TCNodeTracker:1.1.6:dev') compile('net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev') compile('curse.maven:journeymap-32274:2367915') diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index f2642e91..be65a87d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -161,7 +161,7 @@ public static void recalculateNEISearch() { for (VeinType veinType : veinTypes) { if (veinType != VeinType.NO_VEIN) { - if (isSearchActive) { + if (isSearchActive && !searchString.equals("")) { List searchableStrings = veinType.getOreMaterialNames(); searchableStrings.add(I18n.format(veinType.name)); final boolean match = searchableStrings.stream() From 7d58b0529bdffd1cb405695aafecd34d728051d5 Mon Sep 17 00:00:00 2001 From: miozune Date: Tue, 9 Aug 2022 11:53:18 +0900 Subject: [PATCH 010/132] Add back dimension info on book (#16) * Add back dimension info on book * updateBuildScript & spotlessApply --- build.gradle | 518 +++++++++++++----- repositories.gradle | 2 +- settings.gradle | 10 + .../sinthoras/visualprospecting/Config.java | 98 ++-- .../visualprospecting/ServerTranslations.java | 6 +- .../sinthoras/visualprospecting/Utils.java | 58 +- .../com/sinthoras/visualprospecting/VP.java | 7 +- .../sinthoras/visualprospecting/VPMod.java | 12 +- .../VisualProspecting_API.java | 67 ++- .../database/ClientCache.java | 82 +-- .../database/DimensionCache.java | 59 +- .../database/RedoServerCacheCommand.java | 13 +- .../database/ResetClientCacheCommand.java | 3 +- .../database/ServerCache.java | 49 +- .../database/TransferCache.java | 23 +- .../database/UndergroundFluidPosition.java | 10 +- .../database/WorldCache.java | 34 +- .../database/WorldIdHandler.java | 3 +- .../cachebuilder/AnalysisProgressTracker.java | 21 +- .../database/cachebuilder/ChunkAnalysis.java | 13 +- .../cachebuilder/DetailedChunkAnalysis.java | 106 ++-- .../cachebuilder/DimensionAnalysis.java | 36 +- .../database/cachebuilder/GregTechOre.java | 16 +- .../database/cachebuilder/WorldAnalysis.java | 5 +- .../BartworksOreMaterialProvider.java | 4 +- .../veintypes/IOreMaterialProvider.java | 1 - .../database/veintypes/VeinType.java | 22 +- .../database/veintypes/VeinTypeCaching.java | 62 ++- .../visualprospecting/hooks/HooksClient.java | 97 ++-- .../hooks/HooksEventBus.java | 9 +- .../visualprospecting/hooks/HooksShared.java | 139 +++-- .../hooks/ProspectingNotificationEvent.java | 64 +-- .../integration/DrawUtils.java | 63 ++- .../gregtech/UndergroundFluidsWrapper.java | 59 +- .../journeymap/JourneyMapState.java | 13 +- .../integration/journeymap/Reflection.java | 9 +- .../ResetClientCacheConfirmation.java | 10 +- .../journeymap/buttons/LayerButton.java | 2 +- .../drawsteps/ClickableDrawStep.java | 3 +- .../drawsteps/DirtyChunkDrawStep.java | 55 +- .../journeymap/drawsteps/OreVeinDrawStep.java | 72 ++- .../drawsteps/ThaumcraftNodeDrawStep.java | 138 +++-- .../UndergroundFluidChunkDrawStep.java | 80 ++- .../drawsteps/UndergroundFluidDrawStep.java | 66 ++- .../journeymap/render/DirtyChunkRenderer.java | 3 +- .../journeymap/render/LayerRenderer.java | 6 +- .../journeymap/render/OreVeinRenderer.java | 4 +- .../render/ThaumcraftNodeRenderer.java | 4 +- .../render/UndergroundFluidChunkRenderer.java | 3 +- .../render/UndergroundFluidRenderer.java | 3 +- .../render/WaypointProviderLayerRenderer.java | 27 +- .../journeymap/waypoints/WaypointManager.java | 7 +- .../integration/model/MapState.java | 9 +- .../model/buttons/ButtonManager.java | 8 +- .../model/layers/DirtyChunkLayerManager.java | 12 +- .../model/layers/LayerManager.java | 12 +- .../model/layers/LayerRenderer.java | 1 - .../model/layers/OreVeinLayerManager.java | 18 +- .../layers/ThaumcraftNodeLayerManager.java | 21 +- .../UndergroundFluidChunkLayerManager.java | 55 +- .../layers/UndergroundFluidLayerManager.java | 46 +- .../model/layers/WaypointProviderManager.java | 10 +- .../model/locations/DirtyChunkLocation.java | 4 +- .../model/locations/OreVeinLocation.java | 21 +- .../locations/ThaumcraftNodeLocation.java | 25 +- .../UndergroundFluidChunkLocation.java | 11 +- .../NTNodeTrackerWaypointManager.java | 3 +- .../voxelmap/IWaypointManagerReflection.java | 42 +- .../voxelmap/VoxelMapEventHandler.java | 129 +++-- .../xaerominimap/XaeroMiniMapState.java | 5 +- .../waypoints/WaypointManager.java | 22 +- .../xaeroworldmap/XaeroWorldMapState.java | 8 +- .../buttons/SizedGuiTexturedButton.java | 12 +- .../renderers/InteractableLayerRenderer.java | 9 +- .../renderers/LayerRenderer.java | 4 +- .../renderers/OreVeinRenderer.java | 1 - .../renderers/ThaumcraftNodeRenderer.java | 1 - .../UndergroundFluidChunkRenderer.java | 4 +- .../renderers/UndergroundFluidRenderer.java | 1 - .../rendersteps/InteractableRenderStep.java | 1 - .../rendersteps/OreVeinRenderStep.java | 46 +- .../xaeroworldmap/rendersteps/RenderStep.java | 3 +- .../rendersteps/ThaumcraftNodeRenderStep.java | 80 ++- .../UndergroundFluidChunkRenderStep.java | 20 +- .../UndergroundFluidRenderStep.java | 11 +- .../item/ProspectorsLog.java | 47 +- .../visualprospecting/mixinplugin/Mixin.java | 7 +- .../mixinplugin/MixinPlugin.java | 45 +- .../mixinplugin/TargetedMod.java | 18 +- .../bartworks/WorldGenContainerMixin.java | 35 +- .../GT_Worldgenerator_SpaceMixin.java | 35 +- .../gregtech/GT_Block_Ores_AbstractMixin.java | 11 +- ...aTileEntity_AdvSeismicProspectorMixin.java | 69 ++- .../GT_MetaTileEntity_ScannerMixin.java | 76 ++- .../gregtech/WorldGenContainerMixin.java | 42 +- .../mixins/ifu/ItemOreFinderToolMixin.java | 105 ++-- .../journeymap/FullscreenActionsMixin.java | 16 +- .../mixins/journeymap/FullscreenMixin.java | 111 ++-- .../mixins/journeymap/MiniMapMixin.java | 37 +- .../journeymap/RenderWaypointBeaconMixin.java | 16 +- .../journeymap/WaypointManagerMixin.java | 13 +- .../minecraft/ForgeHooksClientMixin.java | 5 +- .../minecraft/ItemEditableBookMixin.java | 36 +- .../mixins/tcnodetracker/GuiMainMixin.java | 54 +- .../xaerosminimap/MinimapRendererMixin.java | 144 +++-- .../WaypointsIngameRendererMixin.java | 28 +- .../mixins/xaerosworldmap/GuiMapMixin.java | 142 +++-- .../network/ProspectingNotification.java | 25 +- .../network/ProspectingRequest.java | 48 +- .../network/ProspectionSharing.java | 53 +- .../network/WorldIdNotification.java | 4 +- .../task/SnapshotDownloadTask.java | 10 +- .../task/SnapshotUploadTask.java | 3 +- 113 files changed, 2554 insertions(+), 1612 deletions(-) create mode 100644 settings.gradle diff --git a/build.gradle b/build.gradle index be841eb2..ec6cfc96 100644 --- a/build.gradle +++ b/build.gradle @@ -1,57 +1,78 @@ -//version: 1644349045 +//version: 1659365110 /* -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. -*/ + 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 { + mavenCentral() + maven { - name = "forge" - url = "https://maven.minecraftforge.net" + name 'forge' + url 'https://maven.minecraftforge.net' } maven { - name = "sonatype" - url = "https://oss.sonatype.org/content/repositories/snapshots/" + name 'sonatype' + url 'https://oss.sonatype.org/content/repositories/snapshots/' } maven { - name = "Scala CI dependencies" - url = "https://repo1.maven.org/maven2/" + name 'Scala CI dependencies' + url 'https://repo1.maven.org/maven2/' } maven { - name = "jitpack" - url = "https://jitpack.io" + name 'jitpack' + url 'https://jitpack.io' } } dependencies { classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.7' } } - plugins { + id 'java-library' id 'idea' id 'eclipse' id 'scala' id 'maven-publish' - id('org.jetbrains.kotlin.jvm') version ('1.6.10') 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 '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" +} +verifySettingsGradle() + +dependencies { + implementation 'com.diffplug:blowdryer:1.6.0' } +apply plugin: 'com.diffplug.blowdryer' + 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) @@ -69,6 +90,7 @@ idea { downloadSources = true } } +apply from: Blowdryer.file('spotless.gradle') if(JavaVersion.current() != JavaVersion.VERSION_1_8) { throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current()) @@ -95,8 +117,11 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") -boolean noPublishedSources = project.findProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false - +boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false +boolean usesMixinDebug = project.hasProperty('usesMixinDebug') ?: project.usesMixins.toBoolean() +boolean forceEnableMixins = project.hasProperty('forceEnableMixins') ? project.forceEnableMixins.toBoolean() : false +String channel = project.hasProperty('channel') ? project.channel : 'stable' +String mappingsVersion = project.hasProperty('mappingsVersion') ? project.mappingsVersion : '12' String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" @@ -167,8 +192,8 @@ configurations.all { try { 'git config core.fileMode false'.execute() } -catch (Exception e) { - logger.error("\u001B[31mgit isn't installed at all\u001B[0m") +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 @@ -177,19 +202,22 @@ String versionOverride = System.getenv("VERSION") ?: null try { identifiedVersion = versionOverride == null ? gitVersion() : versionOverride } -catch (Exception e) { - logger.error("\n\u001B[1;31mThis mod must be version controlled by Git AND the repository must provide at least one tag,\n" + - "or the VERSION override must be set! \u001B[32m(Don't download from GitHub using the ZIP option, instead\n" + - "clone the repository, see\u001B[33m https://gtnh.miraheze.org/wiki/Development \u001B[32mfor details.)\u001B[0m\n"); +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 -String modVersion = identifiedVersion +ext { + modVersion = identifiedVersion +} -if( identifiedVersion.equals(versionOverride) ) { - logger.error('\u001B[31m\u001B[7mWe hope you know what you\'re doing using\u001B[0m\u001B[1;34m ' + modVersion + '\u001B[0m\n'); - logger.error('\7\u001B[31mGoing to blindly try to use\u001B[1;34m ' + modVersion + '\u001B[0m\u001B[31m, this probably won\'t work the way you expect!!\u001B[0m\n'); +if(identifiedVersion == versionOverride) { + out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') } group = modGroup @@ -200,22 +228,25 @@ else { archivesBaseName = modId } - def arguments = [] def jvmArguments = [] -if(usesMixins.toBoolean()) { +if (usesMixins.toBoolean() || forceEnableMixins) { arguments += [ - "--tweakClass org.spongepowered.asm.launch.MixinTweaker" - ] - jvmArguments += [ - "-Dmixin.debug.countInjections=true", "-Dmixin.debug.verbose=true", "-Dmixin.debug.export=true" + "--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" + version = minecraftVersion + '-' + forgeVersion + '-' + minecraftVersion + runDir = 'run' if (replaceGradleTokenInFile) { replaceIn replaceGradleTokenInFile @@ -248,8 +279,8 @@ minecraft { } } -if(file("addon.gradle").exists()) { - apply from: "addon.gradle" +if(file('addon.gradle').exists()) { + apply from: 'addon.gradle' } apply from: 'repositories.gradle' @@ -262,58 +293,65 @@ configurations { repositories { maven { - name = "Overmind forge repo mirror" - url = "https://gregtech.overminddl1.com/" + name 'Overmind forge repo mirror' + url 'https://gregtech.overminddl1.com/' } - if(usesMixins.toBoolean()) { + if(usesMixins.toBoolean() || forceEnableMixins) { maven { - name = "sponge" - url = "https://repo.spongepowered.org/repository/maven-public" + name 'sponge' + url 'https://repo.spongepowered.org/repository/maven-public' } maven { - url = "https://jitpack.io" + 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") + 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') + } + if(usesMixins.toBoolean() || forceEnableMixins) { // using 0.8 to workaround a issue in 0.7 which fails mixin application - compile("com.github.GTNewHorizons:SpongePoweredMixin:0.7.12-GTNH") { + 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" + 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") + compile('com.github.GTNewHorizons:SpongeMixins:1.5.0') } } apply from: 'dependencies.gradle' -def mixingConfigRefMap = "mixins." + modId + ".refmap.json" +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()) { - getFile("/src/main/resources/mixins." + modId + ".json").text = """{ + 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" + "compatibilityLevel": "JAVA_8", + "mixins": [], + "client": [], + "server": [] } - """ + } } } @@ -334,7 +372,10 @@ shadowJar { } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] + configurations = [ + project.configurations.shadowImplementation, + project.configurations.shadowCompile + ] dependsOn(relocateShadowJar) } @@ -365,12 +406,12 @@ 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" + "-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" ] } } @@ -379,8 +420,8 @@ afterEvaluate { runClient { if(developmentEnvironmentUserName) { arguments += [ - "--username", - developmentEnvironmentUserName + "--username", + developmentEnvironmentUserName ] } @@ -398,24 +439,24 @@ tasks.withType(JavaExec).configureEach { javaToolchains.launcherFor { languageVersion = projectJavaVersion } - ) + ) } -processResources -{ +processResources { // this will ensure that this task is redone when the versions change. inputs.property "version", project.version inputs.property "mcversion", project.minecraft.version - + exclude("spotless.gradle") + // 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 + "modVersion": modVersion, + "modId": modId, + "modName": modName } if(usesMixins.toBoolean()) { @@ -425,12 +466,13 @@ processResources // copy everything else that's not the mcmod.info from(sourceSets.main.resources.srcDirs) { exclude 'mcmod.info' + exclude 'spotless.gradle' } } def getManifestAttributes() { def manifestAttributes = [:] - if(containsMixinsAndOrCoreModOnly.toBoolean() == false && (usesMixins.toBoolean() || coreModClass)) { + if(!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { manifestAttributes += ["FMLCorePluginContainsFMLMod": true] } @@ -444,16 +486,16 @@ def getManifestAttributes() { if(usesMixins.toBoolean()) { manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : "mixins." + modId + ".json", - "ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false + "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", + "MixinConfigs" : "mixins." + modId + ".json", + "ForceLoadAsMod" : !containsMixinsAndOrCoreModOnly.toBoolean() ] } return manifestAttributes } task sourcesJar(type: Jar) { - from (sourceSets.main.allJava) + from (sourceSets.main.allSource) from (file("$projectDir/LICENSE")) getArchiveClassifier().set('sources') } @@ -473,7 +515,10 @@ task shadowDevJar(type: ShadowJar) { } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] + configurations = [ + project.configurations.shadowImplementation, + project.configurations.shadowCompile + ] } task relocateShadowDevJar(type: ConfigureShadowRelocation) { @@ -508,7 +553,7 @@ task devJar(type: Jar) { } task apiJar(type: Jar) { - from (sourceSets.main.allJava) { + from (sourceSets.main.allSource) { include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } @@ -533,12 +578,15 @@ artifacts { } } -// The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID), +// 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) { @@ -547,7 +595,7 @@ publishing { artifact source: shadowJar, classifier: "" } if(!noPublishedSources) { - artifact source: sourcesJar, classifier: "src" + artifact source: sourcesJar, classifier: "sources" } artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev" if (apiPackage) { @@ -558,17 +606,24 @@ publishing { 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 who knows where + + // remove extra garbage from minecraft and minecraftDeps configuration pom.withXml { - def badPomGroup = ['net.minecraft', 'com.google.code.findbugs', 'org.ow2.asm', 'com.typesafe.akka', 'com.typesafe', 'org.scala-lang', - 'org.scala-lang.plugins', 'net.sf.jopt-simple', 'lzma', 'com.mojang', 'org.apache.commons', 'org.apache.httpcomponents', - 'commons-logging', 'java3d', 'net.sf.trove4j', 'com.ibm.icu', 'com.paulscode', 'io.netty', 'com.google.guava', - 'commons-io', 'commons-codec', 'net.java.jinput', 'net.java.jutils', 'com.google.code.gson', 'org.apache.logging.log4j', - 'org.lwjgl.lwjgl', 'tv.twitch', ''] + def badArtifacts = [:].withDefault {[] as Set} + 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() { - badPomGroup.contains(it.groupId.text()) + badArtifacts[it.groupId.text()].contains(it.artifactId.text()) }.each() { it.parent().remove(it) } @@ -592,7 +647,7 @@ task updateBuildScript { doLast { if (performBuildScriptUpdate(projectDir.toString())) return - print("Build script already up-to-date!") + print("Build script already up-to-date!") } } @@ -600,19 +655,33 @@ if (isNewBuildScriptVersionAvailable(projectDir.toString())) { if (autoUpdateBuildScript.toBoolean()) { performBuildScriptUpdate(projectDir.toString()) } else { - println("Build script update available! Run 'gradle updateBuildScript'") + 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") } +static URL exampleSettingsGradleUrl() { + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/settings.gradle.example") +} + + +def verifySettingsGradle() { + def settingsFile = getFile("settings.gradle") + if (!settingsFile.exists()) { + println("Downloading default settings.gradle") + exampleSettingsGradleUrl().withInputStream { i -> settingsFile.withOutputStream { it << i } } + throw new GradleException("Settings.gradle has been updated, please re-run task.") + } +} boolean performBuildScriptUpdate(String projectDir) { if (isNewBuildScriptVersionAvailable(projectDir)) { def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } - print("Build script updated. Please REIMPORT the project or RESTART your IDE!") + out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!") + verifySettingsGradle() return true } return false @@ -643,80 +712,225 @@ configure(updateBuildScript) { description = 'Updates the build script to the latest version' } -// Deobfuscation +// Parameter 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) +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 } - //get rid of extension: - if(fileName.endsWith(".jar")) { - fileName = fileName.substring(0, fileName.lastIndexOf(".")) + + if(!file(paramsCSV).exists()) { + println("Extracting MCP archive ...") + unzip(mcpZIP, mcpDir) } - String hostName = url.getHost() - if(hostName.startsWith("www.")) { - hostName = hostName.substring(4) + println("Parsing params.csv ...") + Map 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]) + } } - 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/" + String.valueOf(sourceURL.hashCode())) - } + 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.") +} } -// 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 fileName) { - String cacheDir = System.getProperty("user.home") + "/.gradle/caches/" - String bon2Dir = cacheDir + "forge_gradle/deobf" - String bon2File = bon2Dir + "/BON2-2.5.0.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) - } +static int replaceParams(File file, Map params) { +int fileCount = 0 - download.run { - src 'https://github.com/GTNewHorizons/BON2/releases/download/2.5.0/BON2-2.5.0.CUSTOM-all.jar' - dest bon2File - quiet true - overwrite false +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() - download.run { - src sourceURL - dest obfFile - quiet true - overwrite false + //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(".")) } - exec { - commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', '1.7.10', '--mappingsVer', 'stable_12', '--notch' - workingDir bon2Dir - standardOutput = new ByteArrayOutputStream() + 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 +String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/' +if(remoteMappings) { + String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion" + String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip" + + zipMappings(mappingsZIP, remoteMappings, bon2Dir) + + mappingsVer = "snapshot_$id" +} else { + mappingsVer = "${channel}_$mappingsVersion" +} + +download.run { + src "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases/com/github/parker8283/BON2/$bon2Version-CUSTOM/BON2-$bon2Version-CUSTOM-all.jar" + dest bon2File + quiet true + overwrite false +} + +download.run { + src sourceURL + 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) == false) { - 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") - } +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) +return new File(projectDir, relativePath) } diff --git a/repositories.gradle b/repositories.gradle index 7a4e8cd4..953ea178 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -11,7 +11,7 @@ repositories { artifact() } } - maven { + maven { name = "ic2" url = "https://maven2.ic2.player.to/" metadataSources { diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..97d8f71c --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +plugins { + id 'com.diffplug.blowdryerSetup' version '1.6.0' +} + +apply plugin: 'com.diffplug.blowdryerSetup' + +blowdryerSetup { + github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.1.4') + //devLocal '.' // Use this when testing config updates locally +} diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index 77c5533b..3eaf9475 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -1,10 +1,9 @@ package com.sinthoras.visualprospecting; +import java.io.File; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; -import java.io.File; - public class Config { private static class Defaults { @@ -42,67 +41,98 @@ private static class Categories { public static int maxDimensionSizeMBForFastScanning = Defaults.maxDimensionSizeMBForFastScanning; public static boolean enableDeveloperOverlays = Defaults.enableDeveloperOverlays; - public static void syncronizeConfiguration(File configFile) { Configuration configuration = new Configuration(configFile); configuration.load(); - Property enableProspectingProperty = configuration.get(Categories.general, "enableProspecting", - Defaults.enableProspecting, "[CLIENT] You may want to disable prospecting for low-performance clients."); + Property enableProspectingProperty = configuration.get( + Categories.general, + "enableProspecting", + Defaults.enableProspecting, + "[CLIENT] You may want to disable prospecting for low-performance clients."); enableProspecting = enableProspectingProperty.getBoolean(); - Property cacheGenerationLogUpdateMinTimeProperty = configuration.get(Categories.general, "cacheGenerationLogUpdateMinTime", - Defaults.cacheGenerationLogUpdateMinTime, "[SERVER] Minimum between log updates to show progress when " + - "caching save files. This happens only ONCE!"); + Property cacheGenerationLogUpdateMinTimeProperty = configuration.get( + Categories.general, + "cacheGenerationLogUpdateMinTime", + Defaults.cacheGenerationLogUpdateMinTime, + "[SERVER] Minimum between log updates to show progress when " + + "caching save files. This happens only ONCE!"); cacheGenerationLogUpdateMinTime = cacheGenerationLogUpdateMinTimeProperty.getInt(); - Property minDelayBetweenVeinRequestsProperty = configuration.get(Categories.network, "minDelayBetweenVeinRequests", - Defaults.minDelayBetweenVeinRequests, "[CLIENT + SERVER] Anti spam mechanic: What is the minimum delay (in milliseconds)" + - " a player is allowed to request ore vein information."); + Property minDelayBetweenVeinRequestsProperty = configuration.get( + Categories.network, + "minDelayBetweenVeinRequests", + Defaults.minDelayBetweenVeinRequests, + "[CLIENT + SERVER] Anti spam mechanic: What is the minimum delay (in milliseconds)" + + " a player is allowed to request ore vein information."); minDelayBetweenVeinRequests = minDelayBetweenVeinRequestsProperty.getInt(); - Property minZoomLevelProperty = configuration.get(Categories.general, "minZoomLevelForOreLabel", Defaults.minZoomLevelForOreLabel, + Property minZoomLevelProperty = configuration.get( + Categories.general, + "minZoomLevelForOreLabel", + Defaults.minZoomLevelForOreLabel, "[CLIENT] Minimum zoom level at which ore veins labels are displayed. Zoom starts at 0 and increments linearly."); minZoomLevelForOreLabel = minZoomLevelProperty.getInt(); - Property minZoomLevelForUndergroundFluidDetailsProperty = configuration.get(Categories.general, "minZoomLevelForUndergroundFluidDetails", - Defaults.minZoomLevelForUndergroundFluidDetails, "[CLIENT] Minimum zoom level at which underground fluid details are displayed. Zoom starts at 0 and increments linearly."); + Property minZoomLevelForUndergroundFluidDetailsProperty = configuration.get( + Categories.general, + "minZoomLevelForUndergroundFluidDetails", + Defaults.minZoomLevelForUndergroundFluidDetails, + "[CLIENT] Minimum zoom level at which underground fluid details are displayed. Zoom starts at 0 and increments linearly."); minZoomLevelForUndergroundFluidDetails = minZoomLevelForUndergroundFluidDetailsProperty.getInt(); - Property uploadBandwidthProperty = configuration.get(Categories.network, "uploadBandwidth", Defaults.uploadBandwidthBytes, - "[CLIENT + SERVER] Limit the bandwidth (in B/s) a client is allowed to transmit when uploading its prospection data." + - " If exceeded, the client will be kicked!"); + Property uploadBandwidthProperty = configuration.get( + Categories.network, + "uploadBandwidth", + Defaults.uploadBandwidthBytes, + "[CLIENT + SERVER] Limit the bandwidth (in B/s) a client is allowed to transmit when uploading its prospection data." + + " If exceeded, the client will be kicked!"); uploadBandwidthBytes = uploadBandwidthProperty.getInt(); uploadPacketsPerSecond = uploadBandwidthBytes / VP.uploadSizePerPacketInBytes; - Property maxTransferCacheSizeMBProperty = configuration.get(Categories.general, "maxTransferCacheSizeMB", - Defaults.maxTransferCacheSizeMB, "[Server] Limit the RAM size in MB of what can players use to" + - " synchronize their map data."); + Property maxTransferCacheSizeMBProperty = configuration.get( + Categories.general, + "maxTransferCacheSizeMB", + Defaults.maxTransferCacheSizeMB, + "[Server] Limit the RAM size in MB of what can players use to" + " synchronize their map data."); maxTransferCacheSizeMB = maxTransferCacheSizeMBProperty.getInt(); - Property recacheVeinsProperty = configuration.get(Categories.general, "recacheVeins", Defaults.recacheVeins, - "[SERVER] Redo GT ore vein caching if set to True. Will automatically be set back to False the next " + - "time the game is started."); + Property recacheVeinsProperty = configuration.get( + Categories.general, + "recacheVeins", + Defaults.recacheVeins, + "[SERVER] Redo GT ore vein caching if set to True. Will automatically be set back to False the next " + + "time the game is started."); recacheVeins = recacheVeinsProperty.getBoolean(); - if(recacheVeins) { + if (recacheVeins) { recacheVeinsProperty.set(false); } - - Property enableVoxelMapWaypointsByDefaultProperty = configuration.get(Categories.integration, "enableVoxelMapWaypointsByDefault", Defaults.enableVoxelMapWaypointsByDefault, - "[CLIENT / VoxelMap] Enable waypoints added by prospecting GT ore veins or underground fluids by default"); + + Property enableVoxelMapWaypointsByDefaultProperty = configuration.get( + Categories.integration, + "enableVoxelMapWaypointsByDefault", + Defaults.enableVoxelMapWaypointsByDefault, + "[CLIENT / VoxelMap] Enable waypoints added by prospecting GT ore veins or underground fluids by default"); enableVoxelMapWaypointsByDefault = enableVoxelMapWaypointsByDefaultProperty.getBoolean(); - Property maxDimensionSizeMBForFastScanningProperty = configuration.get(Categories.caching, "maxDimensionSizeMBForFastScanning", - Defaults.maxDimensionSizeMBForFastScanning, "[Client + Server] Define the maximum size of a " + - "dimension in MB that can be processed in a single pass. Reduce this number if you run into " + - "memory issues during the initial world scan (OutOfMemoryException)."); + Property maxDimensionSizeMBForFastScanningProperty = configuration.get( + Categories.caching, + "maxDimensionSizeMBForFastScanning", + Defaults.maxDimensionSizeMBForFastScanning, + "[Client + Server] Define the maximum size of a " + + "dimension in MB that can be processed in a single pass. Reduce this number if you run into " + + "memory issues during the initial world scan (OutOfMemoryException)."); maxDimensionSizeMBForFastScanning = maxDimensionSizeMBForFastScanningProperty.getInt(); - Property enableDeveloperOverlaysProperty = configuration.get(Categories.general, "enableDeveloperOverlays", - Defaults.enableDeveloperOverlays, "[CLIENT] Enable mod developer overlays, not useful for gameplay"); + Property enableDeveloperOverlaysProperty = configuration.get( + Categories.general, + "enableDeveloperOverlays", + Defaults.enableDeveloperOverlays, + "[CLIENT] Enable mod developer overlays, not useful for gameplay"); enableDeveloperOverlays = enableDeveloperOverlaysProperty.getBoolean(); - if(configuration.hasChanged()) { + if (configuration.hasChanged()) { configuration.save(); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java b/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java index 32d16737..a13192d9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java +++ b/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java @@ -9,11 +9,11 @@ public class ServerTranslations { public static String getEnglishLocalization(Fluid fluid) { - if(MinecraftServer.getServer().isSinglePlayer()) { + if (MinecraftServer.getServer().isSinglePlayer()) { return fluid.getLocalizedName(); } - switch(fluid.getUnlocalizedName()) { + switch (fluid.getUnlocalizedName()) { case "fluid.gas_natural_gas": return "Natural Gas"; case "fluid.liquid_light_oil": @@ -94,7 +94,7 @@ with open("data.dat") as f: print(" return \"" + value + "\";") */ public static String getEnglishLocalization(VeinType veinType) { - if(MinecraftServer.getServer().isSinglePlayer()) { + if (MinecraftServer.getServer().isSinglePlayer()) { return I18n.format(veinType.name); } diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index f5fe456a..33708371 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -3,11 +3,7 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.sinthoras.visualprospecting.hooks.HooksClient; - import cpw.mods.fml.common.Loader; -import net.minecraft.client.Minecraft; -import net.minecraft.launchwrapper.Launch; - import java.io.*; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; @@ -19,6 +15,8 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import net.minecraft.client.Minecraft; +import net.minecraft.launchwrapper.Launch; public class Utils { @@ -45,7 +43,7 @@ public static boolean isJourneyMapInstalled() { public static boolean isXaerosWorldMapInstalled() { return Loader.isModLoaded("XaeroWorldMap"); } - + public static boolean isVoxelMapInstalled() { try { // If a LiteLoader mod is present cannot be checked by calling Loader#isModLoaded. @@ -66,14 +64,13 @@ public static int coordChunkToBlock(int chunkCoord) { } public static long chunkCoordsToKey(int chunkX, int chunkZ) { - return (((long)chunkX) << 32) | (chunkZ & 0xffffffffL); + return (((long) chunkX) << 32) | (chunkZ & 0xffffffffL); } public static int mapToCenterOreChunkCoord(final int chunkCoord) { - if(chunkCoord >= 0) { + if (chunkCoord >= 0) { return chunkCoord - (chunkCoord % 3) + 1; - } - else { + } else { return chunkCoord - (chunkCoord % 3) - 1; } } @@ -91,7 +88,7 @@ public static boolean isSmallOreId(short metaData) { } public static short oreIdToMaterialId(short metaData) { - return (short)(metaData % 1000); + return (short) (metaData % 1000); } public static boolean isLogicalClient() { @@ -99,10 +96,9 @@ public static boolean isLogicalClient() { } public static File getMinecraftDirectory() { - if(isLogicalClient()) { + if (isLogicalClient()) { return Minecraft.getMinecraft().mcDataDir; - } - else { + } else { return new File("."); } } @@ -117,18 +113,16 @@ public static void deleteDirectoryRecursively(final File targetDirectory) { .sorted(Comparator.reverseOrder()) .map(Path::toFile) .forEach(File::delete); - } - catch (IOException e) { + } catch (IOException e) { e.printStackTrace(); } } public static ByteBuffer readFileToBuffer(File file) { - if(file.exists() == false) { + if (file.exists() == false) { return null; } - try - { + try { final FileInputStream inputStream = new FileInputStream(file); final FileChannel inputChannel = inputStream.getChannel(); final ByteBuffer buffer = ByteBuffer.allocate((int) inputChannel.size()); @@ -140,25 +134,23 @@ public static ByteBuffer readFileToBuffer(File file) { inputStream.close(); return buffer; - } - catch (IOException e) { + } catch (IOException e) { e.printStackTrace(); return null; } } public static Map readFileToMap(File file) { - if(file.exists() == false) { + if (file.exists() == false) { return new HashMap<>(); } try { final Gson gson = new Gson(); final Reader reader = Files.newBufferedReader(file.toPath()); - final Map map = gson.fromJson(reader, new TypeToken>() { }.getType()); + final Map map = gson.fromJson(reader, new TypeToken>() {}.getType()); reader.close(); return map; - } - catch (IOException e) { + } catch (IOException e) { e.printStackTrace(); return new HashMap<>(); } @@ -166,22 +158,21 @@ public static Map readFileToMap(File file) { public static void writeMapToFile(File file, Map map) { try { - if(file.exists()) { + if (file.exists()) { file.delete(); } final Gson gson = new Gson(); final Writer writer = Files.newBufferedWriter(file.toPath(), StandardOpenOption.CREATE_NEW); - gson.toJson(map, new TypeToken>() { }.getType(), writer); + gson.toJson(map, new TypeToken>() {}.getType(), writer); writer.close(); - } - catch (IOException e) { + } catch (IOException e) { e.printStackTrace(); } } public static void appendToFile(File file, ByteBuffer byteBuffer) { try { - if(file.exists() == false) { + if (file.exists() == false) { file.createNewFile(); } final FileOutputStream outputStream = new FileOutputStream(file, true); @@ -191,8 +182,7 @@ public static void appendToFile(File file, ByteBuffer byteBuffer) { outputChannel.close(); outputStream.close(); - } - catch (IOException e) { + } catch (IOException e) { e.printStackTrace(); } } @@ -202,7 +192,8 @@ public static Map getDIMFiles(File directory) { final List dimensionIds = Files.walk(directory.toPath(), 1) .filter(Files::isRegularFile) .filter(path -> path.getFileName().toString().startsWith("DIM")) - .map(dimensionFolder -> Integer.parseInt(dimensionFolder.getFileName().toString().substring(3))) + .map(dimensionFolder -> Integer.parseInt( + dimensionFolder.getFileName().toString().substring(3))) .collect(Collectors.toList()); final Map dimensionFiles = new HashMap<>(); for (int dimensionId : dimensionIds) { @@ -213,8 +204,7 @@ public static Map getDIMFiles(File directory) { } return dimensionFiles; - } - catch (IOException e) { + } catch (IOException e) { e.printStackTrace(); return new HashMap<>(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/VP.java b/src/main/java/com/sinthoras/visualprospecting/VP.java index 2a43efa2..ad7d7eb6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VP.java +++ b/src/main/java/com/sinthoras/visualprospecting/VP.java @@ -1,13 +1,11 @@ package com.sinthoras.visualprospecting; +import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; +import java.util.Random; import net.minecraft.client.settings.KeyBinding; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; - -import java.util.Random; - public class VP { public static SimpleNetworkWrapper network; @@ -30,7 +28,6 @@ public class VP { public static final int undergroundFluidChunkProspectingBlockRadius = undergroundFluidSizeChunkX * chunkWidth; public static int uploadSizePerPacketInBytes = 30000; // Larger then 32kB will kick the player! - public static void debug(String message) { VP.LOG.debug(formatMessage(message)); } diff --git a/src/main/java/com/sinthoras/visualprospecting/VPMod.java b/src/main/java/com/sinthoras/visualprospecting/VPMod.java index ac92350c..4490392e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VPMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/VPMod.java @@ -5,11 +5,15 @@ import cpw.mods.fml.common.SidedProxy; import cpw.mods.fml.common.event.*; - -@Mod(modid = Tags.MODID, version = Tags.VERSION, name = Tags.MODNAME, acceptedMinecraftVersions = "[1.7.10]", dependencies = "required-after:spongemixins@[1.1.0,);") +@Mod( + modid = Tags.MODID, + version = Tags.VERSION, + name = Tags.MODNAME, + acceptedMinecraftVersions = "[1.7.10]", + dependencies = "required-after:spongemixins@[1.1.0,);") public class VPMod { - @SidedProxy(clientSide= Tags.GROUPNAME + ".hooks.HooksClient", serverSide= Tags.GROUPNAME + ".hooks.HooksShared") + @SidedProxy(clientSide = Tags.GROUPNAME + ".hooks.HooksClient", serverSide = Tags.GROUPNAME + ".hooks.HooksShared") public static HooksShared proxy; @Mod.EventHandler @@ -17,7 +21,7 @@ public class VPMod { // etc, and register them with the GameRegistry." public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { VP.debug("Registered sided proxy for: " + (Utils.isLogicalClient() ? "Client" : "Dedicated server")); - VP.debug("preInit()"+event.getModMetadata().name); + VP.debug("preInit()" + event.getModMetadata().name); proxy.fmlLifeCycleEvent(event); } diff --git a/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java b/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java index ca80959b..205eb29e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java +++ b/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java @@ -1,5 +1,8 @@ package com.sinthoras.visualprospecting; +import static com.sinthoras.visualprospecting.Utils.isJourneyMapInstalled; +import static com.sinthoras.visualprospecting.Utils.isXaerosWorldMapInstalled; + import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; @@ -16,16 +19,12 @@ import com.sinthoras.visualprospecting.network.ProspectingNotification; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import java.util.Collections; +import java.util.List; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.world.World; -import java.util.Collections; -import java.util.List; - -import static com.sinthoras.visualprospecting.Utils.isJourneyMapInstalled; -import static com.sinthoras.visualprospecting.Utils.isXaerosWorldMapInstalled; - @SuppressWarnings("unused") public class VisualProspecting_API { @@ -44,28 +43,30 @@ public static void registerCustomLayer(LayerManager customLayer) { // Register visualization for logical button in JourneyMap public static void registerJourneyMapButton(LayerButton customButton) { - if(isJourneyMapInstalled()) { + if (isJourneyMapInstalled()) { JourneyMapState.instance.buttons.add(customButton); } } // Register visualization for logical button in Xaero's World Map - public static void registerXaeroMapButton(com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.LayerButton customButton) { - if(isXaerosWorldMapInstalled()) { + public static void registerXaeroMapButton( + com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.LayerButton customButton) { + if (isXaerosWorldMapInstalled()) { XaeroWorldMapState.instance.buttons.add(customButton); } } // Add the JourneyMap renderer for a layer public static void registerJourneyMapRenderer(LayerRenderer customRenderer) { - if(isJourneyMapInstalled()) { + if (isJourneyMapInstalled()) { JourneyMapState.instance.renderers.add(customRenderer); } } // Add the Xaero's World Map renderer for a layer - public static void registerXaeroMapRenderer(com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer customRenderer) { - if(isXaerosWorldMapInstalled()) { + public static void registerXaeroMapRenderer( + com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer customRenderer) { + if (isXaerosWorldMapInstalled()) { XaeroWorldMapState.instance.renderers.add(customRenderer); } } @@ -99,33 +100,39 @@ public static void openJourneyMapForUndergroundFluidsAt(int blockX, int blockZ, } // This mechanic is limited to blocks the player can touch - public static void triggerProspectingForOreBlock(EntityPlayer player, World world, int blockX, int blockY, int blockZ) { + public static void triggerProspectingForOreBlock( + EntityPlayer player, World world, int blockX, int blockY, int blockZ) { ClientCache.instance.onOreInteracted(world, blockX, blockY, blockZ, player); } public static OreVeinPosition getOreVein(int dimensionId, int blockX, int blockZ) { - return ClientCache.instance.getOreVein(dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); + return ClientCache.instance.getOreVein( + dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); } public static UndergroundFluidPosition getUndergroundFluid(int dimensionId, int blockX, int blockZ) { - return ClientCache.instance.getUndergroundFluid(dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); + return ClientCache.instance.getUndergroundFluid( + dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); } public static void setOreVeinDepleted(int dimensionId, int blockX, int blockZ) { - final OreVeinPosition oreVeinPosition = ClientCache.instance.getOreVein(dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); - if(oreVeinPosition.isDepleted() == false) { + final OreVeinPosition oreVeinPosition = ClientCache.instance.getOreVein( + dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); + if (oreVeinPosition.isDepleted() == false) { oreVeinPosition.toggleDepleted(); } ClientCache.instance.putOreVeins(Collections.singletonList(oreVeinPosition)); } public static void toggleOreVeinDepleted(OreVeinPosition oreVeinPosition) { - oreVeinPosition = ClientCache.instance.getOreVein(oreVeinPosition.dimensionId, oreVeinPosition.chunkX, oreVeinPosition.chunkZ); + oreVeinPosition = ClientCache.instance.getOreVein( + oreVeinPosition.dimensionId, oreVeinPosition.chunkX, oreVeinPosition.chunkZ); oreVeinPosition.toggleDepleted(); ClientCache.instance.putOreVeins(Collections.singletonList(oreVeinPosition)); } - public static void putProspectionResults(List oreVeins, List undergroundFluids) { + public static void putProspectionResults( + List oreVeins, List undergroundFluids) { ClientCache.instance.putOreVeins(oreVeins); ClientCache.instance.putUndergroundFluids(undergroundFluids); } @@ -134,33 +141,39 @@ public static void putProspectionResults(List oreVeins, List oreVeins, List undergroundFluids) { + public static void sendProspectionResultsToClient( + EntityPlayerMP player, + List oreVeins, + List undergroundFluids) { // Skip networking if in single player - if(Utils.isLogicalClient()) { + if (Utils.isLogicalClient()) { ClientCache.instance.putOreVeins(oreVeins); ClientCache.instance.putUndergroundFluids(undergroundFluids); - } - else { + } else { VP.network.sendTo(new ProspectingNotification(oreVeins, undergroundFluids), player); } } - public static List prospectOreVeinsWithinRadius(int dimensionId, int blockX, int blockZ, int blockRadius) { + public static List prospectOreVeinsWithinRadius( + int dimensionId, int blockX, int blockZ, int blockRadius) { return ServerCache.instance.prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); } - public static List prospectUndergroundFluidsWithingRadius(World world, int blockX, int blockZ, int blockRadius) { + public static List prospectUndergroundFluidsWithingRadius( + World world, int blockX, int blockZ, int blockRadius) { return ServerCache.instance.prospectUndergroundFluidBlockRadius(world, blockX, blockZ, blockRadius); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index ea7e23f3..7f94d1dd 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -4,6 +4,9 @@ import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; import com.sinthoras.visualprospecting.network.ProspectingRequest; import gregtech.common.blocks.GT_TileEntity_Ores; +import java.io.File; +import java.util.ArrayList; +import java.util.List; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.client.resources.I18n; @@ -15,51 +18,51 @@ import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; -import java.io.File; -import java.util.ArrayList; -import java.util.List; - public class ClientCache extends WorldCache { public static final ClientCache instance = new ClientCache(); protected File getStorageDirectory() { final EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer; - return new File(Utils.getSubDirectory(Tags.CLIENT_DIR), player.getDisplayName() + "_" + player.getPersistentID().toString()); + return new File( + Utils.getSubDirectory(Tags.CLIENT_DIR), + player.getDisplayName() + "_" + player.getPersistentID().toString()); } private void notifyNewOreVein(OreVeinPosition oreVeinPosition) { final String location = "(" + (oreVeinPosition.getBlockX() + 8) + "," + (oreVeinPosition.getBlockZ() + 8) + ")"; - final IChatComponent veinNotification = new ChatComponentTranslation("visualprospecting.vein.prospected", I18n.format(oreVeinPosition.veinType.name), location); + final IChatComponent veinNotification = new ChatComponentTranslation( + "visualprospecting.vein.prospected", I18n.format(oreVeinPosition.veinType.name), location); veinNotification.getChatStyle().setItalic(true); veinNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(veinNotification); final String oreNames = String.join(", ", oreVeinPosition.veinType.getOreMaterialNames()); - final IChatComponent oresNotification = new ChatComponentTranslation("visualprospecting.vein.contents", oreNames); + final IChatComponent oresNotification = + new ChatComponentTranslation("visualprospecting.vein.contents", oreNames); oresNotification.getChatStyle().setItalic(true); oresNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(oresNotification); } public void putOreVeins(List oreVeinPositions) { - if(oreVeinPositions.size() == 1) { + if (oreVeinPositions.size() == 1) { final OreVeinPosition oreVeinPosition = oreVeinPositions.get(0); - if(putOreVein(oreVeinPosition) != DimensionCache.UpdateResult.AlreadyKnown) { + if (putOreVein(oreVeinPosition) != DimensionCache.UpdateResult.AlreadyKnown) { MinecraftForge.EVENT_BUS.post(new ProspectingNotificationEvent.OreVein(oreVeinPosition)); notifyNewOreVein(oreVeinPosition); } - } - else if(oreVeinPositions.size() > 1) { + } else if (oreVeinPositions.size() > 1) { int newOreVeins = 0; - for(OreVeinPosition oreVeinPosition : oreVeinPositions) { - if(putOreVein(oreVeinPosition) != DimensionCache.UpdateResult.AlreadyKnown) { + for (OreVeinPosition oreVeinPosition : oreVeinPositions) { + if (putOreVein(oreVeinPosition) != DimensionCache.UpdateResult.AlreadyKnown) { MinecraftForge.EVENT_BUS.post(new ProspectingNotificationEvent.OreVein(oreVeinPosition)); newOreVeins++; } } - if(newOreVeins > 0) { - final IChatComponent oreVeinNotification = new ChatComponentTranslation("visualprospecting.veins.prospected", newOreVeins); + if (newOreVeins > 0) { + final IChatComponent oreVeinNotification = + new ChatComponentTranslation("visualprospecting.veins.prospected", newOreVeins); oreVeinNotification.getChatStyle().setItalic(true); oreVeinNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(oreVeinNotification); @@ -74,32 +77,37 @@ public void toggleOreVein(int dimensionId, int chunkX, int chunkZ) { public void putUndergroundFluids(List undergroundFluids) { int newUndergroundFluids = 0; int updatedUndergroundFluids = 0; - for(UndergroundFluidPosition undergroundFluidPosition : undergroundFluids) { + for (UndergroundFluidPosition undergroundFluidPosition : undergroundFluids) { DimensionCache.UpdateResult updateResult = putUndergroundFluids(undergroundFluidPosition); - if(updateResult == DimensionCache.UpdateResult.New) { - MinecraftForge.EVENT_BUS.post(new ProspectingNotificationEvent.UndergroundFluid(undergroundFluidPosition)); + if (updateResult == DimensionCache.UpdateResult.New) { + MinecraftForge.EVENT_BUS.post( + new ProspectingNotificationEvent.UndergroundFluid(undergroundFluidPosition)); newUndergroundFluids++; - } - else if(updateResult == DimensionCache.UpdateResult.Updated) { - MinecraftForge.EVENT_BUS.post(new ProspectingNotificationEvent.UndergroundFluid(undergroundFluidPosition)); + } else if (updateResult == DimensionCache.UpdateResult.Updated) { + MinecraftForge.EVENT_BUS.post( + new ProspectingNotificationEvent.UndergroundFluid(undergroundFluidPosition)); updatedUndergroundFluids++; } } - if(newUndergroundFluids > 0 && updatedUndergroundFluids > 0) { - final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation("visualprospecting.undergroundfluid.prospected.newandupdated", newUndergroundFluids, updatedUndergroundFluids); + if (newUndergroundFluids > 0 && updatedUndergroundFluids > 0) { + final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation( + "visualprospecting.undergroundfluid.prospected.newandupdated", + newUndergroundFluids, + updatedUndergroundFluids); undergroundFluidsNotification.getChatStyle().setItalic(true); undergroundFluidsNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); - } - else { - if(newUndergroundFluids > 0) { - final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation("visualprospecting.undergroundfluid.prospected.onlynew", newUndergroundFluids); + } else { + if (newUndergroundFluids > 0) { + final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation( + "visualprospecting.undergroundfluid.prospected.onlynew", newUndergroundFluids); undergroundFluidsNotification.getChatStyle().setItalic(true); undergroundFluidsNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); } - if(updatedUndergroundFluids > 0) { - final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation("visualprospecting.undergroundfluid.prospected.onlyupdated", updatedUndergroundFluids); + if (updatedUndergroundFluids > 0) { + final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation( + "visualprospecting.undergroundfluid.prospected.onlyupdated", updatedUndergroundFluids); undergroundFluidsNotification.getChatStyle().setItalic(true); undergroundFluidsNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); @@ -108,19 +116,19 @@ else if(updateResult == DimensionCache.UpdateResult.Updated) { } public void onOreInteracted(World world, int blockX, int blockY, int blockZ, EntityPlayer entityPlayer) { - if(world.isRemote && Config.enableProspecting - && Minecraft.getMinecraft().thePlayer == entityPlayer) { + if (world.isRemote && Config.enableProspecting && Minecraft.getMinecraft().thePlayer == entityPlayer) { final TileEntity tTileEntity = world.getTileEntity(blockX, blockY, blockZ); if (tTileEntity instanceof GT_TileEntity_Ores) { final short oreMetaData = ((GT_TileEntity_Ores) tTileEntity).mMetaData; - if (Utils.isSmallOreId(oreMetaData) == false - && oreMetaData != 0) { + if (Utils.isSmallOreId(oreMetaData) == false && oreMetaData != 0) { final int chunkX = Utils.coordBlockToChunk(blockX); final int chunkZ = Utils.coordBlockToChunk(blockZ); final OreVeinPosition oreVeinPosition = getOreVein(entityPlayer.dimension, chunkX, chunkZ); final short materialId = Utils.oreIdToMaterialId(oreMetaData); - if(oreVeinPosition.veinType.containsOre(materialId) == false && ProspectingRequest.canSendRequest()) { - VP.network.sendToServer(new ProspectingRequest(entityPlayer.dimension, blockX, blockY, blockZ, materialId)); + if (oreVeinPosition.veinType.containsOre(materialId) == false + && ProspectingRequest.canSendRequest()) { + VP.network.sendToServer( + new ProspectingRequest(entityPlayer.dimension, blockX, blockY, blockZ, materialId)); } } } @@ -137,7 +145,7 @@ public void resetPlayerProgression() { public List getAllOreVeins() { List allOreVeins = new ArrayList<>(); - for(DimensionCache dimension : dimensions.values()) { + for (DimensionCache dimension : dimensions.values()) { allOreVeins.addAll(dimension.getAllOreVeins()); } return allOreVeins; @@ -145,7 +153,7 @@ public List getAllOreVeins() { public List getAllUndergroundFluids() { List allUndergroundFluids = new ArrayList<>(); - for(DimensionCache dimension : dimensions.values()) { + for (DimensionCache dimension : dimensions.values()) { allUndergroundFluids.addAll(dimension.getAllUndergroundFluids()); } return allUndergroundFluids; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index 71d2ed1a..ee617905 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -1,16 +1,15 @@ package com.sinthoras.visualprospecting.database; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import java.nio.ByteBuffer; +import java.util.*; import net.minecraft.world.ChunkCoordIntPair; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; -import java.nio.ByteBuffer; -import java.util.*; - public class DimensionCache { public enum UpdateResult { @@ -30,13 +29,14 @@ public DimensionCache(int dimensionId) { } public ByteBuffer saveOreChunks() { - if(changedOrNewOreChunks.isEmpty() == false) { - final ByteBuffer byteBuffer = ByteBuffer.allocate(changedOrNewOreChunks.size() * (2 * Integer.BYTES + Short.BYTES)); + if (changedOrNewOreChunks.isEmpty() == false) { + final ByteBuffer byteBuffer = + ByteBuffer.allocate(changedOrNewOreChunks.size() * (2 * Integer.BYTES + Short.BYTES)); changedOrNewOreChunks.stream().map(oreChunks::get).forEach(oreVeinPosition -> { byteBuffer.putInt(oreVeinPosition.chunkX); byteBuffer.putInt(oreVeinPosition.chunkZ); short veinTypeId = VeinTypeCaching.getVeinTypeId(oreVeinPosition.veinType); - if(oreVeinPosition.isDepleted()) { + if (oreVeinPosition.isDepleted()) { veinTypeId |= 0x8000; } byteBuffer.putShort(veinTypeId); @@ -49,13 +49,15 @@ public ByteBuffer saveOreChunks() { } public ByteBuffer saveUndergroundFluids() { - if(changedOrNewUndergroundFluids.isEmpty() == false) { - final ByteBuffer byteBuffer = ByteBuffer.allocate(changedOrNewUndergroundFluids.size() * (Long.BYTES + Integer.BYTES * (1 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ))); + if (changedOrNewUndergroundFluids.isEmpty() == false) { + final ByteBuffer byteBuffer = ByteBuffer.allocate(changedOrNewUndergroundFluids.size() + * (Long.BYTES + + Integer.BYTES * (1 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ))); changedOrNewUndergroundFluids.stream().map(undergroundFluids::get).forEach(undergroundFluidPosition -> { byteBuffer.putInt(undergroundFluidPosition.chunkX); byteBuffer.putInt(undergroundFluidPosition.chunkZ); byteBuffer.putInt(undergroundFluidPosition.fluid.getID()); - for(int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { + for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { byteBuffer.putInt(undergroundFluidPosition.chunks[offsetChunkX][offsetChunkZ]); } @@ -69,28 +71,33 @@ public ByteBuffer saveUndergroundFluids() { } public void loadCache(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBuffer) { - if(oreChunksBuffer != null) { + if (oreChunksBuffer != null) { while (oreChunksBuffer.remaining() >= Integer.BYTES * 2 + Short.BYTES) { final int chunkX = oreChunksBuffer.getInt(); final int chunkZ = oreChunksBuffer.getInt(); final short veinTypeId = oreChunksBuffer.getShort(); final boolean depleted = (veinTypeId & 0x8000) > 0; - final VeinType veinType = VeinTypeCaching.getVeinType((short)(veinTypeId & 0x7FFF)); - oreChunks.put(getOreVeinKey(chunkX, chunkZ), new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); + final VeinType veinType = VeinTypeCaching.getVeinType((short) (veinTypeId & 0x7FFF)); + oreChunks.put( + getOreVeinKey(chunkX, chunkZ), + new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); } } - if(undergroundFluidsBuffer != null) { - while (undergroundFluidsBuffer.remaining() >= Integer.BYTES * (3 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ)) { + if (undergroundFluidsBuffer != null) { + while (undergroundFluidsBuffer.remaining() + >= Integer.BYTES * (3 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ)) { final int chunkX = undergroundFluidsBuffer.getInt(); final int chunkZ = undergroundFluidsBuffer.getInt(); final Fluid fluid = FluidRegistry.getFluid(undergroundFluidsBuffer.getInt()); final int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; - for(int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { + for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { chunks[offsetChunkX][offsetChunkZ] = undergroundFluidsBuffer.getInt(); } } - undergroundFluids.put(getUndergroundFluidKey(chunkX, chunkZ), new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); + undergroundFluids.put( + getUndergroundFluidKey(chunkX, chunkZ), + new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); } } } @@ -101,13 +108,13 @@ private ChunkCoordIntPair getOreVeinKey(int chunkX, int chunkZ) { public UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) { final ChunkCoordIntPair key = getOreVeinKey(oreVeinPosition.chunkX, oreVeinPosition.chunkZ); - if(oreChunks.containsKey(key) == false) { + if (oreChunks.containsKey(key) == false) { oreChunks.put(key, oreVeinPosition); changedOrNewOreChunks.add(key); return UpdateResult.New; } final OreVeinPosition storedOreVeinPosition = oreChunks.get(key); - if(storedOreVeinPosition.veinType != oreVeinPosition.veinType) { + if (storedOreVeinPosition.veinType != oreVeinPosition.veinType) { oreChunks.put(key, oreVeinPosition.joinDepletedState(storedOreVeinPosition)); changedOrNewOreChunks.add(key); return UpdateResult.New; @@ -117,7 +124,7 @@ public UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) { public void toggleOreVein(int chunkX, int chunkZ) { final ChunkCoordIntPair key = getOreVeinKey(chunkX, chunkZ); - if(oreChunks.containsKey(key)) { + if (oreChunks.containsKey(key)) { oreChunks.get(key).toggleDepleted(); changedOrNewOreChunks.add(key); } @@ -129,17 +136,18 @@ public OreVeinPosition getOreVein(int chunkX, int chunkZ) { } private ChunkCoordIntPair getUndergroundFluidKey(int chunkX, int chunkZ) { - return new ChunkCoordIntPair(Utils.mapToCornerUndergroundFluidChunkCoord(chunkX), Utils.mapToCornerUndergroundFluidChunkCoord(chunkZ)); + return new ChunkCoordIntPair( + Utils.mapToCornerUndergroundFluidChunkCoord(chunkX), + Utils.mapToCornerUndergroundFluidChunkCoord(chunkZ)); } public UpdateResult putUndergroundFluid(final UndergroundFluidPosition undergroundFluid) { final ChunkCoordIntPair key = getUndergroundFluidKey(undergroundFluid.chunkX, undergroundFluid.chunkZ); - if(undergroundFluids.containsKey(key) == false) { + if (undergroundFluids.containsKey(key) == false) { changedOrNewUndergroundFluids.add(key); undergroundFluids.put(key, undergroundFluid); return UpdateResult.New; - } - else if(undergroundFluids.get(key).equals(undergroundFluid) == false) { + } else if (undergroundFluids.get(key).equals(undergroundFluid) == false) { changedOrNewUndergroundFluids.add(key); undergroundFluids.put(key, undergroundFluid); return UpdateResult.Updated; @@ -149,7 +157,8 @@ else if(undergroundFluids.get(key).equals(undergroundFluid) == false) { public UndergroundFluidPosition getUndergroundFluid(int chunkX, int chunkZ) { final ChunkCoordIntPair key = getUndergroundFluidKey(chunkX, chunkZ); - return undergroundFluids.getOrDefault(key, UndergroundFluidPosition.getNotProspected(dimensionId, chunkX, chunkZ)); + return undergroundFluids.getOrDefault( + key, UndergroundFluidPosition.getNotProspected(dimensionId, chunkX, chunkZ)); } public Collection getAllOreVeins() { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java index 3c03a14a..57d3493d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java @@ -3,6 +3,9 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; import cpw.mods.fml.server.FMLServerHandler; +import java.io.IOException; +import java.util.Objects; +import java.util.zip.DataFormatException; import net.minecraft.command.CommandBase; import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayerMP; @@ -11,10 +14,6 @@ import net.minecraft.util.IChatComponent; import net.minecraft.util.StatCollector; -import java.io.IOException; -import java.util.Objects; -import java.util.zip.DataFormatException; - public class RedoServerCacheCommand extends CommandBase { @Override @@ -44,7 +43,8 @@ public void processCommand(ICommandSender sender, String[] parameters) { start.getChatStyle().setItalic(true); sender.addChatMessage(start); try { - WorldAnalysis world = new WorldAnalysis(server.getEntityWorld().getSaveHandler().getWorldDirectory()); + WorldAnalysis world = + new WorldAnalysis(server.getEntityWorld().getSaveHandler().getWorldDirectory()); world.cacheVeins(); } catch (IOException | DataFormatException e) { VP.info("Could not load world save files to build vein cache!"); @@ -53,7 +53,8 @@ public void processCommand(ICommandSender sender, String[] parameters) { failure.getChatStyle().setItalic(true); sender.addChatMessage(failure); } - final IChatComponent confirmation = new ChatComponentTranslation("visualprospecting.redoservercache.confirmation"); + final IChatComponent confirmation = + new ChatComponentTranslation("visualprospecting.redoservercache.confirmation"); confirmation.getChatStyle().setItalic(true); sender.addChatMessage(confirmation); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java index 2d581bbb..49fa9ee2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java @@ -21,7 +21,8 @@ public String getCommandUsage(ICommandSender sender) { @Override public void processCommand(ICommandSender sender, String[] parameters) { ClientCache.instance.resetPlayerProgression(); - final IChatComponent confirmation = new ChatComponentTranslation("visualprospecting.resetprogress.confirmation"); + final IChatComponent confirmation = + new ChatComponentTranslation("visualprospecting.resetprogress.confirmation"); confirmation.getChatStyle().setItalic(true); sender.addChatMessage(confirmation); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java index 3378b5dd..7b011f7a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java @@ -1,18 +1,17 @@ package com.sinthoras.visualprospecting.database; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import com.sinthoras.visualprospecting.integration.gregtech.UndergroundFluidsWrapper; -import net.minecraft.world.World; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidStack; - import java.io.File; import java.util.ArrayList; import java.util.List; +import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; public class ServerCache extends WorldCache { @@ -23,7 +22,7 @@ protected File getStorageDirectory() { } public synchronized void notifyOreVeinGeneration(int dimensionId, int chunkX, int chunkZ, final VeinType veinType) { - if(veinType != VeinType.NO_VEIN) { + if (veinType != VeinType.NO_VEIN) { super.putOreVein(new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType)); } } @@ -32,14 +31,15 @@ public void notifyOreVeinGeneration(int dimensionId, int chunkX, int chunkZ, fin notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, VeinTypeCaching.getVeinType(veinName)); } - public List prospectOreChunks(int dimensionId, int minChunkX, int minChunkZ, int maxChunkX, int maxChunkZ) { + public List prospectOreChunks( + int dimensionId, int minChunkX, int minChunkZ, int maxChunkX, int maxChunkZ) { minChunkX = Utils.mapToCenterOreChunkCoord(minChunkX); minChunkZ = Utils.mapToCenterOreChunkCoord(minChunkZ); maxChunkX = Utils.mapToCenterOreChunkCoord(maxChunkX); maxChunkZ = Utils.mapToCenterOreChunkCoord(maxChunkZ); List oreVeinPositions = new ArrayList<>(); - for(int chunkX = minChunkX; chunkX <= maxChunkX; chunkX = Utils.mapToCenterOreChunkCoord(chunkX + 3)) { + for (int chunkX = minChunkX; chunkX <= maxChunkX; chunkX = Utils.mapToCenterOreChunkCoord(chunkX + 3)) { for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; chunkZ = Utils.mapToCenterOreChunkCoord(chunkZ + 3)) { final OreVeinPosition oreVeinPosition = getOreVein(dimensionId, chunkX, chunkZ); if (oreVeinPosition.veinType != VeinType.NO_VEIN) { @@ -50,8 +50,10 @@ public List prospectOreChunks(int dimensionId, int minChunkX, i return oreVeinPositions; } - public List prospectOreBlocks(int dimensionId, int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - return prospectOreChunks(dimensionId, + public List prospectOreBlocks( + int dimensionId, int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + return prospectOreChunks( + dimensionId, Utils.coordBlockToChunk(minBlockX), Utils.coordBlockToChunk(minBlockZ), Utils.coordBlockToChunk(maxBlockX), @@ -59,19 +61,26 @@ public List prospectOreBlocks(int dimensionId, int minBlockX, i } public List prospectOreBlockRadius(int dimensionId, int blockX, int blockZ, int blockRadius) { - return prospectOreBlocks(dimensionId, blockX - blockRadius, blockZ - blockRadius, blockX + blockRadius, blockZ + blockRadius); + return prospectOreBlocks( + dimensionId, blockX - blockRadius, blockZ - blockRadius, blockX + blockRadius, blockZ + blockRadius); } - public List prospectUndergroundFluidBlockRadius(World world, int blockX, int blockZ, int undergroundFluidBlockRadius) { - final int minChunkX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(blockX - undergroundFluidBlockRadius)); - final int minChunkZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(blockZ - undergroundFluidBlockRadius)); + public List prospectUndergroundFluidBlockRadius( + World world, int blockX, int blockZ, int undergroundFluidBlockRadius) { + final int minChunkX = Utils.mapToCornerUndergroundFluidChunkCoord( + Utils.coordBlockToChunk(blockX - undergroundFluidBlockRadius)); + final int minChunkZ = Utils.mapToCornerUndergroundFluidChunkCoord( + Utils.coordBlockToChunk(blockZ - undergroundFluidBlockRadius)); // Equals to ceil(undergroundFluidBlockRadius / (VP.undergroundFluidFieldSizeChunkX * VP.chunkWidth)) - final int undergroundFluidRadius = (undergroundFluidBlockRadius + VP.undergroundFluidSizeChunkX * VP.chunkWidth - 1) / (VP.undergroundFluidSizeChunkX * VP.chunkWidth); + final int undergroundFluidRadius = + (undergroundFluidBlockRadius + VP.undergroundFluidSizeChunkX * VP.chunkWidth - 1) + / (VP.undergroundFluidSizeChunkX * VP.chunkWidth); - List foundUndergroundFluids = new ArrayList<>((2 * undergroundFluidRadius + 1) * (2 * undergroundFluidRadius + 1)); + List foundUndergroundFluids = + new ArrayList<>((2 * undergroundFluidRadius + 1) * (2 * undergroundFluidRadius + 1)); - for(int undergroundFluidX = 0; undergroundFluidX < 2 * undergroundFluidRadius + 1; undergroundFluidX++) { + for (int undergroundFluidX = 0; undergroundFluidX < 2 * undergroundFluidRadius + 1; undergroundFluidX++) { for (int undergroundFluidZ = 0; undergroundFluidZ < 2 * undergroundFluidRadius + 1; undergroundFluidZ++) { final int chunkX = minChunkX + undergroundFluidX * VP.undergroundFluidSizeChunkX; final int chunkZ = minChunkZ + undergroundFluidZ * VP.undergroundFluidSizeChunkZ; @@ -79,7 +88,8 @@ public List prospectUndergroundFluidBlockRadius(World Fluid fluid = null; for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - final FluidStack prospectedFluid = UndergroundFluidsWrapper.prospectFluid(world, chunkX + offsetChunkX, chunkZ + offsetChunkZ); + final FluidStack prospectedFluid = UndergroundFluidsWrapper.prospectFluid( + world, chunkX + offsetChunkX, chunkZ + offsetChunkZ); if (prospectedFluid != null) { fluid = prospectedFluid.getFluid(); chunks[offsetChunkX][offsetChunkZ] = prospectedFluid.amount; @@ -87,7 +97,8 @@ public List prospectUndergroundFluidBlockRadius(World } } if (fluid != null) { - foundUndergroundFluids.add(new UndergroundFluidPosition(world.provider.dimensionId, chunkX, chunkZ, fluid, chunks)); + foundUndergroundFluids.add( + new UndergroundFluidPosition(world.provider.dimensionId, chunkX, chunkZ, fluid, chunks)); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java b/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java index 4b1ee12e..92eeced1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java @@ -1,7 +1,6 @@ package com.sinthoras.visualprospecting.database; import com.sinthoras.visualprospecting.Config; - import java.util.*; public class TransferCache { @@ -12,15 +11,18 @@ public class TransferCache { private final Map> sharedUndergroundFluids = new HashMap<>(); private final Queue timestamp = new LinkedList<>(); - public void addClientProspectionData(String uuid, List oreVeins, List undergroundFluids) { + public void addClientProspectionData( + String uuid, List oreVeins, List undergroundFluids) { sharedOreVeins.remove(uuid); sharedUndergroundFluids.remove(uuid); timestamp.remove(uuid); - final int oreVeinPositionSizeInRam = OreVeinPosition.getMaxBytes() + 3 * Byte.BYTES; // JVM represents everything aligned at 4 bytes - final int newEntryBytes = oreVeins.size() * oreVeinPositionSizeInRam + undergroundFluids.size() * UndergroundFluidPosition.BYTES; + final int oreVeinPositionSizeInRam = + OreVeinPosition.getMaxBytes() + 3 * Byte.BYTES; // JVM represents everything aligned at 4 bytes + final int newEntryBytes = + oreVeins.size() * oreVeinPositionSizeInRam + undergroundFluids.size() * UndergroundFluidPosition.BYTES; - while(getUsedMemory() > (Config.maxTransferCacheSizeMB << 20) - newEntryBytes + while (getUsedMemory() > (Config.maxTransferCacheSizeMB << 20) - newEntryBytes && timestamp.isEmpty() == false) { String oldestUUID = timestamp.remove(); sharedOreVeins.remove(oldestUUID); @@ -45,8 +47,13 @@ public List getSharedUndergroundFluidsFrom(String uuid } private int getUsedMemory() { - final int oreVeinPositionSizeInRam = OreVeinPosition.getMaxBytes() + 3 * Byte.BYTES; // JVM represents everything aligned at 4 bytes - return sharedOreVeins.values().stream().mapToInt(oreVeins -> oreVeins.size() * oreVeinPositionSizeInRam).sum() - + sharedUndergroundFluids.values().stream().mapToInt(undergroundFluids -> undergroundFluids.size() * UndergroundFluidPosition.BYTES).sum(); + final int oreVeinPositionSizeInRam = + OreVeinPosition.getMaxBytes() + 3 * Byte.BYTES; // JVM represents everything aligned at 4 bytes + return sharedOreVeins.values().stream() + .mapToInt(oreVeins -> oreVeins.size() * oreVeinPositionSizeInRam) + .sum() + + sharedUndergroundFluids.values().stream() + .mapToInt(undergroundFluids -> undergroundFluids.size() * UndergroundFluidPosition.BYTES) + .sum(); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java b/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java index a7b1212c..4060c3f7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java @@ -2,13 +2,13 @@ import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; -import net.minecraftforge.fluids.Fluid; - import java.util.Arrays; +import net.minecraftforge.fluids.Fluid; public class UndergroundFluidPosition { - public static final int BYTES = (3 + 1 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ) * Integer.BYTES; + public static final int BYTES = + (3 + 1 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ) * Integer.BYTES; public final int dimensionId; public final int chunkX; @@ -38,7 +38,7 @@ public int getBlockZ() { public int getMinProduction() { int smallest = Integer.MAX_VALUE; - for(int chunkX = 0; chunkX < VP.undergroundFluidSizeChunkX; chunkX++) { + for (int chunkX = 0; chunkX < VP.undergroundFluidSizeChunkX; chunkX++) { for (int chunkZ = 0; chunkZ < VP.undergroundFluidSizeChunkZ; chunkZ++) { if (chunks[chunkX][chunkZ] < smallest) { smallest = chunks[chunkX][chunkZ]; @@ -50,7 +50,7 @@ public int getMinProduction() { public int getMaxProduction() { int largest = Integer.MIN_VALUE; - for(int chunkX = 0; chunkX < VP.undergroundFluidSizeChunkX; chunkX++) { + for (int chunkX = 0; chunkX < VP.undergroundFluidSizeChunkX; chunkX++) { for (int chunkZ = 0; chunkZ < VP.undergroundFluidSizeChunkZ; chunkZ++) { if (chunks[chunkX][chunkZ] > largest) { largest = chunks[chunkX][chunkZ]; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index 464a4a38..7791cfea 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -3,7 +3,6 @@ import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.veintypes.VeinType; - import java.io.File; import java.nio.ByteBuffer; import java.util.HashMap; @@ -22,7 +21,7 @@ public abstract class WorldCache { protected abstract File getStorageDirectory(); public boolean loadVeinCache(String worldId) { - if(isLoaded ) { + if (isLoaded) { return true; } isLoaded = true; @@ -32,32 +31,37 @@ public boolean loadVeinCache(String worldId) { oreVeinCacheDirectory.mkdirs(); undergroundFluidCacheDirectory.mkdirs(); final Map oreVeinDimensionBuffers = Utils.getDIMFiles(oreVeinCacheDirectory); - final Map undergroundFluidDimensionBuffers = Utils.getDIMFiles(undergroundFluidCacheDirectory); + final Map undergroundFluidDimensionBuffers = + Utils.getDIMFiles(undergroundFluidCacheDirectory); final Set dimensionsIds = new HashSet<>(); dimensionsIds.addAll(oreVeinDimensionBuffers.keySet()); dimensionsIds.addAll(undergroundFluidDimensionBuffers.keySet()); - if(dimensionsIds.isEmpty()) { + if (dimensionsIds.isEmpty()) { return false; } - for(int dimensionId : dimensionsIds) { + for (int dimensionId : dimensionsIds) { final DimensionCache dimension = new DimensionCache(dimensionId); - dimension.loadCache(oreVeinDimensionBuffers.get(dimensionId), undergroundFluidDimensionBuffers.get(dimensionId)); + dimension.loadCache( + oreVeinDimensionBuffers.get(dimensionId), undergroundFluidDimensionBuffers.get(dimensionId)); dimensions.put(dimensionId, dimension); } return true; } public void saveVeinCache() { - if(needsSaving) { + if (needsSaving) { for (DimensionCache dimension : dimensions.values()) { final ByteBuffer oreVeinBuffer = dimension.saveOreChunks(); if (oreVeinBuffer != null) { - Utils.appendToFile(new File(oreVeinCacheDirectory.toPath() + "/DIM" + dimension.dimensionId), oreVeinBuffer); + Utils.appendToFile( + new File(oreVeinCacheDirectory.toPath() + "/DIM" + dimension.dimensionId), oreVeinBuffer); } final ByteBuffer undergroundFluidBuffer = dimension.saveUndergroundFluids(); - if(undergroundFluidBuffer != null) { - Utils.appendToFile(new File(undergroundFluidCacheDirectory.toPath() + "/DIM" + dimension.dimensionId), undergroundFluidBuffer); + if (undergroundFluidBuffer != null) { + Utils.appendToFile( + new File(undergroundFluidCacheDirectory.toPath() + "/DIM" + dimension.dimensionId), + undergroundFluidBuffer); } } needsSaving = false; @@ -77,7 +81,7 @@ private DimensionCache.UpdateResult updateSaveFlag(DimensionCache.UpdateResult u protected DimensionCache.UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) { DimensionCache dimension = dimensions.get(oreVeinPosition.dimensionId); - if(dimension == null) { + if (dimension == null) { dimension = new DimensionCache(oreVeinPosition.dimensionId); dimensions.put(oreVeinPosition.dimensionId, dimension); } @@ -86,7 +90,7 @@ protected DimensionCache.UpdateResult putOreVein(final OreVeinPosition oreVeinPo protected void toggleOreVein(int dimensionId, int chunkX, int chunkZ) { DimensionCache dimension = dimensions.get(dimensionId); - if(dimension != null) { + if (dimension != null) { dimension.toggleOreVein(chunkX, chunkZ); } needsSaving = true; @@ -94,7 +98,7 @@ protected void toggleOreVein(int dimensionId, int chunkX, int chunkZ) { public OreVeinPosition getOreVein(int dimensionId, int chunkX, int chunkZ) { DimensionCache dimension = dimensions.get(dimensionId); - if(dimension == null) { + if (dimension == null) { return new OreVeinPosition(dimensionId, chunkX, chunkZ, VeinType.NO_VEIN, true); } return dimension.getOreVein(chunkX, chunkZ); @@ -102,7 +106,7 @@ public OreVeinPosition getOreVein(int dimensionId, int chunkX, int chunkZ) { protected DimensionCache.UpdateResult putUndergroundFluids(final UndergroundFluidPosition undergroundFluid) { DimensionCache dimension = dimensions.get(undergroundFluid.dimensionId); - if(dimension == null) { + if (dimension == null) { dimension = new DimensionCache(undergroundFluid.dimensionId); dimensions.put(undergroundFluid.dimensionId, dimension); } @@ -111,7 +115,7 @@ protected DimensionCache.UpdateResult putUndergroundFluids(final UndergroundFlui public UndergroundFluidPosition getUndergroundFluid(int dimensionId, int chunkX, int chunkZ) { DimensionCache dimension = dimensions.get(dimensionId); - if(dimension == null) { + if (dimension == null) { return UndergroundFluidPosition.getNotProspected(dimensionId, chunkX, chunkZ); } return dimension.getUndergroundFluid(chunkX, chunkZ); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldIdHandler.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldIdHandler.java index e020d9b6..d5b03a2a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldIdHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldIdHandler.java @@ -1,12 +1,11 @@ package com.sinthoras.visualprospecting.database; import com.sinthoras.visualprospecting.Tags; +import java.util.UUID; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.WorldSavedData; import net.minecraft.world.WorldServer; -import java.util.UUID; - public class WorldIdHandler extends WorldSavedData { private static WorldIdHandler instance; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java index bd5c4ea0..651e34ee 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java @@ -3,10 +3,9 @@ import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; -import net.minecraft.server.MinecraftServer; - import java.io.File; import java.text.DecimalFormat; +import net.minecraft.server.MinecraftServer; public class AnalysisProgressTracker { @@ -32,7 +31,7 @@ public static synchronized void dimensionProcessed() { public static synchronized void announceFastDimension(int dimensionId) { final String message = "Processing dimension with id " + dimensionId + " with fast scanning."; VP.info(message); - if(Utils.isLogicalClient()) { + if (Utils.isLogicalClient()) { MinecraftServer.getServer().userMessage = message; } } @@ -40,7 +39,7 @@ public static synchronized void announceFastDimension(int dimensionId) { public static synchronized void announceSlowDimension(int dimensionId) { final String message = "Processing dimension with id " + dimensionId + " with slow (safe) scanning."; VP.info(message); - if(Utils.isLogicalClient()) { + if (Utils.isLogicalClient()) { MinecraftServer.getServer().userMessage = message; } } @@ -58,16 +57,15 @@ public static synchronized void regionFileProcessed() { private static synchronized void updateLog() { long timestamp = System.currentTimeMillis(); - if(timestamp - (Config.cacheGenerationLogUpdateMinTime * 1000) > lastLogUpdate) { + if (timestamp - (Config.cacheGenerationLogUpdateMinTime * 1000) > lastLogUpdate) { lastLogUpdate = timestamp; final String message = "Caching GT ore generation meta data - Dimension (" + (dimensionsProcessed + 1) + "/" + numberOfDimensions + ") " + (numberOfRegionFiles == 0 ? 0 : ((regionFilesProcessed * 100) / numberOfRegionFiles)) + "%"; VP.info(message); - if(Utils.isLogicalClient()) { - MinecraftServer.getServer().userMessage = message + "%"; // Escape % for String.format + if (Utils.isLogicalClient()) { + MinecraftServer.getServer().userMessage = message + "%"; // Escape % for String.format } - } } @@ -76,9 +74,10 @@ public static synchronized void processingFinished() { DecimalFormat format = new DecimalFormat(); format.setMinimumFractionDigits(1); format.setMaximumFractionDigits(1); - final String message = "Parsing complete! Thank you for your patience. - Duration: " + format.format(elapsedTimeMS / 1000) + "sec"; + final String message = "Parsing complete! Thank you for your patience. - Duration: " + + format.format(elapsedTimeMS / 1000) + "sec"; VP.info(message); - if(Utils.isLogicalClient()) { + if (Utils.isLogicalClient()) { MinecraftServer.getServer().userMessage = message; } } @@ -86,7 +85,7 @@ public static synchronized void processingFinished() { public static synchronized void notifyCorruptFile(File regionFile) { final String message = "Encountered corrupt/malformed/modified save file: " + regionFile; VP.info(message); - if(Utils.isLogicalClient()) { + if (Utils.isLogicalClient()) { MinecraftServer.getServer().userMessage = message; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java index 006c6fa6..a97d9494 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java @@ -4,7 +4,6 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import io.xol.enklume.nbt.*; - import java.util.HashSet; import java.util.Set; @@ -18,9 +17,9 @@ public class ChunkAnalysis { public void processMinecraftChunk(final NBTCompound chunkRoot) { for (final NBTNamed tileEntity : ((NBTList) chunkRoot.getTag("Level.TileEntities")).elements) { final GregTechOre gtOre = new GregTechOre((NBTCompound) tileEntity); - if(gtOre.isValidGTOre) { + if (gtOre.isValidGTOre) { ores.add(gtOre.metaData); - if(minVeinBlockY > gtOre.blockY) { + if (minVeinBlockY > gtOre.blockY) { minVeinBlockY = gtOre.blockY; } } @@ -28,8 +27,8 @@ public void processMinecraftChunk(final NBTCompound chunkRoot) { } public boolean matchesSingleVein() { - for(VeinType veinType : VeinTypeCaching.veinTypes) { - if(veinType.matches(ores)) { + for (VeinType veinType : VeinTypeCaching.veinTypes) { + if (veinType.matches(ores)) { matchedVeins.add(veinType); } } @@ -38,7 +37,7 @@ public boolean matchesSingleVein() { // Result only valid if matchesSingleVein() returned true public VeinType getMatchedVein() { - if(matchedVeins.isEmpty()) { + if (matchedVeins.isEmpty()) { return VeinType.NO_VEIN; } return matchedVeins.stream().findAny().get(); @@ -47,4 +46,4 @@ public VeinType getMatchedVein() { public int getVeinBlockY() { return minVeinBlockY; } -} \ No newline at end of file +} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index 835bd041..f20207fb 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -1,13 +1,12 @@ package com.sinthoras.visualprospecting.database.cachebuilder; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import io.xol.enklume.nbt.*; - import java.util.*; import java.util.stream.IntStream; @@ -29,11 +28,11 @@ public DetailedChunkAnalysis(int dimensionId, int chunkX, int chunkZ) { public void processMinecraftChunk(final NBTCompound chunkRoot) { for (final NBTNamed tileEntity : ((NBTList) chunkRoot.getTag("Level.TileEntities")).elements) { final GregTechOre gtOre = new GregTechOre((NBTCompound) tileEntity); - if(gtOre.isValidGTOre) { - if(oresPerY[gtOre.blockY] == null) { + if (gtOre.isValidGTOre) { + if (oresPerY[gtOre.blockY] == null) { oresPerY[gtOre.blockY] = new HashMap<>(); } - if(oresPerY[gtOre.blockY].containsKey(gtOre.metaData) == false) { + if (oresPerY[gtOre.blockY].containsKey(gtOre.metaData) == false) { oresPerY[gtOre.blockY].put(gtOre.metaData, 0); } oresPerY[gtOre.blockY].put(gtOre.metaData, oresPerY[gtOre.blockY].get(gtOre.metaData) + 1); @@ -43,40 +42,67 @@ public void processMinecraftChunk(final NBTCompound chunkRoot) { public void cleanUpWithNeighbors(final Map veinChunkY) { final OreVeinPosition[] neighbors = new OreVeinPosition[] { - ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ + 3), - ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ + 3), - ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ + 3), - ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ), - ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ - 3), - ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ - 3), - ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ - 3), - ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ) + ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ + 3), + ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ + 3), + ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ + 3), + ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ), + ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ - 3), + ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ - 3), + ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ - 3), + ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ) }; final int[] neighborVeinBlockY = new int[] { - veinChunkY.getOrDefault(Utils.chunkCoordsToKey(Utils.mapToCenterOreChunkCoord(chunkX - 3), Utils.mapToCenterOreChunkCoord(chunkZ + 3)), 0), - veinChunkY.getOrDefault(Utils.chunkCoordsToKey(Utils.mapToCenterOreChunkCoord(chunkX), Utils.mapToCenterOreChunkCoord(chunkZ + 3)), 0), - veinChunkY.getOrDefault(Utils.chunkCoordsToKey(Utils.mapToCenterOreChunkCoord(chunkX + 3), Utils.mapToCenterOreChunkCoord(chunkZ + 3)), 0), - veinChunkY.getOrDefault(Utils.chunkCoordsToKey(Utils.mapToCenterOreChunkCoord(chunkX + 3), Utils.mapToCenterOreChunkCoord(chunkZ)), 0), - veinChunkY.getOrDefault(Utils.chunkCoordsToKey(Utils.mapToCenterOreChunkCoord(chunkX + 3), Utils.mapToCenterOreChunkCoord(chunkZ - 3)), 0), - veinChunkY.getOrDefault(Utils.chunkCoordsToKey(Utils.mapToCenterOreChunkCoord(chunkX), Utils.mapToCenterOreChunkCoord(chunkZ - 3)), 0), - veinChunkY.getOrDefault(Utils.chunkCoordsToKey(Utils.mapToCenterOreChunkCoord(chunkX - 3), Utils.mapToCenterOreChunkCoord(chunkZ - 3)), 0), - veinChunkY.getOrDefault(Utils.chunkCoordsToKey(Utils.mapToCenterOreChunkCoord(chunkX - 3), Utils.mapToCenterOreChunkCoord(chunkZ)), 0) + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX - 3), Utils.mapToCenterOreChunkCoord(chunkZ + 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX), Utils.mapToCenterOreChunkCoord(chunkZ + 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX + 3), Utils.mapToCenterOreChunkCoord(chunkZ + 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX + 3), Utils.mapToCenterOreChunkCoord(chunkZ)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX + 3), Utils.mapToCenterOreChunkCoord(chunkZ - 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX), Utils.mapToCenterOreChunkCoord(chunkZ - 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX - 3), Utils.mapToCenterOreChunkCoord(chunkZ - 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX - 3), Utils.mapToCenterOreChunkCoord(chunkZ)), + 0) }; // Remove all generated ores from neighbors. They could also be generated in the same chunk, // but that case is rare and therefore, neglected - for(int neighborId = 0; neighborId < neighbors.length; neighborId++) { + for (int neighborId = 0; neighborId < neighbors.length; neighborId++) { final OreVeinPosition neighbor = neighbors[neighborId]; - final boolean atCoordinateAxis = Math.abs(neighbor.chunkX - chunkX) < 3 || Math.abs(neighbor.chunkZ - chunkZ) < 3; - final boolean canOverlap = atCoordinateAxis ? neighbor.veinType.canOverlapIntoNeighborOreChunkAtCoordinateAxis() : neighbor.veinType.canOverlapIntoNeighborOreChunk(); + final boolean atCoordinateAxis = + Math.abs(neighbor.chunkX - chunkX) < 3 || Math.abs(neighbor.chunkZ - chunkZ) < 3; + final boolean canOverlap = atCoordinateAxis + ? neighbor.veinType.canOverlapIntoNeighborOreChunkAtCoordinateAxis() + : neighbor.veinType.canOverlapIntoNeighborOreChunk(); if (neighbor.veinType != VeinType.NO_VEIN && canOverlap) { final int veinBlockY = neighborVeinBlockY[neighborId]; for (int layerBlockY = 0; layerBlockY < VeinType.veinHeight; layerBlockY++) { final int blockY = veinBlockY + layerBlockY; - if(blockY > 255) { + if (blockY > 255) { break; } - if(oresPerY[blockY] != null) { + if (oresPerY[blockY] != null) { for (short metaData : neighbor.veinType.getOresAtLayer(layerBlockY)) { oresPerY[blockY].remove(metaData); } @@ -90,7 +116,7 @@ public VeinType getMatchedVein() { final Set matchedVeins = new HashSet<>(); final Map allOres = new HashMap<>(); - for(Map oreLevel : oresPerY) { + for (Map oreLevel : oresPerY) { if (oreLevel != null && oreLevel.isEmpty() == false) { oreLevel.forEach((metaData, numberOfBlocks) -> allOres.merge(metaData, numberOfBlocks, Integer::sum)); } @@ -98,32 +124,34 @@ public VeinType getMatchedVein() { final Optional dominantOre = allOres.entrySet().stream() .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) - .map(Map.Entry::getKey).findFirst(); - if(dominantOre.isPresent()) { - for(VeinType veinType : VeinTypeCaching.veinTypes) { - if(veinType.matchesWithSpecificPrimaryOrSecondary(allOres.keySet(), dominantOre.get())) { + .map(Map.Entry::getKey) + .findFirst(); + if (dominantOre.isPresent()) { + for (VeinType veinType : VeinTypeCaching.veinTypes) { + if (veinType.matchesWithSpecificPrimaryOrSecondary(allOres.keySet(), dominantOre.get())) { matchedVeins.add(veinType); } } } - if(matchedVeins.size() == 1) { + if (matchedVeins.size() == 1) { return matchedVeins.stream().findAny().get(); - } - else if(matchedVeins.size() >= 2) { - matchedVeins.removeIf(veinType -> IntStream.range(veinType.minBlockY, veinType.maxBlockY).boxed().noneMatch(blockY -> isOreVeinGeneratedAtHeight(veinType, blockY))); + } else if (matchedVeins.size() >= 2) { + matchedVeins.removeIf(veinType -> IntStream.range(veinType.minBlockY, veinType.maxBlockY) + .boxed() + .noneMatch(blockY -> isOreVeinGeneratedAtHeight(veinType, blockY))); - if(matchedVeins.size() == 1) { + if (matchedVeins.size() == 1) { return matchedVeins.stream().findAny().get(); } - } return VeinType.NO_VEIN; } private boolean isOreVeinGeneratedAtHeight(VeinType veinType, int blockY) { - for(int layer = 0; layer < VeinType.veinHeight; layer++) { - if(oresPerY[blockY + layer] == null || oresPerY[blockY + layer].keySet().containsAll(veinType.getOresAtLayer(layer)) == false) { + for (int layer = 0; layer < VeinType.veinHeight; layer++) { + if (oresPerY[blockY + layer] == null + || oresPerY[blockY + layer].keySet().containsAll(veinType.getOresAtLayer(layer)) == false) { return false; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java index 3c976f60..c182568c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java @@ -1,20 +1,18 @@ package com.sinthoras.visualprospecting.database.cachebuilder; import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import io.xol.enklume.MinecraftRegion; import io.xol.enklume.MinecraftWorld; import io.xol.enklume.nbt.NBTCompound; - import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.DataFormatException; @@ -33,7 +31,8 @@ private interface IChunkHandler { public void processMinecraftWorld(MinecraftWorld world) throws IOException { final Map veinBlockY = new ConcurrentHashMap<>(); final List regionFiles = world.getAllRegionFiles(dimensionId); - final long dimensionSizeMB = regionFiles.stream().mapToLong(File::length).sum() >> 20; + final long dimensionSizeMB = + regionFiles.stream().mapToLong(File::length).sum() >> 20; if (dimensionSizeMB <= Config.maxDimensionSizeMBForFastScanning) { AnalysisProgressTracker.announceFastDimension(dimensionId); @@ -47,10 +46,12 @@ public void processMinecraftWorld(MinecraftWorld world) throws IOException { chunk.processMinecraftChunk(root); if (chunk.matchesSingleVein()) { - ServerCache.instance.notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, chunk.getMatchedVein()); + ServerCache.instance.notifyOreVeinGeneration( + dimensionId, chunkX, chunkZ, chunk.getMatchedVein()); veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), chunk.getVeinBlockY()); } else { - final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis(dimensionId, chunkX, chunkZ); + final DetailedChunkAnalysis detailedChunk = + new DetailedChunkAnalysis(dimensionId, chunkX, chunkZ); detailedChunk.processMinecraftChunk(root); chunksForSecondIdentificationPass.put(Utils.chunkCoordsToKey(chunkX, chunkZ), detailedChunk); } @@ -59,7 +60,8 @@ public void processMinecraftWorld(MinecraftWorld world) throws IOException { chunksForSecondIdentificationPass.values().parallelStream().forEach(chunk -> { chunk.cleanUpWithNeighbors(veinBlockY); - ServerCache.instance.notifyOreVeinGeneration(dimensionId, chunk.chunkX, chunk.chunkZ, chunk.getMatchedVein()); + ServerCache.instance.notifyOreVeinGeneration( + dimensionId, chunk.chunkX, chunk.chunkZ, chunk.getMatchedVein()); }); } else { AnalysisProgressTracker.announceSlowDimension(dimensionId); @@ -71,7 +73,8 @@ public void processMinecraftWorld(MinecraftWorld world) throws IOException { chunk.processMinecraftChunk(root); if (chunk.matchesSingleVein()) { - ServerCache.instance.notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, chunk.getMatchedVein()); + ServerCache.instance.notifyOreVeinGeneration( + dimensionId, chunkX, chunkZ, chunk.getMatchedVein()); veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), chunk.getVeinBlockY()); } }); @@ -80,10 +83,15 @@ public void processMinecraftWorld(MinecraftWorld world) throws IOException { regionFiles.parallelStream().forEach(regionFile -> { executeForEachGeneratedOreChunk(regionFile, (root, chunkX, chunkZ) -> { if (ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ).veinType == VeinType.NO_VEIN) { - final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis(dimensionId, chunkX, chunkZ); + final DetailedChunkAnalysis detailedChunk = + new DetailedChunkAnalysis(dimensionId, chunkX, chunkZ); detailedChunk.processMinecraftChunk(root); detailedChunk.cleanUpWithNeighbors(veinBlockY); - ServerCache.instance.notifyOreVeinGeneration(dimensionId, detailedChunk.chunkX, detailedChunk.chunkZ, detailedChunk.getMatchedVein()); + ServerCache.instance.notifyOreVeinGeneration( + dimensionId, + detailedChunk.chunkX, + detailedChunk.chunkZ, + detailedChunk.getMatchedVein()); } }); }); @@ -92,7 +100,7 @@ public void processMinecraftWorld(MinecraftWorld world) throws IOException { private void executeForEachGeneratedOreChunk(File regionFile, IChunkHandler chunkHandler) { try { - if ( !Pattern.matches("^r\\.-?\\d+\\.-?\\d+\\.mca$", regionFile.getName())) { + if (!Pattern.matches("^r\\.-?\\d+\\.-?\\d+\\.mca$", regionFile.getName())) { VP.warn("Invalid region file found! " + regionFile.getCanonicalPath() + " continuing"); return; } @@ -106,9 +114,11 @@ private void executeForEachGeneratedOreChunk(File regionFile, IChunkHandler chun final int chunkZ = regionChunkZ + localChunkZ; // Only process ore chunks - if (chunkX == Utils.mapToCenterOreChunkCoord(chunkX) && chunkZ == Utils.mapToCenterOreChunkCoord(chunkZ)) { + if (chunkX == Utils.mapToCenterOreChunkCoord(chunkX) + && chunkZ == Utils.mapToCenterOreChunkCoord(chunkZ)) { // Helpful read about 'root' structure: https://minecraft.fandom.com/wiki/Chunk_format - final NBTCompound root = region.getChunk(localChunkX, localChunkZ).getRootTag(); + final NBTCompound root = + region.getChunk(localChunkX, localChunkZ).getRootTag(); // root == null occurs when a chunk is not yet generated if (root != null) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java index 31705e6a..0169ff02 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java @@ -1,13 +1,13 @@ package com.sinthoras.visualprospecting.database.cachebuilder; +import static com.sinthoras.visualprospecting.Utils.isSmallOreId; +import static com.sinthoras.visualprospecting.Utils.oreIdToMaterialId; + import io.xol.enklume.nbt.NBTCompound; import io.xol.enklume.nbt.NBTInt; import io.xol.enklume.nbt.NBTShort; import io.xol.enklume.nbt.NBTString; -import static com.sinthoras.visualprospecting.Utils.isSmallOreId; -import static com.sinthoras.visualprospecting.Utils.oreIdToMaterialId; - public class GregTechOre { public final boolean isValidGTOre; @@ -19,13 +19,15 @@ public GregTechOre(NBTCompound tileEntity) { final NBTShort tagMeta = (NBTShort) tileEntity.getTag("m"); final NBTInt tagBlockY = (NBTInt) tileEntity.getTag("y"); - if (tagId != null && tagId.getText().equals("GT_TileEntity_Ores") && tagBlockY != null - && tagMeta != null && isSmallOreId(tagMeta.data) == false) { + if (tagId != null + && tagId.getText().equals("GT_TileEntity_Ores") + && tagBlockY != null + && tagMeta != null + && isSmallOreId(tagMeta.data) == false) { metaData = oreIdToMaterialId(tagMeta.data); isValidGTOre = true; blockY = tagBlockY.data; - } - else { + } else { isValidGTOre = false; metaData = 0; blockY = 0; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java index 793c56e0..682099b7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java @@ -3,7 +3,6 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; import io.xol.enklume.MinecraftWorld; - import java.io.File; import java.io.IOException; import java.util.List; @@ -14,7 +13,7 @@ public class WorldAnalysis { private final MinecraftWorld world; public WorldAnalysis(File worldDirectory) throws IOException { - world = new MinecraftWorld(worldDirectory); + world = new MinecraftWorld(worldDirectory); } public void cacheVeins() throws IOException, DataFormatException { @@ -22,7 +21,7 @@ public void cacheVeins() throws IOException, DataFormatException { ServerCache.instance.reset(); final List dimensionIds = world.getDimensionIds(); AnalysisProgressTracker.setNumberOfDimensions(dimensionIds.size()); - for(int dimensionId : dimensionIds) { + for (int dimensionId : dimensionIds) { final DimensionAnalysis dimension = new DimensionAnalysis(dimensionId); dimension.processMinecraftWorld(world); AnalysisProgressTracker.dimensionProcessed(); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java index da8512aa..fd280a95 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java @@ -1,13 +1,13 @@ package com.sinthoras.visualprospecting.database.veintypes; +import static com.github.bartimaeusnek.bartworks.util.BW_ColorUtil.getColorFromRGBArray; + import com.github.bartimaeusnek.bartworks.system.material.Werkstoff; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.enums.OrePrefixes; import net.minecraft.util.IIcon; -import static com.github.bartimaeusnek.bartworks.util.BW_ColorUtil.getColorFromRGBArray; - public class BartworksOreMaterialProvider implements IOreMaterialProvider { private final Werkstoff material; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java index c4ee26b8..c70b43cd 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java @@ -4,7 +4,6 @@ import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.util.IIcon; - public interface IOreMaterialProvider { @SideOnly(Side.CLIENT) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index c92ec7b0..4a2c2cdc 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -2,13 +2,12 @@ import com.sinthoras.visualprospecting.Tags; import gregtech.api.GregTech_API; -import net.minecraft.util.EnumChatFormatting; - import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import net.minecraft.util.EnumChatFormatting; public class VeinType { @@ -28,10 +27,19 @@ public class VeinType { private boolean isHighlighted = true; // Available after VisualProspecting post GT initialization - public static final VeinType NO_VEIN = new VeinType(Tags.ORE_MIX_NONE_NAME, null, 0, (short)-1, (short)-1, (short)-1, (short)-1, 0, 0); - - public VeinType(String name, IOreMaterialProvider oreMaterialProvider, int blockSize, short primaryOreMeta, short secondaryOreMeta, short inBetweenOreMeta, short sporadicOreMeta, int minBlockY, int maxBlockY) - { + public static final VeinType NO_VEIN = + new VeinType(Tags.ORE_MIX_NONE_NAME, null, 0, (short) -1, (short) -1, (short) -1, (short) -1, 0, 0); + + public VeinType( + String name, + IOreMaterialProvider oreMaterialProvider, + int blockSize, + short primaryOreMeta, + short secondaryOreMeta, + short inBetweenOreMeta, + short sporadicOreMeta, + int minBlockY, + int maxBlockY) { this.name = name; this.oreMaterialProvider = oreMaterialProvider; this.blockSize = blockSize; @@ -82,7 +90,7 @@ public List getOreMaterialNames() { public Set getOresAtLayer(int layerBlockY) { final Set result = new HashSet<>(); - switch(layerBlockY) { + switch (layerBlockY) { case 0: case 1: case 2: diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index be65a87d..cea0609d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -1,5 +1,7 @@ package com.sinthoras.visualprospecting.database.veintypes; +import static com.sinthoras.visualprospecting.Utils.*; + import codechicken.nei.NEIClientConfig; import codechicken.nei.SearchField; import com.github.bartimaeusnek.bartworks.system.material.Werkstoff; @@ -11,15 +13,11 @@ import gregtech.api.GregTech_API; import gregtech.api.enums.Materials; import gregtech.common.GT_Worldgen_GT_Ore_Layer; -import net.minecraft.client.resources.I18n; -import net.minecraft.util.EnumChatFormatting; - import java.io.File; import java.util.*; import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import static com.sinthoras.visualprospecting.Utils.*; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.EnumChatFormatting; public class VeinTypeCaching implements Runnable { @@ -31,7 +29,8 @@ public class VeinTypeCaching implements Runnable { private static int longesOreName = 0; // BartWorks initializes veins in FML preInit - // GalacticGreg initializes veins in FML postInit, but only copies all base game veins to make them available on all planets + // GalacticGreg initializes veins in FML postInit, but only copies all base game veins to make them available on all + // planets // GregTech initializes veins in a thread in FML postInit // Therefore, this method must be called after GregTech postInit public void run() { @@ -39,8 +38,8 @@ public void run() { largeVeinOres = new HashSet<>(); veinTypes.add(VeinType.NO_VEIN); - for(GT_Worldgen_GT_Ore_Layer vein : GT_Worldgen_GT_Ore_Layer.sList) { - if(vein.mWorldGenName.equals(Tags.ORE_MIX_NONE_NAME)) { + for (GT_Worldgen_GT_Ore_Layer vein : GT_Worldgen_GT_Ore_Layer.sList) { + if (vein.mWorldGenName.equals(Tags.ORE_MIX_NONE_NAME)) { break; } final Materials material = getGregTechMaterial(vein.mPrimaryMeta); @@ -53,14 +52,17 @@ public void run() { vein.mSecondaryMeta, vein.mBetweenMeta, vein.mSporadicMeta, - Math.max(0, vein.mMinY - 6), // GregTech ore veins start at layer -1 and the blockY RNG adds another -5 offset + Math.max( + 0, + vein.mMinY - 6), // GregTech ore veins start at layer -1 and the blockY RNG adds another -5 + // offset Math.min(255, vein.mMaxY - 6))); } - if(isBartworksInstalled()) { - for(BW_OreLayer vein : BW_OreLayer.sList) { - final IOreMaterialProvider oreMaterialProvider = (vein.bwOres & 0b1000) == 0 ? - new GregTechOreMaterialProvider(getGregTechMaterial((short) vein.mPrimaryMeta)) + if (isBartworksInstalled()) { + for (BW_OreLayer vein : BW_OreLayer.sList) { + final IOreMaterialProvider oreMaterialProvider = (vein.bwOres & 0b1000) == 0 + ? new GregTechOreMaterialProvider(getGregTechMaterial((short) vein.mPrimaryMeta)) : new BartworksOreMaterialProvider(Werkstoff.werkstoffHashMap.get((short) vein.mPrimaryMeta)); veinTypes.add(new VeinType( @@ -79,14 +81,14 @@ public void run() { // Assign veinTypeIds for efficient storage loadVeinTypeStorageInfo(); - final Optional maxVeinTypeIdOptional = veinTypeStorageInfo.values().stream().max(Short::compare); + final Optional maxVeinTypeIdOptional = + veinTypeStorageInfo.values().stream().max(Short::compare); short maxVeinTypeId = maxVeinTypeIdOptional.isPresent() ? maxVeinTypeIdOptional.get() : 0; - for(VeinType veinType : veinTypes) { - if(veinTypeStorageInfo.containsKey(veinType.name)) { + for (VeinType veinType : veinTypes) { + if (veinTypeStorageInfo.containsKey(veinType.name)) { veinType.veinId = veinTypeStorageInfo.get(veinType.name); - } - else { + } else { maxVeinTypeId++; veinType.veinId = maxVeinTypeId; veinTypeStorageInfo.put(veinType.name, veinType.veinId); @@ -98,7 +100,7 @@ public void run() { veinTypeLookupTableForNames.put(veinType.name, veinType); // Build large vein LUT - if(veinType.canOverlapIntoNeighborOreChunk()) { + if (veinType.canOverlapIntoNeighborOreChunk()) { largeVeinOres.add(veinType.primaryOreMeta); largeVeinOres.add(veinType.secondaryOreMeta); largeVeinOres.add(veinType.inBetweenOreMeta); @@ -107,8 +109,8 @@ public void run() { } saveVeinTypeStorageInfo(); - for(VeinType veinType : veinTypes) { - if(veinType.name.length() > longesOreName) { + for (VeinType veinType : veinTypes) { + if (veinType.name.length() > longesOreName) { longesOreName = veinType.name.length(); } } @@ -116,9 +118,12 @@ public void run() { private Materials getGregTechMaterial(short metaId) { final Materials material = GregTech_API.sGeneratedMaterials[metaId]; - if(material == null) { + if (material == null) { // Some materials are not registered in dev when their usage mod is not available. - return Materials.getAll().stream().filter(m -> m.mMetaItemSubID == metaId).findAny().get(); + return Materials.getAll().stream() + .filter(m -> m.mMetaItemSubID == metaId) + .findAny() + .get(); } return material; } @@ -154,7 +159,7 @@ private static void saveVeinTypeStorageInfo() { } public static void recalculateNEISearch() { - if(isNEIInstalled()) { + if (isNEIInstalled()) { final boolean isSearchActive = SearchField.searchInventories(); final String searchString = NEIClientConfig.getSearchExpression().toLowerCase(); final Pattern filterPattern = SearchField.getPattern(searchString); @@ -165,9 +170,10 @@ public static void recalculateNEISearch() { List searchableStrings = veinType.getOreMaterialNames(); searchableStrings.add(I18n.format(veinType.name)); final boolean match = searchableStrings.stream() - .map(EnumChatFormatting::getTextWithoutFormattingCodes) - .map(String::toLowerCase) - .anyMatch(searchableString -> filterPattern.matcher(searchableString).find()); + .map(EnumChatFormatting::getTextWithoutFormattingCodes) + .map(String::toLowerCase) + .anyMatch(searchableString -> + filterPattern.matcher(searchableString).find()); veinType.setNEISearchHeighlight(match); } else { diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java index d3702b6a..6edae4be 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java @@ -4,7 +4,6 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ResetClientCacheCommand; import com.sinthoras.visualprospecting.integration.voxelmap.VoxelMapEventHandler; - import cpw.mods.fml.client.registry.ClientRegistry; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; @@ -17,58 +16,58 @@ import net.minecraft.client.settings.KeyBinding; import net.minecraftforge.client.ClientCommandHandler; import net.minecraftforge.common.MinecraftForge; - import org.lwjgl.input.Keyboard; public class HooksClient extends HooksShared { - @Override - // load "Do your mod setup. Build whatever data structures you care about. Register recipes." - public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { - super.fmlLifeCycleEvent(event); + @Override + // load "Do your mod setup. Build whatever data structures you care about. Register recipes." + public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { + super.fmlLifeCycleEvent(event); + + VP.keyAction = new KeyBinding( + "visualprospecting.key.action.name", Keyboard.KEY_DELETE, "visualprospecting.key.action.category"); + ClientRegistry.registerKeyBinding(VP.keyAction); + } + + @Override + // load "Do your mod setup. Build whatever data structures you care about. Register recipes." + public void fmlLifeCycleEvent(FMLInitializationEvent event) { + super.fmlLifeCycleEvent(event); + } + + @Override + // postInit "Handle interaction with other mods, complete your setup based on this." + public void fmlLifeCycleEvent(FMLPostInitializationEvent event) { + super.fmlLifeCycleEvent(event); + ClientCommandHandler.instance.registerCommand(new ResetClientCacheCommand()); + if (Utils.isVoxelMapInstalled()) { + MinecraftForge.EVENT_BUS.register(new VoxelMapEventHandler()); + } + } + + @Override + public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) { + super.fmlLifeCycleEvent(event); + } + + @Override + public void fmlLifeCycleEvent(FMLServerStartingEvent event) { + super.fmlLifeCycleEvent(event); + } + + @Override + public void fmlLifeCycleEvent(FMLServerStartedEvent event) { + super.fmlLifeCycleEvent(event); + } - VP.keyAction = new KeyBinding("visualprospecting.key.action.name", Keyboard.KEY_DELETE, "visualprospecting.key.action.category"); - ClientRegistry.registerKeyBinding(VP.keyAction); - } - - @Override - // load "Do your mod setup. Build whatever data structures you care about. Register recipes." - public void fmlLifeCycleEvent(FMLInitializationEvent event) { - super.fmlLifeCycleEvent(event); - } - - @Override - // postInit "Handle interaction with other mods, complete your setup based on this." - public void fmlLifeCycleEvent(FMLPostInitializationEvent event) { - super.fmlLifeCycleEvent(event); - ClientCommandHandler.instance.registerCommand(new ResetClientCacheCommand()); - if(Utils.isVoxelMapInstalled()) { - MinecraftForge.EVENT_BUS.register(new VoxelMapEventHandler()); - } - } + @Override + public void fmlLifeCycleEvent(FMLServerStoppingEvent event) { + super.fmlLifeCycleEvent(event); + } - @Override - public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) { - super.fmlLifeCycleEvent(event); - } - - @Override - public void fmlLifeCycleEvent(FMLServerStartingEvent event) { - super.fmlLifeCycleEvent(event); - } - - @Override - public void fmlLifeCycleEvent(FMLServerStartedEvent event) { - super.fmlLifeCycleEvent(event); - } - - @Override - public void fmlLifeCycleEvent(FMLServerStoppingEvent event) { - super.fmlLifeCycleEvent(event); - } - - @Override - public void fmlLifeCycleEvent(FMLServerStoppedEvent event) { - super.fmlLifeCycleEvent(event); - } + @Override + public void fmlLifeCycleEvent(FMLServerStoppedEvent event) { + super.fmlLifeCycleEvent(event); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java index 77f732b4..d6508b64 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java @@ -1,7 +1,7 @@ package com.sinthoras.visualprospecting.hooks; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.WorldIdHandler; @@ -16,7 +16,7 @@ public class HooksEventBus { @SubscribeEvent public void onEvent(WorldEvent.Unload event) { - if(Utils.isLogicalClient()) { + if (Utils.isLogicalClient()) { ClientCache.instance.saveVeinCache(); } } @@ -28,11 +28,10 @@ public void onEvent(WorldEvent.Save event) { @SubscribeEvent public void onEvent(EntityJoinWorldEvent event) { - if(event.world.isRemote == false) { + if (event.world.isRemote == false) { if (event.entity instanceof EntityPlayerMP) { VP.network.sendTo(new WorldIdNotification(WorldIdHandler.getWorldId()), (EntityPlayerMP) event.entity); - } - else if (event.entity instanceof EntityPlayer) { + } else if (event.entity instanceof EntityPlayer) { ClientCache.instance.loadVeinCache(WorldIdHandler.getWorldId()); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index 46bc59dc..415632ab 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -1,8 +1,8 @@ package com.sinthoras.visualprospecting.hooks; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.RedoServerCacheCommand; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.WorldIdHandler; @@ -30,86 +30,83 @@ import gregtech.api.enums.Materials; import gregtech.api.enums.OrePrefixes; import gregtech.api.util.GT_OreDictUnificator; +import java.io.IOException; +import java.util.zip.DataFormatException; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.server.MinecraftServer; import net.minecraftforge.common.MinecraftForge; -import java.io.IOException; -import java.util.zip.DataFormatException; +public class HooksShared { + // preInit "Run before anything else. Read your config, create blocks, items, + // etc, and register them with the GameRegistry." + public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { + Config.syncronizeConfiguration(event.getSuggestedConfigurationFile()); -public class HooksShared { - - // preInit "Run before anything else. Read your config, create blocks, items, - // etc, and register them with the GameRegistry." - public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { - Config.syncronizeConfiguration(event.getSuggestedConfigurationFile()); + VP.network = NetworkRegistry.INSTANCE.newSimpleChannel(Tags.MODID); + int networkId = 0; + VP.network.registerMessage( + ProspectingRequest.Handler.class, ProspectingRequest.class, networkId++, Side.SERVER); + VP.network.registerMessage( + ProspectingNotification.Handler.class, ProspectingNotification.class, networkId++, Side.CLIENT); + VP.network.registerMessage( + WorldIdNotification.Handler.class, WorldIdNotification.class, networkId++, Side.CLIENT); + VP.network.registerMessage( + ProspectionSharing.ServerHandler.class, ProspectionSharing.class, networkId++, Side.SERVER); + VP.network.registerMessage( + ProspectionSharing.ClientHandler.class, ProspectionSharing.class, networkId++, Side.CLIENT); + + ProspectorsLog.instance = new ProspectorsLog(); + GameRegistry.registerItem(ProspectorsLog.instance, ProspectorsLog.instance.getUnlocalizedName()); + } - VP.network = NetworkRegistry.INSTANCE.newSimpleChannel(Tags.MODID); - int networkId = 0; - VP.network.registerMessage(ProspectingRequest.Handler.class, ProspectingRequest.class, networkId++, Side.SERVER); - VP.network.registerMessage(ProspectingNotification.Handler.class, ProspectingNotification.class, networkId++, Side.CLIENT); - VP.network.registerMessage(WorldIdNotification.Handler.class, WorldIdNotification.class, networkId++, Side.CLIENT); - VP.network.registerMessage(ProspectionSharing.ServerHandler.class, ProspectionSharing.class, networkId++, Side.SERVER); - VP.network.registerMessage(ProspectionSharing.ClientHandler.class, ProspectionSharing.class, networkId++, Side.CLIENT); + // load "Do your mod setup. Build whatever data structures you care about. Register recipes." + public void fmlLifeCycleEvent(FMLInitializationEvent event) { + MinecraftForge.EVENT_BUS.register(new HooksEventBus()); + FMLCommonHandler.instance().bus().register(new HooksFML()); + } - ProspectorsLog.instance = new ProspectorsLog(); - GameRegistry.registerItem(ProspectorsLog.instance, ProspectorsLog.instance.getUnlocalizedName()); - } - - // load "Do your mod setup. Build whatever data structures you care about. Register recipes." - public void fmlLifeCycleEvent(FMLInitializationEvent event) { - MinecraftForge.EVENT_BUS.register(new HooksEventBus()); - FMLCommonHandler.instance().bus().register(new HooksFML()); - } - - // postInit "Handle interaction with other mods, complete your setup based on this." - public void fmlLifeCycleEvent(FMLPostInitializationEvent event) { - GregTech_API.sAfterGTPostload.add(new VeinTypeCaching()); - GregTech_API.sAfterGTPostload.add(() -> GT_Values.RA.addAssemblerRecipe( - new ItemStack[] { - GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Wood, 2L), - new ItemStack(Items.writable_book, 1, 0x7FFF), - new ItemStack(Items.gold_nugget, 1, 0x7FFF) - }, - Materials.Glue.getFluid(20L), - new ItemStack(ProspectorsLog.instance, 1, 0), - 128, - 8)); - } - - public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) { + // postInit "Handle interaction with other mods, complete your setup based on this." + public void fmlLifeCycleEvent(FMLPostInitializationEvent event) { + GregTech_API.sAfterGTPostload.add(new VeinTypeCaching()); + GregTech_API.sAfterGTPostload.add(() -> GT_Values.RA.addAssemblerRecipe( + new ItemStack[] { + GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Wood, 2L), + new ItemStack(Items.writable_book, 1, 0x7FFF), + new ItemStack(Items.gold_nugget, 1, 0x7FFF) + }, + Materials.Glue.getFluid(20L), + new ItemStack(ProspectorsLog.instance, 1, 0), + 128, + 8)); + } - } + public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) {} - // register server commands in this event handler - public void fmlLifeCycleEvent(FMLServerStartingEvent event) { - final MinecraftServer minecraftServer = event.getServer(); - WorldIdHandler.load(minecraftServer.worldServers[0]); - if(ServerCache.instance.loadVeinCache(WorldIdHandler.getWorldId()) == false || Config.recacheVeins) { - try { - WorldAnalysis world = new WorldAnalysis(minecraftServer.getEntityWorld().getSaveHandler().getWorldDirectory()); - world.cacheVeins(); - } - catch (IOException | DataFormatException e) { - VP.info("Could not load world save files to build vein cache!"); - e.printStackTrace(); - } - } + // register server commands in this event handler + public void fmlLifeCycleEvent(FMLServerStartingEvent event) { + final MinecraftServer minecraftServer = event.getServer(); + WorldIdHandler.load(minecraftServer.worldServers[0]); + if (ServerCache.instance.loadVeinCache(WorldIdHandler.getWorldId()) == false || Config.recacheVeins) { + try { + WorldAnalysis world = new WorldAnalysis( + minecraftServer.getEntityWorld().getSaveHandler().getWorldDirectory()); + world.cacheVeins(); + } catch (IOException | DataFormatException e) { + VP.info("Could not load world save files to build vein cache!"); + e.printStackTrace(); + } + } event.registerServerCommand(new RedoServerCacheCommand()); - } - - public void fmlLifeCycleEvent(FMLServerStartedEvent event) { - - } - - public void fmlLifeCycleEvent(FMLServerStoppingEvent event) { - ServerCache.instance.saveVeinCache(); - ServerCache.instance.reset(); - } - - public void fmlLifeCycleEvent(FMLServerStoppedEvent event) { - - } + } + + public void fmlLifeCycleEvent(FMLServerStartedEvent event) {} + + public void fmlLifeCycleEvent(FMLServerStoppingEvent event) { + ServerCache.instance.saveVeinCache(); + ServerCache.instance.reset(); + } + + public void fmlLifeCycleEvent(FMLServerStoppedEvent event) {} } diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/ProspectingNotificationEvent.java b/src/main/java/com/sinthoras/visualprospecting/hooks/ProspectingNotificationEvent.java index 448f05df..803c69b1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/ProspectingNotificationEvent.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/ProspectingNotificationEvent.java @@ -2,42 +2,38 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; - import cpw.mods.fml.common.eventhandler.Event; public class ProspectingNotificationEvent extends Event { - - @Override - public boolean isCancelable() { - return false; - } - - public static class OreVein extends ProspectingNotificationEvent { - - private final OreVeinPosition position; - - public OreVein(OreVeinPosition position) { - this.position = position; - } - - public OreVeinPosition getPosition() { - return this.position; - } - - } - - public static class UndergroundFluid extends ProspectingNotificationEvent { - - private final UndergroundFluidPosition position; - - public UndergroundFluid(UndergroundFluidPosition position) { - this.position = position; - } - - public UndergroundFluidPosition getPosition() { - return this.position; - } - - } + @Override + public boolean isCancelable() { + return false; + } + + public static class OreVein extends ProspectingNotificationEvent { + + private final OreVeinPosition position; + + public OreVein(OreVeinPosition position) { + this.position = position; + } + + public OreVeinPosition getPosition() { + return this.position; + } + } + + public static class UndergroundFluid extends ProspectingNotificationEvent { + + private final UndergroundFluidPosition position; + + public UndergroundFluid(UndergroundFluidPosition position) { + this.position = position; + } + + public UndergroundFluidPosition getPosition() { + return this.position; + } + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java b/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java index be7b7ffa..acc008e5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java @@ -1,5 +1,6 @@ package com.sinthoras.visualprospecting.integration; +import java.util.List; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.OpenGlHelper; @@ -11,11 +12,10 @@ import thaumcraft.api.aspects.Aspect; import thaumcraft.client.lib.UtilsFX; -import java.util.List; - public class DrawUtils { - public static void drawGradientRect(double minPixelX, double minPixelY, double maxPixelX, double maxPixelY, double z, int colorA, int colorB) { + public static void drawGradientRect( + double minPixelX, double minPixelY, double maxPixelX, double maxPixelY, double z, int colorA, int colorB) { GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); @@ -47,11 +47,13 @@ public static void drawGradientRect(double minPixelX, double minPixelY, double m GL11.glEnable(GL11.GL_TEXTURE_2D); } - public static void drawGradientRect(double minPixelX, double minPixelY, double maxPixelX, double maxPixelY, int colorA, int colorB) { + public static void drawGradientRect( + double minPixelX, double minPixelY, double maxPixelX, double maxPixelY, int colorA, int colorB) { drawGradientRect(minPixelX, minPixelY, maxPixelX, maxPixelY, 300, colorA, colorB); } - public static void drawQuad(ResourceLocation texture, double x, double y, double width, double height, int color, float alpha) { + public static void drawQuad( + ResourceLocation texture, double x, double y, double width, double height, int color, float alpha) { GL11.glEnable(GL11.GL_BLEND); OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); @@ -69,7 +71,6 @@ public static void drawQuad(ResourceLocation texture, double x, double y, double tessellator.addVertexWithUV(x + width, y, 0.0, 1.0, 0.0); tessellator.addVertexWithUV(x, y, 0.0, 0.0, 0.0); tessellator.draw(); - } public static void drawQuad(IIcon icon, double x, double y, double width, double height, int color, float alpha) { @@ -90,21 +91,31 @@ public static void drawQuad(IIcon icon, double x, double y, double width, double tessellator.addVertexWithUV(x + width, y, 0.0, icon.getMaxU(), icon.getMinV()); tessellator.addVertexWithUV(x, y, 0.0, icon.getMinU(), icon.getMinV()); tessellator.draw(); - } - public static void drawAspect(double centerPixelX, double centerPixelY, double pixelSize, Aspect aspect, int amount) { + public static void drawAspect( + double centerPixelX, double centerPixelY, double pixelSize, Aspect aspect, int amount) { final int textureSize = 16; GL11.glPushMatrix(); final double scale = pixelSize / textureSize; GL11.glScaled(scale, scale, scale); - UtilsFX.drawTag((centerPixelX - pixelSize / 2) / scale, (centerPixelY - pixelSize / 2) / scale, aspect, amount, 0, 0, GL11.GL_ONE_MINUS_SRC_ALPHA, 1.0F, false); + UtilsFX.drawTag( + (centerPixelX - pixelSize / 2) / scale, + (centerPixelY - pixelSize / 2) / scale, + aspect, + amount, + 0, + 0, + GL11.GL_ONE_MINUS_SRC_ALPHA, + 1.0F, + false); GL11.glDisable(GL11.GL_LIGHTING); GL11.glPopMatrix(); } - public static void drawSimpleLabel(GuiScreen gui, String text, double textX, double textY, int fontColor, int bgColor, boolean centered) { + public static void drawSimpleLabel( + GuiScreen gui, String text, double textX, double textY, int fontColor, int bgColor, boolean centered) { GL11.glPushMatrix(); double dTextX = textX - (double) (int) textX; double dTextY = textY - (double) (int) textY; @@ -112,22 +123,27 @@ public static void drawSimpleLabel(GuiScreen gui, String text, double textX, dou double xOffsetL = centered ? -textWidth / 2.0 - 2 : -2; double xOffsetR = centered ? textWidth / 2.0 + 2 : textWidth + 2; GL11.glTranslated(dTextX, dTextY, 0.0); - drawGradientRect((int) textX + xOffsetL, (int) textY - 2, (int) textX + xOffsetR, (int) textY + gui.mc.fontRenderer.FONT_HEIGHT + 2, 0, bgColor, bgColor); - if (centered) - gui.drawCenteredString(gui.mc.fontRenderer, text, (int) textX, (int) textY, fontColor); - else - gui.drawString(gui.mc.fontRenderer, text, (int) textX, (int) textY, fontColor); + drawGradientRect( + (int) textX + xOffsetL, + (int) textY - 2, + (int) textX + xOffsetR, + (int) textY + gui.mc.fontRenderer.FONT_HEIGHT + 2, + 0, + bgColor, + bgColor); + if (centered) gui.drawCenteredString(gui.mc.fontRenderer, text, (int) textX, (int) textY, fontColor); + else gui.drawString(gui.mc.fontRenderer, text, (int) textX, (int) textY, fontColor); GL11.glPopMatrix(); } - public static void drawSimpleTooltip(GuiScreen gui, List text, double x, double y, int fontColor, int bgColor) { + public static void drawSimpleTooltip( + GuiScreen gui, List text, double x, double y, int fontColor, int bgColor) { if (text.isEmpty()) return; int maxTextWidth = 0; for (String str : text) { int strWidth = gui.mc.fontRenderer.getStringWidth(str); - if (strWidth > maxTextWidth) - maxTextWidth = strWidth; + if (strWidth > maxTextWidth) maxTextWidth = strWidth; } int boxWidth = maxTextWidth + 6; @@ -141,13 +157,20 @@ public static void drawSimpleTooltip(GuiScreen gui, List text, double x, drawGradientRect(x, y, x + boxWidth, y + boxHeight, bgColor, bgColor); GL11.glTranslated(dx, dy, 301); for (int i = 0; i < text.size(); i++) { - gui.drawString(gui.mc.fontRenderer, text.get(i), (int) x + 3, (int) y + 3 + i * (gui.mc.fontRenderer.FONT_HEIGHT + 2), fontColor); + gui.drawString( + gui.mc.fontRenderer, + text.get(i), + (int) x + 3, + (int) y + 3 + i * (gui.mc.fontRenderer.FONT_HEIGHT + 2), + fontColor); } GL11.glPopMatrix(); } public static float[] floats(int rgb) { - return new float[]{(float) (rgb >> 16 & 255) / 255.0F, (float) (rgb >> 8 & 255) / 255.0F, (float) (rgb & 255) / 255.0F}; + return new float[] { + (float) (rgb >> 16 & 255) / 255.0F, (float) (rgb >> 8 & 255) / 255.0F, (float) (rgb & 255) / 255.0F + }; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java index 0ddfaae5..e085e951 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java @@ -1,35 +1,33 @@ package com.sinthoras.visualprospecting.integration.gregtech; +import static gregtech.api.objects.XSTR.XSTR_INSTANCE; +import static gregtech.common.GT_Proxy.*; +import static gregtech.common.GT_Proxy.GTOIL; +import static gregtech.common.GT_UndergroundOil.undergroundOil; + import gregtech.GT_Mod; import gregtech.api.objects.GT_UO_Dimension; import gregtech.api.objects.GT_UO_Fluid; import gregtech.api.objects.XSTR; import gregtech.common.GT_UndergroundOil; +import java.util.HashMap; +import java.util.Map; import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; -import java.util.HashMap; -import java.util.Map; - -import static gregtech.api.objects.XSTR.XSTR_INSTANCE; -import static gregtech.common.GT_Proxy.*; -import static gregtech.common.GT_Proxy.GTOIL; -import static gregtech.common.GT_UndergroundOil.undergroundOil; - public class UndergroundFluidsWrapper { - private final static boolean isGTNHGregTechUndergroundFluids; - private final static float MODE_READ_ONLY = -1; + private static final boolean isGTNHGregTechUndergroundFluids; + private static final float MODE_READ_ONLY = -1; static { boolean foundMethod; try { GT_UndergroundOil.class.getDeclaredMethod("undergroundOil", World.class, int.class, int.class, float.class); foundMethod = true; - } - catch (NoSuchMethodException e) { + } catch (NoSuchMethodException e) { foundMethod = false; } isGTNHGregTechUndergroundFluids = foundMethod; @@ -37,10 +35,9 @@ public class UndergroundFluidsWrapper { // GTNH's GregTech5-Unofficial was rewritten and requires different access public static FluidStack prospectFluid(World world, int chunkX, int chunkZ) { - if(isGTNHGregTechUndergroundFluids) { + if (isGTNHGregTechUndergroundFluids) { return undergroundOil(world, chunkX, chunkZ, MODE_READ_ONLY); - } - else { + } else { return vanillaProspectFluid(world, chunkX, chunkZ); } } @@ -55,14 +52,14 @@ private static FluidStack vanillaProspectFluid(World world, int chunkX, int chun return null; } - Map chunkData = dimensionWiseChunkData.computeIfAbsent(dimensionId, k -> new HashMap<>(1024)); + Map chunkData = + dimensionWiseChunkData.computeIfAbsent(dimensionId, k -> new HashMap<>(1024)); int[] tInts = chunkData.get(chunkCoordinate); if (tInts == null) { tInts = getDefaultChunkDataOnCreation(); - } - else if (tInts[GTOIL] == 0) { + } else if (tInts[GTOIL] == 0) { return new FluidStack(FluidRegistry.getFluid(tInts[GTOILFLUID]), 0); } @@ -73,32 +70,30 @@ else if (tInts[GTOIL] == 0) { FluidStack fluidInChunk; if (uoFluid == null || uoFluid.getFluid() == null) { - tInts[GTOILFLUID] = Integer.MAX_VALUE;//null fluid pointer... kind of + tInts[GTOILFLUID] = Integer.MAX_VALUE; // null fluid pointer... kind of tInts[GTOIL] = 0; - chunkData.put(chunkCoordinate, tInts);//update hash map + chunkData.put(chunkCoordinate, tInts); // update hash map return null; - } - else { - if (tInts[GTOILFLUID] == uoFluid.getFluid().getID()) {//if stored fluid matches uoFluid + } else { + if (tInts[GTOILFLUID] == uoFluid.getFluid().getID()) { // if stored fluid matches uoFluid fluidInChunk = new FluidStack(uoFluid.getFluid(), tInts[GTOIL]); - } - else { + } else { fluidInChunk = new FluidStack(uoFluid.getFluid(), uoFluid.getRandomAmount(tRandom)); - fluidInChunk.amount = (int) ((float) fluidInChunk.amount * (0.75f + (XSTR_INSTANCE.nextFloat() / 2f)));//Randomly change amounts by +/- 25% + fluidInChunk.amount = (int) ((float) fluidInChunk.amount + * (0.75f + (XSTR_INSTANCE.nextFloat() / 2f))); // Randomly change amounts by +/- 25% } tInts[GTOIL] = fluidInChunk.amount; tInts[GTOILFLUID] = fluidInChunk.getFluidID(); } if (fluidInChunk.amount <= GT_UndergroundOil.DIVIDER) { - fluidInChunk.amount = 0;//return informative stack - tInts[GTOIL] = 0;//so in next access it will stop way above - } - else { - fluidInChunk.amount = fluidInChunk.amount / GT_UndergroundOil.DIVIDER;//give moderate extraction speed + fluidInChunk.amount = 0; // return informative stack + tInts[GTOIL] = 0; // so in next access it will stop way above + } else { + fluidInChunk.amount = fluidInChunk.amount / GT_UndergroundOil.DIVIDER; // give moderate extraction speed } - chunkData.put(chunkCoordinate, tInts);//update hash map + chunkData.put(chunkCoordinate, tInts); // update hash map return fluidInChunk; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java index b470c59f..c4efa455 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java @@ -1,18 +1,17 @@ package com.sinthoras.visualprospecting.integration.journeymap; +import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; +import static com.sinthoras.visualprospecting.integration.journeymap.Reflection.getJourneyMapGridRenderer; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.integration.journeymap.buttons.*; import com.sinthoras.visualprospecting.integration.journeymap.render.*; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.OreVeinWaypointManager; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.ThaumcraftNodeWaypointManager; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.WaypointManager; -import journeymap.client.render.map.GridRenderer; - import java.util.ArrayList; import java.util.List; - -import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; -import static com.sinthoras.visualprospecting.integration.journeymap.Reflection.getJourneyMapGridRenderer; +import journeymap.client.render.map.GridRenderer; public class JourneyMapState { @@ -23,7 +22,7 @@ public class JourneyMapState { public final List waypointManagers = new ArrayList<>(); public JourneyMapState() { - if(isTCNodeTrackerInstalled()) { + if (isTCNodeTrackerInstalled()) { buttons.add(ThaumcraftNodeButton.instance); renderers.add(ThaumcraftNodeRenderer.instance); waypointManagers.add(ThaumcraftNodeWaypointManager.instance); @@ -37,7 +36,7 @@ public JourneyMapState() { renderers.add(OreVeinRenderer.instance); waypointManagers.add(OreVeinWaypointManager.instance); - if(Config.enableDeveloperOverlays) { + if (Config.enableDeveloperOverlays) { buttons.add(DirtyChunkButton.instance); renderers.add(DirtyChunkRenderer.instance); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java index 3d118124..a64aa03c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java @@ -1,11 +1,10 @@ package com.sinthoras.visualprospecting.integration.journeymap; import com.sinthoras.visualprospecting.VP; +import java.lang.reflect.Field; import journeymap.client.render.map.GridRenderer; import journeymap.client.ui.fullscreen.Fullscreen; -import java.lang.reflect.Field; - public class Reflection { private static Field gridRenderer; @@ -14,8 +13,7 @@ public class Reflection { try { gridRenderer = Fullscreen.class.getDeclaredField("gridRenderer"); gridRenderer.setAccessible(true); - } - catch (Exception e) { + } catch (Exception e) { VP.error("Failed to access private fields in JourneyMap!"); e.printStackTrace(); } @@ -24,8 +22,7 @@ public class Reflection { public static GridRenderer getJourneyMapGridRenderer() { try { return (GridRenderer) gridRenderer.get(null); - } - catch (IllegalAccessException e) { + } catch (IllegalAccessException e) { e.printStackTrace(); return null; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java index 4a63aad0..f648fc2e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java @@ -39,20 +39,20 @@ protected void layoutButtons() { } protected void func_146284_a(GuiButton guibutton) { - if(guibutton == confirmButton) { + if (guibutton == confirmButton) { ClientCache.instance.resetPlayerProgression(); - final IChatComponent confirmation = new ChatComponentTranslation("visualprospecting.resetprogress.confirmation"); + final IChatComponent confirmation = + new ChatComponentTranslation("visualprospecting.resetprogress.confirmation"); confirmation.getChatStyle().setItalic(true); Minecraft.getMinecraft().thePlayer.addChatMessage(confirmation); UIManager.getInstance().openFullscreenMap(); - } - else if(guibutton == cancelButton) { + } else if (guibutton == cancelButton) { UIManager.getInstance().openMapActions(); } } protected void func_73869_a(char c, int i) { - switch(i) { + switch (i) { case 1: UIManager.getInstance().openMapActions(); default: diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java index 91e9b87f..3cab68f2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java @@ -19,7 +19,7 @@ public LayerButton(ButtonManager manager) { @Override public void updateState(boolean active) { isActive = active; - if(button != null) { + if (button != null) { button.setToggled(active, false); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java index 675dbcf7..e1bbe7e0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java @@ -1,11 +1,10 @@ package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; +import java.util.List; import journeymap.client.render.draw.DrawStep; import net.minecraft.client.gui.FontRenderer; -import java.util.List; - public interface ClickableDrawStep extends DrawStep { List getTooltip(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java index a0d9286c..608a2454 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java @@ -2,12 +2,11 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; +import java.awt.geom.Point2D; import journeymap.client.render.draw.DrawStep; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; -import java.awt.geom.Point2D; - public class DirtyChunkDrawStep implements DrawStep { private final DirtyChunkLocation dirtyChunkLocation; @@ -17,30 +16,54 @@ public DirtyChunkDrawStep(DirtyChunkLocation dirtyChunkLocation) { } @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, double fontScale, double rotation) { + public void draw( + double draggedPixelX, + double draggedPixelY, + GridRenderer gridRenderer, + float drawScale, + double fontScale, + double rotation) { final int zoom = gridRenderer.getZoom(); double blockSize = Math.pow(2, zoom); - final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid(dirtyChunkLocation.getBlockX(), dirtyChunkLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); + final Point2D.Double blockAsPixel = + gridRenderer.getBlockPixelInGrid(dirtyChunkLocation.getBlockX(), dirtyChunkLocation.getBlockZ()); + final Point2D.Double pixel = + new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); float alpha = 0.5f; alpha *= alpha * 204; int color = dirtyChunkLocation.isDirty() ? 0xFF0000 : 0x00FFAA; - DrawUtil.drawRectangle(pixel.getX(), pixel.getY(), - VP.chunkWidth * blockSize, VP.chunkDepth * blockSize, - color, (int)alpha); + DrawUtil.drawRectangle( + pixel.getX(), pixel.getY(), VP.chunkWidth * blockSize, VP.chunkDepth * blockSize, color, (int) alpha); - if(dirtyChunkLocation.isDirty()) { + if (dirtyChunkLocation.isDirty()) { final int borderColor = 0xFFD700; final int borderAlpha = 204; DrawUtil.drawRectangle(pixel.getX(), pixel.getY(), 15 * blockSize, blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle(pixel.getX() + 15 * blockSize, pixel.getY(), blockSize, 15 * blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle(pixel.getX() + 1 * blockSize, pixel.getY() + 15 * blockSize, 15 * blockSize, blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle(pixel.getX(), pixel.getY() + 1 * blockSize, blockSize, 15 * blockSize, borderColor, borderAlpha); + DrawUtil.drawRectangle( + pixel.getX() + 15 * blockSize, pixel.getY(), blockSize, 15 * blockSize, borderColor, borderAlpha); + DrawUtil.drawRectangle( + pixel.getX() + 1 * blockSize, + pixel.getY() + 15 * blockSize, + 15 * blockSize, + blockSize, + borderColor, + borderAlpha); + DrawUtil.drawRectangle( + pixel.getX(), pixel.getY() + 1 * blockSize, blockSize, 15 * blockSize, borderColor, borderAlpha); - DrawUtil.drawLabel("D", - pixel.getX() + 13 * blockSize, pixel.getY() + 13 * blockSize, - DrawUtil.HAlign.Left, DrawUtil.VAlign.Above, - 0, 180, 0x00FFFFFF, 255, fontScale, false, rotation); + DrawUtil.drawLabel( + "D", + pixel.getX() + 13 * blockSize, + pixel.getY() + 13 * blockSize, + DrawUtil.HAlign.Left, + DrawUtil.VAlign.Above, + 0, + 180, + 0x00FFFFFF, + 255, + fontScale, + false, + rotation); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java index 76820cb3..3074dca7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java @@ -5,6 +5,9 @@ import com.sinthoras.visualprospecting.integration.DrawUtils; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.List; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; import net.minecraft.client.gui.FontRenderer; @@ -12,13 +15,10 @@ import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; -import java.awt.geom.Point2D; -import java.util.ArrayList; -import java.util.List; - public class OreVeinDrawStep implements ClickableDrawStep { - private static final ResourceLocation depletedTextureLocation = new ResourceLocation(Tags.MODID, "textures/depleted.png"); + private static final ResourceLocation depletedTextureLocation = + new ResourceLocation(Tags.MODID, "textures/depleted.png"); private final OreVeinLocation oreVeinLocation; @@ -33,14 +33,14 @@ public OreVeinDrawStep(OreVeinLocation oreVeinLocation) { @Override public List getTooltip() { final List tooltip = new ArrayList<>(); - if(oreVeinLocation.isDepleted()) { + if (oreVeinLocation.isDepleted()) { tooltip.add(oreVeinLocation.getDepletedHint()); } - if(oreVeinLocation.isActiveAsWaypoint()) { + if (oreVeinLocation.isActiveAsWaypoint()) { tooltip.add(oreVeinLocation.getActiveWaypointHint()); } tooltip.add(oreVeinLocation.getName()); - if(oreVeinLocation.isDepleted() == false) { + if (oreVeinLocation.isDepleted() == false) { tooltip.addAll(oreVeinLocation.getMaterialNames()); } tooltip.add(oreVeinLocation.getToggleDepletedHint()); @@ -48,9 +48,7 @@ public List getTooltip() { } @Override - public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, int displayHeight) { - - } + public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, int displayHeight) {} @Override public boolean isMouseOver(int mouseX, int mouseY) { @@ -68,16 +66,35 @@ public IWaypointAndLocationProvider getLocationProvider() { } @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, double fontScale, double rotation) { + public void draw( + double draggedPixelX, + double draggedPixelY, + GridRenderer gridRenderer, + float drawScale, + double fontScale, + double rotation) { iconSize = 32 * fontScale; final double iconSizeHalf = iconSize / 2; - final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid(oreVeinLocation.getBlockX(), oreVeinLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); - + final Point2D.Double blockAsPixel = + gridRenderer.getBlockPixelInGrid(oreVeinLocation.getBlockX(), oreVeinLocation.getBlockZ()); + final Point2D.Double pixel = + new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); - if(gridRenderer.getZoom() >= Config.minZoomLevelForOreLabel && oreVeinLocation.isDepleted() == false) { + if (gridRenderer.getZoom() >= Config.minZoomLevelForOreLabel && oreVeinLocation.isDepleted() == false) { final int fontColor = oreVeinLocation.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F; - DrawUtil.drawLabel(oreVeinLocation.getName(), pixel.getX(), pixel.getY() - iconSize, DrawUtil.HAlign.Center, DrawUtil.VAlign.Middle, 0, 180, fontColor, 255, fontScale, false, rotation); + DrawUtil.drawLabel( + oreVeinLocation.getName(), + pixel.getX(), + pixel.getY() - iconSize, + DrawUtil.HAlign.Center, + DrawUtil.VAlign.Middle, + 0, + 180, + fontColor, + 255, + fontScale, + false, + rotation); } iconX = pixel.getX() - iconSizeHalf; @@ -85,21 +102,30 @@ public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRe final IIcon blockIcon = Blocks.stone.getIcon(0, 0); DrawUtils.drawQuad(blockIcon, iconX, iconY, iconSize, iconSize, 0xFFFFFF, 255); - DrawUtils.drawQuad(oreVeinLocation.getIconFromPrimaryOre(), iconX, iconY, iconSize, iconSize, oreVeinLocation.getColor(), 255); + DrawUtils.drawQuad( + oreVeinLocation.getIconFromPrimaryOre(), + iconX, + iconY, + iconSize, + iconSize, + oreVeinLocation.getColor(), + 255); - if(oreVeinLocation.drawSearchHighlight() == false || oreVeinLocation.isDepleted()) { + if (oreVeinLocation.drawSearchHighlight() == false || oreVeinLocation.isDepleted()) { DrawUtil.drawRectangle(iconX, iconY, iconSize, iconSize, 0x000000, 150); - if(oreVeinLocation.isDepleted()) { + if (oreVeinLocation.isDepleted()) { DrawUtils.drawQuad(depletedTextureLocation, iconX, iconY, iconSize, iconSize, 0xFFFFFF, 255); } } - if(oreVeinLocation.isActiveAsWaypoint()) { + if (oreVeinLocation.isActiveAsWaypoint()) { final double thickness = iconSize / 8; final int borderAlpha = 204; final int color = 0xFFD700; - DrawUtil.drawRectangle(iconX - thickness, iconY - thickness, iconSize + thickness, thickness, color, borderAlpha); - DrawUtil.drawRectangle(iconX + iconSize, iconY - thickness, thickness, iconSize + thickness, color, borderAlpha); + DrawUtil.drawRectangle( + iconX - thickness, iconY - thickness, iconSize + thickness, thickness, color, borderAlpha); + DrawUtil.drawRectangle( + iconX + iconSize, iconY - thickness, thickness, iconSize + thickness, color, borderAlpha); DrawUtil.drawRectangle(iconX, iconY + iconSize, iconSize + thickness, thickness, color, borderAlpha); DrawUtil.drawRectangle(iconX - thickness, iconY, thickness, iconSize + thickness, color, borderAlpha); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java index a28eb395..928dfaee 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java @@ -5,6 +5,8 @@ import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; +import java.awt.geom.Point2D; +import java.util.List; import journeymap.client.render.map.GridRenderer; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.RenderHelper; @@ -14,13 +16,12 @@ import thaumcraft.api.aspects.Aspect; import thaumcraft.client.lib.UtilsFX; -import java.awt.geom.Point2D; -import java.util.List; - public class ThaumcraftNodeDrawStep implements ClickableDrawStep { - private static final ResourceLocation markedTextureLocation = new ResourceLocation(Tags.MODID, "textures/node_marked.png"); - private static final ResourceLocation unmarkedTextureLocation = new ResourceLocation(Tags.MODID, "textures/node_unmarked.png"); + private static final ResourceLocation markedTextureLocation = + new ResourceLocation(Tags.MODID, "textures/node_marked.png"); + private static final ResourceLocation unmarkedTextureLocation = + new ResourceLocation(Tags.MODID, "textures/node_unmarked.png"); private final ThaumcraftNodeLocation thaumcraftNodeLocation; @@ -33,20 +34,36 @@ public ThaumcraftNodeDrawStep(ThaumcraftNodeLocation thaumcraftNodeLocation) { } @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, double fontScale, double rotation) { + public void draw( + double draggedPixelX, + double draggedPixelY, + GridRenderer gridRenderer, + float drawScale, + double fontScale, + double rotation) { final double borderSize = 44 * fontScale; final double borderSizeHalf = borderSize / 2; - final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid(thaumcraftNodeLocation.getBlockX(), thaumcraftNodeLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); + final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid( + thaumcraftNodeLocation.getBlockX(), thaumcraftNodeLocation.getBlockZ()); + final Point2D.Double pixel = + new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); centerPixelX = pixel.getX(); centerPixelY = pixel.getY(); clickableRadiusPixelSquared = borderSizeHalf * borderSizeHalf; final int alpha = 204; - DrawUtils.drawQuad(thaumcraftNodeLocation.isActiveAsWaypoint() ? markedTextureLocation : unmarkedTextureLocation, pixel.getX() - borderSizeHalf, pixel.getY() - borderSizeHalf, borderSize, borderSize, 0xFFFFFF, alpha); + DrawUtils.drawQuad( + thaumcraftNodeLocation.isActiveAsWaypoint() ? markedTextureLocation : unmarkedTextureLocation, + pixel.getX() - borderSizeHalf, + pixel.getY() - borderSizeHalf, + borderSize, + borderSize, + 0xFFFFFF, + alpha); final int aspectPixelDiameter = 32; - DrawUtils.drawAspect(pixel.getX(), pixel.getY(), aspectPixelDiameter, thaumcraftNodeLocation.getStrongestAspect(), 0); + DrawUtils.drawAspect( + pixel.getX(), pixel.getY(), aspectPixelDiameter, thaumcraftNodeLocation.getStrongestAspect(), 0); } public List getTooltip() { @@ -75,25 +92,28 @@ public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int d final String nodeDescription = thaumcraftNodeLocation.getDescription(); final String deleteHint = thaumcraftNodeLocation.getDeleteHint(); - int maxTextWidth = Math.max(Math.max(fontRenderer.getStringWidth(title), fontRenderer.getStringWidth(nodeDescription)), fontRenderer.getStringWidth(deleteHint)); - if(isWaypoint) { + int maxTextWidth = Math.max( + Math.max(fontRenderer.getStringWidth(title), fontRenderer.getStringWidth(nodeDescription)), + fontRenderer.getStringWidth(deleteHint)); + if (isWaypoint) { maxTextWidth = Math.max(maxTextWidth, fontRenderer.getStringWidth(activeWaypointHint)); } - if(fontRenderer.getBidiFlag()) { + if (fontRenderer.getBidiFlag()) { maxTextWidth = (int) Math.ceil(maxTextWidth * 1.25f); } - final int aspectRows = (thaumcraftNodeLocation.getAspects().size() + 4) / 5; // Equivalent to Math.ceil(size / 5) + final int aspectRows = + (thaumcraftNodeLocation.getAspects().size() + 4) / 5; // Equivalent to Math.ceil(size / 5) final int aspectColumns = Math.min(thaumcraftNodeLocation.getAspects().size(), 5); int pixelX = mouseX + 12; int pixelY = mouseY - 12; final int tooltipHeight = (isWaypoint ? 44 : 32) + aspectRows * 16; final int tooltipWidth = Math.max(aspectColumns * 16, maxTextWidth); - if(pixelX + tooltipWidth > displayWidth) { + if (pixelX + tooltipWidth > displayWidth) { pixelX -= 28 + tooltipWidth; } - if(pixelY + tooltipHeight + 6 > displayHeight) { + if (pixelY + tooltipHeight + 6 > displayHeight) { pixelY = displayHeight - tooltipHeight - 6; } @@ -104,23 +124,57 @@ public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int d // Draw background final int backgroundColor = 0xF0100010; - DrawUtils.drawGradientRect(pixelX - 3, pixelY - 4, pixelX + tooltipWidth + 3, pixelY - 3, backgroundColor, backgroundColor); - DrawUtils.drawGradientRect(pixelX - 3, pixelY + tooltipHeight + 3, pixelX + tooltipWidth + 3, pixelY + tooltipHeight + 4, backgroundColor, backgroundColor); - DrawUtils.drawGradientRect(pixelX - 3, pixelY - 3, pixelX + tooltipWidth + 3, pixelY + tooltipHeight + 3, backgroundColor, backgroundColor); - DrawUtils.drawGradientRect(pixelX - 4, pixelY - 3, pixelX - 3, pixelY + tooltipHeight + 3, backgroundColor, backgroundColor); - DrawUtils.drawGradientRect(pixelX + tooltipWidth + 3, pixelY - 3, pixelX + tooltipWidth + 4, pixelY + tooltipHeight + 3, backgroundColor, backgroundColor); + DrawUtils.drawGradientRect( + pixelX - 3, pixelY - 4, pixelX + tooltipWidth + 3, pixelY - 3, backgroundColor, backgroundColor); + DrawUtils.drawGradientRect( + pixelX - 3, + pixelY + tooltipHeight + 3, + pixelX + tooltipWidth + 3, + pixelY + tooltipHeight + 4, + backgroundColor, + backgroundColor); + DrawUtils.drawGradientRect( + pixelX - 3, + pixelY - 3, + pixelX + tooltipWidth + 3, + pixelY + tooltipHeight + 3, + backgroundColor, + backgroundColor); + DrawUtils.drawGradientRect( + pixelX - 4, pixelY - 3, pixelX - 3, pixelY + tooltipHeight + 3, backgroundColor, backgroundColor); + DrawUtils.drawGradientRect( + pixelX + tooltipWidth + 3, + pixelY - 3, + pixelX + tooltipWidth + 4, + pixelY + tooltipHeight + 3, + backgroundColor, + backgroundColor); int verdunGreen = 0x505000FF; int borderColor = 0x5028007F; - DrawUtils.drawGradientRect(pixelX - 3, pixelY - 3 + 1, pixelX - 3 + 1, pixelY + tooltipHeight + 3 - 1, verdunGreen, borderColor); - DrawUtils.drawGradientRect(pixelX + tooltipWidth + 2, pixelY - 3 + 1, pixelX + tooltipWidth + 3, pixelY + tooltipHeight + 3 - 1, verdunGreen, borderColor); - DrawUtils.drawGradientRect(pixelX - 3, pixelY - 3, pixelX + tooltipWidth + 3, pixelY - 3 + 1, verdunGreen, verdunGreen); - DrawUtils.drawGradientRect(pixelX - 3, pixelY + tooltipHeight + 2, pixelX + tooltipWidth + 3, pixelY + tooltipHeight + 3, borderColor, borderColor); + DrawUtils.drawGradientRect( + pixelX - 3, pixelY - 3 + 1, pixelX - 3 + 1, pixelY + tooltipHeight + 3 - 1, verdunGreen, borderColor); + DrawUtils.drawGradientRect( + pixelX + tooltipWidth + 2, + pixelY - 3 + 1, + pixelX + tooltipWidth + 3, + pixelY + tooltipHeight + 3 - 1, + verdunGreen, + borderColor); + DrawUtils.drawGradientRect( + pixelX - 3, pixelY - 3, pixelX + tooltipWidth + 3, pixelY - 3 + 1, verdunGreen, verdunGreen); + DrawUtils.drawGradientRect( + pixelX - 3, + pixelY + tooltipHeight + 2, + pixelX + tooltipWidth + 3, + pixelY + tooltipHeight + 3, + borderColor, + borderColor); // Draw text int offset = 0; - if(fontRenderer.getBidiFlag()) { - if(isWaypoint) { + if (fontRenderer.getBidiFlag()) { + if (isWaypoint) { final int asWaypointWidth = (int) Math.ceil(fontRenderer.getStringWidth(activeWaypointHint) * 1.1f); fontRenderer.drawString(title, pixelX + tooltipWidth - asWaypointWidth, pixelY, 0xFFFFFFFF); offset += 12; @@ -129,13 +183,17 @@ public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int d fontRenderer.drawString(title, pixelX + tooltipWidth - titleWidth, pixelY + offset, 0xFFFFFFFF); offset += 12; final int nodeDescriptonWidth = (int) Math.ceil(fontRenderer.getStringWidth(nodeDescription) * 1.1f); - fontRenderer.drawString(nodeDescription, pixelX + nodeDescriptonWidth - titleWidth, pixelY + offset, 0xFFFFFFFF); + fontRenderer.drawString( + nodeDescription, pixelX + nodeDescriptonWidth - titleWidth, pixelY + offset, 0xFFFFFFFF); final int deleteHintWidth = (int) Math.ceil(fontRenderer.getStringWidth(deleteHint) * 1.1f); - fontRenderer.drawString(deleteHint, pixelX + tooltipWidth - deleteHintWidth, pixelY + aspectRows * 16 + offset + 12, 0xFFFFFFFF); - } - else { - if(isWaypoint) { + fontRenderer.drawString( + deleteHint, + pixelX + tooltipWidth - deleteHintWidth, + pixelY + aspectRows * 16 + offset + 12, + 0xFFFFFFFF); + } else { + if (isWaypoint) { fontRenderer.drawString(activeWaypointHint, pixelX, pixelY, 0xFFFFFFFF); offset += 12; } @@ -150,13 +208,21 @@ public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int d int aspectX = 0; int aspectY = 0; - - for(Aspect aspect : thaumcraftNodeLocation.getAspects().getAspectsSortedAmount()) { + for (Aspect aspect : thaumcraftNodeLocation.getAspects().getAspectsSortedAmount()) { GL11.glPushMatrix(); - UtilsFX.drawTag(pixelX + aspectX * 16, pixelY + aspectY * 16 + offset + 10, aspect, thaumcraftNodeLocation.getAspects().getAmount(aspect), 0, 0.01, 1, 1, false); + UtilsFX.drawTag( + pixelX + aspectX * 16, + pixelY + aspectY * 16 + offset + 10, + aspect, + thaumcraftNodeLocation.getAspects().getAmount(aspect), + 0, + 0.01, + 1, + 1, + false); GL11.glPopMatrix(); ++aspectX; - if(aspectX >= 5) { + if (aspectX >= 5) { aspectX = 0; ++aspectY; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java index 24a21e9a..acb7b56d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java @@ -3,12 +3,11 @@ import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; +import java.awt.geom.Point2D; import journeymap.client.render.draw.DrawStep; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; -import java.awt.geom.Point2D; - public class UndergroundFluidChunkDrawStep implements DrawStep { private final UndergroundFluidChunkLocation undergroundFluidChunkLocation; @@ -18,32 +17,75 @@ public UndergroundFluidChunkDrawStep(UndergroundFluidChunkLocation undergroundFl } @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, double fontScale, double rotation) { + public void draw( + double draggedPixelX, + double draggedPixelY, + GridRenderer gridRenderer, + float drawScale, + double fontScale, + double rotation) { final int zoom = gridRenderer.getZoom(); - if (undergroundFluidChunkLocation.getFluidAmount() > 0 && zoom >= Config.minZoomLevelForUndergroundFluidDetails) { + if (undergroundFluidChunkLocation.getFluidAmount() > 0 + && zoom >= Config.minZoomLevelForUndergroundFluidDetails) { double blockSize = Math.pow(2, zoom); - final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid(undergroundFluidChunkLocation.getBlockX(), undergroundFluidChunkLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); - float alpha = ((float)(undergroundFluidChunkLocation.getFluidAmount() - undergroundFluidChunkLocation.getMinAmountInField())) - / (undergroundFluidChunkLocation.getMaxAmountInField() - undergroundFluidChunkLocation.getMinAmountInField() + 1); + final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid( + undergroundFluidChunkLocation.getBlockX(), undergroundFluidChunkLocation.getBlockZ()); + final Point2D.Double pixel = + new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); + float alpha = ((float) (undergroundFluidChunkLocation.getFluidAmount() + - undergroundFluidChunkLocation.getMinAmountInField())) + / (undergroundFluidChunkLocation.getMaxAmountInField() + - undergroundFluidChunkLocation.getMinAmountInField() + + 1); alpha *= alpha * 204; - DrawUtil.drawRectangle(pixel.getX(), pixel.getY(), - VP.chunkWidth * blockSize, VP.chunkDepth * blockSize, - undergroundFluidChunkLocation.getFluid().getColor(), (int)alpha); + DrawUtil.drawRectangle( + pixel.getX(), + pixel.getY(), + VP.chunkWidth * blockSize, + VP.chunkDepth * blockSize, + undergroundFluidChunkLocation.getFluid().getColor(), + (int) alpha); - if(undergroundFluidChunkLocation.getFluidAmount() >= undergroundFluidChunkLocation.getMaxAmountInField()) { + if (undergroundFluidChunkLocation.getFluidAmount() >= undergroundFluidChunkLocation.getMaxAmountInField()) { final int borderColor = 0xFFD700; final int borderAlpha = 204; DrawUtil.drawRectangle(pixel.getX(), pixel.getY(), 15 * blockSize, blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle(pixel.getX() + 15 * blockSize, pixel.getY(), blockSize, 15 * blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle(pixel.getX() + 1 * blockSize, pixel.getY() + 15 * blockSize, 15 * blockSize, blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle(pixel.getX(), pixel.getY() + 1 * blockSize, blockSize, 15 * blockSize, borderColor, borderAlpha); + DrawUtil.drawRectangle( + pixel.getX() + 15 * blockSize, + pixel.getY(), + blockSize, + 15 * blockSize, + borderColor, + borderAlpha); + DrawUtil.drawRectangle( + pixel.getX() + 1 * blockSize, + pixel.getY() + 15 * blockSize, + 15 * blockSize, + blockSize, + borderColor, + borderAlpha); + DrawUtil.drawRectangle( + pixel.getX(), + pixel.getY() + 1 * blockSize, + blockSize, + 15 * blockSize, + borderColor, + borderAlpha); } - DrawUtil.drawLabel(undergroundFluidChunkLocation.getFluidAmountFormatted(), - pixel.getX() + 13 * blockSize, pixel.getY() + 13 * blockSize, - DrawUtil.HAlign.Left, DrawUtil.VAlign.Above, - 0, 180, 0x00FFFFFF, 255, fontScale, false, rotation); + DrawUtil.drawLabel( + undergroundFluidChunkLocation.getFluidAmountFormatted(), + pixel.getX() + 13 * blockSize, + pixel.getY() + 13 * blockSize, + DrawUtil.HAlign.Left, + DrawUtil.VAlign.Above, + 0, + 180, + 0x00FFFFFF, + 255, + fontScale, + false, + rotation); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java index 32d83356..3b75237d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java @@ -2,12 +2,11 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; +import java.awt.geom.Point2D; import journeymap.client.render.draw.DrawStep; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; -import java.awt.geom.Point2D; - public class UndergroundFluidDrawStep implements DrawStep { private final UndergroundFluidLocation undergroundFluidLocation; @@ -17,22 +16,67 @@ public UndergroundFluidDrawStep(UndergroundFluidLocation undergroundFluidLocatio } @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, double fontScale, double rotation) { + public void draw( + double draggedPixelX, + double draggedPixelY, + GridRenderer gridRenderer, + float drawScale, + double fontScale, + double rotation) { final int maxAmountInField = undergroundFluidLocation.getMaxProduction(); if (maxAmountInField > 0) { final double blockSize = Math.pow(2, gridRenderer.getZoom()); - final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid(undergroundFluidLocation.getBlockX(), undergroundFluidLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); + final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid( + undergroundFluidLocation.getBlockX(), undergroundFluidLocation.getBlockZ()); + final Point2D.Double pixel = + new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); final int borderColor = undergroundFluidLocation.getFluid().getColor(); final int borderAlpha = 204; - DrawUtil.drawRectangle(pixel.getX(), pixel.getY(), VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, 2 * blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle(pixel.getX() + VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, pixel.getY(), 2 * blockSize, VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle(pixel.getX() + 2 * blockSize, pixel.getY() + VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, 2 * blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle(pixel.getX(), pixel.getY() + 2 * blockSize, 2 * blockSize, VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, borderColor, borderAlpha); + DrawUtil.drawRectangle( + pixel.getX(), + pixel.getY(), + VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, + 2 * blockSize, + borderColor, + borderAlpha); + DrawUtil.drawRectangle( + pixel.getX() + VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, + pixel.getY(), + 2 * blockSize, + VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, + borderColor, + borderAlpha); + DrawUtil.drawRectangle( + pixel.getX() + 2 * blockSize, + pixel.getY() + VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, + VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, + 2 * blockSize, + borderColor, + borderAlpha); + DrawUtil.drawRectangle( + pixel.getX(), + pixel.getY() + 2 * blockSize, + 2 * blockSize, + VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, + borderColor, + borderAlpha); - final String label = undergroundFluidLocation.getMinProduction() + "L - " + maxAmountInField + "L " + undergroundFluidLocation.getFluid().getLocalizedName(); - DrawUtil.drawLabel(label, pixel.getX() + VP.chunkWidth * blockSize, pixel.getY(), DrawUtil.HAlign.Right, DrawUtil.VAlign.Below, 0, 180, 0x00FFFFFF, 255, fontScale, false, rotation); + final String label = undergroundFluidLocation.getMinProduction() + "L - " + maxAmountInField + "L " + + undergroundFluidLocation.getFluid().getLocalizedName(); + DrawUtil.drawLabel( + label, + pixel.getX() + VP.chunkWidth * blockSize, + pixel.getY(), + DrawUtil.HAlign.Right, + DrawUtil.VAlign.Below, + 0, + 180, + 0x00FFFFFF, + 255, + fontScale, + false, + rotation); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java index dd8376d3..3cfb53d9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java @@ -4,10 +4,9 @@ import com.sinthoras.visualprospecting.integration.model.layers.DirtyChunkLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; -import journeymap.client.render.draw.DrawStep; - import java.util.ArrayList; import java.util.List; +import journeymap.client.render.draw.DrawStep; public class DirtyChunkRenderer extends LayerRenderer { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java index bb53299a..4d202f8b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java @@ -3,10 +3,9 @@ import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; -import journeymap.client.render.draw.DrawStep; - import java.util.ArrayList; import java.util.List; +import journeymap.client.render.draw.DrawStep; public abstract class LayerRenderer extends com.sinthoras.visualprospecting.integration.model.layers.LayerRenderer { @@ -36,5 +35,6 @@ public void updateVisibleElements(List visibleEleme drawSteps = (List) mapLocationProviderToDrawStep(visibleElements); } - protected abstract List mapLocationProviderToDrawStep(List visibleElements); + protected abstract List mapLocationProviderToDrawStep( + List visibleElements); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java index 2e107bc5..aca61a2c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java @@ -5,7 +5,6 @@ import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; - import java.util.ArrayList; import java.util.List; @@ -18,7 +17,8 @@ public OreVeinRenderer() { } @Override - public List mapLocationProviderToDrawStep(List visibleElements) { + public List mapLocationProviderToDrawStep( + List visibleElements) { final List drawSteps = new ArrayList<>(); visibleElements.stream() .map(element -> (OreVeinLocation) element) diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java index b6891d89..cbd490b1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java @@ -5,7 +5,6 @@ import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; - import java.util.ArrayList; import java.util.List; @@ -18,7 +17,8 @@ public ThaumcraftNodeRenderer() { } @Override - public List mapLocationProviderToDrawStep(List visibleElements) { + public List mapLocationProviderToDrawStep( + List visibleElements) { final List drawSteps = new ArrayList<>(); visibleElements.stream() .map(element -> (ThaumcraftNodeLocation) element) diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java index 9acf255e..c06f0f83 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java @@ -4,10 +4,9 @@ import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidChunkLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -import journeymap.client.render.draw.DrawStep; - import java.util.ArrayList; import java.util.List; +import journeymap.client.render.draw.DrawStep; public class UndergroundFluidChunkRenderer extends LayerRenderer { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java index ae62ec92..a254ecf3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java @@ -4,10 +4,9 @@ import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; -import journeymap.client.render.draw.DrawStep; - import java.util.ArrayList; import java.util.List; +import journeymap.client.render.draw.DrawStep; public class UndergroundFluidRenderer extends LayerRenderer { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java index afce9311..febb3b18 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java @@ -3,11 +3,10 @@ import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.ClickableDrawStep; import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; -import net.minecraft.client.gui.FontRenderer; - import java.util.ArrayList; import java.util.Collections; import java.util.List; +import net.minecraft.client.gui.FontRenderer; public abstract class WaypointProviderLayerRenderer extends LayerRenderer { @@ -40,7 +39,8 @@ public void updateVisibleElements(List visibleEleme Collections.reverse(drawStepsReversed); } - protected abstract List mapLocationProviderToDrawStep(List visibleElements); + protected abstract List mapLocationProviderToDrawStep( + List visibleElements); public void onMouseMove(int mouseX, int mouseY) { hoveredDrawStep = null; @@ -53,13 +53,13 @@ public void onMouseMove(int mouseX, int mouseY) { } public boolean onMouseAction(boolean isDoubleClick) { - if(hoveredDrawStep != null) { - if(isDoubleClick) { - if(hoveredDrawStep.getLocationProvider().isActiveAsWaypoint()) { + if (hoveredDrawStep != null) { + if (isDoubleClick) { + if (hoveredDrawStep.getLocationProvider().isActiveAsWaypoint()) { manager.clearActiveWaypoint(); - } - else { - manager.setActiveWaypoint(hoveredDrawStep.getLocationProvider().toWaypoint()); + } else { + manager.setActiveWaypoint( + hoveredDrawStep.getLocationProvider().toWaypoint()); } } return true; @@ -68,20 +68,21 @@ public boolean onMouseAction(boolean isDoubleClick) { } public List getTextTooltip() { - if(hoveredDrawStep != null) { + if (hoveredDrawStep != null) { return hoveredDrawStep.getTooltip(); } return null; } - public void drawCustomTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, int displayHeight) { - if(hoveredDrawStep != null) { + public void drawCustomTooltip( + FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, int displayHeight) { + if (hoveredDrawStep != null) { hoveredDrawStep.drawTooltip(fontRenderer, mouseX, mouseY, displayWidth, displayHeight); } } public void onActionKeyPressed() { - if(manager.isLayerActive() && hoveredDrawStep != null) { + if (manager.isLayerActive() && hoveredDrawStep != null) { hoveredDrawStep.onActionKeyPressed(); manager.forceRefresh(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java index 30f11513..ce814403 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java @@ -3,7 +3,6 @@ import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; - import java.awt.*; public class WaypointManager extends com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager { @@ -29,14 +28,16 @@ public journeymap.client.model.Waypoint getJmWaypoint() { @Override public void updateActiveWaypoint(Waypoint waypoint) { - if(hasWaypoint() == false + if (hasWaypoint() == false || waypoint.blockX != jmWaypoint.getX() || waypoint.blockY != jmWaypoint.getY() || waypoint.blockZ != jmWaypoint.getZ() || jmWaypoint.getDimensions().contains(waypoint.dimensionId) == false) { jmWaypoint = new journeymap.client.model.Waypoint( waypoint.label, - waypoint.blockX, waypoint.blockY, waypoint.blockZ, + waypoint.blockX, + waypoint.blockY, + waypoint.blockZ, new Color(waypoint.color), journeymap.client.model.Waypoint.Type.Normal, waypoint.dimensionId); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java index ef6b35fe..200d5dff 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java @@ -1,15 +1,14 @@ package com.sinthoras.visualprospecting.integration.model; +import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.integration.model.buttons.*; import com.sinthoras.visualprospecting.integration.model.layers.*; import com.sinthoras.visualprospecting.integration.tcnodetracker.NTNodeTrackerWaypointManager; - import java.util.ArrayList; import java.util.List; -import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; - public class MapState { public static final MapState instance = new MapState(); @@ -17,7 +16,7 @@ public class MapState { public final List layers = new ArrayList<>(); public MapState() { - if(isTCNodeTrackerInstalled()) { + if (isTCNodeTrackerInstalled()) { buttons.add(ThaumcraftNodeButtonManager.instance); layers.add(ThaumcraftNodeLayerManager.instance); new NTNodeTrackerWaypointManager(); @@ -30,7 +29,7 @@ public MapState() { buttons.add(OreVeinButtonManager.instance); layers.add(OreVeinLayerManager.instance); - if(Config.enableDeveloperOverlays) { + if (Config.enableDeveloperOverlays) { buttons.add(DirtyChunkButtonManager.instance); layers.add(DirtyChunkLayerManager.instance); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java index 9541e3d2..4d480b00 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java @@ -2,7 +2,6 @@ import com.sinthoras.visualprospecting.integration.model.MapState; import com.sinthoras.visualprospecting.integration.model.SupportedMods; - import java.util.EnumMap; import java.util.Map; @@ -60,11 +59,10 @@ public void deactivate() { } public void toggle() { - if(isActive) { + if (isActive) { deactivate(); - } - else { + } else { activate(); } } -} \ No newline at end of file +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java index 16aaa8e9..27ddc47a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java @@ -4,15 +4,13 @@ import com.sinthoras.visualprospecting.integration.model.buttons.DirtyChunkButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; +import java.util.ArrayList; +import java.util.List; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; -import net.minecraft.world.gen.ChunkProviderServer; - -import java.util.ArrayList; -import java.util.List; public class DirtyChunkLayerManager extends LayerManager { @@ -28,7 +26,8 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i } @Override - protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + protected List generateVisibleElements( + int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { final int minX = Utils.coordBlockToChunk(minBlockX); final int minZ = Utils.coordBlockToChunk(minBlockZ); final int maxX = Utils.coordBlockToChunk(maxBlockX); @@ -38,7 +37,8 @@ protected List generateVisibleElements(int minBlock ArrayList dirtyChunks = new ArrayList<>(); - if (MinecraftServer.getServer() == null || MinecraftServer.getServer().worldServerForDimension(playerDimensionId) == null) { + if (MinecraftServer.getServer() == null + || MinecraftServer.getServer().worldServerForDimension(playerDimensionId) == null) { return dirtyChunks; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java index fb16726e..b473f908 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java @@ -4,7 +4,6 @@ import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; import com.sinthoras.visualprospecting.integration.model.buttons.LayerButton; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; - import java.util.ArrayList; import java.util.EnumMap; import java.util.List; @@ -28,7 +27,7 @@ public LayerManager(ButtonManager buttonManager) { } public void onButtonClicked(LayerButton button) { - if(buttonManager.containsButton(button)) { + if (buttonManager.containsButton(button)) { toggleLayer(); } } @@ -53,11 +52,10 @@ public void forceRefresh() { forceRefresh = true; } - public void onOpenMap() { - - } + public void onOpenMap() {} - protected abstract List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ); + protected abstract List generateVisibleElements( + int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ); protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { return true; @@ -92,7 +90,7 @@ private void recacheVisibleElements(int centerBlockX, int centerBlockZ) { } protected void checkAndUpdateElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - if(forceRefresh || needsRegenerateVisibleElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ)) { + if (forceRefresh || needsRegenerateVisibleElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ)) { visibleElements = generateVisibleElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ); layerRenderer.values().forEach(layer -> layer.updateVisibleElements(visibleElements)); forceRefresh = false; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java index 83baa8be..7c6d2d6f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java @@ -2,7 +2,6 @@ import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; - import java.util.List; public abstract class LayerRenderer { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java index fc044f12..3a76c9ea 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java @@ -8,10 +8,9 @@ import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; -import net.minecraft.client.Minecraft; - import java.util.ArrayList; import java.util.List; +import net.minecraft.client.Minecraft; public class OreVeinLayerManager extends WaypointProviderManager { @@ -38,7 +37,10 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i final int maxOreChunkX = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(maxBlockX)); final int maxOreChunkZ = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - if (minOreChunkX != oldMinOreChunkX || maxOreChunkX != oldMaxOreChunkX || minOreChunkZ != oldMinOreChunkZ || maxOreChunkZ != oldMaxOreChunkZ) { + if (minOreChunkX != oldMinOreChunkX + || maxOreChunkX != oldMaxOreChunkX + || minOreChunkZ != oldMinOreChunkZ + || maxOreChunkZ != oldMaxOreChunkZ) { oldMinOreChunkX = minOreChunkX; oldMaxOreChunkX = maxOreChunkX; oldMinOreChunkZ = minOreChunkZ; @@ -49,7 +51,8 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i } @Override - protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + protected List generateVisibleElements( + int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { final int minOreChunkX = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(minBlockX)); final int minOreChunkZ = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(minBlockZ)); final int maxOreChunkX = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(maxBlockX)); @@ -59,8 +62,11 @@ protected List generateVisibleElements(i ArrayList oreChunkLocations = new ArrayList<>(); for (int chunkX = minOreChunkX; chunkX <= maxOreChunkX; chunkX = Utils.mapToCenterOreChunkCoord(chunkX + 3)) { - for (int chunkZ = minOreChunkZ; chunkZ <= maxOreChunkZ; chunkZ = Utils.mapToCenterOreChunkCoord(chunkZ + 3)) { - final OreVeinPosition oreVeinPosition = ClientCache.instance.getOreVein(playerDimensionId, chunkX, chunkZ); + for (int chunkZ = minOreChunkZ; + chunkZ <= maxOreChunkZ; + chunkZ = Utils.mapToCenterOreChunkCoord(chunkZ + 3)) { + final OreVeinPosition oreVeinPosition = + ClientCache.instance.getOreVein(playerDimensionId, chunkX, chunkZ); if (oreVeinPosition.veinType != VeinType.NO_VEIN) { oreChunkLocations.add(new OreVeinLocation(oreVeinPosition)); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java index 3af95cc2..ae9331d6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java @@ -5,10 +5,9 @@ import com.sinthoras.visualprospecting.integration.model.buttons.ThaumcraftNodeButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; -import net.minecraft.client.Minecraft; - import java.util.ArrayList; import java.util.List; +import net.minecraft.client.Minecraft; public class ThaumcraftNodeLayerManager extends WaypointProviderManager { @@ -25,7 +24,10 @@ public ThaumcraftNodeLayerManager() { @Override protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - if(minBlockX != oldMinBlockX || minBlockZ != oldMinBlockZ || maxBlockX != oldMaxBlockX || maxBlockZ != oldMaxBlockZ) { + if (minBlockX != oldMinBlockX + || minBlockZ != oldMinBlockZ + || maxBlockX != oldMaxBlockX + || maxBlockZ != oldMaxBlockZ) { oldMinBlockX = minBlockX; oldMinBlockZ = minBlockZ; oldMaxBlockX = maxBlockX; @@ -36,15 +38,18 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i } @Override - protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + protected List generateVisibleElements( + int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { final int playerDimensionId = Minecraft.getMinecraft().thePlayer.dimension; ArrayList thaumcraftNodeLocations = new ArrayList<>(); for (NodeList node : TCNodeTracker.nodelist) { - if(node.dim == playerDimensionId - && node.x >= minBlockX && node.x <= maxBlockX - && node.z >= minBlockZ && node.z <= maxBlockZ) { + if (node.dim == playerDimensionId + && node.x >= minBlockX + && node.x <= maxBlockX + && node.z >= minBlockZ + && node.z <= maxBlockZ) { thaumcraftNodeLocations.add(new ThaumcraftNodeLocation(node)); } } @@ -54,7 +59,7 @@ protected List generateVisibleElements(i public void deleteNode(ThaumcraftNodeLocation thaumcraftNodeLocation) { TCNodeTracker.nodelist.removeIf(thaumcraftNodeLocation::belongsToNode); - if(thaumcraftNodeLocation.isActiveAsWaypoint()) { + if (thaumcraftNodeLocation.isActiveAsWaypoint()) { clearActiveWaypoint(); } forceRefresh(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java index 0581b75d..97a409d5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java @@ -7,10 +7,9 @@ import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -import net.minecraft.client.Minecraft; - import java.util.ArrayList; import java.util.List; +import net.minecraft.client.Minecraft; public class UndergroundFluidChunkLayerManager extends LayerManager { @@ -27,11 +26,18 @@ public UndergroundFluidChunkLayerManager() { @Override protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - if (minUndergroundFluidX != oldMinUndergroundFluidX || maxUndergroundFluidX != oldMaxUndergroundFluidX || minUndergroundFluidZ != oldMinUndergroundFluidZ || maxUndergroundFluidZ != oldMaxUndergroundFluidZ) { + final int minUndergroundFluidX = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); + final int minUndergroundFluidZ = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); + final int maxUndergroundFluidX = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); + final int maxUndergroundFluidZ = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); + if (minUndergroundFluidX != oldMinUndergroundFluidX + || maxUndergroundFluidX != oldMaxUndergroundFluidX + || minUndergroundFluidZ != oldMinUndergroundFluidZ + || maxUndergroundFluidZ != oldMaxUndergroundFluidZ) { oldMinUndergroundFluidX = minUndergroundFluidX; oldMaxUndergroundFluidX = maxUndergroundFluidX; oldMinUndergroundFluidZ = minUndergroundFluidZ; @@ -42,24 +48,41 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i } @Override - protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); + protected List generateVisibleElements( + int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + final int minUndergroundFluidX = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); + final int minUndergroundFluidZ = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); + final int maxUndergroundFluidX = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); + final int maxUndergroundFluidZ = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); final int playerDimensionId = Minecraft.getMinecraft().thePlayer.dimension; ArrayList undergroundFluidPositions = new ArrayList<>(); - for (int chunkX = minUndergroundFluidX; chunkX <= maxUndergroundFluidX; chunkX += VP.undergroundFluidSizeChunkX) { - for (int chunkZ = minUndergroundFluidZ; chunkZ <= maxUndergroundFluidZ; chunkZ += VP.undergroundFluidSizeChunkZ) { - final UndergroundFluidPosition undergroundFluid = ClientCache.instance.getUndergroundFluid(playerDimensionId, chunkX, chunkZ); + for (int chunkX = minUndergroundFluidX; + chunkX <= maxUndergroundFluidX; + chunkX += VP.undergroundFluidSizeChunkX) { + for (int chunkZ = minUndergroundFluidZ; + chunkZ <= maxUndergroundFluidZ; + chunkZ += VP.undergroundFluidSizeChunkZ) { + final UndergroundFluidPosition undergroundFluid = + ClientCache.instance.getUndergroundFluid(playerDimensionId, chunkX, chunkZ); if (undergroundFluid.isProspected()) { final int minAmountInField = undergroundFluid.getMinProduction(); final int maxAmountInField = undergroundFluid.getMaxProduction(); for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - undergroundFluidPositions.add(new UndergroundFluidChunkLocation(chunkX + offsetChunkX, chunkZ + offsetChunkZ, playerDimensionId, undergroundFluid.fluid, undergroundFluid.chunks[offsetChunkX][offsetChunkZ], minAmountInField, maxAmountInField)); + undergroundFluidPositions.add(new UndergroundFluidChunkLocation( + chunkX + offsetChunkX, + chunkZ + offsetChunkZ, + playerDimensionId, + undergroundFluid.fluid, + undergroundFluid.chunks[offsetChunkX][offsetChunkZ], + minAmountInField, + maxAmountInField)); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java index dee182af..57895b13 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java @@ -7,10 +7,9 @@ import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; -import net.minecraft.client.Minecraft; - import java.util.ArrayList; import java.util.List; +import net.minecraft.client.Minecraft; public class UndergroundFluidLayerManager extends LayerManager { @@ -27,11 +26,18 @@ public UndergroundFluidLayerManager() { @Override protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - if (minUndergroundFluidX != oldMinUndergroundFluidX || maxUndergroundFluidX != oldMaxUndergroundFluidX || minUndergroundFluidZ != oldMinUndergroundFluidZ || maxUndergroundFluidZ != oldMaxUndergroundFluidZ) { + final int minUndergroundFluidX = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); + final int minUndergroundFluidZ = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); + final int maxUndergroundFluidX = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); + final int maxUndergroundFluidZ = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); + if (minUndergroundFluidX != oldMinUndergroundFluidX + || maxUndergroundFluidX != oldMaxUndergroundFluidX + || minUndergroundFluidZ != oldMinUndergroundFluidZ + || maxUndergroundFluidZ != oldMaxUndergroundFluidZ) { oldMinUndergroundFluidX = minUndergroundFluidX; oldMaxUndergroundFluidX = maxUndergroundFluidX; oldMinUndergroundFluidZ = minUndergroundFluidZ; @@ -42,18 +48,28 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i } @Override - protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); + protected List generateVisibleElements( + int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + final int minUndergroundFluidX = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); + final int minUndergroundFluidZ = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); + final int maxUndergroundFluidX = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); + final int maxUndergroundFluidZ = + Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); final int playerDimensionId = Minecraft.getMinecraft().thePlayer.dimension; ArrayList undergroundFluidLocations = new ArrayList<>(); - for (int chunkX = minUndergroundFluidX; chunkX <= maxUndergroundFluidX; chunkX += VP.undergroundFluidSizeChunkX) { - for (int chunkZ = minUndergroundFluidZ; chunkZ <= maxUndergroundFluidZ; chunkZ += VP.undergroundFluidSizeChunkZ) { - final UndergroundFluidPosition undergroundFluid = ClientCache.instance.getUndergroundFluid(playerDimensionId, chunkX, chunkZ); + for (int chunkX = minUndergroundFluidX; + chunkX <= maxUndergroundFluidX; + chunkX += VP.undergroundFluidSizeChunkX) { + for (int chunkZ = minUndergroundFluidZ; + chunkZ <= maxUndergroundFluidZ; + chunkZ += VP.undergroundFluidSizeChunkZ) { + final UndergroundFluidPosition undergroundFluid = + ClientCache.instance.getUndergroundFluid(playerDimensionId, chunkX, chunkZ); if (undergroundFluid.isProspected()) { undergroundFluidLocations.add(new UndergroundFluidLocation(undergroundFluid)); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java index 94f55daf..5a3c76fc 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java @@ -1,11 +1,10 @@ package com.sinthoras.visualprospecting.integration.model.layers; import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; +import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; import com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager; - import java.util.ArrayList; import java.util.EnumMap; import java.util.List; @@ -46,14 +45,15 @@ public WaypointManager getWaypointManager(SupportedMods map) { return waypointManagers.get(map); } - protected abstract List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ); + protected abstract List generateVisibleElements( + int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ); @Override protected void checkAndUpdateElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - if(forceRefresh || needsRegenerateVisibleElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ)) { + if (forceRefresh || needsRegenerateVisibleElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ)) { visibleElements = generateVisibleElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ); - if(hasActiveWaypoint()) { + if (hasActiveWaypoint()) { for (IWaypointAndLocationProvider element : visibleElements) { element.onWaypointUpdated(activeWaypoint); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java index bcdcd529..75066c31 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java @@ -28,5 +28,7 @@ public int getDimensionId() { return dimensionId; } - public boolean isDirty() {return dirty;} + public boolean isDirty() { + return dirty; + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index 0c290555..aded93dd 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -4,19 +4,20 @@ import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; +import java.util.List; +import java.util.stream.Collectors; import net.minecraft.client.resources.I18n; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IIcon; import org.lwjgl.input.Keyboard; -import java.util.List; -import java.util.stream.Collectors; - public class OreVeinLocation implements IWaypointAndLocationProvider { private static final String depletedHint = EnumChatFormatting.RED + I18n.format("visualprospecting.depleted"); - private static final String activeWaypointHint = EnumChatFormatting.GOLD + I18n.format("visualprospecting.iswaypoint"); - private static final String toggleDepletedHint = EnumChatFormatting.DARK_GRAY + I18n.format("visualprospecting.node.deletehint", Keyboard.getKeyName(VP.keyAction.getKeyCode())); + private static final String activeWaypointHint = + EnumChatFormatting.GOLD + I18n.format("visualprospecting.iswaypoint"); + private static final String toggleDepletedHint = EnumChatFormatting.DARK_GRAY + + I18n.format("visualprospecting.node.deletehint", Keyboard.getKeyName(VP.keyAction.getKeyCode())); private final OreVeinPosition oreVeinPosition; private final String name; @@ -27,12 +28,18 @@ public class OreVeinLocation implements IWaypointAndLocationProvider { public OreVeinLocation(OreVeinPosition oreVeinPosition) { this.oreVeinPosition = oreVeinPosition; name = EnumChatFormatting.WHITE + I18n.format(oreVeinPosition.veinType.name); - materialNames = oreVeinPosition.veinType.getOreMaterialNames().stream().map(materialName -> EnumChatFormatting.GRAY + materialName).collect(Collectors.toList()); + materialNames = oreVeinPosition.veinType.getOreMaterialNames().stream() + .map(materialName -> EnumChatFormatting.GRAY + materialName) + .collect(Collectors.toList()); } @Override public Waypoint toWaypoint() { - return new Waypoint(oreVeinPosition.getBlockX(), 65, oreVeinPosition.getBlockZ(), oreVeinPosition.dimensionId, + return new Waypoint( + oreVeinPosition.getBlockX(), + 65, + oreVeinPosition.getBlockZ(), + oreVeinPosition.dimensionId, I18n.format("visualprospecting.tracked", I18n.format(oreVeinPosition.veinType.name)), getColor()); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java index c4476dc1..67a396a7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java @@ -14,8 +14,11 @@ public class ThaumcraftNodeLocation implements IWaypointAndLocationProvider { - private static final String deleteHint = EnumChatFormatting.DARK_GRAY + I18n.format("visualprospecting.node.deletehint", Keyboard.getKeyName(VP.keyAction.getKeyCode()));; - private static final String activeWaypointHint = EnumChatFormatting.GOLD + I18n.format("visualprospecting.iswaypoint"); + private static final String deleteHint = EnumChatFormatting.DARK_GRAY + + I18n.format("visualprospecting.node.deletehint", Keyboard.getKeyName(VP.keyAction.getKeyCode())); + ; + private static final String activeWaypointHint = + EnumChatFormatting.GOLD + I18n.format("visualprospecting.iswaypoint"); private static final String title = EnumChatFormatting.BOLD + I18n.format("tile.blockAiry.0.name"); private final NodeList node; @@ -29,11 +32,11 @@ public ThaumcraftNodeLocation(NodeList node) { nodeTile = new TileNode(); final AspectList aspectList = new AspectList(); - for(String aspectTag : node.aspect.keySet()) { + for (String aspectTag : node.aspect.keySet()) { aspectList.add(Aspect.getAspect(aspectTag), node.aspect.get(aspectTag)); } nodeTile.setAspects(aspectList); - switch(node.type) { + switch (node.type) { case "NORMAL": nodeTile.setNodeType(NodeType.NORMAL); break; @@ -56,8 +59,10 @@ public ThaumcraftNodeLocation(NodeList node) { nodeTile.blockType = ConfigBlocks.blockAiry; nodeTile.blockMetadata = 0; - description = node.mod.equals("BLANK") ? EnumChatFormatting.GRAY + I18n.format("nodetype." + node.type + ".name") - : EnumChatFormatting.GRAY + I18n.format("nodetype." + node.type + ".name") + ", " + I18n.format("nodemod." + node.mod + ".name"); + description = node.mod.equals("BLANK") + ? EnumChatFormatting.GRAY + I18n.format("nodetype." + node.type + ".name") + : EnumChatFormatting.GRAY + I18n.format("nodetype." + node.type + ".name") + ", " + + I18n.format("nodemod." + node.mod + ".name"); } @Override @@ -81,7 +86,11 @@ public int getDimensionId() { @Override public Waypoint toWaypoint() { - return new Waypoint(node.x, node.y, node.z, node.dim, + return new Waypoint( + node.x, + node.y, + node.z, + node.dim, I18n.format("visualprospecting.tracked", I18n.format("tile.blockAiry.0.name")), nodeTile.targetColor.getRGB()); } @@ -101,7 +110,7 @@ public void onWaypointUpdated(Waypoint waypoint) { isActiveAsWaypoint = waypoint.dimensionId == node.dim && waypoint.blockX == node.x && waypoint.blockY == node.y - && waypoint.blockZ== node.z; + && waypoint.blockZ == node.z; } public boolean belongsToNode(NodeList other) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java index 41769a50..fdc68c3c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java @@ -13,7 +13,14 @@ public class UndergroundFluidChunkLocation implements ILocationProvider { private final int maxAmountInField; private final int minAmountInField; - public UndergroundFluidChunkLocation(int chunkX, int chunkZ, int dimensionId, Fluid fluid, int fluidAmount, int minAmountInField, int maxAmountInField) { + public UndergroundFluidChunkLocation( + int chunkX, + int chunkZ, + int dimensionId, + Fluid fluid, + int fluidAmount, + int minAmountInField, + int maxAmountInField) { blockX = Utils.coordChunkToBlock(chunkX); blockZ = Utils.coordChunkToBlock(chunkZ); this.dimensionId = dimensionId; @@ -36,7 +43,7 @@ public int getDimensionId() { } public String getFluidAmountFormatted() { - if(fluidAmount >= 1000) { + if (fluidAmount >= 1000) { return (fluidAmount / 1000) + "kL"; } return fluidAmount + "L"; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/tcnodetracker/NTNodeTrackerWaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/tcnodetracker/NTNodeTrackerWaypointManager.java index 39c076b6..fc610d3b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/tcnodetracker/NTNodeTrackerWaypointManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/tcnodetracker/NTNodeTrackerWaypointManager.java @@ -5,7 +5,8 @@ import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; -public class NTNodeTrackerWaypointManager extends com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager { +public class NTNodeTrackerWaypointManager + extends com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager { public NTNodeTrackerWaypointManager() { super(ThaumcraftNodeLayerManager.instance, SupportedMods.TCNodeTracker); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java index 68d915a0..bba1e502 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java @@ -1,31 +1,31 @@ package com.sinthoras.visualprospecting.integration.voxelmap; -import java.lang.reflect.Method; - import com.sinthoras.visualprospecting.VP; import com.thevoxelbox.voxelmap.interfaces.IWaypointManager; +import java.lang.reflect.Method; public class IWaypointManagerReflection { - private static Method getCurrentSubworldDescriptor; - - public static String getCurrentSubworldDescriptor(IWaypointManager obj, boolean arg) { - try { - return (String) getCurrentSubworldDescriptor.invoke(obj, arg); - } catch (Exception e) { - VP.error("Could not invoke IWaypointManager#if. If it failed due to a NullPointerException, look for an error message starting with \"Getting the method IWaypointManager#if failed\" further up."); - e.printStackTrace(); - } - return ""; - } + private static Method getCurrentSubworldDescriptor; - static { - try { - getCurrentSubworldDescriptor = IWaypointManager.class.getMethod("if", boolean.class); - } catch (Exception e) { - VP.error("Getting the method IWaypointManager#if failed, any calls to IWaypointManagerReflection#getCurrentSubworldDescriptor will return an empty String."); - e.printStackTrace(); - } - } + public static String getCurrentSubworldDescriptor(IWaypointManager obj, boolean arg) { + try { + return (String) getCurrentSubworldDescriptor.invoke(obj, arg); + } catch (Exception e) { + VP.error( + "Could not invoke IWaypointManager#if. If it failed due to a NullPointerException, look for an error message starting with \"Getting the method IWaypointManager#if failed\" further up."); + e.printStackTrace(); + } + return ""; + } + static { + try { + getCurrentSubworldDescriptor = IWaypointManager.class.getMethod("if", boolean.class); + } catch (Exception e) { + VP.error( + "Getting the method IWaypointManager#if failed, any calls to IWaypointManagerReflection#getCurrentSubworldDescriptor will return an empty String."); + e.printStackTrace(); + } + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java index da609e09..ec216cfd 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java @@ -1,7 +1,5 @@ package com.sinthoras.visualprospecting.integration.voxelmap; -import java.util.TreeSet; - import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.OreVeinPosition; @@ -10,77 +8,76 @@ import com.thevoxelbox.voxelmap.interfaces.AbstractVoxelMap; import com.thevoxelbox.voxelmap.interfaces.IWaypointManager; import com.thevoxelbox.voxelmap.util.Waypoint; - import cpw.mods.fml.common.eventhandler.SubscribeEvent; import gregtech.api.GregTech_API; +import java.util.TreeSet; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.item.ItemStack; import net.minecraft.util.StatCollector; public class VoxelMapEventHandler { - - @SubscribeEvent - public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { - if(event.isCanceled()) { - return; - } - - OreVeinPosition pos = event.getPosition(); - IWaypointManager waypointManager = AbstractVoxelMap.getInstance().getWaypointManager(); - short[] color = GregTech_API.sGeneratedMaterials[pos.veinType.primaryOreMeta].getRGBA(); - TreeSet dim = new TreeSet<>(); - dim.add(pos.dimensionId); - - waypointManager.addWaypoint(new Waypoint( - StatCollector.translateToLocal(pos.veinType.name), // name - pos.getBlockX(), // X - pos.getBlockZ(), // Z - getY(), // Y - Config.enableVoxelMapWaypointsByDefault, // enabled - (float) color[0] / 255.0f, // red - (float) color[1] / 255.0f, // green - (float) color[2] / 255.0f, // blue - "Pickaxe", // icon - IWaypointManagerReflection.getCurrentSubworldDescriptor(waypointManager, false), // world - dim)); // dimension - } - - @SubscribeEvent - public void onFluidProspected(ProspectingNotificationEvent.UndergroundFluid event) { - if(event.isCanceled()) { - return; - } - - UndergroundFluidPosition pos = event.getPosition(); - IWaypointManager waypointManager = AbstractVoxelMap.getInstance().getWaypointManager(); - int x = Utils.coordChunkToBlock(pos.chunkX); - int z = Utils.coordChunkToBlock(pos.chunkZ); - int color = pos.fluid.getColor(); - TreeSet dim = new TreeSet<>(); - dim.add(pos.dimensionId); - - waypointManager.addWaypoint(new Waypoint( - pos.fluid.getLocalizedName(), // name - x, // X - z, // Z - Minecraft.getMinecraft().theWorld.getHeightValue(x, z), // Y - Config.enableVoxelMapWaypointsByDefault, // enabled - (float) (color >> 16 & 0xFF) / 255.0f, // red - (float) (color >> 8 & 0xFF) / 255.0f, // green - (float) (color & 0xFF) / 255.0f, // blue - "Science", // icon - IWaypointManagerReflection.getCurrentSubworldDescriptor(waypointManager, false), // world - dim)); // dimension - } - - private static int getY() { - EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer; - ItemStack heldItem = player.getHeldItem(); - if(heldItem == null || !heldItem.getUnlocalizedName().contains("gt.detrav.metatool.01")) { - return (int) player.posY; - } - return 65; - } + @SubscribeEvent + public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { + if (event.isCanceled()) { + return; + } + + OreVeinPosition pos = event.getPosition(); + IWaypointManager waypointManager = AbstractVoxelMap.getInstance().getWaypointManager(); + short[] color = GregTech_API.sGeneratedMaterials[pos.veinType.primaryOreMeta].getRGBA(); + TreeSet dim = new TreeSet<>(); + dim.add(pos.dimensionId); + + waypointManager.addWaypoint(new Waypoint( + StatCollector.translateToLocal(pos.veinType.name), // name + pos.getBlockX(), // X + pos.getBlockZ(), // Z + getY(), // Y + Config.enableVoxelMapWaypointsByDefault, // enabled + (float) color[0] / 255.0f, // red + (float) color[1] / 255.0f, // green + (float) color[2] / 255.0f, // blue + "Pickaxe", // icon + IWaypointManagerReflection.getCurrentSubworldDescriptor(waypointManager, false), // world + dim)); // dimension + } + + @SubscribeEvent + public void onFluidProspected(ProspectingNotificationEvent.UndergroundFluid event) { + if (event.isCanceled()) { + return; + } + + UndergroundFluidPosition pos = event.getPosition(); + IWaypointManager waypointManager = AbstractVoxelMap.getInstance().getWaypointManager(); + int x = Utils.coordChunkToBlock(pos.chunkX); + int z = Utils.coordChunkToBlock(pos.chunkZ); + int color = pos.fluid.getColor(); + TreeSet dim = new TreeSet<>(); + dim.add(pos.dimensionId); + + waypointManager.addWaypoint(new Waypoint( + pos.fluid.getLocalizedName(), // name + x, // X + z, // Z + Minecraft.getMinecraft().theWorld.getHeightValue(x, z), // Y + Config.enableVoxelMapWaypointsByDefault, // enabled + (float) (color >> 16 & 0xFF) / 255.0f, // red + (float) (color >> 8 & 0xFF) / 255.0f, // green + (float) (color & 0xFF) / 255.0f, // blue + "Science", // icon + IWaypointManagerReflection.getCurrentSubworldDescriptor(waypointManager, false), // world + dim)); // dimension + } + + private static int getY() { + EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer; + ItemStack heldItem = player.getHeldItem(); + if (heldItem == null || !heldItem.getUnlocalizedName().contains("gt.detrav.metatool.01")) { + return (int) player.posY; + } + return 65; + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java index 34332a99..b76a683d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java @@ -1,14 +1,13 @@ package com.sinthoras.visualprospecting.integration.xaerominimap; +import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; + import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.OreVeinWaypointManager; import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.ThaumcraftNodeWaypointManager; import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.WaypointManager; - import java.util.ArrayList; import java.util.List; -import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; - public class XaeroMiniMapState { public static XaeroMiniMapState instance = new XaeroMiniMapState(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java index 337051df..0c7ef6e2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java @@ -4,13 +4,13 @@ import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; -import xaero.common.minimap.waypoints.WaypointsManager; - import java.util.Hashtable; +import xaero.common.minimap.waypoints.WaypointsManager; public class WaypointManager extends com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager { - private static final Hashtable xWaypointTable = WaypointsManager.getCustomWaypoints(Tags.MODID); + private static final Hashtable xWaypointTable = + WaypointsManager.getCustomWaypoints(Tags.MODID); private WaypointWithDimension xWaypoint; private final WaypointType waypointType; @@ -36,9 +36,19 @@ public WaypointWithDimension getXWaypoint() { @Override public void updateActiveWaypoint(Waypoint waypoint) { - if (!hasWaypoint() || waypoint.blockX != xWaypoint.getX() || waypoint.blockY != xWaypoint.getY() || - waypoint.blockZ != xWaypoint.getZ() || waypoint.dimensionId != xWaypoint.getDimID()) { - xWaypoint = new WaypointWithDimension(waypoint.blockX, waypoint.blockY, waypoint.blockZ, waypoint.label, getSymbol(waypoint), 15, waypoint.dimensionId); + if (!hasWaypoint() + || waypoint.blockX != xWaypoint.getX() + || waypoint.blockY != xWaypoint.getY() + || waypoint.blockZ != xWaypoint.getZ() + || waypoint.dimensionId != xWaypoint.getDimID()) { + xWaypoint = new WaypointWithDimension( + waypoint.blockX, + waypoint.blockY, + waypoint.blockZ, + waypoint.label, + getSymbol(waypoint), + 15, + waypoint.dimensionId); xWaypointTable.put(waypointType.ordinal(), xWaypoint); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java index 0683b4e5..3caca6a8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java @@ -1,19 +1,15 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap; +import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; + import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.LayerButton; import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.OreVeinButton; import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.ThaumcraftNodeButton; import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.UndergroundFluidButton; import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.*; -import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.OreVeinWaypointManager; -import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.ThaumcraftNodeWaypointManager; -import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.WaypointManager; - import java.util.ArrayList; import java.util.List; -import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; - public class XaeroWorldMapState { public static XaeroWorldMapState instance = new XaeroWorldMapState(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java index f29b5ad2..aa959e55 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java @@ -1,5 +1,6 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons; +import java.util.function.Consumer; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiButton; @@ -8,8 +9,6 @@ import xaero.map.gui.CursorBox; import xaero.map.gui.GuiTexturedButton; -import java.util.function.Consumer; - public class SizedGuiTexturedButton extends GuiTexturedButton { private static final int BUTTON_WIDTH = 20; @@ -19,7 +18,8 @@ public class SizedGuiTexturedButton extends GuiTexturedButton { protected boolean active; - public SizedGuiTexturedButton(int x, int y, ResourceLocation texture, Consumer action, CursorBox tooltip) { + public SizedGuiTexturedButton( + int x, int y, ResourceLocation texture, Consumer action, CursorBox tooltip) { super(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, 0, 0, ICON_WIDTH, ICON_HEIGHT, texture, action, tooltip); active = false; } @@ -34,12 +34,10 @@ public void drawButton(Minecraft minecraft, int mouseX, int mouseY) { if (isMouseOver(mouseX, mouseY)) { iconY--; GL11.glColor4f(0.5F, 0.9F, 0.5F, 1.0F); - } - else { + } else { GL11.glColor4f(0.5882F, 0.9882F, 0.5882F, 1.0F); } - } - else { + } else { if (isMouseOver(mouseX, mouseY)) { iconY--; GL11.glColor4f(0.9F, 0.9F, 0.9F, 1.0F); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java index 93e0b8af..fc176354 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java @@ -4,9 +4,8 @@ import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.InteractableRenderStep; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; -import net.minecraft.client.gui.GuiScreen; - import java.util.List; +import net.minecraft.client.gui.GuiScreen; public abstract class InteractableLayerRenderer extends LayerRenderer { private double mouseXForRender; @@ -21,13 +20,15 @@ public InteractableLayerRenderer(WaypointProviderManager manager) { } @Override - protected abstract List generateRenderSteps(List visibleElements); + protected abstract List generateRenderSteps( + List visibleElements); public void updateHovered(double mouseX, double mouseY, double cameraX, double cameraZ, double scale) { mouseXForRender = mouseX - cameraX; mouseYForRender = mouseY - cameraZ; for (RenderStep step : renderStepsReversed) { - if (step instanceof InteractableRenderStep && ((InteractableRenderStep) step).isMouseOver(mouseXForRender, mouseYForRender, scale)) { + if (step instanceof InteractableRenderStep + && ((InteractableRenderStep) step).isMouseOver(mouseXForRender, mouseYForRender, scale)) { hovered = (InteractableRenderStep) step; return; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java index ea7e4d77..78fd86b0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java @@ -4,7 +4,6 @@ import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -40,5 +39,6 @@ public void updateVisibleElements(List visibleEleme Collections.reverse(renderStepsReversed); } - protected abstract List generateRenderSteps(List visibleElements); + protected abstract List generateRenderSteps( + List visibleElements); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java index 798cfbcb..af07fa00 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java @@ -4,7 +4,6 @@ import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.OreVeinRenderStep; - import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java index 2336923c..70a6ff6a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java @@ -4,7 +4,6 @@ import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.ThaumcraftNodeRenderStep; - import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java index f3ebe260..7ef9e675 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java @@ -4,7 +4,6 @@ import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.UndergroundFluidChunkRenderStep; - import java.util.ArrayList; import java.util.List; @@ -16,7 +15,8 @@ public UndergroundFluidChunkRenderer() { } @Override - protected List generateRenderSteps(List visibleElements) { + protected List generateRenderSteps( + List visibleElements) { final List renderSteps = new ArrayList<>(); visibleElements.stream() .map(element -> (UndergroundFluidChunkLocation) element) diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java index fe63816c..a024c279 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java @@ -4,7 +4,6 @@ import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.UndergroundFluidRenderStep; - import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java index 93660d1c..b8962ab9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java @@ -12,5 +12,4 @@ public interface InteractableRenderStep extends RenderStep { void onActionButton(); IWaypointAndLocationProvider getLocationProvider(); - } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java index 690350df..2f6832d0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java @@ -6,6 +6,9 @@ import com.sinthoras.visualprospecting.integration.DrawUtils; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.resources.I18n; import net.minecraft.init.Blocks; @@ -13,10 +16,6 @@ import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; - public class OreVeinRenderStep implements InteractableRenderStep { private final OreVeinLocation oreVeinLocation; @@ -42,28 +41,44 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double GL11.glScaled(1 / scaleForGui, 1 / scaleForGui, 1); DrawUtils.drawQuad(blockStoneIcon, -iconSizeHalf, -iconSizeHalf, iconSize, iconSize, 0xFFFFFF, 255); - DrawUtils.drawQuad(oreVeinLocation.getIconFromPrimaryOre(), -iconSizeHalf, -iconSizeHalf, iconSize, iconSize, oreVeinLocation.getColor(), 255); + DrawUtils.drawQuad( + oreVeinLocation.getIconFromPrimaryOre(), + -iconSizeHalf, + -iconSizeHalf, + iconSize, + iconSize, + oreVeinLocation.getColor(), + 255); if (!oreVeinLocation.drawSearchHighlight() || oreVeinLocation.isDepleted()) { - DrawUtils.drawGradientRect(-iconSizeHalf, -iconSizeHalf, iconSizeHalf, iconSizeHalf, 0, 0x96000000, 0x96000000); + DrawUtils.drawGradientRect( + -iconSizeHalf, -iconSizeHalf, iconSizeHalf, iconSizeHalf, 0, 0x96000000, 0x96000000); if (oreVeinLocation.isDepleted()) { - DrawUtils.drawQuad(depletedTextureLocation, -iconSizeHalf, -iconSizeHalf, iconSize, iconSize, 0xFFFFFF, 255); + DrawUtils.drawQuad( + depletedTextureLocation, -iconSizeHalf, -iconSizeHalf, iconSize, iconSize, 0xFFFFFF, 255); } } - if (gui != null && scale >= Utils.journeyMapScaleToLinear(Config.minZoomLevelForOreLabel) && !oreVeinLocation.isDepleted()) { + if (gui != null + && scale >= Utils.journeyMapScaleToLinear(Config.minZoomLevelForOreLabel) + && !oreVeinLocation.isDepleted()) { final int fontColor = oreVeinLocation.drawSearchHighlight() ? 0xFFFFFFFF : 0xFF7F7F7F; String text = I18n.format(oreVeinLocation.getName()); - DrawUtils.drawSimpleLabel(gui, text, 0, -iconSizeHalf - gui.mc.fontRenderer.FONT_HEIGHT - 5, fontColor, 0xB4000000, true); + DrawUtils.drawSimpleLabel( + gui, text, 0, -iconSizeHalf - gui.mc.fontRenderer.FONT_HEIGHT - 5, fontColor, 0xB4000000, true); } if (oreVeinLocation.isActiveAsWaypoint()) { final double thickness = iconSize / 8; final int color = 0xFFFFD700; - DrawUtils.drawGradientRect(-iconSizeHalf - thickness, -iconSizeHalf - thickness, iconSizeHalf, -iconSizeHalf, 0, color, color); - DrawUtils.drawGradientRect(iconSizeHalf, -iconSizeHalf - thickness, iconSizeHalf + thickness, iconSizeHalf, 0, color, color); - DrawUtils.drawGradientRect(-iconSizeHalf, iconSizeHalf, iconSizeHalf + thickness, iconSizeHalf + thickness, 0, color, color); - DrawUtils.drawGradientRect(-iconSizeHalf - thickness, -iconSizeHalf, -iconSizeHalf, iconSizeHalf + thickness, 0, color, color); + DrawUtils.drawGradientRect( + -iconSizeHalf - thickness, -iconSizeHalf - thickness, iconSizeHalf, -iconSizeHalf, 0, color, color); + DrawUtils.drawGradientRect( + iconSizeHalf, -iconSizeHalf - thickness, iconSizeHalf + thickness, iconSizeHalf, 0, color, color); + DrawUtils.drawGradientRect( + -iconSizeHalf, iconSizeHalf, iconSizeHalf + thickness, iconSizeHalf + thickness, 0, color, color); + DrawUtils.drawGradientRect( + -iconSizeHalf - thickness, -iconSizeHalf, -iconSizeHalf, iconSizeHalf + thickness, 0, color, color); } GL11.glPopMatrix(); @@ -79,7 +94,7 @@ public boolean isMouseOver(double mouseX, double mouseY, double scale) { @Override public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scale, int scaleAdj) { - //correct for gl matrix differences + // correct for gl matrix differences mouseX = mouseX * scale + (gui.mc.displayWidth >> 1); mouseY = mouseY * scale + (gui.mc.displayHeight >> 1); @@ -98,7 +113,8 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal GL11.glPushMatrix(); - DrawUtils.drawSimpleTooltip(gui, tooltip, mouseX / scaleAdj + 6, mouseY / scaleAdj - 12, 0xFFFFFFFF, 0x86000000); + DrawUtils.drawSimpleTooltip( + gui, tooltip, mouseX / scaleAdj + 6, mouseY / scaleAdj - 12, 0xFFFFFFFF, 0x86000000); GL11.glPopMatrix(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java index 762f6da6..4e9927af 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java @@ -1,8 +1,7 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; -import net.minecraft.client.gui.GuiScreen; - import javax.annotation.Nullable; +import net.minecraft.client.gui.GuiScreen; public interface RenderStep { void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double scale); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java index 126b2bb9..ea5d0f5c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java @@ -5,18 +5,19 @@ import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; +import javax.annotation.Nullable; import net.minecraft.client.gui.GuiScreen; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; import thaumcraft.api.aspects.Aspect; import thaumcraft.client.lib.UtilsFX; -import javax.annotation.Nullable; - public class ThaumcraftNodeRenderStep implements InteractableRenderStep { - private static final ResourceLocation markedTextureLocation = new ResourceLocation(Tags.MODID, "textures/node_marked.png"); - private static final ResourceLocation unmarkedTextureLocation = new ResourceLocation(Tags.MODID, "textures/node_unmarked.png"); + private static final ResourceLocation markedTextureLocation = + new ResourceLocation(Tags.MODID, "textures/node_marked.png"); + private static final ResourceLocation unmarkedTextureLocation = + new ResourceLocation(Tags.MODID, "textures/node_unmarked.png"); private final ThaumcraftNodeLocation thaumcraftNodeLocation; @@ -38,11 +39,19 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double clickableRadiusPixelSquared = borderSizeHalf * borderSizeHalf; GL11.glPushMatrix(); - GL11.glTranslated(thaumcraftNodeLocation.getBlockX() - cameraX, thaumcraftNodeLocation.getBlockZ() - cameraZ, 0); + GL11.glTranslated( + thaumcraftNodeLocation.getBlockX() - cameraX, thaumcraftNodeLocation.getBlockZ() - cameraZ, 0); GL11.glScaled(1 / scaleForGui, 1 / scaleForGui, 1); final int alpha = 204; - DrawUtils.drawQuad(thaumcraftNodeLocation.isActiveAsWaypoint() ? markedTextureLocation : unmarkedTextureLocation, -borderSizeHalf, -borderSizeHalf, borderSize, borderSize, 0xFFFFFF, alpha); + DrawUtils.drawQuad( + thaumcraftNodeLocation.isActiveAsWaypoint() ? markedTextureLocation : unmarkedTextureLocation, + -borderSizeHalf, + -borderSizeHalf, + borderSize, + borderSize, + 0xFFFFFF, + alpha); final int aspectPixelDiameter = 32; DrawUtils.drawAspect(0, 0, aspectPixelDiameter, thaumcraftNodeLocation.getStrongestAspect(), 0); @@ -72,7 +81,10 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal final String nodeDescription = thaumcraftNodeLocation.getDescription(); final String deleteHint = thaumcraftNodeLocation.getDeleteHint(); - int maxTextWidth = Math.max(Math.max(gui.mc.fontRenderer.getStringWidth(title), gui.mc.fontRenderer.getStringWidth(nodeDescription)), gui.mc.fontRenderer.getStringWidth(deleteHint)); + int maxTextWidth = Math.max( + Math.max( + gui.mc.fontRenderer.getStringWidth(title), gui.mc.fontRenderer.getStringWidth(nodeDescription)), + gui.mc.fontRenderer.getStringWidth(deleteHint)); if (isWaypoint) { maxTextWidth = Math.max(maxTextWidth, gui.mc.fontRenderer.getStringWidth(asWaypoint)); } @@ -80,7 +92,8 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal maxTextWidth = (int) Math.ceil(maxTextWidth * 1.25f); } - final int aspectRows = (thaumcraftNodeLocation.getAspects().size() + 4) / 5; // Equivalent to Math.ceil(size / 5) + final int aspectRows = + (thaumcraftNodeLocation.getAspects().size() + 4) / 5; // Equivalent to Math.ceil(size / 5) final int aspectColumns = Math.min(thaumcraftNodeLocation.getAspects().size(), 5); int pixelX = (int) (mouseX + 12); @@ -98,11 +111,31 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal // Draw background final int backgroundColor = 0xF0100010; - DrawUtils.drawGradientRect(pixelX - 3, pixelY - 4, pixelX + tooltipWidth + 3, pixelY - 3, backgroundColor, backgroundColor); - DrawUtils.drawGradientRect(pixelX - 3, pixelY + tooltipHeight + 3, pixelX + tooltipWidth + 3, pixelY + tooltipHeight + 4, backgroundColor, backgroundColor); - DrawUtils.drawGradientRect(pixelX - 3, pixelY - 3, pixelX + tooltipWidth + 3, pixelY + tooltipHeight + 3, backgroundColor, backgroundColor); - DrawUtils.drawGradientRect(pixelX - 4, pixelY - 3, pixelX - 3, pixelY + tooltipHeight + 3, backgroundColor, backgroundColor); - DrawUtils.drawGradientRect(pixelX + tooltipWidth + 3, pixelY - 3, pixelX + tooltipWidth + 4, pixelY + tooltipHeight + 3, backgroundColor, backgroundColor); + DrawUtils.drawGradientRect( + pixelX - 3, pixelY - 4, pixelX + tooltipWidth + 3, pixelY - 3, backgroundColor, backgroundColor); + DrawUtils.drawGradientRect( + pixelX - 3, + pixelY + tooltipHeight + 3, + pixelX + tooltipWidth + 3, + pixelY + tooltipHeight + 4, + backgroundColor, + backgroundColor); + DrawUtils.drawGradientRect( + pixelX - 3, + pixelY - 3, + pixelX + tooltipWidth + 3, + pixelY + tooltipHeight + 3, + backgroundColor, + backgroundColor); + DrawUtils.drawGradientRect( + pixelX - 4, pixelY - 3, pixelX - 3, pixelY + tooltipHeight + 3, backgroundColor, backgroundColor); + DrawUtils.drawGradientRect( + pixelX + tooltipWidth + 3, + pixelY - 3, + pixelX + tooltipWidth + 4, + pixelY + tooltipHeight + 3, + backgroundColor, + backgroundColor); // Draw text int offset = 0; @@ -116,10 +149,15 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal gui.mc.fontRenderer.drawString(title, pixelX + tooltipWidth - titleWidth, pixelY + offset, 0xFFFFFFFF); offset += 12; final int nodeDescriptonWidth = (int) Math.ceil(gui.mc.fontRenderer.getStringWidth(nodeDescription) * 1.1f); - gui.mc.fontRenderer.drawString(nodeDescription, pixelX + nodeDescriptonWidth - titleWidth, pixelY + offset, 0xFFFFFFFF); + gui.mc.fontRenderer.drawString( + nodeDescription, pixelX + nodeDescriptonWidth - titleWidth, pixelY + offset, 0xFFFFFFFF); final int deleteHintWidth = (int) Math.ceil(gui.mc.fontRenderer.getStringWidth(deleteHint) * 1.1f); - gui.mc.fontRenderer.drawString(deleteHint, pixelX + tooltipWidth - deleteHintWidth, pixelY + aspectRows * 16 + offset + 12, 0xFFFFFFFF); + gui.mc.fontRenderer.drawString( + deleteHint, + pixelX + tooltipWidth - deleteHintWidth, + pixelY + aspectRows * 16 + offset + 12, + 0xFFFFFFFF); } else { if (isWaypoint) { gui.mc.fontRenderer.drawString(asWaypoint, pixelX, pixelY, 0xFFFFFFFF); @@ -136,10 +174,18 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal int aspectX = 0; int aspectY = 0; - for (Aspect aspect : thaumcraftNodeLocation.getAspects().getAspectsSortedAmount()) { GL11.glPushMatrix(); - UtilsFX.drawTag(pixelX + aspectX * 16, pixelY + aspectY * 16 + offset + 10, aspect, thaumcraftNodeLocation.getAspects().getAmount(aspect), 0, 0.01, 1, 1, false); + UtilsFX.drawTag( + pixelX + aspectX * 16, + pixelY + aspectY * 16 + offset + 10, + aspect, + thaumcraftNodeLocation.getAspects().getAmount(aspect), + 0, + 0.01, + 1, + 1, + false); GL11.glPopMatrix(); ++aspectX; if (aspectX >= 5) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java index d2a1d595..9412107d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java @@ -5,11 +5,10 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.DrawUtils; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; +import javax.annotation.Nullable; import net.minecraft.client.gui.GuiScreen; import org.lwjgl.opengl.GL11; -import javax.annotation.Nullable; - public class UndergroundFluidChunkRenderStep implements RenderStep { private final UndergroundFluidChunkLocation undergroundFluidChunkLocation; @@ -26,12 +25,19 @@ private String getFluidAmountFormatted() { @Override public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double scale) { - if (undergroundFluidChunkLocation.getFluidAmount() > 0 && scale >= Utils.journeyMapScaleToLinear(Config.minZoomLevelForUndergroundFluidDetails)) { + if (undergroundFluidChunkLocation.getFluidAmount() > 0 + && scale >= Utils.journeyMapScaleToLinear(Config.minZoomLevelForUndergroundFluidDetails)) { GL11.glPushMatrix(); - GL11.glTranslated(undergroundFluidChunkLocation.getBlockX() - 0.5 - cameraX, undergroundFluidChunkLocation.getBlockZ() - 0.5 - cameraZ, 0); - - float alpha = ((float) (undergroundFluidChunkLocation.getFluidAmount() - undergroundFluidChunkLocation.getMinAmountInField())) / - (undergroundFluidChunkLocation.getMaxAmountInField() - undergroundFluidChunkLocation.getMinAmountInField() + 1); + GL11.glTranslated( + undergroundFluidChunkLocation.getBlockX() - 0.5 - cameraX, + undergroundFluidChunkLocation.getBlockZ() - 0.5 - cameraZ, + 0); + + float alpha = ((float) (undergroundFluidChunkLocation.getFluidAmount() + - undergroundFluidChunkLocation.getMinAmountInField())) + / (undergroundFluidChunkLocation.getMaxAmountInField() + - undergroundFluidChunkLocation.getMinAmountInField() + + 1); alpha *= alpha * 204; int fluidColor = undergroundFluidChunkLocation.getFluid().getColor() | (((int) alpha) << 24); DrawUtils.drawGradientRect(0, 0, VP.chunkWidth, VP.chunkDepth, 0, fluidColor, fluidColor); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java index 8a1e4207..587b396b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java @@ -3,11 +3,10 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.DrawUtils; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; +import javax.annotation.Nullable; import net.minecraft.client.gui.GuiScreen; import org.lwjgl.opengl.GL11; -import javax.annotation.Nullable; - public class UndergroundFluidRenderStep implements RenderStep { private final UndergroundFluidLocation undergroundFluidLocation; @@ -22,7 +21,10 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double // < 0.5 scale is when scaling issues show up if (maxAmountInField > 0 && scale >= 0.5) { GL11.glPushMatrix(); - GL11.glTranslated(undergroundFluidLocation.getBlockX() - 0.5 - cameraX, undergroundFluidLocation.getBlockZ() - 0.5 - cameraZ, 0); + GL11.glTranslated( + undergroundFluidLocation.getBlockX() - 0.5 - cameraX, + undergroundFluidLocation.getBlockZ() - 0.5 - cameraZ, + 0); final int borderColor = undergroundFluidLocation.getFluid().getColor() | 0xCC000000; final double lenX = VP.undergroundFluidSizeChunkX * VP.chunkWidth; @@ -35,7 +37,8 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double // min scale that journeymap can go to if (scale >= 1 && gui != null) { GL11.glScaled(1 / scale, 1 / scale, 1); - final String label = undergroundFluidLocation.getMinProduction() + "L - " + maxAmountInField + "L " + undergroundFluidLocation.getFluid().getLocalizedName(); + final String label = undergroundFluidLocation.getMinProduction() + "L - " + maxAmountInField + "L " + + undergroundFluidLocation.getFluid().getLocalizedName(); DrawUtils.drawSimpleLabel(gui, label, VP.chunkWidth * scale, 0, 0xFFFFFFFF, 0xB4000000, false); } diff --git a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java index 1c7f368d..a2cae21e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java +++ b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java @@ -7,6 +7,7 @@ import com.sinthoras.visualprospecting.task.SnapshotUploadTask; import com.sinthoras.visualprospecting.task.TaskManager; import gregtech.api.GregTech_API; +import java.util.List; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -18,8 +19,6 @@ import net.minecraft.util.IChatComponent; import net.minecraft.world.World; -import java.util.List; - public class ProspectorsLog extends Item { public static ProspectorsLog instance; @@ -33,47 +32,47 @@ public ProspectorsLog() { @Override public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer player) { - if(isFilledLog(item) == false) { + if (isFilledLog(item) == false) { final NBTTagCompound compound = new NBTTagCompound(); compound.setString(Tags.PROSPECTORSLOG_AUTHOR, player.getDisplayName()); - compound.setString(Tags.PROSPECTORSLOG_AUTHOR_ID, player.getPersistentID().toString()); + compound.setString( + Tags.PROSPECTORSLOG_AUTHOR_ID, player.getPersistentID().toString()); item.setTagCompound(compound); if (world.isRemote) { TaskManager.instance.addTask(new SnapshotUploadTask()); - } - else { + } else { final int random = VP.randomGeneration.nextInt(1000); - if(random < 5) { + if (random < 5) { final String localizationKey = "item.visualprospecting.prospectorslog.creation.fail" + random; final IChatComponent notification = new ChatComponentTranslation(localizationKey); notification.getChatStyle().setItalic(true); notification.getChatStyle().setColor(EnumChatFormatting.GRAY); player.addChatMessage(notification); player.destroyCurrentEquippedItem(); - } - else { - final IChatComponent notification = new ChatComponentTranslation("item.visualprospecting.prospectorslog.creation.begin"); + } else { + final IChatComponent notification = + new ChatComponentTranslation("item.visualprospecting.prospectorslog.creation.begin"); notification.getChatStyle().setItalic(true); notification.getChatStyle().setColor(EnumChatFormatting.GRAY); player.addChatMessage(notification); } } - } - else if(world.isRemote == false){ + } else if (world.isRemote == false) { final NBTTagCompound compound = item.getTagCompound(); final String authorUuid = compound.getString(Tags.PROSPECTORSLOG_AUTHOR_ID); - if(authorUuid.equals(player.getPersistentID().toString()) == false) { - final int random = VP.randomGeneration.nextInt(TransferCache.instance.isClientDataAvailable(authorUuid) ? 1000 : 5); - if(random < 5) { + if (authorUuid.equals(player.getPersistentID().toString()) == false) { + final int random = VP.randomGeneration.nextInt( + TransferCache.instance.isClientDataAvailable(authorUuid) ? 1000 : 5); + if (random < 5) { final String localizationKey = "item.visualprospecting.prospectorslog.reading.fail" + random; final IChatComponent notification = new ChatComponentTranslation(localizationKey); notification.getChatStyle().setItalic(true); notification.getChatStyle().setColor(EnumChatFormatting.GRAY); player.addChatMessage(notification); player.destroyCurrentEquippedItem(); - } - else { - final IChatComponent notification = new ChatComponentTranslation("item.visualprospecting.prospectorslog.reading.begin"); + } else { + final IChatComponent notification = + new ChatComponentTranslation("item.visualprospecting.prospectorslog.reading.begin"); notification.getChatStyle().setItalic(true); notification.getChatStyle().setColor(EnumChatFormatting.GRAY); player.addChatMessage(notification); @@ -86,17 +85,19 @@ else if(world.isRemote == false){ @Override public void addInformation(ItemStack item, EntityPlayer player, List infoList, boolean ignored) { - if(isFilledLog(item)) { + if (isFilledLog(item)) { final NBTTagCompound compound = item.getTagCompound(); - infoList.add(I18n.format("item.visualprospecting.prospectorslog.author", compound.getString(Tags.PROSPECTORSLOG_AUTHOR))); - } - else { + infoList.add(I18n.format( + "item.visualprospecting.prospectorslog.author", compound.getString(Tags.PROSPECTORSLOG_AUTHOR))); + } else { infoList.add(I18n.format("item.visualprospecting.prospectorslog.empty")); } } private boolean isFilledLog(ItemStack item) { final NBTTagCompound compound = item.getTagCompound(); - return compound != null && compound.hasKey(Tags.PROSPECTORSLOG_AUTHOR) && compound.hasKey(Tags.PROSPECTORSLOG_AUTHOR_ID); + return compound != null + && compound.hasKey(Tags.PROSPECTORSLOG_AUTHOR) + && compound.hasKey(Tags.PROSPECTORSLOG_AUTHOR_ID); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java index 289f2a4e..8a6d0e9d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java @@ -10,7 +10,8 @@ public enum Mixin { // // IMPORTANT: Do not make any references to any mod from this file. This file is loaded quite early on and if - // you refer to other mods you load them as well. The consequence is: You can't inject any previously loaded classes! + // you refer to other mods you load them as well. The consequence is: You can't inject any previously loaded + // classes! // Exception: Tags.java, as long as it is used for Strings only! // @@ -59,8 +60,8 @@ public enum Mixin { public boolean shouldLoad(List loadedMods) { return (side == Side.BOTH - || side == Side.SERVER && FMLLaunchHandler.side().isServer() - || side == Side.CLIENT && FMLLaunchHandler.side().isClient()) + || side == Side.SERVER && FMLLaunchHandler.side().isServer() + || side == Side.CLIENT && FMLLaunchHandler.side().isClient()) && loadedMods.containsAll(targetedMods); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java index 4a0ebdaa..f9e5be88 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java @@ -27,9 +27,7 @@ public class MixinPlugin implements IMixinConfigPlugin { private static final Path MODS_DIRECTORY_PATH = new File(Launch.minecraftHome, "mods/").toPath(); @Override - public void onLoad(String mixinPackage) { - - } + public void onLoad(String mixinPackage) {} @Override public String getRefMapperConfig() { @@ -42,9 +40,7 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { } @Override - public void acceptTargets(Set myTargets, Set otherTargets) { - - } + public void acceptTargets(Set myTargets, Set otherTargets) {} // This method return a List of mixins. Every mixins in this list will be loaded. @Override @@ -52,16 +48,13 @@ public List getMixins() { final boolean isDevelopmentEnvironment = (boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment"); List loadedMods = Arrays.stream(TargetedMod.values()) - .filter(mod -> mod == VANILLA - || (mod.loadInDevelopment && isDevelopmentEnvironment) - || loadJarOf(mod)) + .filter(mod -> mod == VANILLA || (mod.loadInDevelopment && isDevelopmentEnvironment) || loadJarOf(mod)) .collect(Collectors.toList()); - + for (TargetedMod mod : TargetedMod.values()) { - if(loadedMods.contains(mod)) { + if (loadedMods.contains(mod)) { LOG.info("Found " + mod.modName + "! Integrating now..."); - } - else { + } else { LOG.info("Could not find " + mod.modName + "! Skipping integration...."); } } @@ -79,19 +72,18 @@ public List getMixins() { private boolean loadJarOf(final TargetedMod mod) { try { File jar = findJarOf(mod); - if(jar == null) { + if (jar == null) { LOG.info("Jar not found for " + mod); return false; } LOG.info("Attempting to add " + jar + " to the URL Class Path"); - if(!jar.exists()) { + if (!jar.exists()) { throw new FileNotFoundException(jar.toString()); } MinecraftURLClassPath.addJar(jar); return true; - } - catch (Exception e) { + } catch (Exception e) { e.printStackTrace(); return false; } @@ -100,24 +92,19 @@ private boolean loadJarOf(final TargetedMod mod) { public static File findJarOf(final TargetedMod mod) { try { return walk(MODS_DIRECTORY_PATH) - .filter(mod::isMatchingJar) - .map(Path::toFile) - .findFirst() - .orElse(null); - } - catch (IOException e) { + .filter(mod::isMatchingJar) + .map(Path::toFile) + .findFirst() + .orElse(null); + } catch (IOException e) { e.printStackTrace(); return null; } } @Override - public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { - - } + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} @Override - public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { - - } + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java index 84813210..71204228 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java @@ -7,7 +7,8 @@ public enum TargetedMod { // // IMPORTANT: Do not make any references to any mod from this file. This file is loaded quite early on and if - // you refer to other mods you load them as well. The consequence is: You can't inject any previously loaded classes! + // you refer to other mods you load them as well. The consequence is: You can't inject any previously loaded + // classes! // Exception: Tags.java, as long as it is used for Strings only! // @@ -24,7 +25,8 @@ public enum TargetedMod { public final String modName; public final String jarNamePrefixLowercase; - // Optional dependencies can be omitted in development. Especially skipping GT5U will drastically speed up your game start! + // Optional dependencies can be omitted in development. Especially skipping GT5U will drastically speed up your game + // start! public final boolean loadInDevelopment; TargetedMod(String modName, String jarNamePrefix, boolean loadInDevelopment) { @@ -37,15 +39,15 @@ public boolean isMatchingJar(Path path) { final String pathString = path.toString(); final String nameLowerCase = Files.getNameWithoutExtension(pathString).toLowerCase(); final String fileExtension = Files.getFileExtension(pathString); - - return nameLowerCase.startsWith(jarNamePrefixLowercase) && ("jar".equals(fileExtension) || "litemod".equals(fileExtension)); + + return nameLowerCase.startsWith(jarNamePrefixLowercase) + && ("jar".equals(fileExtension) || "litemod".equals(fileExtension)); } @Override public String toString() { - return "TargetedMod{" + - "modName='" + modName + '\'' + - ", jarNamePrefixLowercase='" + jarNamePrefixLowercase + '\'' + - '}'; + return "TargetedMod{" + "modName='" + + modName + '\'' + ", jarNamePrefixLowercase='" + + jarNamePrefixLowercase + '\'' + '}'; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java index 884b8b70..a5b415c0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java @@ -4,26 +4,43 @@ import com.github.bartimaeusnek.bartworks.system.oregen.BW_WordGenerator; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.ServerCache; +import java.util.Random; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import java.util.Random; - @Mixin(BW_WordGenerator.WorldGenContainer.class) public class WorldGenContainerMixin { - @Redirect(method = "run", - at = @At(value = "INVOKE", - target = "Lcom/github/bartimaeusnek/bartworks/system/oregen/BW_OreLayer;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), + @Redirect( + method = "run", + at = + @At( + value = "INVOKE", + target = + "Lcom/github/bartimaeusnek/bartworks/system/oregen/BW_OreLayer;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), remap = false, require = 1) - private boolean onOreVeinGenerationAttempt(BW_OreLayer worldGen, World world, Random random, String biome, int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { - final boolean oreVeinPlaced = worldGen.executeWorldgen(world, random, biome, Integer.MIN_VALUE, blockX, blockZ, chunkGenerator, chunkProvider); - if(oreVeinPlaced) { - ServerCache.instance.notifyOreVeinGeneration(world.provider.dimensionId, Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockX)), Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockZ)), worldGen.mWorldGenName); + private boolean onOreVeinGenerationAttempt( + BW_OreLayer worldGen, + World world, + Random random, + String biome, + int dimensionType, + int blockX, + int blockZ, + IChunkProvider chunkGenerator, + IChunkProvider chunkProvider) { + final boolean oreVeinPlaced = worldGen.executeWorldgen( + world, random, biome, Integer.MIN_VALUE, blockX, blockZ, chunkGenerator, chunkProvider); + if (oreVeinPlaced) { + ServerCache.instance.notifyOreVeinGeneration( + world.provider.dimensionId, + Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockX)), + Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockZ)), + worldGen.mWorldGenName); } return oreVeinPlaced; } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java index cd834c46..88867dd8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java @@ -4,26 +4,43 @@ import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.ServerCache; import gregtech.api.world.GT_Worldgen; +import java.util.Random; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import java.util.Random; - @Mixin(GT_Worldgenerator_Space.class) public class GT_Worldgenerator_SpaceMixin { - @Redirect(method = "Generate_OreVeins", - at = @At(value = "INVOKE", - target = "Lgregtech/api/world/GT_Worldgen;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), + @Redirect( + method = "Generate_OreVeins", + at = + @At( + value = "INVOKE", + target = + "Lgregtech/api/world/GT_Worldgen;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), remap = false, require = 1) - private boolean onOreVeinGenerated(GT_Worldgen worldGen, World world, Random random, String biome, int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { - final boolean oreVeinPlaced = worldGen.executeWorldgen(world, random, biome, Integer.MIN_VALUE, blockX, blockZ, chunkGenerator, chunkProvider); - if(oreVeinPlaced) { - ServerCache.instance.notifyOreVeinGeneration(world.provider.dimensionId, Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockX)), Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockZ)), worldGen.mWorldGenName); + private boolean onOreVeinGenerated( + GT_Worldgen worldGen, + World world, + Random random, + String biome, + int dimensionType, + int blockX, + int blockZ, + IChunkProvider chunkGenerator, + IChunkProvider chunkProvider) { + final boolean oreVeinPlaced = worldGen.executeWorldgen( + world, random, biome, Integer.MIN_VALUE, blockX, blockZ, chunkGenerator, chunkProvider); + if (oreVeinPlaced) { + ServerCache.instance.notifyOreVeinGeneration( + world.provider.dimensionId, + Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockX)), + Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockZ)), + worldGen.mWorldGenName); } return oreVeinPlaced; } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java index 1975cec2..0e5d9cef 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java @@ -15,7 +15,16 @@ protected GT_Block_Ores_AbstractMixin() { } @Override - public boolean onBlockActivated(World world, int blockX, int blockY, int blockZ, EntityPlayer player, int side, float offsetX, float offsetY, float offsetZ) { + public boolean onBlockActivated( + World world, + int blockX, + int blockY, + int blockZ, + EntityPlayer player, + int side, + float offsetX, + float offsetY, + float offsetZ) { ClientCache.instance.onOreInteracted(world, blockX, blockY, blockZ, player); return super.onBlockActivated(world, blockX, blockY, blockZ, player, side, offsetX, offsetY, offsetZ); } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java index ffe5358a..11b7368d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java @@ -1,9 +1,12 @@ package com.sinthoras.visualprospecting.mixins.gregtech; +import static gregtech.api.util.GT_Utility.ItemNBT.getNBT; +import static gregtech.api.util.GT_Utility.ItemNBT.setNBT; + import com.sinthoras.visualprospecting.ServerTranslations; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import gregtech.api.enums.ItemList; @@ -14,6 +17,7 @@ import gregtech.api.util.GT_Utility; import gregtech.common.tileentities.machines.basic.GT_MetaTileEntity_AdvSeismicProspector; import ic2.core.Ic2Items; +import java.util.List; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.Item; @@ -23,11 +27,6 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import java.util.List; - -import static gregtech.api.util.GT_Utility.ItemNBT.getNBT; -import static gregtech.api.util.GT_Utility.ItemNBT.setNBT; - @Mixin(value = GT_MetaTileEntity_AdvSeismicProspector.class, remap = false) public abstract class GT_MetaTileEntity_AdvSeismicProspectorMixin extends GT_MetaTileEntity_BasicMachine { @@ -51,17 +50,19 @@ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlaye if (aBaseMetaTileEntity.isServerSide()) { ItemStack aStack = aPlayer.getCurrentEquippedItem(); - if (!ready && (GT_Utility.consumeItems(aPlayer, aStack, Item.getItemFromBlock(Blocks.tnt), 16) - || GT_Utility.consumeItems(aPlayer, aStack, Ic2Items.industrialTnt.getItem(), 8) - || GT_Utility.consumeItems(aPlayer, aStack, Materials.Glyceryl, 4) - || GT_Utility.consumeItems(aPlayer, aStack, ItemList.Block_Powderbarrel.getItem(), 2))) { + if (!ready + && (GT_Utility.consumeItems(aPlayer, aStack, Item.getItemFromBlock(Blocks.tnt), 16) + || GT_Utility.consumeItems(aPlayer, aStack, Ic2Items.industrialTnt.getItem(), 8) + || GT_Utility.consumeItems(aPlayer, aStack, Materials.Glyceryl, 4) + || GT_Utility.consumeItems(aPlayer, aStack, ItemList.Block_Powderbarrel.getItem(), 2))) { this.ready = true; this.mMaxProgresstime = (aPlayer.capabilities.isCreativeMode ? 20 : 800); - } - else if (ready && mMaxProgresstime == 0 - && aStack != null && aStack.stackSize == 1 + } else if (ready + && mMaxProgresstime == 0 + && aStack != null + && aStack.stackSize == 1 && aStack.getItem() == ItemList.Tool_DataStick.getItem()) { this.ready = false; @@ -69,23 +70,43 @@ else if (ready && mMaxProgresstime == 0 compound.setString(Tags.BOOK_TITLE, "Raw Prospection Data"); compound.setBoolean(Tags.VISUALPROSPECTING_FLAG, true); compound.setByte(Tags.PROSPECTION_TIER, mTier); - compound.setInteger(Tags.PROSPECTION_DIMENSION_ID, getBaseMetaTileEntity().getWorld().provider.dimensionId); - compound.setInteger(Tags.PROSPECTION_BLOCK_X, getBaseMetaTileEntity().getXCoord()); - compound.setInteger(Tags.PROSPECTION_BLOCK_Y, getBaseMetaTileEntity().getYCoord()); - compound.setInteger(Tags.PROSPECTION_BLOCK_Z, getBaseMetaTileEntity().getZCoord()); + compound.setInteger( + Tags.PROSPECTION_DIMENSION_ID, getBaseMetaTileEntity().getWorld().provider.dimensionId); + compound.setInteger( + Tags.PROSPECTION_BLOCK_X, getBaseMetaTileEntity().getXCoord()); + compound.setInteger( + Tags.PROSPECTION_BLOCK_Y, getBaseMetaTileEntity().getYCoord()); + compound.setInteger( + Tags.PROSPECTION_BLOCK_Z, getBaseMetaTileEntity().getZCoord()); compound.setInteger(Tags.PROSPECTION_ORE_RADIUS, radius); - final List undergroundFluidPositions = ServerCache.instance.prospectUndergroundFluidBlockRadius(aPlayer.worldObj, getBaseMetaTileEntity().getXCoord(), getBaseMetaTileEntity().getZCoord(), VP.undergroundFluidChunkProspectingBlockRadius); + final List undergroundFluidPositions = + ServerCache.instance.prospectUndergroundFluidBlockRadius( + aPlayer.worldObj, + getBaseMetaTileEntity().getXCoord(), + getBaseMetaTileEntity().getZCoord(), + VP.undergroundFluidChunkProspectingBlockRadius); compound.setInteger(Tags.PROSPECTION_NUMBER_OF_UNDERGROUND_FLUID, undergroundFluidPositions.size()); String[] fluidStrings = new String[9]; - final int minUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(getBaseMetaTileEntity().getXCoord() - VP.undergroundFluidChunkProspectingBlockRadius)); - final int minUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(getBaseMetaTileEntity().getZCoord() - VP.undergroundFluidChunkProspectingBlockRadius)); - for(UndergroundFluidPosition undergroundFluidPosition : undergroundFluidPositions) { - final int offsetUndergroundFluidX = (Utils.mapToCornerUndergroundFluidChunkCoord(undergroundFluidPosition.chunkX) - minUndergroundFluidX) >> 3; - final int offsetUndergroundFluidZ = (Utils.mapToCornerUndergroundFluidChunkCoord(undergroundFluidPosition.chunkZ) - minUndergroundFluidZ) >> 3; + final int minUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk( + getBaseMetaTileEntity().getXCoord() - VP.undergroundFluidChunkProspectingBlockRadius)); + final int minUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk( + getBaseMetaTileEntity().getZCoord() - VP.undergroundFluidChunkProspectingBlockRadius)); + for (UndergroundFluidPosition undergroundFluidPosition : undergroundFluidPositions) { + final int offsetUndergroundFluidX = + (Utils.mapToCornerUndergroundFluidChunkCoord(undergroundFluidPosition.chunkX) + - minUndergroundFluidX) + >> 3; + final int offsetUndergroundFluidZ = + (Utils.mapToCornerUndergroundFluidChunkCoord(undergroundFluidPosition.chunkZ) + - minUndergroundFluidZ) + >> 3; final int undergroundFluidBookId = offsetUndergroundFluidX + offsetUndergroundFluidZ * 3; - fluidStrings[undergroundFluidBookId] = "" + undergroundFluidBookId + ": " + undergroundFluidPosition.getMinProduction() + "-" + undergroundFluidPosition.getMaxProduction() + " " + ServerTranslations.getEnglishLocalization(undergroundFluidPosition.fluid); + fluidStrings[undergroundFluidBookId] = + "" + undergroundFluidBookId + ": " + undergroundFluidPosition.getMinProduction() + "-" + + undergroundFluidPosition.getMaxProduction() + " " + + ServerTranslations.getEnglishLocalization(undergroundFluidPosition.fluid); } compound.setString(Tags.PROSPECTION_FLUIDS, String.join("|", fluidStrings)); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java index 6c25b223..d3ad46d5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java @@ -1,5 +1,7 @@ package com.sinthoras.visualprospecting.mixins.gregtech; +import static gregtech.api.util.GT_Utility.ItemNBT.setNBT; + import com.sinthoras.visualprospecting.ServerTranslations; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.database.OreVeinPosition; @@ -8,6 +10,7 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine; import gregtech.api.util.GT_Utility; import gregtech.common.tileentities.machines.basic.GT_MetaTileEntity_Scanner; +import java.util.List; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -17,10 +20,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.List; - -import static gregtech.api.util.GT_Utility.ItemNBT.setNBT; - @Mixin(value = GT_MetaTileEntity_Scanner.class, remap = false) public abstract class GT_MetaTileEntity_ScannerMixin extends GT_MetaTileEntity_BasicMachine { @@ -28,23 +27,27 @@ public GT_MetaTileEntity_ScannerMixin() { super(0, "", "", 0, 0, "", 0, 0, "", "", (ITexture[]) null); } - @Inject(method = "checkRecipe", - at = @At(value = "INVOKE", - target = "Lgregtech/api/util/GT_Utility$ItemNBT;convertProspectionData(Lnet/minecraft/item/ItemStack;)V"), + @Inject( + method = "checkRecipe", + at = + @At( + value = "INVOKE", + target = + "Lgregtech/api/util/GT_Utility$ItemNBT;convertProspectionData(Lnet/minecraft/item/ItemStack;)V"), remap = false, require = 1, cancellable = true) private void onAnalyzeProspectionData(CallbackInfoReturnable callbackInfoReturnable) { final ItemStack itemStack = getInputAt(0); final NBTTagCompound compound = itemStack.getTagCompound(); - if(compound.hasKey(Tags.VISUALPROSPECTING_FLAG)) { + if (compound.hasKey(Tags.VISUALPROSPECTING_FLAG)) { final int dimensionId = compound.getInteger(Tags.PROSPECTION_DIMENSION_ID); final int blockX = compound.getInteger(Tags.PROSPECTION_BLOCK_X); final int blockY = compound.getInteger(Tags.PROSPECTION_BLOCK_Y); final int blockZ = compound.getInteger(Tags.PROSPECTION_BLOCK_Z); final int blockRadius = compound.getInteger(Tags.PROSPECTION_ORE_RADIUS); final int numberOfUndergroundFluids = compound.getInteger(Tags.PROSPECTION_NUMBER_OF_UNDERGROUND_FLUID); - final String position = "X: " + blockX + " Y: " + blockY + " Z: " + blockZ; + final String position = "Dim: " + dimensionId + " X: " + blockX + " Y: " + blockY + " Z: " + blockZ; final NBTTagList bookPages = new NBTTagList(); @@ -56,28 +59,43 @@ private void onAnalyzeProspectionData(CallbackInfoReturnable callbackIn + "Results are synchronized to your map"; bookPages.appendTag(new NBTTagString(frontPage)); - final List foundOreVeins = ServerCache.instance.prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); - if(foundOreVeins.isEmpty() == false) { + final List foundOreVeins = + ServerCache.instance.prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); + if (foundOreVeins.isEmpty() == false) { final int pageSize = 7; - final int numberOfPages = (foundOreVeins.size() + pageSize) / pageSize; // Equals to ceil((foundOreVeins.size()) + final int numberOfPages = + (foundOreVeins.size() + pageSize) / pageSize; // Equals to ceil((foundOreVeins.size()) - for(int pageNumber = 0; pageNumber < numberOfPages; pageNumber++) { + for (int pageNumber = 0; pageNumber < numberOfPages; pageNumber++) { final StringBuilder pageString = new StringBuilder(); - for(int i = 0; i < pageSize; i++) { + for (int i = 0; i < pageSize; i++) { final int veinId = pageNumber * pageSize + i; - if(veinId < foundOreVeins.size()) { + if (veinId < foundOreVeins.size()) { final OreVeinPosition oreVein = foundOreVeins.get(veinId); - pageString.append(oreVein.getBlockX()).append(",").append(oreVein.getBlockZ()).append(" - ").append(ServerTranslations.getEnglishLocalization(oreVein.veinType)).append("\n"); + pageString + .append(oreVein.getBlockX()) + .append(",") + .append(oreVein.getBlockZ()) + .append(" - ") + .append(ServerTranslations.getEnglishLocalization(oreVein.veinType)) + .append("\n"); } } - String pageCounter = numberOfPages > 1 ? String.format(" %d/%d", pageNumber + 1, numberOfPages) : ""; - NBTTagString pageTag = new NBTTagString(String.format("Ore Veins %s\n\n", pageCounter) + pageString); + String pageCounter = + numberOfPages > 1 ? String.format(" %d/%d", pageNumber + 1, numberOfPages) : ""; + NBTTagString pageTag = + new NBTTagString(String.format("Ore Veins %s\n\n", pageCounter) + pageString); bookPages.appendTag(pageTag); } } - if(compound.hasKey(Tags.PROSPECTION_FLUIDS)) { - GT_Utility.ItemNBT.fillBookWithList(bookPages, "Fluids%s\n\n", "\n", 9, compound.getString(Tags.PROSPECTION_FLUIDS).split("\\|")); + if (compound.hasKey(Tags.PROSPECTION_FLUIDS)) { + GT_Utility.ItemNBT.fillBookWithList( + bookPages, + "Fluids%s\n\n", + "\n", + 9, + compound.getString(Tags.PROSPECTION_FLUIDS).split("\\|")); final String fluidCoverPage = "Fluid notes\n\n" + "Prospects from NW to SE 576 chunks" @@ -89,8 +107,8 @@ private void onAnalyzeProspectionData(CallbackInfoReturnable callbackIn + "[5] - Prospector in this 8x8 area"; bookPages.appendTag(new NBTTagString(fluidCoverPage)); - - String tFluidsPosStr = "X: " + Math.floorDiv(blockX, 16 * 8) * 16 * 8 + " Z: " + Math.floorDiv(blockZ, 16 * 8) * 16 * 8 + "\n"; + String tFluidsPosStr = "X: " + Math.floorDiv(blockX, 16 * 8) * 16 * 8 + " Z: " + + Math.floorDiv(blockZ, 16 * 8) * 16 * 8 + "\n"; int xOff = blockX - Math.floorDiv(blockX, 16 * 8) * 16 * 8; xOff = xOff / 16; int xOffRemain = 7 - xOff; @@ -115,10 +133,10 @@ private void onAnalyzeProspectionData(CallbackInfoReturnable callbackIn for (; zOffRemain > 0; zOffRemain--) { tFluidsPosStr = tFluidsPosStr.concat("--------\n"); } - tFluidsPosStr = tFluidsPosStr.concat(" X: " + (Math.floorDiv(blockX, 16 * 8) + 1) * 16 * 8 + " Z: " + (Math.floorDiv(blockZ, 16 * 8) + 1) * 16 * 8); // +1 field to find bottomright of [5] - final String fluidsPage = "Corners of [5] are \n" + - tFluidsPosStr + "\n" + - "P - Prospector in 8x8 field"; + tFluidsPosStr = tFluidsPosStr.concat(" X: " + (Math.floorDiv(blockX, 16 * 8) + 1) * 16 * 8 + + " Z: " + (Math.floorDiv(blockZ, 16 * 8) + 1) * 16 * 8); // +1 field to find bottomright of [5] + final String fluidsPage = + "Corners of [5] are \n" + tFluidsPosStr + "\n" + "P - Prospector in 8x8 field"; bookPages.appendTag(new NBTTagString(fluidsPage)); } @@ -126,16 +144,14 @@ private void onAnalyzeProspectionData(CallbackInfoReturnable callbackIn compound.setTag("pages", bookPages); setNBT(itemStack, compound); - // Mimic original behaviour itemStack.stackSize -= 1; mOutputItems[0] = GT_Utility.copyAmount(1L, itemStack); calculateOverclockedNess(30, 1000); - //In case recipe is too OP for that machine + // In case recipe is too OP for that machine if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) { callbackInfoReturnable.setReturnValue(FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS); - } - else { + } else { callbackInfoReturnable.setReturnValue(2); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java index 81fcd699..ff350452 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java @@ -4,26 +4,50 @@ import com.sinthoras.visualprospecting.database.ServerCache; import gregtech.common.GT_Worldgen_GT_Ore_Layer; import gregtech.common.GT_Worldgenerator; +import java.util.Random; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import java.util.Random; - @Mixin(GT_Worldgenerator.WorldGenContainer.class) public class WorldGenContainerMixin { - // Redirect both calls to ensure that Bartworks ore veins are captured as well - @Redirect(method = "worldGenFindVein", - at = @At(value = "INVOKE", - target = "Lgregtech/common/GT_Worldgen_GT_Ore_Layer;executeWorldgenChunkified(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIIIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)I"), + // Redirect both calls to ensure that Bartworks ore veins are captured as well + @Redirect( + method = "worldGenFindVein", + at = + @At( + value = "INVOKE", + target = + "Lgregtech/common/GT_Worldgen_GT_Ore_Layer;executeWorldgenChunkified(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIIIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)I"), remap = false, require = 2) - protected int onOreVeinPlaced(GT_Worldgen_GT_Ore_Layer instance, World aWorld, Random aRandom, String aBiome, int aDimensionType, int aChunkX, int aChunkZ, int aSeedX, int aSeedZ, IChunkProvider aChunkGenerator, IChunkProvider aChunkProvider) { - final int result = instance.executeWorldgenChunkified(aWorld, aRandom, aBiome, aDimensionType, aChunkX, aChunkZ, aSeedX, aSeedZ, aChunkGenerator, aChunkProvider); - if(result == GT_Worldgen_GT_Ore_Layer.ORE_PLACED && instance.mWorldGenName.equals("NoOresInVein") == false) { + protected int onOreVeinPlaced( + GT_Worldgen_GT_Ore_Layer instance, + World aWorld, + Random aRandom, + String aBiome, + int aDimensionType, + int aChunkX, + int aChunkZ, + int aSeedX, + int aSeedZ, + IChunkProvider aChunkGenerator, + IChunkProvider aChunkProvider) { + final int result = instance.executeWorldgenChunkified( + aWorld, + aRandom, + aBiome, + aDimensionType, + aChunkX, + aChunkZ, + aSeedX, + aSeedZ, + aChunkGenerator, + aChunkProvider); + if (result == GT_Worldgen_GT_Ore_Layer.ORE_PLACED && instance.mWorldGenName.equals("NoOresInVein") == false) { ServerCache.instance.notifyOreVeinGeneration( aWorld.provider.dimensionId, Utils.coordBlockToChunk(aSeedX), diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/ifu/ItemOreFinderToolMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/ifu/ItemOreFinderToolMixin.java index ce5f884a..9132ae5f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/ifu/ItemOreFinderToolMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/ifu/ItemOreFinderToolMixin.java @@ -27,51 +27,74 @@ @Mixin(value = ItemOreFinderTool.class, remap = false) public class ItemOreFinderToolMixin extends Item { - @Shadow - private static int found; - - @Shadow - private static int MAX_DAMAGE; + @Shadow + private static int found; - @Inject( - method = "onUpdate", - at = @At(value = "INVOKE", target = "Lcom/encraft/dz/items/ItemOreFinderTool;shouldKeepLooking()Z", shift = Shift.AFTER, remap = false, ordinal = 0), - locals = LocalCapture.CAPTURE_FAILEXCEPTION, - remap = true - ) - public void onGtOreFound( - ItemStack itemstack, - World world, Entity entity, - int par4, boolean par5, - CallbackInfo ci, - ItemStack searchItem, ItemData data, boolean vanilla, int id, - double cur_x, double cur_y, double cur_z, - int min_x, int min_y, int min_z, - int max_x, int max_y, int max_z, - boolean keepLooking, - int z1, int x1, int y1, - Block tBlock, int meta, ItemStack inWorld, ItemData dataInWorld, List oreTypes - ) { - if (vanilla || world.isRemote || didNotDetectSignificantOreCluster() || !(entity instanceof EntityPlayer)) return; + @Shadow + private static int MAX_DAMAGE; - final short foundMaterialMetaId = (short) dataInWorld.mMaterial.mMaterial.mMetaItemSubID; + @Inject( + method = "onUpdate", + at = + @At( + value = "INVOKE", + target = "Lcom/encraft/dz/items/ItemOreFinderTool;shouldKeepLooking()Z", + shift = Shift.AFTER, + remap = false, + ordinal = 0), + locals = LocalCapture.CAPTURE_FAILEXCEPTION, + remap = true) + public void onGtOreFound( + ItemStack itemstack, + World world, + Entity entity, + int par4, + boolean par5, + CallbackInfo ci, + ItemStack searchItem, + ItemData data, + boolean vanilla, + int id, + double cur_x, + double cur_y, + double cur_z, + int min_x, + int min_y, + int min_z, + int max_x, + int max_y, + int max_z, + boolean keepLooking, + int z1, + int x1, + int y1, + Block tBlock, + int meta, + ItemStack inWorld, + ItemData dataInWorld, + List oreTypes) { + if (vanilla || world.isRemote || didNotDetectSignificantOreCluster() || !(entity instanceof EntityPlayer)) + return; - final int blockX = x1; - final int blockZ = z1; - final List discoveredOreVeins = listVeinsInProximityContaining(foundMaterialMetaId, blockX, blockZ, world); + final short foundMaterialMetaId = (short) dataInWorld.mMaterial.mMaterial.mMetaItemSubID; - VisualProspecting_API.LogicalServer.sendProspectionResultsToClient((EntityPlayerMP) entity, discoveredOreVeins, Collections.emptyList()); - } + final int blockX = x1; + final int blockZ = z1; + final List discoveredOreVeins = + listVeinsInProximityContaining(foundMaterialMetaId, blockX, blockZ, world); - private boolean didNotDetectSignificantOreCluster() { - return found < MAX_DAMAGE; - } + VisualProspecting_API.LogicalServer.sendProspectionResultsToClient( + (EntityPlayerMP) entity, discoveredOreVeins, Collections.emptyList()); + } - private List listVeinsInProximityContaining(short foundMaterialMetaId, int blocX, int blockZ, World world) { - return LogicalServer - .prospectOreVeinsWithinRadius(world.provider.dimensionId, blocX, blockZ, 48) - .stream() - .filter(it -> it.veinType.containsOre(foundMaterialMetaId)) - .collect(Collectors.toList()); - } + private boolean didNotDetectSignificantOreCluster() { + return found < MAX_DAMAGE; + } + + private List listVeinsInProximityContaining( + short foundMaterialMetaId, int blocX, int blockZ, World world) { + return LogicalServer.prospectOreVeinsWithinRadius(world.provider.dimensionId, blocX, blockZ, 48).stream() + .filter(it -> it.veinType.containsOre(foundMaterialMetaId)) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java index 90eab92d..baee57e7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java @@ -27,9 +27,9 @@ public FullscreenActionsMixin() { super(""); } - @Inject(method = "func_73866_w_", - at = @At(value = "INVOKE", - target = "Ljourneymap/client/ui/component/Button;setDrawFrame(Z)V"), + @Inject( + method = "func_73866_w_", + at = @At(value = "INVOKE", target = "Ljourneymap/client/ui/component/Button;setDrawFrame(Z)V"), remap = false, require = 1) private void onInitGui(CallbackInfo callbackInfo) { @@ -44,9 +44,15 @@ private void onLayoutButtons(CallbackInfo callbackInfo) { row.layoutCenteredHorizontal(width / 2, height / 4, true, 4); } - @Inject(method = "func_146284_a", at = @At("HEAD"), remap = false, cancellable = true, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) + @Inject( + method = "func_146284_a", + at = @At("HEAD"), + remap = false, + cancellable = true, + require = 1, + locals = LocalCapture.CAPTURE_FAILEXCEPTION) private void onButtonClicked(GuiButton guibutton, CallbackInfo callbackInfo) { - if(guibutton == resetVisualProspectingCacheButton) { + if (guibutton == resetVisualProspectingCacheButton) { UIManager.getInstance().open(ResetClientCacheConfirmation.class); callbackInfo.cancel(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java index 57999d67..7d2968ea 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java @@ -7,6 +7,7 @@ import com.sinthoras.visualprospecting.integration.journeymap.render.WaypointProviderLayerRenderer; import com.sinthoras.visualprospecting.integration.model.MapState; import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; +import java.util.List; import journeymap.client.Constants; import journeymap.client.io.ThemeFileHandler; import journeymap.client.log.LogFormatter; @@ -39,8 +40,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.util.List; - @Mixin(value = Fullscreen.class, remap = false) public abstract class FullscreenMixin extends JmUI { @@ -107,44 +106,59 @@ private void onConstructed(CallbackInfo callbackInfo) { MapState.instance.layers.forEach(LayerManager::onOpenMap); } - @Inject(method = "drawMap", - at = @At(value = "INVOKE", - target = "Ljourneymap/client/model/MapState;getDrawWaypointSteps()Ljava/util/List;"), + @Inject( + method = "drawMap", + at = + @At( + value = "INVOKE", + target = "Ljourneymap/client/model/MapState;getDrawWaypointSteps()Ljava/util/List;"), remap = false, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void onBeforeDrawJourneyMapWaypoints(CallbackInfo callbackInfo, boolean refreshReady, StatTimer timer, int xOffset, int yOffset, float drawScale) { + private void onBeforeDrawJourneyMapWaypoints( + CallbackInfo callbackInfo, + boolean refreshReady, + StatTimer timer, + int xOffset, + int yOffset, + float drawScale) { final int fontScale = getMapFontScale(); final Minecraft minecraft = Minecraft.getMinecraft(); final int centerBlockX = (int) Math.round(gridRenderer.getCenterBlockX()); final int centerBlockZ = (int) Math.round(gridRenderer.getCenterBlockZ()); final int widthBlocks = minecraft.displayWidth >> gridRenderer.getZoom(); final int heightBlocks = minecraft.displayHeight >> gridRenderer.getZoom(); - for(LayerManager layerManager : MapState.instance.layers) { - if(layerManager.isLayerActive()) { + for (LayerManager layerManager : MapState.instance.layers) { + if (layerManager.isLayerActive()) { layerManager.recacheFullscreenMap(centerBlockX, centerBlockZ, widthBlocks, heightBlocks); } } - for(LayerRenderer layerRenderer : JourneyMapState.instance.renderers) { - if(layerRenderer.isLayerActive()) { - gridRenderer.draw(layerRenderer.getDrawStepsCachedForRendering(), xOffset, yOffset, drawScale, fontScale, 0.0); + for (LayerRenderer layerRenderer : JourneyMapState.instance.renderers) { + if (layerRenderer.isLayerActive()) { + gridRenderer.draw( + layerRenderer.getDrawStepsCachedForRendering(), xOffset, yOffset, drawScale, fontScale, 0.0); } } } - @Redirect(method = "initButtons", - at = @At(value = "FIELD", - target = "Ljourneymap/client/ui/fullscreen/Fullscreen;mapTypeToolbar:Ljourneymap/client/ui/theme/ThemeToolbar;", - opcode = Opcodes.PUTFIELD), + @Redirect( + method = "initButtons", + at = + @At( + value = "FIELD", + target = + "Ljourneymap/client/ui/fullscreen/Fullscreen;mapTypeToolbar:Ljourneymap/client/ui/theme/ThemeToolbar;", + opcode = Opcodes.PUTFIELD), remap = false, require = 1) private void OnCreateMapTypeToolbar(Fullscreen owner, ThemeToolbar value) { final Theme theme = ThemeFileHandler.getCurrentTheme(); final ButtonList buttonList = new ButtonList(); - for(LayerButton layerButton : JourneyMapState.instance.buttons) { - final ThemeToggle button = new ThemeToggle(theme, layerButton.getButtonTextKey(), layerButton.getIconName()); + for (LayerButton layerButton : JourneyMapState.instance.buttons) { + final ThemeToggle button = + new ThemeToggle(theme, layerButton.getButtonTextKey(), layerButton.getIconName()); layerButton.setButton(button); button.setToggled(layerButton.isActive(), false); button.addToggleListener((unused, toggled) -> { @@ -171,13 +185,12 @@ public void func_73863_a(int width, int height, float f) { if (firstLayoutPass) { layoutButtons(); firstLayoutPass = false; - } - else { - for(int k = 0; k < buttonList.size(); ++k) { + } else { + for (int k = 0; k < buttonList.size(); ++k) { GuiButton guibutton = (GuiButton) buttonList.get(k); guibutton.drawButton(mc, width, height); if (tooltip == null && guibutton instanceof Button) { - Button button = (Button)guibutton; + Button button = (Button) guibutton; if (button.mouseOver(mx, my)) { tooltip = button.getTooltip(); } @@ -187,17 +200,18 @@ public void func_73863_a(int width, int height, float f) { final int scaledMouseX = (mx * mc.displayWidth) / this.width; final int scaledMouseY = (my * mc.displayHeight) / this.height; - for(LayerRenderer layer : JourneyMapState.instance.renderers) { + for (LayerRenderer layer : JourneyMapState.instance.renderers) { if (layer instanceof WaypointProviderLayerRenderer) { final WaypointProviderLayerRenderer waypointProviderLayer = (WaypointProviderLayerRenderer) layer; waypointProviderLayer.onMouseMove(scaledMouseX, scaledMouseY); } } - if(tooltip == null) { - for(LayerRenderer layer : JourneyMapState.instance.renderers) { + if (tooltip == null) { + for (LayerRenderer layer : JourneyMapState.instance.renderers) { if (layer instanceof WaypointProviderLayerRenderer) { - final WaypointProviderLayerRenderer waypointProviderLayer = (WaypointProviderLayerRenderer) layer; + final WaypointProviderLayerRenderer waypointProviderLayer = + (WaypointProviderLayerRenderer) layer; if (waypointProviderLayer.isLayerActive()) { tooltip = waypointProviderLayer.getTextTooltip(); } @@ -212,11 +226,11 @@ public void func_73863_a(int width, int height, float f) { if (tooltip != null && !tooltip.isEmpty()) { drawHoveringText(tooltip, mx, my, getFontRenderer()); RenderHelper.disableStandardItemLighting(); - } - else { - for(LayerRenderer layer : JourneyMapState.instance.renderers) { + } else { + for (LayerRenderer layer : JourneyMapState.instance.renderers) { if (layer instanceof WaypointProviderLayerRenderer) { - final WaypointProviderLayerRenderer waypointProviderLayer = (WaypointProviderLayerRenderer) layer; + final WaypointProviderLayerRenderer waypointProviderLayer = + (WaypointProviderLayerRenderer) layer; if (waypointProviderLayer.isLayerActive()) { waypointProviderLayer.drawCustomTooltip(getFontRenderer(), mx, my, this.width, this.height); } @@ -224,26 +238,19 @@ public void func_73863_a(int width, int height, float f) { } } - - } - catch (Throwable var11) { - logger.log(Level.ERROR, "Unexpected exception in jm.fullscreen.drawScreen(): " + LogFormatter.toString(var11)); + } catch (Throwable var11) { + logger.log( + Level.ERROR, "Unexpected exception in jm.fullscreen.drawScreen(): " + LogFormatter.toString(var11)); UIManager.getInstance().closeAll(); - } - finally { + } finally { drawScreenTimer.stop(); } - } - @Inject(method = "func_73869_a", - at = @At(value = "HEAD"), - remap = false, - require = 1, - cancellable = true) + @Inject(method = "func_73869_a", at = @At(value = "HEAD"), remap = false, require = 1, cancellable = true) private void onKeyPress(CallbackInfo callbackInfo) { - if((chat == null || chat.isHidden()) && Constants.isPressed(VP.keyAction)) { - for(LayerRenderer layer : JourneyMapState.instance.renderers) { + if ((chat == null || chat.isHidden()) && Constants.isPressed(VP.keyAction)) { + for (LayerRenderer layer : JourneyMapState.instance.renderers) { if (layer instanceof WaypointProviderLayerRenderer) { ((WaypointProviderLayerRenderer) layer).onActionKeyPressed(); } @@ -263,9 +270,17 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { final int scaledMouseX = mx * mc.displayWidth / width; final int scaledMouseY = my * mc.displayHeight / height; final double blockSize = Math.pow(2.0D, gridRenderer.getZoom()); - if(onMapClicked(mouseButton, scaledMouseX, scaledMouseY, blockSize) == false) { - BlockCoordIntPair blockCoord = gridRenderer.getBlockUnderMouse(Mouse.getEventX(), Mouse.getEventY(), mc.displayWidth, mc.displayHeight); - layerDelegate.onMouseClicked(mc, Mouse.getEventX(), Mouse.getEventY(), gridRenderer.getWidth(), gridRenderer.getHeight(), blockCoord, mouseButton); + if (onMapClicked(mouseButton, scaledMouseX, scaledMouseY, blockSize) == false) { + BlockCoordIntPair blockCoord = gridRenderer.getBlockUnderMouse( + Mouse.getEventX(), Mouse.getEventY(), mc.displayWidth, mc.displayHeight); + layerDelegate.onMouseClicked( + mc, + Mouse.getEventX(), + Mouse.getEventY(), + gridRenderer.getWidth(), + gridRenderer.getHeight(), + blockCoord, + mouseButton); } } } @@ -277,12 +292,12 @@ private boolean onMapClicked(int mouseButton, int mouseX, int mouseY, double blo oldMouseY = mouseY; timeLastClick = isDoubleClick ? 0 : timestamp; - if(mouseButton != 0) { + if (mouseButton != 0) { return false; } boolean layerHit = false; - for(LayerRenderer layer : JourneyMapState.instance.renderers) { + for (LayerRenderer layer : JourneyMapState.instance.renderers) { if (layer instanceof WaypointProviderLayerRenderer) { ((WaypointProviderLayerRenderer) layer).onMouseMove(mouseX, mouseY); layerHit |= ((WaypointProviderLayerRenderer) layer).onMouseAction(isDoubleClick); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java index 1e74c4b7..b9ae1fa4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java @@ -4,6 +4,7 @@ import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; import com.sinthoras.visualprospecting.integration.model.MapState; import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; +import java.lang.reflect.Field; import journeymap.client.render.draw.DrawStep; import journeymap.client.render.map.GridRenderer; import journeymap.client.ui.minimap.DisplayVars; @@ -18,9 +19,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.awt.geom.Point2D; -import java.lang.reflect.Field; - @Mixin(MiniMap.class) public abstract class MiniMapMixin { @@ -39,8 +37,7 @@ public abstract class MiniMapMixin { shape.setAccessible(true); minimapWidth = DisplayVars.class.getDeclaredField("minimapWidth"); minimapWidth.setAccessible(true); - } - catch (NoSuchFieldException e) { + } catch (NoSuchFieldException e) { e.printStackTrace(); } } @@ -48,8 +45,7 @@ public abstract class MiniMapMixin { private static float getDrawScale(DisplayVars displayVars) { try { return drawScale.getFloat(displayVars); - } - catch (IllegalAccessException e) { + } catch (IllegalAccessException e) { return 0.0f; } } @@ -57,8 +53,7 @@ private static float getDrawScale(DisplayVars displayVars) { private static double getFontScale(DisplayVars displayVars) { try { return fontScale.getDouble(displayVars); - } - catch (IllegalAccessException e) { + } catch (IllegalAccessException e) { return 0.0; } } @@ -66,8 +61,7 @@ private static double getFontScale(DisplayVars displayVars) { private static Shape getShape(DisplayVars displayVars) { try { return (Shape) shape.get(displayVars); - } - catch (IllegalAccessException e) { + } catch (IllegalAccessException e) { return Shape.Circle; } } @@ -75,8 +69,7 @@ private static Shape getShape(DisplayVars displayVars) { private static int getMinimapWidth(DisplayVars displayVars) { try { return minimapWidth.getInt(displayVars); - } - catch (IllegalAccessException e) { + } catch (IllegalAccessException e) { return 1; } } @@ -92,25 +85,29 @@ private static int getMinimapWidth(DisplayVars displayVars) { @Shadow(remap = false) private DisplayVars dv; - @Inject(method = "drawOnMapWaypoints", + @Inject( + method = "drawOnMapWaypoints", at = @At(value = "HEAD"), remap = false, require = 1, locals = LocalCapture.CAPTURE_FAILHARD) private void onBeforeDrawWaypoints(double rotation, CallbackInfo callbackInfo) { - for(LayerManager layerManager : MapState.instance.layers) { + for (LayerManager layerManager : MapState.instance.layers) { if (layerManager.isLayerActive()) { if (getShape(dv) == Shape.Circle) { layerManager.recacheMiniMap((int) mc.thePlayer.posX, (int) mc.thePlayer.posZ, getMinimapWidth(dv)); - } - else { - layerManager.recacheMiniMap((int) mc.thePlayer.posX, (int) mc.thePlayer.posZ, gridRenderer.getWidth(), gridRenderer.getHeight()); + } else { + layerManager.recacheMiniMap( + (int) mc.thePlayer.posX, + (int) mc.thePlayer.posZ, + gridRenderer.getWidth(), + gridRenderer.getHeight()); } } } - for(LayerRenderer layerRenderer : JourneyMapState.instance.renderers) { - if(layerRenderer.isLayerActive()) { + for (LayerRenderer layerRenderer : JourneyMapState.instance.renderers) { + if (layerRenderer.isLayerActive()) { for (DrawStep drawStep : layerRenderer.getDrawStepsCachedForRendering()) { drawStep.draw(0.0D, 0.0D, gridRenderer, getDrawScale(dv), getFontScale(dv), rotation); } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java index 4c2faa10..2f846714 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java @@ -22,16 +22,20 @@ static void doRender(Waypoint waypoint) { throw new IllegalStateException("Mixin failed to shadow doRender()"); } - @Inject(method = "renderAll", - at = @At(value = "INVOKE", - target = "Ljourneymap/client/waypoint/WaypointStore;instance()Ljourneymap/client/waypoint/WaypointStore;"), + @Inject( + method = "renderAll", + at = + @At( + value = "INVOKE", + target = + "Ljourneymap/client/waypoint/WaypointStore;instance()Ljourneymap/client/waypoint/WaypointStore;"), remap = false, require = 1) private static void onRenderAll(CallbackInfo callbackInfo) { - for(WaypointManager waypointManager : JourneyMapState.instance.waypointManagers) { - if(waypointManager.hasWaypoint()) { + for (WaypointManager waypointManager : JourneyMapState.instance.waypointManagers) { + if (waypointManager.hasWaypoint()) { final Waypoint waypoint = waypointManager.getJmWaypoint(); - if(waypoint.getDimensions().contains(mc.thePlayer.dimension)) { + if (waypoint.getDimensions().contains(mc.thePlayer.dimension)) { doRender(waypoint); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java index 15ed16af..22c059b6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java @@ -13,11 +13,16 @@ @Mixin(WaypointManager.class) public class WaypointManagerMixin { - @Inject(method = "toggleItems", at = @At("HEAD"), remap = false, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) + @Inject( + method = "toggleItems", + at = @At("HEAD"), + remap = false, + require = 1, + locals = LocalCapture.CAPTURE_FAILEXCEPTION) private void onToggleAllWaypoints(boolean enable, CallbackInfoReturnable callbackInfoReturnable) { - if(enable == false) { - for(LayerManager layer : MapState.instance.layers) { - if(layer instanceof WaypointProviderManager) { + if (enable == false) { + for (LayerManager layer : MapState.instance.layers) { + if (layer instanceof WaypointProviderManager) { ((WaypointProviderManager) layer).clearActiveWaypoint(); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java index d7dcb185..85070a08 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java @@ -11,12 +11,9 @@ public class ForgeHooksClientMixin { // this is only a mixin because it needs to run before the minecraft window is created - @Inject(method = "createDisplay", - at = @At("HEAD") - ) + @Inject(method = "createDisplay", at = @At("HEAD")) private static void enableStencilBuffer(CallbackInfo ci) { // give me my stencil buffer, forge. System.setProperty("forge.forceDisplayStencil", "true"); } - } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java index cdd249fc..1b539d3a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java @@ -1,13 +1,14 @@ package com.sinthoras.visualprospecting.mixins.minecraft; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; +import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; -import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.network.ProspectingNotification; +import java.util.List; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemEditableBook; @@ -20,32 +21,39 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.util.List; - @Mixin(value = ItemEditableBook.class, remap = true) public class ItemEditableBookMixin { - @Inject(method = "onItemRightClick", + @Inject( + method = "onItemRightClick", at = @At("HEAD"), remap = true, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void onItemRightClick(ItemStack itemStack, World world, EntityPlayer entityPlayer, CallbackInfoReturnable callbackInfoReturnable) { - if(world.isRemote == false) { + private void onItemRightClick( + ItemStack itemStack, + World world, + EntityPlayer entityPlayer, + CallbackInfoReturnable callbackInfoReturnable) { + if (world.isRemote == false) { final NBTTagCompound compound = itemStack.getTagCompound(); - if(compound.hasKey(Tags.VISUALPROSPECTING_FLAG)) { + if (compound.hasKey(Tags.VISUALPROSPECTING_FLAG)) { final int dimensionId = compound.getInteger(Tags.PROSPECTION_DIMENSION_ID); final int blockX = compound.getInteger(Tags.PROSPECTION_BLOCK_X); final int blockZ = compound.getInteger(Tags.PROSPECTION_BLOCK_Z); final int blockRadius = compound.getInteger(Tags.PROSPECTION_ORE_RADIUS); - final List foundOreVeins = ServerCache.instance.prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); - final List foundUndergroundFluids = ServerCache.instance.prospectUndergroundFluidBlockRadius(world, blockX, blockZ, VP.undergroundFluidChunkProspectingBlockRadius); - if(Utils.isLogicalClient()) { + final List foundOreVeins = + ServerCache.instance.prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); + final List foundUndergroundFluids = + ServerCache.instance.prospectUndergroundFluidBlockRadius( + world, blockX, blockZ, VP.undergroundFluidChunkProspectingBlockRadius); + if (Utils.isLogicalClient()) { ClientCache.instance.putOreVeins(foundOreVeins); ClientCache.instance.putUndergroundFluids(foundUndergroundFluids); - } - else { - VP.network.sendTo(new ProspectingNotification(foundOreVeins, foundUndergroundFluids), (EntityPlayerMP) entityPlayer); + } else { + VP.network.sendTo( + new ProspectingNotification(foundOreVeins, foundUndergroundFluids), + (EntityPlayerMP) entityPlayer); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java index c70ffa88..6f6ae43d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java @@ -20,12 +20,15 @@ public class GuiMainMixin { @Shadow(remap = false) private int low; - @Inject(method = "actionPerformed", - at = @At(value = "FIELD", - target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;zMarker:I", - opcode = Opcodes.PUTSTATIC, - shift = At.Shift.AFTER, - remap = false), + @Inject( + method = "actionPerformed", + at = + @At( + value = "FIELD", + target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;zMarker:I", + opcode = Opcodes.PUTSTATIC, + shift = At.Shift.AFTER, + remap = false), remap = true, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION, @@ -33,29 +36,40 @@ public class GuiMainMixin { private void onWaypointSet(GuiButton button, CallbackInfo callbackInfo, int i) { final AspectLoc aspect = GuiMain.aspectList.get(low + i); GuiMain.aspectList.clear(); - ThaumcraftNodeLayerManager.instance.setActiveWaypoint(new Waypoint(aspect.x, aspect.y, aspect.z, aspect.dimID, - I18n.format("visualprospecting.tracked", I18n.format("tile.blockAiry.0.name")), 0xFFFFFF)); + ThaumcraftNodeLayerManager.instance.setActiveWaypoint(new Waypoint( + aspect.x, + aspect.y, + aspect.z, + aspect.dimID, + I18n.format("visualprospecting.tracked", I18n.format("tile.blockAiry.0.name")), + 0xFFFFFF)); callbackInfo.cancel(); } - @Inject(method = "actionPerformed", - at = @At(value = "FIELD", - target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;doGui:Z", - opcode = Opcodes.PUTSTATIC, - ordinal = 0, - remap = false), + @Inject( + method = "actionPerformed", + at = + @At( + value = "FIELD", + target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;doGui:Z", + opcode = Opcodes.PUTSTATIC, + ordinal = 0, + remap = false), remap = true, require = 1) private void onWaypointClear(CallbackInfo callbackInfo) { ThaumcraftNodeLayerManager.instance.clearActiveWaypoint(); } - @Inject(method = "actionPerformed", - at = @At(value = "FIELD", - target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;doGui:Z", - opcode = Opcodes.PUTSTATIC, - ordinal = 1, - remap = false), + @Inject( + method = "actionPerformed", + at = + @At( + value = "FIELD", + target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;doGui:Z", + opcode = Opcodes.PUTSTATIC, + ordinal = 1, + remap = false), remap = true, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java index c48b614f..2b3dcbd1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java @@ -6,6 +6,7 @@ import com.sinthoras.visualprospecting.integration.xaeroworldmap.XaeroWorldMapState; import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; +import java.util.ArrayList; import net.minecraft.client.Minecraft; import net.minecraftforge.client.MinecraftForgeClient; import org.lwjgl.opengl.GL11; @@ -22,37 +23,77 @@ import xaero.common.minimap.render.MinimapRenderer; import xaero.common.settings.ModSettings; -import java.util.ArrayList; - @SuppressWarnings("UnusedMixin") @Mixin(value = MinimapRenderer.class, remap = false) public class MinimapRendererMixin { - @Unique private boolean stencilEnabled = true; + @Unique + private boolean stencilEnabled = true; - @Shadow protected Minecraft mc; + @Shadow + protected Minecraft mc; - @Shadow protected double zoom; + @Shadow + protected double zoom; - @Inject(method = "renderMinimap", - at = @At(value = "INVOKE", - target = "Lxaero/common/minimap/waypoints/render/WaypointsGuiRenderer;render(Lxaero/common/XaeroMinimapSession;Lxaero/common/minimap/render/MinimapRendererHelper;DDIIDDFDZFZ)V" - ), - locals = LocalCapture.CAPTURE_FAILEXCEPTION - ) - private void injectDraw(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, int y, int width, int height, int scale, int size, - float partial, CallbackInfo ci, ModSettings settings, ArrayList underText, int mapSize, int bufferSize, - float minimapScale, float mapScale, float sizeFix, int shape, boolean lockedNorth, double angle, double ps, double pc, - boolean useWorldMap, int lightLevel, boolean cave, boolean circleShape, int scaledX, int scaledY, int minimapFrameSize, - int circleSides, int frameType, boolean renderFrame, int frameTextureX, int halfFrame, int rightCornerStartX, int specH, - boolean safeMode, double playerX, double playerZ) { + @Inject( + method = "renderMinimap", + at = + @At( + value = "INVOKE", + target = + "Lxaero/common/minimap/waypoints/render/WaypointsGuiRenderer;render(Lxaero/common/XaeroMinimapSession;Lxaero/common/minimap/render/MinimapRendererHelper;DDIIDDFDZFZ)V"), + locals = LocalCapture.CAPTURE_FAILEXCEPTION) + private void injectDraw( + XaeroMinimapSession minimapSession, + MinimapProcessor minimap, + int x, + int y, + int width, + int height, + int scale, + int size, + float partial, + CallbackInfo ci, + ModSettings settings, + ArrayList underText, + int mapSize, + int bufferSize, + float minimapScale, + float mapScale, + float sizeFix, + int shape, + boolean lockedNorth, + double angle, + double ps, + double pc, + boolean useWorldMap, + int lightLevel, + boolean cave, + boolean circleShape, + int scaledX, + int scaledY, + int minimapFrameSize, + int circleSides, + int frameType, + boolean renderFrame, + int frameTextureX, + int halfFrame, + int rightCornerStartX, + int specH, + boolean safeMode, + double playerX, + double playerZ) { for (LayerManager layerManager : MapState.instance.layers) { if (layerManager.isLayerActive()) { if (circleShape) { layerManager.recacheMiniMap((int) mc.thePlayer.posX, (int) mc.thePlayer.posZ, minimapFrameSize * 2); - } - else { - layerManager.recacheMiniMap((int) mc.thePlayer.posX, (int) mc.thePlayer.posZ, minimapFrameSize * 2, minimapFrameSize * 2); + } else { + layerManager.recacheMiniMap( + (int) mc.thePlayer.posX, + (int) mc.thePlayer.posZ, + minimapFrameSize * 2, + minimapFrameSize * 2); } } } @@ -75,17 +116,27 @@ private void injectDraw(XaeroMinimapSession minimapSession, MinimapProcessor min } } - @Inject(method = "renderMinimap", - at = @At(value = "INVOKE", - target = "Lorg/lwjgl/opengl/GL11;glScalef(FFF)V", - shift = At.Shift.AFTER - ), slice = @Slice( - to = @At(value = "INVOKE", - target = "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V" - ) - ) - ) - private void injectBeginStencil(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, int y, int width, int height, int scale, int size, float partial, CallbackInfo ci) { + @Inject( + method = "renderMinimap", + at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glScalef(FFF)V", shift = At.Shift.AFTER), + slice = + @Slice( + to = + @At( + value = "INVOKE", + target = + "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V"))) + private void injectBeginStencil( + XaeroMinimapSession minimapSession, + MinimapProcessor minimap, + int x, + int y, + int width, + int height, + int scale, + int size, + float partial, + CallbackInfo ci) { if (stencilEnabled && MinecraftForgeClient.getStencilBits() == 0) { stencilEnabled = false; VP.warn("Could not enable stencils! Xaero's minimap overlays will not render"); @@ -98,16 +149,27 @@ private void injectBeginStencil(XaeroMinimapSession minimapSession, MinimapProce GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT); } - @Inject(method = "renderMinimap", - at = @At(value = "INVOKE", - target = "Lxaero/common/minimap/MinimapInterface;usingFBO()Z" - ), slice = @Slice( - from = @At(value = "INVOKE", - target = "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V" - ) - ) - ) - private void injectEndStencil(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, int y, int width, int height, int scale, int size, float partial, CallbackInfo ci) { + @Inject( + method = "renderMinimap", + at = @At(value = "INVOKE", target = "Lxaero/common/minimap/MinimapInterface;usingFBO()Z"), + slice = + @Slice( + from = + @At( + value = "INVOKE", + target = + "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V"))) + private void injectEndStencil( + XaeroMinimapSession minimapSession, + MinimapProcessor minimap, + int x, + int y, + int width, + int height, + int scale, + int size, + float partial, + CallbackInfo ci) { GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); GL11.glStencilMask(0x00); GL11.glDisable(GL11.GL_STENCIL_TEST); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java index 4002c4f4..1f7c5390 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java @@ -1,7 +1,7 @@ package com.sinthoras.visualprospecting.mixins.xaerosminimap; -import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.WaypointManager; import com.sinthoras.visualprospecting.integration.xaerominimap.XaeroMiniMapState; +import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.WaypointManager; import net.minecraft.client.Minecraft; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; @@ -15,17 +15,21 @@ @Mixin(value = WaypointsIngameRenderer.class, remap = false) public class WaypointsIngameRendererMixin { - @Inject(method = "render", - at = @At(value = "INVOKE", - target = "Lxaero/common/minimap/waypoints/render/WaypointsIngameRenderer;renderWaypointsList(Ljava/util/Collection;DDDLnet/minecraft/entity/Entity;Lnet/minecraft/client/renderer/Tessellator;DDDDFFDIFFLnet/minecraft/util/Vec3;D)V" - ), - slice = @Slice( - from = @At(value = "FIELD", - target = "Lxaero/common/minimap/waypoints/WaypointsManager;customWaypoints:Ljava/util/Hashtable;", - opcode = Opcodes.GETSTATIC - ) - ) - ) + @Inject( + method = "render", + at = + @At( + value = "INVOKE", + target = + "Lxaero/common/minimap/waypoints/render/WaypointsIngameRenderer;renderWaypointsList(Ljava/util/Collection;DDDLnet/minecraft/entity/Entity;Lnet/minecraft/client/renderer/Tessellator;DDDDFFDIFFLnet/minecraft/util/Vec3;D)V"), + slice = + @Slice( + from = + @At( + value = "FIELD", + target = + "Lxaero/common/minimap/waypoints/WaypointsManager;customWaypoints:Ljava/util/Hashtable;", + opcode = Opcodes.GETSTATIC))) private void injectPreRenderCustomWaypoints(XaeroMinimapSession sets, float modCustomWaypoints, CallbackInfo ci) { for (WaypointManager manager : XaeroMiniMapState.instance.waypointManagers) { if (manager.hasWaypoint()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java index 137f314b..22a74a09 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java @@ -35,8 +35,10 @@ public abstract class GuiMapMixin extends ScreenBase { @Unique private int oldMouseX = 0; + @Unique private int oldMouseY = 0; + @Unique private long timeLastClick = 0; @@ -59,29 +61,49 @@ protected GuiMapMixin(GuiScreen parent, GuiScreen escape) { @Shadow private int screenScale; - @Inject(method = "", - at = @At("RETURN") - ) - private void injectConstruct(GuiScreen parent, GuiScreen escape, MapProcessor mapProcessor, EntityPlayer player, CallbackInfo ci) { + @Inject(method = "", at = @At("RETURN")) + private void injectConstruct( + GuiScreen parent, GuiScreen escape, MapProcessor mapProcessor, EntityPlayer player, CallbackInfo ci) { MapState.instance.layers.forEach(LayerManager::onOpenMap); } // apparently mixin can read the obfuscated names even with the deobf jar loaded. weird // i guess all the errors mcdev shows here aren't real? // deobf method = "drawScreen" - @Inject(method = "func_73863_a", - at = @At(value = "INVOKE", - target = "Lorg/lwjgl/opengl/GL11;glPushMatrix()V", - ordinal = 1 - ), - locals = LocalCapture.CAPTURE_FAILEXCEPTION - ) + @Inject( + method = "func_73863_a", + at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glPushMatrix()V", ordinal = 1), + locals = LocalCapture.CAPTURE_FAILEXCEPTION) // why is this method so long. this isnt even 1/5 of the way through and look at how many locals there are already - private void injectPreRender(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci, Minecraft mc, long startTime, long passed, double passedScrolls, - int direction, Object var12, boolean mapLoaded, boolean noWorldMapEffect, int mouseXPos, int mouseYPos, double scaleMultiplier, - double oldMousePosZ, double preScale, double fboScale, double secondaryScale, double mousePosX, double mousePosZ, int mouseFromCentreX, - int mouseFromCentreY, double oldMousePosX, int textureLevel, int leveledRegionShift) { - // snap the camera to whole pixel values. works around a rendering issue but causes another when framerate is uncapped + private void injectPreRender( + int scaledMouseX, + int scaledMouseY, + float partialTicks, + CallbackInfo ci, + Minecraft mc, + long startTime, + long passed, + double passedScrolls, + int direction, + Object var12, + boolean mapLoaded, + boolean noWorldMapEffect, + int mouseXPos, + int mouseYPos, + double scaleMultiplier, + double oldMousePosZ, + double preScale, + double fboScale, + double secondaryScale, + double mousePosX, + double mousePosZ, + int mouseFromCentreX, + int mouseFromCentreY, + double oldMousePosX, + int textureLevel, + int leveledRegionShift) { + // snap the camera to whole pixel values. works around a rendering issue but causes another when framerate is + // uncapped if (mc.gameSettings.limitFramerate < 255 || mc.gameSettings.enableVsync) { cameraX = Math.round(cameraX * scale) / scale; cameraZ = Math.round(cameraZ * scale) / scale; @@ -95,25 +117,31 @@ private void injectPreRender(int scaledMouseX, int scaledMouseY, float partialTi } // deobf method = "drawScreen" - @Inject(method = "func_73863_a", - at = @At(value = "INVOKE", - target = "Lorg/lwjgl/opengl/GL11;glEnable(I)V", - ordinal = 1, - shift = At.Shift.AFTER - ), slice = @Slice( - from = @At(value = "INVOKE", - target = "Lorg/lwjgl/opengl/GL14;glBlendFuncSeparate(IIII)V" - ), - to = @At(value = "INVOKE", - target = "Lxaero/map/mods/SupportXaeroMinimap;renderWaypoints(Lnet/minecraft/client/gui/GuiScreen;DDIIDDDDLjava/util/regex/Pattern;Ljava/util/regex/Pattern;FLxaero/map/mods/gui/Waypoint;Lnet/minecraft/client/Minecraft;Lnet/minecraft/client/gui/ScaledResolution;)Lxaero/map/mods/gui/Waypoint;" - ) - ) - ) + @Inject( + method = "func_73863_a", + at = + @At( + value = "INVOKE", + target = "Lorg/lwjgl/opengl/GL11;glEnable(I)V", + ordinal = 1, + shift = At.Shift.AFTER), + slice = + @Slice( + from = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL14;glBlendFuncSeparate(IIII)V"), + to = + @At( + value = "INVOKE", + target = + "Lxaero/map/mods/SupportXaeroMinimap;renderWaypoints(Lnet/minecraft/client/gui/GuiScreen;DDIIDDDDLjava/util/regex/Pattern;Ljava/util/regex/Pattern;FLxaero/map/mods/gui/Waypoint;Lnet/minecraft/client/Minecraft;Lnet/minecraft/client/gui/ScaledResolution;)Lxaero/map/mods/gui/Waypoint;"))) private void injectDraw(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci) { for (LayerManager layerManager : MapState.instance.layers) { if (layerManager.isLayerActive()) { // +20s are to work around precision loss from casting to int and right-shifting - layerManager.recacheFullscreenMap((int) cameraX, (int) cameraZ, (int) (mc.displayWidth / scale) + 20, (int) (mc.displayHeight / scale) + 20); + layerManager.recacheFullscreenMap( + (int) cameraX, + (int) cameraZ, + (int) (mc.displayWidth / scale) + 20, + (int) (mc.displayHeight / scale) + 20); } } @@ -127,21 +155,20 @@ private void injectDraw(int scaledMouseX, int scaledMouseY, float partialTicks, } // deobf method = drawScreen - @Inject(method = "func_73863_a", - at = @At(value = "INVOKE", - target = "Lorg/lwjgl/opengl/GL11;glTranslated(DDD)V" - ), - slice = @Slice( - from = @At(value = "FIELD", - // deobf target = "Lnet/minecraft/client/Minecraft;currentScreen:Lnet/minecraft/client/gui/GuiScreen;" - target = "Lnet/minecraft/client/Minecraft;field_71462_r:Lnet/minecraft/client/gui/GuiScreen;", - opcode = Opcodes.GETFIELD - ), - to = @At(value = "INVOKE", - target = "Lxaero/map/gui/CursorBox;drawBox(IIII)V" - ) - ) - ) + @Inject( + method = "func_73863_a", + at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glTranslated(DDD)V"), + slice = + @Slice( + from = + @At( + value = "FIELD", + // deobf target = + // "Lnet/minecraft/client/Minecraft;currentScreen:Lnet/minecraft/client/gui/GuiScreen;" + target = + "Lnet/minecraft/client/Minecraft;field_71462_r:Lnet/minecraft/client/gui/GuiScreen;", + opcode = Opcodes.GETFIELD), + to = @At(value = "INVOKE", target = "Lxaero/map/gui/CursorBox;drawBox(IIII)V"))) private void injectDrawTooltip(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci) { for (LayerRenderer layer : XaeroWorldMapState.instance.renderers) { if (layer instanceof InteractableLayerRenderer && layer.isLayerActive()) { @@ -151,25 +178,24 @@ private void injectDrawTooltip(int scaledMouseX, int scaledMouseY, float partial } // deobf method = "initGui" - @Inject(method = "func_73866_w_", - at = @At(value = "INVOKE", - target = "Lorg/lwjgl/input/Keyboard;enableRepeatEvents(Z)V" - ) - ) + @Inject( + method = "func_73866_w_", + at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Keyboard;enableRepeatEvents(Z)V")) private void injectInitButtons(CallbackInfo ci) { for (int i = 0; i < XaeroWorldMapState.instance.buttons.size(); i++) { LayerButton layerButton = XaeroWorldMapState.instance.buttons.get(i); - SizedGuiTexturedButton button = new SizedGuiTexturedButton(0, height - 20 * (i + 1), - layerButton.textureLocation, (btn) -> layerButton.toggle(), + SizedGuiTexturedButton button = new SizedGuiTexturedButton( + 0, + height - 20 * (i + 1), + layerButton.textureLocation, + (btn) -> layerButton.toggle(), new CursorBox(layerButton.getButtonTextKey())); layerButton.setButton(button); addGuiButton(button); } } - @Inject(method = "onInputPress", - at = @At("TAIL") - ) + @Inject(method = "onInputPress", at = @At("TAIL")) private void injectListenKeypress(boolean mouse, int code, CallbackInfoReturnable cir) { if (Misc.inputMatchesKeyBinding(mouse, code, VP.keyAction)) { for (LayerRenderer layer : XaeroWorldMapState.instance.renderers) { @@ -180,9 +206,7 @@ private void injectListenKeypress(boolean mouse, int code, CallbackInfoReturnabl } } - @Inject(method = "mapClicked", - at = @At("TAIL") - ) + @Inject(method = "mapClicked", at = @At("TAIL")) private void injectListenClick(int button, int x, int y, CallbackInfo ci) { if (button == 0) { final long timestamp = System.currentTimeMillis(); diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java index 780e5bfd..ed7d28ba 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java @@ -2,20 +2,19 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; -import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidRegistry; - import java.util.ArrayList; import java.util.Collections; import java.util.List; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; public class ProspectingNotification implements IMessage { @@ -24,9 +23,7 @@ public class ProspectingNotification implements IMessage { private List oreVeins; private List undergroundFluids; - public ProspectingNotification() { - - } + public ProspectingNotification() {} public ProspectingNotification(OreVeinPosition oreVeinPosition) { oreVeins = Collections.singletonList(oreVeinPosition); @@ -42,7 +39,7 @@ public ProspectingNotification(List oreVeins, List(numberOfOreVeins); - for(int i = 0; i < numberOfOreVeins; i++) { + for (int i = 0; i < numberOfOreVeins; i++) { final int dimensionId = buf.readInt(); final int chunkX = buf.readInt(); final int chunkZ = buf.readInt(); @@ -52,14 +49,14 @@ public void fromBytes(ByteBuf buf) { final int numberOfUndergroundFluids = buf.readInt(); undergroundFluids = new ArrayList<>(numberOfUndergroundFluids); - for(int i = 0; i < numberOfUndergroundFluids; i++) { + for (int i = 0; i < numberOfUndergroundFluids; i++) { final int dimensionId = buf.readInt(); final int chunkX = buf.readInt(); final int chunkZ = buf.readInt(); final Fluid fluid = FluidRegistry.getFluid(buf.readInt()); final int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; - for(int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) - for(int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { + for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) + for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { chunks[offsetChunkX][offsetChunkZ] = buf.readInt(); } undergroundFluids.add(new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); @@ -69,7 +66,7 @@ public void fromBytes(ByteBuf buf) { @Override public void toBytes(ByteBuf buf) { buf.writeInt(oreVeins.size()); - for(OreVeinPosition oreVein : oreVeins) { + for (OreVeinPosition oreVein : oreVeins) { buf.writeInt(oreVein.dimensionId); buf.writeInt(oreVein.chunkX); buf.writeInt(oreVein.chunkZ); @@ -77,12 +74,12 @@ public void toBytes(ByteBuf buf) { } buf.writeInt(undergroundFluids.size()); - for(UndergroundFluidPosition undergroundFluid : undergroundFluids) { + for (UndergroundFluidPosition undergroundFluid : undergroundFluids) { buf.writeInt(undergroundFluid.dimensionId); buf.writeInt(undergroundFluid.chunkX); buf.writeInt(undergroundFluid.chunkZ); buf.writeInt(undergroundFluid.fluid.getID()); - for(int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { + for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { buf.writeInt(undergroundFluid.chunks[offsetChunkX][offsetChunkZ]); } diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java index 21a62092..b16ef4a1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java @@ -1,5 +1,8 @@ package com.sinthoras.visualprospecting.network; +import static com.sinthoras.visualprospecting.Utils.isSmallOreId; +import static com.sinthoras.visualprospecting.Utils.oreIdToMaterialId; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.OreVeinPosition; @@ -10,15 +13,11 @@ import gregtech.common.blocks.GT_Block_Ores_Abstract; import gregtech.common.blocks.GT_TileEntity_Ores; import io.netty.buffer.ByteBuf; +import java.util.*; import net.minecraft.block.Block; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; -import java.util.*; - -import static com.sinthoras.visualprospecting.Utils.isSmallOreId; -import static com.sinthoras.visualprospecting.Utils.oreIdToMaterialId; - public class ProspectingRequest implements IMessage { public static long timestampLastRequest = 0; @@ -29,9 +28,7 @@ public class ProspectingRequest implements IMessage { private int blockZ; private short foundOreMetaData; - public ProspectingRequest() { - - } + public ProspectingRequest() {} public ProspectingRequest(int dimensionId, int blockX, int blockY, int blockZ, short foundOreMetaData) { this.dimensionId = dimensionId; @@ -43,7 +40,7 @@ public ProspectingRequest(int dimensionId, int blockX, int blockY, int blockZ, s public static boolean canSendRequest() { final long timestamp = System.currentTimeMillis(); - if(timestamp - timestampLastRequest > Config.minDelayBetweenVeinRequests) { + if (timestamp - timestampLastRequest > Config.minDelayBetweenVeinRequests) { timestampLastRequest = timestamp; return true; } @@ -78,41 +75,50 @@ public IMessage onMessage(ProspectingRequest message, MessageContext ctx) { final UUID uuid = ctx.getServerHandler().playerEntity.getUniqueID(); final long lastRequest = lastRequestPerPlayer.containsKey(uuid) ? lastRequestPerPlayer.get(uuid) : 0; final long timestamp = System.currentTimeMillis(); - final float distanceSquared = ctx.getServerHandler().playerEntity.getPlayerCoordinates().getDistanceSquared(message.blockX, message.blockY, message.blockZ); + final float distanceSquared = ctx.getServerHandler() + .playerEntity + .getPlayerCoordinates() + .getDistanceSquared(message.blockX, message.blockY, message.blockZ); final World world = ctx.getServerHandler().playerEntity.getEntityWorld(); final int chunkX = Utils.coordBlockToChunk(message.blockX); final int chunkZ = Utils.coordBlockToChunk(message.blockZ); final boolean isChunkLoaded = world.getChunkProvider().chunkExists(chunkX, chunkZ); - if(ctx.getServerHandler().playerEntity.dimension == message.dimensionId - && distanceSquared <= 1024 // max 32 blocks distance + if (ctx.getServerHandler().playerEntity.dimension == message.dimensionId + && distanceSquared <= 1024 // max 32 blocks distance && timestamp - lastRequest >= Config.minDelayBetweenVeinRequests && isChunkLoaded) { final Block block = world.getBlock(message.blockX, message.blockY, message.blockZ); - if(block instanceof GT_Block_Ores_Abstract) { + if (block instanceof GT_Block_Ores_Abstract) { final TileEntity tileEntity = world.getTileEntity(message.blockX, message.blockY, message.blockZ); if (tileEntity instanceof GT_TileEntity_Ores) { final short metaData = ((GT_TileEntity_Ores) tileEntity).mMetaData; - if(isSmallOreId(metaData) == false && oreIdToMaterialId(metaData) == message.foundOreMetaData) { + if (isSmallOreId(metaData) == false + && oreIdToMaterialId(metaData) == message.foundOreMetaData) { lastRequestPerPlayer.put(uuid, timestamp); // Prioritise center vein - final OreVeinPosition centerOreVeinPosition = ServerCache.instance.getOreVein(message.dimensionId, chunkX, chunkZ); - if(centerOreVeinPosition.veinType.containsOre(message.foundOreMetaData)) { + final OreVeinPosition centerOreVeinPosition = + ServerCache.instance.getOreVein(message.dimensionId, chunkX, chunkZ); + if (centerOreVeinPosition.veinType.containsOre(message.foundOreMetaData)) { return new ProspectingNotification(centerOreVeinPosition); } // Check if neighboring veins could fit final int centerChunkX = Utils.mapToCenterOreChunkCoord(chunkX); final int centerChunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); - for(int offsetChunkX = -3; offsetChunkX <= 3; offsetChunkX += 3) { + for (int offsetChunkX = -3; offsetChunkX <= 3; offsetChunkX += 3) { for (int offsetChunkZ = -3; offsetChunkZ <= 3; offsetChunkZ += 3) { if (offsetChunkX != 0 || offsetChunkZ != 0) { final int neighborChunkX = centerChunkX + offsetChunkX; final int neighborChunkZ = centerChunkZ + offsetChunkZ; - final int distanceBlocks = Math.max(Math.abs(neighborChunkX - chunkX), Math.abs(neighborChunkZ - chunkZ)); - final OreVeinPosition neighborOreVeinPosition = ServerCache.instance.getOreVein(message.dimensionId, neighborChunkX, neighborChunkZ); - final int maxDistance = ((neighborOreVeinPosition.veinType.blockSize + 16) >> 4) + 1; // Equals to: ceil(blockSize / 16.0) + 1 - if (neighborOreVeinPosition.veinType.containsOre(message.foundOreMetaData) && distanceBlocks <= maxDistance) { + final int distanceBlocks = Math.max( + Math.abs(neighborChunkX - chunkX), Math.abs(neighborChunkZ - chunkZ)); + final OreVeinPosition neighborOreVeinPosition = ServerCache.instance.getOreVein( + message.dimensionId, neighborChunkX, neighborChunkZ); + final int maxDistance = ((neighborOreVeinPosition.veinType.blockSize + 16) >> 4) + + 1; // Equals to: ceil(blockSize / 16.0) + 1 + if (neighborOreVeinPosition.veinType.containsOre(message.foundOreMetaData) + && distanceBlocks <= maxDistance) { return new ProspectingNotification(neighborOreVeinPosition); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java index 40fb48c4..8e21ac3e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java @@ -1,6 +1,5 @@ package com.sinthoras.visualprospecting.network; -import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; @@ -12,14 +11,13 @@ import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidRegistry; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; public class ProspectionSharing implements IMessage { @@ -31,9 +29,7 @@ public class ProspectionSharing implements IMessage { boolean isFirstMessage = false; boolean isLastMessage = false; - public ProspectionSharing() { - - } + public ProspectionSharing() {} public int putOreVeins(List oreVeins) { final int availableBytes = VP.uploadSizePerPacketInBytes - bytesUsed; @@ -73,24 +69,25 @@ public void fromBytes(ByteBuf buf) { isLastMessage = buf.readByte() > 0; final int numberOfOreVeins = buf.readInt(); - for(int i = 0; i < numberOfOreVeins; i++) { + for (int i = 0; i < numberOfOreVeins; i++) { final int dimensionId = buf.readInt(); final int chunkX = buf.readInt(); final int chunkZ = buf.readInt(); final boolean isDepleted = buf.readByte() > 0; final String oreVeinName = ByteBufUtils.readUTF8String(buf); - oreVeins.add(new OreVeinPosition(dimensionId, chunkX, chunkZ, VeinTypeCaching.getVeinType(oreVeinName), isDepleted)); + oreVeins.add(new OreVeinPosition( + dimensionId, chunkX, chunkZ, VeinTypeCaching.getVeinType(oreVeinName), isDepleted)); } final int numberOfUndergroundFluids = buf.readInt(); - for(int i = 0; i < numberOfUndergroundFluids; i++) { + for (int i = 0; i < numberOfUndergroundFluids; i++) { final int dimensionId = buf.readInt(); final int chunkX = buf.readInt(); final int chunkZ = buf.readInt(); final Fluid fluid = FluidRegistry.getFluid(buf.readInt()); final int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; - for(int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) - for(int offsetChunkZ = 0; offsetChunkZ< VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { + for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) + for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { chunks[offsetChunkX][offsetChunkZ] = buf.readInt(); } undergroundFluids.add(new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); @@ -103,7 +100,7 @@ public void toBytes(ByteBuf buf) { buf.writeByte(isLastMessage ? 1 : 0); buf.writeInt(oreVeins.size()); - for(OreVeinPosition oreVein : oreVeins) { + for (OreVeinPosition oreVein : oreVeins) { buf.writeInt(oreVein.dimensionId); buf.writeInt(oreVein.chunkX); buf.writeInt(oreVein.chunkZ); @@ -112,12 +109,12 @@ public void toBytes(ByteBuf buf) { } buf.writeInt(undergroundFluids.size()); - for(UndergroundFluidPosition undergroundFluid : undergroundFluids) { + for (UndergroundFluidPosition undergroundFluid : undergroundFluids) { buf.writeInt(undergroundFluid.dimensionId); buf.writeInt(undergroundFluid.chunkX); buf.writeInt(undergroundFluid.chunkZ); buf.writeInt(undergroundFluid.fluid.getID()); - for(int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { + for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { buf.writeInt(undergroundFluid.chunks[offsetChunkX][offsetChunkZ]); } @@ -135,20 +132,22 @@ public IMessage onMessage(ProspectionSharing message, MessageContext ctx) { final EntityPlayerMP player = ctx.getServerHandler().playerEntity; // Optional todo: Integrate over time for proper checking - if(message.getBytes() > VP.uploadSizePerPacketInBytes) { - player.playerNetServerHandler.kickPlayerFromServer("Do not spam the server! Change your VisualProcessing configuration back to the servers!"); + if (message.getBytes() > VP.uploadSizePerPacketInBytes) { + player.playerNetServerHandler.kickPlayerFromServer( + "Do not spam the server! Change your VisualProcessing configuration back to the servers!"); } - if(message.isFirstMessage) { + if (message.isFirstMessage) { oreVeins.put(player, new ArrayList<>()); undergroundFluids.put(player, new ArrayList<>()); } - if(oreVeins.containsKey(player) == false || undergroundFluids.containsKey(player) == false) { + if (oreVeins.containsKey(player) == false || undergroundFluids.containsKey(player) == false) { return null; } oreVeins.get(player).addAll(message.oreVeins); undergroundFluids.get(player).addAll(message.undergroundFluids); - if(message.isLastMessage) { - TransferCache.instance.addClientProspectionData(player.getPersistentID().toString(), oreVeins.get(player), undergroundFluids.get(player)); + if (message.isLastMessage) { + TransferCache.instance.addClientProspectionData( + player.getPersistentID().toString(), oreVeins.get(player), undergroundFluids.get(player)); oreVeins.remove(player); undergroundFluids.remove(player); } @@ -163,16 +162,16 @@ public static class ClientHandler implements IMessageHandler(); - undergroundFluids= new ArrayList<>(); + if (message.isFirstMessage) { + oreVeins = new ArrayList<>(); + undergroundFluids = new ArrayList<>(); } - if(oreVeins == null || undergroundFluids == null) { + if (oreVeins == null || undergroundFluids == null) { return null; } oreVeins.addAll(message.oreVeins); undergroundFluids.addAll(message.undergroundFluids); - if(message.isLastMessage) { + if (message.isLastMessage) { ClientCache.instance.putOreVeins(oreVeins); ClientCache.instance.putUndergroundFluids(undergroundFluids); } diff --git a/src/main/java/com/sinthoras/visualprospecting/network/WorldIdNotification.java b/src/main/java/com/sinthoras/visualprospecting/network/WorldIdNotification.java index b6fb9315..ce19945d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/WorldIdNotification.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/WorldIdNotification.java @@ -11,9 +11,7 @@ public class WorldIdNotification implements IMessage { private String worldId; - public WorldIdNotification() { - - } + public WorldIdNotification() {} public WorldIdNotification(String worldId) { this.worldId = worldId; diff --git a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java index d06e6342..8c2d2599 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java @@ -6,13 +6,12 @@ import com.sinthoras.visualprospecting.database.TransferCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.network.ProspectionSharing; +import java.util.List; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; -import java.util.List; - public class SnapshotDownloadTask implements ITask { private final EntityPlayerMP player; @@ -30,7 +29,7 @@ public SnapshotDownloadTask(String authorUuid, EntityPlayerMP player) { @Override public boolean process() { final long timestamp = System.currentTimeMillis(); - if(timestamp - lastUpload > 1000 / Config.uploadPacketsPerSecond && listsEmpty() == false) { + if (timestamp - lastUpload > 1000 / Config.uploadPacketsPerSecond && listsEmpty() == false) { lastUpload = timestamp; final ProspectionSharing packet = new ProspectionSharing(); @@ -47,8 +46,9 @@ public boolean process() { VP.network.sendTo(packet, player); - if(listsEmpty()) { - final IChatComponent notification = new ChatComponentTranslation("item.visualprospecting.prospectorslog.reading.end", player.getDisplayName()); + if (listsEmpty()) { + final IChatComponent notification = new ChatComponentTranslation( + "item.visualprospecting.prospectorslog.reading.end", player.getDisplayName()); notification.getChatStyle().setItalic(true); notification.getChatStyle().setColor(EnumChatFormatting.GRAY); player.addChatMessage(notification); diff --git a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java index cb12d817..65bd77b7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java @@ -6,7 +6,6 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.network.ProspectionSharing; - import java.util.List; public class SnapshotUploadTask implements ITask { @@ -24,7 +23,7 @@ public SnapshotUploadTask() { @Override public boolean process() { final long timestamp = System.currentTimeMillis(); - if(timestamp - lastUpload > 1000 / Config.uploadPacketsPerSecond && listsEmpty() == false) { + if (timestamp - lastUpload > 1000 / Config.uploadPacketsPerSecond && listsEmpty() == false) { lastUpload = timestamp; final ProspectionSharing packet = new ProspectionSharing(); From d7d444a64ac5ab35af3a405b2e3ca496ac080a68 Mon Sep 17 00:00:00 2001 From: miozune Date: Fri, 12 Aug 2022 19:55:41 +0900 Subject: [PATCH 011/132] Fix prospection triggered on wrong dimension (#19) --- .../minecraft/ItemEditableBookMixin.java | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java index 1b539d3a..908f917c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java @@ -35,25 +35,28 @@ private void onItemRightClick( World world, EntityPlayer entityPlayer, CallbackInfoReturnable callbackInfoReturnable) { - if (world.isRemote == false) { + if (!world.isRemote) { final NBTTagCompound compound = itemStack.getTagCompound(); if (compound.hasKey(Tags.VISUALPROSPECTING_FLAG)) { final int dimensionId = compound.getInteger(Tags.PROSPECTION_DIMENSION_ID); final int blockX = compound.getInteger(Tags.PROSPECTION_BLOCK_X); final int blockZ = compound.getInteger(Tags.PROSPECTION_BLOCK_Z); final int blockRadius = compound.getInteger(Tags.PROSPECTION_ORE_RADIUS); - final List foundOreVeins = - ServerCache.instance.prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); - final List foundUndergroundFluids = - ServerCache.instance.prospectUndergroundFluidBlockRadius( - world, blockX, blockZ, VP.undergroundFluidChunkProspectingBlockRadius); - if (Utils.isLogicalClient()) { - ClientCache.instance.putOreVeins(foundOreVeins); - ClientCache.instance.putUndergroundFluids(foundUndergroundFluids); - } else { - VP.network.sendTo( - new ProspectingNotification(foundOreVeins, foundUndergroundFluids), - (EntityPlayerMP) entityPlayer); + + if (world.provider.dimensionId == dimensionId) { + final List foundOreVeins = + ServerCache.instance.prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); + final List foundUndergroundFluids = + ServerCache.instance.prospectUndergroundFluidBlockRadius( + world, blockX, blockZ, VP.undergroundFluidChunkProspectingBlockRadius); + if (Utils.isLogicalClient()) { + ClientCache.instance.putOreVeins(foundOreVeins); + ClientCache.instance.putUndergroundFluids(foundUndergroundFluids); + } else { + VP.network.sendTo( + new ProspectingNotification(foundOreVeins, foundUndergroundFluids), + (EntityPlayerMP) entityPlayer); + } } } } From 193cd35cf0ad5fc7c5edb0008b1fda21c43f790f Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Sun, 11 Sep 2022 10:33:24 +0100 Subject: [PATCH 012/132] Performance improvements and lower memory usage (#20) * Update buildscript & dependencies * Update Enklume for significant performance improvements --- .gitattributes | 42 +++++++++ build.gradle | 208 +++++++++++++++++++++++++------------------- dependencies.gradle | 10 +-- 3 files changed, 167 insertions(+), 93 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..84cf8ff0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,42 @@ +* 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 + +*.[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 diff --git a/build.gradle b/build.gradle index ec6cfc96..054e7d94 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1659365110 +//version: 1661114848 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -26,6 +26,11 @@ buildscript { name 'forge' url 'https://maven.minecraftforge.net' } + maven { + // GTNH ForgeGradle Fork + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + } maven { name 'sonatype' url 'https://oss.sonatype.org/content/repositories/snapshots/' @@ -34,13 +39,9 @@ buildscript { 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' + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.9' } } plugins { @@ -49,17 +50,20 @@ plugins { 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 '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" + 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' apply false } -verifySettingsGradle() +boolean settingsupdated = verifySettingsGradle() +settingsupdated = verifyGitAttributes() || settingsupdated +if (settingsupdated) + throw new GradleException("Settings has been updated, please re-run task.") dependencies { implementation 'com.diffplug:blowdryer:1.6.0' @@ -90,9 +94,15 @@ idea { downloadSources = true } } -apply from: Blowdryer.file('spotless.gradle') -if(JavaVersion.current() != JavaVersion.VERSION_1_8) { +boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false + +if (!disableSpotless) { + apply plugin: 'com.diffplug.spotless' + apply from: Blowdryer.file('spotless.gradle') +} + +if (JavaVersion.current() != JavaVersion.VERSION_1_8) { throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current()) } @@ -129,53 +139,53 @@ 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())) { +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) { +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())) { + 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) { +if (accessTransformersFile) { String targetFile = "src/main/resources/META-INF/" + accessTransformersFile - if(!getFile(targetFile).exists()) { + if (!getFile(targetFile).exists()) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } } -if(usesMixins.toBoolean()) { - if(mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) { +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) + 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())) { + 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) { +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())) { + 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) } } @@ -216,15 +226,14 @@ ext { modVersion = identifiedVersion } -if(identifiedVersion == versionOverride) { +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) { +if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { archivesBaseName = customArchiveBaseName -} -else { +} else { archivesBaseName = modId } @@ -250,16 +259,16 @@ minecraft { if (replaceGradleTokenInFile) { replaceIn replaceGradleTokenInFile - if(gradleTokenModId) { + if (gradleTokenModId) { replace gradleTokenModId, modId } - if(gradleTokenModName) { + if (gradleTokenModName) { replace gradleTokenModName, modName } - if(gradleTokenVersion) { + if (gradleTokenVersion) { replace gradleTokenVersion, modVersion } - if(gradleTokenGroupName) { + if (gradleTokenGroupName) { replace gradleTokenGroupName, modGroup } } @@ -268,7 +277,7 @@ minecraft { args(arguments) jvmArgs(jvmArguments) - if(developmentEnvironmentUserName) { + if (developmentEnvironmentUserName) { args("--username", developmentEnvironmentUserName) } } @@ -279,7 +288,7 @@ minecraft { } } -if(file('addon.gradle').exists()) { +if (file('addon.gradle').exists()) { apply from: 'addon.gradle' } @@ -296,7 +305,7 @@ repositories { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' } - if(usesMixins.toBoolean() || forceEnableMixins) { + if (usesMixins.toBoolean() || forceEnableMixins) { maven { name 'sponge' url 'https://repo.spongepowered.org/repository/maven-public' @@ -308,13 +317,13 @@ repositories { } dependencies { - if(usesMixins.toBoolean()) { + 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') } - if(usesMixins.toBoolean() || forceEnableMixins) { + if (usesMixins.toBoolean() || forceEnableMixins) { // 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 @@ -390,20 +399,20 @@ jar { attributes(getManifestAttributes()) } - if(usesShadowedDependencies.toBoolean()) { + if (usesShadowedDependencies.toBoolean()) { dependsOn(shadowJar) enabled = false } } reobf { - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { addExtraSrgFile mixinSrg } } afterEvaluate { - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { tasks.compileJava { options.compilerArgs += [ "-AreobfSrgFile=${tasks.reobf.srg}", @@ -418,7 +427,7 @@ afterEvaluate { } runClient { - if(developmentEnvironmentUserName) { + if (developmentEnvironmentUserName) { arguments += [ "--username", developmentEnvironmentUserName @@ -459,7 +468,7 @@ processResources { "modName": modName } - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { from refMap } @@ -472,31 +481,31 @@ processResources { def getManifestAttributes() { def manifestAttributes = [:] - if(!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { + if (!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { manifestAttributes += ["FMLCorePluginContainsFMLMod": true] } - if(accessTransformersFile) { - manifestAttributes += ["FMLAT" : accessTransformersFile.toString()] + if (accessTransformersFile) { + manifestAttributes += ["FMLAT": accessTransformersFile.toString()] } - if(coreModClass) { + if (coreModClass) { manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass] } - if(usesMixins.toBoolean()) { + if (usesMixins.toBoolean()) { manifestAttributes += [ - "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", - "MixinConfigs" : "mixins." + modId + ".json", - "ForceLoadAsMod" : !containsMixinsAndOrCoreModOnly.toBoolean() + "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")) + from(sourceSets.main.allSource) + from(file("$projectDir/LICENSE")) getArchiveClassifier().set('sources') } @@ -546,22 +555,22 @@ task devJar(type: Jar) { attributes(getManifestAttributes()) } - if(usesShadowedDependencies.toBoolean()) { + if (usesShadowedDependencies.toBoolean()) { dependsOn(circularResolverJar) enabled = false } } task apiJar(type: Jar) { - from (sourceSets.main.allSource) { + from(sourceSets.main.allSource) { include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } - from (sourceSets.main.output) { + from(sourceSets.main.output) { include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } - from (sourceSets.main.resources.srcDirs) { + from(sourceSets.main.resources.srcDirs) { include("LICENSE") } @@ -569,11 +578,11 @@ task apiJar(type: Jar) { } artifacts { - if(!noPublishedSources) { + if (!noPublishedSources) { archives sourcesJar } archives devJar - if(apiPackage) { + if (apiPackage) { archives apiJar } } @@ -591,10 +600,10 @@ publishing { publications { maven(MavenPublication) { from components.java - if(usesShadowedDependencies.toBoolean()) { + if (usesShadowedDependencies.toBoolean()) { artifact source: shadowJar, classifier: "" } - if(!noPublishedSources) { + if (!noPublishedSources) { artifact source: sourcesJar, classifier: "sources" } artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev" @@ -609,7 +618,7 @@ publishing { // remove extra garbage from minecraft and minecraftDeps configuration pom.withXml { - def badArtifacts = [:].withDefault {[] as Set} + def badArtifacts = [:].withDefault { [] as Set } for (configuration in [ projectConfigs.minecraft, projectConfigs.minecraftDeps @@ -651,7 +660,7 @@ task updateBuildScript { } } -if (isNewBuildScriptVersionAvailable(projectDir.toString())) { +if (!project.getGradle().startParameter.isOffline() && isNewBuildScriptVersionAvailable(projectDir.toString())) { if (autoUpdateBuildScript.toBoolean()) { performBuildScriptUpdate(projectDir.toString()) } else { @@ -660,20 +669,40 @@ if (isNewBuildScriptVersionAvailable(projectDir.toString())) { } static URL availableBuildScriptUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/build.gradle") + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/build.gradle") } + static URL exampleSettingsGradleUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/main/settings.gradle.example") + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/settings.gradle.example") } +static URL exampleGitAttributesUrl() { + new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/.gitattributes") +} -def verifySettingsGradle() { + +boolean verifyGitAttributes() { + def gitattributesFile = getFile(".gitattributes") + if (!gitattributesFile.exists()) { + println("Downloading default .gitattributes") + exampleGitAttributesUrl().withInputStream { i -> gitattributesFile.withOutputStream { it << i } } + exec { + workingDir '.' + commandLine 'git', 'add', '--renormalize', '.' + } + return true + } + return false +} + +boolean verifySettingsGradle() { def settingsFile = getFile("settings.gradle") if (!settingsFile.exists()) { println("Downloading default settings.gradle") exampleSettingsGradleUrl().withInputStream { i -> settingsFile.withOutputStream { it << i } } - throw new GradleException("Settings.gradle has been updated, please re-run task.") + return true } + return false } boolean performBuildScriptUpdate(String projectDir) { @@ -681,7 +710,10 @@ boolean performBuildScriptUpdate(String 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!") - verifySettingsGradle() + boolean settingsupdated = verifySettingsGradle() + settingsupdated = verifyGitAttributes() || settingsupdated + if (settingsupdated) + throw new GradleException("Settings has been updated, please re-run task.") return true } return false @@ -701,7 +733,7 @@ boolean isNewBuildScriptVersionAvailable(String projectDir) { static String getVersionHash(String buildScriptContent) { String versionLine = buildScriptContent.find("^//version: [a-z0-9]*") - if(versionLine != null) { + if (versionLine != null) { return versionLine.split(": ").last() } return "" @@ -727,16 +759,16 @@ task deobfParams { overwrite false } - if(!file(paramsCSV).exists()) { + if (!file(paramsCSV).exists()) { println("Extracting MCP archive ...") unzip(mcpZIP, mcpDir) } println("Parsing params.csv ...") Map params = new HashMap<>() - Files.lines(Paths.get(paramsCSV)).forEach{line -> + Files.lines(Paths.get(paramsCSV)).forEach { line -> String[] cells = line.split(",") - if(cells.length > 2 && cells[0].matches("p_i?\\d+_\\d+_")) { + if (cells.length > 2 && cells[0].matches("p_i?\\d+_\\d+_")) { params.put(cells[0], cells[1]) } } @@ -749,8 +781,8 @@ task deobfParams { static int replaceParams(File file, Map params) { int fileCount = 0 -if(file.isDirectory()) { - for(File f : file.listFiles()) { +if (file.isDirectory()) { + for (File f : file.listFiles()) { fileCount += replaceParams(f, params) } return fileCount @@ -759,14 +791,14 @@ println("Visiting ${file.getName()} ...") try { String content = new String(Files.readAllBytes(file.toPath())) int hash = content.hashCode() - params.forEach{key, value -> + params.forEach { key, value -> content = content.replaceAll(key, value) } - if(hash != content.hashCode()) { + if (hash != content.hashCode()) { Files.write(file.toPath(), content.getBytes("UTF-8")) return 1 } -} catch(Exception e) { +} catch (Exception e) { e.printStackTrace() } return 0 @@ -817,16 +849,16 @@ try { //get rid of directories: int lastSlash = fileName.lastIndexOf("/") - if(lastSlash > 0) { + if (lastSlash > 0) { fileName = fileName.substring(lastSlash + 1) } //get rid of extension: - if(fileName.endsWith(".jar") || fileName.endsWith(".litemod")) { + if (fileName.endsWith(".jar") || fileName.endsWith(".litemod")) { fileName = fileName.substring(0, fileName.lastIndexOf(".")) } String hostName = url.getHost() - if(hostName.startsWith("www.")) { + if (hostName.startsWith("www.")) { hostName = hostName.substring(4) } List parts = Arrays.asList(hostName.split("\\.")) @@ -834,7 +866,7 @@ try { hostName = String.join(".", parts) return deobf(sourceURL, "$hostName/$fileName") -} catch(Exception e) { +} catch (Exception e) { return deobf(sourceURL, "deobf/${sourceURL.hashCode()}") } } @@ -849,13 +881,13 @@ 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()) { +if (file(deobfFile).exists()) { return files(deobfFile) } String mappingsVer String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/' -if(remoteMappings) { +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" @@ -891,7 +923,7 @@ return files(deobfFile) def zipMappings(String zipPath, String url, String bon2Dir) { File zipFile = new File(zipPath) -if(zipFile.exists()) { +if (zipFile.exists()) { return } diff --git a/dependencies.gradle b/dependencies.gradle index 53588654..b0281822 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,15 +1,15 @@ dependencies { - shadowImplementation('com.github.GTNewHorizons:Enklume:1.1.1:dev') + shadowImplementation('com.github.GTNewHorizons:Enklume:2.0.0:dev') - compile('com.github.GTNewHorizons:GT5-Unofficial:5.09.40.33:dev') + compile('com.github.GTNewHorizons:GT5-Unofficial:5.09.41.34:dev') compile('com.github.GTNewHorizons:TCNodeTracker:1.1.6:dev') compile('net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev') compile('curse.maven:journeymap-32274:2367915') - compileOnly('com.github.GTNewHorizons:IFU:1.9.2:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.7:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.5.36:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:IFU:1.9.4:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.8:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.5.82:dev') {transitive = false} compileOnly(deobf('https://media.forgecdn.net/files/3630/490/Xaeros_Minimap_21.10.20_Forge_1.7.10.jar')) compileOnly(deobf('https://media.forgecdn.net/files/3599/504/XaerosWorldMap_1.14.1.13_Forge_1.7.10.jar')) From 17911b1de20270b3264006e645972ab06cbe9be1 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 3 Oct 2022 10:24:28 +0100 Subject: [PATCH 013/132] Save fluids by name instead of ID (#21) Should prevent future fluid ID shifts from displaying the fluids wrong. Only applies to newly scanned fluids because of how VP saves its data (the file is append-only) --- .../database/DimensionCache.java | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index ee617905..96cadb29 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -4,7 +4,11 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.*; import net.minecraft.world.ChunkCoordIntPair; import net.minecraftforge.fluids.Fluid; @@ -49,23 +53,33 @@ public ByteBuffer saveOreChunks() { } public ByteBuffer saveUndergroundFluids() { - if (changedOrNewUndergroundFluids.isEmpty() == false) { - final ByteBuffer byteBuffer = ByteBuffer.allocate(changedOrNewUndergroundFluids.size() + if (!changedOrNewUndergroundFluids.isEmpty()) { + final int initialCapacity = changedOrNewUndergroundFluids.size() * (Long.BYTES - + Integer.BYTES * (1 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ))); - changedOrNewUndergroundFluids.stream().map(undergroundFluids::get).forEach(undergroundFluidPosition -> { - byteBuffer.putInt(undergroundFluidPosition.chunkX); - byteBuffer.putInt(undergroundFluidPosition.chunkZ); - byteBuffer.putInt(undergroundFluidPosition.fluid.getID()); - for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { - for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - byteBuffer.putInt(undergroundFluidPosition.chunks[offsetChunkX][offsetChunkZ]); + + Integer.BYTES * (8 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ)); + try (final ByteArrayOutputStream baos = new ByteArrayOutputStream(initialCapacity); + final DataOutputStream dos = new DataOutputStream(baos)) { + for (ChunkCoordIntPair changedOrNewUndergroundFluid : changedOrNewUndergroundFluids) { + UndergroundFluidPosition undergroundFluidPosition = + undergroundFluids.get(changedOrNewUndergroundFluid); + dos.writeInt(undergroundFluidPosition.chunkX); + dos.writeInt(undergroundFluidPosition.chunkZ); + byte[] fluidNameBytes = + undergroundFluidPosition.fluid.getName().getBytes(StandardCharsets.UTF_8); + // Negative to keep backwards compat with int fluidID written here before. + dos.writeInt(-fluidNameBytes.length); + dos.write(fluidNameBytes); + for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { + for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { + dos.writeInt(undergroundFluidPosition.chunks[offsetChunkX][offsetChunkZ]); + } } } - }); - changedOrNewUndergroundFluids.clear(); - byteBuffer.flip(); - return byteBuffer; + changedOrNewUndergroundFluids.clear(); + return ByteBuffer.wrap(baos.toByteArray()); + } catch (IOException e) { + throw new RuntimeException(e); + } } return null; } @@ -88,16 +102,27 @@ public void loadCache(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBu >= Integer.BYTES * (3 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ)) { final int chunkX = undergroundFluidsBuffer.getInt(); final int chunkZ = undergroundFluidsBuffer.getInt(); - final Fluid fluid = FluidRegistry.getFluid(undergroundFluidsBuffer.getInt()); + final int fluidIDorNameLength = undergroundFluidsBuffer.getInt(); + final Fluid fluid; + if (fluidIDorNameLength < 0) { // name length + byte[] fluidNameBytes = new byte[-fluidIDorNameLength]; + undergroundFluidsBuffer.get(fluidNameBytes); + String fluidName = new String(fluidNameBytes, StandardCharsets.UTF_8); + fluid = FluidRegistry.getFluid(fluidName); + } else { // ID (legacy save format) + fluid = FluidRegistry.getFluid(fluidIDorNameLength); + } final int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { chunks[offsetChunkX][offsetChunkZ] = undergroundFluidsBuffer.getInt(); } } - undergroundFluids.put( - getUndergroundFluidKey(chunkX, chunkZ), - new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); + if (fluid != null) { + undergroundFluids.put( + getUndergroundFluidKey(chunkX, chunkZ), + new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); + } } } } From 2c42c1bca63f8747209fff225d7c6814a47d2c80 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Wed, 12 Oct 2022 10:55:12 -0700 Subject: [PATCH 014/132] Remove IFU mixin, now uses a native integration (#22) --- dependencies.gradle | 1 - .../visualprospecting/mixinplugin/Mixin.java | 2 - .../mixinplugin/TargetedMod.java | 1 - .../mixins/ifu/ItemOreFinderToolMixin.java | 100 ------------------ 4 files changed, 104 deletions(-) delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/ifu/ItemOreFinderToolMixin.java diff --git a/dependencies.gradle b/dependencies.gradle index b0281822..687cbf87 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,7 +7,6 @@ dependencies { compile('net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev') compile('curse.maven:journeymap-32274:2367915') - compileOnly('com.github.GTNewHorizons:IFU:1.9.4:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.8:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:bartworks:0.5.82:dev') {transitive = false} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java index 8a6d0e9d..1a54a184 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java @@ -24,8 +24,6 @@ public enum Mixin { GT_MetaTileEntity_ScannerMixin("gregtech.GT_MetaTileEntity_ScannerMixin", GREGTECH), GT_WorldGenContainerMixin("gregtech.WorldGenContainerMixin", GREGTECH), - ItemOreFinderToolMixin("ifu.ItemOreFinderToolMixin", IFU), - FullscreenMixin("journeymap.FullscreenMixin", Side.CLIENT, JOURNEYMAP), FullscreenActionsMixin("journeymap.FullscreenActionsMixin", Side.CLIENT, JOURNEYMAP), MiniMapMixin("journeymap.MiniMapMixin", Side.CLIENT, JOURNEYMAP), diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java index 71204228..dcacd941 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java @@ -19,7 +19,6 @@ public enum TargetedMod { XAEROWORLDMAP("Xaero's World Map", "XaerosWorldMap", true), XAEROMINIMAP("Xaero's Minimap", "Xaeros_Minimap", true), TCNODETRACKER("TCNodeTracker", "tcnodetracker-1.7.10", true), - IFU("I will find you", "ifu", false), BARTWORKS("Bartworks", "bartworks", false), GALACTICGREG("GalacticGreg", "GalacticGreg", false); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/ifu/ItemOreFinderToolMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/ifu/ItemOreFinderToolMixin.java deleted file mode 100644 index 9132ae5f..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/ifu/ItemOreFinderToolMixin.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.ifu; - -import com.encraft.dz.items.ItemOreFinderTool; -import com.sinthoras.visualprospecting.VisualProspecting_API; -import com.sinthoras.visualprospecting.VisualProspecting_API.LogicalServer; -import com.sinthoras.visualprospecting.database.OreVeinPosition; -import gregtech.api.enums.OrePrefixes; -import gregtech.api.objects.ItemData; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import net.minecraft.block.Block; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.At.Shift; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -@Mixin(value = ItemOreFinderTool.class, remap = false) -public class ItemOreFinderToolMixin extends Item { - - @Shadow - private static int found; - - @Shadow - private static int MAX_DAMAGE; - - @Inject( - method = "onUpdate", - at = - @At( - value = "INVOKE", - target = "Lcom/encraft/dz/items/ItemOreFinderTool;shouldKeepLooking()Z", - shift = Shift.AFTER, - remap = false, - ordinal = 0), - locals = LocalCapture.CAPTURE_FAILEXCEPTION, - remap = true) - public void onGtOreFound( - ItemStack itemstack, - World world, - Entity entity, - int par4, - boolean par5, - CallbackInfo ci, - ItemStack searchItem, - ItemData data, - boolean vanilla, - int id, - double cur_x, - double cur_y, - double cur_z, - int min_x, - int min_y, - int min_z, - int max_x, - int max_y, - int max_z, - boolean keepLooking, - int z1, - int x1, - int y1, - Block tBlock, - int meta, - ItemStack inWorld, - ItemData dataInWorld, - List oreTypes) { - if (vanilla || world.isRemote || didNotDetectSignificantOreCluster() || !(entity instanceof EntityPlayer)) - return; - - final short foundMaterialMetaId = (short) dataInWorld.mMaterial.mMaterial.mMetaItemSubID; - - final int blockX = x1; - final int blockZ = z1; - final List discoveredOreVeins = - listVeinsInProximityContaining(foundMaterialMetaId, blockX, blockZ, world); - - VisualProspecting_API.LogicalServer.sendProspectionResultsToClient( - (EntityPlayerMP) entity, discoveredOreVeins, Collections.emptyList()); - } - - private boolean didNotDetectSignificantOreCluster() { - return found < MAX_DAMAGE; - } - - private List listVeinsInProximityContaining( - short foundMaterialMetaId, int blocX, int blockZ, World world) { - return LogicalServer.prospectOreVeinsWithinRadius(world.provider.dimensionId, blocX, blockZ, 48).stream() - .filter(it -> it.veinType.containsOre(foundMaterialMetaId)) - .collect(Collectors.toList()); - } -} From 07de40d6eb44aa291b493a7802c0db71ca786cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Dip=C4=8D=C3=A1r?= Date: Sun, 20 Nov 2022 14:06:38 +0100 Subject: [PATCH 015/132] Update BuildScript (#23) * Update BuildScript * Update BuildScript again * spotlessApply Co-authored-by: GitHub GTNH Actions <> --- build.gradle | 256 ++++++++++++++---- .../sinthoras/visualprospecting/VPMod.java | 7 +- .../mixinplugin/MixinPlugin.java | 2 +- .../mixins/journeymap/FullscreenMixin.java | 2 +- .../mixins/tcnodetracker/GuiMainMixin.java | 2 +- 5 files changed, 205 insertions(+), 64 deletions(-) diff --git a/build.gradle b/build.gradle index 054e7d94..987d3023 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,17 @@ -//version: 1661114848 +//version: 1668274302 /* 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. + Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/build.gradle for updates. */ import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.matthewprenger.cursegradle.CurseArtifact +import com.matthewprenger.cursegradle.CurseRelation +import com.modrinth.minotaur.dependencies.ModDependency +import com.modrinth.minotaur.dependencies.VersionDependency import org.gradle.internal.logging.text.StyledTextOutput.Style import org.gradle.internal.logging.text.StyledTextOutputFactory @@ -41,7 +45,7 @@ buildscript { } } dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.9' + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.11' } } plugins { @@ -59,6 +63,8 @@ plugins { 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' apply false + id 'com.modrinth.minotaur' version '2.+' apply false + id 'com.matthewprenger.cursegradle' version '1.4.0' apply false } boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated @@ -127,26 +133,35 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") -boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false -boolean usesMixinDebug = project.hasProperty('usesMixinDebug') ?: project.usesMixins.toBoolean() -boolean forceEnableMixins = project.hasProperty('forceEnableMixins') ? project.forceEnableMixins.toBoolean() : false -String channel = project.hasProperty('channel') ? project.channel : 'stable' -String mappingsVersion = project.hasProperty('mappingsVersion') ? project.mappingsVersion : '12' +propertyDefaultIfUnset("noPublishedSources", false) +propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) +propertyDefaultIfUnset("forceEnableMixins", false) +propertyDefaultIfUnset("channel", "stable") +propertyDefaultIfUnset("mappingsVersion", "12") +propertyDefaultIfUnset("modrinthProjectId", "") +propertyDefaultIfUnset("modrinthRelations", "") +propertyDefaultIfUnset("curseForgeProjectId", "") +propertyDefaultIfUnset("curseForgeRelations", "") + 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("\\.", "/") + +final String modGroupPath = modGroup.toString().replaceAll("\\.", "/") +final String apiPackagePath = apiPackage.toString().replaceAll("\\.", "/") + +String targetPackageJava = javaSourceDir + modGroupPath +String targetPackageScala = scalaSourceDir + modGroupPath +String targetPackageKotlin = kotlinSourceDir + modGroupPath 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("\\.", "/") + targetPackageJava = javaSourceDir + modGroupPath + "/" + apiPackagePath + targetPackageScala = scalaSourceDir + modGroupPath + "/" + apiPackagePath + targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + apiPackagePath 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) } @@ -160,31 +175,36 @@ if (accessTransformersFile) { } if (usesMixins.toBoolean()) { - if (mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) { - throw new GradleException("\"mixinPlugin\" requires \"mixinsPackage\" and \"mixinPlugin\" to be set!") + if (mixinsPackage.isEmpty()) { + throw new GradleException("\"usesMixins\" requires \"mixinsPackage\" to be set!") } + final String mixinPackagePath = mixinsPackage.toString().replaceAll("\\.", "/") + final String mixinPluginPath = mixinPlugin.toString().replaceAll("\\.", "/") - targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") + targetPackageJava = javaSourceDir + modGroupPath + "/" + mixinPackagePath + targetPackageScala = scalaSourceDir + modGroupPath + "/" + mixinPackagePath + targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPackagePath 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 (!mixinPlugin.isEmpty()) { + String targetFileJava = javaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" + String targetFileScala = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".scala" + String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" + String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPluginPath + ".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" + final String coreModPath = coreModClass.toString().replaceAll("\\.", "/") + String targetFileJava = javaSourceDir + modGroupPath + "/" + coreModPath + ".java" + String targetFileScala = scalaSourceDir + modGroupPath + "/" + coreModPath + ".scala" + String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + coreModPath + ".java" + String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + coreModPath + ".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) } @@ -240,7 +260,7 @@ if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { def arguments = [] def jvmArguments = [] -if (usesMixins.toBoolean() || forceEnableMixins) { +if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { arguments += [ "--tweakClass org.spongepowered.asm.launch.MixinTweaker" ] @@ -305,13 +325,10 @@ repositories { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' } - if (usesMixins.toBoolean() || forceEnableMixins) { + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { maven { - name 'sponge' - url 'https://repo.spongepowered.org/repository/maven-public' - } - maven { - url 'https://jitpack.io' + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" } } } @@ -321,19 +338,10 @@ dependencies { 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') - } - if (usesMixins.toBoolean() || forceEnableMixins) { - // 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') + annotationProcessor('org.spongepowered:mixin:0.8.5-GTNH:processor') + } + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { + compile('com.gtnewhorizon:gtnhmixins:2.0.2') } } @@ -345,13 +353,18 @@ def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" task generateAssets { if (usesMixins.toBoolean()) { - def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json"); + def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json") if (!mixinConfigFile.exists()) { + def mixinPluginLine = "" + if(!mixinPlugin.isEmpty()) { + // We might not have a mixin plugin if we're using early/late mixins + mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ + } + mixinConfigFile.text = """{ "required": true, - "minVersion": "0.7.11", - "package": "${modGroup}.${mixinsPackage}", - "plugin": "${modGroup}.${mixinPlugin}", + "minVersion": "0.8.5-GTNH", + "package": "${modGroup}.${mixinsPackage}",${mixinPluginLine} "refmap": "${mixingConfigRefMap}", "target": "@env(DEFAULT)", "compatibilityLevel": "JAVA_8", @@ -563,11 +576,11 @@ task devJar(type: Jar) { task apiJar(type: Jar) { from(sourceSets.main.allSource) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' + include modGroupPath + "/" + apiPackagePath + '/**' } from(sourceSets.main.output) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' + include modGroupPath + "/" + apiPackagePath + '/**' } from(sourceSets.main.resources.srcDirs) { @@ -651,6 +664,124 @@ publishing { } } +if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { + apply plugin: 'com.modrinth.minotaur' + + File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") + + modrinth { + token = System.getenv("MODRINTH_TOKEN") + projectId = modrinthProjectId + versionNumber = identifiedVersion + versionType = identifiedVersion.endsWith("-pre") ? "beta" : "release" + changelog = changelogFile.exists() ? changelogFile.getText("UTF-8") : "" + uploadFile = jar + additionalFiles = getSecondaryArtifacts() + gameVersions = [minecraftVersion] + loaders = ["forge"] + debugMode = false + } + + if (modrinthRelations.size() != 0) { + String[] deps = modrinthRelations.split(";") + deps.each { dep -> + if (dep.size() == 0) { + return + } + String[] parts = dep.split(":") + String[] qual = parts[0].split("-") + addModrinthDep(qual[0], qual[1], parts[1]) + } + } + if (usesMixins.toBoolean()) { + addModrinthDep("required", "version", "gtnhmixins") + } + tasks.modrinth.dependsOn(build) + tasks.publish.dependsOn(tasks.modrinth) +} + +if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null) { + apply plugin: 'com.matthewprenger.cursegradle' + + File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") + + curseforge { + apiKey = System.getenv("CURSEFORGE_TOKEN") + project { + id = curseForgeProjectId + if (changelogFile.exists()) { + changelogType = "markdown" + changelog = changelogFile + } + releaseType = identifiedVersion.endsWith("-pre") ? "beta" : "release" + addGameVersion minecraftVersion + addGameVersion "Forge" + mainArtifact jar + for (artifact in getSecondaryArtifacts()) addArtifact artifact + } + + options { + javaIntegration = false + forgeGradleIntegration = false + debug = false + } + } + + if (curseForgeRelations.size() != 0) { + String[] deps = curseForgeRelations.split(";") + deps.each { dep -> + if (dep.size() == 0) { + return + } + String[] parts = dep.split(":") + addCurseForgeRelation(parts[0], parts[1]) + } + } + if (usesMixins.toBoolean()) { + addCurseForgeRelation("requiredDependency", "gtnhmixins") + } + tasks.curseforge.dependsOn(build) + tasks.publish.dependsOn(tasks.curseforge) +} + +def addModrinthDep(scope, type, name) { + com.modrinth.minotaur.dependencies.Dependency dep; + if (!(scope in [ + "required", + "optional", + "incompatible", + "embedded" + ])) { + throw new Exception("Invalid modrinth dependency scope: " + scope) + } + switch (type) { + case "project": + dep = new ModDependency(name, scope) + break + case "version": + dep = new VersionDependency(name, scope) + break + default: + throw new Exception("Invalid modrinth dependency type: " + type) + } + project.modrinth.dependencies.add(dep) +} + +def addCurseForgeRelation(type, name) { + if (!(type in [ + "requiredDependency", + "embeddedLibrary", + "optionalDependency", + "tool", + "incompatible" + ])) { + throw new Exception("Invalid CurseForge relation type: " + type) + } + CurseArtifact artifact = project.curseforge.curseProjects[0].mainArtifact + CurseRelation rel = (artifact.curseRelations ?: (artifact.curseRelations = new CurseRelation())) + rel."$type"(name) +} + // Updating task updateBuildScript { doLast { @@ -963,6 +1094,21 @@ if (!project.hasProperty(propertyName)) { } } +def propertyDefaultIfUnset(String propertyName, defaultValue) { +if (!project.hasProperty(propertyName) || project.property(propertyName) == "") { + project.ext.setProperty(propertyName, defaultValue) +} +} + def getFile(String relativePath) { return new File(projectDir, relativePath) } + +def getSecondaryArtifacts() { +// Because noPublishedSources from the beginning of the script is somehow not visible here... +boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false +def secondaryArtifacts = [devJar] +if (!noPublishedSources) secondaryArtifacts += [sourcesJar] +if (apiPackage) secondaryArtifacts += [apiJar] +return secondaryArtifacts +} diff --git a/src/main/java/com/sinthoras/visualprospecting/VPMod.java b/src/main/java/com/sinthoras/visualprospecting/VPMod.java index 4490392e..c6e992da 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VPMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/VPMod.java @@ -5,12 +5,7 @@ import cpw.mods.fml.common.SidedProxy; import cpw.mods.fml.common.event.*; -@Mod( - modid = Tags.MODID, - version = Tags.VERSION, - name = Tags.MODNAME, - acceptedMinecraftVersions = "[1.7.10]", - dependencies = "required-after:spongemixins@[1.1.0,);") +@Mod(modid = Tags.MODID, version = Tags.VERSION, name = Tags.MODNAME, acceptedMinecraftVersions = "[1.7.10]") public class VPMod { @SidedProxy(clientSide = Tags.GROUPNAME + ".hooks.HooksClient", serverSide = Tags.GROUPNAME + ".hooks.HooksShared") diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java index f9e5be88..864694fe 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java @@ -16,9 +16,9 @@ import net.minecraft.launchwrapper.Launch; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.lib.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; +import org.spongepowered.libraries.org.objectweb.asm.tree.ClassNode; import ru.timeconqueror.spongemixins.MinecraftURLClassPath; public class MixinPlugin implements IMixinConfigPlugin { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java index 7d2968ea..61538cb2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java @@ -30,7 +30,6 @@ import net.minecraft.client.renderer.RenderHelper; import org.apache.logging.log4j.Level; import org.lwjgl.input.Mouse; -import org.spongepowered.asm.lib.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -39,6 +38,7 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.spongepowered.libraries.org.objectweb.asm.Opcodes; @Mixin(value = Fullscreen.class, remap = false) public abstract class FullscreenMixin extends JmUI { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java index 6f6ae43d..eb0a99aa 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java @@ -6,13 +6,13 @@ import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.resources.I18n; -import org.spongepowered.asm.lib.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import org.spongepowered.libraries.org.objectweb.asm.Opcodes; @Mixin(GuiMain.class) public class GuiMainMixin { From 29f5d04ce98b75e9e0bc7a4bc00ae158a493ac57 Mon Sep 17 00:00:00 2001 From: froot <66188216+kumquat-ir@users.noreply.github.com> Date: Wed, 4 Jan 2023 07:32:00 -0800 Subject: [PATCH 016/132] Fix Xaero's map issues: (#25) - Now works with (and requires) a newer version of Xaero's maps - Refactor out a very volatile local capture so I don't have to constantly update it - Fix waypoints not appearing when ore veins/TC nodes are activated - Remove some warning suppressions that were apparently unneeded --- dependencies.gradle | 4 +- .../sinthoras/visualprospecting/Utils.java | 4 ++ .../integration/model/MapState.java | 8 +++- .../renderers/InteractableLayerRenderer.java | 14 +++---- .../minecraft/ForgeHooksClientMixin.java | 1 - .../xaerosminimap/MinimapRendererMixin.java | 1 - .../mixins/xaerosworldmap/GuiMapMixin.java | 39 ++++--------------- 7 files changed, 28 insertions(+), 43 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 687cbf87..f4877300 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -10,7 +10,7 @@ dependencies { compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.8:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:bartworks:0.5.82:dev') {transitive = false} - compileOnly(deobf('https://media.forgecdn.net/files/3630/490/Xaeros_Minimap_21.10.20_Forge_1.7.10.jar')) - compileOnly(deobf('https://media.forgecdn.net/files/3599/504/XaerosWorldMap_1.14.1.13_Forge_1.7.10.jar')) + compileOnly(deobf('https://media.forgecdn.net/files/4127/308/Xaeros_Minimap_21.10.30_Forge_1.7.10.jar')) + compileOnly(deobf('https://media.forgecdn.net/files/4127/328/XaerosWorldMap_1.14.1.22_Forge_1.7.10.jar')) compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 33708371..279da79a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -44,6 +44,10 @@ public static boolean isXaerosWorldMapInstalled() { return Loader.isModLoaded("XaeroWorldMap"); } + public static boolean isXaerosMinimapInstalled() { + return Loader.isModLoaded("XaeroMinimap"); + } + public static boolean isVoxelMapInstalled() { try { // If a LiteLoader mod is present cannot be checked by calling Loader#isModLoaded. diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java index 200d5dff..c57a4863 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java @@ -1,11 +1,12 @@ package com.sinthoras.visualprospecting.integration.model; -import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; +import static com.sinthoras.visualprospecting.Utils.*; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.integration.model.buttons.*; import com.sinthoras.visualprospecting.integration.model.layers.*; import com.sinthoras.visualprospecting.integration.tcnodetracker.NTNodeTrackerWaypointManager; +import com.sinthoras.visualprospecting.integration.xaerominimap.XaeroMiniMapState; import java.util.ArrayList; import java.util.List; @@ -33,5 +34,10 @@ public MapState() { buttons.add(DirtyChunkButtonManager.instance); layers.add(DirtyChunkLayerManager.instance); } + + if (isXaerosMinimapInstalled()) { + // need to classload XaeroMiniMapState in order for its waypoint manager to get registered + XaeroMiniMapState.instance.toString(); + } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java index fc176354..4d3d304c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java @@ -8,8 +8,8 @@ import net.minecraft.client.gui.GuiScreen; public abstract class InteractableLayerRenderer extends LayerRenderer { - private double mouseXForRender; - private double mouseYForRender; + private double mouseX; + private double mouseY; protected WaypointProviderManager manager; protected InteractableRenderStep hovered; @@ -23,12 +23,12 @@ public InteractableLayerRenderer(WaypointProviderManager manager) { protected abstract List generateRenderSteps( List visibleElements); - public void updateHovered(double mouseX, double mouseY, double cameraX, double cameraZ, double scale) { - mouseXForRender = mouseX - cameraX; - mouseYForRender = mouseY - cameraZ; + public void updateHovered(double mouseX, double mouseY, double scale) { + this.mouseX = mouseX; + this.mouseY = mouseY; for (RenderStep step : renderStepsReversed) { if (step instanceof InteractableRenderStep - && ((InteractableRenderStep) step).isMouseOver(mouseXForRender, mouseYForRender, scale)) { + && ((InteractableRenderStep) step).isMouseOver(mouseX, mouseY, scale)) { hovered = (InteractableRenderStep) step; return; } @@ -38,7 +38,7 @@ public void updateHovered(double mouseX, double mouseY, double cameraX, double c public void drawTooltip(GuiScreen gui, double scale, int scaleAdj) { if (hovered != null) { - hovered.drawTooltip(gui, mouseXForRender, mouseYForRender, scale, scaleAdj); + hovered.drawTooltip(gui, mouseX, mouseY, scale, scaleAdj); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java index 85070a08..7a4b1640 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java @@ -6,7 +6,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@SuppressWarnings("UnusedMixin") @Mixin(value = ForgeHooksClient.class, remap = false) public class ForgeHooksClientMixin { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java index 2b3dcbd1..20f611ab 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java @@ -23,7 +23,6 @@ import xaero.common.minimap.render.MinimapRenderer; import xaero.common.settings.ModSettings; -@SuppressWarnings("UnusedMixin") @Mixin(value = MinimapRenderer.class, remap = false) public class MinimapRendererMixin { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java index 22a74a09..97c5c878 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java @@ -12,7 +12,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.Entity; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -29,7 +29,6 @@ import xaero.map.gui.ScreenBase; import xaero.map.misc.Misc; -@SuppressWarnings({"MixinAnnotationTarget", "UnresolvedMixinReference", "UnusedMixin"}) @Mixin(value = GuiMap.class, remap = false) public abstract class GuiMapMixin extends ScreenBase { @@ -63,7 +62,7 @@ protected GuiMapMixin(GuiScreen parent, GuiScreen escape) { @Inject(method = "", at = @At("RETURN")) private void injectConstruct( - GuiScreen parent, GuiScreen escape, MapProcessor mapProcessor, EntityPlayer player, CallbackInfo ci) { + GuiScreen parent, GuiScreen escape, MapProcessor mapProcessor, Entity player, CallbackInfo ci) { MapState.instance.layers.forEach(LayerManager::onOpenMap); } @@ -74,34 +73,8 @@ private void injectConstruct( method = "func_73863_a", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glPushMatrix()V", ordinal = 1), locals = LocalCapture.CAPTURE_FAILEXCEPTION) - // why is this method so long. this isnt even 1/5 of the way through and look at how many locals there are already private void injectPreRender( - int scaledMouseX, - int scaledMouseY, - float partialTicks, - CallbackInfo ci, - Minecraft mc, - long startTime, - long passed, - double passedScrolls, - int direction, - Object var12, - boolean mapLoaded, - boolean noWorldMapEffect, - int mouseXPos, - int mouseYPos, - double scaleMultiplier, - double oldMousePosZ, - double preScale, - double fboScale, - double secondaryScale, - double mousePosX, - double mousePosZ, - int mouseFromCentreX, - int mouseFromCentreY, - double oldMousePosX, - int textureLevel, - int leveledRegionShift) { + int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci, Minecraft mc) { // snap the camera to whole pixel values. works around a rendering issue but causes another when framerate is // uncapped if (mc.gameSettings.limitFramerate < 255 || mc.gameSettings.enableVsync) { @@ -109,9 +82,13 @@ private void injectPreRender( cameraZ = Math.round(cameraZ * scale) / scale; } + // there's some nice local variables for exactly this but the local table for this function is hell + double mousePosX = (double) ((int) Misc.getMouseX(mc) - mc.displayWidth / 2) / this.scale; + double mousePosZ = (double) ((int) Misc.getMouseY(mc) - mc.displayHeight / 2) / this.scale; + for (LayerRenderer layer : XaeroWorldMapState.instance.renderers) { if (layer instanceof InteractableLayerRenderer) { - ((InteractableLayerRenderer) layer).updateHovered(mousePosX, mousePosZ, cameraX, cameraZ, scale); + ((InteractableLayerRenderer) layer).updateHovered(mousePosX, mousePosZ, scale); } } } From b1bb9c66b9faba1da632bb75d7e79573247851b4 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Sun, 29 Jan 2023 10:48:01 -0800 Subject: [PATCH 017/132] [ci skip] Update buildscript to RetroFuturaGradle --- .gitattributes | 2 + build.gradle | 1046 ++++++++++++---------- gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 272 +++--- gradlew.bat | 38 +- settings.gradle | 24 +- 7 files changed, 776 insertions(+), 609 deletions(-) diff --git a/.gitattributes b/.gitattributes index 84cf8ff0..fd2792b6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -32,6 +32,8 @@ *.[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 diff --git a/build.gradle b/build.gradle index 987d3023..18afe431 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1668274302 +//version: 1675013090 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -6,24 +6,27 @@ */ +import com.diffplug.blowdryer.Blowdryer import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar import com.matthewprenger.cursegradle.CurseArtifact import com.matthewprenger.cursegradle.CurseRelation import com.modrinth.minotaur.dependencies.ModDependency import com.modrinth.minotaur.dependencies.VersionDependency import org.gradle.internal.logging.text.StyledTextOutput.Style import org.gradle.internal.logging.text.StyledTextOutputFactory +import org.jetbrains.gradle.ext.* 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 { + mavenLocal() mavenCentral() maven { @@ -31,9 +34,10 @@ buildscript { url 'https://maven.minecraftforge.net' } maven { - // GTNH ForgeGradle Fork - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + // GTNH RetroFuturaGradle and ASM Fork + name "GTNH Maven" + url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + allowInsecureProtocol = true } maven { name 'sonatype' @@ -44,74 +48,41 @@ buildscript { url 'https://repo1.maven.org/maven2/' } } - dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.11' - } } plugins { id 'java-library' - id 'idea' + id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7" 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 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version ,unused, available for addon.gradle + id 'com.github.johnrengelman.shadow' version '7.1.2' apply false + id 'com.palantir.git-version' version '0.13.0' apply false // 0.13.0 is the last jvm8 supporting version + id 'de.undercouch.download' version '5.3.0' + id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle id 'com.diffplug.spotless' version '6.7.2' apply false id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false + id 'com.gtnewhorizons.retrofuturagradle' version '1.0.18' } boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated if (settingsupdated) throw new GradleException("Settings has been updated, please re-run task.") -dependencies { - implementation 'com.diffplug:blowdryer:1.6.0' -} - -apply plugin: 'com.diffplug.blowdryer' - 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 - } -} - boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false -if (!disableSpotless) { - apply plugin: 'com.diffplug.spotless' - apply from: Blowdryer.file('spotless.gradle') -} - -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") @@ -119,10 +90,7 @@ checkPropertyExists("autoUpdateBuildScript") checkPropertyExists("minecraftVersion") checkPropertyExists("forgeVersion") checkPropertyExists("replaceGradleTokenInFile") -checkPropertyExists("gradleTokenModId") -checkPropertyExists("gradleTokenModName") checkPropertyExists("gradleTokenVersion") -checkPropertyExists("gradleTokenGroupName") checkPropertyExists("apiPackage") checkPropertyExists("accessTransformersFile") checkPropertyExists("usesMixins") @@ -133,6 +101,8 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") +propertyDefaultIfUnset("generateGradleTokenClass", "") +propertyDefaultIfUnset("includeWellKnownRepositories", true) propertyDefaultIfUnset("noPublishedSources", false) propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) propertyDefaultIfUnset("forceEnableMixins", false) @@ -142,14 +112,82 @@ propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") propertyDefaultIfUnset("curseForgeRelations", "") +propertyDefaultIfUnset("minimizeShadowedDependencies", true) +// Deprecated properties (kept for backwards compat) +propertyDefaultIfUnset("gradleTokenModId", "") +propertyDefaultIfUnset("gradleTokenModName", "") +propertyDefaultIfUnset("gradleTokenGroupName", "") + +propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only +propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only + +project.extensions.add(Blowdryer, "Blowdryer", Blowdryer) // Make blowdryer available in "apply from:" scripts +if (!disableSpotless) { + apply plugin: 'com.diffplug.spotless' + apply from: Blowdryer.file('spotless.gradle') +} String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" +if (usesShadowedDependencies.toBoolean()) { + apply plugin: "com.github.johnrengelman.shadow" +} -final String modGroupPath = modGroup.toString().replaceAll("\\.", "/") -final String apiPackagePath = apiPackage.toString().replaceAll("\\.", "/") +java { + toolchain { + if (enableModernJavaSyntax.toBoolean()) { + languageVersion.set(JavaLanguageVersion.of(17)) + } else { + languageVersion.set(projectJavaVersion) + } + vendor.set(JvmVendorSpec.ADOPTIUM) + } + if (!noPublishedSources) { + withSourcesJar() + } +} + +configurations { + create("runtimeOnlyNonPublishable") { + description = "Runtime only dependencies that are not published alongside the jar" + canBeConsumed = false + canBeResolved = false + } +} + +if (enableModernJavaSyntax.toBoolean()) { + dependencies { + annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' + compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { + transitive = false // We only care about the 1 annotation class + } + } + + tasks.withType(JavaCompile).configureEach { + if (it.name in ["compileMcLauncherJava", "compilePatchedMcJava"]) { + return + } + sourceCompatibility = 17 // for the IDE support + options.release.set(8) + + javaCompiler.set(javaToolchains.compilerFor { + languageVersion.set(JavaLanguageVersion.of(17)) + vendor.set(JvmVendorSpec.ADOPTIUM) + }) + } +} + +eclipse { + classpath { + downloadSources = true + downloadJavadoc = true + } +} + +final String modGroupPath = modGroup.toString().replace('.' as char, '/' as char) +final String apiPackagePath = apiPackage.toString().replace('.' as char, '/' as char) String targetPackageJava = javaSourceDir + modGroupPath String targetPackageScala = scalaSourceDir + modGroupPath @@ -172,6 +210,27 @@ if (accessTransformersFile) { if (!getFile(targetFile).exists()) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) +} else { + boolean atsFound = false + for (File at : sourceSets.getByName("main").resources.files) { + if (at.name.toLowerCase().endsWith("_at.cfg")) { + atsFound = true + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) + } + } + for (File at : sourceSets.getByName("api").resources.files) { + if (at.name.toLowerCase().endsWith("_at.cfg")) { + atsFound = true + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) + } + } + if (atsFound) { + logger.warn("Found and added access transformers in the resources folder, please configure gradle.properties to explicitly mention them by name") + } } if (usesMixins.toBoolean()) { @@ -210,7 +269,7 @@ if (coreModClass) { } } -configurations.all { +configurations.configureEach { resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS) // Make sure GregTech build won't time out @@ -234,14 +293,14 @@ try { } 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' + + '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.)' - ) + '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 +version = identifiedVersion ext { modVersion = identifiedVersion } @@ -257,54 +316,72 @@ if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { archivesBaseName = modId } -def arguments = [] -def jvmArguments = [] - -if (usesMixins.toBoolean() || forceEnableMixins.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 + for (f in replaceGradleTokenInFile.split(',')) { + tagReplacementFiles.add f } - if (gradleTokenGroupName) { - replace gradleTokenGroupName, modGroup + } + if (gradleTokenModId) { + injectedTags.put gradleTokenModId, modId + } + if (gradleTokenModName) { + injectedTags.put gradleTokenModName, modName + } + if (gradleTokenVersion) { + injectedTags.put gradleTokenVersion, modVersion + } + if (gradleTokenGroupName) { + injectedTags.put gradleTokenGroupName, modGroup + } + if (enableGenericInjection.toBoolean()) { + injectMissingGenerics.set(true) + } + + // Enable assertions in the current mod + extraRunJvmArguments.add("-ea:${modGroup}") + + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { + extraTweakClasses.add("org.spongepowered.asm.launch.MixinTweaker") + + if (usesMixinDebug.toBoolean()) { + extraRunJvmArguments.addAll([ + "-Dmixin.debug.countInjections=true", + "-Dmixin.debug.verbose=true", + "-Dmixin.debug.export=true" + ]) } } - clientIntellijRun { - args(arguments) - jvmArgs(jvmArguments) + // Blowdryer is present in some old mod builds, do not propagate it further as a dependency + // IC2 has no reobf jars in its Maven + groupsToExcludeFromAutoReobfMapping.addAll(["com.diffplug", "com.diffplug.durian", "net.industrial-craft"]) +} + +if (generateGradleTokenClass) { + tasks.injectTags.outputClassName.set(generateGradleTokenClass) +} - if (developmentEnvironmentUserName) { - args("--username", developmentEnvironmentUserName) +// Custom reobf auto-mappings +configurations.configureEach { + dependencies.configureEach { dep -> + if (dep instanceof org.gradle.api.artifacts.ExternalModuleDependency) { + if (dep.group == "net.industrial-craft" && dep.name == "industrialcraft-2") { + // https://www.curseforge.com/minecraft/mc-mods/industrial-craft/files/2353971 + project.dependencies.reobfJarConfiguration("curse.maven:ic2-242638:2353971") + } } } +} - serverIntellijRun { - args(arguments) - jvmArgs(jvmArguments) +// Ensure tests have access to minecraft classes +sourceSets { + test { + java { + compileClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output + runtimeClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output + } } } @@ -312,23 +389,100 @@ if (file('addon.gradle').exists()) { apply from: 'addon.gradle' } +// Allow unsafe repos but warn +repositories.configureEach { repo -> + if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) { + if (repo.getUrl() != null && repo.getUrl().getScheme() == "http" && !repo.allowInsecureProtocol) { + logger.warn("Deprecated: Allowing insecure connections for repo '${repo.name}' - add 'allowInsecureProtocol = true'") + repo.allowInsecureProtocol = true + } + } +} + apply from: 'repositories.gradle' configurations { - implementation.extendsFrom(shadowImplementation) // TODO: remove after all uses are refactored - implementation.extendsFrom(shadowCompile) - implementation.extendsFrom(shadeCompile) + for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { + config.extendsFrom(runtimeOnlyNonPublishable) + if (usesShadowedDependencies.toBoolean()) { + config.extendsFrom(shadowImplementation) + // TODO: remove Compile after all uses are refactored to Implementation + config.extendsFrom(shadeCompile) + config.extendsFrom(shadowCompile) + } + } + // A "bag-of-dependencies"-style configuration for backwards compatibility, gets put in "api" + create("compile") { + description = "Deprecated: use api or implementation instead, gets put in api" + canBeConsumed = false + canBeResolved = false + visible = false + } + create("testCompile") { + description = "Deprecated: use testImplementation instead" + canBeConsumed = false + canBeResolved = false + visible = false + } + api.extendsFrom(compile) + testImplementation.extendsFrom(testCompile) +} + +afterEvaluate { + if (!configurations.compile.allDependencies.empty || !configurations.testCompile.allDependencies.empty) { + logger.warn("This project uses deprecated `compile` dependencies, please migrate to using `api` and `implementation`") + logger.warn("For more details, see https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/dependencies.gradle") + } } repositories { maven { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' + mavenContent { + excludeGroup("net.minecraftforge") // missing the `universal` artefact + } + } + maven { + name = "GTNH Maven" + url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + allowInsecureProtocol = true } if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { + if (usesMixinDebug.toBoolean()) { + maven { + name = "Fabric Maven" + url = "https://maven.fabricmc.net/" + } + } + } + if (includeWellKnownRepositories.toBoolean()) { maven { - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + name "CurseMaven" + url "https://cursemaven.com" + content { + includeGroup "curse.maven" + } + } + maven { + name = "ic2" + url = "https://maven.ic2.player.to/" + metadataSources { + mavenPom() + artifact() + } + } + maven { + name = "ic2-mirror" + url = "https://maven2.ic2.player.to/" + metadataSources { + mavenPom() + artifact() + } + } + maven { + name "MMD Maven" + url "https://maven.mcmoddev.com/" } } } @@ -338,27 +492,34 @@ dependencies { 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.5-GTNH:processor') + annotationProcessor('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + if (usesMixinDebug.toBoolean()) { + runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16') + } } if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - compile('com.gtnewhorizon:gtnhmixins:2.0.2') + implementation('com.gtnewhorizon:gtnhmixins:2.1.10') } } 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 mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' +def refMap = "${mixinTmpDir}" + File.separator + mixingConfigRefMap +def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" + +tasks.register('generateAssets') { + group = "GTNH Buildscript" + description = "Generates a mixin config file at /src/main/resources/mixins.modid.json if needed" + onlyIf { usesMixins.toBoolean() } + doLast { def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json") if (!mixinConfigFile.exists()) { def mixinPluginLine = "" - if(!mixinPlugin.isEmpty()) { + if (!mixinPlugin.isEmpty()) { // We might not have a mixin plugin if we're using early/late mixins - mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ + mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ } mixinConfigFile.text = """{ @@ -377,119 +538,45 @@ task generateAssets { } } -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 +if (usesMixins.toBoolean()) { + tasks.named("reobfJar", ReobfuscatedJar).configure { + extraSrgFiles.from(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" - ] +if (usesMixins.toBoolean()) { + tasks.named("compileJava", JavaCompile).configure { + doFirst { + new File(mixinTmpDir).mkdirs() } - } -} - -runClient { - if (developmentEnvironmentUserName) { - arguments += [ - "--username", - developmentEnvironmentUserName + options.compilerArgs += [ + "-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}", + "-AoutSrgFile=${mixinSrg}", + "-AoutRefMapFile=${refMap}", + // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code + "-XDenableSunApiLintControl", + "-XDignore.symbol.file" ] } - - args(arguments) - jvmArgs(jvmArguments) -} - -runServer { - args(arguments) - jvmArgs(jvmArguments) } -tasks.withType(JavaExec).configureEach { - javaLauncher.set( - javaToolchains.launcherFor { - languageVersion = projectJavaVersion - } - ) -} - -processResources { +tasks.named("processResources", ProcessResources).configure { // this will ensure that this task is redone when the versions change. inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version + inputs.property "mcversion", project.minecraft.mcVersion exclude("spotless.gradle") - // 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 + // replace stuff in mcmod.info, nothing else. replaces ${key} with value in text + filesMatching("mcmod.info") { + expand "minecraftVersion": project.minecraft.mcVersion, + "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' - exclude 'spotless.gradle' - } } def getManifestAttributes() { @@ -516,65 +603,68 @@ def getManifestAttributes() { 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") - +tasks.named("jar", Jar).configure { 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 -} +if (usesShadowedDependencies.toBoolean()) { + tasks.register('relocateShadowJar', ConfigureShadowRelocation) { + target = tasks.shadowJar + prefix = modGroup + ".shadow" + } + tasks.named("shadowJar", ShadowJar).configure { + manifest { + attributes(getManifestAttributes()) + } -task devJar(type: Jar) { - project.configurations.shadeCompile.each { dep -> - from(project.zipTree(dep)) { - exclude 'META-INF', 'META-INF/**' + if (minimizeShadowedDependencies.toBoolean()) { + minimize() // This will only allow shading for actually used classes } + configurations = [ + project.configurations.shadowImplementation, + project.configurations.shadowCompile, + project.configurations.shadeCompile + ] + archiveClassifier.set('dev') + dependsOn(relocateShadowJar) + } + configurations.runtimeElements.outgoing.artifacts.clear() + configurations.apiElements.outgoing.artifacts.clear() + configurations.runtimeElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) + configurations.apiElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) + tasks.named("jar", Jar) { + enabled = false + finalizedBy(tasks.shadowJar) } - - from sourceSets.main.output - getArchiveClassifier().set("dev") - - manifest { - attributes(getManifestAttributes()) + tasks.named("reobfJar", ReobfuscatedJar) { + inputJar.set(tasks.named("shadowJar", ShadowJar).flatMap({it.archiveFile})) + } + AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.findByName("java") + javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { + skip() + } + for (runTask in ["runClient", "runServer"]) { + tasks.named(runTask).configure { + dependsOn("shadowJar") + } } +} +ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar +ext.publishableObfJar = tasks.reobfJar - if (usesShadowedDependencies.toBoolean()) { - dependsOn(circularResolverJar) - enabled = false +tasks.named('extractForgeUserdev', Copy).configure { efu -> + doLast { + // Fix CoFH-repackaged CCL not finding mappings + project.copy { + from(mcpTasks.userdevDir("conf")) + into(new File(project.buildDir, "unpacked/conf")) + } } } -task apiJar(type: Jar) { +tasks.register('apiJar', Jar) { from(sourceSets.main.allSource) { include modGroupPath + "/" + apiPackagePath + '/**' } @@ -592,18 +682,78 @@ task apiJar(type: Jar) { artifacts { if (!noPublishedSources) { - archives sourcesJar + archives tasks.named("sourcesJar") } - archives devJar if (apiPackage) { - archives apiJar + archives tasks.named("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 +idea { + module { + downloadJavadoc = true + downloadSources = true + } + project { + settings { + runConfigurations { + "1. Run Client"(Gradle) { + taskNames = ["runClient"] + } + "2. Run Server"(Gradle) { + taskNames = ["runServer"] + } + "3. Run Obfuscated Client"(Gradle) { + taskNames = ["runObfClient"] + } + "4. Run Obfuscated Server"(Gradle) { + taskNames = ["runObfServer"] + } + if (!disableSpotless) { + "5. Apply spotless"(Gradle) { + taskNames = ["spotlessApply"] + } + } + def coreModArgs = "" + if (coreModClass) { + coreModArgs = ' "-Dfml.coreMods.load=' + modGroup + '.' + coreModClass + '"' + } + "Run Client (IJ Native)"(Application) { + mainClass = "GradleStart" + moduleName = project.name + ".main" + afterEvaluate { + workingDirectory = tasks.runClient.workingDir.absolutePath + programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ') + jvmArgs = tasks.runClient.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + + ' ' + tasks.runClient.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + + coreModArgs + } + } + "Run Server (IJ Native)"(Application) { + mainClass = "GradleStartServer" + moduleName = project.name + ".main" + afterEvaluate { + workingDirectory = tasks.runServer.workingDir.absolutePath + programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ') + jvmArgs = tasks.runServer.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + + ' ' + tasks.runServer.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + + coreModArgs + } + } + } + compiler.javac { + afterEvaluate { + moduleJavacAdditionalOptions = [ + (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') + ] + } + } + } + } +} + +tasks.named("processIdeaSettings").configure { + dependsOn("injectTags") } // workaround variable hiding in pom processing @@ -611,51 +761,24 @@ def projectConfigs = project.configurations publishing { publications { - maven(MavenPublication) { + create("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" + artifact apiJar } 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 } - 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" + allowInsecureProtocol = true credentials { username = System.getenv("MAVEN_USER") ?: "NONE" password = System.getenv("MAVEN_PASSWORD") ?: "NONE" @@ -675,7 +798,7 @@ if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { versionNumber = identifiedVersion versionType = identifiedVersion.endsWith("-pre") ? "beta" : "release" changelog = changelogFile.exists() ? changelogFile.getText("UTF-8") : "" - uploadFile = jar + uploadFile = publishableObfJar additionalFiles = getSecondaryArtifacts() gameVersions = [minecraftVersion] loaders = ["forge"] @@ -694,7 +817,7 @@ if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { } } if (usesMixins.toBoolean()) { - addModrinthDep("required", "version", "gtnhmixins") + addModrinthDep("required", "project", "gtnhmixins") } tasks.modrinth.dependsOn(build) tasks.publish.dependsOn(tasks.modrinth) @@ -716,7 +839,7 @@ if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null releaseType = identifiedVersion.endsWith("-pre") ? "beta" : "release" addGameVersion minecraftVersion addGameVersion "Forge" - mainArtifact jar + mainArtifact publishableObfJar for (artifact in getSecondaryArtifacts()) addArtifact artifact } @@ -744,14 +867,9 @@ if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null tasks.publish.dependsOn(tasks.curseforge) } -def addModrinthDep(scope, type, name) { +def addModrinthDep(String scope, String type, String name) { com.modrinth.minotaur.dependencies.Dependency dep; - if (!(scope in [ - "required", - "optional", - "incompatible", - "embedded" - ])) { + if (!(scope in ["required", "optional", "incompatible", "embedded"])) { throw new Exception("Invalid modrinth dependency scope: " + scope) } switch (type) { @@ -767,14 +885,8 @@ def addModrinthDep(scope, type, name) { project.modrinth.dependencies.add(dep) } -def addCurseForgeRelation(type, name) { - if (!(type in [ - "requiredDependency", - "embeddedLibrary", - "optionalDependency", - "tool", - "incompatible" - ])) { +def addCurseForgeRelation(String type, String name) { + if (!(type in ["requiredDependency", "embeddedLibrary", "optionalDependency", "tool", "incompatible"])) { throw new Exception("Invalid CurseForge relation type: " + type) } CurseArtifact artifact = project.curseforge.curseProjects[0].mainArtifact @@ -783,17 +895,20 @@ def addCurseForgeRelation(type, name) { } // Updating -task updateBuildScript { +tasks.register('updateBuildScript') { + group = 'GTNH Buildscript' + description = 'Updates the build script to the latest version' + doLast { - if (performBuildScriptUpdate(projectDir.toString())) return + if (performBuildScriptUpdate()) return - print("Build script already up-to-date!") + print("Build script already up-to-date!") } } -if (!project.getGradle().startParameter.isOffline() && isNewBuildScriptVersionAvailable(projectDir.toString())) { +if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_UPDATE_CHECK') && isNewBuildScriptVersionAvailable()) { if (autoUpdateBuildScript.toBoolean()) { - performBuildScriptUpdate(projectDir.toString()) + performBuildScriptUpdate() } else { out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") } @@ -836,10 +951,11 @@ boolean verifySettingsGradle() { return false } -boolean performBuildScriptUpdate(String projectDir) { - if (isNewBuildScriptVersionAvailable(projectDir)) { +boolean performBuildScriptUpdate() { + if (isNewBuildScriptVersionAvailable()) { def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } + def out = services.get(StyledTextOutputFactory).create('buildscript-update-output') out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!") boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated @@ -850,7 +966,7 @@ boolean performBuildScriptUpdate(String projectDir) { return false } -boolean isNewBuildScriptVersionAvailable(String projectDir) { +boolean isNewBuildScriptVersionAvailable() { Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] String currentBuildScript = getFile("build.gradle").getText() @@ -870,15 +986,12 @@ static String getVersionHash(String buildScriptContent) { return "" } -configure(updateBuildScript) { - group = 'forgegradle' - description = 'Updates the build script to the latest version' -} - // Parameter Deobfuscation -task deobfParams { - doLast { +tasks.register('deobfParams') { + group = 'GTNH Buildscript' + description = 'Rename all obfuscated parameter names inherited from Minecraft classes' + doLast { // TODO String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion" String mcpZIP = "$mcpDir/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip" @@ -892,7 +1005,10 @@ task deobfParams { if (!file(paramsCSV).exists()) { println("Extracting MCP archive ...") - unzip(mcpZIP, mcpDir) + copy { + from(zipTree(mcpZIP)) + into(mcpDir) + } } println("Parsing params.csv ...") @@ -905,210 +1021,192 @@ task deobfParams { } 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.") -} + 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 params) { -int fileCount = 0 + 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") + if (file.isDirectory()) { + for (File f : file.listFiles()) { + fileCount += replaceParams(f, params) } - } else { - // fix for Windows-created archives - File parent = newFile.parentFile - if (!parent.isDirectory() && !parent.mkdirs()) { - throw new IOException("Failed to create directory $parent") + 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) } - // write file content - FileOutputStream fos = new FileOutputStream(newFile) - int len = 0 - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len) + if (hash != content.hashCode()) { + Files.write(file.toPath(), content.getBytes("UTF-8")) + return 1 } - fos.close() + } catch (Exception e) { + e.printStackTrace() } - zipEntry = zis.getNextEntry() -} -zis.closeEntry() -zis.close() -} - -configure(deobfParams) { -group = 'forgegradle' -description = 'Rename all obfuscated parameter names inherited from Minecraft classes' + return 0 } // Dependency Deobfuscation def deobf(String sourceURL) { -try { - URL url = new URL(sourceURL) - String fileName = url.getFile() + 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(".")) + } - //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) - String hostName = url.getHost() - if (hostName.startsWith("www.")) { - hostName = hostName.substring(4) + return deobf(sourceURL, "$hostName/$fileName") + } catch (Exception ignored) { + return deobf(sourceURL, "deobf/${sourceURL.hashCode()}") } - 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()}") +def deobfMaven(String repoURL, String mavenDep) { + if (!repoURL.endsWith("/")) { + repoURL += "/" + } + String[] parts = mavenDep.split(":") + parts[0] = parts[0].replace('.', '/') + def jarURL = repoURL + parts[0] + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + ".jar" + return deobf(jarURL) } + +def deobfCurse(String curseDep) { + try { + return deobfMaven("https://www.cursemaven.com/", "curse.maven:$curseDep") + } catch (Exception ignored) { + out.style(Style.Failure).println("Failed to get $curseDep from cursemaven.") + } } // 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 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" -String mappingsVer -String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/' -if (remoteMappings) { - String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion" - String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip" + if (file(deobfFile).exists()) { + return files(deobfFile) + } - zipMappings(mappingsZIP, remoteMappings, bon2Dir) + String mappingsVer + String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/' + if (remoteMappings) { + String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion" + String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip" - mappingsVer = "snapshot_$id" -} else { - mappingsVer = "${channel}_$mappingsVersion" -} + zipMappings(mappingsZIP, remoteMappings, bon2Dir) -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 -} + mappingsVer = "snapshot_$id" + } else { + mappingsVer = "${channel}_$mappingsVersion" + } -download.run { - src sourceURL - dest obfFile - quiet true - overwrite false -} + 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 + } -exec { - commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', minecraftVersion, '--mappingsVer', mappingsVer, '--notch' - workingDir bon2Dir - standardOutput = new FileOutputStream("${deobfFile}.log") -} + 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) + return files(deobfFile) } def zipMappings(String zipPath, String url, String bon2Dir) { -File zipFile = new File(zipPath) -if (zipFile.exists()) { - return -} + File zipFile = new File(zipPath) + if (zipFile.exists()) { + return + } -String fieldsCache = "$bon2Dir/data/fields.csv" -String methodsCache = "$bon2Dir/data/methods.csv" + 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 -} + 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)) + 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("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.putNextEntry(new ZipEntry("methods.csv")) + Files.copy(Paths.get(methodsCache), zos) + zos.closeEntry() -zos.close() + 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") -} + 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 propertyDefaultIfUnset(String propertyName, defaultValue) { -if (!project.hasProperty(propertyName) || project.property(propertyName) == "") { - project.ext.setProperty(propertyName, defaultValue) -} + if (!project.hasProperty(propertyName) || project.property(propertyName) == "") { + project.ext.setProperty(propertyName, defaultValue) + } } def getFile(String relativePath) { -return new File(projectDir, relativePath) + return new File(projectDir, relativePath) } def getSecondaryArtifacts() { -// Because noPublishedSources from the beginning of the script is somehow not visible here... -boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false -def secondaryArtifacts = [devJar] -if (!noPublishedSources) secondaryArtifacts += [sourcesJar] -if (apiPackage) secondaryArtifacts += [apiJar] -return secondaryArtifacts + // Because noPublishedSources from the beginning of the script is somehow not visible here... + boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false + def secondaryArtifacts = [publishableDevJar] + if (!noPublishedSources) secondaryArtifacts += [sourcesJar] + if (apiPackage) secondaryArtifacts += [apiJar] + return secondaryArtifacts } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..ccebba7710deaf9f98673a68957ea02138b60d0a 100644 GIT binary patch delta 42198 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%0Dx9&DJ+=*NrOLFNd~jpXIl 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 OOi;9)pb#jaQ2zt%fx@f+ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3ab0b725..f398c33c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ 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-7.6-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 83f2acfd..79a61d42 100755 --- a/gradlew +++ b/gradlew @@ -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. @@ -17,78 +17,113 @@ # ############################################################################## -## -## 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/subprojects/plugins/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"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +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,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + 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. Please set the JAVA_HOME variable in your environment to match the @@ -105,84 +140,105 @@ location of your Java installation." 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 +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=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=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac 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 +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "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 +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - 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\"" + 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 - i=$((i+1)) + # 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 - 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" ;; - 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; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +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 -# 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" +# 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. +# -# 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")" -fi +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 9618d8d9..93e3f59f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,10 +25,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,7 +41,7 @@ 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. @@ -51,7 +55,7 @@ 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% @@ -61,38 +65,26 @@ echo location of your Java installation. 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 diff --git a/settings.gradle b/settings.gradle index 97d8f71c..01ea5f12 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,10 +1,28 @@ + +pluginManagement { + repositories { + maven { + // RetroFuturaGradle + name "GTNH Maven" + url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" + allowInsecureProtocol = true + mavenContent { + includeGroup("com.gtnewhorizons.retrofuturagradle") + } + } + gradlePluginPortal() + mavenCentral() + mavenLocal() + } +} + plugins { id 'com.diffplug.blowdryerSetup' version '1.6.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' // Provides java toolchains } -apply plugin: 'com.diffplug.blowdryerSetup' - blowdryerSetup { - github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.1.4') + repoSubfolder 'gtnhShared' + github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.2.0') //devLocal '.' // Use this when testing config updates locally } From 9d48150e57e46c8df16822acee58f6f36dcdc91a Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Sun, 29 Jan 2023 10:49:16 -0800 Subject: [PATCH 018/132] [ci skip] spotlessApply with the new settings --- .../sinthoras/visualprospecting/Config.java | 2 + .../visualprospecting/ServerTranslations.java | 16 +-- .../sinthoras/visualprospecting/Utils.java | 20 ++- .../com/sinthoras/visualprospecting/VP.java | 5 +- .../sinthoras/visualprospecting/VPMod.java | 1 + .../VisualProspecting_API.java | 56 ++++---- .../database/ClientCache.java | 38 ++++-- .../database/DimensionCache.java | 30 ++-- .../database/RedoServerCacheCommand.java | 15 +- .../database/ResetClientCacheCommand.java | 4 +- .../database/ServerCache.java | 53 +++---- .../database/TransferCache.java | 28 ++-- .../database/UndergroundFluidPosition.java | 13 +- .../database/WorldCache.java | 17 ++- .../database/WorldIdHandler.java | 4 +- .../cachebuilder/AnalysisProgressTracker.java | 20 ++- .../database/cachebuilder/ChunkAnalysis.java | 5 +- .../cachebuilder/DetailedChunkAnalysis.java | 109 ++++++++------- .../cachebuilder/DimensionAnalysis.java | 47 ++++--- .../database/cachebuilder/GregTechOre.java | 3 +- .../database/cachebuilder/WorldAnalysis.java | 7 +- .../BartworksOreMaterialProvider.java | 4 +- .../GregTechOreMaterialProvider.java | 3 +- .../veintypes/IOreMaterialProvider.java | 3 +- .../database/veintypes/VeinType.java | 42 +++--- .../database/veintypes/VeinTypeCaching.java | 75 +++++----- .../visualprospecting/hooks/HooksClient.java | 15 +- .../hooks/HooksEventBus.java | 9 +- .../visualprospecting/hooks/HooksFML.java | 1 + .../visualprospecting/hooks/HooksShared.java | 58 +++++--- .../integration/DrawUtils.java | 32 +++-- .../gregtech/UndergroundFluidsWrapper.java | 24 ++-- .../journeymap/JourneyMapState.java | 8 +- .../integration/journeymap/Reflection.java | 4 +- .../ResetClientCacheConfirmation.java | 9 +- .../journeymap/buttons/LayerButton.java | 3 +- .../drawsteps/ClickableDrawStep.java | 5 +- .../drawsteps/DirtyChunkDrawStep.java | 45 +++--- .../journeymap/drawsteps/OreVeinDrawStep.java | 50 ++++--- .../drawsteps/ThaumcraftNodeDrawStep.java | 86 ++++++++---- .../UndergroundFluidChunkDrawStep.java | 27 ++-- .../drawsteps/UndergroundFluidDrawStep.java | 28 ++-- .../journeymap/render/DirtyChunkRenderer.java | 11 +- .../journeymap/render/LayerRenderer.java | 8 +- .../journeymap/render/OreVeinRenderer.java | 8 +- .../render/ThaumcraftNodeRenderer.java | 8 +- .../render/UndergroundFluidChunkRenderer.java | 11 +- .../render/UndergroundFluidRenderer.java | 11 +- .../render/WaypointProviderLayerRenderer.java | 15 +- .../journeymap/waypoints/WaypointManager.java | 6 +- .../integration/model/MapState.java | 6 +- .../model/buttons/ButtonManager.java | 11 +- .../model/layers/DirtyChunkLayerManager.java | 14 +- .../model/layers/LayerManager.java | 13 +- .../model/layers/LayerRenderer.java | 3 +- .../model/layers/OreVeinLayerManager.java | 24 ++-- .../layers/ThaumcraftNodeLayerManager.java | 18 +-- .../UndergroundFluidChunkLayerManager.java | 78 +++++------ .../layers/UndergroundFluidLayerManager.java | 61 ++++----- .../model/layers/WaypointProviderManager.java | 13 +- .../model/locations/OreVeinLocation.java | 18 +-- .../locations/ThaumcraftNodeLocation.java | 22 +-- .../UndergroundFluidChunkLocation.java | 13 +- .../locations/UndergroundFluidLocation.java | 3 +- .../integration/model/waypoints/Waypoint.java | 1 + .../voxelmap/IWaypointManagerReflection.java | 3 +- .../voxelmap/VoxelMapEventHandler.java | 63 +++++---- .../xaerominimap/XaeroMiniMapState.java | 5 +- .../waypoints/WaypointManager.java | 13 +- .../xaeroworldmap/XaeroWorldMapState.java | 6 +- .../xaeroworldmap/buttons/LayerButton.java | 3 +- .../buttons/SizedGuiTexturedButton.java | 7 +- .../renderers/InteractableLayerRenderer.java | 7 +- .../renderers/LayerRenderer.java | 9 +- .../renderers/OreVeinRenderer.java | 9 +- .../renderers/ThaumcraftNodeRenderer.java | 9 +- .../UndergroundFluidChunkRenderer.java | 9 +- .../renderers/UndergroundFluidRenderer.java | 9 +- .../rendersteps/InteractableRenderStep.java | 3 +- .../rendersteps/OreVeinRenderStep.java | 79 ++++++++--- .../xaeroworldmap/rendersteps/RenderStep.java | 2 + .../rendersteps/ThaumcraftNodeRenderStep.java | 54 +++++--- .../UndergroundFluidChunkRenderStep.java | 12 +- .../UndergroundFluidRenderStep.java | 13 +- .../item/ProspectorsLog.java | 40 +++--- .../visualprospecting/mixinplugin/Mixin.java | 9 +- .../mixinplugin/MixinPlugin.java | 12 +- .../mixinplugin/TargetedMod.java | 11 +- .../bartworks/WorldGenContainerMixin.java | 40 +++--- .../GT_Worldgenerator_SpaceMixin.java | 41 +++--- .../gregtech/GT_Block_Ores_AbstractMixin.java | 21 ++- ...aTileEntity_AdvSeismicProspectorMixin.java | 129 +++++++++--------- .../GT_MetaTileEntity_ScannerMixin.java | 97 +++++++------ .../gregtech/WorldGenContainerMixin.java | 33 ++--- .../journeymap/FullscreenActionsMixin.java | 5 +- .../mixins/journeymap/FullscreenMixin.java | 70 +++++----- .../mixins/journeymap/MiniMapMixin.java | 12 +- .../journeymap/RenderWaypointBeaconMixin.java | 15 +- .../journeymap/WaypointManagerMixin.java | 8 +- .../minecraft/ForgeHooksClientMixin.java | 1 + .../minecraft/ItemEditableBookMixin.java | 37 ++--- .../mixins/tcnodetracker/GuiMainMixin.java | 64 ++++----- .../xaerosminimap/MinimapRendererMixin.java | 119 +++++----------- .../WaypointsIngameRendererMixin.java | 28 ++-- .../mixins/xaerosworldmap/GuiMapMixin.java | 70 +++++----- .../network/ProspectingNotification.java | 13 +- .../network/ProspectingRequest.java | 32 +++-- .../network/ProspectionSharing.java | 33 +++-- .../network/WorldIdNotification.java | 1 + .../visualprospecting/task/ITask.java | 3 +- .../task/SnapshotDownloadTask.java | 15 +- .../task/SnapshotUploadTask.java | 3 +- 112 files changed, 1453 insertions(+), 1224 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index 3eaf9475..741d14e8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -1,6 +1,7 @@ package com.sinthoras.visualprospecting; import java.io.File; + import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; @@ -22,6 +23,7 @@ private static class Defaults { } private static class Categories { + public static final String general = "general"; public static final String network = "network"; public static final String integration = "integration"; diff --git a/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java b/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java index a13192d9..4021cbec 100644 --- a/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java +++ b/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java @@ -1,10 +1,11 @@ package com.sinthoras.visualprospecting; -import com.sinthoras.visualprospecting.database.veintypes.VeinType; import net.minecraft.client.resources.I18n; import net.minecraft.server.MinecraftServer; import net.minecraftforge.fluids.Fluid; +import com.sinthoras.visualprospecting.database.veintypes.VeinType; + // Backup translations for server side lookups only public class ServerTranslations { @@ -82,16 +83,9 @@ public static String getEnglishLocalization(Fluid fluid) { } /* - Copy the relevant content into a file 'data.dat' and run the following python script to generate the switch-case: - - with open("data.dat") as f: - lines = f.readlines() - for line in lines: - if line is not "\n": - key, value = line.split("=") - value = value[:-1] - print("case \"" + key + "\":") - print(" return \"" + value + "\";") + * Copy the relevant content into a file 'data.dat' and run the following python script to generate the switch-case: + * with open("data.dat") as f: lines = f.readlines() for line in lines: if line is not "\n": key, value = + * line.split("=") value = value[:-1] print("case \"" + key + "\":") print(" return \"" + value + "\";") */ public static String getEnglishLocalization(VeinType veinType) { if (MinecraftServer.getServer().isSinglePlayer()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 279da79a..b74ea182 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -1,9 +1,5 @@ package com.sinthoras.visualprospecting; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.sinthoras.visualprospecting.hooks.HooksClient; -import cpw.mods.fml.common.Loader; import java.io.*; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; @@ -15,9 +11,15 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; + import net.minecraft.client.Minecraft; import net.minecraft.launchwrapper.Launch; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.sinthoras.visualprospecting.hooks.HooksClient; +import cpw.mods.fml.common.Loader; + public class Utils { public static boolean isDevelopmentEnvironment() { @@ -113,9 +115,7 @@ public static File getSubDirectory(final String subdirectory) { public static void deleteDirectoryRecursively(final File targetDirectory) { try { - Files.walk(targetDirectory.toPath()) - .sorted(Comparator.reverseOrder()) - .map(Path::toFile) + Files.walk(targetDirectory.toPath()).sorted(Comparator.reverseOrder()).map(Path::toFile) .forEach(File::delete); } catch (IOException e) { e.printStackTrace(); @@ -193,11 +193,9 @@ public static void appendToFile(File file, ByteBuffer byteBuffer) { public static Map getDIMFiles(File directory) { try { - final List dimensionIds = Files.walk(directory.toPath(), 1) - .filter(Files::isRegularFile) + final List dimensionIds = Files.walk(directory.toPath(), 1).filter(Files::isRegularFile) .filter(path -> path.getFileName().toString().startsWith("DIM")) - .map(dimensionFolder -> Integer.parseInt( - dimensionFolder.getFileName().toString().substring(3))) + .map(dimensionFolder -> Integer.parseInt(dimensionFolder.getFileName().toString().substring(3))) .collect(Collectors.toList()); final Map dimensionFiles = new HashMap<>(); for (int dimensionId : dimensionIds) { diff --git a/src/main/java/com/sinthoras/visualprospecting/VP.java b/src/main/java/com/sinthoras/visualprospecting/VP.java index ad7d7eb6..1d4a738f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VP.java +++ b/src/main/java/com/sinthoras/visualprospecting/VP.java @@ -1,11 +1,14 @@ package com.sinthoras.visualprospecting; -import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; import java.util.Random; + import net.minecraft.client.settings.KeyBinding; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; + public class VP { public static SimpleNetworkWrapper network; diff --git a/src/main/java/com/sinthoras/visualprospecting/VPMod.java b/src/main/java/com/sinthoras/visualprospecting/VPMod.java index c6e992da..e2576ec2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VPMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/VPMod.java @@ -1,6 +1,7 @@ package com.sinthoras.visualprospecting; import com.sinthoras.visualprospecting.hooks.HooksShared; + import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.SidedProxy; import cpw.mods.fml.common.event.*; diff --git a/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java b/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java index 205eb29e..caecef0f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java +++ b/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java @@ -3,6 +3,13 @@ import static com.sinthoras.visualprospecting.Utils.isJourneyMapInstalled; import static com.sinthoras.visualprospecting.Utils.isXaerosWorldMapInstalled; +import java.util.Collections; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.world.World; + import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; @@ -17,13 +24,9 @@ import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.xaeroworldmap.XaeroWorldMapState; import com.sinthoras.visualprospecting.network.ProspectingNotification; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import java.util.Collections; -import java.util.List; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.world.World; @SuppressWarnings("unused") public class VisualProspecting_API { @@ -100,24 +103,24 @@ public static void openJourneyMapForUndergroundFluidsAt(int blockX, int blockZ, } // This mechanic is limited to blocks the player can touch - public static void triggerProspectingForOreBlock( - EntityPlayer player, World world, int blockX, int blockY, int blockZ) { + public static void triggerProspectingForOreBlock(EntityPlayer player, World world, int blockX, int blockY, + int blockZ) { ClientCache.instance.onOreInteracted(world, blockX, blockY, blockZ, player); } public static OreVeinPosition getOreVein(int dimensionId, int blockX, int blockZ) { - return ClientCache.instance.getOreVein( - dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); + return ClientCache.instance + .getOreVein(dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); } public static UndergroundFluidPosition getUndergroundFluid(int dimensionId, int blockX, int blockZ) { - return ClientCache.instance.getUndergroundFluid( - dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); + return ClientCache.instance + .getUndergroundFluid(dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); } public static void setOreVeinDepleted(int dimensionId, int blockX, int blockZ) { - final OreVeinPosition oreVeinPosition = ClientCache.instance.getOreVein( - dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); + final OreVeinPosition oreVeinPosition = ClientCache.instance + .getOreVein(dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); if (oreVeinPosition.isDepleted() == false) { oreVeinPosition.toggleDepleted(); } @@ -125,14 +128,14 @@ public static void setOreVeinDepleted(int dimensionId, int blockX, int blockZ) { } public static void toggleOreVeinDepleted(OreVeinPosition oreVeinPosition) { - oreVeinPosition = ClientCache.instance.getOreVein( - oreVeinPosition.dimensionId, oreVeinPosition.chunkX, oreVeinPosition.chunkZ); + oreVeinPosition = ClientCache.instance + .getOreVein(oreVeinPosition.dimensionId, oreVeinPosition.chunkX, oreVeinPosition.chunkZ); oreVeinPosition.toggleDepleted(); ClientCache.instance.putOreVeins(Collections.singletonList(oreVeinPosition)); } - public static void putProspectionResults( - List oreVeins, List undergroundFluids) { + public static void putProspectionResults(List oreVeins, + List undergroundFluids) { ClientCache.instance.putOreVeins(oreVeins); ClientCache.instance.putUndergroundFluids(undergroundFluids); } @@ -142,21 +145,20 @@ public static class LogicalServer { public static OreVeinPosition getOreVein(int dimensionId, int blockX, int blockZ) { return ServerCache.instance.getOreVein( - dimensionId, Utils.mapToCenterOreChunkCoord(blockX), Utils.mapToCenterOreChunkCoord(blockZ)); + dimensionId, + Utils.mapToCenterOreChunkCoord(blockX), + Utils.mapToCenterOreChunkCoord(blockZ)); } public static UndergroundFluidPosition getUndergroundFluid(World world, int blockX, int blockZ) { - return prospectUndergroundFluidsWithingRadius(world, blockX, blockZ, 0) - .get(0); + return prospectUndergroundFluidsWithingRadius(world, blockX, blockZ, 0).get(0); } public static void notifyOreGeneration(int dimensionId, int blockX, int blockZ, final String oreVeinName) { ServerCache.instance.notifyOreVeinGeneration(dimensionId, blockX, blockZ, oreVeinName); } - public static void sendProspectionResultsToClient( - EntityPlayerMP player, - List oreVeins, + public static void sendProspectionResultsToClient(EntityPlayerMP player, List oreVeins, List undergroundFluids) { // Skip networking if in single player if (Utils.isLogicalClient()) { @@ -167,13 +169,13 @@ public static void sendProspectionResultsToClient( } } - public static List prospectOreVeinsWithinRadius( - int dimensionId, int blockX, int blockZ, int blockRadius) { + public static List prospectOreVeinsWithinRadius(int dimensionId, int blockX, int blockZ, + int blockRadius) { return ServerCache.instance.prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); } - public static List prospectUndergroundFluidsWithingRadius( - World world, int blockX, int blockZ, int blockRadius) { + public static List prospectUndergroundFluidsWithingRadius(World world, int blockX, + int blockZ, int blockRadius) { return ServerCache.instance.prospectUndergroundFluidBlockRadius(world, blockX, blockZ, blockRadius); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index 7f94d1dd..0a55e033 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -1,12 +1,9 @@ package com.sinthoras.visualprospecting.database; -import com.sinthoras.visualprospecting.*; -import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; -import com.sinthoras.visualprospecting.network.ProspectingRequest; -import gregtech.common.blocks.GT_TileEntity_Ores; import java.io.File; import java.util.ArrayList; import java.util.List; + import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.client.resources.I18n; @@ -18,6 +15,11 @@ import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; +import com.sinthoras.visualprospecting.*; +import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; +import com.sinthoras.visualprospecting.network.ProspectingRequest; +import gregtech.common.blocks.GT_TileEntity_Ores; + public class ClientCache extends WorldCache { public static final ClientCache instance = new ClientCache(); @@ -32,14 +34,17 @@ protected File getStorageDirectory() { private void notifyNewOreVein(OreVeinPosition oreVeinPosition) { final String location = "(" + (oreVeinPosition.getBlockX() + 8) + "," + (oreVeinPosition.getBlockZ() + 8) + ")"; final IChatComponent veinNotification = new ChatComponentTranslation( - "visualprospecting.vein.prospected", I18n.format(oreVeinPosition.veinType.name), location); + "visualprospecting.vein.prospected", + I18n.format(oreVeinPosition.veinType.name), + location); veinNotification.getChatStyle().setItalic(true); veinNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(veinNotification); final String oreNames = String.join(", ", oreVeinPosition.veinType.getOreMaterialNames()); - final IChatComponent oresNotification = - new ChatComponentTranslation("visualprospecting.vein.contents", oreNames); + final IChatComponent oresNotification = new ChatComponentTranslation( + "visualprospecting.vein.contents", + oreNames); oresNotification.getChatStyle().setItalic(true); oresNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(oresNotification); @@ -61,8 +66,9 @@ public void putOreVeins(List oreVeinPositions) { } } if (newOreVeins > 0) { - final IChatComponent oreVeinNotification = - new ChatComponentTranslation("visualprospecting.veins.prospected", newOreVeins); + final IChatComponent oreVeinNotification = new ChatComponentTranslation( + "visualprospecting.veins.prospected", + newOreVeins); oreVeinNotification.getChatStyle().setItalic(true); oreVeinNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(oreVeinNotification); @@ -80,12 +86,12 @@ public void putUndergroundFluids(List undergroundFluid for (UndergroundFluidPosition undergroundFluidPosition : undergroundFluids) { DimensionCache.UpdateResult updateResult = putUndergroundFluids(undergroundFluidPosition); if (updateResult == DimensionCache.UpdateResult.New) { - MinecraftForge.EVENT_BUS.post( - new ProspectingNotificationEvent.UndergroundFluid(undergroundFluidPosition)); + MinecraftForge.EVENT_BUS + .post(new ProspectingNotificationEvent.UndergroundFluid(undergroundFluidPosition)); newUndergroundFluids++; } else if (updateResult == DimensionCache.UpdateResult.Updated) { - MinecraftForge.EVENT_BUS.post( - new ProspectingNotificationEvent.UndergroundFluid(undergroundFluidPosition)); + MinecraftForge.EVENT_BUS + .post(new ProspectingNotificationEvent.UndergroundFluid(undergroundFluidPosition)); updatedUndergroundFluids++; } } @@ -100,14 +106,16 @@ public void putUndergroundFluids(List undergroundFluid } else { if (newUndergroundFluids > 0) { final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation( - "visualprospecting.undergroundfluid.prospected.onlynew", newUndergroundFluids); + "visualprospecting.undergroundfluid.prospected.onlynew", + newUndergroundFluids); undergroundFluidsNotification.getChatStyle().setItalic(true); undergroundFluidsNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); } if (updatedUndergroundFluids > 0) { final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation( - "visualprospecting.undergroundfluid.prospected.onlyupdated", updatedUndergroundFluids); + "visualprospecting.undergroundfluid.prospected.onlyupdated", + updatedUndergroundFluids); undergroundFluidsNotification.getChatStyle().setItalic(true); undergroundFluidsNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index 96cadb29..9b64c7bc 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -1,19 +1,21 @@ package com.sinthoras.visualprospecting.database; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.veintypes.VeinType; -import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.*; + import net.minecraft.world.ChunkCoordIntPair; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.veintypes.VeinType; +import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; + public class DimensionCache { public enum UpdateResult { @@ -34,8 +36,8 @@ public DimensionCache(int dimensionId) { public ByteBuffer saveOreChunks() { if (changedOrNewOreChunks.isEmpty() == false) { - final ByteBuffer byteBuffer = - ByteBuffer.allocate(changedOrNewOreChunks.size() * (2 * Integer.BYTES + Short.BYTES)); + final ByteBuffer byteBuffer = ByteBuffer + .allocate(changedOrNewOreChunks.size() * (2 * Integer.BYTES + Short.BYTES)); changedOrNewOreChunks.stream().map(oreChunks::get).forEach(oreVeinPosition -> { byteBuffer.putInt(oreVeinPosition.chunkX); byteBuffer.putInt(oreVeinPosition.chunkZ); @@ -54,18 +56,16 @@ public ByteBuffer saveOreChunks() { public ByteBuffer saveUndergroundFluids() { if (!changedOrNewUndergroundFluids.isEmpty()) { - final int initialCapacity = changedOrNewUndergroundFluids.size() - * (Long.BYTES - + Integer.BYTES * (8 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ)); + final int initialCapacity = changedOrNewUndergroundFluids.size() * (Long.BYTES + + Integer.BYTES * (8 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ)); try (final ByteArrayOutputStream baos = new ByteArrayOutputStream(initialCapacity); final DataOutputStream dos = new DataOutputStream(baos)) { for (ChunkCoordIntPair changedOrNewUndergroundFluid : changedOrNewUndergroundFluids) { - UndergroundFluidPosition undergroundFluidPosition = - undergroundFluids.get(changedOrNewUndergroundFluid); + UndergroundFluidPosition undergroundFluidPosition = undergroundFluids + .get(changedOrNewUndergroundFluid); dos.writeInt(undergroundFluidPosition.chunkX); dos.writeInt(undergroundFluidPosition.chunkZ); - byte[] fluidNameBytes = - undergroundFluidPosition.fluid.getName().getBytes(StandardCharsets.UTF_8); + byte[] fluidNameBytes = undergroundFluidPosition.fluid.getName().getBytes(StandardCharsets.UTF_8); // Negative to keep backwards compat with int fluidID written here before. dos.writeInt(-fluidNameBytes.length); dos.write(fluidNameBytes); @@ -182,8 +182,8 @@ public UpdateResult putUndergroundFluid(final UndergroundFluidPosition undergrou public UndergroundFluidPosition getUndergroundFluid(int chunkX, int chunkZ) { final ChunkCoordIntPair key = getUndergroundFluidKey(chunkX, chunkZ); - return undergroundFluids.getOrDefault( - key, UndergroundFluidPosition.getNotProspected(dimensionId, chunkX, chunkZ)); + return undergroundFluids + .getOrDefault(key, UndergroundFluidPosition.getNotProspected(dimensionId, chunkX, chunkZ)); } public Collection getAllOreVeins() { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java index 57d3493d..ec84675f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java @@ -1,11 +1,9 @@ package com.sinthoras.visualprospecting.database; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; -import cpw.mods.fml.server.FMLServerHandler; import java.io.IOException; import java.util.Objects; import java.util.zip.DataFormatException; + import net.minecraft.command.CommandBase; import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayerMP; @@ -14,6 +12,10 @@ import net.minecraft.util.IChatComponent; import net.minecraft.util.StatCollector; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; +import cpw.mods.fml.server.FMLServerHandler; + public class RedoServerCacheCommand extends CommandBase { @Override @@ -43,8 +45,7 @@ public void processCommand(ICommandSender sender, String[] parameters) { start.getChatStyle().setItalic(true); sender.addChatMessage(start); try { - WorldAnalysis world = - new WorldAnalysis(server.getEntityWorld().getSaveHandler().getWorldDirectory()); + WorldAnalysis world = new WorldAnalysis(server.getEntityWorld().getSaveHandler().getWorldDirectory()); world.cacheVeins(); } catch (IOException | DataFormatException e) { VP.info("Could not load world save files to build vein cache!"); @@ -53,8 +54,8 @@ public void processCommand(ICommandSender sender, String[] parameters) { failure.getChatStyle().setItalic(true); sender.addChatMessage(failure); } - final IChatComponent confirmation = - new ChatComponentTranslation("visualprospecting.redoservercache.confirmation"); + final IChatComponent confirmation = new ChatComponentTranslation( + "visualprospecting.redoservercache.confirmation"); confirmation.getChatStyle().setItalic(true); sender.addChatMessage(confirmation); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java index 49fa9ee2..8ce18847 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java @@ -21,8 +21,8 @@ public String getCommandUsage(ICommandSender sender) { @Override public void processCommand(ICommandSender sender, String[] parameters) { ClientCache.instance.resetPlayerProgression(); - final IChatComponent confirmation = - new ChatComponentTranslation("visualprospecting.resetprogress.confirmation"); + final IChatComponent confirmation = new ChatComponentTranslation( + "visualprospecting.resetprogress.confirmation"); confirmation.getChatStyle().setItalic(true); sender.addChatMessage(confirmation); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java index 7b011f7a..4979c2b7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java @@ -1,18 +1,20 @@ package com.sinthoras.visualprospecting.database; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.veintypes.VeinType; -import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; -import com.sinthoras.visualprospecting.integration.gregtech.UndergroundFluidsWrapper; import java.io.File; import java.util.ArrayList; import java.util.List; + import net.minecraft.world.World; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.veintypes.VeinType; +import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import com.sinthoras.visualprospecting.integration.gregtech.UndergroundFluidsWrapper; + public class ServerCache extends WorldCache { public static final ServerCache instance = new ServerCache(); @@ -31,8 +33,8 @@ public void notifyOreVeinGeneration(int dimensionId, int chunkX, int chunkZ, fin notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, VeinTypeCaching.getVeinType(veinName)); } - public List prospectOreChunks( - int dimensionId, int minChunkX, int minChunkZ, int maxChunkX, int maxChunkZ) { + public List prospectOreChunks(int dimensionId, int minChunkX, int minChunkZ, int maxChunkX, + int maxChunkZ) { minChunkX = Utils.mapToCenterOreChunkCoord(minChunkX); minChunkZ = Utils.mapToCenterOreChunkCoord(minChunkZ); maxChunkX = Utils.mapToCenterOreChunkCoord(maxChunkX); @@ -50,8 +52,8 @@ public List prospectOreChunks( return oreVeinPositions; } - public List prospectOreBlocks( - int dimensionId, int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + public List prospectOreBlocks(int dimensionId, int minBlockX, int minBlockZ, int maxBlockX, + int maxBlockZ) { return prospectOreChunks( dimensionId, Utils.coordBlockToChunk(minBlockX), @@ -62,23 +64,26 @@ public List prospectOreBlocks( public List prospectOreBlockRadius(int dimensionId, int blockX, int blockZ, int blockRadius) { return prospectOreBlocks( - dimensionId, blockX - blockRadius, blockZ - blockRadius, blockX + blockRadius, blockZ + blockRadius); + dimensionId, + blockX - blockRadius, + blockZ - blockRadius, + blockX + blockRadius, + blockZ + blockRadius); } - public List prospectUndergroundFluidBlockRadius( - World world, int blockX, int blockZ, int undergroundFluidBlockRadius) { - final int minChunkX = Utils.mapToCornerUndergroundFluidChunkCoord( - Utils.coordBlockToChunk(blockX - undergroundFluidBlockRadius)); - final int minChunkZ = Utils.mapToCornerUndergroundFluidChunkCoord( - Utils.coordBlockToChunk(blockZ - undergroundFluidBlockRadius)); + public List prospectUndergroundFluidBlockRadius(World world, int blockX, int blockZ, + int undergroundFluidBlockRadius) { + final int minChunkX = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(blockX - undergroundFluidBlockRadius)); + final int minChunkZ = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(blockZ - undergroundFluidBlockRadius)); // Equals to ceil(undergroundFluidBlockRadius / (VP.undergroundFluidFieldSizeChunkX * VP.chunkWidth)) - final int undergroundFluidRadius = - (undergroundFluidBlockRadius + VP.undergroundFluidSizeChunkX * VP.chunkWidth - 1) - / (VP.undergroundFluidSizeChunkX * VP.chunkWidth); + final int undergroundFluidRadius = (undergroundFluidBlockRadius + VP.undergroundFluidSizeChunkX * VP.chunkWidth + - 1) / (VP.undergroundFluidSizeChunkX * VP.chunkWidth); - List foundUndergroundFluids = - new ArrayList<>((2 * undergroundFluidRadius + 1) * (2 * undergroundFluidRadius + 1)); + List foundUndergroundFluids = new ArrayList<>( + (2 * undergroundFluidRadius + 1) * (2 * undergroundFluidRadius + 1)); for (int undergroundFluidX = 0; undergroundFluidX < 2 * undergroundFluidRadius + 1; undergroundFluidX++) { for (int undergroundFluidZ = 0; undergroundFluidZ < 2 * undergroundFluidRadius + 1; undergroundFluidZ++) { @@ -88,8 +93,8 @@ public List prospectUndergroundFluidBlockRadius( Fluid fluid = null; for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - final FluidStack prospectedFluid = UndergroundFluidsWrapper.prospectFluid( - world, chunkX + offsetChunkX, chunkZ + offsetChunkZ); + final FluidStack prospectedFluid = UndergroundFluidsWrapper + .prospectFluid(world, chunkX + offsetChunkX, chunkZ + offsetChunkZ); if (prospectedFluid != null) { fluid = prospectedFluid.getFluid(); chunks[offsetChunkX][offsetChunkZ] = prospectedFluid.amount; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java b/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java index 92eeced1..5e488d0d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java @@ -1,8 +1,9 @@ package com.sinthoras.visualprospecting.database; -import com.sinthoras.visualprospecting.Config; import java.util.*; +import com.sinthoras.visualprospecting.Config; + public class TransferCache { public static final TransferCache instance = new TransferCache(); @@ -11,16 +12,17 @@ public class TransferCache { private final Map> sharedUndergroundFluids = new HashMap<>(); private final Queue timestamp = new LinkedList<>(); - public void addClientProspectionData( - String uuid, List oreVeins, List undergroundFluids) { + public void addClientProspectionData(String uuid, List oreVeins, + List undergroundFluids) { sharedOreVeins.remove(uuid); sharedUndergroundFluids.remove(uuid); timestamp.remove(uuid); - final int oreVeinPositionSizeInRam = - OreVeinPosition.getMaxBytes() + 3 * Byte.BYTES; // JVM represents everything aligned at 4 bytes - final int newEntryBytes = - oreVeins.size() * oreVeinPositionSizeInRam + undergroundFluids.size() * UndergroundFluidPosition.BYTES; + final int oreVeinPositionSizeInRam = OreVeinPosition.getMaxBytes() + 3 * Byte.BYTES; // JVM represents + // everything aligned at 4 + // bytes + final int newEntryBytes = oreVeins.size() * oreVeinPositionSizeInRam + + undergroundFluids.size() * UndergroundFluidPosition.BYTES; while (getUsedMemory() > (Config.maxTransferCacheSizeMB << 20) - newEntryBytes && timestamp.isEmpty() == false) { @@ -47,13 +49,11 @@ public List getSharedUndergroundFluidsFrom(String uuid } private int getUsedMemory() { - final int oreVeinPositionSizeInRam = - OreVeinPosition.getMaxBytes() + 3 * Byte.BYTES; // JVM represents everything aligned at 4 bytes - return sharedOreVeins.values().stream() - .mapToInt(oreVeins -> oreVeins.size() * oreVeinPositionSizeInRam) - .sum() + final int oreVeinPositionSizeInRam = OreVeinPosition.getMaxBytes() + 3 * Byte.BYTES; // JVM represents + // everything aligned at 4 + // bytes + return sharedOreVeins.values().stream().mapToInt(oreVeins -> oreVeins.size() * oreVeinPositionSizeInRam).sum() + sharedUndergroundFluids.values().stream() - .mapToInt(undergroundFluids -> undergroundFluids.size() * UndergroundFluidPosition.BYTES) - .sum(); + .mapToInt(undergroundFluids -> undergroundFluids.size() * UndergroundFluidPosition.BYTES).sum(); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java b/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java index 4060c3f7..fc58a502 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java @@ -1,14 +1,16 @@ package com.sinthoras.visualprospecting.database; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.VP; import java.util.Arrays; + import net.minecraftforge.fluids.Fluid; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; + public class UndergroundFluidPosition { - public static final int BYTES = - (3 + 1 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ) * Integer.BYTES; + public static final int BYTES = (3 + 1 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ) + * Integer.BYTES; public final int dimensionId; public final int chunkX; @@ -65,8 +67,7 @@ public boolean isProspected() { } public boolean equals(UndergroundFluidPosition other) { - return dimensionId == other.dimensionId - && chunkX == other.chunkX + return dimensionId == other.dimensionId && chunkX == other.chunkX && chunkZ == other.chunkZ && fluid == other.fluid && Arrays.deepEquals(chunks, other.chunks); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index 7791cfea..95c16aaa 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -1,8 +1,5 @@ package com.sinthoras.visualprospecting.database; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.database.veintypes.VeinType; import java.io.File; import java.nio.ByteBuffer; import java.util.HashMap; @@ -10,6 +7,10 @@ import java.util.Map; import java.util.Set; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.database.veintypes.VeinType; + public abstract class WorldCache { protected final Map dimensions = new HashMap<>(); @@ -31,8 +32,8 @@ public boolean loadVeinCache(String worldId) { oreVeinCacheDirectory.mkdirs(); undergroundFluidCacheDirectory.mkdirs(); final Map oreVeinDimensionBuffers = Utils.getDIMFiles(oreVeinCacheDirectory); - final Map undergroundFluidDimensionBuffers = - Utils.getDIMFiles(undergroundFluidCacheDirectory); + final Map undergroundFluidDimensionBuffers = Utils + .getDIMFiles(undergroundFluidCacheDirectory); final Set dimensionsIds = new HashSet<>(); dimensionsIds.addAll(oreVeinDimensionBuffers.keySet()); dimensionsIds.addAll(undergroundFluidDimensionBuffers.keySet()); @@ -43,7 +44,8 @@ public boolean loadVeinCache(String worldId) { for (int dimensionId : dimensionsIds) { final DimensionCache dimension = new DimensionCache(dimensionId); dimension.loadCache( - oreVeinDimensionBuffers.get(dimensionId), undergroundFluidDimensionBuffers.get(dimensionId)); + oreVeinDimensionBuffers.get(dimensionId), + undergroundFluidDimensionBuffers.get(dimensionId)); dimensions.put(dimensionId, dimension); } return true; @@ -55,7 +57,8 @@ public void saveVeinCache() { final ByteBuffer oreVeinBuffer = dimension.saveOreChunks(); if (oreVeinBuffer != null) { Utils.appendToFile( - new File(oreVeinCacheDirectory.toPath() + "/DIM" + dimension.dimensionId), oreVeinBuffer); + new File(oreVeinCacheDirectory.toPath() + "/DIM" + dimension.dimensionId), + oreVeinBuffer); } final ByteBuffer undergroundFluidBuffer = dimension.saveUndergroundFluids(); if (undergroundFluidBuffer != null) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldIdHandler.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldIdHandler.java index d5b03a2a..b714070c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldIdHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldIdHandler.java @@ -1,11 +1,13 @@ package com.sinthoras.visualprospecting.database; -import com.sinthoras.visualprospecting.Tags; import java.util.UUID; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.WorldSavedData; import net.minecraft.world.WorldServer; +import com.sinthoras.visualprospecting.Tags; + public class WorldIdHandler extends WorldSavedData { private static WorldIdHandler instance; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java index 651e34ee..e1f06f9a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java @@ -1,12 +1,14 @@ package com.sinthoras.visualprospecting.database.cachebuilder; -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.VP; import java.io.File; import java.text.DecimalFormat; + import net.minecraft.server.MinecraftServer; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; + public class AnalysisProgressTracker { private static int numberOfDimensions = 0; @@ -59,9 +61,12 @@ private static synchronized void updateLog() { long timestamp = System.currentTimeMillis(); if (timestamp - (Config.cacheGenerationLogUpdateMinTime * 1000) > lastLogUpdate) { lastLogUpdate = timestamp; - final String message = "Caching GT ore generation meta data - Dimension (" - + (dimensionsProcessed + 1) + "/" + numberOfDimensions + ") " - + (numberOfRegionFiles == 0 ? 0 : ((regionFilesProcessed * 100) / numberOfRegionFiles)) + "%"; + final String message = "Caching GT ore generation meta data - Dimension (" + (dimensionsProcessed + 1) + + "/" + + numberOfDimensions + + ") " + + (numberOfRegionFiles == 0 ? 0 : ((regionFilesProcessed * 100) / numberOfRegionFiles)) + + "%"; VP.info(message); if (Utils.isLogicalClient()) { MinecraftServer.getServer().userMessage = message + "%"; // Escape % for String.format @@ -75,7 +80,8 @@ public static synchronized void processingFinished() { format.setMinimumFractionDigits(1); format.setMaximumFractionDigits(1); final String message = "Parsing complete! Thank you for your patience. - Duration: " - + format.format(elapsedTimeMS / 1000) + "sec"; + + format.format(elapsedTimeMS / 1000) + + "sec"; VP.info(message); if (Utils.isLogicalClient()) { MinecraftServer.getServer().userMessage = message; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java index a97d9494..e6e35e86 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java @@ -1,11 +1,12 @@ package com.sinthoras.visualprospecting.database.cachebuilder; +import java.util.HashSet; +import java.util.Set; + import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import io.xol.enklume.nbt.*; -import java.util.HashSet; -import java.util.Set; // A slim, but faster version to identify >90% of veins public class ChunkAnalysis { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index f20207fb..3a40c57e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -1,5 +1,8 @@ package com.sinthoras.visualprospecting.database.cachebuilder; +import java.util.*; +import java.util.stream.IntStream; + import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.OreVeinPosition; @@ -7,8 +10,6 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import io.xol.enklume.nbt.*; -import java.util.*; -import java.util.stream.IntStream; // Slower, but more sophisticated approach to identify overlapping veins public class DetailedChunkAnalysis { @@ -42,56 +43,62 @@ public void processMinecraftChunk(final NBTCompound chunkRoot) { public void cleanUpWithNeighbors(final Map veinChunkY) { final OreVeinPosition[] neighbors = new OreVeinPosition[] { - ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ + 3), - ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ + 3), - ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ + 3), - ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ), - ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ - 3), - ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ - 3), - ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ - 3), - ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ) - }; + ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ + 3), + ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ + 3), + ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ + 3), + ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ), + ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ - 3), + ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ - 3), + ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ - 3), + ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ) }; final int[] neighborVeinBlockY = new int[] { - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX - 3), Utils.mapToCenterOreChunkCoord(chunkZ + 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX), Utils.mapToCenterOreChunkCoord(chunkZ + 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX + 3), Utils.mapToCenterOreChunkCoord(chunkZ + 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX + 3), Utils.mapToCenterOreChunkCoord(chunkZ)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX + 3), Utils.mapToCenterOreChunkCoord(chunkZ - 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX), Utils.mapToCenterOreChunkCoord(chunkZ - 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX - 3), Utils.mapToCenterOreChunkCoord(chunkZ - 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX - 3), Utils.mapToCenterOreChunkCoord(chunkZ)), - 0) - }; + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX - 3), + Utils.mapToCenterOreChunkCoord(chunkZ + 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX), + Utils.mapToCenterOreChunkCoord(chunkZ + 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX + 3), + Utils.mapToCenterOreChunkCoord(chunkZ + 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX + 3), + Utils.mapToCenterOreChunkCoord(chunkZ)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX + 3), + Utils.mapToCenterOreChunkCoord(chunkZ - 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX), + Utils.mapToCenterOreChunkCoord(chunkZ - 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX - 3), + Utils.mapToCenterOreChunkCoord(chunkZ - 3)), + 0), + veinChunkY.getOrDefault( + Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(chunkX - 3), + Utils.mapToCenterOreChunkCoord(chunkZ)), + 0) }; // Remove all generated ores from neighbors. They could also be generated in the same chunk, // but that case is rare and therefore, neglected for (int neighborId = 0; neighborId < neighbors.length; neighborId++) { final OreVeinPosition neighbor = neighbors[neighborId]; - final boolean atCoordinateAxis = - Math.abs(neighbor.chunkX - chunkX) < 3 || Math.abs(neighbor.chunkZ - chunkZ) < 3; + final boolean atCoordinateAxis = Math.abs(neighbor.chunkX - chunkX) < 3 + || Math.abs(neighbor.chunkZ - chunkZ) < 3; final boolean canOverlap = atCoordinateAxis ? neighbor.veinType.canOverlapIntoNeighborOreChunkAtCoordinateAxis() : neighbor.veinType.canOverlapIntoNeighborOreChunk(); @@ -123,9 +130,7 @@ public VeinType getMatchedVein() { } final Optional dominantOre = allOres.entrySet().stream() - .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) - .map(Map.Entry::getKey) - .findFirst(); + .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(Map.Entry::getKey).findFirst(); if (dominantOre.isPresent()) { for (VeinType veinType : VeinTypeCaching.veinTypes) { if (veinType.matchesWithSpecificPrimaryOrSecondary(allOres.keySet(), dominantOre.get())) { @@ -137,9 +142,9 @@ public VeinType getMatchedVein() { if (matchedVeins.size() == 1) { return matchedVeins.stream().findAny().get(); } else if (matchedVeins.size() >= 2) { - matchedVeins.removeIf(veinType -> IntStream.range(veinType.minBlockY, veinType.maxBlockY) - .boxed() - .noneMatch(blockY -> isOreVeinGeneratedAtHeight(veinType, blockY))); + matchedVeins.removeIf( + veinType -> IntStream.range(veinType.minBlockY, veinType.maxBlockY).boxed() + .noneMatch(blockY -> isOreVeinGeneratedAtHeight(veinType, blockY))); if (matchedVeins.size() == 1) { return matchedVeins.stream().findAny().get(); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java index c182568c..52182062 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java @@ -1,20 +1,22 @@ package com.sinthoras.visualprospecting.database.cachebuilder; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Pattern; +import java.util.zip.DataFormatException; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.veintypes.VeinType; + import io.xol.enklume.MinecraftRegion; import io.xol.enklume.MinecraftWorld; import io.xol.enklume.nbt.NBTCompound; -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Pattern; -import java.util.zip.DataFormatException; public class DimensionAnalysis { @@ -25,14 +27,14 @@ public DimensionAnalysis(int dimensionId) { } private interface IChunkHandler { + void processChunk(NBTCompound root, int chunkX, int chunkZ); } public void processMinecraftWorld(MinecraftWorld world) throws IOException { final Map veinBlockY = new ConcurrentHashMap<>(); final List regionFiles = world.getAllRegionFiles(dimensionId); - final long dimensionSizeMB = - regionFiles.stream().mapToLong(File::length).sum() >> 20; + final long dimensionSizeMB = regionFiles.stream().mapToLong(File::length).sum() >> 20; if (dimensionSizeMB <= Config.maxDimensionSizeMBForFastScanning) { AnalysisProgressTracker.announceFastDimension(dimensionId); @@ -46,12 +48,14 @@ public void processMinecraftWorld(MinecraftWorld world) throws IOException { chunk.processMinecraftChunk(root); if (chunk.matchesSingleVein()) { - ServerCache.instance.notifyOreVeinGeneration( - dimensionId, chunkX, chunkZ, chunk.getMatchedVein()); + ServerCache.instance + .notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, chunk.getMatchedVein()); veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), chunk.getVeinBlockY()); } else { - final DetailedChunkAnalysis detailedChunk = - new DetailedChunkAnalysis(dimensionId, chunkX, chunkZ); + final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis( + dimensionId, + chunkX, + chunkZ); detailedChunk.processMinecraftChunk(root); chunksForSecondIdentificationPass.put(Utils.chunkCoordsToKey(chunkX, chunkZ), detailedChunk); } @@ -60,8 +64,8 @@ public void processMinecraftWorld(MinecraftWorld world) throws IOException { chunksForSecondIdentificationPass.values().parallelStream().forEach(chunk -> { chunk.cleanUpWithNeighbors(veinBlockY); - ServerCache.instance.notifyOreVeinGeneration( - dimensionId, chunk.chunkX, chunk.chunkZ, chunk.getMatchedVein()); + ServerCache.instance + .notifyOreVeinGeneration(dimensionId, chunk.chunkX, chunk.chunkZ, chunk.getMatchedVein()); }); } else { AnalysisProgressTracker.announceSlowDimension(dimensionId); @@ -73,8 +77,8 @@ public void processMinecraftWorld(MinecraftWorld world) throws IOException { chunk.processMinecraftChunk(root); if (chunk.matchesSingleVein()) { - ServerCache.instance.notifyOreVeinGeneration( - dimensionId, chunkX, chunkZ, chunk.getMatchedVein()); + ServerCache.instance + .notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, chunk.getMatchedVein()); veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), chunk.getVeinBlockY()); } }); @@ -83,8 +87,10 @@ public void processMinecraftWorld(MinecraftWorld world) throws IOException { regionFiles.parallelStream().forEach(regionFile -> { executeForEachGeneratedOreChunk(regionFile, (root, chunkX, chunkZ) -> { if (ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ).veinType == VeinType.NO_VEIN) { - final DetailedChunkAnalysis detailedChunk = - new DetailedChunkAnalysis(dimensionId, chunkX, chunkZ); + final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis( + dimensionId, + chunkX, + chunkZ); detailedChunk.processMinecraftChunk(root); detailedChunk.cleanUpWithNeighbors(veinBlockY); ServerCache.instance.notifyOreVeinGeneration( @@ -117,8 +123,7 @@ private void executeForEachGeneratedOreChunk(File regionFile, IChunkHandler chun if (chunkX == Utils.mapToCenterOreChunkCoord(chunkX) && chunkZ == Utils.mapToCenterOreChunkCoord(chunkZ)) { // Helpful read about 'root' structure: https://minecraft.fandom.com/wiki/Chunk_format - final NBTCompound root = - region.getChunk(localChunkX, localChunkZ).getRootTag(); + final NBTCompound root = region.getChunk(localChunkX, localChunkZ).getRootTag(); // root == null occurs when a chunk is not yet generated if (root != null) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java index 0169ff02..44c38765 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java @@ -19,8 +19,7 @@ public GregTechOre(NBTCompound tileEntity) { final NBTShort tagMeta = (NBTShort) tileEntity.getTag("m"); final NBTInt tagBlockY = (NBTInt) tileEntity.getTag("y"); - if (tagId != null - && tagId.getText().equals("GT_TileEntity_Ores") + if (tagId != null && tagId.getText().equals("GT_TileEntity_Ores") && tagBlockY != null && tagMeta != null && isSmallOreId(tagMeta.data) == false) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java index 682099b7..51e2f882 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java @@ -1,13 +1,14 @@ package com.sinthoras.visualprospecting.database.cachebuilder; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.ServerCache; -import io.xol.enklume.MinecraftWorld; import java.io.File; import java.io.IOException; import java.util.List; import java.util.zip.DataFormatException; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.ServerCache; +import io.xol.enklume.MinecraftWorld; + public class WorldAnalysis { private final MinecraftWorld world; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java index fd280a95..54161298 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java @@ -2,11 +2,13 @@ import static com.github.bartimaeusnek.bartworks.util.BW_ColorUtil.getColorFromRGBArray; +import net.minecraft.util.IIcon; + import com.github.bartimaeusnek.bartworks.system.material.Werkstoff; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.enums.OrePrefixes; -import net.minecraft.util.IIcon; public class BartworksOreMaterialProvider implements IOreMaterialProvider { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java index f9a754d2..f4cdcb62 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java @@ -1,10 +1,11 @@ package com.sinthoras.visualprospecting.database.veintypes; +import net.minecraft.util.IIcon; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.enums.Materials; import gregtech.api.enums.OrePrefixes; -import net.minecraft.util.IIcon; public class GregTechOreMaterialProvider implements IOreMaterialProvider { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java index c70b43cd..2e8b24f1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java @@ -1,8 +1,9 @@ package com.sinthoras.visualprospecting.database.veintypes; +import net.minecraft.util.IIcon; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.util.IIcon; public interface IOreMaterialProvider { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 4a2c2cdc..5fbec160 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -1,14 +1,16 @@ package com.sinthoras.visualprospecting.database.veintypes; -import com.sinthoras.visualprospecting.Tags; -import gregtech.api.GregTech_API; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; + import net.minecraft.util.EnumChatFormatting; +import com.sinthoras.visualprospecting.Tags; +import gregtech.api.GregTech_API; + public class VeinType { public static final int veinHeight = 9; @@ -27,19 +29,19 @@ public class VeinType { private boolean isHighlighted = true; // Available after VisualProspecting post GT initialization - public static final VeinType NO_VEIN = - new VeinType(Tags.ORE_MIX_NONE_NAME, null, 0, (short) -1, (short) -1, (short) -1, (short) -1, 0, 0); - - public VeinType( - String name, - IOreMaterialProvider oreMaterialProvider, - int blockSize, - short primaryOreMeta, - short secondaryOreMeta, - short inBetweenOreMeta, - short sporadicOreMeta, - int minBlockY, - int maxBlockY) { + public static final VeinType NO_VEIN = new VeinType( + Tags.ORE_MIX_NONE_NAME, + null, + 0, + (short) -1, + (short) -1, + (short) -1, + (short) -1, + 0, + 0); + + public VeinType(String name, IOreMaterialProvider oreMaterialProvider, int blockSize, short primaryOreMeta, + short secondaryOreMeta, short inBetweenOreMeta, short sporadicOreMeta, int minBlockY, int maxBlockY) { this.name = name; this.oreMaterialProvider = oreMaterialProvider; this.blockSize = blockSize; @@ -74,18 +76,14 @@ public boolean canOverlapIntoNeighborOreChunkAtCoordinateAxis() { } public boolean containsOre(short oreMetaData) { - return primaryOreMeta == oreMetaData - || secondaryOreMeta == oreMetaData + return primaryOreMeta == oreMetaData || secondaryOreMeta == oreMetaData || inBetweenOreMeta == oreMetaData || sporadicOreMeta == oreMetaData; } public List getOreMaterialNames() { - return oresAsSet.stream() - .map(metaData -> GregTech_API.sGeneratedMaterials[metaData]) - .filter(Objects::nonNull) - .map(material -> EnumChatFormatting.GRAY + material.mLocalizedName) - .collect(Collectors.toList()); + return oresAsSet.stream().map(metaData -> GregTech_API.sGeneratedMaterials[metaData]).filter(Objects::nonNull) + .map(material -> EnumChatFormatting.GRAY + material.mLocalizedName).collect(Collectors.toList()); } public Set getOresAtLayer(int layerBlockY) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index cea0609d..f8b412b9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -2,22 +2,26 @@ import static com.sinthoras.visualprospecting.Utils.*; +import java.io.File; +import java.util.*; +import java.util.regex.Pattern; + +import net.minecraft.client.resources.I18n; +import net.minecraft.util.EnumChatFormatting; + import codechicken.nei.NEIClientConfig; import codechicken.nei.SearchField; + import com.github.bartimaeusnek.bartworks.system.material.Werkstoff; import com.github.bartimaeusnek.bartworks.system.oregen.BW_OreLayer; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; + import gregtech.api.GregTech_API; import gregtech.api.enums.Materials; import gregtech.common.GT_Worldgen_GT_Ore_Layer; -import java.io.File; -import java.util.*; -import java.util.regex.Pattern; -import net.minecraft.client.resources.I18n; -import net.minecraft.util.EnumChatFormatting; public class VeinTypeCaching implements Runnable { @@ -44,19 +48,19 @@ public void run() { } final Materials material = getGregTechMaterial(vein.mPrimaryMeta); - veinTypes.add(new VeinType( - vein.mWorldGenName, - new GregTechOreMaterialProvider(material), - vein.mSize, - vein.mPrimaryMeta, - vein.mSecondaryMeta, - vein.mBetweenMeta, - vein.mSporadicMeta, - Math.max( - 0, - vein.mMinY - 6), // GregTech ore veins start at layer -1 and the blockY RNG adds another -5 - // offset - Math.min(255, vein.mMaxY - 6))); + veinTypes.add( + new VeinType( + vein.mWorldGenName, + new GregTechOreMaterialProvider(material), + vein.mSize, + vein.mPrimaryMeta, + vein.mSecondaryMeta, + vein.mBetweenMeta, + vein.mSporadicMeta, + Math.max(0, vein.mMinY - 6), // GregTech ore veins start at layer -1 and the blockY RNG adds + // another -5 + // offset + Math.min(255, vein.mMaxY - 6))); } if (isBartworksInstalled()) { @@ -65,24 +69,24 @@ public void run() { ? new GregTechOreMaterialProvider(getGregTechMaterial((short) vein.mPrimaryMeta)) : new BartworksOreMaterialProvider(Werkstoff.werkstoffHashMap.get((short) vein.mPrimaryMeta)); - veinTypes.add(new VeinType( - vein.mWorldGenName, - oreMaterialProvider, - vein.mSize, - (short) vein.mPrimaryMeta, - (short) vein.mSecondaryMeta, - (short) vein.mBetweenMeta, - (short) vein.mSporadicMeta, - Math.max(0, vein.mMinY), - Math.min(255, vein.mMaxY))); + veinTypes.add( + new VeinType( + vein.mWorldGenName, + oreMaterialProvider, + vein.mSize, + (short) vein.mPrimaryMeta, + (short) vein.mSecondaryMeta, + (short) vein.mBetweenMeta, + (short) vein.mSporadicMeta, + Math.max(0, vein.mMinY), + Math.min(255, vein.mMaxY))); } } // Assign veinTypeIds for efficient storage loadVeinTypeStorageInfo(); - final Optional maxVeinTypeIdOptional = - veinTypeStorageInfo.values().stream().max(Short::compare); + final Optional maxVeinTypeIdOptional = veinTypeStorageInfo.values().stream().max(Short::compare); short maxVeinTypeId = maxVeinTypeIdOptional.isPresent() ? maxVeinTypeIdOptional.get() : 0; for (VeinType veinType : veinTypes) { @@ -120,10 +124,7 @@ private Materials getGregTechMaterial(short metaId) { final Materials material = GregTech_API.sGeneratedMaterials[metaId]; if (material == null) { // Some materials are not registered in dev when their usage mod is not available. - return Materials.getAll().stream() - .filter(m -> m.mMetaItemSubID == metaId) - .findAny() - .get(); + return Materials.getAll().stream().filter(m -> m.mMetaItemSubID == metaId).findAny().get(); } return material; } @@ -170,10 +171,8 @@ public static void recalculateNEISearch() { List searchableStrings = veinType.getOreMaterialNames(); searchableStrings.add(I18n.format(veinType.name)); final boolean match = searchableStrings.stream() - .map(EnumChatFormatting::getTextWithoutFormattingCodes) - .map(String::toLowerCase) - .anyMatch(searchableString -> - filterPattern.matcher(searchableString).find()); + .map(EnumChatFormatting::getTextWithoutFormattingCodes).map(String::toLowerCase) + .anyMatch(searchableString -> filterPattern.matcher(searchableString).find()); veinType.setNEISearchHeighlight(match); } else { diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java index 6edae4be..2be8956d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java @@ -1,9 +1,16 @@ package com.sinthoras.visualprospecting.hooks; +import net.minecraft.client.settings.KeyBinding; +import net.minecraftforge.client.ClientCommandHandler; +import net.minecraftforge.common.MinecraftForge; + +import org.lwjgl.input.Keyboard; + import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ResetClientCacheCommand; import com.sinthoras.visualprospecting.integration.voxelmap.VoxelMapEventHandler; + import cpw.mods.fml.client.registry.ClientRegistry; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; @@ -13,10 +20,6 @@ import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.event.FMLServerStoppedEvent; import cpw.mods.fml.common.event.FMLServerStoppingEvent; -import net.minecraft.client.settings.KeyBinding; -import net.minecraftforge.client.ClientCommandHandler; -import net.minecraftforge.common.MinecraftForge; -import org.lwjgl.input.Keyboard; public class HooksClient extends HooksShared { @@ -26,7 +29,9 @@ public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { super.fmlLifeCycleEvent(event); VP.keyAction = new KeyBinding( - "visualprospecting.key.action.name", Keyboard.KEY_DELETE, "visualprospecting.key.action.category"); + "visualprospecting.key.action.name", + Keyboard.KEY_DELETE, + "visualprospecting.key.action.category"); ClientRegistry.registerKeyBinding(VP.keyAction); } diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java index d6508b64..a12adcf6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java @@ -1,5 +1,10 @@ package com.sinthoras.visualprospecting.hooks; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; +import net.minecraftforge.event.world.WorldEvent; + import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; @@ -7,10 +12,6 @@ import com.sinthoras.visualprospecting.database.WorldIdHandler; import com.sinthoras.visualprospecting.network.WorldIdNotification; import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraftforge.event.entity.EntityJoinWorldEvent; -import net.minecraftforge.event.world.WorldEvent; public class HooksEventBus { diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java index 0ae0afb3..530734e5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java @@ -2,6 +2,7 @@ import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.task.TaskManager; + import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.common.network.FMLNetworkEvent; diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index 415632ab..80e7a120 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -1,5 +1,13 @@ package com.sinthoras.visualprospecting.hooks; +import java.io.IOException; +import java.util.zip.DataFormatException; + +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.server.MinecraftServer; +import net.minecraftforge.common.MinecraftForge; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.VP; @@ -13,6 +21,7 @@ import com.sinthoras.visualprospecting.network.ProspectingRequest; import com.sinthoras.visualprospecting.network.ProspectionSharing; import com.sinthoras.visualprospecting.network.WorldIdNotification; + import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; @@ -30,12 +39,6 @@ import gregtech.api.enums.Materials; import gregtech.api.enums.OrePrefixes; import gregtech.api.util.GT_OreDictUnificator; -import java.io.IOException; -import java.util.zip.DataFormatException; -import net.minecraft.init.Items; -import net.minecraft.item.ItemStack; -import net.minecraft.server.MinecraftServer; -import net.minecraftforge.common.MinecraftForge; public class HooksShared { @@ -46,16 +49,28 @@ public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { VP.network = NetworkRegistry.INSTANCE.newSimpleChannel(Tags.MODID); int networkId = 0; + VP.network + .registerMessage(ProspectingRequest.Handler.class, ProspectingRequest.class, networkId++, Side.SERVER); VP.network.registerMessage( - ProspectingRequest.Handler.class, ProspectingRequest.class, networkId++, Side.SERVER); - VP.network.registerMessage( - ProspectingNotification.Handler.class, ProspectingNotification.class, networkId++, Side.CLIENT); + ProspectingNotification.Handler.class, + ProspectingNotification.class, + networkId++, + Side.CLIENT); VP.network.registerMessage( - WorldIdNotification.Handler.class, WorldIdNotification.class, networkId++, Side.CLIENT); + WorldIdNotification.Handler.class, + WorldIdNotification.class, + networkId++, + Side.CLIENT); VP.network.registerMessage( - ProspectionSharing.ServerHandler.class, ProspectionSharing.class, networkId++, Side.SERVER); + ProspectionSharing.ServerHandler.class, + ProspectionSharing.class, + networkId++, + Side.SERVER); VP.network.registerMessage( - ProspectionSharing.ClientHandler.class, ProspectionSharing.class, networkId++, Side.CLIENT); + ProspectionSharing.ClientHandler.class, + ProspectionSharing.class, + networkId++, + Side.CLIENT); ProspectorsLog.instance = new ProspectorsLog(); GameRegistry.registerItem(ProspectorsLog.instance, ProspectorsLog.instance.getUnlocalizedName()); @@ -70,16 +85,15 @@ public void fmlLifeCycleEvent(FMLInitializationEvent event) { // postInit "Handle interaction with other mods, complete your setup based on this." public void fmlLifeCycleEvent(FMLPostInitializationEvent event) { GregTech_API.sAfterGTPostload.add(new VeinTypeCaching()); - GregTech_API.sAfterGTPostload.add(() -> GT_Values.RA.addAssemblerRecipe( - new ItemStack[] { - GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Wood, 2L), - new ItemStack(Items.writable_book, 1, 0x7FFF), - new ItemStack(Items.gold_nugget, 1, 0x7FFF) - }, - Materials.Glue.getFluid(20L), - new ItemStack(ProspectorsLog.instance, 1, 0), - 128, - 8)); + GregTech_API.sAfterGTPostload.add( + () -> GT_Values.RA.addAssemblerRecipe( + new ItemStack[] { GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Wood, 2L), + new ItemStack(Items.writable_book, 1, 0x7FFF), + new ItemStack(Items.gold_nugget, 1, 0x7FFF) }, + Materials.Glue.getFluid(20L), + new ItemStack(ProspectorsLog.instance, 1, 0), + 128, + 8)); } public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) {} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java b/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java index acc008e5..731936c8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java @@ -1,6 +1,7 @@ package com.sinthoras.visualprospecting.integration; import java.util.List; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.OpenGlHelper; @@ -8,14 +9,16 @@ import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; + import org.lwjgl.opengl.GL11; + import thaumcraft.api.aspects.Aspect; import thaumcraft.client.lib.UtilsFX; public class DrawUtils { - public static void drawGradientRect( - double minPixelX, double minPixelY, double maxPixelX, double maxPixelY, double z, int colorA, int colorB) { + public static void drawGradientRect(double minPixelX, double minPixelY, double maxPixelX, double maxPixelY, + double z, int colorA, int colorB) { GL11.glDisable(GL11.GL_TEXTURE_2D); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); @@ -47,13 +50,13 @@ public static void drawGradientRect( GL11.glEnable(GL11.GL_TEXTURE_2D); } - public static void drawGradientRect( - double minPixelX, double minPixelY, double maxPixelX, double maxPixelY, int colorA, int colorB) { + public static void drawGradientRect(double minPixelX, double minPixelY, double maxPixelX, double maxPixelY, + int colorA, int colorB) { drawGradientRect(minPixelX, minPixelY, maxPixelX, maxPixelY, 300, colorA, colorB); } - public static void drawQuad( - ResourceLocation texture, double x, double y, double width, double height, int color, float alpha) { + public static void drawQuad(ResourceLocation texture, double x, double y, double width, double height, int color, + float alpha) { GL11.glEnable(GL11.GL_BLEND); OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); @@ -93,8 +96,8 @@ public static void drawQuad(IIcon icon, double x, double y, double width, double tessellator.draw(); } - public static void drawAspect( - double centerPixelX, double centerPixelY, double pixelSize, Aspect aspect, int amount) { + public static void drawAspect(double centerPixelX, double centerPixelY, double pixelSize, Aspect aspect, + int amount) { final int textureSize = 16; GL11.glPushMatrix(); @@ -114,8 +117,8 @@ public static void drawAspect( GL11.glPopMatrix(); } - public static void drawSimpleLabel( - GuiScreen gui, String text, double textX, double textY, int fontColor, int bgColor, boolean centered) { + public static void drawSimpleLabel(GuiScreen gui, String text, double textX, double textY, int fontColor, + int bgColor, boolean centered) { GL11.glPushMatrix(); double dTextX = textX - (double) (int) textX; double dTextY = textY - (double) (int) textY; @@ -136,8 +139,8 @@ public static void drawSimpleLabel( GL11.glPopMatrix(); } - public static void drawSimpleTooltip( - GuiScreen gui, List text, double x, double y, int fontColor, int bgColor) { + public static void drawSimpleTooltip(GuiScreen gui, List text, double x, double y, int fontColor, + int bgColor) { if (text.isEmpty()) return; int maxTextWidth = 0; @@ -169,8 +172,7 @@ public static void drawSimpleTooltip( } public static float[] floats(int rgb) { - return new float[] { - (float) (rgb >> 16 & 255) / 255.0F, (float) (rgb >> 8 & 255) / 255.0F, (float) (rgb & 255) / 255.0F - }; + return new float[] { (float) (rgb >> 16 & 255) / 255.0F, (float) (rgb >> 8 & 255) / 255.0F, + (float) (rgb & 255) / 255.0F }; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java index e085e951..8c914bb5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java @@ -5,18 +5,20 @@ import static gregtech.common.GT_Proxy.GTOIL; import static gregtech.common.GT_UndergroundOil.undergroundOil; -import gregtech.GT_Mod; -import gregtech.api.objects.GT_UO_Dimension; -import gregtech.api.objects.GT_UO_Fluid; -import gregtech.api.objects.XSTR; -import gregtech.common.GT_UndergroundOil; import java.util.HashMap; import java.util.Map; + import net.minecraft.world.ChunkCoordIntPair; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; +import gregtech.GT_Mod; +import gregtech.api.objects.GT_UO_Dimension; +import gregtech.api.objects.GT_UO_Fluid; +import gregtech.api.objects.XSTR; +import gregtech.common.GT_UndergroundOil; + public class UndergroundFluidsWrapper { private static final boolean isGTNHGregTechUndergroundFluids; @@ -52,8 +54,8 @@ private static FluidStack vanillaProspectFluid(World world, int chunkX, int chun return null; } - Map chunkData = - dimensionWiseChunkData.computeIfAbsent(dimensionId, k -> new HashMap<>(1024)); + Map chunkData = dimensionWiseChunkData + .computeIfAbsent(dimensionId, k -> new HashMap<>(1024)); int[] tInts = chunkData.get(chunkCoordinate); @@ -79,8 +81,12 @@ private static FluidStack vanillaProspectFluid(World world, int chunkX, int chun fluidInChunk = new FluidStack(uoFluid.getFluid(), tInts[GTOIL]); } else { fluidInChunk = new FluidStack(uoFluid.getFluid(), uoFluid.getRandomAmount(tRandom)); - fluidInChunk.amount = (int) ((float) fluidInChunk.amount - * (0.75f + (XSTR_INSTANCE.nextFloat() / 2f))); // Randomly change amounts by +/- 25% + fluidInChunk.amount = (int) ((float) fluidInChunk.amount * (0.75f + (XSTR_INSTANCE.nextFloat() / 2f))); // Randomly + // change + // amounts + // by + // +/- + // 25% } tInts[GTOIL] = fluidInChunk.amount; tInts[GTOILFLUID] = fluidInChunk.getFluidID(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java index c4efa455..4be3cb6d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java @@ -3,15 +3,17 @@ import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; import static com.sinthoras.visualprospecting.integration.journeymap.Reflection.getJourneyMapGridRenderer; +import java.util.ArrayList; +import java.util.List; + +import journeymap.client.render.map.GridRenderer; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.integration.journeymap.buttons.*; import com.sinthoras.visualprospecting.integration.journeymap.render.*; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.OreVeinWaypointManager; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.ThaumcraftNodeWaypointManager; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.WaypointManager; -import java.util.ArrayList; -import java.util.List; -import journeymap.client.render.map.GridRenderer; public class JourneyMapState { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java index a64aa03c..31e9121c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java @@ -1,10 +1,12 @@ package com.sinthoras.visualprospecting.integration.journeymap; -import com.sinthoras.visualprospecting.VP; import java.lang.reflect.Field; + import journeymap.client.render.map.GridRenderer; import journeymap.client.ui.fullscreen.Fullscreen; +import com.sinthoras.visualprospecting.VP; + public class Reflection { private static Field gridRenderer; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java index f648fc2e..d3c8ea89 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java @@ -1,17 +1,20 @@ package com.sinthoras.visualprospecting.integration.journeymap; -import com.sinthoras.visualprospecting.database.ClientCache; import journeymap.client.ui.UIManager; import journeymap.client.ui.component.Button; import journeymap.client.ui.component.ButtonList; import journeymap.client.ui.component.JmUI; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.resources.I18n; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.IChatComponent; +import com.sinthoras.visualprospecting.database.ClientCache; + public class ResetClientCacheConfirmation extends JmUI { + private Button confirmButton; private Button cancelButton; @@ -41,8 +44,8 @@ protected void layoutButtons() { protected void func_146284_a(GuiButton guibutton) { if (guibutton == confirmButton) { ClientCache.instance.resetPlayerProgression(); - final IChatComponent confirmation = - new ChatComponentTranslation("visualprospecting.resetprogress.confirmation"); + final IChatComponent confirmation = new ChatComponentTranslation( + "visualprospecting.resetprogress.confirmation"); confirmation.getChatStyle().setItalic(true); Minecraft.getMinecraft().thePlayer.addChatMessage(confirmation); UIManager.getInstance().openFullscreenMap(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java index 3cab68f2..0007af1a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java @@ -1,8 +1,9 @@ package com.sinthoras.visualprospecting.integration.journeymap.buttons; +import journeymap.client.ui.theme.ThemeToggle; + import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.buttons.*; -import journeymap.client.ui.theme.ThemeToggle; public class LayerButton extends com.sinthoras.visualprospecting.integration.model.buttons.LayerButton { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java index e1bbe7e0..dff1ece2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java @@ -1,10 +1,13 @@ package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import java.util.List; + import journeymap.client.render.draw.DrawStep; + import net.minecraft.client.gui.FontRenderer; +import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; + public interface ClickableDrawStep extends DrawStep { List getTooltip(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java index 608a2454..966a1b0e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java @@ -1,12 +1,14 @@ package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; import java.awt.geom.Point2D; + import journeymap.client.render.draw.DrawStep; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; + public class DirtyChunkDrawStep implements DrawStep { private final DirtyChunkLocation dirtyChunkLocation; @@ -16,31 +18,37 @@ public DirtyChunkDrawStep(DirtyChunkLocation dirtyChunkLocation) { } @Override - public void draw( - double draggedPixelX, - double draggedPixelY, - GridRenderer gridRenderer, - float drawScale, - double fontScale, - double rotation) { + public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, + double fontScale, double rotation) { final int zoom = gridRenderer.getZoom(); double blockSize = Math.pow(2, zoom); - final Point2D.Double blockAsPixel = - gridRenderer.getBlockPixelInGrid(dirtyChunkLocation.getBlockX(), dirtyChunkLocation.getBlockZ()); - final Point2D.Double pixel = - new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); + final Point2D.Double blockAsPixel = gridRenderer + .getBlockPixelInGrid(dirtyChunkLocation.getBlockX(), dirtyChunkLocation.getBlockZ()); + final Point2D.Double pixel = new Point2D.Double( + blockAsPixel.getX() + draggedPixelX, + blockAsPixel.getY() + draggedPixelY); float alpha = 0.5f; alpha *= alpha * 204; int color = dirtyChunkLocation.isDirty() ? 0xFF0000 : 0x00FFAA; DrawUtil.drawRectangle( - pixel.getX(), pixel.getY(), VP.chunkWidth * blockSize, VP.chunkDepth * blockSize, color, (int) alpha); + pixel.getX(), + pixel.getY(), + VP.chunkWidth * blockSize, + VP.chunkDepth * blockSize, + color, + (int) alpha); if (dirtyChunkLocation.isDirty()) { final int borderColor = 0xFFD700; final int borderAlpha = 204; DrawUtil.drawRectangle(pixel.getX(), pixel.getY(), 15 * blockSize, blockSize, borderColor, borderAlpha); DrawUtil.drawRectangle( - pixel.getX() + 15 * blockSize, pixel.getY(), blockSize, 15 * blockSize, borderColor, borderAlpha); + pixel.getX() + 15 * blockSize, + pixel.getY(), + blockSize, + 15 * blockSize, + borderColor, + borderAlpha); DrawUtil.drawRectangle( pixel.getX() + 1 * blockSize, pixel.getY() + 15 * blockSize, @@ -49,7 +57,12 @@ public void draw( borderColor, borderAlpha); DrawUtil.drawRectangle( - pixel.getX(), pixel.getY() + 1 * blockSize, blockSize, 15 * blockSize, borderColor, borderAlpha); + pixel.getX(), + pixel.getY() + 1 * blockSize, + blockSize, + 15 * blockSize, + borderColor, + borderAlpha); DrawUtil.drawLabel( "D", diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java index 3074dca7..2bfc0985 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java @@ -1,24 +1,28 @@ package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.integration.DrawUtils; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; -import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.List; + import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; + import net.minecraft.client.gui.FontRenderer; import net.minecraft.init.Blocks; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.integration.DrawUtils; +import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; +import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; + public class OreVeinDrawStep implements ClickableDrawStep { - private static final ResourceLocation depletedTextureLocation = - new ResourceLocation(Tags.MODID, "textures/depleted.png"); + private static final ResourceLocation depletedTextureLocation = new ResourceLocation( + Tags.MODID, + "textures/depleted.png"); private final OreVeinLocation oreVeinLocation; @@ -66,19 +70,15 @@ public IWaypointAndLocationProvider getLocationProvider() { } @Override - public void draw( - double draggedPixelX, - double draggedPixelY, - GridRenderer gridRenderer, - float drawScale, - double fontScale, - double rotation) { + public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, + double fontScale, double rotation) { iconSize = 32 * fontScale; final double iconSizeHalf = iconSize / 2; - final Point2D.Double blockAsPixel = - gridRenderer.getBlockPixelInGrid(oreVeinLocation.getBlockX(), oreVeinLocation.getBlockZ()); - final Point2D.Double pixel = - new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); + final Point2D.Double blockAsPixel = gridRenderer + .getBlockPixelInGrid(oreVeinLocation.getBlockX(), oreVeinLocation.getBlockZ()); + final Point2D.Double pixel = new Point2D.Double( + blockAsPixel.getX() + draggedPixelX, + blockAsPixel.getY() + draggedPixelY); if (gridRenderer.getZoom() >= Config.minZoomLevelForOreLabel && oreVeinLocation.isDepleted() == false) { final int fontColor = oreVeinLocation.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F; @@ -123,9 +123,19 @@ public void draw( final int borderAlpha = 204; final int color = 0xFFD700; DrawUtil.drawRectangle( - iconX - thickness, iconY - thickness, iconSize + thickness, thickness, color, borderAlpha); + iconX - thickness, + iconY - thickness, + iconSize + thickness, + thickness, + color, + borderAlpha); DrawUtil.drawRectangle( - iconX + iconSize, iconY - thickness, thickness, iconSize + thickness, color, borderAlpha); + iconX + iconSize, + iconY - thickness, + thickness, + iconSize + thickness, + color, + borderAlpha); DrawUtil.drawRectangle(iconX, iconY + iconSize, iconSize + thickness, thickness, color, borderAlpha); DrawUtil.drawRectangle(iconX - thickness, iconY, thickness, iconSize + thickness, color, borderAlpha); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java index 928dfaee..45cab280 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java @@ -1,27 +1,34 @@ package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.integration.DrawUtils; -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; -import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; import java.awt.geom.Point2D; import java.util.List; + import journeymap.client.render.map.GridRenderer; + import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.util.ResourceLocation; + import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; + import thaumcraft.api.aspects.Aspect; import thaumcraft.client.lib.UtilsFX; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.integration.DrawUtils; +import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; +import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; +import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; + public class ThaumcraftNodeDrawStep implements ClickableDrawStep { - private static final ResourceLocation markedTextureLocation = - new ResourceLocation(Tags.MODID, "textures/node_marked.png"); - private static final ResourceLocation unmarkedTextureLocation = - new ResourceLocation(Tags.MODID, "textures/node_unmarked.png"); + private static final ResourceLocation markedTextureLocation = new ResourceLocation( + Tags.MODID, + "textures/node_marked.png"); + private static final ResourceLocation unmarkedTextureLocation = new ResourceLocation( + Tags.MODID, + "textures/node_unmarked.png"); private final ThaumcraftNodeLocation thaumcraftNodeLocation; @@ -34,19 +41,15 @@ public ThaumcraftNodeDrawStep(ThaumcraftNodeLocation thaumcraftNodeLocation) { } @Override - public void draw( - double draggedPixelX, - double draggedPixelY, - GridRenderer gridRenderer, - float drawScale, - double fontScale, - double rotation) { + public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, + double fontScale, double rotation) { final double borderSize = 44 * fontScale; final double borderSizeHalf = borderSize / 2; - final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid( - thaumcraftNodeLocation.getBlockX(), thaumcraftNodeLocation.getBlockZ()); - final Point2D.Double pixel = - new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); + final Point2D.Double blockAsPixel = gridRenderer + .getBlockPixelInGrid(thaumcraftNodeLocation.getBlockX(), thaumcraftNodeLocation.getBlockZ()); + final Point2D.Double pixel = new Point2D.Double( + blockAsPixel.getX() + draggedPixelX, + blockAsPixel.getY() + draggedPixelY); centerPixelX = pixel.getX(); centerPixelY = pixel.getY(); clickableRadiusPixelSquared = borderSizeHalf * borderSizeHalf; @@ -63,7 +66,11 @@ public void draw( final int aspectPixelDiameter = 32; DrawUtils.drawAspect( - pixel.getX(), pixel.getY(), aspectPixelDiameter, thaumcraftNodeLocation.getStrongestAspect(), 0); + pixel.getX(), + pixel.getY(), + aspectPixelDiameter, + thaumcraftNodeLocation.getStrongestAspect(), + 0); } public List getTooltip() { @@ -102,8 +109,8 @@ public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int d maxTextWidth = (int) Math.ceil(maxTextWidth * 1.25f); } - final int aspectRows = - (thaumcraftNodeLocation.getAspects().size() + 4) / 5; // Equivalent to Math.ceil(size / 5) + final int aspectRows = (thaumcraftNodeLocation.getAspects().size() + 4) / 5; // Equivalent to Math.ceil(size / + // 5) final int aspectColumns = Math.min(thaumcraftNodeLocation.getAspects().size(), 5); int pixelX = mouseX + 12; @@ -125,7 +132,12 @@ public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int d // Draw background final int backgroundColor = 0xF0100010; DrawUtils.drawGradientRect( - pixelX - 3, pixelY - 4, pixelX + tooltipWidth + 3, pixelY - 3, backgroundColor, backgroundColor); + pixelX - 3, + pixelY - 4, + pixelX + tooltipWidth + 3, + pixelY - 3, + backgroundColor, + backgroundColor); DrawUtils.drawGradientRect( pixelX - 3, pixelY + tooltipHeight + 3, @@ -141,7 +153,12 @@ public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int d backgroundColor, backgroundColor); DrawUtils.drawGradientRect( - pixelX - 4, pixelY - 3, pixelX - 3, pixelY + tooltipHeight + 3, backgroundColor, backgroundColor); + pixelX - 4, + pixelY - 3, + pixelX - 3, + pixelY + tooltipHeight + 3, + backgroundColor, + backgroundColor); DrawUtils.drawGradientRect( pixelX + tooltipWidth + 3, pixelY - 3, @@ -153,7 +170,12 @@ public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int d int verdunGreen = 0x505000FF; int borderColor = 0x5028007F; DrawUtils.drawGradientRect( - pixelX - 3, pixelY - 3 + 1, pixelX - 3 + 1, pixelY + tooltipHeight + 3 - 1, verdunGreen, borderColor); + pixelX - 3, + pixelY - 3 + 1, + pixelX - 3 + 1, + pixelY + tooltipHeight + 3 - 1, + verdunGreen, + borderColor); DrawUtils.drawGradientRect( pixelX + tooltipWidth + 2, pixelY - 3 + 1, @@ -162,7 +184,12 @@ public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int d verdunGreen, borderColor); DrawUtils.drawGradientRect( - pixelX - 3, pixelY - 3, pixelX + tooltipWidth + 3, pixelY - 3 + 1, verdunGreen, verdunGreen); + pixelX - 3, + pixelY - 3, + pixelX + tooltipWidth + 3, + pixelY - 3 + 1, + verdunGreen, + verdunGreen); DrawUtils.drawGradientRect( pixelX - 3, pixelY + tooltipHeight + 2, @@ -184,7 +211,10 @@ public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int d offset += 12; final int nodeDescriptonWidth = (int) Math.ceil(fontRenderer.getStringWidth(nodeDescription) * 1.1f); fontRenderer.drawString( - nodeDescription, pixelX + nodeDescriptonWidth - titleWidth, pixelY + offset, 0xFFFFFFFF); + nodeDescription, + pixelX + nodeDescriptonWidth - titleWidth, + pixelY + offset, + 0xFFFFFFFF); final int deleteHintWidth = (int) Math.ceil(fontRenderer.getStringWidth(deleteHint) * 1.1f); fontRenderer.drawString( diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java index acb7b56d..f0ea4eaa 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java @@ -1,13 +1,15 @@ package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; import java.awt.geom.Point2D; + import journeymap.client.render.draw.DrawStep; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; + public class UndergroundFluidChunkDrawStep implements DrawStep { private final UndergroundFluidChunkLocation undergroundFluidChunkLocation; @@ -17,23 +19,20 @@ public UndergroundFluidChunkDrawStep(UndergroundFluidChunkLocation undergroundFl } @Override - public void draw( - double draggedPixelX, - double draggedPixelY, - GridRenderer gridRenderer, - float drawScale, - double fontScale, - double rotation) { + public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, + double fontScale, double rotation) { final int zoom = gridRenderer.getZoom(); if (undergroundFluidChunkLocation.getFluidAmount() > 0 && zoom >= Config.minZoomLevelForUndergroundFluidDetails) { double blockSize = Math.pow(2, zoom); final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid( - undergroundFluidChunkLocation.getBlockX(), undergroundFluidChunkLocation.getBlockZ()); - final Point2D.Double pixel = - new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); + undergroundFluidChunkLocation.getBlockX(), + undergroundFluidChunkLocation.getBlockZ()); + final Point2D.Double pixel = new Point2D.Double( + blockAsPixel.getX() + draggedPixelX, + blockAsPixel.getY() + draggedPixelY); float alpha = ((float) (undergroundFluidChunkLocation.getFluidAmount() - - undergroundFluidChunkLocation.getMinAmountInField())) + - undergroundFluidChunkLocation.getMinAmountInField())) / (undergroundFluidChunkLocation.getMaxAmountInField() - undergroundFluidChunkLocation.getMinAmountInField() + 1); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java index 3b75237d..7f0edcfb 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java @@ -1,12 +1,14 @@ package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; import java.awt.geom.Point2D; + import journeymap.client.render.draw.DrawStep; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; + public class UndergroundFluidDrawStep implements DrawStep { private final UndergroundFluidLocation undergroundFluidLocation; @@ -16,20 +18,16 @@ public UndergroundFluidDrawStep(UndergroundFluidLocation undergroundFluidLocatio } @Override - public void draw( - double draggedPixelX, - double draggedPixelY, - GridRenderer gridRenderer, - float drawScale, - double fontScale, - double rotation) { + public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, + double fontScale, double rotation) { final int maxAmountInField = undergroundFluidLocation.getMaxProduction(); if (maxAmountInField > 0) { final double blockSize = Math.pow(2, gridRenderer.getZoom()); - final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid( - undergroundFluidLocation.getBlockX(), undergroundFluidLocation.getBlockZ()); - final Point2D.Double pixel = - new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); + final Point2D.Double blockAsPixel = gridRenderer + .getBlockPixelInGrid(undergroundFluidLocation.getBlockX(), undergroundFluidLocation.getBlockZ()); + final Point2D.Double pixel = new Point2D.Double( + blockAsPixel.getX() + draggedPixelX, + blockAsPixel.getY() + draggedPixelY); final int borderColor = undergroundFluidLocation.getFluid().getColor(); final int borderAlpha = 204; @@ -62,7 +60,9 @@ public void draw( borderColor, borderAlpha); - final String label = undergroundFluidLocation.getMinProduction() + "L - " + maxAmountInField + "L " + final String label = undergroundFluidLocation.getMinProduction() + "L - " + + maxAmountInField + + "L " + undergroundFluidLocation.getFluid().getLocalizedName(); DrawUtil.drawLabel( label, diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java index 3cfb53d9..877d17d3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java @@ -1,12 +1,14 @@ package com.sinthoras.visualprospecting.integration.journeymap.render; +import java.util.ArrayList; +import java.util.List; + +import journeymap.client.render.draw.DrawStep; + import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.DirtyChunkDrawStep; import com.sinthoras.visualprospecting.integration.model.layers.DirtyChunkLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; -import java.util.ArrayList; -import java.util.List; -import journeymap.client.render.draw.DrawStep; public class DirtyChunkRenderer extends LayerRenderer { @@ -19,8 +21,7 @@ public DirtyChunkRenderer() { @Override public List mapLocationProviderToDrawStep(List visibleElements) { final List drawSteps = new ArrayList<>(); - visibleElements.stream() - .map(element -> (DirtyChunkLocation) element) + visibleElements.stream().map(element -> (DirtyChunkLocation) element) .forEach(location -> drawSteps.add(new DirtyChunkDrawStep(location))); return drawSteps; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java index 4d202f8b..00c90904 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java @@ -1,12 +1,14 @@ package com.sinthoras.visualprospecting.integration.journeymap.render; -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import java.util.ArrayList; import java.util.List; + import journeymap.client.render.draw.DrawStep; +import com.sinthoras.visualprospecting.integration.model.SupportedMods; +import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; +import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; + public abstract class LayerRenderer extends com.sinthoras.visualprospecting.integration.model.layers.LayerRenderer { private final LayerManager manager; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java index aca61a2c..410172bc 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java @@ -1,12 +1,13 @@ package com.sinthoras.visualprospecting.integration.journeymap.render; +import java.util.ArrayList; +import java.util.List; + import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.ClickableDrawStep; import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.OreVeinDrawStep; import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; -import java.util.ArrayList; -import java.util.List; public class OreVeinRenderer extends WaypointProviderLayerRenderer { @@ -20,8 +21,7 @@ public OreVeinRenderer() { public List mapLocationProviderToDrawStep( List visibleElements) { final List drawSteps = new ArrayList<>(); - visibleElements.stream() - .map(element -> (OreVeinLocation) element) + visibleElements.stream().map(element -> (OreVeinLocation) element) .forEach(location -> drawSteps.add(new OreVeinDrawStep(location))); return drawSteps; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java index cbd490b1..408188f8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java @@ -1,12 +1,13 @@ package com.sinthoras.visualprospecting.integration.journeymap.render; +import java.util.ArrayList; +import java.util.List; + import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.ClickableDrawStep; import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.ThaumcraftNodeDrawStep; import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; -import java.util.ArrayList; -import java.util.List; public class ThaumcraftNodeRenderer extends WaypointProviderLayerRenderer { @@ -20,8 +21,7 @@ public ThaumcraftNodeRenderer() { public List mapLocationProviderToDrawStep( List visibleElements) { final List drawSteps = new ArrayList<>(); - visibleElements.stream() - .map(element -> (ThaumcraftNodeLocation) element) + visibleElements.stream().map(element -> (ThaumcraftNodeLocation) element) .forEach(location -> drawSteps.add(new ThaumcraftNodeDrawStep(location))); return drawSteps; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java index c06f0f83..e5f0a740 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java @@ -1,12 +1,14 @@ package com.sinthoras.visualprospecting.integration.journeymap.render; +import java.util.ArrayList; +import java.util.List; + +import journeymap.client.render.draw.DrawStep; + import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.UndergroundFluidChunkDrawStep; import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidChunkLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -import java.util.ArrayList; -import java.util.List; -import journeymap.client.render.draw.DrawStep; public class UndergroundFluidChunkRenderer extends LayerRenderer { @@ -19,8 +21,7 @@ public UndergroundFluidChunkRenderer() { @Override public List mapLocationProviderToDrawStep(List visibleElements) { final List drawSteps = new ArrayList<>(); - visibleElements.stream() - .map(element -> (UndergroundFluidChunkLocation) element) + visibleElements.stream().map(element -> (UndergroundFluidChunkLocation) element) .forEach(location -> drawSteps.add(new UndergroundFluidChunkDrawStep(location))); return drawSteps; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java index a254ecf3..3116e7e6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java @@ -1,12 +1,14 @@ package com.sinthoras.visualprospecting.integration.journeymap.render; +import java.util.ArrayList; +import java.util.List; + +import journeymap.client.render.draw.DrawStep; + import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.UndergroundFluidDrawStep; import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; -import java.util.ArrayList; -import java.util.List; -import journeymap.client.render.draw.DrawStep; public class UndergroundFluidRenderer extends LayerRenderer { @@ -19,8 +21,7 @@ public UndergroundFluidRenderer() { @Override public List mapLocationProviderToDrawStep(List visibleElements) { final List drawSteps = new ArrayList<>(); - visibleElements.stream() - .map(element -> (UndergroundFluidLocation) element) + visibleElements.stream().map(element -> (UndergroundFluidLocation) element) .forEach(location -> drawSteps.add(new UndergroundFluidDrawStep(location))); return drawSteps; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java index febb3b18..3b30e061 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java @@ -1,13 +1,15 @@ package com.sinthoras.visualprospecting.integration.journeymap.render; -import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.ClickableDrawStep; -import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import java.util.ArrayList; import java.util.Collections; import java.util.List; + import net.minecraft.client.gui.FontRenderer; +import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.ClickableDrawStep; +import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; +import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; + public abstract class WaypointProviderLayerRenderer extends LayerRenderer { private final WaypointProviderManager manager; @@ -58,8 +60,7 @@ public boolean onMouseAction(boolean isDoubleClick) { if (hoveredDrawStep.getLocationProvider().isActiveAsWaypoint()) { manager.clearActiveWaypoint(); } else { - manager.setActiveWaypoint( - hoveredDrawStep.getLocationProvider().toWaypoint()); + manager.setActiveWaypoint(hoveredDrawStep.getLocationProvider().toWaypoint()); } } return true; @@ -74,8 +75,8 @@ public List getTextTooltip() { return null; } - public void drawCustomTooltip( - FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, int displayHeight) { + public void drawCustomTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, + int displayHeight) { if (hoveredDrawStep != null) { hoveredDrawStep.drawTooltip(fontRenderer, mouseX, mouseY, displayWidth, displayHeight); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java index ce814403..ffcd02a5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java @@ -1,9 +1,10 @@ package com.sinthoras.visualprospecting.integration.journeymap.waypoints; +import java.awt.*; + import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; -import java.awt.*; public class WaypointManager extends com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager { @@ -28,8 +29,7 @@ public journeymap.client.model.Waypoint getJmWaypoint() { @Override public void updateActiveWaypoint(Waypoint waypoint) { - if (hasWaypoint() == false - || waypoint.blockX != jmWaypoint.getX() + if (hasWaypoint() == false || waypoint.blockX != jmWaypoint.getX() || waypoint.blockY != jmWaypoint.getY() || waypoint.blockZ != jmWaypoint.getZ() || jmWaypoint.getDimensions().contains(waypoint.dimensionId) == false) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java index c57a4863..93e4c1ef 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java @@ -2,15 +2,17 @@ import static com.sinthoras.visualprospecting.Utils.*; +import java.util.ArrayList; +import java.util.List; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.integration.model.buttons.*; import com.sinthoras.visualprospecting.integration.model.layers.*; import com.sinthoras.visualprospecting.integration.tcnodetracker.NTNodeTrackerWaypointManager; import com.sinthoras.visualprospecting.integration.xaerominimap.XaeroMiniMapState; -import java.util.ArrayList; -import java.util.List; public class MapState { + public static final MapState instance = new MapState(); public final List buttons = new ArrayList<>(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java index 4d480b00..40c09867 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java @@ -1,10 +1,11 @@ package com.sinthoras.visualprospecting.integration.model.buttons; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.SupportedMods; import java.util.EnumMap; import java.util.Map; +import com.sinthoras.visualprospecting.integration.model.MapState; +import com.sinthoras.visualprospecting.integration.model.SupportedMods; + public class ButtonManager { private final String buttonTextKey; @@ -14,9 +15,9 @@ public class ButtonManager { private boolean isActive = false; /* - Provide textures in assets/journeymap/icon/theme/Vault/icon/.png - and assets/journeymap/icon/theme/Victorian/icon/.png for JourneyMap - and provide a texture in assets/xaeroworldmap/textures/.png for XaeroWorldMap. + * Provide textures in assets/journeymap/icon/theme/Vault/icon/.png and + * assets/journeymap/icon/theme/Victorian/icon/.png for JourneyMap and provide a texture in + * assets/xaeroworldmap/textures/.png for XaeroWorldMap. */ public ButtonManager(String buttonTextKey, String iconName) { this.buttonTextKey = buttonTextKey; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java index 27ddc47a..de9204ca 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java @@ -1,17 +1,19 @@ package com.sinthoras.visualprospecting.integration.model.layers; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.integration.model.buttons.DirtyChunkButtonManager; -import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import java.util.ArrayList; import java.util.List; + import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.integration.model.buttons.DirtyChunkButtonManager; +import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; +import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; + public class DirtyChunkLayerManager extends LayerManager { public static final DirtyChunkLayerManager instance = new DirtyChunkLayerManager(); @@ -26,8 +28,8 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i } @Override - protected List generateVisibleElements( - int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, + int maxBlockZ) { final int minX = Utils.coordBlockToChunk(minBlockX); final int minZ = Utils.coordBlockToChunk(minBlockZ); final int maxX = Utils.coordBlockToChunk(maxBlockX); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java index b473f908..7b0dd31e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java @@ -1,14 +1,15 @@ package com.sinthoras.visualprospecting.integration.model.layers; -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; -import com.sinthoras.visualprospecting.integration.model.buttons.LayerButton; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; import java.util.Map; +import com.sinthoras.visualprospecting.integration.model.SupportedMods; +import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; +import com.sinthoras.visualprospecting.integration.model.buttons.LayerButton; +import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; + public abstract class LayerManager { private final ButtonManager buttonManager; @@ -54,8 +55,8 @@ public void forceRefresh() { public void onOpenMap() {} - protected abstract List generateVisibleElements( - int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ); + protected abstract List generateVisibleElements(int minBlockX, int minBlockZ, + int maxBlockX, int maxBlockZ); protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { return true; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java index 7c6d2d6f..89c335d8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java @@ -1,8 +1,9 @@ package com.sinthoras.visualprospecting.integration.model.layers; +import java.util.List; + import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; -import java.util.List; public abstract class LayerRenderer { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java index 3a76c9ea..5d06c9e4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java @@ -1,5 +1,10 @@ package com.sinthoras.visualprospecting.integration.model.layers; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.Minecraft; + import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; @@ -8,9 +13,6 @@ import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; -import java.util.ArrayList; -import java.util.List; -import net.minecraft.client.Minecraft; public class OreVeinLayerManager extends WaypointProviderManager { @@ -37,8 +39,7 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i final int maxOreChunkX = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(maxBlockX)); final int maxOreChunkZ = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - if (minOreChunkX != oldMinOreChunkX - || maxOreChunkX != oldMaxOreChunkX + if (minOreChunkX != oldMinOreChunkX || maxOreChunkX != oldMaxOreChunkX || minOreChunkZ != oldMinOreChunkZ || maxOreChunkZ != oldMaxOreChunkZ) { oldMinOreChunkX = minOreChunkX; @@ -51,8 +52,8 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i } @Override - protected List generateVisibleElements( - int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + protected List generateVisibleElements(int minBlockX, int minBlockZ, + int maxBlockX, int maxBlockZ) { final int minOreChunkX = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(minBlockX)); final int minOreChunkZ = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(minBlockZ)); final int maxOreChunkX = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(maxBlockX)); @@ -62,11 +63,10 @@ protected List generateVisibleElements( ArrayList oreChunkLocations = new ArrayList<>(); for (int chunkX = minOreChunkX; chunkX <= maxOreChunkX; chunkX = Utils.mapToCenterOreChunkCoord(chunkX + 3)) { - for (int chunkZ = minOreChunkZ; - chunkZ <= maxOreChunkZ; - chunkZ = Utils.mapToCenterOreChunkCoord(chunkZ + 3)) { - final OreVeinPosition oreVeinPosition = - ClientCache.instance.getOreVein(playerDimensionId, chunkX, chunkZ); + for (int chunkZ = minOreChunkZ; chunkZ + <= maxOreChunkZ; chunkZ = Utils.mapToCenterOreChunkCoord(chunkZ + 3)) { + final OreVeinPosition oreVeinPosition = ClientCache.instance + .getOreVein(playerDimensionId, chunkX, chunkZ); if (oreVeinPosition.veinType != VeinType.NO_VEIN) { oreChunkLocations.add(new OreVeinLocation(oreVeinPosition)); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java index ae9331d6..a51ba352 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java @@ -1,13 +1,15 @@ package com.sinthoras.visualprospecting.integration.model.layers; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.Minecraft; + import com.dyonovan.tcnodetracker.TCNodeTracker; import com.dyonovan.tcnodetracker.lib.NodeList; import com.sinthoras.visualprospecting.integration.model.buttons.ThaumcraftNodeButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; -import java.util.ArrayList; -import java.util.List; -import net.minecraft.client.Minecraft; public class ThaumcraftNodeLayerManager extends WaypointProviderManager { @@ -24,8 +26,7 @@ public ThaumcraftNodeLayerManager() { @Override protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - if (minBlockX != oldMinBlockX - || minBlockZ != oldMinBlockZ + if (minBlockX != oldMinBlockX || minBlockZ != oldMinBlockZ || maxBlockX != oldMaxBlockX || maxBlockZ != oldMaxBlockZ) { oldMinBlockX = minBlockX; @@ -38,15 +39,14 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i } @Override - protected List generateVisibleElements( - int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { + protected List generateVisibleElements(int minBlockX, int minBlockZ, + int maxBlockX, int maxBlockZ) { final int playerDimensionId = Minecraft.getMinecraft().thePlayer.dimension; ArrayList thaumcraftNodeLocations = new ArrayList<>(); for (NodeList node : TCNodeTracker.nodelist) { - if (node.dim == playerDimensionId - && node.x >= minBlockX + if (node.dim == playerDimensionId && node.x >= minBlockX && node.x <= maxBlockX && node.z >= minBlockZ && node.z <= maxBlockZ) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java index 97a409d5..9a547697 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java @@ -1,5 +1,10 @@ package com.sinthoras.visualprospecting.integration.model.layers; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.Minecraft; + import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; @@ -7,9 +12,6 @@ import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -import java.util.ArrayList; -import java.util.List; -import net.minecraft.client.Minecraft; public class UndergroundFluidChunkLayerManager extends LayerManager { @@ -26,16 +28,15 @@ public UndergroundFluidChunkLayerManager() { @Override protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minUndergroundFluidX = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - if (minUndergroundFluidX != oldMinUndergroundFluidX - || maxUndergroundFluidX != oldMaxUndergroundFluidX + final int minUndergroundFluidX = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); + final int minUndergroundFluidZ = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); + final int maxUndergroundFluidX = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); + final int maxUndergroundFluidZ = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); + if (minUndergroundFluidX != oldMinUndergroundFluidX || maxUndergroundFluidX != oldMaxUndergroundFluidX || minUndergroundFluidZ != oldMinUndergroundFluidZ || maxUndergroundFluidZ != oldMaxUndergroundFluidZ) { oldMinUndergroundFluidX = minUndergroundFluidX; @@ -48,41 +49,40 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i } @Override - protected List generateVisibleElements( - int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minUndergroundFluidX = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); + protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, + int maxBlockZ) { + final int minUndergroundFluidX = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); + final int minUndergroundFluidZ = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); + final int maxUndergroundFluidX = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); + final int maxUndergroundFluidZ = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); final int playerDimensionId = Minecraft.getMinecraft().thePlayer.dimension; ArrayList undergroundFluidPositions = new ArrayList<>(); - for (int chunkX = minUndergroundFluidX; - chunkX <= maxUndergroundFluidX; - chunkX += VP.undergroundFluidSizeChunkX) { - for (int chunkZ = minUndergroundFluidZ; - chunkZ <= maxUndergroundFluidZ; - chunkZ += VP.undergroundFluidSizeChunkZ) { - final UndergroundFluidPosition undergroundFluid = - ClientCache.instance.getUndergroundFluid(playerDimensionId, chunkX, chunkZ); + for (int chunkX = minUndergroundFluidX; chunkX + <= maxUndergroundFluidX; chunkX += VP.undergroundFluidSizeChunkX) { + for (int chunkZ = minUndergroundFluidZ; chunkZ + <= maxUndergroundFluidZ; chunkZ += VP.undergroundFluidSizeChunkZ) { + final UndergroundFluidPosition undergroundFluid = ClientCache.instance + .getUndergroundFluid(playerDimensionId, chunkX, chunkZ); if (undergroundFluid.isProspected()) { final int minAmountInField = undergroundFluid.getMinProduction(); final int maxAmountInField = undergroundFluid.getMaxProduction(); for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - undergroundFluidPositions.add(new UndergroundFluidChunkLocation( - chunkX + offsetChunkX, - chunkZ + offsetChunkZ, - playerDimensionId, - undergroundFluid.fluid, - undergroundFluid.chunks[offsetChunkX][offsetChunkZ], - minAmountInField, - maxAmountInField)); + undergroundFluidPositions.add( + new UndergroundFluidChunkLocation( + chunkX + offsetChunkX, + chunkZ + offsetChunkZ, + playerDimensionId, + undergroundFluid.fluid, + undergroundFluid.chunks[offsetChunkX][offsetChunkZ], + minAmountInField, + maxAmountInField)); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java index 57895b13..6cab439b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java @@ -1,5 +1,10 @@ package com.sinthoras.visualprospecting.integration.model.layers; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.Minecraft; + import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; @@ -7,9 +12,6 @@ import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; -import java.util.ArrayList; -import java.util.List; -import net.minecraft.client.Minecraft; public class UndergroundFluidLayerManager extends LayerManager { @@ -26,16 +28,15 @@ public UndergroundFluidLayerManager() { @Override protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minUndergroundFluidX = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - if (minUndergroundFluidX != oldMinUndergroundFluidX - || maxUndergroundFluidX != oldMaxUndergroundFluidX + final int minUndergroundFluidX = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); + final int minUndergroundFluidZ = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); + final int maxUndergroundFluidX = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); + final int maxUndergroundFluidZ = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); + if (minUndergroundFluidX != oldMinUndergroundFluidX || maxUndergroundFluidX != oldMaxUndergroundFluidX || minUndergroundFluidZ != oldMinUndergroundFluidZ || maxUndergroundFluidZ != oldMaxUndergroundFluidZ) { oldMinUndergroundFluidX = minUndergroundFluidX; @@ -48,28 +49,26 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i } @Override - protected List generateVisibleElements( - int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minUndergroundFluidX = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = - Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); + protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, + int maxBlockZ) { + final int minUndergroundFluidX = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); + final int minUndergroundFluidZ = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); + final int maxUndergroundFluidX = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); + final int maxUndergroundFluidZ = Utils + .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); final int playerDimensionId = Minecraft.getMinecraft().thePlayer.dimension; ArrayList undergroundFluidLocations = new ArrayList<>(); - for (int chunkX = minUndergroundFluidX; - chunkX <= maxUndergroundFluidX; - chunkX += VP.undergroundFluidSizeChunkX) { - for (int chunkZ = minUndergroundFluidZ; - chunkZ <= maxUndergroundFluidZ; - chunkZ += VP.undergroundFluidSizeChunkZ) { - final UndergroundFluidPosition undergroundFluid = - ClientCache.instance.getUndergroundFluid(playerDimensionId, chunkX, chunkZ); + for (int chunkX = minUndergroundFluidX; chunkX + <= maxUndergroundFluidX; chunkX += VP.undergroundFluidSizeChunkX) { + for (int chunkZ = minUndergroundFluidZ; chunkZ + <= maxUndergroundFluidZ; chunkZ += VP.undergroundFluidSizeChunkZ) { + final UndergroundFluidPosition undergroundFluid = ClientCache.instance + .getUndergroundFluid(playerDimensionId, chunkX, chunkZ); if (undergroundFluid.isProspected()) { undergroundFluidLocations.add(new UndergroundFluidLocation(undergroundFluid)); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java index 5a3c76fc..99e963f2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java @@ -1,14 +1,15 @@ package com.sinthoras.visualprospecting.integration.model.layers; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; import com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; public abstract class WaypointProviderManager extends LayerManager { @@ -45,8 +46,8 @@ public WaypointManager getWaypointManager(SupportedMods map) { return waypointManagers.get(map); } - protected abstract List generateVisibleElements( - int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ); + protected abstract List generateVisibleElements(int minBlockX, + int minBlockZ, int maxBlockX, int maxBlockZ); @Override protected void checkAndUpdateElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index aded93dd..5520c785 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -1,21 +1,24 @@ package com.sinthoras.visualprospecting.integration.model.locations; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.ClientCache; -import com.sinthoras.visualprospecting.database.OreVeinPosition; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; import java.util.List; import java.util.stream.Collectors; + import net.minecraft.client.resources.I18n; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IIcon; + import org.lwjgl.input.Keyboard; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.ClientCache; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; + public class OreVeinLocation implements IWaypointAndLocationProvider { private static final String depletedHint = EnumChatFormatting.RED + I18n.format("visualprospecting.depleted"); - private static final String activeWaypointHint = - EnumChatFormatting.GOLD + I18n.format("visualprospecting.iswaypoint"); + private static final String activeWaypointHint = EnumChatFormatting.GOLD + + I18n.format("visualprospecting.iswaypoint"); private static final String toggleDepletedHint = EnumChatFormatting.DARK_GRAY + I18n.format("visualprospecting.node.deletehint", Keyboard.getKeyName(VP.keyAction.getKeyCode())); @@ -29,8 +32,7 @@ public OreVeinLocation(OreVeinPosition oreVeinPosition) { this.oreVeinPosition = oreVeinPosition; name = EnumChatFormatting.WHITE + I18n.format(oreVeinPosition.veinType.name); materialNames = oreVeinPosition.veinType.getOreMaterialNames().stream() - .map(materialName -> EnumChatFormatting.GRAY + materialName) - .collect(Collectors.toList()); + .map(materialName -> EnumChatFormatting.GRAY + materialName).collect(Collectors.toList()); } @Override diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java index 67a396a7..263873af 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java @@ -1,24 +1,26 @@ package com.sinthoras.visualprospecting.integration.model.locations; -import com.dyonovan.tcnodetracker.lib.NodeList; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; import net.minecraft.client.resources.I18n; import net.minecraft.util.EnumChatFormatting; + import org.lwjgl.input.Keyboard; + import thaumcraft.api.aspects.Aspect; import thaumcraft.api.aspects.AspectList; import thaumcraft.api.nodes.NodeType; import thaumcraft.common.config.ConfigBlocks; import thaumcraft.common.tiles.TileNode; +import com.dyonovan.tcnodetracker.lib.NodeList; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; + public class ThaumcraftNodeLocation implements IWaypointAndLocationProvider { private static final String deleteHint = EnumChatFormatting.DARK_GRAY - + I18n.format("visualprospecting.node.deletehint", Keyboard.getKeyName(VP.keyAction.getKeyCode())); - ; - private static final String activeWaypointHint = - EnumChatFormatting.GOLD + I18n.format("visualprospecting.iswaypoint"); + + I18n.format("visualprospecting.node.deletehint", Keyboard.getKeyName(VP.keyAction.getKeyCode()));; + private static final String activeWaypointHint = EnumChatFormatting.GOLD + + I18n.format("visualprospecting.iswaypoint"); private static final String title = EnumChatFormatting.BOLD + I18n.format("tile.blockAiry.0.name"); private final NodeList node; @@ -61,7 +63,8 @@ public ThaumcraftNodeLocation(NodeList node) { description = node.mod.equals("BLANK") ? EnumChatFormatting.GRAY + I18n.format("nodetype." + node.type + ".name") - : EnumChatFormatting.GRAY + I18n.format("nodetype." + node.type + ".name") + ", " + : EnumChatFormatting.GRAY + I18n.format("nodetype." + node.type + ".name") + + ", " + I18n.format("nodemod." + node.mod + ".name"); } @@ -107,8 +110,7 @@ public void onWaypointCleared() { @Override public void onWaypointUpdated(Waypoint waypoint) { - isActiveAsWaypoint = waypoint.dimensionId == node.dim - && waypoint.blockX == node.x + isActiveAsWaypoint = waypoint.dimensionId == node.dim && waypoint.blockX == node.x && waypoint.blockY == node.y && waypoint.blockZ == node.z; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java index fdc68c3c..78713f61 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java @@ -1,8 +1,9 @@ package com.sinthoras.visualprospecting.integration.model.locations; -import com.sinthoras.visualprospecting.Utils; import net.minecraftforge.fluids.Fluid; +import com.sinthoras.visualprospecting.Utils; + public class UndergroundFluidChunkLocation implements ILocationProvider { private final int blockX; @@ -13,14 +14,8 @@ public class UndergroundFluidChunkLocation implements ILocationProvider { private final int maxAmountInField; private final int minAmountInField; - public UndergroundFluidChunkLocation( - int chunkX, - int chunkZ, - int dimensionId, - Fluid fluid, - int fluidAmount, - int minAmountInField, - int maxAmountInField) { + public UndergroundFluidChunkLocation(int chunkX, int chunkZ, int dimensionId, Fluid fluid, int fluidAmount, + int minAmountInField, int maxAmountInField) { blockX = Utils.coordChunkToBlock(chunkX); blockZ = Utils.coordChunkToBlock(chunkZ); this.dimensionId = dimensionId; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java index cf4bfbb1..a4fe404b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java @@ -1,8 +1,9 @@ package com.sinthoras.visualprospecting.integration.model.locations; -import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import net.minecraftforge.fluids.Fluid; +import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; + public class UndergroundFluidLocation implements ILocationProvider { private final UndergroundFluidPosition undergroundFluidPosition; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/Waypoint.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/Waypoint.java index 2d728403..971b8725 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/Waypoint.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/Waypoint.java @@ -1,6 +1,7 @@ package com.sinthoras.visualprospecting.integration.model.waypoints; public class Waypoint { + public final int blockX; public final int blockY; public final int blockZ; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java index bba1e502..1d77761d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java @@ -1,8 +1,9 @@ package com.sinthoras.visualprospecting.integration.voxelmap; +import java.lang.reflect.Method; + import com.sinthoras.visualprospecting.VP; import com.thevoxelbox.voxelmap.interfaces.IWaypointManager; -import java.lang.reflect.Method; public class IWaypointManagerReflection { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java index ec216cfd..32a3246f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java @@ -1,5 +1,12 @@ package com.sinthoras.visualprospecting.integration.voxelmap; +import java.util.TreeSet; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityClientPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.util.StatCollector; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.OreVeinPosition; @@ -8,13 +15,9 @@ import com.thevoxelbox.voxelmap.interfaces.AbstractVoxelMap; import com.thevoxelbox.voxelmap.interfaces.IWaypointManager; import com.thevoxelbox.voxelmap.util.Waypoint; + import cpw.mods.fml.common.eventhandler.SubscribeEvent; import gregtech.api.GregTech_API; -import java.util.TreeSet; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityClientPlayerMP; -import net.minecraft.item.ItemStack; -import net.minecraft.util.StatCollector; public class VoxelMapEventHandler { @@ -30,18 +33,19 @@ public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { TreeSet dim = new TreeSet<>(); dim.add(pos.dimensionId); - waypointManager.addWaypoint(new Waypoint( - StatCollector.translateToLocal(pos.veinType.name), // name - pos.getBlockX(), // X - pos.getBlockZ(), // Z - getY(), // Y - Config.enableVoxelMapWaypointsByDefault, // enabled - (float) color[0] / 255.0f, // red - (float) color[1] / 255.0f, // green - (float) color[2] / 255.0f, // blue - "Pickaxe", // icon - IWaypointManagerReflection.getCurrentSubworldDescriptor(waypointManager, false), // world - dim)); // dimension + waypointManager.addWaypoint( + new Waypoint( + StatCollector.translateToLocal(pos.veinType.name), // name + pos.getBlockX(), // X + pos.getBlockZ(), // Z + getY(), // Y + Config.enableVoxelMapWaypointsByDefault, // enabled + (float) color[0] / 255.0f, // red + (float) color[1] / 255.0f, // green + (float) color[2] / 255.0f, // blue + "Pickaxe", // icon + IWaypointManagerReflection.getCurrentSubworldDescriptor(waypointManager, false), // world + dim)); // dimension } @SubscribeEvent @@ -58,18 +62,19 @@ public void onFluidProspected(ProspectingNotificationEvent.UndergroundFluid even TreeSet dim = new TreeSet<>(); dim.add(pos.dimensionId); - waypointManager.addWaypoint(new Waypoint( - pos.fluid.getLocalizedName(), // name - x, // X - z, // Z - Minecraft.getMinecraft().theWorld.getHeightValue(x, z), // Y - Config.enableVoxelMapWaypointsByDefault, // enabled - (float) (color >> 16 & 0xFF) / 255.0f, // red - (float) (color >> 8 & 0xFF) / 255.0f, // green - (float) (color & 0xFF) / 255.0f, // blue - "Science", // icon - IWaypointManagerReflection.getCurrentSubworldDescriptor(waypointManager, false), // world - dim)); // dimension + waypointManager.addWaypoint( + new Waypoint( + pos.fluid.getLocalizedName(), // name + x, // X + z, // Z + Minecraft.getMinecraft().theWorld.getHeightValue(x, z), // Y + Config.enableVoxelMapWaypointsByDefault, // enabled + (float) (color >> 16 & 0xFF) / 255.0f, // red + (float) (color >> 8 & 0xFF) / 255.0f, // green + (float) (color & 0xFF) / 255.0f, // blue + "Science", // icon + IWaypointManagerReflection.getCurrentSubworldDescriptor(waypointManager, false), // world + dim)); // dimension } private static int getY() { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java index b76a683d..f9191bf9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java @@ -2,11 +2,12 @@ import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; +import java.util.ArrayList; +import java.util.List; + import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.OreVeinWaypointManager; import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.ThaumcraftNodeWaypointManager; import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.WaypointManager; -import java.util.ArrayList; -import java.util.List; public class XaeroMiniMapState { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java index 0c7ef6e2..cbfbe1e5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java @@ -1,16 +1,18 @@ package com.sinthoras.visualprospecting.integration.xaerominimap.waypoints; +import java.util.Hashtable; + +import xaero.common.minimap.waypoints.WaypointsManager; + import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; -import java.util.Hashtable; -import xaero.common.minimap.waypoints.WaypointsManager; public class WaypointManager extends com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager { - private static final Hashtable xWaypointTable = - WaypointsManager.getCustomWaypoints(Tags.MODID); + private static final Hashtable xWaypointTable = WaypointsManager + .getCustomWaypoints(Tags.MODID); private WaypointWithDimension xWaypoint; private final WaypointType waypointType; @@ -36,8 +38,7 @@ public WaypointWithDimension getXWaypoint() { @Override public void updateActiveWaypoint(Waypoint waypoint) { - if (!hasWaypoint() - || waypoint.blockX != xWaypoint.getX() + if (!hasWaypoint() || waypoint.blockX != xWaypoint.getX() || waypoint.blockY != xWaypoint.getY() || waypoint.blockZ != xWaypoint.getZ() || waypoint.dimensionId != xWaypoint.getDimID()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java index 3caca6a8..4cbf84b9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java @@ -2,15 +2,17 @@ import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; +import java.util.ArrayList; +import java.util.List; + import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.LayerButton; import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.OreVeinButton; import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.ThaumcraftNodeButton; import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.UndergroundFluidButton; import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.*; -import java.util.ArrayList; -import java.util.List; public class XaeroWorldMapState { + public static XaeroWorldMapState instance = new XaeroWorldMapState(); public final List buttons = new ArrayList<>(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/LayerButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/LayerButton.java index ac760ef8..869e3acb 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/LayerButton.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/LayerButton.java @@ -1,8 +1,9 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons; +import net.minecraft.util.ResourceLocation; + import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; -import net.minecraft.util.ResourceLocation; public class LayerButton extends com.sinthoras.visualprospecting.integration.model.buttons.LayerButton { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java index aa959e55..8498fbd3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java @@ -1,11 +1,14 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons; import java.util.function.Consumer; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiButton; import net.minecraft.util.ResourceLocation; + import org.lwjgl.opengl.GL11; + import xaero.map.gui.CursorBox; import xaero.map.gui.GuiTexturedButton; @@ -18,8 +21,8 @@ public class SizedGuiTexturedButton extends GuiTexturedButton { protected boolean active; - public SizedGuiTexturedButton( - int x, int y, ResourceLocation texture, Consumer action, CursorBox tooltip) { + public SizedGuiTexturedButton(int x, int y, ResourceLocation texture, Consumer action, + CursorBox tooltip) { super(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, 0, 0, ICON_WIDTH, ICON_HEIGHT, texture, action, tooltip); active = false; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java index 4d3d304c..14ada20a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java @@ -1,13 +1,16 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; +import java.util.List; + +import net.minecraft.client.gui.GuiScreen; + import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.InteractableRenderStep; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; -import java.util.List; -import net.minecraft.client.gui.GuiScreen; public abstract class InteractableLayerRenderer extends LayerRenderer { + private double mouseX; private double mouseY; protected WaypointProviderManager manager; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java index 78fd86b0..cd0edc47 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java @@ -1,12 +1,13 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; public abstract class LayerRenderer extends com.sinthoras.visualprospecting.integration.model.layers.LayerRenderer { @@ -33,7 +34,7 @@ public boolean isLayerActive() { @Override public void updateVisibleElements(List visibleElements) { - //noinspection unchecked + // noinspection unchecked renderSteps = (List) generateRenderSteps(visibleElements); renderStepsReversed = new ArrayList<>(renderSteps); Collections.reverse(renderStepsReversed); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java index af07fa00..53f5d261 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java @@ -1,13 +1,15 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; +import java.util.ArrayList; +import java.util.List; + import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.OreVeinRenderStep; -import java.util.ArrayList; -import java.util.List; public class OreVeinRenderer extends InteractableLayerRenderer { + public static OreVeinRenderer instance = new OreVeinRenderer(); public OreVeinRenderer() { @@ -17,8 +19,7 @@ public OreVeinRenderer() { @Override protected List generateRenderSteps(List visibleElements) { final List renderSteps = new ArrayList<>(); - visibleElements.stream() - .map(element -> (OreVeinLocation) element) + visibleElements.stream().map(element -> (OreVeinLocation) element) .forEach(location -> renderSteps.add(new OreVeinRenderStep(location))); return renderSteps; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java index 70a6ff6a..a511fee0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java @@ -1,13 +1,15 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; +import java.util.ArrayList; +import java.util.List; + import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.ThaumcraftNodeRenderStep; -import java.util.ArrayList; -import java.util.List; public class ThaumcraftNodeRenderer extends InteractableLayerRenderer { + public static ThaumcraftNodeRenderer instance = new ThaumcraftNodeRenderer(); public ThaumcraftNodeRenderer() { @@ -17,8 +19,7 @@ public ThaumcraftNodeRenderer() { @Override protected List generateRenderSteps(List visibleElements) { final List renderSteps = new ArrayList<>(); - visibleElements.stream() - .map(element -> (ThaumcraftNodeLocation) element) + visibleElements.stream().map(element -> (ThaumcraftNodeLocation) element) .forEach(location -> renderSteps.add(new ThaumcraftNodeRenderStep(location))); return renderSteps; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java index 7ef9e675..7b46e3c7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java @@ -1,13 +1,15 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; +import java.util.ArrayList; +import java.util.List; + import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidChunkLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.UndergroundFluidChunkRenderStep; -import java.util.ArrayList; -import java.util.List; public class UndergroundFluidChunkRenderer extends LayerRenderer { + public static UndergroundFluidChunkRenderer instance = new UndergroundFluidChunkRenderer(); public UndergroundFluidChunkRenderer() { @@ -18,8 +20,7 @@ public UndergroundFluidChunkRenderer() { protected List generateRenderSteps( List visibleElements) { final List renderSteps = new ArrayList<>(); - visibleElements.stream() - .map(element -> (UndergroundFluidChunkLocation) element) + visibleElements.stream().map(element -> (UndergroundFluidChunkLocation) element) .forEach(location -> renderSteps.add(new UndergroundFluidChunkRenderStep(location))); return renderSteps; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java index a024c279..8883a833 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java @@ -1,13 +1,15 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; +import java.util.ArrayList; +import java.util.List; + import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.UndergroundFluidRenderStep; -import java.util.ArrayList; -import java.util.List; public class UndergroundFluidRenderer extends LayerRenderer { + public static UndergroundFluidRenderer instance = new UndergroundFluidRenderer(); public UndergroundFluidRenderer() { @@ -17,8 +19,7 @@ public UndergroundFluidRenderer() { @Override protected List generateRenderSteps(List visibleElements) { final List renderSteps = new ArrayList<>(); - visibleElements.stream() - .map(element -> (UndergroundFluidLocation) element) + visibleElements.stream().map(element -> (UndergroundFluidLocation) element) .forEach(location -> renderSteps.add(new UndergroundFluidRenderStep(location))); return renderSteps; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java index b8962ab9..0a5e1856 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java @@ -1,8 +1,9 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import net.minecraft.client.gui.GuiScreen; +import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; + public interface InteractableRenderStep extends RenderStep { boolean isMouseOver(double mouseX, double mouseY, double scale); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java index 2f6832d0..3350a073 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java @@ -1,21 +1,25 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.integration.DrawUtils; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; -import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; import java.util.ArrayList; import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.resources.I18n; import net.minecraft.init.Blocks; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; + import org.lwjgl.opengl.GL11; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.integration.DrawUtils; +import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; +import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; + public class OreVeinRenderStep implements InteractableRenderStep { private final OreVeinLocation oreVeinLocation; @@ -52,33 +56,74 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double if (!oreVeinLocation.drawSearchHighlight() || oreVeinLocation.isDepleted()) { DrawUtils.drawGradientRect( - -iconSizeHalf, -iconSizeHalf, iconSizeHalf, iconSizeHalf, 0, 0x96000000, 0x96000000); + -iconSizeHalf, + -iconSizeHalf, + iconSizeHalf, + iconSizeHalf, + 0, + 0x96000000, + 0x96000000); if (oreVeinLocation.isDepleted()) { DrawUtils.drawQuad( - depletedTextureLocation, -iconSizeHalf, -iconSizeHalf, iconSize, iconSize, 0xFFFFFF, 255); + depletedTextureLocation, + -iconSizeHalf, + -iconSizeHalf, + iconSize, + iconSize, + 0xFFFFFF, + 255); } } - if (gui != null - && scale >= Utils.journeyMapScaleToLinear(Config.minZoomLevelForOreLabel) + if (gui != null && scale >= Utils.journeyMapScaleToLinear(Config.minZoomLevelForOreLabel) && !oreVeinLocation.isDepleted()) { final int fontColor = oreVeinLocation.drawSearchHighlight() ? 0xFFFFFFFF : 0xFF7F7F7F; String text = I18n.format(oreVeinLocation.getName()); DrawUtils.drawSimpleLabel( - gui, text, 0, -iconSizeHalf - gui.mc.fontRenderer.FONT_HEIGHT - 5, fontColor, 0xB4000000, true); + gui, + text, + 0, + -iconSizeHalf - gui.mc.fontRenderer.FONT_HEIGHT - 5, + fontColor, + 0xB4000000, + true); } if (oreVeinLocation.isActiveAsWaypoint()) { final double thickness = iconSize / 8; final int color = 0xFFFFD700; DrawUtils.drawGradientRect( - -iconSizeHalf - thickness, -iconSizeHalf - thickness, iconSizeHalf, -iconSizeHalf, 0, color, color); + -iconSizeHalf - thickness, + -iconSizeHalf - thickness, + iconSizeHalf, + -iconSizeHalf, + 0, + color, + color); DrawUtils.drawGradientRect( - iconSizeHalf, -iconSizeHalf - thickness, iconSizeHalf + thickness, iconSizeHalf, 0, color, color); + iconSizeHalf, + -iconSizeHalf - thickness, + iconSizeHalf + thickness, + iconSizeHalf, + 0, + color, + color); DrawUtils.drawGradientRect( - -iconSizeHalf, iconSizeHalf, iconSizeHalf + thickness, iconSizeHalf + thickness, 0, color, color); + -iconSizeHalf, + iconSizeHalf, + iconSizeHalf + thickness, + iconSizeHalf + thickness, + 0, + color, + color); DrawUtils.drawGradientRect( - -iconSizeHalf - thickness, -iconSizeHalf, -iconSizeHalf, iconSizeHalf + thickness, 0, color, color); + -iconSizeHalf - thickness, + -iconSizeHalf, + -iconSizeHalf, + iconSizeHalf + thickness, + 0, + color, + color); } GL11.glPopMatrix(); @@ -113,8 +158,8 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal GL11.glPushMatrix(); - DrawUtils.drawSimpleTooltip( - gui, tooltip, mouseX / scaleAdj + 6, mouseY / scaleAdj - 12, 0xFFFFFFFF, 0x86000000); + DrawUtils + .drawSimpleTooltip(gui, tooltip, mouseX / scaleAdj + 6, mouseY / scaleAdj - 12, 0xFFFFFFFF, 0x86000000); GL11.glPopMatrix(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java index 4e9927af..2c4be5ca 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java @@ -1,8 +1,10 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; import javax.annotation.Nullable; + import net.minecraft.client.gui.GuiScreen; public interface RenderStep { + void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double scale); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java index ea5d0f5c..24f43d45 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java @@ -1,23 +1,29 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.integration.DrawUtils; -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; -import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; import javax.annotation.Nullable; + import net.minecraft.client.gui.GuiScreen; import net.minecraft.util.ResourceLocation; + import org.lwjgl.opengl.GL11; + import thaumcraft.api.aspects.Aspect; import thaumcraft.client.lib.UtilsFX; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.integration.DrawUtils; +import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; +import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; +import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; + public class ThaumcraftNodeRenderStep implements InteractableRenderStep { - private static final ResourceLocation markedTextureLocation = - new ResourceLocation(Tags.MODID, "textures/node_marked.png"); - private static final ResourceLocation unmarkedTextureLocation = - new ResourceLocation(Tags.MODID, "textures/node_unmarked.png"); + private static final ResourceLocation markedTextureLocation = new ResourceLocation( + Tags.MODID, + "textures/node_marked.png"); + private static final ResourceLocation unmarkedTextureLocation = new ResourceLocation( + Tags.MODID, + "textures/node_unmarked.png"); private final ThaumcraftNodeLocation thaumcraftNodeLocation; @@ -40,7 +46,9 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double GL11.glPushMatrix(); GL11.glTranslated( - thaumcraftNodeLocation.getBlockX() - cameraX, thaumcraftNodeLocation.getBlockZ() - cameraZ, 0); + thaumcraftNodeLocation.getBlockX() - cameraX, + thaumcraftNodeLocation.getBlockZ() - cameraZ, + 0); GL11.glScaled(1 / scaleForGui, 1 / scaleForGui, 1); final int alpha = 204; @@ -83,7 +91,8 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal int maxTextWidth = Math.max( Math.max( - gui.mc.fontRenderer.getStringWidth(title), gui.mc.fontRenderer.getStringWidth(nodeDescription)), + gui.mc.fontRenderer.getStringWidth(title), + gui.mc.fontRenderer.getStringWidth(nodeDescription)), gui.mc.fontRenderer.getStringWidth(deleteHint)); if (isWaypoint) { maxTextWidth = Math.max(maxTextWidth, gui.mc.fontRenderer.getStringWidth(asWaypoint)); @@ -92,8 +101,8 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal maxTextWidth = (int) Math.ceil(maxTextWidth * 1.25f); } - final int aspectRows = - (thaumcraftNodeLocation.getAspects().size() + 4) / 5; // Equivalent to Math.ceil(size / 5) + final int aspectRows = (thaumcraftNodeLocation.getAspects().size() + 4) / 5; // Equivalent to Math.ceil(size / + // 5) final int aspectColumns = Math.min(thaumcraftNodeLocation.getAspects().size(), 5); int pixelX = (int) (mouseX + 12); @@ -112,7 +121,12 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal // Draw background final int backgroundColor = 0xF0100010; DrawUtils.drawGradientRect( - pixelX - 3, pixelY - 4, pixelX + tooltipWidth + 3, pixelY - 3, backgroundColor, backgroundColor); + pixelX - 3, + pixelY - 4, + pixelX + tooltipWidth + 3, + pixelY - 3, + backgroundColor, + backgroundColor); DrawUtils.drawGradientRect( pixelX - 3, pixelY + tooltipHeight + 3, @@ -128,7 +142,12 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal backgroundColor, backgroundColor); DrawUtils.drawGradientRect( - pixelX - 4, pixelY - 3, pixelX - 3, pixelY + tooltipHeight + 3, backgroundColor, backgroundColor); + pixelX - 4, + pixelY - 3, + pixelX - 3, + pixelY + tooltipHeight + 3, + backgroundColor, + backgroundColor); DrawUtils.drawGradientRect( pixelX + tooltipWidth + 3, pixelY - 3, @@ -150,7 +169,10 @@ public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scal offset += 12; final int nodeDescriptonWidth = (int) Math.ceil(gui.mc.fontRenderer.getStringWidth(nodeDescription) * 1.1f); gui.mc.fontRenderer.drawString( - nodeDescription, pixelX + nodeDescriptonWidth - titleWidth, pixelY + offset, 0xFFFFFFFF); + nodeDescription, + pixelX + nodeDescriptonWidth - titleWidth, + pixelY + offset, + 0xFFFFFFFF); final int deleteHintWidth = (int) Math.ceil(gui.mc.fontRenderer.getStringWidth(deleteHint) * 1.1f); gui.mc.fontRenderer.drawString( diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java index 9412107d..47e477ef 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java @@ -1,15 +1,19 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; +import javax.annotation.Nullable; + +import net.minecraft.client.gui.GuiScreen; + +import org.lwjgl.opengl.GL11; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.DrawUtils; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -import javax.annotation.Nullable; -import net.minecraft.client.gui.GuiScreen; -import org.lwjgl.opengl.GL11; public class UndergroundFluidChunkRenderStep implements RenderStep { + private final UndergroundFluidChunkLocation undergroundFluidChunkLocation; public UndergroundFluidChunkRenderStep(UndergroundFluidChunkLocation location) { @@ -34,7 +38,7 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double 0); float alpha = ((float) (undergroundFluidChunkLocation.getFluidAmount() - - undergroundFluidChunkLocation.getMinAmountInField())) + - undergroundFluidChunkLocation.getMinAmountInField())) / (undergroundFluidChunkLocation.getMaxAmountInField() - undergroundFluidChunkLocation.getMinAmountInField() + 1); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java index 587b396b..bb0153ff 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java @@ -1,12 +1,15 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.DrawUtils; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; import javax.annotation.Nullable; + import net.minecraft.client.gui.GuiScreen; + import org.lwjgl.opengl.GL11; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.DrawUtils; +import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; + public class UndergroundFluidRenderStep implements RenderStep { private final UndergroundFluidLocation undergroundFluidLocation; @@ -37,7 +40,9 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double // min scale that journeymap can go to if (scale >= 1 && gui != null) { GL11.glScaled(1 / scale, 1 / scale, 1); - final String label = undergroundFluidLocation.getMinProduction() + "L - " + maxAmountInField + "L " + final String label = undergroundFluidLocation.getMinProduction() + "L - " + + maxAmountInField + + "L " + undergroundFluidLocation.getFluid().getLocalizedName(); DrawUtils.drawSimpleLabel(gui, label, VP.chunkWidth * scale, 0, 0xFFFFFFFF, 0xB4000000, false); } diff --git a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java index a2cae21e..59a1a3d3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java +++ b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java @@ -1,13 +1,7 @@ package com.sinthoras.visualprospecting.item; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.TransferCache; -import com.sinthoras.visualprospecting.task.SnapshotDownloadTask; -import com.sinthoras.visualprospecting.task.SnapshotUploadTask; -import com.sinthoras.visualprospecting.task.TaskManager; -import gregtech.api.GregTech_API; import java.util.List; + import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -19,6 +13,14 @@ import net.minecraft.util.IChatComponent; import net.minecraft.world.World; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.TransferCache; +import com.sinthoras.visualprospecting.task.SnapshotDownloadTask; +import com.sinthoras.visualprospecting.task.SnapshotUploadTask; +import com.sinthoras.visualprospecting.task.TaskManager; +import gregtech.api.GregTech_API; + public class ProspectorsLog extends Item { public static ProspectorsLog instance; @@ -35,8 +37,7 @@ public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer play if (isFilledLog(item) == false) { final NBTTagCompound compound = new NBTTagCompound(); compound.setString(Tags.PROSPECTORSLOG_AUTHOR, player.getDisplayName()); - compound.setString( - Tags.PROSPECTORSLOG_AUTHOR_ID, player.getPersistentID().toString()); + compound.setString(Tags.PROSPECTORSLOG_AUTHOR_ID, player.getPersistentID().toString()); item.setTagCompound(compound); if (world.isRemote) { TaskManager.instance.addTask(new SnapshotUploadTask()); @@ -50,8 +51,8 @@ public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer play player.addChatMessage(notification); player.destroyCurrentEquippedItem(); } else { - final IChatComponent notification = - new ChatComponentTranslation("item.visualprospecting.prospectorslog.creation.begin"); + final IChatComponent notification = new ChatComponentTranslation( + "item.visualprospecting.prospectorslog.creation.begin"); notification.getChatStyle().setItalic(true); notification.getChatStyle().setColor(EnumChatFormatting.GRAY); player.addChatMessage(notification); @@ -61,8 +62,8 @@ public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer play final NBTTagCompound compound = item.getTagCompound(); final String authorUuid = compound.getString(Tags.PROSPECTORSLOG_AUTHOR_ID); if (authorUuid.equals(player.getPersistentID().toString()) == false) { - final int random = VP.randomGeneration.nextInt( - TransferCache.instance.isClientDataAvailable(authorUuid) ? 1000 : 5); + final int random = VP.randomGeneration + .nextInt(TransferCache.instance.isClientDataAvailable(authorUuid) ? 1000 : 5); if (random < 5) { final String localizationKey = "item.visualprospecting.prospectorslog.reading.fail" + random; final IChatComponent notification = new ChatComponentTranslation(localizationKey); @@ -71,8 +72,8 @@ public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer play player.addChatMessage(notification); player.destroyCurrentEquippedItem(); } else { - final IChatComponent notification = - new ChatComponentTranslation("item.visualprospecting.prospectorslog.reading.begin"); + final IChatComponent notification = new ChatComponentTranslation( + "item.visualprospecting.prospectorslog.reading.begin"); notification.getChatStyle().setItalic(true); notification.getChatStyle().setColor(EnumChatFormatting.GRAY); player.addChatMessage(notification); @@ -87,8 +88,10 @@ public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer play public void addInformation(ItemStack item, EntityPlayer player, List infoList, boolean ignored) { if (isFilledLog(item)) { final NBTTagCompound compound = item.getTagCompound(); - infoList.add(I18n.format( - "item.visualprospecting.prospectorslog.author", compound.getString(Tags.PROSPECTORSLOG_AUTHOR))); + infoList.add( + I18n.format( + "item.visualprospecting.prospectorslog.author", + compound.getString(Tags.PROSPECTORSLOG_AUTHOR))); } else { infoList.add(I18n.format("item.visualprospecting.prospectorslog.empty")); } @@ -96,8 +99,7 @@ public void addInformation(ItemStack item, EntityPlayer player, List infoList, b private boolean isFilledLog(ItemStack item) { final NBTTagCompound compound = item.getTagCompound(); - return compound != null - && compound.hasKey(Tags.PROSPECTORSLOG_AUTHOR) + return compound != null && compound.hasKey(Tags.PROSPECTORSLOG_AUTHOR) && compound.hasKey(Tags.PROSPECTORSLOG_AUTHOR_ID); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java index 1a54a184..71f9a2cf 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java @@ -2,10 +2,11 @@ import static com.sinthoras.visualprospecting.mixinplugin.TargetedMod.*; -import cpw.mods.fml.relauncher.FMLLaunchHandler; import java.util.Arrays; import java.util.List; +import cpw.mods.fml.relauncher.FMLLaunchHandler; + public enum Mixin { // @@ -57,10 +58,8 @@ public enum Mixin { } public boolean shouldLoad(List loadedMods) { - return (side == Side.BOTH - || side == Side.SERVER && FMLLaunchHandler.side().isServer() - || side == Side.CLIENT && FMLLaunchHandler.side().isClient()) - && loadedMods.containsAll(targetedMods); + return (side == Side.BOTH || side == Side.SERVER && FMLLaunchHandler.side().isServer() + || side == Side.CLIENT && FMLLaunchHandler.side().isClient()) && loadedMods.containsAll(targetedMods); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java index 864694fe..6517aeef 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java @@ -3,7 +3,6 @@ import static com.sinthoras.visualprospecting.mixinplugin.TargetedMod.VANILLA; import static java.nio.file.Files.walk; -import com.sinthoras.visualprospecting.Tags; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -13,14 +12,19 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; + import net.minecraft.launchwrapper.Launch; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; import org.spongepowered.libraries.org.objectweb.asm.tree.ClassNode; + import ru.timeconqueror.spongemixins.MinecraftURLClassPath; +import com.sinthoras.visualprospecting.Tags; + public class MixinPlugin implements IMixinConfigPlugin { private static final Logger LOG = LogManager.getLogger(Tags.MODID + " mixins"); @@ -91,11 +95,7 @@ private boolean loadJarOf(final TargetedMod mod) { public static File findJarOf(final TargetedMod mod) { try { - return walk(MODS_DIRECTORY_PATH) - .filter(mod::isMatchingJar) - .map(Path::toFile) - .findFirst() - .orElse(null); + return walk(MODS_DIRECTORY_PATH).filter(mod::isMatchingJar).map(Path::toFile).findFirst().orElse(null); } catch (IOException e) { e.printStackTrace(); return null; diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java index dcacd941..8964b0ff 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java @@ -1,8 +1,9 @@ package com.sinthoras.visualprospecting.mixinplugin; -import com.google.common.io.Files; import java.nio.file.Path; +import com.google.common.io.Files; + public enum TargetedMod { // @@ -46,7 +47,11 @@ public boolean isMatchingJar(Path path) { @Override public String toString() { return "TargetedMod{" + "modName='" - + modName + '\'' + ", jarNamePrefixLowercase='" - + jarNamePrefixLowercase + '\'' + '}'; + + modName + + '\'' + + ", jarNamePrefixLowercase='" + + jarNamePrefixLowercase + + '\'' + + '}'; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java index a5b415c0..ef45c7e1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java @@ -1,40 +1,40 @@ package com.sinthoras.visualprospecting.mixins.bartworks; -import com.github.bartimaeusnek.bartworks.system.oregen.BW_OreLayer; -import com.github.bartimaeusnek.bartworks.system.oregen.BW_WordGenerator; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.database.ServerCache; import java.util.Random; + import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import com.github.bartimaeusnek.bartworks.system.oregen.BW_OreLayer; +import com.github.bartimaeusnek.bartworks.system.oregen.BW_WordGenerator; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.database.ServerCache; + @Mixin(BW_WordGenerator.WorldGenContainer.class) public class WorldGenContainerMixin { @Redirect( method = "run", - at = - @At( - value = "INVOKE", - target = - "Lcom/github/bartimaeusnek/bartworks/system/oregen/BW_OreLayer;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), + at = @At( + value = "INVOKE", + target = "Lcom/github/bartimaeusnek/bartworks/system/oregen/BW_OreLayer;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), remap = false, require = 1) - private boolean onOreVeinGenerationAttempt( - BW_OreLayer worldGen, - World world, - Random random, - String biome, - int dimensionType, - int blockX, - int blockZ, - IChunkProvider chunkGenerator, - IChunkProvider chunkProvider) { + private boolean onOreVeinGenerationAttempt(BW_OreLayer worldGen, World world, Random random, String biome, + int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { final boolean oreVeinPlaced = worldGen.executeWorldgen( - world, random, biome, Integer.MIN_VALUE, blockX, blockZ, chunkGenerator, chunkProvider); + world, + random, + biome, + Integer.MIN_VALUE, + blockX, + blockZ, + chunkGenerator, + chunkProvider); if (oreVeinPlaced) { ServerCache.instance.notifyOreVeinGeneration( world.provider.dimensionId, diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java index 88867dd8..8cb95861 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java @@ -1,40 +1,41 @@ package com.sinthoras.visualprospecting.mixins.galacticgreg; -import bloodasp.galacticgreg.GT_Worldgenerator_Space; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.database.ServerCache; -import gregtech.api.world.GT_Worldgen; import java.util.Random; + import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import bloodasp.galacticgreg.GT_Worldgenerator_Space; + +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.database.ServerCache; +import gregtech.api.world.GT_Worldgen; + @Mixin(GT_Worldgenerator_Space.class) public class GT_Worldgenerator_SpaceMixin { @Redirect( method = "Generate_OreVeins", - at = - @At( - value = "INVOKE", - target = - "Lgregtech/api/world/GT_Worldgen;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), + at = @At( + value = "INVOKE", + target = "Lgregtech/api/world/GT_Worldgen;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), remap = false, require = 1) - private boolean onOreVeinGenerated( - GT_Worldgen worldGen, - World world, - Random random, - String biome, - int dimensionType, - int blockX, - int blockZ, - IChunkProvider chunkGenerator, - IChunkProvider chunkProvider) { + private boolean onOreVeinGenerated(GT_Worldgen worldGen, World world, Random random, String biome, + int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { final boolean oreVeinPlaced = worldGen.executeWorldgen( - world, random, biome, Integer.MIN_VALUE, blockX, blockZ, chunkGenerator, chunkProvider); + world, + random, + biome, + Integer.MIN_VALUE, + blockX, + blockZ, + chunkGenerator, + chunkProvider); if (oreVeinPlaced) { ServerCache.instance.notifyOreVeinGeneration( world.provider.dimensionId, diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java index 0e5d9cef..6da23a61 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java @@ -1,12 +1,15 @@ package com.sinthoras.visualprospecting.mixins.gregtech; -import com.sinthoras.visualprospecting.database.ClientCache; -import gregtech.api.items.GT_Generic_Block; -import gregtech.common.blocks.GT_Block_Ores_Abstract; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.world.World; + import org.spongepowered.asm.mixin.Mixin; +import com.sinthoras.visualprospecting.database.ClientCache; + +import gregtech.api.items.GT_Generic_Block; +import gregtech.common.blocks.GT_Block_Ores_Abstract; + @Mixin(value = GT_Block_Ores_Abstract.class, remap = false) public class GT_Block_Ores_AbstractMixin extends GT_Generic_Block { @@ -15,16 +18,8 @@ protected GT_Block_Ores_AbstractMixin() { } @Override - public boolean onBlockActivated( - World world, - int blockX, - int blockY, - int blockZ, - EntityPlayer player, - int side, - float offsetX, - float offsetY, - float offsetZ) { + public boolean onBlockActivated(World world, int blockX, int blockY, int blockZ, EntityPlayer player, int side, + float offsetX, float offsetY, float offsetZ) { ClientCache.instance.onOreInteracted(world, blockX, blockY, blockZ, player); return super.onBlockActivated(world, blockX, blockY, blockZ, player, side, offsetX, offsetY, offsetZ); } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java index 11b7368d..25538b22 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java @@ -3,12 +3,25 @@ import static gregtech.api.util.GT_Utility.ItemNBT.getNBT; import static gregtech.api.util.GT_Utility.ItemNBT.setNBT; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + import com.sinthoras.visualprospecting.ServerTranslations; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; + import gregtech.api.enums.ItemList; import gregtech.api.enums.Materials; import gregtech.api.interfaces.ITexture; @@ -17,15 +30,6 @@ import gregtech.api.util.GT_Utility; import gregtech.common.tileentities.machines.basic.GT_MetaTileEntity_AdvSeismicProspector; import ic2.core.Ic2Items; -import java.util.List; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Blocks; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; @Mixin(value = GT_MetaTileEntity_AdvSeismicProspector.class, remap = false) public abstract class GT_MetaTileEntity_AdvSeismicProspectorMixin extends GT_MetaTileEntity_BasicMachine { @@ -50,68 +54,69 @@ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlaye if (aBaseMetaTileEntity.isServerSide()) { ItemStack aStack = aPlayer.getCurrentEquippedItem(); - if (!ready - && (GT_Utility.consumeItems(aPlayer, aStack, Item.getItemFromBlock(Blocks.tnt), 16) - || GT_Utility.consumeItems(aPlayer, aStack, Ic2Items.industrialTnt.getItem(), 8) - || GT_Utility.consumeItems(aPlayer, aStack, Materials.Glyceryl, 4) - || GT_Utility.consumeItems(aPlayer, aStack, ItemList.Block_Powderbarrel.getItem(), 2))) { + if (!ready && (GT_Utility.consumeItems(aPlayer, aStack, Item.getItemFromBlock(Blocks.tnt), 16) + || GT_Utility.consumeItems(aPlayer, aStack, Ic2Items.industrialTnt.getItem(), 8) + || GT_Utility.consumeItems(aPlayer, aStack, Materials.Glyceryl, 4) + || GT_Utility.consumeItems(aPlayer, aStack, ItemList.Block_Powderbarrel.getItem(), 2))) { this.ready = true; this.mMaxProgresstime = (aPlayer.capabilities.isCreativeMode ? 20 : 800); - } else if (ready - && mMaxProgresstime == 0 + } else if (ready && mMaxProgresstime == 0 && aStack != null && aStack.stackSize == 1 && aStack.getItem() == ItemList.Tool_DataStick.getItem()) { - this.ready = false; - - final NBTTagCompound compound = getNBT(aStack); - compound.setString(Tags.BOOK_TITLE, "Raw Prospection Data"); - compound.setBoolean(Tags.VISUALPROSPECTING_FLAG, true); - compound.setByte(Tags.PROSPECTION_TIER, mTier); - compound.setInteger( - Tags.PROSPECTION_DIMENSION_ID, getBaseMetaTileEntity().getWorld().provider.dimensionId); - compound.setInteger( - Tags.PROSPECTION_BLOCK_X, getBaseMetaTileEntity().getXCoord()); - compound.setInteger( - Tags.PROSPECTION_BLOCK_Y, getBaseMetaTileEntity().getYCoord()); - compound.setInteger( - Tags.PROSPECTION_BLOCK_Z, getBaseMetaTileEntity().getZCoord()); - compound.setInteger(Tags.PROSPECTION_ORE_RADIUS, radius); - - final List undergroundFluidPositions = - ServerCache.instance.prospectUndergroundFluidBlockRadius( - aPlayer.worldObj, - getBaseMetaTileEntity().getXCoord(), - getBaseMetaTileEntity().getZCoord(), - VP.undergroundFluidChunkProspectingBlockRadius); - compound.setInteger(Tags.PROSPECTION_NUMBER_OF_UNDERGROUND_FLUID, undergroundFluidPositions.size()); - - String[] fluidStrings = new String[9]; - final int minUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk( - getBaseMetaTileEntity().getXCoord() - VP.undergroundFluidChunkProspectingBlockRadius)); - final int minUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk( - getBaseMetaTileEntity().getZCoord() - VP.undergroundFluidChunkProspectingBlockRadius)); - for (UndergroundFluidPosition undergroundFluidPosition : undergroundFluidPositions) { - final int offsetUndergroundFluidX = - (Utils.mapToCornerUndergroundFluidChunkCoord(undergroundFluidPosition.chunkX) - - minUndergroundFluidX) - >> 3; - final int offsetUndergroundFluidZ = - (Utils.mapToCornerUndergroundFluidChunkCoord(undergroundFluidPosition.chunkZ) - - minUndergroundFluidZ) - >> 3; - final int undergroundFluidBookId = offsetUndergroundFluidX + offsetUndergroundFluidZ * 3; - fluidStrings[undergroundFluidBookId] = - "" + undergroundFluidBookId + ": " + undergroundFluidPosition.getMinProduction() + "-" - + undergroundFluidPosition.getMaxProduction() + " " + this.ready = false; + + final NBTTagCompound compound = getNBT(aStack); + compound.setString(Tags.BOOK_TITLE, "Raw Prospection Data"); + compound.setBoolean(Tags.VISUALPROSPECTING_FLAG, true); + compound.setByte(Tags.PROSPECTION_TIER, mTier); + compound.setInteger( + Tags.PROSPECTION_DIMENSION_ID, + getBaseMetaTileEntity().getWorld().provider.dimensionId); + compound.setInteger(Tags.PROSPECTION_BLOCK_X, getBaseMetaTileEntity().getXCoord()); + compound.setInteger(Tags.PROSPECTION_BLOCK_Y, getBaseMetaTileEntity().getYCoord()); + compound.setInteger(Tags.PROSPECTION_BLOCK_Z, getBaseMetaTileEntity().getZCoord()); + compound.setInteger(Tags.PROSPECTION_ORE_RADIUS, radius); + + final List undergroundFluidPositions = ServerCache.instance + .prospectUndergroundFluidBlockRadius( + aPlayer.worldObj, + getBaseMetaTileEntity().getXCoord(), + getBaseMetaTileEntity().getZCoord(), + VP.undergroundFluidChunkProspectingBlockRadius); + compound.setInteger( + Tags.PROSPECTION_NUMBER_OF_UNDERGROUND_FLUID, + undergroundFluidPositions.size()); + + String[] fluidStrings = new String[9]; + final int minUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord( + Utils.coordBlockToChunk( + getBaseMetaTileEntity().getXCoord() + - VP.undergroundFluidChunkProspectingBlockRadius)); + final int minUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord( + Utils.coordBlockToChunk( + getBaseMetaTileEntity().getZCoord() + - VP.undergroundFluidChunkProspectingBlockRadius)); + for (UndergroundFluidPosition undergroundFluidPosition : undergroundFluidPositions) { + final int offsetUndergroundFluidX = (Utils.mapToCornerUndergroundFluidChunkCoord( + undergroundFluidPosition.chunkX) - minUndergroundFluidX) >> 3; + final int offsetUndergroundFluidZ = (Utils.mapToCornerUndergroundFluidChunkCoord( + undergroundFluidPosition.chunkZ) - minUndergroundFluidZ) >> 3; + final int undergroundFluidBookId = offsetUndergroundFluidX + offsetUndergroundFluidZ * 3; + fluidStrings[undergroundFluidBookId] = "" + undergroundFluidBookId + + ": " + + undergroundFluidPosition.getMinProduction() + + "-" + + undergroundFluidPosition.getMaxProduction() + + " " + ServerTranslations.getEnglishLocalization(undergroundFluidPosition.fluid); - } - compound.setString(Tags.PROSPECTION_FLUIDS, String.join("|", fluidStrings)); + } + compound.setString(Tags.PROSPECTION_FLUIDS, String.join("|", fluidStrings)); - setNBT(aStack, compound); - } + setNBT(aStack, compound); + } } return true; } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java index d3ad46d5..634afcf3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java @@ -2,24 +2,28 @@ import static gregtech.api.util.GT_Utility.ItemNBT.setNBT; -import com.sinthoras.visualprospecting.ServerTranslations; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.database.OreVeinPosition; -import com.sinthoras.visualprospecting.database.ServerCache; -import gregtech.api.interfaces.ITexture; -import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine; -import gregtech.api.util.GT_Utility; -import gregtech.common.tileentities.machines.basic.GT_MetaTileEntity_Scanner; import java.util.List; + import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagString; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import com.sinthoras.visualprospecting.ServerTranslations; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.database.ServerCache; + +import gregtech.api.interfaces.ITexture; +import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine; +import gregtech.api.util.GT_Utility; +import gregtech.common.tileentities.machines.basic.GT_MetaTileEntity_Scanner; + @Mixin(value = GT_MetaTileEntity_Scanner.class, remap = false) public abstract class GT_MetaTileEntity_ScannerMixin extends GT_MetaTileEntity_BasicMachine { @@ -29,11 +33,9 @@ public GT_MetaTileEntity_ScannerMixin() { @Inject( method = "checkRecipe", - at = - @At( - value = "INVOKE", - target = - "Lgregtech/api/util/GT_Utility$ItemNBT;convertProspectionData(Lnet/minecraft/item/ItemStack;)V"), + at = @At( + value = "INVOKE", + target = "Lgregtech/api/util/GT_Utility$ItemNBT;convertProspectionData(Lnet/minecraft/item/ItemStack;)V"), remap = false, require = 1, cancellable = true) @@ -51,20 +53,24 @@ private void onAnalyzeProspectionData(CallbackInfoReturnable callbackIn final NBTTagList bookPages = new NBTTagList(); - final String frontPage = "Prospector report\n" - + position + "\n\n" - + "Fluids: " + numberOfUndergroundFluids + "\n\n" - + "Ores within " + blockRadius + " blocks\n\n" + final String frontPage = "Prospector report\n" + position + + "\n\n" + + "Fluids: " + + numberOfUndergroundFluids + + "\n\n" + + "Ores within " + + blockRadius + + " blocks\n\n" + "Location is center of orevein\n\n" + "Results are synchronized to your map"; bookPages.appendTag(new NBTTagString(frontPage)); - final List foundOreVeins = - ServerCache.instance.prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); + final List foundOreVeins = ServerCache.instance + .prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); if (foundOreVeins.isEmpty() == false) { final int pageSize = 7; - final int numberOfPages = - (foundOreVeins.size() + pageSize) / pageSize; // Equals to ceil((foundOreVeins.size()) + final int numberOfPages = (foundOreVeins.size() + pageSize) / pageSize; // Equals to + // ceil((foundOreVeins.size()) for (int pageNumber = 0; pageNumber < numberOfPages; pageNumber++) { final StringBuilder pageString = new StringBuilder(); @@ -72,19 +78,14 @@ private void onAnalyzeProspectionData(CallbackInfoReturnable callbackIn final int veinId = pageNumber * pageSize + i; if (veinId < foundOreVeins.size()) { final OreVeinPosition oreVein = foundOreVeins.get(veinId); - pageString - .append(oreVein.getBlockX()) - .append(",") - .append(oreVein.getBlockZ()) - .append(" - ") - .append(ServerTranslations.getEnglishLocalization(oreVein.veinType)) - .append("\n"); + pageString.append(oreVein.getBlockX()).append(",").append(oreVein.getBlockZ()).append(" - ") + .append(ServerTranslations.getEnglishLocalization(oreVein.veinType)).append("\n"); } } - String pageCounter = - numberOfPages > 1 ? String.format(" %d/%d", pageNumber + 1, numberOfPages) : ""; - NBTTagString pageTag = - new NBTTagString(String.format("Ore Veins %s\n\n", pageCounter) + pageString); + String pageCounter = numberOfPages > 1 ? String.format(" %d/%d", pageNumber + 1, numberOfPages) + : ""; + NBTTagString pageTag = new NBTTagString( + String.format("Ore Veins %s\n\n", pageCounter) + pageString); bookPages.appendTag(pageTag); } } @@ -97,18 +98,23 @@ private void onAnalyzeProspectionData(CallbackInfoReturnable callbackIn 9, compound.getString(Tags.PROSPECTION_FLUIDS).split("\\|")); - final String fluidCoverPage = "Fluid notes\n\n" - + "Prospects from NW to SE 576 chunks" - + "(9 8x8 fields)\n around and gives min-max amount" + "\n\n" - + "[1][2][3]" + "\n" - + "[4][5][6]" + "\n" - + "[7][8][9]" + "\n" + final String fluidCoverPage = "Fluid notes\n\n" + "Prospects from NW to SE 576 chunks" + + "(9 8x8 fields)\n around and gives min-max amount" + + "\n\n" + + "[1][2][3]" + + "\n" + + "[4][5][6]" + + "\n" + + "[7][8][9]" + + "\n" + "\n" + "[5] - Prospector in this 8x8 area"; bookPages.appendTag(new NBTTagString(fluidCoverPage)); - String tFluidsPosStr = "X: " + Math.floorDiv(blockX, 16 * 8) * 16 * 8 + " Z: " - + Math.floorDiv(blockZ, 16 * 8) * 16 * 8 + "\n"; + String tFluidsPosStr = "X: " + Math.floorDiv(blockX, 16 * 8) * 16 * 8 + + " Z: " + + Math.floorDiv(blockZ, 16 * 8) * 16 * 8 + + "\n"; int xOff = blockX - Math.floorDiv(blockX, 16 * 8) * 16 * 8; xOff = xOff / 16; int xOffRemain = 7 - xOff; @@ -133,10 +139,13 @@ private void onAnalyzeProspectionData(CallbackInfoReturnable callbackIn for (; zOffRemain > 0; zOffRemain--) { tFluidsPosStr = tFluidsPosStr.concat("--------\n"); } - tFluidsPosStr = tFluidsPosStr.concat(" X: " + (Math.floorDiv(blockX, 16 * 8) + 1) * 16 * 8 - + " Z: " + (Math.floorDiv(blockZ, 16 * 8) + 1) * 16 * 8); // +1 field to find bottomright of [5] - final String fluidsPage = - "Corners of [5] are \n" + tFluidsPosStr + "\n" + "P - Prospector in 8x8 field"; + tFluidsPosStr = tFluidsPosStr.concat( + " X: " + (Math.floorDiv(blockX, 16 * 8) + 1) * 16 * 8 + + " Z: " + + (Math.floorDiv(blockZ, 16 * 8) + 1) * 16 * 8); // +1 field to find bottomright of [5] + final String fluidsPage = "Corners of [5] are \n" + tFluidsPosStr + + "\n" + + "P - Prospector in 8x8 field"; bookPages.appendTag(new NBTTagString(fluidsPage)); } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java index ff350452..353b25d4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java @@ -1,40 +1,33 @@ package com.sinthoras.visualprospecting.mixins.gregtech; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.database.ServerCache; -import gregtech.common.GT_Worldgen_GT_Ore_Layer; -import gregtech.common.GT_Worldgenerator; import java.util.Random; + import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.database.ServerCache; + +import gregtech.common.GT_Worldgen_GT_Ore_Layer; +import gregtech.common.GT_Worldgenerator; + @Mixin(GT_Worldgenerator.WorldGenContainer.class) public class WorldGenContainerMixin { // Redirect both calls to ensure that Bartworks ore veins are captured as well @Redirect( method = "worldGenFindVein", - at = - @At( - value = "INVOKE", - target = - "Lgregtech/common/GT_Worldgen_GT_Ore_Layer;executeWorldgenChunkified(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIIIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)I"), + at = @At( + value = "INVOKE", + target = "Lgregtech/common/GT_Worldgen_GT_Ore_Layer;executeWorldgenChunkified(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIIIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)I"), remap = false, require = 2) - protected int onOreVeinPlaced( - GT_Worldgen_GT_Ore_Layer instance, - World aWorld, - Random aRandom, - String aBiome, - int aDimensionType, - int aChunkX, - int aChunkZ, - int aSeedX, - int aSeedZ, - IChunkProvider aChunkGenerator, + protected int onOreVeinPlaced(GT_Worldgen_GT_Ore_Layer instance, World aWorld, Random aRandom, String aBiome, + int aDimensionType, int aChunkX, int aChunkZ, int aSeedX, int aSeedZ, IChunkProvider aChunkGenerator, IChunkProvider aChunkProvider) { final int result = instance.executeWorldgenChunkified( aWorld, diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java index baee57e7..9919b0db 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java @@ -1,13 +1,14 @@ package com.sinthoras.visualprospecting.mixins.journeymap; -import com.sinthoras.visualprospecting.integration.journeymap.ResetClientCacheConfirmation; import journeymap.client.ui.UIManager; import journeymap.client.ui.component.Button; import journeymap.client.ui.component.ButtonList; import journeymap.client.ui.component.JmUI; import journeymap.client.ui.dialog.FullscreenActions; + import net.minecraft.client.gui.GuiButton; import net.minecraft.client.resources.I18n; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -15,6 +16,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import com.sinthoras.visualprospecting.integration.journeymap.ResetClientCacheConfirmation; + @Mixin(FullscreenActions.class) public abstract class FullscreenActionsMixin extends JmUI { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java index 61538cb2..06885e91 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java @@ -1,13 +1,7 @@ package com.sinthoras.visualprospecting.mixins.journeymap; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.LayerButton; -import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; -import com.sinthoras.visualprospecting.integration.journeymap.render.WaypointProviderLayerRenderer; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; import java.util.List; + import journeymap.client.Constants; import journeymap.client.io.ThemeFileHandler; import journeymap.client.log.LogFormatter; @@ -25,9 +19,11 @@ import journeymap.client.ui.theme.ThemeButton; import journeymap.client.ui.theme.ThemeToggle; import journeymap.client.ui.theme.ThemeToolbar; + import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.renderer.RenderHelper; + import org.apache.logging.log4j.Level; import org.lwjgl.input.Mouse; import org.spongepowered.asm.mixin.Final; @@ -40,6 +36,14 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.libraries.org.objectweb.asm.Opcodes; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; +import com.sinthoras.visualprospecting.integration.journeymap.buttons.LayerButton; +import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; +import com.sinthoras.visualprospecting.integration.journeymap.render.WaypointProviderLayerRenderer; +import com.sinthoras.visualprospecting.integration.model.MapState; +import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; + @Mixin(value = Fullscreen.class, remap = false) public abstract class FullscreenMixin extends JmUI { @@ -108,20 +112,14 @@ private void onConstructed(CallbackInfo callbackInfo) { @Inject( method = "drawMap", - at = - @At( - value = "INVOKE", - target = "Ljourneymap/client/model/MapState;getDrawWaypointSteps()Ljava/util/List;"), + at = @At( + value = "INVOKE", + target = "Ljourneymap/client/model/MapState;getDrawWaypointSteps()Ljava/util/List;"), remap = false, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void onBeforeDrawJourneyMapWaypoints( - CallbackInfo callbackInfo, - boolean refreshReady, - StatTimer timer, - int xOffset, - int yOffset, - float drawScale) { + private void onBeforeDrawJourneyMapWaypoints(CallbackInfo callbackInfo, boolean refreshReady, StatTimer timer, + int xOffset, int yOffset, float drawScale) { final int fontScale = getMapFontScale(); final Minecraft minecraft = Minecraft.getMinecraft(); final int centerBlockX = (int) Math.round(gridRenderer.getCenterBlockX()); @@ -137,19 +135,22 @@ private void onBeforeDrawJourneyMapWaypoints( for (LayerRenderer layerRenderer : JourneyMapState.instance.renderers) { if (layerRenderer.isLayerActive()) { gridRenderer.draw( - layerRenderer.getDrawStepsCachedForRendering(), xOffset, yOffset, drawScale, fontScale, 0.0); + layerRenderer.getDrawStepsCachedForRendering(), + xOffset, + yOffset, + drawScale, + fontScale, + 0.0); } } } @Redirect( method = "initButtons", - at = - @At( - value = "FIELD", - target = - "Ljourneymap/client/ui/fullscreen/Fullscreen;mapTypeToolbar:Ljourneymap/client/ui/theme/ThemeToolbar;", - opcode = Opcodes.PUTFIELD), + at = @At( + value = "FIELD", + target = "Ljourneymap/client/ui/fullscreen/Fullscreen;mapTypeToolbar:Ljourneymap/client/ui/theme/ThemeToolbar;", + opcode = Opcodes.PUTFIELD), remap = false, require = 1) private void OnCreateMapTypeToolbar(Fullscreen owner, ThemeToolbar value) { @@ -157,8 +158,10 @@ private void OnCreateMapTypeToolbar(Fullscreen owner, ThemeToolbar value) { final ButtonList buttonList = new ButtonList(); for (LayerButton layerButton : JourneyMapState.instance.buttons) { - final ThemeToggle button = - new ThemeToggle(theme, layerButton.getButtonTextKey(), layerButton.getIconName()); + final ThemeToggle button = new ThemeToggle( + theme, + layerButton.getButtonTextKey(), + layerButton.getIconName()); layerButton.setButton(button); button.setToggled(layerButton.isActive(), false); button.addToggleListener((unused, toggled) -> { @@ -210,8 +213,7 @@ public void func_73863_a(int width, int height, float f) { if (tooltip == null) { for (LayerRenderer layer : JourneyMapState.instance.renderers) { if (layer instanceof WaypointProviderLayerRenderer) { - final WaypointProviderLayerRenderer waypointProviderLayer = - (WaypointProviderLayerRenderer) layer; + final WaypointProviderLayerRenderer waypointProviderLayer = (WaypointProviderLayerRenderer) layer; if (waypointProviderLayer.isLayerActive()) { tooltip = waypointProviderLayer.getTextTooltip(); } @@ -229,8 +231,7 @@ public void func_73863_a(int width, int height, float f) { } else { for (LayerRenderer layer : JourneyMapState.instance.renderers) { if (layer instanceof WaypointProviderLayerRenderer) { - final WaypointProviderLayerRenderer waypointProviderLayer = - (WaypointProviderLayerRenderer) layer; + final WaypointProviderLayerRenderer waypointProviderLayer = (WaypointProviderLayerRenderer) layer; if (waypointProviderLayer.isLayerActive()) { waypointProviderLayer.drawCustomTooltip(getFontRenderer(), mx, my, this.width, this.height); } @@ -240,7 +241,8 @@ public void func_73863_a(int width, int height, float f) { } catch (Throwable var11) { logger.log( - Level.ERROR, "Unexpected exception in jm.fullscreen.drawScreen(): " + LogFormatter.toString(var11)); + Level.ERROR, + "Unexpected exception in jm.fullscreen.drawScreen(): " + LogFormatter.toString(var11)); UIManager.getInstance().closeAll(); } finally { drawScreenTimer.stop(); @@ -271,8 +273,8 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { final int scaledMouseY = my * mc.displayHeight / height; final double blockSize = Math.pow(2.0D, gridRenderer.getZoom()); if (onMapClicked(mouseButton, scaledMouseX, scaledMouseY, blockSize) == false) { - BlockCoordIntPair blockCoord = gridRenderer.getBlockUnderMouse( - Mouse.getEventX(), Mouse.getEventY(), mc.displayWidth, mc.displayHeight); + BlockCoordIntPair blockCoord = gridRenderer + .getBlockUnderMouse(Mouse.getEventX(), Mouse.getEventY(), mc.displayWidth, mc.displayHeight); layerDelegate.onMouseClicked( mc, Mouse.getEventX(), diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java index b9ae1fa4..e670ca06 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java @@ -1,16 +1,15 @@ package com.sinthoras.visualprospecting.mixins.journeymap; -import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; -import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; import java.lang.reflect.Field; + import journeymap.client.render.draw.DrawStep; import journeymap.client.render.map.GridRenderer; import journeymap.client.ui.minimap.DisplayVars; import journeymap.client.ui.minimap.MiniMap; import journeymap.client.ui.minimap.Shape; + import net.minecraft.client.Minecraft; + import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -19,6 +18,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; +import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; +import com.sinthoras.visualprospecting.integration.model.MapState; +import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; + @Mixin(MiniMap.class) public abstract class MiniMapMixin { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java index 2f846714..0767787a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java @@ -1,16 +1,19 @@ package com.sinthoras.visualprospecting.mixins.journeymap; -import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; -import com.sinthoras.visualprospecting.integration.journeymap.waypoints.WaypointManager; import journeymap.client.model.Waypoint; import journeymap.client.render.ingame.RenderWaypointBeacon; + import net.minecraft.client.Minecraft; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; +import com.sinthoras.visualprospecting.integration.journeymap.waypoints.WaypointManager; + @Mixin(RenderWaypointBeacon.class) public class RenderWaypointBeaconMixin { @@ -24,11 +27,9 @@ static void doRender(Waypoint waypoint) { @Inject( method = "renderAll", - at = - @At( - value = "INVOKE", - target = - "Ljourneymap/client/waypoint/WaypointStore;instance()Ljourneymap/client/waypoint/WaypointStore;"), + at = @At( + value = "INVOKE", + target = "Ljourneymap/client/waypoint/WaypointStore;instance()Ljourneymap/client/waypoint/WaypointStore;"), remap = false, require = 1) private static void onRenderAll(CallbackInfo callbackInfo) { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java index 22c059b6..ceaa6dd4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java @@ -1,15 +1,17 @@ package com.sinthoras.visualprospecting.mixins.journeymap; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; import journeymap.client.ui.waypoint.WaypointManager; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import com.sinthoras.visualprospecting.integration.model.MapState; +import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; +import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; + @Mixin(WaypointManager.class) public class WaypointManagerMixin { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java index 7a4b1640..00c918a6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java @@ -1,6 +1,7 @@ package com.sinthoras.visualprospecting.mixins.minecraft; import net.minecraftforge.client.ForgeHooksClient; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java index 908f917c..6caf2efa 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java @@ -1,26 +1,29 @@ package com.sinthoras.visualprospecting.mixins.minecraft; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.ClientCache; -import com.sinthoras.visualprospecting.database.OreVeinPosition; -import com.sinthoras.visualprospecting.database.ServerCache; -import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; -import com.sinthoras.visualprospecting.network.ProspectingNotification; import java.util.List; + import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemEditableBook; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.ClientCache; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.database.ServerCache; +import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; +import com.sinthoras.visualprospecting.network.ProspectingNotification; + @Mixin(value = ItemEditableBook.class, remap = true) public class ItemEditableBookMixin { @@ -30,10 +33,7 @@ public class ItemEditableBookMixin { remap = true, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void onItemRightClick( - ItemStack itemStack, - World world, - EntityPlayer entityPlayer, + private void onItemRightClick(ItemStack itemStack, World world, EntityPlayer entityPlayer, CallbackInfoReturnable callbackInfoReturnable) { if (!world.isRemote) { final NBTTagCompound compound = itemStack.getTagCompound(); @@ -44,11 +44,14 @@ private void onItemRightClick( final int blockRadius = compound.getInteger(Tags.PROSPECTION_ORE_RADIUS); if (world.provider.dimensionId == dimensionId) { - final List foundOreVeins = - ServerCache.instance.prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); - final List foundUndergroundFluids = - ServerCache.instance.prospectUndergroundFluidBlockRadius( - world, blockX, blockZ, VP.undergroundFluidChunkProspectingBlockRadius); + final List foundOreVeins = ServerCache.instance + .prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); + final List foundUndergroundFluids = ServerCache.instance + .prospectUndergroundFluidBlockRadius( + world, + blockX, + blockZ, + VP.undergroundFluidChunkProspectingBlockRadius); if (Utils.isLogicalClient()) { ClientCache.instance.putOreVeins(foundOreVeins); ClientCache.instance.putUndergroundFluids(foundUndergroundFluids); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java index eb0a99aa..b4e4e108 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java @@ -1,11 +1,8 @@ package com.sinthoras.visualprospecting.mixins.tcnodetracker; -import com.dyonovan.tcnodetracker.gui.GuiMain; -import com.dyonovan.tcnodetracker.lib.AspectLoc; -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.resources.I18n; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -14,6 +11,11 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.libraries.org.objectweb.asm.Opcodes; +import com.dyonovan.tcnodetracker.gui.GuiMain; +import com.dyonovan.tcnodetracker.lib.AspectLoc; +import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; +import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; + @Mixin(GuiMain.class) public class GuiMainMixin { @@ -22,13 +24,12 @@ public class GuiMainMixin { @Inject( method = "actionPerformed", - at = - @At( - value = "FIELD", - target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;zMarker:I", - opcode = Opcodes.PUTSTATIC, - shift = At.Shift.AFTER, - remap = false), + at = @At( + value = "FIELD", + target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;zMarker:I", + opcode = Opcodes.PUTSTATIC, + shift = At.Shift.AFTER, + remap = false), remap = true, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION, @@ -36,25 +37,25 @@ public class GuiMainMixin { private void onWaypointSet(GuiButton button, CallbackInfo callbackInfo, int i) { final AspectLoc aspect = GuiMain.aspectList.get(low + i); GuiMain.aspectList.clear(); - ThaumcraftNodeLayerManager.instance.setActiveWaypoint(new Waypoint( - aspect.x, - aspect.y, - aspect.z, - aspect.dimID, - I18n.format("visualprospecting.tracked", I18n.format("tile.blockAiry.0.name")), - 0xFFFFFF)); + ThaumcraftNodeLayerManager.instance.setActiveWaypoint( + new Waypoint( + aspect.x, + aspect.y, + aspect.z, + aspect.dimID, + I18n.format("visualprospecting.tracked", I18n.format("tile.blockAiry.0.name")), + 0xFFFFFF)); callbackInfo.cancel(); } @Inject( method = "actionPerformed", - at = - @At( - value = "FIELD", - target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;doGui:Z", - opcode = Opcodes.PUTSTATIC, - ordinal = 0, - remap = false), + at = @At( + value = "FIELD", + target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;doGui:Z", + opcode = Opcodes.PUTSTATIC, + ordinal = 0, + remap = false), remap = true, require = 1) private void onWaypointClear(CallbackInfo callbackInfo) { @@ -63,13 +64,12 @@ private void onWaypointClear(CallbackInfo callbackInfo) { @Inject( method = "actionPerformed", - at = - @At( - value = "FIELD", - target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;doGui:Z", - opcode = Opcodes.PUTSTATIC, - ordinal = 1, - remap = false), + at = @At( + value = "FIELD", + target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;doGui:Z", + opcode = Opcodes.PUTSTATIC, + ordinal = 1, + remap = false), remap = true, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java index 20f611ab..987e6c9c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java @@ -1,14 +1,10 @@ package com.sinthoras.visualprospecting.mixins.xaerosminimap; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.XaeroWorldMapState; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; import java.util.ArrayList; + import net.minecraft.client.Minecraft; import net.minecraftforge.client.MinecraftForgeClient; + import org.lwjgl.opengl.GL11; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -18,11 +14,19 @@ import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + import xaero.common.XaeroMinimapSession; import xaero.common.minimap.MinimapProcessor; import xaero.common.minimap.render.MinimapRenderer; import xaero.common.settings.ModSettings; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.MapState; +import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.XaeroWorldMapState; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; + @Mixin(value = MinimapRenderer.class, remap = false) public class MinimapRendererMixin { @@ -37,52 +41,17 @@ public class MinimapRendererMixin { @Inject( method = "renderMinimap", - at = - @At( - value = "INVOKE", - target = - "Lxaero/common/minimap/waypoints/render/WaypointsGuiRenderer;render(Lxaero/common/XaeroMinimapSession;Lxaero/common/minimap/render/MinimapRendererHelper;DDIIDDFDZFZ)V"), + at = @At( + value = "INVOKE", + target = "Lxaero/common/minimap/waypoints/render/WaypointsGuiRenderer;render(Lxaero/common/XaeroMinimapSession;Lxaero/common/minimap/render/MinimapRendererHelper;DDIIDDFDZFZ)V"), locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void injectDraw( - XaeroMinimapSession minimapSession, - MinimapProcessor minimap, - int x, - int y, - int width, - int height, - int scale, - int size, - float partial, - CallbackInfo ci, - ModSettings settings, - ArrayList underText, - int mapSize, - int bufferSize, - float minimapScale, - float mapScale, - float sizeFix, - int shape, - boolean lockedNorth, - double angle, - double ps, - double pc, - boolean useWorldMap, - int lightLevel, - boolean cave, - boolean circleShape, - int scaledX, - int scaledY, - int minimapFrameSize, - int circleSides, - int frameType, - boolean renderFrame, - int frameTextureX, - int halfFrame, - int rightCornerStartX, - int specH, - boolean safeMode, - double playerX, - double playerZ) { + private void injectDraw(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, int y, int width, + int height, int scale, int size, float partial, CallbackInfo ci, ModSettings settings, + ArrayList underText, int mapSize, int bufferSize, float minimapScale, float mapScale, float sizeFix, + int shape, boolean lockedNorth, double angle, double ps, double pc, boolean useWorldMap, int lightLevel, + boolean cave, boolean circleShape, int scaledX, int scaledY, int minimapFrameSize, int circleSides, + int frameType, boolean renderFrame, int frameTextureX, int halfFrame, int rightCornerStartX, int specH, + boolean safeMode, double playerX, double playerZ) { for (LayerManager layerManager : MapState.instance.layers) { if (layerManager.isLayerActive()) { if (circleShape) { @@ -118,24 +87,12 @@ private void injectDraw( @Inject( method = "renderMinimap", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glScalef(FFF)V", shift = At.Shift.AFTER), - slice = - @Slice( - to = - @At( - value = "INVOKE", - target = - "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V"))) - private void injectBeginStencil( - XaeroMinimapSession minimapSession, - MinimapProcessor minimap, - int x, - int y, - int width, - int height, - int scale, - int size, - float partial, - CallbackInfo ci) { + slice = @Slice( + to = @At( + value = "INVOKE", + target = "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V"))) + private void injectBeginStencil(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, int y, + int width, int height, int scale, int size, float partial, CallbackInfo ci) { if (stencilEnabled && MinecraftForgeClient.getStencilBits() == 0) { stencilEnabled = false; VP.warn("Could not enable stencils! Xaero's minimap overlays will not render"); @@ -151,24 +108,12 @@ private void injectBeginStencil( @Inject( method = "renderMinimap", at = @At(value = "INVOKE", target = "Lxaero/common/minimap/MinimapInterface;usingFBO()Z"), - slice = - @Slice( - from = - @At( - value = "INVOKE", - target = - "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V"))) - private void injectEndStencil( - XaeroMinimapSession minimapSession, - MinimapProcessor minimap, - int x, - int y, - int width, - int height, - int scale, - int size, - float partial, - CallbackInfo ci) { + slice = @Slice( + from = @At( + value = "INVOKE", + target = "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V"))) + private void injectEndStencil(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, int y, int width, + int height, int scale, int size, float partial, CallbackInfo ci) { GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); GL11.glStencilMask(0x00); GL11.glDisable(GL11.GL_STENCIL_TEST); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java index 1f7c5390..ee5bf15a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java @@ -1,35 +1,33 @@ package com.sinthoras.visualprospecting.mixins.xaerosminimap; -import com.sinthoras.visualprospecting.integration.xaerominimap.XaeroMiniMapState; -import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.WaypointManager; import net.minecraft.client.Minecraft; + import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + import xaero.common.XaeroMinimapSession; import xaero.common.minimap.waypoints.render.WaypointsIngameRenderer; +import com.sinthoras.visualprospecting.integration.xaerominimap.XaeroMiniMapState; +import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.WaypointManager; + @Mixin(value = WaypointsIngameRenderer.class, remap = false) public class WaypointsIngameRendererMixin { @Inject( method = "render", - at = - @At( - value = "INVOKE", - target = - "Lxaero/common/minimap/waypoints/render/WaypointsIngameRenderer;renderWaypointsList(Ljava/util/Collection;DDDLnet/minecraft/entity/Entity;Lnet/minecraft/client/renderer/Tessellator;DDDDFFDIFFLnet/minecraft/util/Vec3;D)V"), - slice = - @Slice( - from = - @At( - value = "FIELD", - target = - "Lxaero/common/minimap/waypoints/WaypointsManager;customWaypoints:Ljava/util/Hashtable;", - opcode = Opcodes.GETSTATIC))) + at = @At( + value = "INVOKE", + target = "Lxaero/common/minimap/waypoints/render/WaypointsIngameRenderer;renderWaypointsList(Ljava/util/Collection;DDDLnet/minecraft/entity/Entity;Lnet/minecraft/client/renderer/Tessellator;DDDDFFDIFFLnet/minecraft/util/Vec3;D)V"), + slice = @Slice( + from = @At( + value = "FIELD", + target = "Lxaero/common/minimap/waypoints/WaypointsManager;customWaypoints:Ljava/util/Hashtable;", + opcode = Opcodes.GETSTATIC))) private void injectPreRenderCustomWaypoints(XaeroMinimapSession sets, float modCustomWaypoints, CallbackInfo ci) { for (WaypointManager manager : XaeroMiniMapState.instance.waypointManagers) { if (manager.hasWaypoint()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java index 97c5c878..db533483 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java @@ -1,18 +1,10 @@ package com.sinthoras.visualprospecting.mixins.xaerosworldmap; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.XaeroWorldMapState; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.LayerButton; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.SizedGuiTexturedButton; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.InteractableLayerRenderer; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.entity.Entity; + import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -23,12 +15,23 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + import xaero.map.MapProcessor; import xaero.map.gui.CursorBox; import xaero.map.gui.GuiMap; import xaero.map.gui.ScreenBase; import xaero.map.misc.Misc; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.MapState; +import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.XaeroWorldMapState; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.LayerButton; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.SizedGuiTexturedButton; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.InteractableLayerRenderer; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; + @Mixin(value = GuiMap.class, remap = false) public abstract class GuiMapMixin extends ScreenBase { @@ -61,8 +64,8 @@ protected GuiMapMixin(GuiScreen parent, GuiScreen escape) { private int screenScale; @Inject(method = "", at = @At("RETURN")) - private void injectConstruct( - GuiScreen parent, GuiScreen escape, MapProcessor mapProcessor, Entity player, CallbackInfo ci) { + private void injectConstruct(GuiScreen parent, GuiScreen escape, MapProcessor mapProcessor, Entity player, + CallbackInfo ci) { MapState.instance.layers.forEach(LayerManager::onOpenMap); } @@ -73,8 +76,8 @@ private void injectConstruct( method = "func_73863_a", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glPushMatrix()V", ordinal = 1), locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void injectPreRender( - int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci, Minecraft mc) { + private void injectPreRender(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci, + Minecraft mc) { // snap the camera to whole pixel values. works around a rendering issue but causes another when framerate is // uncapped if (mc.gameSettings.limitFramerate < 255 || mc.gameSettings.enableVsync) { @@ -96,20 +99,16 @@ private void injectPreRender( // deobf method = "drawScreen" @Inject( method = "func_73863_a", - at = - @At( + at = @At( + value = "INVOKE", + target = "Lorg/lwjgl/opengl/GL11;glEnable(I)V", + ordinal = 1, + shift = At.Shift.AFTER), + slice = @Slice( + from = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL14;glBlendFuncSeparate(IIII)V"), + to = @At( value = "INVOKE", - target = "Lorg/lwjgl/opengl/GL11;glEnable(I)V", - ordinal = 1, - shift = At.Shift.AFTER), - slice = - @Slice( - from = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL14;glBlendFuncSeparate(IIII)V"), - to = - @At( - value = "INVOKE", - target = - "Lxaero/map/mods/SupportXaeroMinimap;renderWaypoints(Lnet/minecraft/client/gui/GuiScreen;DDIIDDDDLjava/util/regex/Pattern;Ljava/util/regex/Pattern;FLxaero/map/mods/gui/Waypoint;Lnet/minecraft/client/Minecraft;Lnet/minecraft/client/gui/ScaledResolution;)Lxaero/map/mods/gui/Waypoint;"))) + target = "Lxaero/map/mods/SupportXaeroMinimap;renderWaypoints(Lnet/minecraft/client/gui/GuiScreen;DDIIDDDDLjava/util/regex/Pattern;Ljava/util/regex/Pattern;FLxaero/map/mods/gui/Waypoint;Lnet/minecraft/client/Minecraft;Lnet/minecraft/client/gui/ScaledResolution;)Lxaero/map/mods/gui/Waypoint;"))) private void injectDraw(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci) { for (LayerManager layerManager : MapState.instance.layers) { if (layerManager.isLayerActive()) { @@ -135,17 +134,14 @@ private void injectDraw(int scaledMouseX, int scaledMouseY, float partialTicks, @Inject( method = "func_73863_a", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glTranslated(DDD)V"), - slice = - @Slice( - from = - @At( - value = "FIELD", - // deobf target = - // "Lnet/minecraft/client/Minecraft;currentScreen:Lnet/minecraft/client/gui/GuiScreen;" - target = - "Lnet/minecraft/client/Minecraft;field_71462_r:Lnet/minecraft/client/gui/GuiScreen;", - opcode = Opcodes.GETFIELD), - to = @At(value = "INVOKE", target = "Lxaero/map/gui/CursorBox;drawBox(IIII)V"))) + slice = @Slice( + from = @At( + value = "FIELD", + // deobf target = + // "Lnet/minecraft/client/Minecraft;currentScreen:Lnet/minecraft/client/gui/GuiScreen;" + target = "Lnet/minecraft/client/Minecraft;field_71462_r:Lnet/minecraft/client/gui/GuiScreen;", + opcode = Opcodes.GETFIELD), + to = @At(value = "INVOKE", target = "Lxaero/map/gui/CursorBox;drawBox(IIII)V"))) private void injectDrawTooltip(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci) { for (LayerRenderer layer : XaeroWorldMapState.instance.renderers) { if (layer instanceof InteractableLayerRenderer && layer.isLayerActive()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java index ed7d28ba..0ea5bb98 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java @@ -1,20 +1,23 @@ package com.sinthoras.visualprospecting.network; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; + import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; + import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidRegistry; public class ProspectingNotification implements IMessage { diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java index b16ef4a1..5c894f54 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java @@ -3,20 +3,23 @@ import static com.sinthoras.visualprospecting.Utils.isSmallOreId; import static com.sinthoras.visualprospecting.Utils.oreIdToMaterialId; +import java.util.*; + +import net.minecraft.block.Block; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; + import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import gregtech.common.blocks.GT_Block_Ores_Abstract; import gregtech.common.blocks.GT_TileEntity_Ores; import io.netty.buffer.ByteBuf; -import java.util.*; -import net.minecraft.block.Block; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.World; public class ProspectingRequest implements IMessage { @@ -75,16 +78,16 @@ public IMessage onMessage(ProspectingRequest message, MessageContext ctx) { final UUID uuid = ctx.getServerHandler().playerEntity.getUniqueID(); final long lastRequest = lastRequestPerPlayer.containsKey(uuid) ? lastRequestPerPlayer.get(uuid) : 0; final long timestamp = System.currentTimeMillis(); - final float distanceSquared = ctx.getServerHandler() - .playerEntity - .getPlayerCoordinates() + final float distanceSquared = ctx.getServerHandler().playerEntity.getPlayerCoordinates() .getDistanceSquared(message.blockX, message.blockY, message.blockZ); final World world = ctx.getServerHandler().playerEntity.getEntityWorld(); final int chunkX = Utils.coordBlockToChunk(message.blockX); final int chunkZ = Utils.coordBlockToChunk(message.blockZ); final boolean isChunkLoaded = world.getChunkProvider().chunkExists(chunkX, chunkZ); - if (ctx.getServerHandler().playerEntity.dimension == message.dimensionId - && distanceSquared <= 1024 // max 32 blocks distance + if (ctx.getServerHandler().playerEntity.dimension == message.dimensionId && distanceSquared <= 1024 // max + // 32 + // blocks + // distance && timestamp - lastRequest >= Config.minDelayBetweenVeinRequests && isChunkLoaded) { final Block block = world.getBlock(message.blockX, message.blockY, message.blockZ); @@ -97,8 +100,8 @@ && oreIdToMaterialId(metaData) == message.foundOreMetaData) { lastRequestPerPlayer.put(uuid, timestamp); // Prioritise center vein - final OreVeinPosition centerOreVeinPosition = - ServerCache.instance.getOreVein(message.dimensionId, chunkX, chunkZ); + final OreVeinPosition centerOreVeinPosition = ServerCache.instance + .getOreVein(message.dimensionId, chunkX, chunkZ); if (centerOreVeinPosition.veinType.containsOre(message.foundOreMetaData)) { return new ProspectingNotification(centerOreVeinPosition); } @@ -112,9 +115,10 @@ && oreIdToMaterialId(metaData) == message.foundOreMetaData) { final int neighborChunkX = centerChunkX + offsetChunkX; final int neighborChunkZ = centerChunkZ + offsetChunkZ; final int distanceBlocks = Math.max( - Math.abs(neighborChunkX - chunkX), Math.abs(neighborChunkZ - chunkZ)); - final OreVeinPosition neighborOreVeinPosition = ServerCache.instance.getOreVein( - message.dimensionId, neighborChunkX, neighborChunkZ); + Math.abs(neighborChunkX - chunkX), + Math.abs(neighborChunkZ - chunkZ)); + final OreVeinPosition neighborOreVeinPosition = ServerCache.instance + .getOreVein(message.dimensionId, neighborChunkX, neighborChunkZ); final int maxDistance = ((neighborOreVeinPosition.veinType.blockSize + 16) >> 4) + 1; // Equals to: ceil(blockSize / 16.0) + 1 if (neighborOreVeinPosition.veinType.containsOre(message.foundOreMetaData) diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java index 8e21ac3e..bb2b17e7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java @@ -1,23 +1,26 @@ package com.sinthoras.visualprospecting.network; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; + import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.TransferCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; + import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidRegistry; public class ProspectionSharing implements IMessage { @@ -58,8 +61,7 @@ public void setLastMessage(boolean isLastMessage) { } public int getBytes() { - return BYTES_OVERHEAD - + VeinTypeCaching.getLongesOreNameLength() * oreVeins.size() + return BYTES_OVERHEAD + VeinTypeCaching.getLongesOreNameLength() * oreVeins.size() + UndergroundFluidPosition.BYTES * undergroundFluids.size(); } @@ -75,8 +77,13 @@ public void fromBytes(ByteBuf buf) { final int chunkZ = buf.readInt(); final boolean isDepleted = buf.readByte() > 0; final String oreVeinName = ByteBufUtils.readUTF8String(buf); - oreVeins.add(new OreVeinPosition( - dimensionId, chunkX, chunkZ, VeinTypeCaching.getVeinType(oreVeinName), isDepleted)); + oreVeins.add( + new OreVeinPosition( + dimensionId, + chunkX, + chunkZ, + VeinTypeCaching.getVeinType(oreVeinName), + isDepleted)); } final int numberOfUndergroundFluids = buf.readInt(); @@ -147,7 +154,9 @@ public IMessage onMessage(ProspectionSharing message, MessageContext ctx) { undergroundFluids.get(player).addAll(message.undergroundFluids); if (message.isLastMessage) { TransferCache.instance.addClientProspectionData( - player.getPersistentID().toString(), oreVeins.get(player), undergroundFluids.get(player)); + player.getPersistentID().toString(), + oreVeins.get(player), + undergroundFluids.get(player)); oreVeins.remove(player); undergroundFluids.remove(player); } diff --git a/src/main/java/com/sinthoras/visualprospecting/network/WorldIdNotification.java b/src/main/java/com/sinthoras/visualprospecting/network/WorldIdNotification.java index ce19945d..a6b3692f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/WorldIdNotification.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/WorldIdNotification.java @@ -1,6 +1,7 @@ package com.sinthoras.visualprospecting.network; import com.sinthoras.visualprospecting.database.ClientCache; + import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; diff --git a/src/main/java/com/sinthoras/visualprospecting/task/ITask.java b/src/main/java/com/sinthoras/visualprospecting/task/ITask.java index b93cd694..c6fedc2f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/ITask.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/ITask.java @@ -3,8 +3,7 @@ public interface ITask { /* - Is called every game tick - Return true to terminate task + * Is called every game tick Return true to terminate task */ public boolean process(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java index 8c2d2599..34f9f8b8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java @@ -1,16 +1,18 @@ package com.sinthoras.visualprospecting.task; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IChatComponent; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.TransferCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.network.ProspectionSharing; -import java.util.List; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.util.ChatComponentTranslation; -import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.IChatComponent; public class SnapshotDownloadTask implements ITask { @@ -48,7 +50,8 @@ public boolean process() { if (listsEmpty()) { final IChatComponent notification = new ChatComponentTranslation( - "item.visualprospecting.prospectorslog.reading.end", player.getDisplayName()); + "item.visualprospecting.prospectorslog.reading.end", + player.getDisplayName()); notification.getChatStyle().setItalic(true); notification.getChatStyle().setColor(EnumChatFormatting.GRAY); player.addChatMessage(notification); diff --git a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java index 65bd77b7..de3a3c97 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java @@ -1,12 +1,13 @@ package com.sinthoras.visualprospecting.task; +import java.util.List; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.network.ProspectionSharing; -import java.util.List; public class SnapshotUploadTask implements ITask { From 7ca8324781e01b25c2a8c6a3a989664282841e51 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Sun, 29 Jan 2023 10:49:16 -0800 Subject: [PATCH 019/132] [ci skip] Add git-blame-ignore-revs for spotlessApply --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..374370d6 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Ignore spotlessApply reformat +9d48150e57e46c8df16822acee58f6f36dcdc91a From 36ed2f650bea6d16811e483eaf50daff792e87fe Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Tue, 31 Jan 2023 09:56:59 +0000 Subject: [PATCH 020/132] [ci skip] upgraded build system --- build.gradle | 90 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 20 deletions(-) diff --git a/build.gradle b/build.gradle index 18afe431..fe8a2e7b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1675013090 +//version: 1675110695 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -55,9 +55,9 @@ plugins { 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.jetbrains.kotlin.jvm' version '1.8.0' apply false + id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false + id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version ,unused, available for addon.gradle id 'com.github.johnrengelman.shadow' version '7.1.2' apply false id 'com.palantir.git-version' version '0.13.0' apply false // 0.13.0 is the last jvm8 supporting version @@ -66,7 +66,7 @@ plugins { id 'com.diffplug.spotless' version '6.7.2' apply false id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.0.18' + id 'com.gtnewhorizons.retrofuturagradle' version '1.1.2' } boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated @@ -113,6 +113,7 @@ propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") propertyDefaultIfUnset("curseForgeRelations", "") propertyDefaultIfUnset("minimizeShadowedDependencies", true) +propertyDefaultIfUnset("relocateShadowedDependencies", true) // Deprecated properties (kept for backwards compat) propertyDefaultIfUnset("gradleTokenModId", "") propertyDefaultIfUnset("gradleTokenModName", "") @@ -149,6 +150,33 @@ java { } } +pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { + // If Kotlin is enabled in the project + kotlin { + jvmToolchain(8) + } + // Kotlin hacks our source sets, so we hack Kotlin's tasks + def disabledKotlinTaskList = [ + "kaptGenerateStubsMcLauncherKotlin", + "kaptGenerateStubsPatchedMcKotlin", + "kaptGenerateStubsInjectedTagsKotlin", + "compileMcLauncherKotlin", + "compilePatchedMcKotlin", + "compileInjectedTagsKotlin", + "kaptMcLauncherKotlin", + "kaptPatchedMcKotlin", + "kaptInjectedTagsKotlin", + "kspMcLauncherKotlin", + "kspPatchedMcKotlin", + "kspInjectedTagsKotlin", + ] + tasks.configureEach { task -> + if (task.name in disabledKotlinTaskList) { + task.enabled = false + } + } +} + configurations { create("runtimeOnlyNonPublishable") { description = "Runtime only dependencies that are not published alongside the jar" @@ -309,7 +337,7 @@ if (identifiedVersion == versionOverride) { out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') } -group = modGroup +group = "com.github.GTNewHorizons" if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { archivesBaseName = customArchiveBaseName } else { @@ -502,6 +530,14 @@ dependencies { } } +pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { + if (usesMixins.toBoolean()) { + dependencies { + kapt('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + } + } +} + apply from: 'dependencies.gradle' def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' @@ -542,9 +578,11 @@ if (usesMixins.toBoolean()) { tasks.named("reobfJar", ReobfuscatedJar).configure { extraSrgFiles.from(mixinSrg) } -} -if (usesMixins.toBoolean()) { + tasks.named("processResources").configure { + dependsOn("generateAssets") + } + tasks.named("compileJava", JavaCompile).configure { doFirst { new File(mixinTmpDir).mkdirs() @@ -558,6 +596,25 @@ if (usesMixins.toBoolean()) { "-XDignore.symbol.file" ] } + + pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { + kapt { + correctErrorTypes = true + javacOptions { + option("-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}") + option("-AoutSrgFile=$mixinSrg") + option("-AoutRefMapFile=$refMap") + } + } + tasks.configureEach { task -> + if (task.name == "kaptKotlin") { + task.doFirst { + new File(mixinTmpDir).mkdirs() + } + } + } + } + } tasks.named("processResources", ProcessResources).configure { @@ -613,6 +670,7 @@ if (usesShadowedDependencies.toBoolean()) { tasks.register('relocateShadowJar', ConfigureShadowRelocation) { target = tasks.shadowJar prefix = modGroup + ".shadow" + enabled = minimizeShadowedDependencies.toBoolean() } tasks.named("shadowJar", ShadowJar).configure { manifest { @@ -628,7 +686,9 @@ if (usesShadowedDependencies.toBoolean()) { project.configurations.shadeCompile ] archiveClassifier.set('dev') - dependsOn(relocateShadowJar) + if (minimizeShadowedDependencies.toBoolean()) { + dependsOn(relocateShadowJar) + } } configurations.runtimeElements.outgoing.artifacts.clear() configurations.apiElements.outgoing.artifacts.clear() @@ -654,16 +714,6 @@ if (usesShadowedDependencies.toBoolean()) { ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar ext.publishableObfJar = tasks.reobfJar -tasks.named('extractForgeUserdev', Copy).configure { efu -> - doLast { - // Fix CoFH-repackaged CCL not finding mappings - project.copy { - from(mcpTasks.userdevDir("conf")) - into(new File(project.buildDir, "unpacked/conf")) - } - } -} - tasks.register('apiJar', Jar) { from(sourceSets.main.allSource) { include modGroupPath + "/" + apiPackagePath + '/**' @@ -768,7 +818,7 @@ publishing { artifact apiJar } - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: "com.github.GTNewHorizons" + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group 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 From 7f0352ef56d314617902a71155234ad173613ec9 Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Sun, 19 Mar 2023 10:38:23 +0100 Subject: [PATCH 021/132] [After Stable] Mixin rework (#27) * rename some mixin handlers * use mixin accessor instead of reflection to access fields of journeymap.client.ui.minimap.DisplayVars * use mixin accessor instead of reflection to access fields of journeymap.client.ui.fullscreen.Fullscreen * migrate to Early and Late mixin system * remove forge access transformer in favor of mixin accessor --- gradle.properties | 6 +- .../cachebuilder/AnalysisProgressTracker.java | 14 +- .../journeymap/JourneyMapState.java | 8 +- .../integration/journeymap/Reflection.java | 32 ----- .../visualprospecting/mixinplugin/Mixin.java | 70 ---------- .../mixinplugin/MixinPlugin.java | 110 ---------------- .../visualprospecting/mixinplugin/Mixins.java | 115 +++++++++++++++++ .../mixinplugin/TargetedMod.java | 62 +++------ .../VisualProspectingEarlyMixinLoader.java | 51 ++++++++ .../VisualProspectingLateMixinLoader.java | 30 +++++ .../minecraft/ForgeHooksClientMixin.java | 5 +- .../minecraft/ItemEditableBookMixin.java | 17 +-- .../minecraft/MinecraftServerAccessor.java | 14 ++ .../mixins/journeymap/MiniMapMixin.java | 121 ------------------ .../bartworks/WorldGenContainerMixin.java | 7 +- .../GT_Worldgenerator_SpaceMixin.java | 4 +- .../gregtech/GT_Block_Ores_AbstractMixin.java | 2 +- ...aTileEntity_AdvSeismicProspectorMixin.java | 2 +- .../GT_MetaTileEntity_ScannerMixin.java | 10 +- .../gregtech/WorldGenContainerMixin.java | 10 +- .../late/journeymap/DisplayVarsAccessor.java | 24 ++++ .../late/journeymap/FullscreenAccessor.java | 17 +++ .../journeymap/FullscreenActionsMixin.java | 10 +- .../journeymap/FullscreenMixin.java | 22 ++-- .../mixins/late/journeymap/MiniMapMixin.java | 70 ++++++++++ .../journeymap/RenderWaypointBeaconMixin.java | 4 +- .../journeymap/WaypointManagerMixin.java | 14 +- .../tcnodetracker/GuiMainMixin.java | 13 +- .../xaerosminimap/MinimapRendererMixin.java | 14 +- .../WaypointsIngameRendererMixin.java | 5 +- .../xaerosworldmap/GuiMapMixin.java | 21 +-- .../META-INF/visualprospecting_at.cfg | 1 - .../mixins.visualprospecting.early.json | 8 ++ .../resources/mixins.visualprospecting.json | 8 ++ .../mixins.visualprospecting.late.json | 8 ++ 35 files changed, 452 insertions(+), 477 deletions(-) delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingLateMixinLoader.java rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => early}/minecraft/ForgeHooksClientMixin.java (75%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => early}/minecraft/ItemEditableBookMixin.java (83%) create mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/MinecraftServerAccessor.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/bartworks/WorldGenContainerMixin.java (84%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/galacticgreg/GT_Worldgenerator_SpaceMixin.java (90%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/gregtech/GT_Block_Ores_AbstractMixin.java (94%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java (99%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/gregtech/GT_MetaTileEntity_ScannerMixin.java (95%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/gregtech/WorldGenContainerMixin.java (78%) create mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/journeymap/FullscreenActionsMixin.java (87%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/journeymap/FullscreenMixin.java (93%) create mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/journeymap/RenderWaypointBeaconMixin.java (91%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/journeymap/WaypointManagerMixin.java (64%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/tcnodetracker/GuiMainMixin.java (86%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/xaerosminimap/MinimapRendererMixin.java (87%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/xaerosminimap/WaypointsIngameRendererMixin.java (88%) rename src/main/java/com/sinthoras/visualprospecting/mixins/{ => late}/xaerosworldmap/GuiMapMixin.java (90%) delete mode 100644 src/main/resources/META-INF/visualprospecting_at.cfg create mode 100644 src/main/resources/mixins.visualprospecting.early.json create mode 100644 src/main/resources/mixins.visualprospecting.json create mode 100644 src/main/resources/mixins.visualprospecting.late.json diff --git a/gradle.properties b/gradle.properties index c966f47e..308204be 100644 --- a/gradle.properties +++ b/gradle.properties @@ -39,18 +39,18 @@ 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 -accessTransformersFile = visualprospecting_at.cfg +accessTransformersFile = # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! usesMixins = true # Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise. -mixinPlugin = mixinplugin.MixinPlugin +mixinPlugin = # Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! mixinsPackage = mixins # 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 -coreModClass = +coreModClass = mixinplugin.VisualProspectingEarlyMixinLoader # 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 = false diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java index e1f06f9a..50d02394 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java @@ -8,6 +8,7 @@ import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.mixins.early.minecraft.MinecraftServerAccessor; public class AnalysisProgressTracker { @@ -34,7 +35,7 @@ public static synchronized void announceFastDimension(int dimensionId) { final String message = "Processing dimension with id " + dimensionId + " with fast scanning."; VP.info(message); if (Utils.isLogicalClient()) { - MinecraftServer.getServer().userMessage = message; + ((MinecraftServerAccessor) MinecraftServer.getServer()).setUserMessage(message); } } @@ -42,7 +43,7 @@ public static synchronized void announceSlowDimension(int dimensionId) { final String message = "Processing dimension with id " + dimensionId + " with slow (safe) scanning."; VP.info(message); if (Utils.isLogicalClient()) { - MinecraftServer.getServer().userMessage = message; + ((MinecraftServerAccessor) MinecraftServer.getServer()).setUserMessage(message); } } @@ -59,7 +60,7 @@ public static synchronized void regionFileProcessed() { private static synchronized void updateLog() { long timestamp = System.currentTimeMillis(); - if (timestamp - (Config.cacheGenerationLogUpdateMinTime * 1000) > lastLogUpdate) { + if (timestamp - (Config.cacheGenerationLogUpdateMinTime * 1000L) > lastLogUpdate) { lastLogUpdate = timestamp; final String message = "Caching GT ore generation meta data - Dimension (" + (dimensionsProcessed + 1) + "/" @@ -69,7 +70,8 @@ private static synchronized void updateLog() { + "%"; VP.info(message); if (Utils.isLogicalClient()) { - MinecraftServer.getServer().userMessage = message + "%"; // Escape % for String.format + // Escape % for String.format + ((MinecraftServerAccessor) MinecraftServer.getServer()).setUserMessage(message + "%"); } } } @@ -84,7 +86,7 @@ public static synchronized void processingFinished() { + "sec"; VP.info(message); if (Utils.isLogicalClient()) { - MinecraftServer.getServer().userMessage = message; + ((MinecraftServerAccessor) MinecraftServer.getServer()).setUserMessage(message); } } @@ -92,7 +94,7 @@ public static synchronized void notifyCorruptFile(File regionFile) { final String message = "Encountered corrupt/malformed/modified save file: " + regionFile; VP.info(message); if (Utils.isLogicalClient()) { - MinecraftServer.getServer().userMessage = message; + ((MinecraftServerAccessor) MinecraftServer.getServer()).setUserMessage(message); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java index 4be3cb6d..4bdc0368 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java @@ -1,7 +1,6 @@ package com.sinthoras.visualprospecting.integration.journeymap; import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; -import static com.sinthoras.visualprospecting.integration.journeymap.Reflection.getJourneyMapGridRenderer; import java.util.ArrayList; import java.util.List; @@ -14,6 +13,7 @@ import com.sinthoras.visualprospecting.integration.journeymap.waypoints.OreVeinWaypointManager; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.ThaumcraftNodeWaypointManager; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.WaypointManager; +import com.sinthoras.visualprospecting.mixins.late.journeymap.FullscreenAccessor; public class JourneyMapState { @@ -45,16 +45,14 @@ public JourneyMapState() { } public void openJourneyMapAt(int blockX, int blockZ) { - final GridRenderer gridRenderer = getJourneyMapGridRenderer(); + final GridRenderer gridRenderer = FullscreenAccessor.getGridRenderer(); assert gridRenderer != null; - gridRenderer.center(gridRenderer.getMapType(), blockX, blockZ, gridRenderer.getZoom()); } public void openJourneyMapAt(int blockX, int blockZ, int zoom) { - final GridRenderer gridRenderer = getJourneyMapGridRenderer(); + final GridRenderer gridRenderer = FullscreenAccessor.getGridRenderer(); assert gridRenderer != null; - gridRenderer.center(gridRenderer.getMapType(), blockX, blockZ, zoom); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java deleted file mode 100644 index 31e9121c..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/Reflection.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap; - -import java.lang.reflect.Field; - -import journeymap.client.render.map.GridRenderer; -import journeymap.client.ui.fullscreen.Fullscreen; - -import com.sinthoras.visualprospecting.VP; - -public class Reflection { - - private static Field gridRenderer; - - static { - try { - gridRenderer = Fullscreen.class.getDeclaredField("gridRenderer"); - gridRenderer.setAccessible(true); - } catch (Exception e) { - VP.error("Failed to access private fields in JourneyMap!"); - e.printStackTrace(); - } - } - - public static GridRenderer getJourneyMapGridRenderer() { - try { - return (GridRenderer) gridRenderer.get(null); - } catch (IllegalAccessException e) { - e.printStackTrace(); - return null; - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java deleted file mode 100644 index 71f9a2cf..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixin.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.sinthoras.visualprospecting.mixinplugin; - -import static com.sinthoras.visualprospecting.mixinplugin.TargetedMod.*; - -import java.util.Arrays; -import java.util.List; - -import cpw.mods.fml.relauncher.FMLLaunchHandler; - -public enum Mixin { - - // - // IMPORTANT: Do not make any references to any mod from this file. This file is loaded quite early on and if - // you refer to other mods you load them as well. The consequence is: You can't inject any previously loaded - // classes! - // Exception: Tags.java, as long as it is used for Strings only! - // - - WorldGenContainerMixin("bartworks.WorldGenContainerMixin", BARTWORKS), - - GT_Worldgenerator_SpaceMixin("galacticgreg.GT_Worldgenerator_SpaceMixin", GALACTICGREG), - - GT_Block_Ores_AbstractMixin("gregtech.GT_Block_Ores_AbstractMixin", GREGTECH), - GT_MetaTileEntity_AdvSeismicProspectorMixin("gregtech.GT_MetaTileEntity_AdvSeismicProspectorMixin", GREGTECH), - GT_MetaTileEntity_ScannerMixin("gregtech.GT_MetaTileEntity_ScannerMixin", GREGTECH), - GT_WorldGenContainerMixin("gregtech.WorldGenContainerMixin", GREGTECH), - - FullscreenMixin("journeymap.FullscreenMixin", Side.CLIENT, JOURNEYMAP), - FullscreenActionsMixin("journeymap.FullscreenActionsMixin", Side.CLIENT, JOURNEYMAP), - MiniMapMixin("journeymap.MiniMapMixin", Side.CLIENT, JOURNEYMAP), - RenderWaypointBeaconMixin("journeymap.RenderWaypointBeaconMixin", Side.CLIENT, JOURNEYMAP), - WaypointManagerMixin("journeymap.WaypointManagerMixin", Side.CLIENT, JOURNEYMAP), - - GuiMainMixin("tcnodetracker.GuiMainMixin", Side.CLIENT, TCNODETRACKER), - - GuiMapMixin("xaerosworldmap.GuiMapMixin", Side.CLIENT, XAEROWORLDMAP), - WaypointsIngameRendererMixin("xaerosminimap.WaypointsIngameRendererMixin", Side.CLIENT, XAEROMINIMAP), - MinimapRendererMixin("xaerosminimap.MinimapRendererMixin", Side.CLIENT, XAEROMINIMAP, XAEROWORLDMAP), - // used to enable the stencil buffer for on-minimap rendering - ForgeHooksClientMixin("minecraft.ForgeHooksClientMixin", Side.CLIENT, XAEROMINIMAP, XAEROWORLDMAP), - - ItemEditableBookMixin("minecraft.ItemEditableBookMixin", VANILLA); - - public final String mixinClass; - public final List targetedMods; - private final Side side; - - Mixin(String mixinClass, Side side, TargetedMod... targetedMods) { - this.mixinClass = mixinClass; - this.targetedMods = Arrays.asList(targetedMods); - this.side = side; - } - - Mixin(String mixinClass, TargetedMod... targetedMods) { - this.mixinClass = mixinClass; - this.targetedMods = Arrays.asList(targetedMods); - this.side = Side.BOTH; - } - - public boolean shouldLoad(List loadedMods) { - return (side == Side.BOTH || side == Side.SERVER && FMLLaunchHandler.side().isServer() - || side == Side.CLIENT && FMLLaunchHandler.side().isClient()) && loadedMods.containsAll(targetedMods); - } -} - -enum Side { - BOTH, - CLIENT, - SERVER; -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java deleted file mode 100644 index 6517aeef..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/MixinPlugin.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.sinthoras.visualprospecting.mixinplugin; - -import static com.sinthoras.visualprospecting.mixinplugin.TargetedMod.VANILLA; -import static java.nio.file.Files.walk; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import net.minecraft.launchwrapper.Launch; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; -import org.spongepowered.asm.mixin.extensibility.IMixinInfo; -import org.spongepowered.libraries.org.objectweb.asm.tree.ClassNode; - -import ru.timeconqueror.spongemixins.MinecraftURLClassPath; - -import com.sinthoras.visualprospecting.Tags; - -public class MixinPlugin implements IMixinConfigPlugin { - - private static final Logger LOG = LogManager.getLogger(Tags.MODID + " mixins"); - private static final Path MODS_DIRECTORY_PATH = new File(Launch.minecraftHome, "mods/").toPath(); - - @Override - public void onLoad(String mixinPackage) {} - - @Override - public String getRefMapperConfig() { - return null; - } - - @Override - public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { - return true; - } - - @Override - public void acceptTargets(Set myTargets, Set otherTargets) {} - - // This method return a List of mixins. Every mixins in this list will be loaded. - @Override - public List getMixins() { - final boolean isDevelopmentEnvironment = (boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment"); - - List loadedMods = Arrays.stream(TargetedMod.values()) - .filter(mod -> mod == VANILLA || (mod.loadInDevelopment && isDevelopmentEnvironment) || loadJarOf(mod)) - .collect(Collectors.toList()); - - for (TargetedMod mod : TargetedMod.values()) { - if (loadedMods.contains(mod)) { - LOG.info("Found " + mod.modName + "! Integrating now..."); - } else { - LOG.info("Could not find " + mod.modName + "! Skipping integration...."); - } - } - - List mixins = new ArrayList<>(); - for (Mixin mixin : Mixin.values()) { - if (mixin.shouldLoad(loadedMods)) { - mixins.add(mixin.mixinClass); - LOG.debug("Loading mixin: " + mixin.mixinClass); - } - } - return mixins; - } - - private boolean loadJarOf(final TargetedMod mod) { - try { - File jar = findJarOf(mod); - if (jar == null) { - LOG.info("Jar not found for " + mod); - return false; - } - - LOG.info("Attempting to add " + jar + " to the URL Class Path"); - if (!jar.exists()) { - throw new FileNotFoundException(jar.toString()); - } - MinecraftURLClassPath.addJar(jar); - return true; - } catch (Exception e) { - e.printStackTrace(); - return false; - } - } - - public static File findJarOf(final TargetedMod mod) { - try { - return walk(MODS_DIRECTORY_PATH).filter(mod::isMatchingJar).map(Path::toFile).findFirst().orElse(null); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - } - - @Override - public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} - - @Override - public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {} -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java new file mode 100644 index 00000000..a95efcdd --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java @@ -0,0 +1,115 @@ +package com.sinthoras.visualprospecting.mixinplugin; + +import static com.sinthoras.visualprospecting.mixinplugin.TargetedMod.*; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import cpw.mods.fml.relauncher.FMLLaunchHandler; + +public enum Mixins { + + // Bartworks mixins + WorldGenContainerMixin("bartworks.WorldGenContainerMixin", BARTWORKS), + + // Galactic greg mixins + GT_Worldgenerator_SpaceMixin("galacticgreg.GT_Worldgenerator_SpaceMixin", GALACTICGREG), + + // Gregtech mixins + GT_Block_Ores_AbstractMixin("gregtech.GT_Block_Ores_AbstractMixin", GT5U), + GT_MetaTileEntity_AdvSeismicProspectorMixin("gregtech.GT_MetaTileEntity_AdvSeismicProspectorMixin", GT5U), + GT_MetaTileEntity_ScannerMixin("gregtech.GT_MetaTileEntity_ScannerMixin", GT5U), + GT_WorldGenContainerMixin("gregtech.WorldGenContainerMixin", GT5U), + + // Journeymap mixins + DisplayVarsAccessorMixin("journeymap.DisplayVarsAccessor", Side.CLIENT, JOURNEYMAP), + FullscreenAccessorMixin("journeymap.FullscreenAccessor", Side.CLIENT, JOURNEYMAP), + FullscreenMixin("journeymap.FullscreenMixin", Side.CLIENT, JOURNEYMAP), + FullscreenActionsMixin("journeymap.FullscreenActionsMixin", Side.CLIENT, JOURNEYMAP), + MiniMapMixin("journeymap.MiniMapMixin", Side.CLIENT, JOURNEYMAP), + RenderWaypointBeaconMixin("journeymap.RenderWaypointBeaconMixin", Side.CLIENT, JOURNEYMAP), + WaypointManagerMixin("journeymap.WaypointManagerMixin", Side.CLIENT, JOURNEYMAP), + + // TC node tracker mixins + GuiMainMixin("tcnodetracker.GuiMainMixin", Side.CLIENT, TCNODETRACKER), + + // Xaerosworldmap & Xaerosminimap mixins + GuiMapMixin("xaerosworldmap.GuiMapMixin", Side.CLIENT, XAEROWORLDMAP), + WaypointsIngameRendererMixin("xaerosminimap.WaypointsIngameRendererMixin", Side.CLIENT, XAEROMINIMAP), + MinimapRendererMixin("xaerosminimap.MinimapRendererMixin", Side.CLIENT, XAEROMINIMAP, XAEROWORLDMAP), + + // Vanilla Mixins + MinecraftServerAccessorMixin("minecraft.MinecraftServerAccessor", Phase.EARLY, Side.BOTH, VANILLA), + ForgeHooksClientMixin("minecraft.ForgeHooksClientMixin", Phase.EARLY, Side.CLIENT, XAEROMINIMAP, XAEROWORLDMAP), + ItemEditableBookMixin("minecraft.ItemEditableBookMixin", Phase.EARLY, VANILLA); + + public final String mixinClass; + public final Phase phase; + private final Side side; + private final List targetedMods; + + Mixins(String mixinClass, TargetedMod... targetedMods) { + this.mixinClass = mixinClass; + this.phase = Phase.LATE; + this.side = Side.BOTH; + this.targetedMods = Arrays.asList(targetedMods); + } + + Mixins(String mixinClass, Phase phase, TargetedMod... targetedMods) { + this.mixinClass = mixinClass; + this.phase = phase; + this.side = Side.BOTH; + this.targetedMods = Arrays.asList(targetedMods); + } + + Mixins(String mixinClass, Side side, TargetedMod... targetedMods) { + this.mixinClass = mixinClass; + this.phase = Phase.LATE; + this.side = side; + this.targetedMods = Arrays.asList(targetedMods); + } + + Mixins(String mixinClass, Phase phase, Side side, TargetedMod... targetedMods) { + this.mixinClass = mixinClass; + this.phase = phase; + this.side = side; + this.targetedMods = Arrays.asList(targetedMods); + } + + public boolean shouldLoad(Set loadedCoreMods, Set loadedMods) { + return shouldLoadSide() && allModsLoaded(targetedMods, loadedCoreMods, loadedMods); + } + + private boolean shouldLoadSide() { + return (side == Side.BOTH || (side == Side.SERVER && FMLLaunchHandler.side().isServer()) + || (side == Side.CLIENT && FMLLaunchHandler.side().isClient())); + } + + private boolean allModsLoaded(List targetedMods, Set loadedCoreMods, Set loadedMods) { + if (targetedMods.isEmpty()) return false; + for (TargetedMod target : targetedMods) { + if (target == TargetedMod.VANILLA) continue; + // Check coremod first + if (!loadedCoreMods.isEmpty() && target.coreModClass != null + && !loadedCoreMods.contains(target.coreModClass)) { + return false; + } else if (!loadedMods.isEmpty() && target.modId != null && !loadedMods.contains(target.modId)) { + return false; + } + } + return true; + } + + enum Side { + BOTH, + CLIENT, + SERVER + } + + public enum Phase { + EARLY, + LATE + } + +} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java index 8964b0ff..3297d630 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java @@ -1,57 +1,35 @@ package com.sinthoras.visualprospecting.mixinplugin; -import java.nio.file.Path; - -import com.google.common.io.Files; - public enum TargetedMod { - // - // IMPORTANT: Do not make any references to any mod from this file. This file is loaded quite early on and if - // you refer to other mods you load them as well. The consequence is: You can't inject any previously loaded - // classes! - // Exception: Tags.java, as long as it is used for Strings only! - // - - // Replace with your injected mods here, but always keep VANILLA: - VANILLA("Minecraft", "unused", true), - GREGTECH("GregTech", "gregtech", true), - JOURNEYMAP("JourneyMap", "journeymap-1.7.10", true), - XAEROWORLDMAP("Xaero's World Map", "XaerosWorldMap", true), - XAEROMINIMAP("Xaero's Minimap", "Xaeros_Minimap", true), - TCNODETRACKER("TCNodeTracker", "tcnodetracker-1.7.10", true), - BARTWORKS("Bartworks", "bartworks", false), - GALACTICGREG("GalacticGreg", "GalacticGreg", false); + BARTWORKS("BartWorks", "com.github.bartimaeusnek.bartworks.ASM.BWCorePlugin", "bartworks"), + GALACTICGREG("Galactic Greg", null, "galacticgreg"), + GT5U("GregTech5u", null, "gregtech"), // Also matches GT6. + JOURNEYMAP("JourneyMap", null, "journeymap"), + TCNODETRACKER("TC Node Tracker", null, "tcnodetracker"), + VANILLA("Minecraft", null), + XAEROMINIMAP("Xaero's Minimap", "xaero.common.core.XaeroMinimapPlugin", "XaeroMinimap"), + XAEROWORLDMAP("Xaero's World Map", "xaero.map.core.XaeroWorldMapPlugin", "XaeroWorldMap"); + /** The "name" in the @Mod annotation */ public final String modName; - public final String jarNamePrefixLowercase; - // Optional dependencies can be omitted in development. Especially skipping GT5U will drastically speed up your game - // start! - public final boolean loadInDevelopment; + /** Class that implements the IFMLLoadingPlugin interface */ + public final String coreModClass; + /** The "modid" in the @Mod annotation */ + public final String modId; - TargetedMod(String modName, String jarNamePrefix, boolean loadInDevelopment) { - this.modName = modName; - this.jarNamePrefixLowercase = jarNamePrefix.toLowerCase(); - this.loadInDevelopment = loadInDevelopment; + TargetedMod(String modName, String coreModClass) { + this(modName, coreModClass, null); } - public boolean isMatchingJar(Path path) { - final String pathString = path.toString(); - final String nameLowerCase = Files.getNameWithoutExtension(pathString).toLowerCase(); - final String fileExtension = Files.getFileExtension(pathString); - - return nameLowerCase.startsWith(jarNamePrefixLowercase) - && ("jar".equals(fileExtension) || "litemod".equals(fileExtension)); + TargetedMod(String modName, String coreModClass, String modId) { + this.modName = modName; + this.coreModClass = coreModClass; + this.modId = modId; } @Override public String toString() { - return "TargetedMod{" + "modName='" - + modName - + '\'' - + ", jarNamePrefixLowercase='" - + jarNamePrefixLowercase - + '\'' - + '}'; + return "TargetedMod{modName='" + modName + "', coreModClass='" + coreModClass + "', modId='" + modId + "'}"; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java new file mode 100644 index 00000000..168fb1e2 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java @@ -0,0 +1,51 @@ +package com.sinthoras.visualprospecting.mixinplugin; + +import java.util.*; + +import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin; + +@IFMLLoadingPlugin.MCVersion("1.7.10") +@IFMLLoadingPlugin.TransformerExclusions("com.sinthoras.visualprospecting.mixinplugin") +public class VisualProspectingEarlyMixinLoader implements IFMLLoadingPlugin, IEarlyMixinLoader { + + @Override + public String getMixinConfig() { + return "mixins.visualprospecting.early.json"; + } + + @Override + public List getMixins(Set loadedCoreMods) { + final List mixins = new ArrayList<>(); + for (Mixins mixin : Mixins.values()) { + if (mixin.phase == Mixins.Phase.EARLY && mixin.shouldLoad(loadedCoreMods, Collections.emptySet())) { + mixins.add(mixin.mixinClass); + } + } + return mixins; + } + + @Override + public String[] getASMTransformerClass() { + return null; + } + + @Override + public String getModContainerClass() { + return null; + } + + @Override + public String getSetupClass() { + return null; + } + + @Override + public void injectData(Map data) {} + + @Override + public String getAccessTransformerClass() { + return null; + } + +} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingLateMixinLoader.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingLateMixinLoader.java new file mode 100644 index 00000000..fad2f590 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingLateMixinLoader.java @@ -0,0 +1,30 @@ +package com.sinthoras.visualprospecting.mixinplugin; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import com.gtnewhorizon.gtnhmixins.ILateMixinLoader; +import com.gtnewhorizon.gtnhmixins.LateMixin; + +@LateMixin +public class VisualProspectingLateMixinLoader implements ILateMixinLoader { + + @Override + public String getMixinConfig() { + return "mixins.visualprospecting.late.json"; + } + + @Override + public List getMixins(Set loadedMods) { + final List mixins = new ArrayList<>(); + for (Mixins mixin : Mixins.values()) { + if (mixin.phase == Mixins.Phase.LATE && mixin.shouldLoad(Collections.emptySet(), loadedMods)) { + mixins.add(mixin.mixinClass); + } + } + return mixins; + } + +} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ForgeHooksClientMixin.java similarity index 75% rename from src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ForgeHooksClientMixin.java index 00c918a6..7969a83d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ForgeHooksClientMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ForgeHooksClientMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.minecraft; +package com.sinthoras.visualprospecting.mixins.early.minecraft; import net.minecraftforge.client.ForgeHooksClient; @@ -7,12 +7,13 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +// used to enable the stencil buffer for on-minimap rendering @Mixin(value = ForgeHooksClient.class, remap = false) public class ForgeHooksClientMixin { // this is only a mixin because it needs to run before the minecraft window is created @Inject(method = "createDisplay", at = @At("HEAD")) - private static void enableStencilBuffer(CallbackInfo ci) { + private static void visualprospecting$enableStencilBuffer(CallbackInfo ci) { // give me my stencil buffer, forge. System.setProperty("forge.forceDisplayStencil", "true"); } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java similarity index 83% rename from src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java index 6caf2efa..fdeafd97 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.minecraft; +package com.sinthoras.visualprospecting.mixins.early.minecraft; import java.util.List; @@ -13,7 +13,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; @@ -24,17 +23,12 @@ import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.network.ProspectingNotification; -@Mixin(value = ItemEditableBook.class, remap = true) +@Mixin(value = ItemEditableBook.class) public class ItemEditableBookMixin { - @Inject( - method = "onItemRightClick", - at = @At("HEAD"), - remap = true, - require = 1, - locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void onItemRightClick(ItemStack itemStack, World world, EntityPlayer entityPlayer, - CallbackInfoReturnable callbackInfoReturnable) { + @Inject(method = "onItemRightClick", at = @At("HEAD")) + private void visualprospecting$onItemRightClick(ItemStack itemStack, World world, EntityPlayer entityPlayer, + CallbackInfoReturnable cir) { if (!world.isRemote) { final NBTTagCompound compound = itemStack.getTagCompound(); if (compound.hasKey(Tags.VISUALPROSPECTING_FLAG)) { @@ -42,7 +36,6 @@ private void onItemRightClick(ItemStack itemStack, World world, EntityPlayer ent final int blockX = compound.getInteger(Tags.PROSPECTION_BLOCK_X); final int blockZ = compound.getInteger(Tags.PROSPECTION_BLOCK_Z); final int blockRadius = compound.getInteger(Tags.PROSPECTION_ORE_RADIUS); - if (world.provider.dimensionId == dimensionId) { final List foundOreVeins = ServerCache.instance .prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/MinecraftServerAccessor.java b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/MinecraftServerAccessor.java new file mode 100644 index 00000000..9403ea71 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/MinecraftServerAccessor.java @@ -0,0 +1,14 @@ +package com.sinthoras.visualprospecting.mixins.early.minecraft; + +import net.minecraft.server.MinecraftServer; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(MinecraftServer.class) +public interface MinecraftServerAccessor { + + @Accessor + void setUserMessage(String msg); + +} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java deleted file mode 100644 index e670ca06..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/MiniMapMixin.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.journeymap; - -import java.lang.reflect.Field; - -import journeymap.client.render.draw.DrawStep; -import journeymap.client.render.map.GridRenderer; -import journeymap.client.ui.minimap.DisplayVars; -import journeymap.client.ui.minimap.MiniMap; -import journeymap.client.ui.minimap.Shape; - -import net.minecraft.client.Minecraft; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; -import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; - -@Mixin(MiniMap.class) -public abstract class MiniMapMixin { - - private static Field drawScale; - private static Field fontScale; - private static Field shape; - private static Field minimapWidth; - - static { - try { - drawScale = DisplayVars.class.getDeclaredField("drawScale"); - drawScale.setAccessible(true); - fontScale = DisplayVars.class.getDeclaredField("fontScale"); - fontScale.setAccessible(true); - shape = DisplayVars.class.getDeclaredField("shape"); - shape.setAccessible(true); - minimapWidth = DisplayVars.class.getDeclaredField("minimapWidth"); - minimapWidth.setAccessible(true); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } - } - - private static float getDrawScale(DisplayVars displayVars) { - try { - return drawScale.getFloat(displayVars); - } catch (IllegalAccessException e) { - return 0.0f; - } - } - - private static double getFontScale(DisplayVars displayVars) { - try { - return fontScale.getDouble(displayVars); - } catch (IllegalAccessException e) { - return 0.0; - } - } - - private static Shape getShape(DisplayVars displayVars) { - try { - return (Shape) shape.get(displayVars); - } catch (IllegalAccessException e) { - return Shape.Circle; - } - } - - private static int getMinimapWidth(DisplayVars displayVars) { - try { - return minimapWidth.getInt(displayVars); - } catch (IllegalAccessException e) { - return 1; - } - } - - @Final - @Shadow(remap = false) - private static GridRenderer gridRenderer; - - @Final - @Shadow(remap = false) - private Minecraft mc; - - @Shadow(remap = false) - private DisplayVars dv; - - @Inject( - method = "drawOnMapWaypoints", - at = @At(value = "HEAD"), - remap = false, - require = 1, - locals = LocalCapture.CAPTURE_FAILHARD) - private void onBeforeDrawWaypoints(double rotation, CallbackInfo callbackInfo) { - for (LayerManager layerManager : MapState.instance.layers) { - if (layerManager.isLayerActive()) { - if (getShape(dv) == Shape.Circle) { - layerManager.recacheMiniMap((int) mc.thePlayer.posX, (int) mc.thePlayer.posZ, getMinimapWidth(dv)); - } else { - layerManager.recacheMiniMap( - (int) mc.thePlayer.posX, - (int) mc.thePlayer.posZ, - gridRenderer.getWidth(), - gridRenderer.getHeight()); - } - } - } - - for (LayerRenderer layerRenderer : JourneyMapState.instance.renderers) { - if (layerRenderer.isLayerActive()) { - for (DrawStep drawStep : layerRenderer.getDrawStepsCachedForRendering()) { - drawStep.draw(0.0D, 0.0D, gridRenderer, getDrawScale(dv), getFontScale(dv), rotation); - } - } - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java similarity index 84% rename from src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java index ef45c7e1..3ede076e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/bartworks/WorldGenContainerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.bartworks; +package com.sinthoras.visualprospecting.mixins.late.bartworks; import java.util.Random; @@ -24,8 +24,9 @@ public class WorldGenContainerMixin { target = "Lcom/github/bartimaeusnek/bartworks/system/oregen/BW_OreLayer;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), remap = false, require = 1) - private boolean onOreVeinGenerationAttempt(BW_OreLayer worldGen, World world, Random random, String biome, - int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { + private boolean visualprospecting$onOreVeinGenerationAttempt(BW_OreLayer worldGen, World world, Random random, + String biome, int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, + IChunkProvider chunkProvider) { final boolean oreVeinPlaced = worldGen.executeWorldgen( world, random, diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java similarity index 90% rename from src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java index 8cb95861..89c980e5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/galacticgreg/GT_Worldgenerator_SpaceMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.galacticgreg; +package com.sinthoras.visualprospecting.mixins.late.galacticgreg; import java.util.Random; @@ -25,7 +25,7 @@ public class GT_Worldgenerator_SpaceMixin { target = "Lgregtech/api/world/GT_Worldgen;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), remap = false, require = 1) - private boolean onOreVeinGenerated(GT_Worldgen worldGen, World world, Random random, String biome, + private boolean visualprospecting$onOreVeinGenerated(GT_Worldgen worldGen, World world, Random random, String biome, int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { final boolean oreVeinPlaced = worldGen.executeWorldgen( world, diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java similarity index 94% rename from src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java index 6da23a61..87e982b3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.gregtech; +package com.sinthoras.visualprospecting.mixins.late.gregtech; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.world.World; diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java similarity index 99% rename from src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java index 25538b22..e7641a2f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.gregtech; +package com.sinthoras.visualprospecting.mixins.late.gregtech; import static gregtech.api.util.GT_Utility.ItemNBT.getNBT; import static gregtech.api.util.GT_Utility.ItemNBT.setNBT; diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java similarity index 95% rename from src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java index 634afcf3..1ef3fb8d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.gregtech; +package com.sinthoras.visualprospecting.mixins.late.gregtech; import static gregtech.api.util.GT_Utility.ItemNBT.setNBT; @@ -39,7 +39,7 @@ public GT_MetaTileEntity_ScannerMixin() { remap = false, require = 1, cancellable = true) - private void onAnalyzeProspectionData(CallbackInfoReturnable callbackInfoReturnable) { + private void visualprospecting$onAnalyzeProspectionData(CallbackInfoReturnable cir) { final ItemStack itemStack = getInputAt(0); final NBTTagCompound compound = itemStack.getTagCompound(); if (compound.hasKey(Tags.VISUALPROSPECTING_FLAG)) { @@ -67,7 +67,7 @@ private void onAnalyzeProspectionData(CallbackInfoReturnable callbackIn final List foundOreVeins = ServerCache.instance .prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); - if (foundOreVeins.isEmpty() == false) { + if (!foundOreVeins.isEmpty()) { final int pageSize = 7; final int numberOfPages = (foundOreVeins.size() + pageSize) / pageSize; // Equals to // ceil((foundOreVeins.size()) @@ -159,9 +159,9 @@ private void onAnalyzeProspectionData(CallbackInfoReturnable callbackIn calculateOverclockedNess(30, 1000); // In case recipe is too OP for that machine if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) { - callbackInfoReturnable.setReturnValue(FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS); + cir.setReturnValue(FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS); } else { - callbackInfoReturnable.setReturnValue(2); + cir.setReturnValue(2); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java similarity index 78% rename from src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java index 353b25d4..68925442 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.gregtech; +package com.sinthoras.visualprospecting.mixins.late.gregtech; import java.util.Random; @@ -26,9 +26,9 @@ public class WorldGenContainerMixin { target = "Lgregtech/common/GT_Worldgen_GT_Ore_Layer;executeWorldgenChunkified(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIIIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)I"), remap = false, require = 2) - protected int onOreVeinPlaced(GT_Worldgen_GT_Ore_Layer instance, World aWorld, Random aRandom, String aBiome, - int aDimensionType, int aChunkX, int aChunkZ, int aSeedX, int aSeedZ, IChunkProvider aChunkGenerator, - IChunkProvider aChunkProvider) { + protected int visualprospecting$onOreVeinPlaced(GT_Worldgen_GT_Ore_Layer instance, World aWorld, Random aRandom, + String aBiome, int aDimensionType, int aChunkX, int aChunkZ, int aSeedX, int aSeedZ, + IChunkProvider aChunkGenerator, IChunkProvider aChunkProvider) { final int result = instance.executeWorldgenChunkified( aWorld, aRandom, @@ -40,7 +40,7 @@ protected int onOreVeinPlaced(GT_Worldgen_GT_Ore_Layer instance, World aWorld, R aSeedZ, aChunkGenerator, aChunkProvider); - if (result == GT_Worldgen_GT_Ore_Layer.ORE_PLACED && instance.mWorldGenName.equals("NoOresInVein") == false) { + if (result == GT_Worldgen_GT_Ore_Layer.ORE_PLACED && !instance.mWorldGenName.equals("NoOresInVein")) { ServerCache.instance.notifyOreVeinGeneration( aWorld.provider.dimensionId, Utils.coordBlockToChunk(aSeedX), diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java new file mode 100644 index 00000000..72a7caab --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java @@ -0,0 +1,24 @@ +package com.sinthoras.visualprospecting.mixins.late.journeymap; + +import journeymap.client.ui.minimap.DisplayVars; +import journeymap.client.ui.minimap.Shape; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(DisplayVars.class) +public interface DisplayVarsAccessor { + + @Accessor(remap = false) + float getDrawScale(); + + @Accessor(remap = false) + double getFontScale(); + + @Accessor(remap = false) + Shape getShape(); + + @Accessor(remap = false) + int getMinimapWidth(); + +} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java new file mode 100644 index 00000000..5e29333c --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java @@ -0,0 +1,17 @@ +package com.sinthoras.visualprospecting.mixins.late.journeymap; + +import journeymap.client.render.map.GridRenderer; +import journeymap.client.ui.fullscreen.Fullscreen; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Fullscreen.class) +public interface FullscreenAccessor { + + @Accessor(remap = false) + static GridRenderer getGridRenderer() { + throw new IllegalStateException("Mixin accessor failed to apply"); + } + +} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java similarity index 87% rename from src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java index 9919b0db..47c67789 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenActionsMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.journeymap; +package com.sinthoras.visualprospecting.mixins.late.journeymap; import journeymap.client.ui.UIManager; import journeymap.client.ui.component.Button; @@ -35,14 +35,14 @@ public FullscreenActionsMixin() { at = @At(value = "INVOKE", target = "Ljourneymap/client/ui/component/Button;setDrawFrame(Z)V"), remap = false, require = 1) - private void onInitGui(CallbackInfo callbackInfo) { + private void visualprospecting$onInitGui(CallbackInfo ci) { resetVisualProspectingCacheButton = new Button(I18n.format("visualprospecting.button.resetprogress")); resetVisualProspectingCacheButton.setTooltip(I18n.format("visualprospecting.button.resetprogress.tooltip")); buttonList.add(resetVisualProspectingCacheButton); } @Inject(method = "layoutButtons", at = @At("RETURN"), remap = false, require = 1) - private void onLayoutButtons(CallbackInfo callbackInfo) { + private void visualprospecting$onLayoutButtons(CallbackInfo ci) { final ButtonList row = new ButtonList(buttonAbout, resetVisualProspectingCacheButton); row.layoutCenteredHorizontal(width / 2, height / 4, true, 4); } @@ -54,10 +54,10 @@ private void onLayoutButtons(CallbackInfo callbackInfo) { cancellable = true, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void onButtonClicked(GuiButton guibutton, CallbackInfo callbackInfo) { + private void visualprospecting$onButtonClicked(GuiButton guibutton, CallbackInfo ci) { if (guibutton == resetVisualProspectingCacheButton) { UIManager.getInstance().open(ResetClientCacheConfirmation.class); - callbackInfo.cancel(); + ci.cancel(); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java similarity index 93% rename from src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java index 06885e91..78c8ebdd 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/FullscreenMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.journeymap; +package com.sinthoras.visualprospecting.mixins.late.journeymap; import java.util.List; @@ -91,7 +91,7 @@ public FullscreenMixin() { } @Inject(method = "*", at = @At("RETURN"), remap = false, require = 1) - private void init(CallbackInfo callbackInfo) { + private void visualprospecting$init(CallbackInfo ci) { MapState.instance.layers.forEach(LayerManager::forceRefresh); } @@ -106,7 +106,7 @@ void drawMap() { } @Inject(method = "*", at = @At("RETURN"), remap = false, require = 1) - private void onConstructed(CallbackInfo callbackInfo) { + private void visualprospecting$onConstructed(CallbackInfo ci) { MapState.instance.layers.forEach(LayerManager::onOpenMap); } @@ -118,8 +118,8 @@ private void onConstructed(CallbackInfo callbackInfo) { remap = false, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void onBeforeDrawJourneyMapWaypoints(CallbackInfo callbackInfo, boolean refreshReady, StatTimer timer, - int xOffset, int yOffset, float drawScale) { + private void visualprospecting$onBeforeDrawJourneyMapWaypoints(CallbackInfo ci, boolean refreshReady, + StatTimer timer, int xOffset, int yOffset, float drawScale) { final int fontScale = getMapFontScale(); final Minecraft minecraft = Minecraft.getMinecraft(); final int centerBlockX = (int) Math.round(gridRenderer.getCenterBlockX()); @@ -153,7 +153,7 @@ private void onBeforeDrawJourneyMapWaypoints(CallbackInfo callbackInfo, boolean opcode = Opcodes.PUTFIELD), remap = false, require = 1) - private void OnCreateMapTypeToolbar(Fullscreen owner, ThemeToolbar value) { + private void visualprospecting$OnCreateMapTypeToolbar(Fullscreen owner, ThemeToolbar value) { final Theme theme = ThemeFileHandler.getCurrentTheme(); final ButtonList buttonList = new ButtonList(); @@ -250,14 +250,14 @@ public void func_73863_a(int width, int height, float f) { } @Inject(method = "func_73869_a", at = @At(value = "HEAD"), remap = false, require = 1, cancellable = true) - private void onKeyPress(CallbackInfo callbackInfo) { + private void visualprospecting$onKeyPress(CallbackInfo ci) { if ((chat == null || chat.isHidden()) && Constants.isPressed(VP.keyAction)) { for (LayerRenderer layer : JourneyMapState.instance.renderers) { if (layer instanceof WaypointProviderLayerRenderer) { ((WaypointProviderLayerRenderer) layer).onActionKeyPressed(); } } - callbackInfo.cancel(); + ci.cancel(); } } @@ -272,7 +272,7 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { final int scaledMouseX = mx * mc.displayWidth / width; final int scaledMouseY = my * mc.displayHeight / height; final double blockSize = Math.pow(2.0D, gridRenderer.getZoom()); - if (onMapClicked(mouseButton, scaledMouseX, scaledMouseY, blockSize) == false) { + if (!visualprospecting$onMapClicked(mouseButton, scaledMouseX, scaledMouseY, blockSize)) { BlockCoordIntPair blockCoord = gridRenderer .getBlockUnderMouse(Mouse.getEventX(), Mouse.getEventY(), mc.displayWidth, mc.displayHeight); layerDelegate.onMouseClicked( @@ -287,17 +287,15 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { } } - private boolean onMapClicked(int mouseButton, int mouseX, int mouseY, double blockSize) { + private boolean visualprospecting$onMapClicked(int mouseButton, int mouseX, int mouseY, double blockSize) { final long timestamp = System.currentTimeMillis(); final boolean isDoubleClick = mouseX == oldMouseX && mouseY == oldMouseY && timestamp - timeLastClick < 500; oldMouseX = mouseX; oldMouseY = mouseY; timeLastClick = isDoubleClick ? 0 : timestamp; - if (mouseButton != 0) { return false; } - boolean layerHit = false; for (LayerRenderer layer : JourneyMapState.instance.renderers) { if (layer instanceof WaypointProviderLayerRenderer) { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java new file mode 100644 index 00000000..96175c7a --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java @@ -0,0 +1,70 @@ +package com.sinthoras.visualprospecting.mixins.late.journeymap; + +import journeymap.client.render.draw.DrawStep; +import journeymap.client.render.map.GridRenderer; +import journeymap.client.ui.minimap.DisplayVars; +import journeymap.client.ui.minimap.MiniMap; +import journeymap.client.ui.minimap.Shape; + +import net.minecraft.client.Minecraft; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; +import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; +import com.sinthoras.visualprospecting.integration.model.MapState; +import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; + +@Mixin(MiniMap.class) +public abstract class MiniMapMixin { + + @Final + @Shadow(remap = false) + private static GridRenderer gridRenderer; + + @Final + @Shadow(remap = false) + private Minecraft mc; + + @Shadow(remap = false) + private DisplayVars dv; + + @Inject(method = "drawOnMapWaypoints", at = @At(value = "HEAD"), remap = false, require = 1) + private void visualprospecting$onBeforeDrawWaypoints(double rotation, CallbackInfo ci) { + for (LayerManager layerManager : MapState.instance.layers) { + if (layerManager.isLayerActive()) { + if (((DisplayVarsAccessor) dv).getShape() == Shape.Circle) { + layerManager.recacheMiniMap( + (int) mc.thePlayer.posX, + (int) mc.thePlayer.posZ, + ((DisplayVarsAccessor) dv).getMinimapWidth()); + } else { + layerManager.recacheMiniMap( + (int) mc.thePlayer.posX, + (int) mc.thePlayer.posZ, + gridRenderer.getWidth(), + gridRenderer.getHeight()); + } + } + } + + for (LayerRenderer layerRenderer : JourneyMapState.instance.renderers) { + if (layerRenderer.isLayerActive()) { + for (DrawStep drawStep : layerRenderer.getDrawStepsCachedForRendering()) { + drawStep.draw( + 0.0D, + 0.0D, + gridRenderer, + ((DisplayVarsAccessor) dv).getDrawScale(), + ((DisplayVarsAccessor) dv).getFontScale(), + rotation); + } + } + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java similarity index 91% rename from src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java index 0767787a..832a3c76 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/RenderWaypointBeaconMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.journeymap; +package com.sinthoras.visualprospecting.mixins.late.journeymap; import journeymap.client.model.Waypoint; import journeymap.client.render.ingame.RenderWaypointBeacon; @@ -32,7 +32,7 @@ static void doRender(Waypoint waypoint) { target = "Ljourneymap/client/waypoint/WaypointStore;instance()Ljourneymap/client/waypoint/WaypointStore;"), remap = false, require = 1) - private static void onRenderAll(CallbackInfo callbackInfo) { + private static void visualprospecting$onRenderAll(CallbackInfo ci) { for (WaypointManager waypointManager : JourneyMapState.instance.waypointManagers) { if (waypointManager.hasWaypoint()) { final Waypoint waypoint = waypointManager.getJmWaypoint(); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java similarity index 64% rename from src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java index ceaa6dd4..bbae3bac 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/journeymap/WaypointManagerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.journeymap; +package com.sinthoras.visualprospecting.mixins.late.journeymap; import journeymap.client.ui.waypoint.WaypointManager; @@ -6,7 +6,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import com.sinthoras.visualprospecting.integration.model.MapState; import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; @@ -15,14 +14,9 @@ @Mixin(WaypointManager.class) public class WaypointManagerMixin { - @Inject( - method = "toggleItems", - at = @At("HEAD"), - remap = false, - require = 1, - locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void onToggleAllWaypoints(boolean enable, CallbackInfoReturnable callbackInfoReturnable) { - if (enable == false) { + @Inject(method = "toggleItems", at = @At("HEAD"), remap = false, require = 1) + private void visualprospecting$onToggleAllWaypoints(boolean enable, CallbackInfoReturnable cir) { + if (!enable) { for (LayerManager layer : MapState.instance.layers) { if (layer instanceof WaypointProviderManager) { ((WaypointProviderManager) layer).clearActiveWaypoint(); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java similarity index 86% rename from src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java index b4e4e108..cc5a156c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/tcnodetracker/GuiMainMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.tcnodetracker; +package com.sinthoras.visualprospecting.mixins.late.tcnodetracker; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.resources.I18n; @@ -30,11 +30,10 @@ public class GuiMainMixin { opcode = Opcodes.PUTSTATIC, shift = At.Shift.AFTER, remap = false), - remap = true, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION, cancellable = true) - private void onWaypointSet(GuiButton button, CallbackInfo callbackInfo, int i) { + private void visualprospecting$onWaypointSet(GuiButton button, CallbackInfo ci, int i) { final AspectLoc aspect = GuiMain.aspectList.get(low + i); GuiMain.aspectList.clear(); ThaumcraftNodeLayerManager.instance.setActiveWaypoint( @@ -45,7 +44,7 @@ private void onWaypointSet(GuiButton button, CallbackInfo callbackInfo, int i) { aspect.dimID, I18n.format("visualprospecting.tracked", I18n.format("tile.blockAiry.0.name")), 0xFFFFFF)); - callbackInfo.cancel(); + ci.cancel(); } @Inject( @@ -56,9 +55,8 @@ private void onWaypointSet(GuiButton button, CallbackInfo callbackInfo, int i) { opcode = Opcodes.PUTSTATIC, ordinal = 0, remap = false), - remap = true, require = 1) - private void onWaypointClear(CallbackInfo callbackInfo) { + private void visualprospecting$onWaypointClear(CallbackInfo ci) { ThaumcraftNodeLayerManager.instance.clearActiveWaypoint(); } @@ -70,10 +68,9 @@ private void onWaypointClear(CallbackInfo callbackInfo) { opcode = Opcodes.PUTSTATIC, ordinal = 1, remap = false), - remap = true, require = 1, locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void onWaypointDelete(GuiButton button, CallbackInfo callbackInfo, int i, int k, int j) { + private void visualprospecting$onWaypointDelete(GuiButton button, CallbackInfo ci, int i, int k, int j) { ThaumcraftNodeLayerManager.instance.clearActiveWaypoint(); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java similarity index 87% rename from src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java index 987e6c9c..acdeb19a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/MinimapRendererMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.xaerosminimap; +package com.sinthoras.visualprospecting.mixins.late.xaerosminimap; import java.util.ArrayList; @@ -45,8 +45,8 @@ public class MinimapRendererMixin { value = "INVOKE", target = "Lxaero/common/minimap/waypoints/render/WaypointsGuiRenderer;render(Lxaero/common/XaeroMinimapSession;Lxaero/common/minimap/render/MinimapRendererHelper;DDIIDDFDZFZ)V"), locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void injectDraw(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, int y, int width, - int height, int scale, int size, float partial, CallbackInfo ci, ModSettings settings, + private void visualprospecting$injectDraw(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, + int y, int width, int height, int scale, int size, float partial, CallbackInfo ci, ModSettings settings, ArrayList underText, int mapSize, int bufferSize, float minimapScale, float mapScale, float sizeFix, int shape, boolean lockedNorth, double angle, double ps, double pc, boolean useWorldMap, int lightLevel, boolean cave, boolean circleShape, int scaledX, int scaledY, int minimapFrameSize, int circleSides, @@ -91,8 +91,8 @@ private void injectDraw(XaeroMinimapSession minimapSession, MinimapProcessor min to = @At( value = "INVOKE", target = "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V"))) - private void injectBeginStencil(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, int y, - int width, int height, int scale, int size, float partial, CallbackInfo ci) { + private void visualprospecting$injectBeginStencil(XaeroMinimapSession minimapSession, MinimapProcessor minimap, + int x, int y, int width, int height, int scale, int size, float partial, CallbackInfo ci) { if (stencilEnabled && MinecraftForgeClient.getStencilBits() == 0) { stencilEnabled = false; VP.warn("Could not enable stencils! Xaero's minimap overlays will not render"); @@ -112,8 +112,8 @@ private void injectBeginStencil(XaeroMinimapSession minimapSession, MinimapProce from = @At( value = "INVOKE", target = "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V"))) - private void injectEndStencil(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, int y, int width, - int height, int scale, int size, float partial, CallbackInfo ci) { + private void visualprospecting$injectEndStencil(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, + int y, int width, int height, int scale, int size, float partial, CallbackInfo ci) { GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); GL11.glStencilMask(0x00); GL11.glDisable(GL11.GL_STENCIL_TEST); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java similarity index 88% rename from src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java index ee5bf15a..b74262ce 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosminimap/WaypointsIngameRendererMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.xaerosminimap; +package com.sinthoras.visualprospecting.mixins.late.xaerosminimap; import net.minecraft.client.Minecraft; @@ -28,7 +28,8 @@ public class WaypointsIngameRendererMixin { value = "FIELD", target = "Lxaero/common/minimap/waypoints/WaypointsManager;customWaypoints:Ljava/util/Hashtable;", opcode = Opcodes.GETSTATIC))) - private void injectPreRenderCustomWaypoints(XaeroMinimapSession sets, float modCustomWaypoints, CallbackInfo ci) { + private void visualprospecting$injectPreRenderCustomWaypoints(XaeroMinimapSession sets, float modCustomWaypoints, + CallbackInfo ci) { for (WaypointManager manager : XaeroMiniMapState.instance.waypointManagers) { if (manager.hasWaypoint()) { manager.getXWaypoint().notifyDimension(Minecraft.getMinecraft().renderViewEntity.dimension); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java similarity index 90% rename from src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java index db533483..5f5b7571 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/xaerosworldmap/GuiMapMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.mixins.xaerosworldmap; +package com.sinthoras.visualprospecting.mixins.late.xaerosworldmap; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; @@ -64,8 +64,8 @@ protected GuiMapMixin(GuiScreen parent, GuiScreen escape) { private int screenScale; @Inject(method = "", at = @At("RETURN")) - private void injectConstruct(GuiScreen parent, GuiScreen escape, MapProcessor mapProcessor, Entity player, - CallbackInfo ci) { + private void visualprospecting$injectConstruct(GuiScreen parent, GuiScreen escape, MapProcessor mapProcessor, + Entity player, CallbackInfo ci) { MapState.instance.layers.forEach(LayerManager::onOpenMap); } @@ -76,8 +76,8 @@ private void injectConstruct(GuiScreen parent, GuiScreen escape, MapProcessor ma method = "func_73863_a", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glPushMatrix()V", ordinal = 1), locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void injectPreRender(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci, - Minecraft mc) { + private void visualprospecting$injectPreRender(int scaledMouseX, int scaledMouseY, float partialTicks, + CallbackInfo ci, Minecraft mc) { // snap the camera to whole pixel values. works around a rendering issue but causes another when framerate is // uncapped if (mc.gameSettings.limitFramerate < 255 || mc.gameSettings.enableVsync) { @@ -109,7 +109,7 @@ private void injectPreRender(int scaledMouseX, int scaledMouseY, float partialTi to = @At( value = "INVOKE", target = "Lxaero/map/mods/SupportXaeroMinimap;renderWaypoints(Lnet/minecraft/client/gui/GuiScreen;DDIIDDDDLjava/util/regex/Pattern;Ljava/util/regex/Pattern;FLxaero/map/mods/gui/Waypoint;Lnet/minecraft/client/Minecraft;Lnet/minecraft/client/gui/ScaledResolution;)Lxaero/map/mods/gui/Waypoint;"))) - private void injectDraw(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci) { + private void visualprospecting$injectDraw(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci) { for (LayerManager layerManager : MapState.instance.layers) { if (layerManager.isLayerActive()) { // +20s are to work around precision loss from casting to int and right-shifting @@ -142,7 +142,8 @@ private void injectDraw(int scaledMouseX, int scaledMouseY, float partialTicks, target = "Lnet/minecraft/client/Minecraft;field_71462_r:Lnet/minecraft/client/gui/GuiScreen;", opcode = Opcodes.GETFIELD), to = @At(value = "INVOKE", target = "Lxaero/map/gui/CursorBox;drawBox(IIII)V"))) - private void injectDrawTooltip(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci) { + private void visualprospecting$injectDrawTooltip(int scaledMouseX, int scaledMouseY, float partialTicks, + CallbackInfo ci) { for (LayerRenderer layer : XaeroWorldMapState.instance.renderers) { if (layer instanceof InteractableLayerRenderer && layer.isLayerActive()) { ((InteractableLayerRenderer) layer).drawTooltip(this, scale, screenScale); @@ -154,7 +155,7 @@ private void injectDrawTooltip(int scaledMouseX, int scaledMouseY, float partial @Inject( method = "func_73866_w_", at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Keyboard;enableRepeatEvents(Z)V")) - private void injectInitButtons(CallbackInfo ci) { + private void visualprospecting$injectInitButtons(CallbackInfo ci) { for (int i = 0; i < XaeroWorldMapState.instance.buttons.size(); i++) { LayerButton layerButton = XaeroWorldMapState.instance.buttons.get(i); SizedGuiTexturedButton button = new SizedGuiTexturedButton( @@ -169,7 +170,7 @@ private void injectInitButtons(CallbackInfo ci) { } @Inject(method = "onInputPress", at = @At("TAIL")) - private void injectListenKeypress(boolean mouse, int code, CallbackInfoReturnable cir) { + private void visualprospecting$injectListenKeypress(boolean mouse, int code, CallbackInfoReturnable cir) { if (Misc.inputMatchesKeyBinding(mouse, code, VP.keyAction)) { for (LayerRenderer layer : XaeroWorldMapState.instance.renderers) { if (layer instanceof InteractableLayerRenderer) { @@ -180,7 +181,7 @@ private void injectListenKeypress(boolean mouse, int code, CallbackInfoReturnabl } @Inject(method = "mapClicked", at = @At("TAIL")) - private void injectListenClick(int button, int x, int y, CallbackInfo ci) { + private void visualprospecting$injectListenClick(int button, int x, int y, CallbackInfo ci) { if (button == 0) { final long timestamp = System.currentTimeMillis(); final boolean isDoubleClick = x == oldMouseX && y == oldMouseY && timestamp - timeLastClick < 500; diff --git a/src/main/resources/META-INF/visualprospecting_at.cfg b/src/main/resources/META-INF/visualprospecting_at.cfg deleted file mode 100644 index 942b84ee..00000000 --- a/src/main/resources/META-INF/visualprospecting_at.cfg +++ /dev/null @@ -1 +0,0 @@ -public net.minecraft.server.MinecraftServer field_71298_S # userMessage \ No newline at end of file diff --git a/src/main/resources/mixins.visualprospecting.early.json b/src/main/resources/mixins.visualprospecting.early.json new file mode 100644 index 00000000..e5e57325 --- /dev/null +++ b/src/main/resources/mixins.visualprospecting.early.json @@ -0,0 +1,8 @@ +{ + "required": true, + "minVersion": "0.7.11", + "package": "com.sinthoras.visualprospecting.mixins.early", + "refmap": "mixins.visualprospecting.refmap.json", + "target": "@env(DEFAULT)", + "compatibilityLevel": "JAVA_8" +} diff --git a/src/main/resources/mixins.visualprospecting.json b/src/main/resources/mixins.visualprospecting.json new file mode 100644 index 00000000..f7ff5a1e --- /dev/null +++ b/src/main/resources/mixins.visualprospecting.json @@ -0,0 +1,8 @@ +{ + "required": true, + "minVersion": "0.7.11", + "package": "com.sinthoras.visualprospecting.mixins", + "refmap": "mixins.visualprospecting.refmap.json", + "target": "@env(DEFAULT)", + "compatibilityLevel": "JAVA_8" +} diff --git a/src/main/resources/mixins.visualprospecting.late.json b/src/main/resources/mixins.visualprospecting.late.json new file mode 100644 index 00000000..78c68a5e --- /dev/null +++ b/src/main/resources/mixins.visualprospecting.late.json @@ -0,0 +1,8 @@ +{ + "required": true, + "minVersion": "0.7.11", + "package": "com.sinthoras.visualprospecting.mixins.late", + "refmap": "mixins.visualprospecting.refmap.json", + "target": "@env(DEFAULT)", + "compatibilityLevel": "JAVA_8" +} From d3b7e191d5daa0b861745acefd3a75a6c733a41a Mon Sep 17 00:00:00 2001 From: chochem <40274384+chochem@users.noreply.github.com> Date: Sun, 23 Apr 2023 11:15:05 +0100 Subject: [PATCH 022/132] Better english translation for depleted veins (#28) * mark depleted * dep * different dep --- dependencies.gradle | 4 ++-- src/main/resources/assets/visualprospecting/lang/en_US.lang | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index f4877300..3e8781b2 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,14 +1,14 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.0.0:dev') - compile('com.github.GTNewHorizons:GT5-Unofficial:5.09.41.34:dev') + compile('com.github.GTNewHorizons:GT5-Unofficial:5.09.42.71:dev') compile('com.github.GTNewHorizons:TCNodeTracker:1.1.6:dev') compile('net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev') compile('curse.maven:journeymap-32274:2367915') compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.8:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.5.82:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.6.14:dev') {transitive = false} compileOnly(deobf('https://media.forgecdn.net/files/4127/308/Xaeros_Minimap_21.10.30_Forge_1.7.10.jar')) compileOnly(deobf('https://media.forgecdn.net/files/4127/328/XaerosWorldMap_1.14.1.22_Forge_1.7.10.jar')) diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index 5dd34a58..589ded9e 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -41,5 +41,5 @@ item.visualprospecting.prospectorslog.reading.fail3=[Failed]: Yeah..No. I can't item.visualprospecting.prospectorslog.reading.fail4=[Failed]: Do I have a Ph.D. in Geography? NOPE! item.visualprospecting.prospectorslog.reading.begin=Those are quite some pages. It might take some time to fully read it. item.visualprospecting.prospectorslog.reading.end=I finished the Prospector's Log of %s -visualprospecting.node.deletehint=Remove with %s +visualprospecting.node.deletehint=Mark depleted with %s visualprospecting.tracked=Tracked: %s From 68bb4aac16bc8b3f0dda2cab7a30ffb6431649ef Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Fri, 12 May 2023 23:43:00 +0200 Subject: [PATCH 023/132] Update dependencies.gradle --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 3e8781b2..c561b3a7 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -5,7 +5,7 @@ dependencies { compile('com.github.GTNewHorizons:TCNodeTracker:1.1.6:dev') compile('net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev') - compile('curse.maven:journeymap-32274:2367915') + compile('curse.maven:journeymap-32274:4500659') compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.8:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:bartworks:0.6.14:dev') {transitive = false} From 062d413959044828a559eb1f90e0f59b8270f3bf Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sat, 13 May 2023 14:11:45 +0200 Subject: [PATCH 024/132] Bs+sa (#29) * update bs+sa+dep * update * fix unimixin uses * Update dependency types --------- Co-authored-by: miozune --- build.gradle | 494 +++++++++++++----- dependencies.gradle | 11 +- gradle/wrapper/gradle-wrapper.properties | 2 +- repositories.gradle | 26 - .../sinthoras/visualprospecting/Utils.java | 1 + .../database/ClientCache.java | 1 + .../database/RedoServerCacheCommand.java | 1 + .../database/cachebuilder/ChunkAnalysis.java | 1 + .../cachebuilder/DetailedChunkAnalysis.java | 1 + .../database/cachebuilder/WorldAnalysis.java | 1 + .../database/veintypes/VeinType.java | 1 + .../database/veintypes/VeinTypeCaching.java | 5 +- .../hooks/HooksEventBus.java | 1 + .../hooks/ProspectingNotificationEvent.java | 1 + .../journeymap/JourneyMapState.java | 4 +- .../ResetClientCacheConfirmation.java | 10 +- .../journeymap/buttons/LayerButton.java | 4 +- .../drawsteps/ClickableDrawStep.java | 4 +- .../drawsteps/DirtyChunkDrawStep.java | 6 +- .../journeymap/drawsteps/OreVeinDrawStep.java | 6 +- .../drawsteps/ThaumcraftNodeDrawStep.java | 9 +- .../UndergroundFluidChunkDrawStep.java | 8 +- .../drawsteps/UndergroundFluidDrawStep.java | 6 +- .../journeymap/render/DirtyChunkRenderer.java | 4 +- .../journeymap/render/LayerRenderer.java | 4 +- .../render/UndergroundFluidChunkRenderer.java | 4 +- .../render/UndergroundFluidRenderer.java | 4 +- .../locations/ThaumcraftNodeLocation.java | 8 +- .../waypoints/WaypointManager.java | 4 +- .../rendersteps/ThaumcraftNodeRenderStep.java | 6 +- .../item/ProspectorsLog.java | 1 + .../VisualProspectingEarlyMixinLoader.java | 1 + .../GT_Worldgenerator_SpaceMixin.java | 4 +- .../late/journeymap/DisplayVarsAccessor.java | 6 +- .../late/journeymap/FullscreenAccessor.java | 6 +- .../journeymap/FullscreenActionsMixin.java | 12 +- .../late/journeymap/FullscreenMixin.java | 38 +- .../mixins/late/journeymap/MiniMapMixin.java | 12 +- .../journeymap/RenderWaypointBeaconMixin.java | 6 +- .../late/journeymap/WaypointManagerMixin.java | 4 +- .../late/tcnodetracker/GuiMainMixin.java | 2 +- .../xaerosminimap/MinimapRendererMixin.java | 10 +- .../WaypointsIngameRendererMixin.java | 6 +- .../late/xaerosworldmap/GuiMapMixin.java | 12 +- 44 files changed, 494 insertions(+), 264 deletions(-) diff --git a/build.gradle b/build.gradle index fe8a2e7b..3fa171e0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1675110695 +//version: 1683705740 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -6,27 +6,28 @@ */ -import com.diffplug.blowdryer.Blowdryer -import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.gtnewhorizons.retrofuturagradle.ObfuscationAttribute import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar +import com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask +import com.gtnewhorizons.retrofuturagradle.util.Distribution import com.matthewprenger.cursegradle.CurseArtifact import com.matthewprenger.cursegradle.CurseRelation import com.modrinth.minotaur.dependencies.ModDependency import com.modrinth.minotaur.dependencies.VersionDependency import org.gradle.internal.logging.text.StyledTextOutput.Style import org.gradle.internal.logging.text.StyledTextOutputFactory -import org.jetbrains.gradle.ext.* +import org.gradle.internal.xml.XmlTransformer +import org.jetbrains.gradle.ext.Application +import org.jetbrains.gradle.ext.Gradle +import javax.inject.Inject import java.nio.file.Files import java.nio.file.Paths import java.util.concurrent.TimeUnit -import java.util.zip.ZipEntry -import java.util.zip.ZipOutputStream buildscript { repositories { - mavenLocal() mavenCentral() maven { @@ -47,6 +48,8 @@ buildscript { name 'Scala CI dependencies' url 'https://repo1.maven.org/maven2/' } + + mavenLocal() } } plugins { @@ -58,22 +61,26 @@ plugins { id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false - id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version ,unused, available for addon.gradle - id 'com.github.johnrengelman.shadow' version '7.1.2' apply false - id 'com.palantir.git-version' version '0.13.0' apply false // 0.13.0 is the last jvm8 supporting version - id 'de.undercouch.download' version '5.3.0' + id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle + id 'com.github.johnrengelman.shadow' version '8.1.1' apply false + id 'com.palantir.git-version' version '3.0.0' apply false + id 'de.undercouch.download' version '5.4.0' id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle - id 'com.diffplug.spotless' version '6.7.2' apply false + id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.1.2' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.11' } + +print("You might want to check out './gradlew :faq' if your build fails.\n") + boolean settingsupdated = verifySettingsGradle() settingsupdated = verifyGitAttributes() || settingsupdated if (settingsupdated) throw new GradleException("Settings has been updated, please re-run task.") -if (project.file('.git/HEAD').isFile()) { +// In submodules, .git is a file pointing to the real git dir +if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) { apply plugin: 'com.palantir.git-version' } @@ -122,7 +129,10 @@ propertyDefaultIfUnset("gradleTokenGroupName", "") propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only -project.extensions.add(Blowdryer, "Blowdryer", Blowdryer) // Make blowdryer available in "apply from:" scripts +// this is meant to be set using the user wide property file. by default we do nothing. +propertyDefaultIfUnset("ideaOverrideBuildType", "") // Can be nothing, "gradle" or "idea" + +project.extensions.add(com.diffplug.blowdryer.Blowdryer, "Blowdryer", com.diffplug.blowdryer.Blowdryer) // Make blowdryer available in "apply from:" scripts if (!disableSpotless) { apply plugin: 'com.diffplug.spotless' apply from: Blowdryer.file('spotless.gradle') @@ -143,13 +153,21 @@ java { } else { languageVersion.set(projectJavaVersion) } - vendor.set(JvmVendorSpec.ADOPTIUM) + vendor.set(JvmVendorSpec.AZUL) } if (!noPublishedSources) { withSourcesJar() } } +tasks.withType(JavaCompile).configureEach { + options.encoding = "UTF-8" +} + +tasks.withType(ScalaCompile).configureEach { + options.encoding = "UTF-8" +} + pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { // If Kotlin is enabled in the project kotlin { @@ -183,14 +201,34 @@ configurations { canBeConsumed = false canBeResolved = false } + + create("devOnlyNonPublishable") { + description = "Runtime and compiletime dependencies that are not published alongside the jar (compileOnly + runtimeOnlyNonPublishable)" + canBeConsumed = false + canBeResolved = false + } + compileOnly.extendsFrom(devOnlyNonPublishable) + runtimeOnlyNonPublishable.extendsFrom(devOnlyNonPublishable) } if (enableModernJavaSyntax.toBoolean()) { + repositories { + mavenCentral { + mavenContent { + includeGroup("me.eigenraven.java8unsupported") + } + } + } + dependencies { annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' + // workaround for https://github.com/bsideup/jabel/issues/174 + annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0' compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { transitive = false // We only care about the 1 annotation class } + // Allow using jdk.unsupported classes like sun.misc.Unsafe in the compiled code, working around JDK-8206937. + patchedMinecraft('me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0') } tasks.withType(JavaCompile).configureEach { @@ -202,7 +240,7 @@ if (enableModernJavaSyntax.toBoolean()) { javaCompiler.set(javaToolchains.compilerFor { languageVersion.set(JavaLanguageVersion.of(17)) - vendor.set(JvmVendorSpec.ADOPTIUM) + vendor.set(JvmVendorSpec.AZUL) }) } } @@ -234,12 +272,14 @@ if (apiPackage) { } 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) + for (atFile in accessTransformersFile.split(",")) { + String targetFile = "src/main/resources/META-INF/" + atFile.trim() + if (!getFile(targetFile).exists()) { + throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) + } + tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) + tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) } - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) } else { boolean atsFound = false for (File at : sourceSets.getByName("main").resources.files) { @@ -367,12 +407,14 @@ minecraft { injectMissingGenerics.set(true) } + username = developmentEnvironmentUserName.toString() + + lwjgl3Version = "3.3.2" + // Enable assertions in the current mod extraRunJvmArguments.add("-ea:${modGroup}") if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - extraTweakClasses.add("org.spongepowered.asm.launch.MixinTweaker") - if (usesMixinDebug.toBoolean()) { extraRunJvmArguments.addAll([ "-Dmixin.debug.countInjections=true", @@ -401,6 +443,16 @@ configurations.configureEach { } } } + def obfuscationAttr = it.attributes.getAttribute(ObfuscationAttribute.OBFUSCATION_ATTRIBUTE) + if (obfuscationAttr != null && obfuscationAttr.name == ObfuscationAttribute.SRG) { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + // Remap CoFH core cursemaven dev jar to the obfuscated version for runObfClient/Server + if (details.requested.group == 'curse.maven' && details.requested.name.endsWith('-69162') && details.requested.version == '2388751') { + details.useVersion '2388750' + details.because 'Pick obfuscated jar' + } + } + } } // Ensure tests have access to minecraft classes @@ -430,8 +482,9 @@ repositories.configureEach { repo -> apply from: 'repositories.gradle' configurations { + runtimeClasspath.extendsFrom(runtimeOnlyNonPublishable) + testRuntimeClasspath.extendsFrom(runtimeOnlyNonPublishable) for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { - config.extendsFrom(runtimeOnlyNonPublishable) if (usesShadowedDependencies.toBoolean()) { config.extendsFrom(shadowImplementation) // TODO: remove Compile after all uses are refactored to Implementation @@ -476,12 +529,11 @@ repositories { url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" allowInsecureProtocol = true } - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - if (usesMixinDebug.toBoolean()) { - maven { - name = "Fabric Maven" - url = "https://maven.fabricmc.net/" - } + maven { + name 'sonatype' + url 'https://oss.sonatype.org/content/repositories/snapshots/' + content { + includeGroup "org.lwjgl" } } if (includeWellKnownRepositories.toBoolean()) { @@ -515,29 +567,50 @@ repositories { } } +def mixinProviderGroup = "io.github.legacymoddingmc" +def mixinProviderModule = "unimixins" +def mixinProviderVersion = "0.1.7.1" +def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}" +def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev" +ext.mixinProviderSpec = mixinProviderSpec + 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('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + annotationProcessor(mixinProviderSpec) if (usesMixinDebug.toBoolean()) { runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16') } } - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - implementation('com.gtnewhorizon:gtnhmixins:2.1.10') + if (usesMixins.toBoolean()) { + implementation(mixinProviderSpec) + } else if (forceEnableMixins.toBoolean()) { + runtimeOnlyNonPublishable(mixinProviderSpec) } } pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { if (usesMixins.toBoolean()) { dependencies { - kapt('com.gtnewhorizon:gtnhmixins:2.1.10:processor') + kapt(mixinProviderSpec) } } } +// Replace old mixin mods with unimixins +// https://docs.gradle.org/8.0.2/userguide/resolution_rules.html#sec:substitution_with_classifier +configurations.all { + resolutionStrategy.dependencySubstitution { + substitute module('com.gtnewhorizon:gtnhmixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:Mixingasm') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") + substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier") + } +} + apply from: 'dependencies.gradle' def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' @@ -633,7 +706,156 @@ tasks.named("processResources", ProcessResources).configure { if (usesMixins.toBoolean()) { from refMap + dependsOn("compileJava", "compileScala") + } +} + +ext.java17Toolchain = (JavaToolchainSpec spec) -> { + spec.languageVersion.set(JavaLanguageVersion.of(17)) + spec.vendor.set(JvmVendorSpec.matching("jetbrains")) +} + +ext.java17DependenciesCfg = configurations.create("java17Dependencies") { + extendsFrom(configurations.getByName("runtimeClasspath")) // Ensure consistent transitive dependency resolution + canBeConsumed = false +} +ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies") { + canBeConsumed = false +} + +dependencies { + def lwjgl3ifyVersion = '1.3.5' + def asmVersion = '9.4' + if (modId != 'lwjgl3ify') { + java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") + } + if (modId != 'hodgepodge') { + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.8') + } + + java17PatchDependencies('net.minecraft:launchwrapper:1.15') {transitive = false} + java17PatchDependencies("org.ow2.asm:asm:${asmVersion}") + java17PatchDependencies("org.ow2.asm:asm-commons:${asmVersion}") + java17PatchDependencies("org.ow2.asm:asm-tree:${asmVersion}") + java17PatchDependencies("org.ow2.asm:asm-analysis:${asmVersion}") + java17PatchDependencies("org.ow2.asm:asm-util:${asmVersion}") + java17PatchDependencies('org.ow2.asm:asm-deprecated:7.1') + java17PatchDependencies("org.apache.commons:commons-lang3:3.12.0") + java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} +} + +ext.java17JvmArgs = [ + // Java 9+ support + "--illegal-access=warn", + "-Djava.security.manager=allow", + "-Dfile.encoding=UTF-8", + "--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED", + "--add-opens", "java.base/java.net=ALL-UNNAMED", + "--add-opens", "java.base/java.nio=ALL-UNNAMED", + "--add-opens", "java.base/java.io=ALL-UNNAMED", + "--add-opens", "java.base/java.lang=ALL-UNNAMED", + "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", + "--add-opens", "java.base/java.text=ALL-UNNAMED", + "--add-opens", "java.base/java.util=ALL-UNNAMED", + "--add-opens", "java.base/jdk.internal.reflect=ALL-UNNAMED", + "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", + "--add-opens", "jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED,java.naming", + "--add-opens", "java.desktop/sun.awt.image=ALL-UNNAMED", + "--add-modules", "jdk.dynalink", + "--add-opens", "jdk.dynalink/jdk.dynalink.beans=ALL-UNNAMED", + "--add-modules", "java.sql.rowset", + "--add-opens", "java.sql.rowset/javax.sql.rowset.serial=ALL-UNNAMED" +] + +ext.hotswapJvmArgs = [ + // DCEVM advanced hot reload + "-XX:+AllowEnhancedClassRedefinition", + "-XX:HotswapAgent=fatjar" +] + +ext.setupHotswapAgentTask = tasks.register("setupHotswapAgent") { + group = "GTNH Buildscript" + description = "Installs a recent version of HotSwapAgent into the Java 17 JetBrains runtime directory" + def hsaUrl = 'https://github.com/HotswapProjects/HotswapAgent/releases/download/1.4.2-SNAPSHOT/hotswap-agent-1.4.2-SNAPSHOT.jar' + def targetFolderProvider = javaToolchains.launcherFor(java17Toolchain).map {it.metadata.installationPath.dir("lib/hotswap")} + def targetFilename = "hotswap-agent.jar" + onlyIf { + !targetFolderProvider.get().file(targetFilename).asFile.exists() } + doLast { + def targetFolder = targetFolderProvider.get() + targetFolder.asFile.mkdirs() + download.run { + src hsaUrl + dest targetFolder.file(targetFilename).asFile + overwrite false + tempAndMove true + } + } +} + +public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask { + // IntelliJ doesn't seem to allow commandline arguments so we also support an env variable + private boolean enableHotswap = Boolean.valueOf(System.getenv("HOTSWAP")); + + @Input + public boolean getEnableHotswap() { return enableHotswap } + @Option(option = "hotswap", description = "Enables HotSwapAgent for enhanced class reloading under a debugger") + public boolean setEnableHotswap(boolean enable) { enableHotswap = enable } + + @Inject + public RunHotswappableMinecraftTask(Distribution side, String superTask, org.gradle.api.invocation.Gradle gradle) { + super(side, gradle) + + this.lwjglVersion = 3 + this.javaLauncher = project.javaToolchains.launcherFor(project.java17Toolchain) + this.extraJvmArgs.addAll(project.java17JvmArgs) + this.extraJvmArgs.addAll(project.provider(() -> enableHotswap ? project.hotswapJvmArgs : [])) + + this.classpath(project.java17PatchDependenciesCfg) + if (side == Distribution.CLIENT) { + this.classpath(project.minecraftTasks.lwjgl3Configuration) + } + // Use a raw provider instead of map to not create a dependency on the task + this.classpath(project.provider(() -> project.tasks.named(superTask, RunMinecraftTask).get().classpath)) + this.classpath.filter { file -> + !file.path.contains("2.9.4-nightly-20150209") // Remove lwjgl2 + } + this.classpath(project.java17DependenciesCfg) + } + + public void setup(Project project) { + super.setup(project) + if (project.usesMixins.toBoolean()) { + this.extraJvmArgs.addAll(project.provider(() -> { + def mixinCfg = project.configurations.detachedConfiguration(project.dependencies.create(project.mixinProviderSpec)) + mixinCfg.canBeConsumed = false + mixinCfg.transitive = false + enableHotswap ? ["-javaagent:" + mixinCfg.singleFile.absolutePath] : [] + })) + } + } +} + +def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient") +runClient17Task.configure { + setup(project) + group = "Modded Minecraft" + description = "Runs the modded client using Java 17, lwjgl3ify and Hodgepodge" + dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') + mainClass = "GradleStart" + username = minecraft.username + userUUID = minecraft.userUUID +} + +def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") +runServer17Task.configure { + setup(project) + group = "Modded Minecraft" + description = "Runs the modded server using Java 17, lwjgl3ify and Hodgepodge" + dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') + mainClass = "GradleStartServer" + extraArgs.add("nogui") } def getManifestAttributes() { @@ -667,11 +889,6 @@ tasks.named("jar", Jar).configure { } if (usesShadowedDependencies.toBoolean()) { - tasks.register('relocateShadowJar', ConfigureShadowRelocation) { - target = tasks.shadowJar - prefix = modGroup + ".shadow" - enabled = minimizeShadowedDependencies.toBoolean() - } tasks.named("shadowJar", ShadowJar).configure { manifest { attributes(getManifestAttributes()) @@ -686,8 +903,9 @@ if (usesShadowedDependencies.toBoolean()) { project.configurations.shadeCompile ] archiveClassifier.set('dev') - if (minimizeShadowedDependencies.toBoolean()) { - dependsOn(relocateShadowJar) + if (relocateShadowedDependencies.toBoolean()) { + relocationPrefix = modGroup + ".shadow" + enableRelocation = true } } configurations.runtimeElements.outgoing.artifacts.clear() @@ -705,7 +923,7 @@ if (usesShadowedDependencies.toBoolean()) { javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { skip() } - for (runTask in ["runClient", "runServer"]) { + for (runTask in ["runClient", "runServer", "runClient17", "runServer17"]) { tasks.named(runTask).configure { dependsOn("shadowJar") } @@ -743,9 +961,23 @@ idea { module { downloadJavadoc = true downloadSources = true + inheritOutputDirs = true } project { settings { + if (ideaOverrideBuildType != "") { + delegateActions { + if ("gradle".equalsIgnoreCase(ideaOverrideBuildType)) { + delegateBuildRunToGradle = true + testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.GRADLE + } else if ("idea".equalsIgnoreCase(ideaOverrideBuildType)) { + delegateBuildRunToGradle = false + testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM + } else { + throw GradleScriptException('Accepted value for ideaOverrideBuildType is one of gradle or idea.') + } + } + } runConfigurations { "1. Run Client"(Gradle) { taskNames = ["runClient"] @@ -753,6 +985,20 @@ idea { "2. Run Server"(Gradle) { taskNames = ["runServer"] } + "1a. Run Client (Java 17)"(Gradle) { + taskNames = ["runClient17"] + } + "2a. Run Server (Java 17)"(Gradle) { + taskNames = ["runServer17"] + } + "1b. Run Client (Java 17, Hotswap)"(Gradle) { + taskNames = ["runClient17"] + envs = ["HOTSWAP": "true"] + } + "2b. Run Server (Java 17, Hotswap)"(Gradle) { + taskNames = ["runServer17"] + envs = ["HOTSWAP": "true"] + } "3. Run Obfuscated Client"(Gradle) { taskNames = ["runObfClient"] } @@ -770,7 +1016,7 @@ idea { } "Run Client (IJ Native)"(Application) { mainClass = "GradleStart" - moduleName = project.name + ".main" + moduleName = project.name + ".ideVirtualMain" afterEvaluate { workingDirectory = tasks.runClient.workingDir.absolutePath programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ') @@ -781,7 +1027,7 @@ idea { } "Run Server (IJ Native)"(Application) { mainClass = "GradleStartServer" - moduleName = project.name + ".main" + moduleName = project.name + ".ideVirtualMain" afterEvaluate { workingDirectory = tasks.runServer.workingDir.absolutePath programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ') @@ -793,11 +1039,57 @@ idea { } compiler.javac { afterEvaluate { + javacAdditionalOptions = "-encoding utf8" moduleJavacAdditionalOptions = [ (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') ] } } + withIDEADir { File ideaDir -> + if (!ideaDir.path.contains(".idea")) { + // If an .ipr file exists, the project root directory is passed here instead of the .idea subdirectory + ideaDir = new File(ideaDir, ".idea") + } + if (ideaDir.isDirectory()) { + def miscFile = new File(ideaDir, "misc.xml") + if (miscFile.isFile()) { + boolean dirty = false + def miscTransformer = new XmlTransformer() + miscTransformer.addAction { root -> + Node rootNode = root.asNode() + def rootManager = rootNode + .component.find { it.@name == 'ProjectRootManager' } + if (!rootManager) { + rootManager = rootNode.appendNode('component', ['name': 'ProjectRootManager', 'version': '2']) + dirty = true + } + def output = rootManager.output + if (!output) { + output = rootManager.appendNode('output') + dirty = true + } + if (!output.@url) { + // Only modify the output url if it doesn't yet have one, or if the existing one is blank somehow. + // This is a sensible default for most setups + output.@url = 'file://$PROJECT_DIR$/build/ideaBuild' + dirty = true + } + } + def result = miscTransformer.transform(miscFile.text) + if (dirty) { + miscFile.write(result) + } + } else { + miscFile.text = """ + + + + + +""" + } + } + } } } } @@ -867,7 +1159,7 @@ if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { } } if (usesMixins.toBoolean()) { - addModrinthDep("required", "project", "gtnhmixins") + addModrinthDep("required", "project", "unimixins") } tasks.modrinth.dependsOn(build) tasks.publish.dependsOn(tasks.modrinth) @@ -911,7 +1203,7 @@ if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null } } if (usesMixins.toBoolean()) { - addCurseForgeRelation("requiredDependency", "gtnhmixins") + addCurseForgeRelation("requiredDependency", "unimixins") } tasks.curseforge.dependsOn(build) tasks.publish.dependsOn(tasks.curseforge) @@ -945,10 +1237,21 @@ def addCurseForgeRelation(String type, String name) { } // Updating + +def buildscriptGradleVersion = "8.1.1" + +tasks.named('wrapper', Wrapper).configure { + gradleVersion = buildscriptGradleVersion +} + tasks.register('updateBuildScript') { group = 'GTNH Buildscript' description = 'Updates the build script to the latest version' + if (gradle.gradleVersion != buildscriptGradleVersion && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_GRADLE_UPDATE')) { + dependsOn('wrapper') + } + doLast { if (performBuildScriptUpdate()) return @@ -961,6 +1264,24 @@ if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISA performBuildScriptUpdate() } else { out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") + if (gradle.gradleVersion != buildscriptGradleVersion) { + out.style(Style.SuccessHeader).println("updateBuildScript can update gradle from ${gradle.gradleVersion} to ${buildscriptGradleVersion}\n") + } + } +} + +// If you want to add more cases to this task, implement them as arguments if total amount to print gets too large +tasks.register('faq') { + group = 'GTNH Buildscript' + description = 'Prints frequently asked questions about building a project' + + doLast { + print("If your build fails to fetch dependencies, they might have been deleted and replaced by newer " + + "versions.\nCheck if the versions you try to fetch are still on the distributing sites.\n" + + "The links can be found in repositories.gradle and build.gradle:repositories, " + + "not build.gradle:buildscript.repositories - this one is for gradle plugin metadata.\n\n" + + "If your build fails to recognize the syntax of new Java versions, enable Jabel in your " + + "gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties.") } } @@ -1101,7 +1422,7 @@ static int replaceParams(File file, Map params) { return 0 } -// Dependency Deobfuscation +// Dependency Deobfuscation (Deprecated, use the new RFG API documented in dependencies.gradle) def deobf(String sourceURL) { try { @@ -1143,11 +1464,7 @@ def deobfMaven(String repoURL, String mavenDep) { } def deobfCurse(String curseDep) { - try { - return deobfMaven("https://www.cursemaven.com/", "curse.maven:$curseDep") - } catch (Exception ignored) { - out.style(Style.Failure).println("Failed to get $curseDep from cursemaven.") - } + return dependencies.rfg.deobf("curse.maven:$curseDep") } // The method above is to be preferred. Use this method if the filename is not at the end of the URL. @@ -1155,34 +1472,7 @@ def deobf(String sourceURL, String rawFileName) { String bon2Version = "2.5.1" String fileName = URLDecoder.decode(rawFileName, "UTF-8") String cacheDir = "$project.gradle.gradleUserHomeDir/caches" - String bon2Dir = "$cacheDir/forge_gradle/deobf" - String bon2File = "$bon2Dir/BON2-${bon2Version}.jar" String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar" - String deobfFile = "$cacheDir/modules-2/files-2.1/${fileName}-deobf.jar" - - if (file(deobfFile).exists()) { - return files(deobfFile) - } - - String mappingsVer - String remoteMappings = project.hasProperty('remoteMappings') ? project.remoteMappings : 'https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/' - if (remoteMappings) { - String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion" - String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip" - - zipMappings(mappingsZIP, remoteMappings, bon2Dir) - - mappingsVer = "snapshot_$id" - } else { - mappingsVer = "${channel}_$mappingsVersion" - } - - download.run { - src "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases/com/github/parker8283/BON2/$bon2Version-CUSTOM/BON2-$bon2Version-CUSTOM-all.jar" - dest bon2File - quiet true - overwrite false - } download.run { src sourceURL @@ -1190,50 +1480,8 @@ def deobf(String sourceURL, String rawFileName) { quiet true overwrite false } - - exec { - commandLine 'java', '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', minecraftVersion, '--mappingsVer', mappingsVer, '--notch' - workingDir bon2Dir - standardOutput = new FileOutputStream("${deobfFile}.log") - } - - return files(deobfFile) + return dependencies.rfg.deobf(files(obfFile)) } - -def zipMappings(String zipPath, String url, String bon2Dir) { - File zipFile = new File(zipPath) - if (zipFile.exists()) { - return - } - - String fieldsCache = "$bon2Dir/data/fields.csv" - String methodsCache = "$bon2Dir/data/methods.csv" - - download.run { - src "${url}fields.csv" - dest fieldsCache - quiet true - } - download.run { - src "${url}methods.csv" - dest methodsCache - quiet true - } - - zipFile.getParentFile().mkdirs() - ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile)) - - zos.putNextEntry(new ZipEntry("fields.csv")) - Files.copy(Paths.get(fieldsCache), zos) - zos.closeEntry() - - zos.putNextEntry(new ZipEntry("methods.csv")) - Files.copy(Paths.get(methodsCache), zos) - zos.closeEntry() - - zos.close() -} - // Helper methods def checkPropertyExists(String propertyName) { diff --git a/dependencies.gradle b/dependencies.gradle index c561b3a7..6e64b82d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,14 +1,13 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.0.0:dev') - compile('com.github.GTNewHorizons:GT5-Unofficial:5.09.42.71:dev') - compile('com.github.GTNewHorizons:TCNodeTracker:1.1.6:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.43.30:dev') + api('curse.maven:journeymap-32274:4500659') - compile('net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev') - compile('curse.maven:journeymap-32274:4500659') + devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.1.7:dev') - compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.8:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.6.14:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.9:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.7.6:dev') {transitive = false} compileOnly(deobf('https://media.forgecdn.net/files/4127/308/Xaeros_Minimap_21.10.30_Forge_1.7.10.jar')) compileOnly(deobf('https://media.forgecdn.net/files/4127/328/XaerosWorldMap_1.14.1.22_Forge_1.7.10.jar')) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f398c33c..37aef8d3 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/repositories.gradle b/repositories.gradle index 953ea178..9fbd7d4a 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,28 +1,2 @@ repositories { - maven { - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - } - maven { - name = "ic2" - url = "https://maven.ic2.player.to/" - metadataSources { - mavenPom() - artifact() - } - } - maven { - name = "ic2" - url = "https://maven2.ic2.player.to/" - metadataSources { - mavenPom() - artifact() - } - } - maven { - url "https://cursemaven.com" - } - maven { - url = "https://jitpack.io" - } } diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index b74ea182..7f1388ea 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -18,6 +18,7 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.sinthoras.visualprospecting.hooks.HooksClient; + import cpw.mods.fml.common.Loader; public class Utils { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index 0a55e033..b6251493 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -18,6 +18,7 @@ import com.sinthoras.visualprospecting.*; import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; import com.sinthoras.visualprospecting.network.ProspectingRequest; + import gregtech.common.blocks.GT_TileEntity_Ores; public class ClientCache extends WorldCache { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java index ec84675f..1005180c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java @@ -14,6 +14,7 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; + import cpw.mods.fml.server.FMLServerHandler; public class RedoServerCacheCommand extends CommandBase { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java index e6e35e86..aec90814 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java @@ -6,6 +6,7 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; + import io.xol.enklume.nbt.*; // A slim, but faster version to identify >90% of veins diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index 3a40c57e..8edb084e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -9,6 +9,7 @@ import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; + import io.xol.enklume.nbt.*; // Slower, but more sophisticated approach to identify overlapping veins diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java index 51e2f882..241e5656 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java @@ -7,6 +7,7 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; + import io.xol.enklume.MinecraftWorld; public class WorldAnalysis { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 5fbec160..a6a1bced 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -9,6 +9,7 @@ import net.minecraft.util.EnumChatFormatting; import com.sinthoras.visualprospecting.Tags; + import gregtech.api.GregTech_API; public class VeinType { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index f8b412b9..ca84fb21 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -9,9 +9,6 @@ import net.minecraft.client.resources.I18n; import net.minecraft.util.EnumChatFormatting; -import codechicken.nei.NEIClientConfig; -import codechicken.nei.SearchField; - import com.github.bartimaeusnek.bartworks.system.material.Werkstoff; import com.github.bartimaeusnek.bartworks.system.oregen.BW_OreLayer; import com.google.common.collect.BiMap; @@ -19,6 +16,8 @@ import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; +import codechicken.nei.NEIClientConfig; +import codechicken.nei.SearchField; import gregtech.api.GregTech_API; import gregtech.api.enums.Materials; import gregtech.common.GT_Worldgen_GT_Ore_Layer; diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java index a12adcf6..45d7bbff 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java @@ -11,6 +11,7 @@ import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.WorldIdHandler; import com.sinthoras.visualprospecting.network.WorldIdNotification; + import cpw.mods.fml.common.eventhandler.SubscribeEvent; public class HooksEventBus { diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/ProspectingNotificationEvent.java b/src/main/java/com/sinthoras/visualprospecting/hooks/ProspectingNotificationEvent.java index 803c69b1..ec72cc40 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/ProspectingNotificationEvent.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/ProspectingNotificationEvent.java @@ -2,6 +2,7 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; + import cpw.mods.fml.common.eventhandler.Event; public class ProspectingNotificationEvent extends Event { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java index 4bdc0368..c4f37cd4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java @@ -5,8 +5,6 @@ import java.util.ArrayList; import java.util.List; -import journeymap.client.render.map.GridRenderer; - import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.integration.journeymap.buttons.*; import com.sinthoras.visualprospecting.integration.journeymap.render.*; @@ -15,6 +13,8 @@ import com.sinthoras.visualprospecting.integration.journeymap.waypoints.WaypointManager; import com.sinthoras.visualprospecting.mixins.late.journeymap.FullscreenAccessor; +import journeymap.client.render.map.GridRenderer; + public class JourneyMapState { public static JourneyMapState instance = new JourneyMapState(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java index d3c8ea89..a6a6a890 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java @@ -1,10 +1,5 @@ package com.sinthoras.visualprospecting.integration.journeymap; -import journeymap.client.ui.UIManager; -import journeymap.client.ui.component.Button; -import journeymap.client.ui.component.ButtonList; -import journeymap.client.ui.component.JmUI; - import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.resources.I18n; @@ -13,6 +8,11 @@ import com.sinthoras.visualprospecting.database.ClientCache; +import journeymap.client.ui.UIManager; +import journeymap.client.ui.component.Button; +import journeymap.client.ui.component.ButtonList; +import journeymap.client.ui.component.JmUI; + public class ResetClientCacheConfirmation extends JmUI { private Button confirmButton; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java index 0007af1a..14a9e0e0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java @@ -1,10 +1,10 @@ package com.sinthoras.visualprospecting.integration.journeymap.buttons; -import journeymap.client.ui.theme.ThemeToggle; - import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.buttons.*; +import journeymap.client.ui.theme.ThemeToggle; + public class LayerButton extends com.sinthoras.visualprospecting.integration.model.buttons.LayerButton { private ThemeToggle button; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java index dff1ece2..f8c04d55 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java @@ -2,12 +2,12 @@ import java.util.List; -import journeymap.client.render.draw.DrawStep; - import net.minecraft.client.gui.FontRenderer; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; +import journeymap.client.render.draw.DrawStep; + public interface ClickableDrawStep extends DrawStep { List getTooltip(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java index 966a1b0e..580524db 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java @@ -2,13 +2,13 @@ import java.awt.geom.Point2D; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; + import journeymap.client.render.draw.DrawStep; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; - public class DirtyChunkDrawStep implements DrawStep { private final DirtyChunkLocation dirtyChunkLocation; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java index 2bfc0985..e2c6ec82 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java @@ -4,9 +4,6 @@ import java.util.ArrayList; import java.util.List; -import journeymap.client.render.draw.DrawUtil; -import journeymap.client.render.map.GridRenderer; - import net.minecraft.client.gui.FontRenderer; import net.minecraft.init.Blocks; import net.minecraft.util.IIcon; @@ -18,6 +15,9 @@ import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; +import journeymap.client.render.draw.DrawUtil; +import journeymap.client.render.map.GridRenderer; + public class OreVeinDrawStep implements ClickableDrawStep { private static final ResourceLocation depletedTextureLocation = new ResourceLocation( diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java index 45cab280..913f123e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java @@ -3,8 +3,6 @@ import java.awt.geom.Point2D; import java.util.List; -import journeymap.client.render.map.GridRenderer; - import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.util.ResourceLocation; @@ -12,15 +10,16 @@ import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; -import thaumcraft.api.aspects.Aspect; -import thaumcraft.client.lib.UtilsFX; - import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.integration.DrawUtils; import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; +import journeymap.client.render.map.GridRenderer; +import thaumcraft.api.aspects.Aspect; +import thaumcraft.client.lib.UtilsFX; + public class ThaumcraftNodeDrawStep implements ClickableDrawStep { private static final ResourceLocation markedTextureLocation = new ResourceLocation( diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java index f0ea4eaa..8ec22120 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java @@ -2,14 +2,14 @@ import java.awt.geom.Point2D; -import journeymap.client.render.draw.DrawStep; -import journeymap.client.render.draw.DrawUtil; -import journeymap.client.render.map.GridRenderer; - import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; +import journeymap.client.render.draw.DrawStep; +import journeymap.client.render.draw.DrawUtil; +import journeymap.client.render.map.GridRenderer; + public class UndergroundFluidChunkDrawStep implements DrawStep { private final UndergroundFluidChunkLocation undergroundFluidChunkLocation; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java index 7f0edcfb..3a024260 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java @@ -2,13 +2,13 @@ import java.awt.geom.Point2D; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; + import journeymap.client.render.draw.DrawStep; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; - public class UndergroundFluidDrawStep implements DrawStep { private final UndergroundFluidLocation undergroundFluidLocation; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java index 877d17d3..a2476eb6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java @@ -3,13 +3,13 @@ import java.util.ArrayList; import java.util.List; -import journeymap.client.render.draw.DrawStep; - import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.DirtyChunkDrawStep; import com.sinthoras.visualprospecting.integration.model.layers.DirtyChunkLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; +import journeymap.client.render.draw.DrawStep; + public class DirtyChunkRenderer extends LayerRenderer { public static final DirtyChunkRenderer instance = new DirtyChunkRenderer(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java index 00c90904..8f539c56 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java @@ -3,12 +3,12 @@ import java.util.ArrayList; import java.util.List; -import journeymap.client.render.draw.DrawStep; - import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; +import journeymap.client.render.draw.DrawStep; + public abstract class LayerRenderer extends com.sinthoras.visualprospecting.integration.model.layers.LayerRenderer { private final LayerManager manager; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java index e5f0a740..1dfcc956 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java @@ -3,13 +3,13 @@ import java.util.ArrayList; import java.util.List; -import journeymap.client.render.draw.DrawStep; - import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.UndergroundFluidChunkDrawStep; import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidChunkLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; +import journeymap.client.render.draw.DrawStep; + public class UndergroundFluidChunkRenderer extends LayerRenderer { public static final UndergroundFluidChunkRenderer instance = new UndergroundFluidChunkRenderer(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java index 3116e7e6..d4978646 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java @@ -3,13 +3,13 @@ import java.util.ArrayList; import java.util.List; -import journeymap.client.render.draw.DrawStep; - import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.UndergroundFluidDrawStep; import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; +import journeymap.client.render.draw.DrawStep; + public class UndergroundFluidRenderer extends LayerRenderer { public static final UndergroundFluidRenderer instance = new UndergroundFluidRenderer(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java index 263873af..7d04c409 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java @@ -5,16 +5,16 @@ import org.lwjgl.input.Keyboard; +import com.dyonovan.tcnodetracker.lib.NodeList; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; + import thaumcraft.api.aspects.Aspect; import thaumcraft.api.aspects.AspectList; import thaumcraft.api.nodes.NodeType; import thaumcraft.common.config.ConfigBlocks; import thaumcraft.common.tiles.TileNode; -import com.dyonovan.tcnodetracker.lib.NodeList; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; - public class ThaumcraftNodeLocation implements IWaypointAndLocationProvider { private static final String deleteHint = EnumChatFormatting.DARK_GRAY diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java index cbfbe1e5..ae20e658 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java @@ -2,13 +2,13 @@ import java.util.Hashtable; -import xaero.common.minimap.waypoints.WaypointsManager; - import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; +import xaero.common.minimap.waypoints.WaypointsManager; + public class WaypointManager extends com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager { private static final Hashtable xWaypointTable = WaypointsManager diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java index 24f43d45..3a47c484 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java @@ -7,15 +7,15 @@ import org.lwjgl.opengl.GL11; -import thaumcraft.api.aspects.Aspect; -import thaumcraft.client.lib.UtilsFX; - import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.integration.DrawUtils; import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; +import thaumcraft.api.aspects.Aspect; +import thaumcraft.client.lib.UtilsFX; + public class ThaumcraftNodeRenderStep implements InteractableRenderStep { private static final ResourceLocation markedTextureLocation = new ResourceLocation( diff --git a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java index 59a1a3d3..51e48f3a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java +++ b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java @@ -19,6 +19,7 @@ import com.sinthoras.visualprospecting.task.SnapshotDownloadTask; import com.sinthoras.visualprospecting.task.SnapshotUploadTask; import com.sinthoras.visualprospecting.task.TaskManager; + import gregtech.api.GregTech_API; public class ProspectorsLog extends Item { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java index 168fb1e2..e9d0e753 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java @@ -3,6 +3,7 @@ import java.util.*; import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader; + import cpw.mods.fml.relauncher.IFMLLoadingPlugin; @IFMLLoadingPlugin.MCVersion("1.7.10") diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java index 89c980e5..d8411bf2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java @@ -9,10 +9,10 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import bloodasp.galacticgreg.GT_Worldgenerator_Space; - import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.ServerCache; + +import bloodasp.galacticgreg.GT_Worldgenerator_Space; import gregtech.api.world.GT_Worldgen; @Mixin(GT_Worldgenerator_Space.class) diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java index 72a7caab..c4d1ba06 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java @@ -1,11 +1,11 @@ package com.sinthoras.visualprospecting.mixins.late.journeymap; -import journeymap.client.ui.minimap.DisplayVars; -import journeymap.client.ui.minimap.Shape; - import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; +import journeymap.client.ui.minimap.DisplayVars; +import journeymap.client.ui.minimap.Shape; + @Mixin(DisplayVars.class) public interface DisplayVarsAccessor { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java index 5e29333c..823ed72b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java @@ -1,11 +1,11 @@ package com.sinthoras.visualprospecting.mixins.late.journeymap; -import journeymap.client.render.map.GridRenderer; -import journeymap.client.ui.fullscreen.Fullscreen; - import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; +import journeymap.client.render.map.GridRenderer; +import journeymap.client.ui.fullscreen.Fullscreen; + @Mixin(Fullscreen.class) public interface FullscreenAccessor { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java index 47c67789..c4eccd06 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java @@ -1,11 +1,5 @@ package com.sinthoras.visualprospecting.mixins.late.journeymap; -import journeymap.client.ui.UIManager; -import journeymap.client.ui.component.Button; -import journeymap.client.ui.component.ButtonList; -import journeymap.client.ui.component.JmUI; -import journeymap.client.ui.dialog.FullscreenActions; - import net.minecraft.client.gui.GuiButton; import net.minecraft.client.resources.I18n; @@ -18,6 +12,12 @@ import com.sinthoras.visualprospecting.integration.journeymap.ResetClientCacheConfirmation; +import journeymap.client.ui.UIManager; +import journeymap.client.ui.component.Button; +import journeymap.client.ui.component.ButtonList; +import journeymap.client.ui.component.JmUI; +import journeymap.client.ui.dialog.FullscreenActions; + @Mixin(FullscreenActions.class) public abstract class FullscreenActionsMixin extends JmUI { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java index 78c8ebdd..b49edc51 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java @@ -2,30 +2,13 @@ import java.util.List; -import journeymap.client.Constants; -import journeymap.client.io.ThemeFileHandler; -import journeymap.client.log.LogFormatter; -import journeymap.client.log.StatTimer; -import journeymap.client.model.BlockCoordIntPair; -import journeymap.client.render.map.GridRenderer; -import journeymap.client.ui.UIManager; -import journeymap.client.ui.component.Button; -import journeymap.client.ui.component.ButtonList; -import journeymap.client.ui.component.JmUI; -import journeymap.client.ui.fullscreen.Fullscreen; -import journeymap.client.ui.fullscreen.MapChat; -import journeymap.client.ui.fullscreen.layer.LayerDelegate; -import journeymap.client.ui.theme.Theme; -import journeymap.client.ui.theme.ThemeButton; -import journeymap.client.ui.theme.ThemeToggle; -import journeymap.client.ui.theme.ThemeToolbar; - import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.renderer.RenderHelper; import org.apache.logging.log4j.Level; import org.lwjgl.input.Mouse; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -34,7 +17,6 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import org.spongepowered.libraries.org.objectweb.asm.Opcodes; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; @@ -44,6 +26,24 @@ import com.sinthoras.visualprospecting.integration.model.MapState; import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; +import journeymap.client.Constants; +import journeymap.client.io.ThemeFileHandler; +import journeymap.client.log.LogFormatter; +import journeymap.client.log.StatTimer; +import journeymap.client.model.BlockCoordIntPair; +import journeymap.client.render.map.GridRenderer; +import journeymap.client.ui.UIManager; +import journeymap.client.ui.component.Button; +import journeymap.client.ui.component.ButtonList; +import journeymap.client.ui.component.JmUI; +import journeymap.client.ui.fullscreen.Fullscreen; +import journeymap.client.ui.fullscreen.MapChat; +import journeymap.client.ui.fullscreen.layer.LayerDelegate; +import journeymap.client.ui.theme.Theme; +import journeymap.client.ui.theme.ThemeButton; +import journeymap.client.ui.theme.ThemeToggle; +import journeymap.client.ui.theme.ThemeToolbar; + @Mixin(value = Fullscreen.class, remap = false) public abstract class FullscreenMixin extends JmUI { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java index 96175c7a..572c7992 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java @@ -1,11 +1,5 @@ package com.sinthoras.visualprospecting.mixins.late.journeymap; -import journeymap.client.render.draw.DrawStep; -import journeymap.client.render.map.GridRenderer; -import journeymap.client.ui.minimap.DisplayVars; -import journeymap.client.ui.minimap.MiniMap; -import journeymap.client.ui.minimap.Shape; - import net.minecraft.client.Minecraft; import org.spongepowered.asm.mixin.Final; @@ -20,6 +14,12 @@ import com.sinthoras.visualprospecting.integration.model.MapState; import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; +import journeymap.client.render.draw.DrawStep; +import journeymap.client.render.map.GridRenderer; +import journeymap.client.ui.minimap.DisplayVars; +import journeymap.client.ui.minimap.MiniMap; +import journeymap.client.ui.minimap.Shape; + @Mixin(MiniMap.class) public abstract class MiniMapMixin { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java index 832a3c76..9982d486 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java @@ -1,8 +1,5 @@ package com.sinthoras.visualprospecting.mixins.late.journeymap; -import journeymap.client.model.Waypoint; -import journeymap.client.render.ingame.RenderWaypointBeacon; - import net.minecraft.client.Minecraft; import org.spongepowered.asm.mixin.Mixin; @@ -14,6 +11,9 @@ import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.WaypointManager; +import journeymap.client.model.Waypoint; +import journeymap.client.render.ingame.RenderWaypointBeacon; + @Mixin(RenderWaypointBeacon.class) public class RenderWaypointBeaconMixin { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java index bbae3bac..597cad96 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java @@ -1,7 +1,5 @@ package com.sinthoras.visualprospecting.mixins.late.journeymap; -import journeymap.client.ui.waypoint.WaypointManager; - import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -11,6 +9,8 @@ import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; +import journeymap.client.ui.waypoint.WaypointManager; + @Mixin(WaypointManager.class) public class WaypointManagerMixin { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java index cc5a156c..c3e057fe 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java @@ -3,13 +3,13 @@ import net.minecraft.client.gui.GuiButton; import net.minecraft.client.resources.I18n; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import org.spongepowered.libraries.org.objectweb.asm.Opcodes; import com.dyonovan.tcnodetracker.gui.GuiMain; import com.dyonovan.tcnodetracker.lib.AspectLoc; diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java index acdeb19a..8ffbe9c2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java @@ -15,11 +15,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import xaero.common.XaeroMinimapSession; -import xaero.common.minimap.MinimapProcessor; -import xaero.common.minimap.render.MinimapRenderer; -import xaero.common.settings.ModSettings; - import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.model.MapState; import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; @@ -27,6 +22,11 @@ import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; +import xaero.common.XaeroMinimapSession; +import xaero.common.minimap.MinimapProcessor; +import xaero.common.minimap.render.MinimapRenderer; +import xaero.common.settings.ModSettings; + @Mixin(value = MinimapRenderer.class, remap = false) public class MinimapRendererMixin { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java index b74262ce..78c4e4f3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java @@ -9,12 +9,12 @@ import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import xaero.common.XaeroMinimapSession; -import xaero.common.minimap.waypoints.render.WaypointsIngameRenderer; - import com.sinthoras.visualprospecting.integration.xaerominimap.XaeroMiniMapState; import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.WaypointManager; +import xaero.common.XaeroMinimapSession; +import xaero.common.minimap.waypoints.render.WaypointsIngameRenderer; + @Mixin(value = WaypointsIngameRenderer.class, remap = false) public class WaypointsIngameRendererMixin { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java index 5f5b7571..a3b3bc94 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java @@ -16,12 +16,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import xaero.map.MapProcessor; -import xaero.map.gui.CursorBox; -import xaero.map.gui.GuiMap; -import xaero.map.gui.ScreenBase; -import xaero.map.misc.Misc; - import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.model.MapState; import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; @@ -32,6 +26,12 @@ import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; +import xaero.map.MapProcessor; +import xaero.map.gui.CursorBox; +import xaero.map.gui.GuiMap; +import xaero.map.gui.ScreenBase; +import xaero.map.misc.Misc; + @Mixin(value = GuiMap.class, remap = false) public abstract class GuiMapMixin extends ScreenBase { From 3ae7b853c857024d26da4f27592d44021667752b Mon Sep 17 00:00:00 2001 From: Wilhelm Schuster Date: Wed, 17 May 2023 07:03:53 +0200 Subject: [PATCH 025/132] Check for null NBT tag in Written Book mixin (#31) --- .../mixins/early/minecraft/ItemEditableBookMixin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java index fdeafd97..2d9c36af 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java @@ -31,7 +31,7 @@ public class ItemEditableBookMixin { CallbackInfoReturnable cir) { if (!world.isRemote) { final NBTTagCompound compound = itemStack.getTagCompound(); - if (compound.hasKey(Tags.VISUALPROSPECTING_FLAG)) { + if (compound != null && compound.hasKey(Tags.VISUALPROSPECTING_FLAG)) { final int dimensionId = compound.getInteger(Tags.PROSPECTION_DIMENSION_ID); final int blockX = compound.getInteger(Tags.PROSPECTION_BLOCK_X); final int blockZ = compound.getInteger(Tags.PROSPECTION_BLOCK_Z); From a318c501122665f77ada7e2229da0f6cd67be5be Mon Sep 17 00:00:00 2001 From: chochem <40274384+chochem@users.noreply.github.com> Date: Sat, 20 May 2023 23:24:37 +0100 Subject: [PATCH 026/132] new ore mixes (#32) --- src/main/resources/assets/gregtech/lang/en_US.lang | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/assets/gregtech/lang/en_US.lang b/src/main/resources/assets/gregtech/lang/en_US.lang index 5bd457b6..9315188b 100644 --- a/src/main/resources/assets/gregtech/lang/en_US.lang +++ b/src/main/resources/assets/gregtech/lang/en_US.lang @@ -91,3 +91,11 @@ ore.mix.ross128ba.Amethyst=Amethyst ore.mix.ross128ba.CopperSulfits=Djurleit ore.mix.ross128ba.RedZircon=Red Zircon ore.mix.ross128ba.Fluorspar=Fluorspar + +ore.mix.dilithium=Dilithium +ore.mix.certusquartz=Certus Quartz +ore.mix.infinitycatalyst=Infinity Catalyst +ore.mix.awakeneddraconium=Awakened Draconium +ore.mix.naquadria=Naquadria +ore.mix.cosmicneutronium=Cosmic Neutronium +ore.mix.tengam=Tengam From 34dbe2fe88c9755a5844bbf0a892e0dfe26e8531 Mon Sep 17 00:00:00 2001 From: Pao <9247381+PolkageistHS@users.noreply.github.com> Date: Fri, 2 Jun 2023 13:14:51 -0700 Subject: [PATCH 027/132] Added hotkeys to toggle map overlays (#33) * Added hotkeys to toggle map overlays * Streamlined code based on feedback --- .../com/sinthoras/visualprospecting/VP.java | 2 +- .../visualprospecting/hooks/HooksClient.java | 2 + .../visualprospecting/hooks/HooksKey.java | 61 +++++++++++++++++++ .../assets/visualprospecting/lang/en_US.lang | 3 + 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java diff --git a/src/main/java/com/sinthoras/visualprospecting/VP.java b/src/main/java/com/sinthoras/visualprospecting/VP.java index 1d4a738f..1a178058 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VP.java +++ b/src/main/java/com/sinthoras/visualprospecting/VP.java @@ -29,7 +29,7 @@ public class VP { public static final int chunkHeight = 16; public static final int chunkDepth = 16; public static final int undergroundFluidChunkProspectingBlockRadius = undergroundFluidSizeChunkX * chunkWidth; - public static int uploadSizePerPacketInBytes = 30000; // Larger then 32kB will kick the player! + public static int uploadSizePerPacketInBytes = 30000; // Larger than 32kB will kick the player! public static void debug(String message) { VP.LOG.debug(formatMessage(message)); diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java index 2be8956d..aa6ed389 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java @@ -12,6 +12,7 @@ import com.sinthoras.visualprospecting.integration.voxelmap.VoxelMapEventHandler; import cpw.mods.fml.client.registry.ClientRegistry; +import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; @@ -39,6 +40,7 @@ public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { // load "Do your mod setup. Build whatever data structures you care about. Register recipes." public void fmlLifeCycleEvent(FMLInitializationEvent event) { super.fmlLifeCycleEvent(event); + FMLCommonHandler.instance().bus().register(new HooksKey()); } @Override diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java new file mode 100644 index 00000000..ef9d5b3d --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java @@ -0,0 +1,61 @@ +package com.sinthoras.visualprospecting.hooks; + +import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; + +import net.minecraft.client.settings.KeyBinding; + +import org.lwjgl.input.Keyboard; + +import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; +import com.sinthoras.visualprospecting.integration.model.buttons.ThaumcraftNodeButtonManager; +import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; + +import cpw.mods.fml.client.registry.ClientRegistry; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.InputEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +public class HooksKey { + + private final KeyBinding keyToggleOres = new KeyBinding( + "visualprospecting.key.toggleore.name", + Keyboard.KEY_NONE, + "visualprospecting.key.action.category"); + private final KeyBinding keyToggleFluids = new KeyBinding( + "visualprospecting.key.togglefluid.name", + Keyboard.KEY_NONE, + "visualprospecting.key.action.category"); + private final KeyBinding keyToggleNodes = new KeyBinding( + "visualprospecting.key.togglenode.name", + Keyboard.KEY_NONE, + "visualprospecting.key.action.category"); + + public HooksKey() { + FMLCommonHandler.instance().bus().register(this); + ClientRegistry.registerKeyBinding(keyToggleOres); + ClientRegistry.registerKeyBinding(keyToggleFluids); + if (isTCNodeTrackerInstalled()) { + ClientRegistry.registerKeyBinding(keyToggleNodes); + } + } + + @SideOnly(Side.CLIENT) + @SubscribeEvent + public void key(InputEvent.KeyInputEvent event) { + checkAndToggleOverlays(); + } + + private void checkAndToggleOverlays() { + if (keyToggleOres.isPressed()) { + OreVeinButtonManager.instance.toggle(); + } + if (keyToggleFluids.isPressed()) { + UndergroundFluidButtonManager.instance.toggle(); + } + if (keyToggleNodes.isPressed() && isTCNodeTrackerInstalled()) { + ThaumcraftNodeButtonManager.instance.toggle(); + } + } +} diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index 589ded9e..7f0886c6 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -24,6 +24,9 @@ visualprospecting.iswaypoint=Active as Waypoint visualprospecting.depleted=DEPLETED visualprospecting.depleted.toggle=Toggle depleted with %s visualprospecting.key.action.name=Action button +visualprospecting.key.toggleore.name=Toggle ore overlay +visualprospecting.key.togglefluid.name=Toggle fluid overlay +visualprospecting.key.togglenode.name=Toggle node overlay visualprospecting.key.action.category=VisualProspecting item.visualprospecting.prospectorslog.name=Prospector's Log item.visualprospecting.prospectorslog.author=Author: %s From bbd1678b4724512a9f28e76cd196b18b4f9ec88d Mon Sep 17 00:00:00 2001 From: chochem <40274384+chochem@users.noreply.github.com> Date: Tue, 4 Jul 2023 17:37:01 +0100 Subject: [PATCH 028/132] Adjust vp to fixed gt oregen (#35) * adjust to oregen change * compat for old ore gen * change for api change * update dep --- dependencies.gradle | 2 +- .../java/com/sinthoras/visualprospecting/Utils.java | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 6e64b82d..7a40b9fd 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.0.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.43.30:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.43.88-pre:dev') api('curse.maven:journeymap-32274:4500659') devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.1.7:dev') diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 7f1388ea..b17ca49a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -20,6 +20,7 @@ import com.sinthoras.visualprospecting.hooks.HooksClient; import cpw.mods.fml.common.Loader; +import gregtech.common.GT_Worldgenerator; public class Utils { @@ -75,10 +76,16 @@ public static long chunkCoordsToKey(int chunkX, int chunkZ) { } public static int mapToCenterOreChunkCoord(final int chunkCoord) { - if (chunkCoord >= 0) { - return chunkCoord - (chunkCoord % 3) + 1; + if (GT_Worldgenerator.oregenPattern == GT_Worldgenerator.OregenPattern.EQUAL_SPACING) { + // new evenly spaced ore pattern + return chunkCoord - Math.floorMod(chunkCoord, 3) + 1; } else { - return chunkCoord - (chunkCoord % 3) - 1; + // old bugged ore pattern + if (chunkCoord >= 0) { + return chunkCoord - (chunkCoord % 3) + 1; + } else { + return chunkCoord - (chunkCoord % 3) - 1; + } } } From 00efcc4f2889d03d2e265ddc86674b845acfda80 Mon Sep 17 00:00:00 2001 From: ah-OOG-ah <75745146+ah-OOG-ah@users.noreply.github.com> Date: Mon, 10 Jul 2023 04:49:52 -0400 Subject: [PATCH 029/132] Fix !visualprospectingnearspawn (#30) * Update BS * Update dependencies.gradle * Update HooksShared.java Just a reformat + comment * Add final patches + spotless This SHOULD fix VPNearSpawn. Also generates a ton of random edits because spotless said so ig. * Update dependencies.gradle Add the electric scanner mod for debugging. * Add recache command, remove auto recache I can't replicate the automatic bug or fix in a full environment, so I'm removing that code for now. Instead, a command to only recache spawn has been added. * spotless + BS * Update dependencies.gradle * Update dependencies.gradle * Apply simple suggestions from SinTh0r4s Co-authored-by: Johann Bernhardt * Apply complex suggestions from SinTh0r4s * Update build.gradle * Update deps --------- Co-authored-by: Johann Bernhardt Co-authored-by: Martin Robertz --- build.gradle | 18 ++-- dependencies.gradle | 9 +- .../com/sinthoras/visualprospecting/Tags.java | 1 + .../database/DimensionCache.java | 20 ++++ .../database/RedoServerSpawnCacheCommand.java | 95 +++++++++++++++++++ .../database/WorldCache.java | 36 +++++++ .../database/cachebuilder/WorldAnalysis.java | 22 ++++- .../visualprospecting/hooks/HooksShared.java | 14 ++- .../assets/visualprospecting/lang/en_US.lang | 4 + 9 files changed, 206 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java diff --git a/build.gradle b/build.gradle index 3fa171e0..39309904 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1683705740 +//version: 1685785062 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -69,7 +69,7 @@ plugins { id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.11' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.14' } print("You might want to check out './gradlew :faq' if your build fails.\n") @@ -730,7 +730,7 @@ dependencies { java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") } if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.8') + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.13') } java17PatchDependencies('net.minecraft:launchwrapper:1.15') {transitive = false} @@ -1276,12 +1276,14 @@ tasks.register('faq') { description = 'Prints frequently asked questions about building a project' doLast { - print("If your build fails to fetch dependencies, they might have been deleted and replaced by newer " + - "versions.\nCheck if the versions you try to fetch are still on the distributing sites.\n" + - "The links can be found in repositories.gradle and build.gradle:repositories, " + - "not build.gradle:buildscript.repositories - this one is for gradle plugin metadata.\n\n" + + print("If your build fails to fetch dependencies, run './gradlew updateDependencies'. " + + "Or you can manually check if the versions are still on the distributing sites - " + + "the links can be found in repositories.gradle and build.gradle:repositories, " + + "but not build.gradle:buildscript.repositories - those ones are for gradle plugin metadata.\n\n" + "If your build fails to recognize the syntax of new Java versions, enable Jabel in your " + - "gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties.") + "gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties. " + + "However, keep in mind that Jabel enables only syntax features, but not APIs that were introduced in " + + "Java 9 or later.") } } diff --git a/dependencies.gradle b/dependencies.gradle index 7a40b9fd..9a287c2a 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,15 +1,18 @@ dependencies { - shadowImplementation('com.github.GTNewHorizons:Enklume:2.0.0:dev') + shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.43.88-pre:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.43.111:dev') api('curse.maven:journeymap-32274:4500659') devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.1.7:dev') compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.9:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.7.6:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.7.20:dev') {transitive = false} compileOnly(deobf('https://media.forgecdn.net/files/4127/308/Xaeros_Minimap_21.10.30_Forge_1.7.10.jar')) compileOnly(deobf('https://media.forgecdn.net/files/4127/328/XaerosWorldMap_1.14.1.22_Forge_1.7.10.jar')) compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) + + // For debugging + runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.7.2:dev') } diff --git a/src/main/java/com/sinthoras/visualprospecting/Tags.java b/src/main/java/com/sinthoras/visualprospecting/Tags.java index a1525f03..b84d0d26 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Tags.java +++ b/src/main/java/com/sinthoras/visualprospecting/Tags.java @@ -29,4 +29,5 @@ public class Tags { public static final String PROSPECTION_NUMBER_OF_UNDERGROUND_FLUID = "prospection_num_fluids"; public static final String PROSPECTORSLOG_AUTHOR = "log_author"; public static final String PROSPECTORSLOG_AUTHOR_ID = "log_author_id"; + public static final int overworldId = 0; } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index 9b64c7bc..9d0d7931 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -193,4 +193,24 @@ public Collection getAllOreVeins() { public Collection getAllUndergroundFluids() { return undergroundFluids.values(); } + + /** + * Reset selected veins; these veins need not be present. Input coords are in chunk coordinates, NOT block coords. + * Will not error on bad input, but it also probably won't do anything useful. startChunks should be less than their + * respective endChunks. + */ + public void clearOreVeins(int startChunkX, int startChunkZ, int endChunkX, int endChunkZ) { + + // Remove entries if they fall within the corners + // This method iterates for each chunk mapped. In many cases, it is probably faster to iterate over chunks in + // the area to be cleared instead. i.e. if (chunksInClearArea < totalChunksMapped) {useAltIterator()}. If + // someone calls this enough to make it a problem, they can add that. + oreChunks.entrySet().removeIf(entry -> { + + OreVeinPosition val = entry.getValue(); + final boolean withinX = val.chunkX >= startChunkX && val.chunkX <= endChunkX; + final boolean withinZ = val.chunkZ >= startChunkZ && val.chunkZ <= endChunkZ; + return withinX && withinZ; + }); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java new file mode 100644 index 00000000..dbb92a6f --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java @@ -0,0 +1,95 @@ +package com.sinthoras.visualprospecting.database; + +import java.io.IOException; +import java.util.Objects; +import java.util.zip.DataFormatException; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.StatCollector; + +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; + +import cpw.mods.fml.server.FMLServerHandler; + +public class RedoServerSpawnCacheCommand extends CommandBase { + + @Override + public String getCommandName() { + return "visualprospectingredoserverspawncache"; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return StatCollector.translateToLocal("visualprospecting.redoserverspawncache.command"); + } + + @Override + public void processCommand(ICommandSender sender, String[] parameters) { + + // Set the correct server + MinecraftServer server; + if (sender instanceof EntityPlayerMP) { + + EntityPlayerMP player = (EntityPlayerMP) sender; + server = player.mcServer; + } else { + + server = FMLServerHandler.instance().getServer(); + } + + if (server == null) { + VP.info("Server not found"); + return; + } + + // Fancy start message + final IChatComponent start = new ChatComponentTranslation("visualprospecting.redoserverspawncache.start"); + start.getChatStyle().setItalic(true); + sender.addChatMessage(start); + + // Attempt to analyze the world + try { + + WorldAnalysis world = new WorldAnalysis(server.getEntityWorld().getSaveHandler().getWorldDirectory()); + world.cacheOverworldSpawnVeins(server.getEntityWorld().getSpawnPoint()); + } catch (IOException | DataFormatException e) { + + VP.info("Could not load world save files to build vein cache near spawn!"); + e.printStackTrace(); + final IChatComponent failure = new ChatComponentTranslation( + "visualprospecting.redoserverspawncache.failure"); + failure.getChatStyle().setItalic(true); + sender.addChatMessage(failure); + } + final IChatComponent confirmation = new ChatComponentTranslation( + "visualprospecting.redoserverspawncache.confirmation"); + confirmation.getChatStyle().setItalic(true); + sender.addChatMessage(confirmation); + } + + @Override + public boolean canCommandSenderUseCommand(ICommandSender sender) { + + // Only SP owner, or OP are allowed + if (sender instanceof EntityPlayerMP) { + + EntityPlayerMP player = (EntityPlayerMP) sender; + if (Objects.equals(player.mcServer.getServerOwner(), sender.getCommandSenderName())) { + return true; + } + } + + return super.canCommandSenderUseCommand(sender); + } + + @Override + public int getRequiredPermissionLevel() { + return 4; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index 95c16aaa..873968c1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -7,6 +7,8 @@ import java.util.Map; import java.util.Set; +import net.minecraft.util.ChunkCoordinates; + import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.veintypes.VeinType; @@ -77,6 +79,40 @@ public void reset() { isLoaded = false; } + /** + * Reset some chunks. Not all, and (usually) not none - but some. Input coords are in chunk coordinates, NOT block + * coords. + * + * @param dimID The dimension ID. + * @param startX The X coord of the starting chunk. Must be less than endX. + * @param startZ The Z coord of the starting chunk. Must be less than endZ. + * @param endX The X coord of the ending chunk. + * @param endZ The Z coord of the ending chunk. + */ + public void resetSome(int dimID, int startX, int startZ, int endX, int endZ) { + + DimensionCache dim = dimensions.get(dimID); + if (dim != null) { + dim.clearOreVeins(startX, startZ, endX, endZ); + needsSaving = true; + isLoaded = false; + } + } + + public void resetSpawnChunks(ChunkCoordinates spawn, int dimID) { + + int spawnChunkX = Utils.coordBlockToChunk(spawn.posX); + int spawnChunkZ = Utils.coordBlockToChunk(spawn.posZ); + + int spawnChunksRadius = 8; + int startX = spawnChunkX - spawnChunksRadius; + int startZ = spawnChunkZ - spawnChunksRadius; + int endX = spawnChunkX + spawnChunksRadius; + int endZ = spawnChunkZ + spawnChunksRadius; + + resetSome(dimID, startX, startZ, endX, endZ); + } + private DimensionCache.UpdateResult updateSaveFlag(DimensionCache.UpdateResult updateResult) { needsSaving |= updateResult != DimensionCache.UpdateResult.AlreadyKnown; return updateResult; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java index 241e5656..84b38f48 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java @@ -2,9 +2,13 @@ import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.List; import java.util.zip.DataFormatException; +import net.minecraft.util.ChunkCoordinates; + +import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; @@ -18,16 +22,32 @@ public WorldAnalysis(File worldDirectory) throws IOException { world = new MinecraftWorld(worldDirectory); } + public void cacheOverworldSpawnVeins(ChunkCoordinates spawn) throws IOException, DataFormatException { + + VP.info("Starting to parse world save to cache GT vein locations near spawn. This might take some time..."); + ServerCache.instance.resetSpawnChunks(spawn, 0); + + cacheVeins(Collections.singletonList(Tags.overworldId)); + } + public void cacheVeins() throws IOException, DataFormatException { + VP.info("Starting to parse world save to cache GT vein locations. This might take some time..."); ServerCache.instance.reset(); - final List dimensionIds = world.getDimensionIds(); + + cacheVeins(world.getDimensionIds()); + } + + private void cacheVeins(List dimensionIds) throws IOException, DataFormatException { + AnalysisProgressTracker.setNumberOfDimensions(dimensionIds.size()); for (int dimensionId : dimensionIds) { + final DimensionAnalysis dimension = new DimensionAnalysis(dimensionId); dimension.processMinecraftWorld(world); AnalysisProgressTracker.dimensionProcessed(); } + AnalysisProgressTracker.processingFinished(); VP.info("Saving ore vein cache..."); ServerCache.instance.saveVeinCache(); diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index 80e7a120..eaab5204 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -12,6 +12,7 @@ import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.RedoServerCacheCommand; +import com.sinthoras.visualprospecting.database.RedoServerSpawnCacheCommand; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.WorldIdHandler; import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; @@ -100,19 +101,30 @@ public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) {} // register server commands in this event handler public void fmlLifeCycleEvent(FMLServerStartingEvent event) { + + // Get the server and load the ID handler final MinecraftServer minecraftServer = event.getServer(); WorldIdHandler.load(minecraftServer.worldServers[0]); - if (ServerCache.instance.loadVeinCache(WorldIdHandler.getWorldId()) == false || Config.recacheVeins) { + + // Attempt to load the vein cache. If unable or forcing a recache... + if (!ServerCache.instance.loadVeinCache(WorldIdHandler.getWorldId()) || Config.recacheVeins) { + + // Reanalyze the world and reload it into memory. try { WorldAnalysis world = new WorldAnalysis( minecraftServer.getEntityWorld().getSaveHandler().getWorldDirectory()); world.cacheVeins(); } catch (IOException | DataFormatException e) { + + // Oops VP.info("Could not load world save files to build vein cache!"); e.printStackTrace(); } } + + // Register the recache command event.registerServerCommand(new RedoServerCacheCommand()); + event.registerServerCommand(new RedoServerSpawnCacheCommand()); } public void fmlLifeCycleEvent(FMLServerStartedEvent event) {} diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index 7f0886c6..013df93a 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -20,6 +20,10 @@ visualprospecting.redoservercache.command=Redo the GT vein cache on the server visualprospecting.redoservercache.start=Start redoing the GT vein cache on the server visualprospecting.redoservercache.failure=Could not load world save files to build vein cache! visualprospecting.redoservercache.confirmation=Redo success! +visualprospecting.redoserverspawncache.command=Redo the GT vein cache near spawn on the server +visualprospecting.redoserverspawncache.start=Start redoing the GT vein cache near spawn on the server +visualprospecting.redoserverspawncache.failure=Could not load world save files to build vein cache near spawn! +visualprospecting.redoserverspawncache.confirmation=Redo success! visualprospecting.iswaypoint=Active as Waypoint visualprospecting.depleted=DEPLETED visualprospecting.depleted.toggle=Toggle depleted with %s From d22b807672f61ce7ea503e0d7a22c404d41c398a Mon Sep 17 00:00:00 2001 From: kumquat-ir <66188216+kumquat-ir@users.noreply.github.com> Date: Sun, 23 Jul 2023 17:02:55 -0400 Subject: [PATCH 030/132] dont nuke the cache if it already has data when initialized --- .../sinthoras/visualprospecting/database/WorldCache.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index 873968c1..563c48d5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -39,12 +39,16 @@ public boolean loadVeinCache(String worldId) { final Set dimensionsIds = new HashSet<>(); dimensionsIds.addAll(oreVeinDimensionBuffers.keySet()); dimensionsIds.addAll(undergroundFluidDimensionBuffers.keySet()); + dimensionsIds.addAll(dimensions.keySet()); if (dimensionsIds.isEmpty()) { return false; } for (int dimensionId : dimensionsIds) { - final DimensionCache dimension = new DimensionCache(dimensionId); + DimensionCache dimension = dimensions.get(dimensionId); + if (dimension == null) { + dimension = new DimensionCache(dimensionId); + } dimension.loadCache( oreVeinDimensionBuffers.get(dimensionId), undergroundFluidDimensionBuffers.get(dimensionId)); From 966d4ffdce3ff07d4211a9968dd56681e0bdcb37 Mon Sep 17 00:00:00 2001 From: glowredman <35727266+glowredman@users.noreply.github.com> Date: Thu, 27 Jul 2023 21:40:42 +0200 Subject: [PATCH 031/132] Update buildscript --- build.gradle | 185 ++++++++++++------ gradle.properties | 103 +++++++++- .../com/sinthoras/visualprospecting/Tags.java | 8 +- 3 files changed, 228 insertions(+), 68 deletions(-) diff --git a/build.gradle b/build.gradle index 39309904..1aaadcce 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1685785062 +//version: 1690104383 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -69,7 +69,7 @@ plugins { id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.14' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.21' } print("You might want to check out './gradlew :faq' if your build fails.\n") @@ -115,6 +115,8 @@ propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) propertyDefaultIfUnset("forceEnableMixins", false) propertyDefaultIfUnset("channel", "stable") propertyDefaultIfUnset("mappingsVersion", "12") +propertyDefaultIfUnset("usesMavenPublishing", true) +propertyDefaultIfUnset("mavenPublishUrl", "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases") propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") @@ -357,7 +359,27 @@ catch (Exception ignored) { String identifiedVersion String versionOverride = System.getenv("VERSION") ?: null try { - identifiedVersion = versionOverride == null ? gitVersion() : versionOverride + // Produce a version based on the tag, or for branches something like 0.2.2-configurable-maven-and-extras.38+43090270b6-dirty + if (versionOverride == null) { + def gitDetails = versionDetails() + def isDirty = gitVersion().endsWith(".dirty") // No public API for this, isCleanTag has a different meaning + String branchName = gitDetails.branchName ?: (System.getenv('GIT_BRANCH') ?: 'git') + if (branchName.startsWith('origin/')) { + branchName = branchName.minus('origin/') + } + branchName = branchName.replaceAll("[^a-zA-Z0-9-]+", "-") // sanitize branch names for semver + identifiedVersion = gitDetails.lastTag ?: '${gitDetails.gitHash}' + if (gitDetails.commitDistance > 0) { + identifiedVersion += "-${branchName}.${gitDetails.commitDistance}+${gitDetails.gitHash}" + if (isDirty) { + identifiedVersion += "-dirty" + } + } else if (isDirty) { + identifiedVersion += "-${branchName}+${gitDetails.gitHash}-dirty" + } + } else { + identifiedVersion = versionOverride + } } catch (Exception ignored) { out.style(Style.Failure).text( @@ -465,10 +487,19 @@ sourceSets { } } -if (file('addon.gradle').exists()) { +if (file('addon.gradle.kts').exists()) { + apply from: 'addon.gradle.kts' +} else if (file('addon.gradle').exists()) { apply from: 'addon.gradle' } +// File for local tweaks not commited to Git +if (file('addon.local.gradle.kts').exists()) { + apply from: 'addon.local.gradle.kts' +} else if (file('addon.local.gradle').exists()) { + apply from: 'addon.local.gradle' +} + // Allow unsafe repos but warn repositories.configureEach { repo -> if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) { @@ -479,7 +510,14 @@ repositories.configureEach { repo -> } } -apply from: 'repositories.gradle' +if (file('repositories.gradle.kts').exists()) { + apply from: 'repositories.gradle.kts' +} else if (file('repositories.gradle').exists()) { + apply from: 'repositories.gradle' +} else { + logger.error("Neither repositories.gradle.kts nor repositories.gradle was found, make sure you extracted the full ExampleMod template.") + throw new RuntimeException("Missing repositories.gradle[.kts]") +} configurations { runtimeClasspath.extendsFrom(runtimeOnlyNonPublishable) @@ -537,13 +575,28 @@ repositories { } } if (includeWellKnownRepositories.toBoolean()) { - maven { - name "CurseMaven" - url "https://cursemaven.com" - content { + exclusiveContent { + forRepository { + maven { + name "CurseMaven" + url "https://cursemaven.com" + } + } + filter { includeGroup "curse.maven" } } + exclusiveContent { + forRepository { + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + } + } + filter { + includeGroup "maven.modrinth" + } + } maven { name = "ic2" url = "https://maven.ic2.player.to/" @@ -585,7 +638,7 @@ dependencies { } } if (usesMixins.toBoolean()) { - implementation(mixinProviderSpec) + implementation(modUtils.enableMixins(mixinProviderSpec)) } else if (forceEnableMixins.toBoolean()) { runtimeOnlyNonPublishable(mixinProviderSpec) } @@ -611,12 +664,34 @@ configurations.all { } } -apply from: 'dependencies.gradle' +dependencies { + constraints { + def minGtnhLibVersion = "0.0.13" + implementation("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + runtimeOnly("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + devOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + runtimeOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { + because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") + } + } +} + +if (file('dependencies.gradle.kts').exists()) { + apply from: 'dependencies.gradle.kts' +} else if (file('dependencies.gradle').exists()) { + apply from: 'dependencies.gradle' +} else { + logger.error("Neither dependencies.gradle.kts nor dependencies.gradle was found, make sure you extracted the full ExampleMod template.") + throw new RuntimeException("Missing dependencies.gradle[.kts]") +} def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' -def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' -def refMap = "${mixinTmpDir}" + File.separator + mixingConfigRefMap -def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" tasks.register('generateAssets') { group = "GTNH Buildscript" @@ -648,46 +723,17 @@ tasks.register('generateAssets') { } if (usesMixins.toBoolean()) { - tasks.named("reobfJar", ReobfuscatedJar).configure { - extraSrgFiles.from(mixinSrg) - } - tasks.named("processResources").configure { dependsOn("generateAssets") } tasks.named("compileJava", JavaCompile).configure { - doFirst { - new File(mixinTmpDir).mkdirs() - } options.compilerArgs += [ - "-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}", - "-AoutSrgFile=${mixinSrg}", - "-AoutRefMapFile=${refMap}", // Elan: from what I understand they are just some linter configs so you get some warning on how to properly code "-XDenableSunApiLintControl", "-XDignore.symbol.file" ] } - - pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { - kapt { - correctErrorTypes = true - javacOptions { - option("-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}") - option("-AoutSrgFile=$mixinSrg") - option("-AoutRefMapFile=$refMap") - } - } - tasks.configureEach { task -> - if (task.name == "kaptKotlin") { - task.doFirst { - new File(mixinTmpDir).mkdirs() - } - } - } - } - } tasks.named("processResources", ProcessResources).configure { @@ -705,7 +751,6 @@ tasks.named("processResources", ProcessResources).configure { } if (usesMixins.toBoolean()) { - from refMap dependsOn("compileJava", "compileScala") } } @@ -724,13 +769,13 @@ ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies" } dependencies { - def lwjgl3ifyVersion = '1.3.5' + def lwjgl3ifyVersion = '1.4.0' def asmVersion = '9.4' if (modId != 'lwjgl3ify') { java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") } if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.13') + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.19') } java17PatchDependencies('net.minecraft:launchwrapper:1.15') {transitive = false} @@ -979,6 +1024,9 @@ idea { } } runConfigurations { + "0. Build and Test"(Gradle) { + taskNames = ["build"] + } "1. Run Client"(Gradle) { taskNames = ["runClient"] } @@ -1098,6 +1146,11 @@ tasks.named("processIdeaSettings").configure { dependsOn("injectTags") } +tasks.named("ideVirtualMainClasses").configure { + // Make IntelliJ "Build project" build the mod jars + dependsOn("jar", "reobfJar", "spotlessCheck") +} + // workaround variable hiding in pom processing def projectConfigs = project.configurations @@ -1118,12 +1171,14 @@ publishing { } repositories { - maven { - url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases" - allowInsecureProtocol = true - credentials { - username = System.getenv("MAVEN_USER") ?: "NONE" - password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + if (usesMavenPublishing.toBoolean()) { + maven { + url = mavenPublishUrl + allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven + credentials { + username = System.getenv("MAVEN_USER") ?: "NONE" + password = System.getenv("MAVEN_PASSWORD") ?: "NONE" + } } } } @@ -1238,7 +1293,7 @@ def addCurseForgeRelation(String type, String name) { // Updating -def buildscriptGradleVersion = "8.1.1" +def buildscriptGradleVersion = "8.2.1" tasks.named('wrapper', Wrapper).configure { gradleVersion = buildscriptGradleVersion @@ -1344,8 +1399,14 @@ boolean isNewBuildScriptVersionAvailable() { String currentBuildScript = getFile("build.gradle").getText() String currentBuildScriptHash = getVersionHash(currentBuildScript) - String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() - String availableBuildScriptHash = getVersionHash(availableBuildScript) + String availableBuildScriptHash + try { + String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() + availableBuildScriptHash = getVersionHash(availableBuildScript) + } catch (IOException e) { + logger.warn("Could not check for buildscript update availability: {}", e.message) + return false + } boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash return !isUpToDate @@ -1510,3 +1571,17 @@ def getSecondaryArtifacts() { if (apiPackage) secondaryArtifacts += [apiJar] return secondaryArtifacts } + +// For easier scripting of things that require variables defined earlier in the buildscript +if (file('addon.late.gradle.kts').exists()) { + apply from: 'addon.late.gradle.kts' +} else if (file('addon.late.gradle').exists()) { + apply from: 'addon.late.gradle' +} + +// File for local tweaks not commited to Git +if (file('addon.late.local.gradle.kts').exists()) { + apply from: 'addon.late.local.gradle.kts' +} else if (file('addon.late.local.gradle').exists()) { + apply from: 'addon.late.local.gradle' +} diff --git a/gradle.properties b/gradle.properties index 308204be..37e0e97c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,22 +15,40 @@ autoUpdateBuildScript = false minecraftVersion = 1.7.10 forgeVersion = 10.13.4.1614 +# Specify a MCP channel and mappings version for dependency deobfuscation and the deobfParams task. +channel = stable +mappingsVersion = 12 + +# Define other MCP mappings for dependency deobfuscation +remoteMappings = https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/ + # 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 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, Map types +enableGenericInjection = true + +# Generate a class with String fields for the mod id, name, version and group name named with the fields below +generateGradleTokenClass = com.sinthoras.visualprospecting.Version +gradleTokenModId = +gradleTokenModName = +gradleTokenVersion = VERSION +gradleTokenGroupName = +# [DEPRECATED] +# Multiple source files can be defined here by providing a comma-seperated 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 = Tags.java -gradleTokenModId = GRADLETOKEN_MODID -gradleTokenModName = GRADLETOKEN_MODNAME -gradleTokenVersion = GRADLETOKEN_VERSION -gradleTokenGroupName = GRADLETOKEN_GROUPNAME +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. @@ -38,11 +56,14 @@ gradleTokenGroupName = GRADLETOKEN_GROUPNAME 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 comma-separated list. +# Example value: mymodid_at.cfg,nei_at.cfg accessTransformersFile = # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! usesMixins = true +# Adds some debug arguments like verbose output and export +usesMixinDebug = true # 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! @@ -55,10 +76,74 @@ coreModClass = mixinplugin.VisualProspectingEarlyMixinLoader # that is annotated with @Mod) you want this to be true. When in doubt: leave it on false! containsMixinsAndOrCoreModOnly = false -# If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your +# 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 in your jar. It is your # responsibility check the licence and request permission for distribution, if required. usesShadowedDependencies = true +# If disabled, won't remove unused classes from shaded 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 the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories +includeWellKnownRepositories = true + +# 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_USERNAME 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 +# mavenPublishUrl = http://jenkins.usrv.eu:8081/nexus/content/repositories/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 on Modrinth. +modrinthProjectId = + +# 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 = + + +# 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 = + +# 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: GTNH Mixins is automatically set as a required dependency if usesMixins = true +curseForgeRelations = + # Optional parameter to customize the produced artifacts. Use this to preserver artifact naming when migrating older # projects. New projects should not use this parameter. -#customArchiveBaseName = +# customArchiveBaseName = + +# Optional parameter to prevent the source code from being published +# noPublishedSources = + +# 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 + +# Override the IDEA build type. Valid value is "" (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 always 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 diff --git a/src/main/java/com/sinthoras/visualprospecting/Tags.java b/src/main/java/com/sinthoras/visualprospecting/Tags.java index b84d0d26..7868acb5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Tags.java +++ b/src/main/java/com/sinthoras/visualprospecting/Tags.java @@ -5,10 +5,10 @@ public class Tags { // GRADLETOKEN_* will be replaced by your configuration values at build time - public static final String MODID = "GRADLETOKEN_MODID"; - public static final String MODNAME = "GRADLETOKEN_MODNAME"; - public static final String VERSION = "GRADLETOKEN_VERSION"; - public static final String GROUPNAME = "GRADLETOKEN_GROUPNAME"; + public static final String MODID = "visualprospecting"; + public static final String MODNAME = "VisualProspecting"; + public static final String VERSION = Version.VERSION; + public static final String GROUPNAME = "com.sinthoras.visualprospecting"; public static final String VISUALPROSPECTING_DIR = MODID + "/"; public static final String CLIENT_DIR = VISUALPROSPECTING_DIR + "client/"; From afd991bc93b774a78829b0f62a9bf2bad8b81ae2 Mon Sep 17 00:00:00 2001 From: glowredman <35727266+glowredman@users.noreply.github.com> Date: Thu, 27 Jul 2023 21:40:58 +0200 Subject: [PATCH 032/132] Small cleanup --- .../com/sinthoras/visualprospecting/ServerTranslations.java | 1 + .../database/cachebuilder/DetailedChunkAnalysis.java | 1 + .../journeymap/drawsteps/UndergroundFluidDrawStep.java | 1 + .../integration/model/layers/LayerManager.java | 1 - .../integration/voxelmap/VoxelMapEventHandler.java | 1 + .../xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java | 1 + .../com/sinthoras/visualprospecting/item/ProspectorsLog.java | 2 +- 7 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java b/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java index 4021cbec..154f8b1c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java +++ b/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java @@ -9,6 +9,7 @@ // Backup translations for server side lookups only public class ServerTranslations { + @SuppressWarnings("deprecation") public static String getEnglishLocalization(Fluid fluid) { if (MinecraftServer.getServer().isSinglePlayer()) { return fluid.getLocalizedName(); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index 8edb084e..61fbe552 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -19,6 +19,7 @@ public class DetailedChunkAnalysis { public final int chunkX; public final int chunkZ; // For each height we count how often a ore (short) has occured + @SuppressWarnings("unchecked") private final Map[] oresPerY = new HashMap[VP.minecraftWorldHeight]; public DetailedChunkAnalysis(int dimensionId, int chunkX, int chunkZ) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java index 3a024260..14fd1dd0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java @@ -60,6 +60,7 @@ public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRe borderColor, borderAlpha); + @SuppressWarnings("deprecation") final String label = undergroundFluidLocation.getMinProduction() + "L - " + maxAmountInField + "L " diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java index 7b0dd31e..947fce88 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java @@ -14,7 +14,6 @@ public abstract class LayerManager { private final ButtonManager buttonManager; - private boolean isLayerActive = false; protected boolean forceRefresh = false; private List visibleElements = new ArrayList<>(); protected Map layerRenderer = new EnumMap<>(SupportedMods.class); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java index 32a3246f..e9f384c6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java @@ -48,6 +48,7 @@ public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { dim)); // dimension } + @SuppressWarnings("deprecation") @SubscribeEvent public void onFluidProspected(ProspectingNotificationEvent.UndergroundFluid event) { if (event.isCanceled()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java index bb0153ff..81e9fcf0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java @@ -40,6 +40,7 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double // min scale that journeymap can go to if (scale >= 1 && gui != null) { GL11.glScaled(1 / scale, 1 / scale, 1); + @SuppressWarnings("deprecation") final String label = undergroundFluidLocation.getMinProduction() + "L - " + maxAmountInField + "L " diff --git a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java index 51e48f3a..bcedac0b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java +++ b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java @@ -86,7 +86,7 @@ public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer play } @Override - public void addInformation(ItemStack item, EntityPlayer player, List infoList, boolean ignored) { + public void addInformation(ItemStack item, EntityPlayer player, List infoList, boolean ignored) { if (isFilledLog(item)) { final NBTTagCompound compound = item.getTagCompound(); infoList.add( From 388ed14d9ae91ab91799b1425a43abc8f1f67058 Mon Sep 17 00:00:00 2001 From: glowredman <35727266+glowredman@users.noreply.github.com> Date: Thu, 27 Jul 2023 21:41:56 +0200 Subject: [PATCH 033/132] Use PlayerLoggedInEvent instead of EntityJoinWorldEvent --- .../visualprospecting/hooks/HooksEventBus.java | 17 ----------------- .../visualprospecting/hooks/HooksFML.java | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java index 45d7bbff..7f9350f9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java @@ -1,16 +1,10 @@ package com.sinthoras.visualprospecting.hooks; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.world.WorldEvent; import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.ServerCache; -import com.sinthoras.visualprospecting.database.WorldIdHandler; -import com.sinthoras.visualprospecting.network.WorldIdNotification; import cpw.mods.fml.common.eventhandler.SubscribeEvent; @@ -27,15 +21,4 @@ public void onEvent(WorldEvent.Unload event) { public void onEvent(WorldEvent.Save event) { ServerCache.instance.saveVeinCache(); } - - @SubscribeEvent - public void onEvent(EntityJoinWorldEvent event) { - if (event.world.isRemote == false) { - if (event.entity instanceof EntityPlayerMP) { - VP.network.sendTo(new WorldIdNotification(WorldIdHandler.getWorldId()), (EntityPlayerMP) event.entity); - } else if (event.entity instanceof EntityPlayer) { - ClientCache.instance.loadVeinCache(WorldIdHandler.getWorldId()); - } - } - } } diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java index 530734e5..31c6297f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java @@ -1,9 +1,17 @@ package com.sinthoras.visualprospecting.hooks; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; + +import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; +import com.sinthoras.visualprospecting.database.WorldIdHandler; +import com.sinthoras.visualprospecting.network.WorldIdNotification; import com.sinthoras.visualprospecting.task.TaskManager; +import cpw.mods.fml.common.eventhandler.EventPriority; import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent; import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.common.network.FMLNetworkEvent; @@ -18,4 +26,13 @@ public void onEvent(FMLNetworkEvent.ClientConnectedToServerEvent event) { public void onEvent(TickEvent event) { TaskManager.instance.onTick(); } + + @SubscribeEvent(priority = EventPriority.LOW) + public void onEvent(PlayerEvent.PlayerLoggedInEvent event) { + if (event.player instanceof EntityPlayerMP playerMP) { + VP.network.sendTo(new WorldIdNotification(WorldIdHandler.getWorldId()), playerMP); + } else if (event.player instanceof EntityPlayer) { + ClientCache.instance.loadVeinCache(WorldIdHandler.getWorldId()); + } + } } From 3c6bb6a07c6bae51cab47105f491da25510e326a Mon Sep 17 00:00:00 2001 From: miozune Date: Sat, 23 Sep 2023 13:38:40 +0900 Subject: [PATCH 034/132] Minor cleanup (#38) * updateBuildScript * Update dependencies * Remove duplicated event bus registration * Fix deprecated basic machine constructors * Fix wildcard import --- build.gradle | 88 +++++++++++++----- dependencies.gradle | 6 +- gradle/wrapper/gradle-wrapper.jar | Bin 61608 -> 62076 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 7 +- .../sinthoras/visualprospecting/Utils.java | 7 +- .../sinthoras/visualprospecting/VPMod.java | 9 +- .../database/ClientCache.java | 5 +- .../database/DimensionCache.java | 6 +- .../database/TransferCache.java | 7 +- .../database/cachebuilder/ChunkAnalysis.java | 4 +- .../cachebuilder/DetailedChunkAnalysis.java | 11 ++- .../database/veintypes/VeinTypeCaching.java | 8 +- .../visualprospecting/hooks/HooksKey.java | 2 - .../journeymap/JourneyMapState.java | 13 ++- .../journeymap/buttons/LayerButton.java | 2 +- .../journeymap/waypoints/WaypointManager.java | 2 +- .../integration/model/MapState.java | 13 ++- .../xaeroworldmap/XaeroWorldMapState.java | 6 +- .../VisualProspectingEarlyMixinLoader.java | 6 +- ...aTileEntity_AdvSeismicProspectorMixin.java | 3 +- .../GT_MetaTileEntity_ScannerMixin.java | 3 +- .../network/ProspectingRequest.java | 4 +- 23 files changed, 162 insertions(+), 52 deletions(-) diff --git a/build.gradle b/build.gradle index 1aaadcce..7ff83a31 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1690104383 +//version: 1695409603 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -69,7 +69,7 @@ plugins { id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.21' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.24' } print("You might want to check out './gradlew :faq' if your build fails.\n") @@ -89,6 +89,23 @@ def out = services.get(StyledTextOutputFactory).create('an-output') def projectJavaVersion = JavaLanguageVersion.of(8) boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false +boolean disableCheckstyle = project.hasProperty("disableCheckstyle") ? project.disableCheckstyle.toBoolean() : false + +final String CHECKSTYLE_CONFIG = """ + + + + + + + + + + + +""" checkPropertyExists("modName") checkPropertyExists("modId") @@ -140,6 +157,17 @@ if (!disableSpotless) { apply from: Blowdryer.file('spotless.gradle') } +if (!disableCheckstyle) { + apply plugin: 'checkstyle' + tasks.named("checkstylePatchedMc") { enabled = false } + tasks.named("checkstyleMcLauncher") { enabled = false } + tasks.named("checkstyleIdeVirtualMain") { enabled = false } + tasks.named("checkstyleInjectedTags") { enabled = false } + checkstyle { + config = resources.text.fromString(CHECKSTYLE_CONFIG) + } +} + String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" @@ -401,9 +429,13 @@ if (identifiedVersion == versionOverride) { group = "com.github.GTNewHorizons" if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { - archivesBaseName = customArchiveBaseName + base { + archivesName = customArchiveBaseName + } } else { - archivesBaseName = modId + base { + archivesName = modId + } } @@ -558,9 +590,6 @@ repositories { maven { name 'Overmind forge repo mirror' url 'https://gregtech.overminddl1.com/' - mavenContent { - excludeGroup("net.minecraftforge") // missing the `universal` artefact - } } maven { name = "GTNH Maven" @@ -599,15 +628,10 @@ repositories { } maven { name = "ic2" - url = "https://maven.ic2.player.to/" - metadataSources { - mavenPom() - artifact() + url = getURL("https://maven.ic2.player.to/", "https://maven2.ic2.player.to/") + content { + includeGroup "net.industrial-craft" } - } - maven { - name = "ic2-mirror" - url = "https://maven2.ic2.player.to/" metadataSources { mavenPom() artifact() @@ -627,6 +651,8 @@ def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule} def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev" ext.mixinProviderSpec = mixinProviderSpec +def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' + dependencies { if (usesMixins.toBoolean()) { annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3') @@ -638,7 +664,7 @@ dependencies { } } if (usesMixins.toBoolean()) { - implementation(modUtils.enableMixins(mixinProviderSpec)) + implementation(modUtils.enableMixins(mixinProviderSpec, mixingConfigRefMap)) } else if (forceEnableMixins.toBoolean()) { runtimeOnlyNonPublishable(mixinProviderSpec) } @@ -691,8 +717,6 @@ if (file('dependencies.gradle.kts').exists()) { throw new RuntimeException("Missing dependencies.gradle[.kts]") } -def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' - tasks.register('generateAssets') { group = "GTNH Buildscript" description = "Generates a mixin config file at /src/main/resources/mixins.modid.json if needed" @@ -775,10 +799,10 @@ dependencies { java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") } if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.19') + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.26') } - java17PatchDependencies('net.minecraft:launchwrapper:1.15') {transitive = false} + java17PatchDependencies('net.minecraft:launchwrapper:1.17.2') {transitive = false} java17PatchDependencies("org.ow2.asm:asm:${asmVersion}") java17PatchDependencies("org.ow2.asm:asm-commons:${asmVersion}") java17PatchDependencies("org.ow2.asm:asm-tree:${asmVersion}") @@ -1148,7 +1172,10 @@ tasks.named("processIdeaSettings").configure { tasks.named("ideVirtualMainClasses").configure { // Make IntelliJ "Build project" build the mod jars - dependsOn("jar", "reobfJar", "spotlessCheck") + dependsOn("jar", "reobfJar") + if (!disableSpotless) { + dependsOn("spotlessCheck") + } } // workaround variable hiding in pom processing @@ -1572,6 +1599,25 @@ def getSecondaryArtifacts() { return secondaryArtifacts } +def getURL(String main, String fallback) { + return pingURL(main, 10000) ? main : fallback +} + +// credit: https://stackoverflow.com/a/3584332 +def pingURL(String url, int timeout) { + url = url.replaceFirst("^https", "http") // Otherwise an exception may be thrown on invalid SSL certificates. + try { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection() + connection.setConnectTimeout(timeout) + connection.setReadTimeout(timeout) + connection.setRequestMethod("HEAD") + int responseCode = connection.getResponseCode() + return 200 <= responseCode && responseCode <= 399 + } catch (IOException ignored) { + return false + } +} + // For easier scripting of things that require variables defined earlier in the buildscript if (file('addon.late.gradle.kts').exists()) { apply from: 'addon.late.gradle.kts' diff --git a/dependencies.gradle b/dependencies.gradle index 9a287c2a..9f3548ca 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,13 +1,13 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.43.111:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.22:dev') api('curse.maven:journeymap-32274:4500659') devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.1.7:dev') - compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.9:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.7.20:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.10:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.8.5:dev') {transitive = false} compileOnly(deobf('https://media.forgecdn.net/files/4127/308/Xaeros_Minimap_21.10.30_Forge_1.7.10.jar')) compileOnly(deobf('https://media.forgecdn.net/files/4127/328/XaerosWorldMap_1.14.1.22_Forge_1.7.10.jar')) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ccebba7710deaf9f98673a68957ea02138b60d0a..c1962a79e29d3e0ab67b14947c167a862655af9b 100644 GIT binary patch delta 8979 zcmY*fV{{$d(moANW81db*tXT!Nn`UgX2ZtD$%&n`v2C-lt;YD?@2-14?EPcUv!0n* z`^Ws4HP4i8L%;4p*JkD-J9ja2aKi!sX@~#-MY5?EPBK~fXAl)Ti}^QGH@6h+V+|}F zv=1RqQxhWW9!hTvYE!)+*m%jEL^9caK;am9X8QP~a9X0N6(=WSX8KF#WpU-6TjyR3 zpKhscivP97d$DGc{KI(f#g07u{Jr0wn#+qNr}yW}2N3{Kx0lCq%p4LBKil*QDTEyR zg{{&=GAy_O0VJ(8ZbtS4tPeeeILKK(M?HtQY!6K^wt zxsPH>E%g%V@=!B;kWF54$xjC&4hO!ZEG0QFMHLqe!tgH;%vO62BQj||nokbX&2kxF zzg#N!2M|NxFL#YdwOL8}>iDLr%2=!LZvk_&`AMrm7Zm%#_{Ot_qw=HkdVg{f9hYHF zlRF*9kxo~FPfyBD!^d6MbD?BRZj(4u9j!5}HFUt+$#Jd48Fd~ahe@)R9Z2M1t%LHa z_IP|tDb0CDl(fsEbvIYawJLJ7hXfpVw)D-)R-mHdyn5uZYefN0rZ-#KDzb`gsow;v zGX>k|g5?D%Vn_}IJIgf%nAz{@j0FCIEVWffc1Z+lliA}L+WJY=MAf$GeI7xw5YD1) z;BJn$T;JI5vTbZ&4aYfmd-XPQd)YQ~d({>(^5u>Y^5rfxEUDci9I5?dXp6{zHG=Tc z6$rLd^C~60=K4ptlZ%Fl-%QLc-x{y=zU$%&4ZU}4&Yu?jF4eqB#kTHhty`Aq=kJE% zzq(5OS9o1t-)}S}`chh1Uu-Sl?ljxMDVIy5j`97Eqg7L~Ak9NSZ?!5M>5TRMXfD#} zFlMmFnr%?ra>vkvJQjmWa8oB{63qPo1L#LAht%FG|6CEe9KP2&VNe_HNb7M}pd*!t zpGL0vzCU02%iK@AKWxP^64fz-U#%u~D+FV?*KdPY9C_9{Ggn;Y;;iKE0b|}KmC&f(WIDcFtvRPDju z?Dc&_dP4*hh!%!6(nYB*TEJs<4zn*V0Nw1O4VzYaNZul>anE2Feb@T$XkI?)u6VK$bg* z22AY7|Ju!_jwc2@JX(;SUE>VDWRD|d56WYUGLAAwPYXU9K&NgY{t{dyMskUBgV%@p zMVcFn>W|hJA?3S?$k!M|1S2e1A&_~W2p$;O2Wpn`$|8W(@~w>RR4kxHdEr`+q|>m@ zTYp%Ut+g`T#HkyE5zw<5uhFvt2=k5fM3!8OxvGgMRS|t7RaJn7!2$r_-~a%C7@*Dq zGUp2g0N^HzLU=%bROVFi2J;#`7#WGTUI$r!(wmbJlbS`E#ZpNp7vOR#TwPQWNf$IW zoX>v@6S8n6+HhUZB7V^A`Y9t4ngdfUFZrDOayMVvg&=RY4@0Z~L|vW)DZTIvqA)%D zi!pa)8L7BipsVh5-LMH4bmwt2?t88YUfIRf!@8^gX$xpKTE^WpM!-=3?UVw^Cs`Y7 z2b<*~Q=1uqs79{h&H_8+X%><4qSbz_cSEa;Hkdmtq5uwGTY+|APD{i_zYhLXqT7HO zT^Am_tW?Cmn%N~MC0!9mYt-~WK;hj-SnayMwqAAHo#^ALwkg0>72&W}5^4%|Z|@T; zwwBQTg*&eXC}j8 zra77(XC^p&&o;KrZ$`_)C$@SDWT+p$3!;ZB#yhnK{CxQc&?R}ZQMcp`!!eXLLhiP8W zM=McHAMnUMlar8XLXk&jx#HBH3U0jbhJuqa~#l`aB)N6;WI(Im322o#{K&92l6(K z)(;=;-m!%9@j#WSA1uniU(^x(UTi+%idMd)x*!*Hub0Rg7DblI!cqo9QUZf29Y#?XN!K!|ovJ7~!^H}!zsaMl(57lpztQ7V zyo#`qJ4jv1zGAW2uIkU3o&7_=lYWz3=SR!sgfuYp{Um<*H%uW8MdUT2&o*QKjD3PEH zHz;H}qCN~`GFsJ_xz$9xga*@VzJTH7-3lggkBM&7xlz5#qWfkgi=#j%{&f-NMsaSv zeIZ60Jpw}QV+t`ovOJxVhYCXe8E7r*eLCJ{lP6sqc}BYrhjXlt(6e9nw=2Le1gOT0 zZX!q9r#DZ&8_cAhWPeq~CJkGvpRU&q8>rR@RBW4~@3j1X>RBum#U z1wjcEdB`|@sXAWxk2*TOj> zr(j{nr1;Mk3x^gvAtZsahY=ou{eAJi-d(XISF-?+Q6{Um4+lu?aA=S33@k=6^OT?F z8TE`ha;q@=ZQ-dlt!q49;Wjjl<&Yee^!h5MFkd)Oj=fsvxytK%!B z-P#YJ)8^dMi=wpKmt43|apX6v2dNXzZ-WHlLEh`JoKFNjCK7LhO^P5XW?Y~rjGcIpv$2v41rE}~0{aj9NVpDXGdD6W8{fyzioQdu&xkn8 zhT*^NY0zv>Om?h3XAku3p-4SHkK@fXrpi{T=@#bwY76TsD4$tAHAhXAStdb$odc z02~lZyb!fG_7qrU_F5 zoOG|pEwdyDhLXDwlU>T|;LF@ACJk(qZ*2h6GB@33mKk};HO^CQM(N7@Ml5|8IeHzt zdG4f$q}SNYA4P=?jV!mJ%3hRKwi&!wFptWZRq4bpV9^b7&L>nW%~Y|junw!jHj%85 z3Ck6%`Y=Abvrujnm{`OtE0uQkeX@3JPzj#iO#eNoAX6cDhM+cc2mLk8;^bG62mtjQ zj|kxI2W|4n{VqMqB?@YnA0y}@Mju)&j3UQ4tSdH=Eu?>i7A50b%i$pc{YJki7ubq7 zVTDqdkGjeAuZdF)KBwR6LZob}7`2935iKIU2-I;88&?t16c-~TNWIcQ8C_cE_F1tv z*>4<_kimwX^CQtFrlk)i!3-+2zD|=!D43Qqk-LtpPnX#QQt%eullxHat97k=00qR|b2|M}`q??yf+h~};_PJ2bLeEeteO3rh+H{9otNQDki^lu)(`a~_x(8NWLE*rb%T=Z~s?JC|G zXNnO~2SzW)H}p6Zn%WqAyadG=?$BXuS(x-2(T!E&sBcIz6`w=MdtxR<7M`s6-#!s+ znhpkcNMw{c#!F%#O!K*?(Hl(;Tgl9~WYBB(P@9KHb8ZkLN>|}+pQ)K#>ANpV1IM{Q z8qL^PiNEOrY*%!7Hj!CwRT2CN4r(ipJA%kCc&s;wOfrweu)H!YlFM z247pwv!nFWbTKq&zm4UVH^d?H2M276ny~@v5jR2>@ihAmcdZI-ah(&)7uLQM5COqg?hjX2<75QU4o5Q7 zZ5gG;6RMhxLa5NFTXgegSXb0a%aPdmLL4=`ox2smE)lDn^!;^PNftzTf~n{NH7uh_ zc9sKmx@q1InUh_BgI3C!f>`HnO~X`9#XTI^Yzaj1928gz8ClI!WIB&2!&;M18pf0T zsZ81LY3$-_O`@4$vrO`Cb&{apkvUwrA0Z49YfZYD)V4;c2&`JPJuwN_o~2vnyW_b! z%yUSS5K{a*t>;WJr&$A_&}bLTTXK23<;*EiNHHF-F<#hy8v2eegrqnE=^gt+|8R5o z_80IY4&-!2`uISX6lb0kCVmkQ{D}HMGUAkCe`I~t2~99(<#}{E;{+Y0!FU>leSP(M zuMoSOEfw3OC5kQ~Y2)EMlJceJlh}p?uw}!cq?h44=b2k@T1;6KviZGc_zbeTtTE$@EDwUcjxd#fpK=W*U@S#U|YKz{#qbb*|BpcaU!>6&Ir zhsA+ywgvk54%Nj>!!oH>MQ+L~36v1pV%^pOmvo7sT|N}$U!T6l^<3W2 z6}mT7Cl=IQo%Y~d%l=+;vdK)yW!C>Es-~b^E?IjUU4h6<86tun6rO#?!37B)M8>ph zJ@`~09W^@5=}sWg8`~ew=0>0*V^b9eG=rBIGbe3Ko$pj!0CBUTmF^Q}l7|kCeB(pX zi6UvbUJWfKcA&PDq?2HrMnJBTW#nm$(vPZE;%FRM#ge$S)i4!y$ShDwduz@EPp3H? z`+%=~-g6`Ibtrb=QsH3w-bKCX1_aGKo4Q7n-zYp->k~KE!(K@VZder&^^hIF6AhiG z;_ig2NDd_hpo!W1Un{GcB@e{O@P3zHnj;@SzYCxsImCHJS5I&^s-J6?cw92qeK8}W zk<_SvajS&d_tDP~>nhkJSoN>UZUHs?)bDY`{`;D^@wMW0@!H1I_BYphly0iqq^Jp; z_aD>eHbu@e6&PUQ4*q*ik0i*$Ru^_@`Mbyrscb&`8|c=RWZ>Ybs16Q?Cj1r6RQA5! zOeuxfzWm(fX!geO(anpBCOV|a&mu|$4cZ<*{pb1F{`-cm1)yB6AGm7b=GV@r*DataJ^I!>^lCvS_@AftZiwtpszHmq{UVl zKL9164tmF5g>uOZ({Jg~fH~QyHd#h#E;WzSYO~zt)_ZMhefdm5*H1K-#=_kw#o%ch zgX|C$K4l4IY8=PV6Q{T8dd`*6MG-TlsTEaA&W{EuwaoN+-BDdSL2>|lwiZ++4eR8h zNS1yJdbhAWjW4k`i1KL)l#G*Y=a0ouTbg8R1aUU`8X7p*AnO+uaNF9mwa+ooA)hlj zR26XBpQ-{6E9;PQAvq2<%!M1;@Q%r@xZ16YRyL&v}9F`Nnx#RLUc<78w$S zZElh==Rnr2u<*qKY|aUR9(A|{cURqP81O-1a@X)khheokEhC}BS-g~|zRbn-igmID z$Ww!O0-j!t(lx>-JH+0KW3*Bgafpm>%n=`(ZLa^TWd*-je!Xi7H*bZ8pz`HPFYeC? zk>`W)4Cj6*A3A8g$MEhp*<@qO&&>3<4YI%0YAMmQvD3 z${78Fa2mqiI>P7|gE)xs$cg3~^?UBb4y6B4Z#0Fzy zN8Gf!c+$uPS`VRB=wRV1f)>+PEHBYco<1?ceXET}Q-tKI=E`21<15xTe@%Bhk$v09 zVpoL_wNuw)@^O+C@VCeuWM}(%C(%lTJ}7n)JVV!^0H!3@)ydq#vEt;_*+xos$9i?{ zCw5^ZcNS&GzaeBmPg6IKrbT`OSuKg$wai+5K}$mTO-Z$s3Y+vb3G}x%WqlnQS1;|Z zlZ$L{onq1Ag#5JrM)%6~ToQ}NmM2A(7X5gy$nVI=tQFOm;7|Oeij{xb_KU{d@%)2z zsVqzTl@XPf(a95;P;oBm9Hlpo`9)D9>G>!Bj=ZmX{ces=aC~E^$rTO5hO$#X65jEA zMj1(p+HXdOh7FAV;(_)_RR#P>&NW?&4C7K1Y$C$i**g;KOdu|JI_Ep zV-N$wuDRkn6=k|tCDXU%d=YvT!M1nU?JY;Pl`dxQX5+660TX7~q@ukEKc!Iqy2y)KuG^Q-Y%$;SR&Mv{%=CjphG1_^dkUM=qI*3Ih^Bk621n`6;q(D;nB_y|~ zW*1ps&h|wcET!#~+Ptsiex~YVhDiIREiw1=uwlNpPyqDZ`qqv9GtKwvxnFE}ME93fD9(Iq zz=f&4ZpD~+qROW6Y2AjPj9pH*r_pS_f@tLl88dbkO9LG0+|4*Xq(Eo7fr5MVg{n<+p>H{LGr}UzToqfk_x6(2YB~-^7>%X z+331Ob|NyMST64u|1dK*#J>qEW@dKNj-u}3MG)ZQi~#GzJ_S4n5lb7vu&>;I-M49a z0Uc#GD-KjO`tQ5ftuSz<+`rT)cLio$OJDLtC`t)bE+Nu@Rok2;`#zv1=n z7_CZr&EhVy{jq(eJPS)XA>!7t<&ormWI~w0@Y#VKjK)`KAO~3|%+{ z$HKIF?86~jH*1p=`j#}8ON0{mvoiN7fS^N+TzF~;9G0_lQ?(OT8!b1F8a~epAH#uA zSN+goE<-psRqPXdG7}w=ddH=QAL|g}x5%l-`Kh69D4{M?jv!l))<@jxLL$Eg2vt@E zc6w`$?_z%awCE~ca)9nMvj($VH%2!?w3c(5Y4&ZC2q#yQ=r{H2O839eoBJ{rfMTs8 zn2aL6e6?;LY#&(BvX_gC6uFK`0yt zJbUATdyz5d3lRyV!rwbj0hVg#KHdK0^A7_3KA%gKi#F#-^K%1XQbeF49arI2LA|Bj z?=;VxKbZo(iQmHB5eAg=8IPRqyskQNR!&KEPrGv&kMr(8`4oe?vd?sIZJK+JY04kc zXWk)4N|~*|0$4sUV3U6W6g+Z3;nN<~n4H17QT*%MCLt_huVl@QkV`A`jyq<|q=&F_ zPEOotTu9?zGKaPJ#9P&ljgW!|Vxhe+l85%G5zpD5kAtn*ZC})qEy!v`_R}EcOn)&# z-+B52@Zle@$!^-N@<_=LKF}fqQkwf1rE(OQP&8!En}jqr-l0A0K>77K8{zT%wVpT~ zMgDx}RUG$jgaeqv*E~<#RT?Q)(RGi8bUm(1X?2OAG2!LbBR+u1r7$}s=lKqu&VjXP zUw3L9DH({yj)M%OqP%GC+$}o0iG|*hN-Ecv3bxS|Mxpmz*%x`w7~=o9BKfEVzr~K- zo&Fh`wZ{#1Jd5QFM4&!PabL!tf%TfJ4wi;45AqWe$x}8*c2cgqua`(6@ErE&P{K5M zQfwGQ4Qg&M3r4^^$B?_AdLzqtxn5nb#kItDY?BTW z#hShspeIDJ1FDmfq@dz1TT`OV;SS0ImUp`P6GzOqB3dPfzf?+w^40!Wn*4s!E;iHW zNzpDG+Vmtnh%CyfAX>X z{Y=vt;yb z;TBRZpw##Kh$l<8qq5|3LkrwX%MoxqWwclBS6|7LDM(I31>$_w=;{=HcyWlak3xM1 z_oaOa)a;AtV{*xSj6v|x%a42{h@X-cr%#HO5hWbuKRGTZS)o=^Id^>H5}0p_(BEXX zx3VnRUj6&1JjDI);c=#EYcsg;D5TFlhe)=nAycR1N)YSHQvO+P5hKe9T0ggZT{oF@ z#i3V4TpQlO1A8*TWn|e}UWZ(OU;Isd^ zb<#Vj`~W_-S_=lDR#223!xq8sRjAAVSY2MhRyUyHa-{ql=zyMz?~i_c&dS>eb>s>#q#$UI+!&6MftpQvxHA@f|k2(G9z zAQCx-lJ-AT;PnX%dY5}N$m6tFt5h6;Mf78TmFUN9#4*qBNg4it3-s22P+|Rw zG@X%R0sm*X07ZZEOJRbDkcjr}tvaVWlrwJ#7KYEw&X`2lDa@qb!0*SHa%+-FU!83q zY{R15$vfL56^Nj42#vGQlQ%coT4bLr2s5Y0zBFp8u&F(+*%k4xE1{s75Q?P(SL7kf zhG?3rfM9V*b?>dOpwr%uGH7Xfk1HZ!*k`@CNM77g_mGN=ucMG&QX19B!%y77w?g#b z%k3x6q_w_%ghL;9Zk_J#V{hxK%6j`?-`UN?^e%(L6R#t#97kZaOr1{&<8VGVs1O>} z6~!myW`ja01v%qy%WI=8WI!cf#YA8KNRoU>`_muCqpt_;F@rkVeDY}F7puI_wBPH9 zgRGre(X_z4PUO5!VDSyg)bea1x_a7M z4AJ?dd9rf{*P`AY+w?g_TyJlB5Nks~1$@PxdtpUGGG##7j<$g&BhKq0mXTva{;h5E ztcN!O17bquKEDC#;Yw2yE>*=|WdZT9+ycgUR^f?~+TY-E552AZlzYn{-2CLRV9mn8 z+zNoWLae^P{co`F?)r;f!C=nnl*1+DI)mZY!frp~f%6tX2g=?zQL^d-j^t1~+xYgK zv;np&js@X=_e7F&&ZUX|N6Q2P0L=fWoBuh*L7$3~$-A)sdy6EQ@Pd-)|7lDA@%ra2 z4jL@^w92&KC>H(=v2j!tVE_3w0KogtrNjgPBsTvW F{TFmrHLU;u delta 8469 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 of veins public class ChunkAnalysis { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index 61fbe552..4d5224a8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -1,6 +1,11 @@ package com.sinthoras.visualprospecting.database.cachebuilder; -import java.util.*; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.stream.IntStream; import com.sinthoras.visualprospecting.Utils; @@ -10,7 +15,9 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; -import io.xol.enklume.nbt.*; +import io.xol.enklume.nbt.NBTCompound; +import io.xol.enklume.nbt.NBTList; +import io.xol.enklume.nbt.NBTNamed; // Slower, but more sophisticated approach to identify overlapping veins public class DetailedChunkAnalysis { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index ca84fb21..072d6fc6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -3,7 +3,13 @@ import static com.sinthoras.visualprospecting.Utils.*; import java.io.File; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.regex.Pattern; import net.minecraft.client.resources.I18n; diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java index ef9d5b3d..e8af5e23 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java @@ -11,7 +11,6 @@ import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; import cpw.mods.fml.client.registry.ClientRegistry; -import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.InputEvent; import cpw.mods.fml.relauncher.Side; @@ -33,7 +32,6 @@ public class HooksKey { "visualprospecting.key.action.category"); public HooksKey() { - FMLCommonHandler.instance().bus().register(this); ClientRegistry.registerKeyBinding(keyToggleOres); ClientRegistry.registerKeyBinding(keyToggleFluids); if (isTCNodeTrackerInstalled()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java index c4f37cd4..7cc47477 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java @@ -6,8 +6,17 @@ import java.util.List; import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.*; -import com.sinthoras.visualprospecting.integration.journeymap.render.*; +import com.sinthoras.visualprospecting.integration.journeymap.buttons.DirtyChunkButton; +import com.sinthoras.visualprospecting.integration.journeymap.buttons.LayerButton; +import com.sinthoras.visualprospecting.integration.journeymap.buttons.OreVeinButton; +import com.sinthoras.visualprospecting.integration.journeymap.buttons.ThaumcraftNodeButton; +import com.sinthoras.visualprospecting.integration.journeymap.buttons.UndergroundFluidButton; +import com.sinthoras.visualprospecting.integration.journeymap.render.DirtyChunkRenderer; +import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; +import com.sinthoras.visualprospecting.integration.journeymap.render.OreVeinRenderer; +import com.sinthoras.visualprospecting.integration.journeymap.render.ThaumcraftNodeRenderer; +import com.sinthoras.visualprospecting.integration.journeymap.render.UndergroundFluidChunkRenderer; +import com.sinthoras.visualprospecting.integration.journeymap.render.UndergroundFluidRenderer; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.OreVeinWaypointManager; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.ThaumcraftNodeWaypointManager; import com.sinthoras.visualprospecting.integration.journeymap.waypoints.WaypointManager; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java index 14a9e0e0..4e179a9f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java @@ -1,7 +1,7 @@ package com.sinthoras.visualprospecting.integration.journeymap.buttons; import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.buttons.*; +import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; import journeymap.client.ui.theme.ThemeToggle; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java index ffcd02a5..74883e64 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java @@ -1,6 +1,6 @@ package com.sinthoras.visualprospecting.integration.journeymap.waypoints; -import java.awt.*; +import java.awt.Color; import com.sinthoras.visualprospecting.integration.model.SupportedMods; import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java index 93e4c1ef..dd46261e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java @@ -6,8 +6,17 @@ import java.util.List; import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.integration.model.buttons.*; -import com.sinthoras.visualprospecting.integration.model.layers.*; +import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; +import com.sinthoras.visualprospecting.integration.model.buttons.DirtyChunkButtonManager; +import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; +import com.sinthoras.visualprospecting.integration.model.buttons.ThaumcraftNodeButtonManager; +import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; +import com.sinthoras.visualprospecting.integration.model.layers.DirtyChunkLayerManager; +import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; +import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; +import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; +import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidChunkLayerManager; +import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.tcnodetracker.NTNodeTrackerWaypointManager; import com.sinthoras.visualprospecting.integration.xaerominimap.XaeroMiniMapState; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java index 4cbf84b9..f21f27bd 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java @@ -9,7 +9,11 @@ import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.OreVeinButton; import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.ThaumcraftNodeButton; import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.UndergroundFluidButton; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.*; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.OreVeinRenderer; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.ThaumcraftNodeRenderer; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.UndergroundFluidChunkRenderer; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.UndergroundFluidRenderer; public class XaeroWorldMapState { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java index e9d0e753..527b168e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java @@ -1,6 +1,10 @@ package com.sinthoras.visualprospecting.mixinplugin; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader; diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java index e7641a2f..f27e6ba3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java @@ -24,7 +24,6 @@ import gregtech.api.enums.ItemList; import gregtech.api.enums.Materials; -import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine; import gregtech.api.util.GT_Utility; @@ -41,7 +40,7 @@ public abstract class GT_MetaTileEntity_AdvSeismicProspectorMixin extends GT_Met int radius; public GT_MetaTileEntity_AdvSeismicProspectorMixin() { - super(0, "", "", 0, 0, "", 0, 0, "", "", (ITexture[]) null); + super(0, "", "", 0, 0, "", 0, 0); } /** diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java index 1ef3fb8d..124fe393 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java @@ -19,7 +19,6 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; -import gregtech.api.interfaces.ITexture; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine; import gregtech.api.util.GT_Utility; import gregtech.common.tileentities.machines.basic.GT_MetaTileEntity_Scanner; @@ -28,7 +27,7 @@ public abstract class GT_MetaTileEntity_ScannerMixin extends GT_MetaTileEntity_BasicMachine { public GT_MetaTileEntity_ScannerMixin() { - super(0, "", "", 0, 0, "", 0, 0, "", "", (ITexture[]) null); + super(0, "", "", 0, 0, "", 0, 0); } @Inject( diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java index 5c894f54..a1df4df8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java @@ -3,7 +3,9 @@ import static com.sinthoras.visualprospecting.Utils.isSmallOreId; import static com.sinthoras.visualprospecting.Utils.oreIdToMaterialId; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import net.minecraft.block.Block; import net.minecraft.tileentity.TileEntity; From a4e4e3dde1da49adf402c4505bf62ab656880d1f Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sat, 23 Sep 2023 17:11:20 +0200 Subject: [PATCH 035/132] update bs+deps --- build.gradle | 15 +++------------ dependencies.gradle | 4 ++-- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 7ff83a31..6a54d13b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1695409603 +//version: 1695474595 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -793,23 +793,14 @@ ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies" } dependencies { - def lwjgl3ifyVersion = '1.4.0' - def asmVersion = '9.4' + def lwjgl3ifyVersion = '1.5.0' if (modId != 'lwjgl3ify') { java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") } if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.26') + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.5') } - java17PatchDependencies('net.minecraft:launchwrapper:1.17.2') {transitive = false} - java17PatchDependencies("org.ow2.asm:asm:${asmVersion}") - java17PatchDependencies("org.ow2.asm:asm-commons:${asmVersion}") - java17PatchDependencies("org.ow2.asm:asm-tree:${asmVersion}") - java17PatchDependencies("org.ow2.asm:asm-analysis:${asmVersion}") - java17PatchDependencies("org.ow2.asm:asm-util:${asmVersion}") - java17PatchDependencies('org.ow2.asm:asm-deprecated:7.1') - java17PatchDependencies("org.apache.commons:commons-lang3:3.12.0") java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} } diff --git a/dependencies.gradle b/dependencies.gradle index 9f3548ca..364d94c2 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,13 +1,13 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.22:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.23:dev') api('curse.maven:journeymap-32274:4500659') devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.1.7:dev') compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.10:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.8.5:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.8.6:dev') {transitive = false} compileOnly(deobf('https://media.forgecdn.net/files/4127/308/Xaeros_Minimap_21.10.30_Forge_1.7.10.jar')) compileOnly(deobf('https://media.forgecdn.net/files/4127/328/XaerosWorldMap_1.14.1.22_Forge_1.7.10.jar')) From 0495d84ee829714cdbc8fa4b72af56f4e1c1b446 Mon Sep 17 00:00:00 2001 From: Rune580 <12521934+Rune580@users.noreply.github.com> Date: Sun, 3 Dec 2023 05:17:40 -0500 Subject: [PATCH 036/132] Networking Refactor (#40) * OreVeinPosition now has constant size for serializing, abstracted serialization/deserialization logic to utility class. * spotlessApply * assign instead of addAll to fix NullPointerException --- .../database/OreVeinPosition.java | 6 +- .../database/TransferCache.java | 10 +- .../network/ProspectingNotification.java | 55 +---------- .../network/ProspectionSharing.java | 65 ++---------- .../utils/VPByteBufUtils.java | 99 +++++++++++++++++++ 5 files changed, 117 insertions(+), 118 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java diff --git a/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java b/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java index f2ecd2a6..bb9de4c4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java @@ -2,11 +2,10 @@ import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.veintypes.VeinType; -import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; public class OreVeinPosition { - private static final int MAX_BYTES = 3 * Integer.BYTES + Byte.BYTES; + public static final int MAX_BYTES = 3 * Integer.BYTES + Short.BYTES; public final int dimensionId; public final int chunkX; @@ -51,7 +50,8 @@ public OreVeinPosition joinDepletedState(final OreVeinPosition other) { return this; } + // Leaving this here for compatability sake public static int getMaxBytes() { - return MAX_BYTES + VeinTypeCaching.getLongesOreNameLength(); + return MAX_BYTES; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java b/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java index 9af0edce..0845907f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java @@ -23,10 +23,7 @@ public void addClientProspectionData(String uuid, List oreVeins sharedUndergroundFluids.remove(uuid); timestamp.remove(uuid); - final int oreVeinPositionSizeInRam = OreVeinPosition.getMaxBytes() + 3 * Byte.BYTES; // JVM represents - // everything aligned at 4 - // bytes - final int newEntryBytes = oreVeins.size() * oreVeinPositionSizeInRam + final int newEntryBytes = oreVeins.size() * OreVeinPosition.MAX_BYTES + undergroundFluids.size() * UndergroundFluidPosition.BYTES; while (getUsedMemory() > (Config.maxTransferCacheSizeMB << 20) - newEntryBytes @@ -54,10 +51,7 @@ public List getSharedUndergroundFluidsFrom(String uuid } private int getUsedMemory() { - final int oreVeinPositionSizeInRam = OreVeinPosition.getMaxBytes() + 3 * Byte.BYTES; // JVM represents - // everything aligned at 4 - // bytes - return sharedOreVeins.values().stream().mapToInt(oreVeins -> oreVeins.size() * oreVeinPositionSizeInRam).sum() + return sharedOreVeins.values().stream().mapToInt(oreVeins -> oreVeins.size() * OreVeinPosition.MAX_BYTES).sum() + sharedUndergroundFluids.values().stream() .mapToInt(undergroundFluids -> undergroundFluids.size() * UndergroundFluidPosition.BYTES).sum(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java index 0ea5bb98..99d41747 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java @@ -4,16 +4,11 @@ import java.util.Collections; import java.util.List; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidRegistry; - -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; -import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import com.sinthoras.visualprospecting.utils.VPByteBufUtils; -import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; @@ -40,54 +35,14 @@ public ProspectingNotification(List oreVeins, List(numberOfOreVeins); - for (int i = 0; i < numberOfOreVeins; i++) { - final int dimensionId = buf.readInt(); - final int chunkX = buf.readInt(); - final int chunkZ = buf.readInt(); - final String oreVeinName = ByteBufUtils.readUTF8String(buf); - oreVeins.add(new OreVeinPosition(dimensionId, chunkX, chunkZ, VeinTypeCaching.getVeinType(oreVeinName))); - } - - final int numberOfUndergroundFluids = buf.readInt(); - undergroundFluids = new ArrayList<>(numberOfUndergroundFluids); - for (int i = 0; i < numberOfUndergroundFluids; i++) { - final int dimensionId = buf.readInt(); - final int chunkX = buf.readInt(); - final int chunkZ = buf.readInt(); - final Fluid fluid = FluidRegistry.getFluid(buf.readInt()); - final int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; - for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) - for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - chunks[offsetChunkX][offsetChunkZ] = buf.readInt(); - } - undergroundFluids.add(new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); - } + oreVeins = VPByteBufUtils.ReadOreVeinPositions(buf); + undergroundFluids = VPByteBufUtils.ReadUndergroundFluidPositions(buf); } @Override public void toBytes(ByteBuf buf) { - buf.writeInt(oreVeins.size()); - for (OreVeinPosition oreVein : oreVeins) { - buf.writeInt(oreVein.dimensionId); - buf.writeInt(oreVein.chunkX); - buf.writeInt(oreVein.chunkZ); - ByteBufUtils.writeUTF8String(buf, oreVein.veinType.name); - } - - buf.writeInt(undergroundFluids.size()); - for (UndergroundFluidPosition undergroundFluid : undergroundFluids) { - buf.writeInt(undergroundFluid.dimensionId); - buf.writeInt(undergroundFluid.chunkX); - buf.writeInt(undergroundFluid.chunkZ); - buf.writeInt(undergroundFluid.fluid.getID()); - for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { - for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - buf.writeInt(undergroundFluid.chunks[offsetChunkX][offsetChunkZ]); - } - } - } + VPByteBufUtils.WriteOreVeinPositions(buf, oreVeins); + VPByteBufUtils.WriteUndergroundFluidPositions(buf, undergroundFluids); } public static class Handler implements IMessageHandler { diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java index bb2b17e7..9ad1611c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java @@ -6,17 +6,14 @@ import java.util.Map; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidRegistry; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.TransferCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; -import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import com.sinthoras.visualprospecting.utils.VPByteBufUtils; -import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; @@ -36,10 +33,10 @@ public ProspectionSharing() {} public int putOreVeins(List oreVeins) { final int availableBytes = VP.uploadSizePerPacketInBytes - bytesUsed; - final int maxAddedOreVeins = availableBytes / OreVeinPosition.getMaxBytes(); + final int maxAddedOreVeins = availableBytes / OreVeinPosition.MAX_BYTES; final int addedOreVeins = Math.min(oreVeins.size(), maxAddedOreVeins); this.oreVeins.addAll(oreVeins.subList(0, addedOreVeins)); - bytesUsed += addedOreVeins * OreVeinPosition.getMaxBytes(); + bytesUsed += addedOreVeins * OreVeinPosition.MAX_BYTES; return addedOreVeins; } @@ -61,7 +58,7 @@ public void setLastMessage(boolean isLastMessage) { } public int getBytes() { - return BYTES_OVERHEAD + VeinTypeCaching.getLongesOreNameLength() * oreVeins.size() + return BYTES_OVERHEAD + OreVeinPosition.MAX_BYTES * oreVeins.size() + UndergroundFluidPosition.BYTES * undergroundFluids.size(); } @@ -70,35 +67,8 @@ public void fromBytes(ByteBuf buf) { isFirstMessage = buf.readByte() > 0; isLastMessage = buf.readByte() > 0; - final int numberOfOreVeins = buf.readInt(); - for (int i = 0; i < numberOfOreVeins; i++) { - final int dimensionId = buf.readInt(); - final int chunkX = buf.readInt(); - final int chunkZ = buf.readInt(); - final boolean isDepleted = buf.readByte() > 0; - final String oreVeinName = ByteBufUtils.readUTF8String(buf); - oreVeins.add( - new OreVeinPosition( - dimensionId, - chunkX, - chunkZ, - VeinTypeCaching.getVeinType(oreVeinName), - isDepleted)); - } - - final int numberOfUndergroundFluids = buf.readInt(); - for (int i = 0; i < numberOfUndergroundFluids; i++) { - final int dimensionId = buf.readInt(); - final int chunkX = buf.readInt(); - final int chunkZ = buf.readInt(); - final Fluid fluid = FluidRegistry.getFluid(buf.readInt()); - final int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; - for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) - for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - chunks[offsetChunkX][offsetChunkZ] = buf.readInt(); - } - undergroundFluids.add(new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); - } + oreVeins.addAll(VPByteBufUtils.ReadOreVeinPositions(buf)); + undergroundFluids.addAll(VPByteBufUtils.ReadUndergroundFluidPositions(buf)); } @Override @@ -106,27 +76,8 @@ public void toBytes(ByteBuf buf) { buf.writeByte(isFirstMessage ? 1 : 0); buf.writeByte(isLastMessage ? 1 : 0); - buf.writeInt(oreVeins.size()); - for (OreVeinPosition oreVein : oreVeins) { - buf.writeInt(oreVein.dimensionId); - buf.writeInt(oreVein.chunkX); - buf.writeInt(oreVein.chunkZ); - buf.writeByte(oreVein.isDepleted() ? 1 : 0); - ByteBufUtils.writeUTF8String(buf, oreVein.veinType.name); - } - - buf.writeInt(undergroundFluids.size()); - for (UndergroundFluidPosition undergroundFluid : undergroundFluids) { - buf.writeInt(undergroundFluid.dimensionId); - buf.writeInt(undergroundFluid.chunkX); - buf.writeInt(undergroundFluid.chunkZ); - buf.writeInt(undergroundFluid.fluid.getID()); - for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { - for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - buf.writeInt(undergroundFluid.chunks[offsetChunkX][offsetChunkZ]); - } - } - } + VPByteBufUtils.WriteOreVeinPositions(buf, oreVeins); + VPByteBufUtils.WriteUndergroundFluidPositions(buf, undergroundFluids); } public static class ServerHandler implements IMessageHandler { diff --git a/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java b/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java new file mode 100644 index 00000000..8137b062 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java @@ -0,0 +1,99 @@ +package com.sinthoras.visualprospecting.utils; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; + +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; +import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; + +import io.netty.buffer.ByteBuf; + +public final class VPByteBufUtils { + + public static void WriteOreVeinPosition(ByteBuf buf, OreVeinPosition oreVeinPosition) { + buf.writeInt(oreVeinPosition.dimensionId); + buf.writeInt(oreVeinPosition.chunkX); + buf.writeInt(oreVeinPosition.chunkZ); + buf.writeShort(oreVeinPosition.veinType.veinId); + buf.writeBoolean(oreVeinPosition.isDepleted()); + } + + public static OreVeinPosition ReadOreVeinPosition(ByteBuf buf) { + final int dimId = buf.readInt(); + final int chunkX = buf.readInt(); + final int chunkZ = buf.readInt(); + final short veinId = buf.readShort(); + final boolean isDepleted = buf.readBoolean(); + + return new OreVeinPosition(dimId, chunkX, chunkZ, VeinTypeCaching.getVeinType(veinId), isDepleted); + } + + public static void WriteUndergroundFluidPosition(ByteBuf buf, UndergroundFluidPosition undergroundFluidPosition) { + buf.writeInt(undergroundFluidPosition.dimensionId); + buf.writeInt(undergroundFluidPosition.chunkX); + buf.writeInt(undergroundFluidPosition.chunkZ); + buf.writeInt(undergroundFluidPosition.fluid.getID()); + for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { + for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { + buf.writeInt(undergroundFluidPosition.chunks[offsetChunkX][offsetChunkZ]); + } + } + } + + public static UndergroundFluidPosition ReadUndergroundFluidPosition(ByteBuf buf) { + final int dimId = buf.readInt(); + final int chunkX = buf.readInt(); + final int chunkZ = buf.readInt(); + final Fluid fluid = FluidRegistry.getFluid(buf.readInt()); + final int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; + for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { + for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { + chunks[offsetChunkX][offsetChunkZ] = buf.readInt(); + } + } + + return new UndergroundFluidPosition(dimId, chunkX, chunkZ, fluid, chunks); + } + + public static void WriteOreVeinPositions(ByteBuf buf, List oreVeinPositions) { + buf.writeInt(oreVeinPositions.size()); + for (OreVeinPosition oreVeinPosition : oreVeinPositions) { + WriteOreVeinPosition(buf, oreVeinPosition); + } + } + + public static List ReadOreVeinPositions(ByteBuf buf) { + List oreVeinPositions = new ArrayList<>(); + + final int oreVeinCount = buf.readInt(); + for (int i = 0; i < oreVeinCount; i++) { + oreVeinPositions.add(ReadOreVeinPosition(buf)); + } + + return oreVeinPositions; + } + + public static void WriteUndergroundFluidPositions(ByteBuf buf, + List undergroundFluidPositions) { + buf.writeInt(undergroundFluidPositions.size()); + for (UndergroundFluidPosition undergroundFluidPosition : undergroundFluidPositions) { + WriteUndergroundFluidPosition(buf, undergroundFluidPosition); + } + } + + public static List ReadUndergroundFluidPositions(ByteBuf buf) { + List undergroundFluidPositions = new ArrayList<>(); + + final int undergroundFluidCount = buf.readInt(); + for (int i = 0; i < undergroundFluidCount; i++) { + undergroundFluidPositions.add(ReadUndergroundFluidPosition(buf)); + } + + return undergroundFluidPositions; + } +} From 10d0735fcc68cef1236565de01657e7726473986 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sun, 3 Dec 2023 12:57:34 +0100 Subject: [PATCH 037/132] update gradle+bs+deps --- build.gradle | 30 ++++++----------------- dependencies.gradle | 4 +-- gradle/wrapper/gradle-wrapper.jar | Bin 62076 -> 63375 bytes gradle/wrapper/gradle-wrapper.properties | 3 ++- gradlew | 5 +++- 5 files changed, 15 insertions(+), 27 deletions(-) diff --git a/build.gradle b/build.gradle index 6a54d13b..8507c7df 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1695474595 +//version: 1701530445 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -28,27 +28,12 @@ import java.util.concurrent.TimeUnit buildscript { repositories { - mavenCentral() - - maven { - name 'forge' - url 'https://maven.minecraftforge.net' - } maven { // GTNH RetroFuturaGradle and ASM Fork name "GTNH Maven" url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" allowInsecureProtocol = true } - maven { - name 'sonatype' - url 'https://oss.sonatype.org/content/repositories/snapshots/' - } - maven { - name 'Scala CI dependencies' - url 'https://repo1.maven.org/maven2/' - } - mavenLocal() } } @@ -302,7 +287,7 @@ if (apiPackage) { } if (accessTransformersFile) { - for (atFile in accessTransformersFile.split(",")) { + for (atFile in accessTransformersFile.split(" ")) { String targetFile = "src/main/resources/META-INF/" + atFile.trim() if (!getFile(targetFile).exists()) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) @@ -646,7 +631,7 @@ repositories { def mixinProviderGroup = "io.github.legacymoddingmc" def mixinProviderModule = "unimixins" -def mixinProviderVersion = "0.1.7.1" +def mixinProviderVersion = "0.1.13" def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}" def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev" ext.mixinProviderSpec = mixinProviderSpec @@ -793,12 +778,12 @@ ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies" } dependencies { - def lwjgl3ifyVersion = '1.5.0' + def lwjgl3ifyVersion = '1.5.7' if (modId != 'lwjgl3ify') { java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") } if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.5') + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.35') } java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} @@ -1187,9 +1172,8 @@ publishing { version = System.getenv("RELEASE_VERSION") ?: identifiedVersion } } - repositories { - if (usesMavenPublishing.toBoolean()) { + if (usesMavenPublishing.toBoolean() && System.getenv("MAVEN_USER") != null) { maven { url = mavenPublishUrl allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven @@ -1311,7 +1295,7 @@ def addCurseForgeRelation(String type, String name) { // Updating -def buildscriptGradleVersion = "8.2.1" +def buildscriptGradleVersion = "8.5" tasks.named('wrapper', Wrapper).configure { gradleVersion = buildscriptGradleVersion diff --git a/dependencies.gradle b/dependencies.gradle index 364d94c2..a9b92365 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,13 +1,13 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.23:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.91:dev') api('curse.maven:journeymap-32274:4500659') devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.1.7:dev') compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.10:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.8.6:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.8.16:dev') {transitive = false} compileOnly(deobf('https://media.forgecdn.net/files/4127/308/Xaeros_Minimap_21.10.30_Forge_1.7.10.jar')) compileOnly(deobf('https://media.forgecdn.net/files/4127/328/XaerosWorldMap_1.14.1.22_Forge_1.7.10.jar')) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index c1962a79e29d3e0ab67b14947c167a862655af9b..033e24c4cdf41af1ab109bc7f253b2b887023340 100644 GIT binary patch delta 16170 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 delta 14892 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 17a8ddce..1af9e093 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index aeb74cbb..fcb6fca1 100755 --- a/gradlew +++ b/gradlew @@ -130,10 +130,13 @@ 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. + 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. From 69a9c8529baa8962740b18ee7b3ae1602050000d Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Mon, 8 Jan 2024 21:30:23 +0000 Subject: [PATCH 038/132] [ci skip] upgraded build system --- build.gradle | 37 ++++++++++++++---------------- gradle/wrapper/gradle-wrapper.jar | Bin 63375 -> 43462 bytes gradlew | 17 +++++++------- settings.gradle | 9 ++++---- 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/build.gradle b/build.gradle index 8507c7df..952a3c59 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1701530445 +//version: 1704650211 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -31,8 +31,7 @@ buildscript { maven { // GTNH RetroFuturaGradle and ASM Fork name "GTNH Maven" - url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - allowInsecureProtocol = true + url "https://nexus.gtnewhorizons.com/repository/public/" } mavenLocal() } @@ -49,12 +48,12 @@ plugins { id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle id 'com.github.johnrengelman.shadow' version '8.1.1' apply false id 'com.palantir.git-version' version '3.0.0' apply false - id 'de.undercouch.download' version '5.4.0' + id 'de.undercouch.download' version '5.5.0' id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.24' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.27' } print("You might want to check out './gradlew :faq' if your build fails.\n") @@ -118,7 +117,7 @@ propertyDefaultIfUnset("forceEnableMixins", false) propertyDefaultIfUnset("channel", "stable") propertyDefaultIfUnset("mappingsVersion", "12") propertyDefaultIfUnset("usesMavenPublishing", true) -propertyDefaultIfUnset("mavenPublishUrl", "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases") +propertyDefaultIfUnset("mavenPublishUrl", "https://nexus.gtnewhorizons.com/repository/releases/") propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") @@ -573,13 +572,15 @@ afterEvaluate { repositories { maven { - name 'Overmind forge repo mirror' - url 'https://gregtech.overminddl1.com/' + name = "GTNH Maven" + url = "https://nexus.gtnewhorizons.com/repository/public/" + // Links for convenience: + // Simple HTML browsing: https://nexus.gtnewhorizons.com/service/rest/repository/browse/releases/ + // Rich web UI browsing: https://nexus.gtnewhorizons.com/#browse/browse:releases } maven { - name = "GTNH Maven" - url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - allowInsecureProtocol = true + name 'Overmind forge repo mirror' + url 'https://gregtech.overminddl1.com/' } maven { name 'sonatype' @@ -613,7 +614,7 @@ repositories { } maven { name = "ic2" - url = getURL("https://maven.ic2.player.to/", "https://maven2.ic2.player.to/") + url = getURL("https://maven2.ic2.player.to/", "https://maven.ic2.player.to/") content { includeGroup "net.industrial-craft" } @@ -672,6 +673,8 @@ configurations.all { substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier") + + substitute module('org.scala-lang:scala-library:2.11.1') using module('org.scala-lang:scala-library:2.11.5') because('To allow mixing with Java 8 targets') } } @@ -958,8 +961,7 @@ if (usesShadowedDependencies.toBoolean()) { configurations.runtimeElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) configurations.apiElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) tasks.named("jar", Jar) { - enabled = false - finalizedBy(tasks.shadowJar) + archiveClassifier.set('dev-preshadow') } tasks.named("reobfJar", ReobfuscatedJar) { inputJar.set(tasks.named("shadowJar", ShadowJar).flatMap({it.archiveFile})) @@ -968,11 +970,6 @@ if (usesShadowedDependencies.toBoolean()) { javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { skip() } - for (runTask in ["runClient", "runServer", "runClient17", "runServer17"]) { - tasks.named(runTask).configure { - dependsOn("shadowJar") - } - } } ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar ext.publishableObfJar = tasks.reobfJar @@ -1176,7 +1173,7 @@ publishing { if (usesMavenPublishing.toBoolean() && System.getenv("MAVEN_USER") != null) { maven { url = mavenPublishUrl - allowInsecureProtocol = mavenPublishUrl.startsWith("http://") // Mostly for the GTNH maven + allowInsecureProtocol = mavenPublishUrl.startsWith("http://") credentials { username = System.getenv("MAVEN_USER") ?: "NONE" password = System.getenv("MAVEN_PASSWORD") ?: "NONE" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 033e24c4cdf41af1ab109bc7f253b2b887023340..d64cd4917707c1f8861d8cb53dd15194d4248596 100644 GIT binary patch literal 43462 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 literal 63375 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≫L+crb^Bz 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 /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -144,7 +145,7 @@ 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=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -201,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# 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" \ diff --git a/settings.gradle b/settings.gradle index 01ea5f12..8a66026e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,10 +4,9 @@ pluginManagement { maven { // RetroFuturaGradle name "GTNH Maven" - url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/" - allowInsecureProtocol = true + url "https://nexus.gtnewhorizons.com/repository/public/" mavenContent { - includeGroup("com.gtnewhorizons.retrofuturagradle") + includeGroupByRegex("com\\.gtnewhorizons\\..+") } } gradlePluginPortal() @@ -17,8 +16,8 @@ pluginManagement { } plugins { - id 'com.diffplug.blowdryerSetup' version '1.6.0' - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' // Provides java toolchains + id 'com.diffplug.blowdryerSetup' version '1.7.1' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' // Provides java toolchains } blowdryerSetup { From 660eb11c47e121c6d982ed982cfba729196a796b Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Tue, 9 Jan 2024 23:51:24 +0100 Subject: [PATCH 039/132] update bs+deps --- build.gradle | 4 ++-- dependencies.gradle | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 952a3c59..3eb19a26 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1704650211 +//version: 1704751096 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -786,7 +786,7 @@ dependencies { java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") } if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.3.35') + java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.4.4') } java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} diff --git a/dependencies.gradle b/dependencies.gradle index a9b92365..31dc2590 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,13 +1,13 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.44.91:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.23:dev') api('curse.maven:journeymap-32274:4500659') devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.1.7:dev') - compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.0.10:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.8.16:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.1.0:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.9.2:dev') {transitive = false} compileOnly(deobf('https://media.forgecdn.net/files/4127/308/Xaeros_Minimap_21.10.30_Forge_1.7.10.jar')) compileOnly(deobf('https://media.forgecdn.net/files/4127/328/XaerosWorldMap_1.14.1.22_Forge_1.7.10.jar')) From db32318779e31f05e10130012bba74e2686ea4b2 Mon Sep 17 00:00:00 2001 From: Caedis Date: Sat, 20 Jan 2024 16:44:58 -0600 Subject: [PATCH 040/132] Reposition VP buttons on Xaero's Worldmap (#41) * Update bs + deps * Use deobf names; change xaero map button placement * fix position * fix deps * revert inject values --- dependencies.gradle | 5 +++-- .../mixins/late/xaerosworldmap/GuiMapMixin.java | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 31dc2590..895f7852 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -9,10 +9,11 @@ dependencies { compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.1.0:dev') {transitive = false} compileOnly('com.github.GTNewHorizons:bartworks:0.9.2:dev') {transitive = false} - compileOnly(deobf('https://media.forgecdn.net/files/4127/308/Xaeros_Minimap_21.10.30_Forge_1.7.10.jar')) - compileOnly(deobf('https://media.forgecdn.net/files/4127/328/XaerosWorldMap_1.14.1.22_Forge_1.7.10.jar')) + compileOnly(deobfCurse('xaeros-minimap-263420:4905582')) + compileOnly(deobfCurse('xaeros-world-map-317780:4905612')) compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) // For debugging runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.7.2:dev') + runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.9:dev') } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java index a3b3bc94..bda178cd 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java @@ -156,11 +156,13 @@ protected GuiMapMixin(GuiScreen parent, GuiScreen escape) { method = "func_73866_w_", at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Keyboard;enableRepeatEvents(Z)V")) private void visualprospecting$injectInitButtons(CallbackInfo ci) { - for (int i = 0; i < XaeroWorldMapState.instance.buttons.size(); i++) { + int numBtns = XaeroWorldMapState.instance.buttons.size(); + int totalHeight = numBtns * 20; + for (int i = 0; i < numBtns; i++) { LayerButton layerButton = XaeroWorldMapState.instance.buttons.get(i); SizedGuiTexturedButton button = new SizedGuiTexturedButton( 0, - height - 20 * (i + 1), + (height / 2 + totalHeight / 2) - 20 - 20 * i, layerButton.textureLocation, (btn) -> layerButton.toggle(), new CursorBox(layerButton.getButtonTextKey())); From 0ef6b49a6763f97f9b9384b75e04325e66e9cb7f Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sun, 21 Jan 2024 00:08:00 +0100 Subject: [PATCH 041/132] update bs+deps --- build.gradle | 27 +++++++++++++++++++++++---- dependencies.gradle | 10 +++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index 3eb19a26..6274cb25 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1704751096 +//version: 1705357285 /* DO NOT CHANGE THIS FILE! Also, you may replace this file at any time if there is an update available. @@ -122,6 +122,7 @@ propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthRelations", "") propertyDefaultIfUnset("curseForgeProjectId", "") propertyDefaultIfUnset("curseForgeRelations", "") +propertyDefaultIfUnset("versionPattern", "") propertyDefaultIfUnset("minimizeShadowedDependencies", true) propertyDefaultIfUnset("relocateShadowedDependencies", true) // Deprecated properties (kept for backwards compat) @@ -370,6 +371,7 @@ catch (Exception ignored) { // Pulls version first from the VERSION env and then git tag String identifiedVersion String versionOverride = System.getenv("VERSION") ?: null +boolean checkVersion = false try { // Produce a version based on the tag, or for branches something like 0.2.2-configurable-maven-and-extras.38+43090270b6-dirty if (versionOverride == null) { @@ -388,6 +390,8 @@ try { } } else if (isDirty) { identifiedVersion += "-${branchName}+${gitDetails.gitHash}-dirty" + } else { + checkVersion = true } } else { identifiedVersion = versionOverride @@ -409,6 +413,8 @@ ext { if (identifiedVersion == versionOverride) { out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7') +} else if (checkVersion && versionPattern && !(identifiedVersion ==~ versionPattern)) { + throw new GradleException("Invalid version: '$identifiedVersion' does not match version pattern '$versionPattern'") } group = "com.github.GTNewHorizons" @@ -428,18 +434,31 @@ minecraft { for (f in replaceGradleTokenInFile.split(',')) { tagReplacementFiles.add f } + out.style(Style.Info).text('replaceGradleTokenInFile is deprecated! Consider using generateGradleTokenClass.').println() } if (gradleTokenModId) { - injectedTags.put gradleTokenModId, modId + if (replaceGradleTokenInFile) { + injectedTags.put gradleTokenModId, modId + } else { + out.style(Style.Failure).text('gradleTokenModId is deprecated! The field will no longer be generated.').println() + } } if (gradleTokenModName) { - injectedTags.put gradleTokenModName, modName + if (replaceGradleTokenInFile) { + injectedTags.put gradleTokenModName, modName + } else { + out.style(Style.Failure).text('gradleTokenModName is deprecated! The field will no longer be generated.').println() + } } if (gradleTokenVersion) { injectedTags.put gradleTokenVersion, modVersion } if (gradleTokenGroupName) { - injectedTags.put gradleTokenGroupName, modGroup + if (replaceGradleTokenInFile) { + injectedTags.put gradleTokenGroupName, modGroup + } else { + out.style(Style.Failure).text('gradleTokenGroupName is deprecated! The field will no longer be generated.').println() + } } if (enableGenericInjection.toBoolean()) { injectMissingGenerics.set(true) diff --git a/dependencies.gradle b/dependencies.gradle index 895f7852..adaa9dba 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,19 +1,19 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.23:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.41:dev') api('curse.maven:journeymap-32274:4500659') - devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.1.7:dev') + devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.2.0:dev') compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.1.0:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.9.2:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.9.4:dev') {transitive = false} compileOnly(deobfCurse('xaeros-minimap-263420:4905582')) compileOnly(deobfCurse('xaeros-world-map-317780:4905612')) compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) // For debugging - runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.7.2:dev') - runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.9:dev') + runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.8.0:dev') + runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.11:dev') } From 6aac3678de8c372ac0eca5dc0255226c5a060da0 Mon Sep 17 00:00:00 2001 From: Raven Szewczyk Date: Sun, 4 Feb 2024 20:02:52 +0000 Subject: [PATCH 042/132] [ci skip] upgraded build system --- build.gradle | 1623 +--------------------- gradle.properties | 128 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew.bat | 20 +- settings.gradle | 10 +- 5 files changed, 101 insertions(+), 1682 deletions(-) diff --git a/build.gradle b/build.gradle index 6274cb25..e57a16f9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,1624 +1,5 @@ -//version: 1705357285 -/* - 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/master/build.gradle for updates. - */ +//version: 1707058017 - -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import com.gtnewhorizons.retrofuturagradle.ObfuscationAttribute -import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar -import com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask -import com.gtnewhorizons.retrofuturagradle.util.Distribution -import com.matthewprenger.cursegradle.CurseArtifact -import com.matthewprenger.cursegradle.CurseRelation -import com.modrinth.minotaur.dependencies.ModDependency -import com.modrinth.minotaur.dependencies.VersionDependency -import org.gradle.internal.logging.text.StyledTextOutput.Style -import org.gradle.internal.logging.text.StyledTextOutputFactory -import org.gradle.internal.xml.XmlTransformer -import org.jetbrains.gradle.ext.Application -import org.jetbrains.gradle.ext.Gradle - -import javax.inject.Inject -import java.nio.file.Files -import java.nio.file.Paths -import java.util.concurrent.TimeUnit - -buildscript { - repositories { - maven { - // GTNH RetroFuturaGradle and ASM Fork - name "GTNH Maven" - url "https://nexus.gtnewhorizons.com/repository/public/" - } - mavenLocal() - } -} plugins { - id 'java-library' - id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7" - id 'eclipse' - id 'scala' - id 'maven-publish' - id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false - id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false - id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false - id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle - id 'com.github.johnrengelman.shadow' version '8.1.1' apply false - id 'com.palantir.git-version' version '3.0.0' apply false - id 'de.undercouch.download' version '5.5.0' - id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle - id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version - id 'com.modrinth.minotaur' version '2.+' apply false - id 'com.matthewprenger.cursegradle' version '1.4.0' apply false - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.27' -} - -print("You might want to check out './gradlew :faq' if your build fails.\n") - -boolean settingsupdated = verifySettingsGradle() -settingsupdated = verifyGitAttributes() || settingsupdated -if (settingsupdated) - throw new GradleException("Settings has been updated, please re-run task.") - -// In submodules, .git is a file pointing to the real git dir -if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) { - apply plugin: 'com.palantir.git-version' -} - -def out = services.get(StyledTextOutputFactory).create('an-output') - -def projectJavaVersion = JavaLanguageVersion.of(8) - -boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false -boolean disableCheckstyle = project.hasProperty("disableCheckstyle") ? project.disableCheckstyle.toBoolean() : false - -final String CHECKSTYLE_CONFIG = """ - - - - - - - - - - - -""" - -checkPropertyExists("modName") -checkPropertyExists("modId") -checkPropertyExists("modGroup") -checkPropertyExists("autoUpdateBuildScript") -checkPropertyExists("minecraftVersion") -checkPropertyExists("forgeVersion") -checkPropertyExists("replaceGradleTokenInFile") -checkPropertyExists("gradleTokenVersion") -checkPropertyExists("apiPackage") -checkPropertyExists("accessTransformersFile") -checkPropertyExists("usesMixins") -checkPropertyExists("mixinPlugin") -checkPropertyExists("mixinsPackage") -checkPropertyExists("coreModClass") -checkPropertyExists("containsMixinsAndOrCoreModOnly") -checkPropertyExists("usesShadowedDependencies") -checkPropertyExists("developmentEnvironmentUserName") - -propertyDefaultIfUnset("generateGradleTokenClass", "") -propertyDefaultIfUnset("includeWellKnownRepositories", true) -propertyDefaultIfUnset("noPublishedSources", false) -propertyDefaultIfUnset("usesMixinDebug", project.usesMixins) -propertyDefaultIfUnset("forceEnableMixins", false) -propertyDefaultIfUnset("channel", "stable") -propertyDefaultIfUnset("mappingsVersion", "12") -propertyDefaultIfUnset("usesMavenPublishing", true) -propertyDefaultIfUnset("mavenPublishUrl", "https://nexus.gtnewhorizons.com/repository/releases/") -propertyDefaultIfUnset("modrinthProjectId", "") -propertyDefaultIfUnset("modrinthRelations", "") -propertyDefaultIfUnset("curseForgeProjectId", "") -propertyDefaultIfUnset("curseForgeRelations", "") -propertyDefaultIfUnset("versionPattern", "") -propertyDefaultIfUnset("minimizeShadowedDependencies", true) -propertyDefaultIfUnset("relocateShadowedDependencies", true) -// Deprecated properties (kept for backwards compat) -propertyDefaultIfUnset("gradleTokenModId", "") -propertyDefaultIfUnset("gradleTokenModName", "") -propertyDefaultIfUnset("gradleTokenGroupName", "") - -propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only -propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only - -// this is meant to be set using the user wide property file. by default we do nothing. -propertyDefaultIfUnset("ideaOverrideBuildType", "") // Can be nothing, "gradle" or "idea" - -project.extensions.add(com.diffplug.blowdryer.Blowdryer, "Blowdryer", com.diffplug.blowdryer.Blowdryer) // Make blowdryer available in "apply from:" scripts -if (!disableSpotless) { - apply plugin: 'com.diffplug.spotless' - apply from: Blowdryer.file('spotless.gradle') -} - -if (!disableCheckstyle) { - apply plugin: 'checkstyle' - tasks.named("checkstylePatchedMc") { enabled = false } - tasks.named("checkstyleMcLauncher") { enabled = false } - tasks.named("checkstyleIdeVirtualMain") { enabled = false } - tasks.named("checkstyleInjectedTags") { enabled = false } - checkstyle { - config = resources.text.fromString(CHECKSTYLE_CONFIG) - } -} - -String javaSourceDir = "src/main/java/" -String scalaSourceDir = "src/main/scala/" -String kotlinSourceDir = "src/main/kotlin/" - -if (usesShadowedDependencies.toBoolean()) { - apply plugin: "com.github.johnrengelman.shadow" -} - -java { - toolchain { - if (enableModernJavaSyntax.toBoolean()) { - languageVersion.set(JavaLanguageVersion.of(17)) - } else { - languageVersion.set(projectJavaVersion) - } - vendor.set(JvmVendorSpec.AZUL) - } - if (!noPublishedSources) { - withSourcesJar() - } -} - -tasks.withType(JavaCompile).configureEach { - options.encoding = "UTF-8" -} - -tasks.withType(ScalaCompile).configureEach { - options.encoding = "UTF-8" -} - -pluginManager.withPlugin('org.jetbrains.kotlin.jvm') { - // If Kotlin is enabled in the project - kotlin { - jvmToolchain(8) - } - // Kotlin hacks our source sets, so we hack Kotlin's tasks - def disabledKotlinTaskList = [ - "kaptGenerateStubsMcLauncherKotlin", - "kaptGenerateStubsPatchedMcKotlin", - "kaptGenerateStubsInjectedTagsKotlin", - "compileMcLauncherKotlin", - "compilePatchedMcKotlin", - "compileInjectedTagsKotlin", - "kaptMcLauncherKotlin", - "kaptPatchedMcKotlin", - "kaptInjectedTagsKotlin", - "kspMcLauncherKotlin", - "kspPatchedMcKotlin", - "kspInjectedTagsKotlin", - ] - tasks.configureEach { task -> - if (task.name in disabledKotlinTaskList) { - task.enabled = false - } - } -} - -configurations { - create("runtimeOnlyNonPublishable") { - description = "Runtime only dependencies that are not published alongside the jar" - canBeConsumed = false - canBeResolved = false - } - - create("devOnlyNonPublishable") { - description = "Runtime and compiletime dependencies that are not published alongside the jar (compileOnly + runtimeOnlyNonPublishable)" - canBeConsumed = false - canBeResolved = false - } - compileOnly.extendsFrom(devOnlyNonPublishable) - runtimeOnlyNonPublishable.extendsFrom(devOnlyNonPublishable) -} - -if (enableModernJavaSyntax.toBoolean()) { - repositories { - mavenCentral { - mavenContent { - includeGroup("me.eigenraven.java8unsupported") - } - } - } - - dependencies { - annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' - // workaround for https://github.com/bsideup/jabel/issues/174 - annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0' - compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { - transitive = false // We only care about the 1 annotation class - } - // Allow using jdk.unsupported classes like sun.misc.Unsafe in the compiled code, working around JDK-8206937. - patchedMinecraft('me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0') - } - - tasks.withType(JavaCompile).configureEach { - if (it.name in ["compileMcLauncherJava", "compilePatchedMcJava"]) { - return - } - sourceCompatibility = 17 // for the IDE support - options.release.set(8) - - javaCompiler.set(javaToolchains.compilerFor { - languageVersion.set(JavaLanguageVersion.of(17)) - vendor.set(JvmVendorSpec.AZUL) - }) - } -} - -eclipse { - classpath { - downloadSources = true - downloadJavadoc = true - } -} - -final String modGroupPath = modGroup.toString().replace('.' as char, '/' as char) -final String apiPackagePath = apiPackage.toString().replace('.' as char, '/' as char) - -String targetPackageJava = javaSourceDir + modGroupPath -String targetPackageScala = scalaSourceDir + modGroupPath -String targetPackageKotlin = kotlinSourceDir + modGroupPath -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 + modGroupPath + "/" + apiPackagePath - targetPackageScala = scalaSourceDir + modGroupPath + "/" + apiPackagePath - targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + apiPackagePath - 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) { - for (atFile in accessTransformersFile.split(" ")) { - String targetFile = "src/main/resources/META-INF/" + atFile.trim() - if (!getFile(targetFile).exists()) { - throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) - } - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile) - } -} else { - boolean atsFound = false - for (File at : sourceSets.getByName("main").resources.files) { - if (at.name.toLowerCase().endsWith("_at.cfg")) { - atsFound = true - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) - } - } - for (File at : sourceSets.getByName("api").resources.files) { - if (at.name.toLowerCase().endsWith("_at.cfg")) { - atsFound = true - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) - } - } - if (atsFound) { - logger.warn("Found and added access transformers in the resources folder, please configure gradle.properties to explicitly mention them by name") - } -} - -if (usesMixins.toBoolean()) { - if (mixinsPackage.isEmpty()) { - throw new GradleException("\"usesMixins\" requires \"mixinsPackage\" to be set!") - } - final String mixinPackagePath = mixinsPackage.toString().replaceAll("\\.", "/") - final String mixinPluginPath = mixinPlugin.toString().replaceAll("\\.", "/") - - targetPackageJava = javaSourceDir + modGroupPath + "/" + mixinPackagePath - targetPackageScala = scalaSourceDir + modGroupPath + "/" + mixinPackagePath - targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPackagePath - 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) - } - - if (!mixinPlugin.isEmpty()) { - String targetFileJava = javaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" - String targetFileScala = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".scala" - String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java" - String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPluginPath + ".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) { - final String coreModPath = coreModClass.toString().replaceAll("\\.", "/") - String targetFileJava = javaSourceDir + modGroupPath + "/" + coreModPath + ".java" - String targetFileScala = scalaSourceDir + modGroupPath + "/" + coreModPath + ".scala" - String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + coreModPath + ".java" - String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + coreModPath + ".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.configureEach { - 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 -boolean checkVersion = false -try { - // Produce a version based on the tag, or for branches something like 0.2.2-configurable-maven-and-extras.38+43090270b6-dirty - if (versionOverride == null) { - def gitDetails = versionDetails() - def isDirty = gitVersion().endsWith(".dirty") // No public API for this, isCleanTag has a different meaning - String branchName = gitDetails.branchName ?: (System.getenv('GIT_BRANCH') ?: 'git') - if (branchName.startsWith('origin/')) { - branchName = branchName.minus('origin/') - } - branchName = branchName.replaceAll("[^a-zA-Z0-9-]+", "-") // sanitize branch names for semver - identifiedVersion = gitDetails.lastTag ?: '${gitDetails.gitHash}' - if (gitDetails.commitDistance > 0) { - identifiedVersion += "-${branchName}.${gitDetails.commitDistance}+${gitDetails.gitHash}" - if (isDirty) { - identifiedVersion += "-dirty" - } - } else if (isDirty) { - identifiedVersion += "-${branchName}+${gitDetails.gitHash}-dirty" - } else { - checkVersion = true - } - } else { - identifiedVersion = 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 = 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') -} else if (checkVersion && versionPattern && !(identifiedVersion ==~ versionPattern)) { - throw new GradleException("Invalid version: '$identifiedVersion' does not match version pattern '$versionPattern'") -} - -group = "com.github.GTNewHorizons" -if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { - base { - archivesName = customArchiveBaseName - } -} else { - base { - archivesName = modId - } -} - - -minecraft { - if (replaceGradleTokenInFile) { - for (f in replaceGradleTokenInFile.split(',')) { - tagReplacementFiles.add f - } - out.style(Style.Info).text('replaceGradleTokenInFile is deprecated! Consider using generateGradleTokenClass.').println() - } - if (gradleTokenModId) { - if (replaceGradleTokenInFile) { - injectedTags.put gradleTokenModId, modId - } else { - out.style(Style.Failure).text('gradleTokenModId is deprecated! The field will no longer be generated.').println() - } - } - if (gradleTokenModName) { - if (replaceGradleTokenInFile) { - injectedTags.put gradleTokenModName, modName - } else { - out.style(Style.Failure).text('gradleTokenModName is deprecated! The field will no longer be generated.').println() - } - } - if (gradleTokenVersion) { - injectedTags.put gradleTokenVersion, modVersion - } - if (gradleTokenGroupName) { - if (replaceGradleTokenInFile) { - injectedTags.put gradleTokenGroupName, modGroup - } else { - out.style(Style.Failure).text('gradleTokenGroupName is deprecated! The field will no longer be generated.').println() - } - } - if (enableGenericInjection.toBoolean()) { - injectMissingGenerics.set(true) - } - - username = developmentEnvironmentUserName.toString() - - lwjgl3Version = "3.3.2" - - // Enable assertions in the current mod - extraRunJvmArguments.add("-ea:${modGroup}") - - if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { - if (usesMixinDebug.toBoolean()) { - extraRunJvmArguments.addAll([ - "-Dmixin.debug.countInjections=true", - "-Dmixin.debug.verbose=true", - "-Dmixin.debug.export=true" - ]) - } - } - - // Blowdryer is present in some old mod builds, do not propagate it further as a dependency - // IC2 has no reobf jars in its Maven - groupsToExcludeFromAutoReobfMapping.addAll(["com.diffplug", "com.diffplug.durian", "net.industrial-craft"]) -} - -if (generateGradleTokenClass) { - tasks.injectTags.outputClassName.set(generateGradleTokenClass) -} - -// Custom reobf auto-mappings -configurations.configureEach { - dependencies.configureEach { dep -> - if (dep instanceof org.gradle.api.artifacts.ExternalModuleDependency) { - if (dep.group == "net.industrial-craft" && dep.name == "industrialcraft-2") { - // https://www.curseforge.com/minecraft/mc-mods/industrial-craft/files/2353971 - project.dependencies.reobfJarConfiguration("curse.maven:ic2-242638:2353971") - } - } - } - def obfuscationAttr = it.attributes.getAttribute(ObfuscationAttribute.OBFUSCATION_ATTRIBUTE) - if (obfuscationAttr != null && obfuscationAttr.name == ObfuscationAttribute.SRG) { - resolutionStrategy.eachDependency { DependencyResolveDetails details -> - // Remap CoFH core cursemaven dev jar to the obfuscated version for runObfClient/Server - if (details.requested.group == 'curse.maven' && details.requested.name.endsWith('-69162') && details.requested.version == '2388751') { - details.useVersion '2388750' - details.because 'Pick obfuscated jar' - } - } - } -} - -// Ensure tests have access to minecraft classes -sourceSets { - test { - java { - compileClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output - runtimeClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output - } - } -} - -if (file('addon.gradle.kts').exists()) { - apply from: 'addon.gradle.kts' -} else if (file('addon.gradle').exists()) { - apply from: 'addon.gradle' -} - -// File for local tweaks not commited to Git -if (file('addon.local.gradle.kts').exists()) { - apply from: 'addon.local.gradle.kts' -} else if (file('addon.local.gradle').exists()) { - apply from: 'addon.local.gradle' -} - -// Allow unsafe repos but warn -repositories.configureEach { repo -> - if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) { - if (repo.getUrl() != null && repo.getUrl().getScheme() == "http" && !repo.allowInsecureProtocol) { - logger.warn("Deprecated: Allowing insecure connections for repo '${repo.name}' - add 'allowInsecureProtocol = true'") - repo.allowInsecureProtocol = true - } - } -} - -if (file('repositories.gradle.kts').exists()) { - apply from: 'repositories.gradle.kts' -} else if (file('repositories.gradle').exists()) { - apply from: 'repositories.gradle' -} else { - logger.error("Neither repositories.gradle.kts nor repositories.gradle was found, make sure you extracted the full ExampleMod template.") - throw new RuntimeException("Missing repositories.gradle[.kts]") -} - -configurations { - runtimeClasspath.extendsFrom(runtimeOnlyNonPublishable) - testRuntimeClasspath.extendsFrom(runtimeOnlyNonPublishable) - for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { - if (usesShadowedDependencies.toBoolean()) { - config.extendsFrom(shadowImplementation) - // TODO: remove Compile after all uses are refactored to Implementation - config.extendsFrom(shadeCompile) - config.extendsFrom(shadowCompile) - } - } - // A "bag-of-dependencies"-style configuration for backwards compatibility, gets put in "api" - create("compile") { - description = "Deprecated: use api or implementation instead, gets put in api" - canBeConsumed = false - canBeResolved = false - visible = false - } - create("testCompile") { - description = "Deprecated: use testImplementation instead" - canBeConsumed = false - canBeResolved = false - visible = false - } - api.extendsFrom(compile) - testImplementation.extendsFrom(testCompile) -} - -afterEvaluate { - if (!configurations.compile.allDependencies.empty || !configurations.testCompile.allDependencies.empty) { - logger.warn("This project uses deprecated `compile` dependencies, please migrate to using `api` and `implementation`") - logger.warn("For more details, see https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/dependencies.gradle") - } -} - -repositories { - maven { - name = "GTNH Maven" - url = "https://nexus.gtnewhorizons.com/repository/public/" - // Links for convenience: - // Simple HTML browsing: https://nexus.gtnewhorizons.com/service/rest/repository/browse/releases/ - // Rich web UI browsing: https://nexus.gtnewhorizons.com/#browse/browse:releases - } - maven { - name 'Overmind forge repo mirror' - url 'https://gregtech.overminddl1.com/' - } - maven { - name 'sonatype' - url 'https://oss.sonatype.org/content/repositories/snapshots/' - content { - includeGroup "org.lwjgl" - } - } - if (includeWellKnownRepositories.toBoolean()) { - exclusiveContent { - forRepository { - maven { - name "CurseMaven" - url "https://cursemaven.com" - } - } - filter { - includeGroup "curse.maven" - } - } - exclusiveContent { - forRepository { - maven { - name = "Modrinth" - url = "https://api.modrinth.com/maven" - } - } - filter { - includeGroup "maven.modrinth" - } - } - maven { - name = "ic2" - url = getURL("https://maven2.ic2.player.to/", "https://maven.ic2.player.to/") - content { - includeGroup "net.industrial-craft" - } - metadataSources { - mavenPom() - artifact() - } - } - maven { - name "MMD Maven" - url "https://maven.mcmoddev.com/" - } - } -} - -def mixinProviderGroup = "io.github.legacymoddingmc" -def mixinProviderModule = "unimixins" -def mixinProviderVersion = "0.1.13" -def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}" -def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev" -ext.mixinProviderSpec = mixinProviderSpec - -def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json' - -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(mixinProviderSpec) - if (usesMixinDebug.toBoolean()) { - runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16') - } - } - if (usesMixins.toBoolean()) { - implementation(modUtils.enableMixins(mixinProviderSpec, mixingConfigRefMap)) - } else if (forceEnableMixins.toBoolean()) { - runtimeOnlyNonPublishable(mixinProviderSpec) - } -} - -pluginManager.withPlugin('org.jetbrains.kotlin.kapt') { - if (usesMixins.toBoolean()) { - dependencies { - kapt(mixinProviderSpec) - } - } -} - -// Replace old mixin mods with unimixins -// https://docs.gradle.org/8.0.2/userguide/resolution_rules.html#sec:substitution_with_classifier -configurations.all { - resolutionStrategy.dependencySubstitution { - substitute module('com.gtnewhorizon:gtnhmixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('com.github.GTNewHorizons:Mixingasm') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods") - substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier") - - substitute module('org.scala-lang:scala-library:2.11.1') using module('org.scala-lang:scala-library:2.11.5') because('To allow mixing with Java 8 targets') - } -} - -dependencies { - constraints { - def minGtnhLibVersion = "0.0.13" - implementation("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - runtimeOnly("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - devOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - runtimeOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:${minGtnhLibVersion}") { - because("fixes duplicate mod errors in java 17 configurations using old gtnhlib") - } - } -} - -if (file('dependencies.gradle.kts').exists()) { - apply from: 'dependencies.gradle.kts' -} else if (file('dependencies.gradle').exists()) { - apply from: 'dependencies.gradle' -} else { - logger.error("Neither dependencies.gradle.kts nor dependencies.gradle was found, make sure you extracted the full ExampleMod template.") - throw new RuntimeException("Missing dependencies.gradle[.kts]") -} - -tasks.register('generateAssets') { - group = "GTNH Buildscript" - description = "Generates a mixin config file at /src/main/resources/mixins.modid.json if needed" - onlyIf { usesMixins.toBoolean() } - doLast { - def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json") - if (!mixinConfigFile.exists()) { - def mixinPluginLine = "" - if (!mixinPlugin.isEmpty()) { - // We might not have a mixin plugin if we're using early/late mixins - mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """ - } - - mixinConfigFile.text = """{ - "required": true, - "minVersion": "0.8.5-GTNH", - "package": "${modGroup}.${mixinsPackage}",${mixinPluginLine} - "refmap": "${mixingConfigRefMap}", - "target": "@env(DEFAULT)", - "compatibilityLevel": "JAVA_8", - "mixins": [], - "client": [], - "server": [] -} -""" - } - } -} - -if (usesMixins.toBoolean()) { - tasks.named("processResources").configure { - dependsOn("generateAssets") - } - - tasks.named("compileJava", JavaCompile).configure { - options.compilerArgs += [ - // 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" - ] - } -} - -tasks.named("processResources", ProcessResources).configure { - // this will ensure that this task is redone when the versions change. - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.mcVersion - exclude("spotless.gradle") - - // replace stuff in mcmod.info, nothing else. replaces ${key} with value in text - filesMatching("mcmod.info") { - expand "minecraftVersion": project.minecraft.mcVersion, - "modVersion": modVersion, - "modId": modId, - "modName": modName - } - - if (usesMixins.toBoolean()) { - dependsOn("compileJava", "compileScala") - } -} - -ext.java17Toolchain = (JavaToolchainSpec spec) -> { - spec.languageVersion.set(JavaLanguageVersion.of(17)) - spec.vendor.set(JvmVendorSpec.matching("jetbrains")) -} - -ext.java17DependenciesCfg = configurations.create("java17Dependencies") { - extendsFrom(configurations.getByName("runtimeClasspath")) // Ensure consistent transitive dependency resolution - canBeConsumed = false -} -ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies") { - canBeConsumed = false -} - -dependencies { - def lwjgl3ifyVersion = '1.5.7' - if (modId != 'lwjgl3ify') { - java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}") - } - if (modId != 'hodgepodge') { - java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.4.4') - } - - java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false} -} - -ext.java17JvmArgs = [ - // Java 9+ support - "--illegal-access=warn", - "-Djava.security.manager=allow", - "-Dfile.encoding=UTF-8", - "--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED", - "--add-opens", "java.base/java.net=ALL-UNNAMED", - "--add-opens", "java.base/java.nio=ALL-UNNAMED", - "--add-opens", "java.base/java.io=ALL-UNNAMED", - "--add-opens", "java.base/java.lang=ALL-UNNAMED", - "--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED", - "--add-opens", "java.base/java.text=ALL-UNNAMED", - "--add-opens", "java.base/java.util=ALL-UNNAMED", - "--add-opens", "java.base/jdk.internal.reflect=ALL-UNNAMED", - "--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED", - "--add-opens", "jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED,java.naming", - "--add-opens", "java.desktop/sun.awt.image=ALL-UNNAMED", - "--add-modules", "jdk.dynalink", - "--add-opens", "jdk.dynalink/jdk.dynalink.beans=ALL-UNNAMED", - "--add-modules", "java.sql.rowset", - "--add-opens", "java.sql.rowset/javax.sql.rowset.serial=ALL-UNNAMED" -] - -ext.hotswapJvmArgs = [ - // DCEVM advanced hot reload - "-XX:+AllowEnhancedClassRedefinition", - "-XX:HotswapAgent=fatjar" -] - -ext.setupHotswapAgentTask = tasks.register("setupHotswapAgent") { - group = "GTNH Buildscript" - description = "Installs a recent version of HotSwapAgent into the Java 17 JetBrains runtime directory" - def hsaUrl = 'https://github.com/HotswapProjects/HotswapAgent/releases/download/1.4.2-SNAPSHOT/hotswap-agent-1.4.2-SNAPSHOT.jar' - def targetFolderProvider = javaToolchains.launcherFor(java17Toolchain).map {it.metadata.installationPath.dir("lib/hotswap")} - def targetFilename = "hotswap-agent.jar" - onlyIf { - !targetFolderProvider.get().file(targetFilename).asFile.exists() - } - doLast { - def targetFolder = targetFolderProvider.get() - targetFolder.asFile.mkdirs() - download.run { - src hsaUrl - dest targetFolder.file(targetFilename).asFile - overwrite false - tempAndMove true - } - } -} - -public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask { - // IntelliJ doesn't seem to allow commandline arguments so we also support an env variable - private boolean enableHotswap = Boolean.valueOf(System.getenv("HOTSWAP")); - - @Input - public boolean getEnableHotswap() { return enableHotswap } - @Option(option = "hotswap", description = "Enables HotSwapAgent for enhanced class reloading under a debugger") - public boolean setEnableHotswap(boolean enable) { enableHotswap = enable } - - @Inject - public RunHotswappableMinecraftTask(Distribution side, String superTask, org.gradle.api.invocation.Gradle gradle) { - super(side, gradle) - - this.lwjglVersion = 3 - this.javaLauncher = project.javaToolchains.launcherFor(project.java17Toolchain) - this.extraJvmArgs.addAll(project.java17JvmArgs) - this.extraJvmArgs.addAll(project.provider(() -> enableHotswap ? project.hotswapJvmArgs : [])) - - this.classpath(project.java17PatchDependenciesCfg) - if (side == Distribution.CLIENT) { - this.classpath(project.minecraftTasks.lwjgl3Configuration) - } - // Use a raw provider instead of map to not create a dependency on the task - this.classpath(project.provider(() -> project.tasks.named(superTask, RunMinecraftTask).get().classpath)) - this.classpath.filter { file -> - !file.path.contains("2.9.4-nightly-20150209") // Remove lwjgl2 - } - this.classpath(project.java17DependenciesCfg) - } - - public void setup(Project project) { - super.setup(project) - if (project.usesMixins.toBoolean()) { - this.extraJvmArgs.addAll(project.provider(() -> { - def mixinCfg = project.configurations.detachedConfiguration(project.dependencies.create(project.mixinProviderSpec)) - mixinCfg.canBeConsumed = false - mixinCfg.transitive = false - enableHotswap ? ["-javaagent:" + mixinCfg.singleFile.absolutePath] : [] - })) - } - } -} - -def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient") -runClient17Task.configure { - setup(project) - group = "Modded Minecraft" - description = "Runs the modded client using Java 17, lwjgl3ify and Hodgepodge" - dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') - mainClass = "GradleStart" - username = minecraft.username - userUUID = minecraft.userUUID -} - -def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer") -runServer17Task.configure { - setup(project) - group = "Modded Minecraft" - description = "Runs the modded server using Java 17, lwjgl3ify and Hodgepodge" - dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar') - mainClass = "GradleStartServer" - extraArgs.add("nogui") -} - -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 -} - -tasks.named("jar", Jar).configure { - manifest { - attributes(getManifestAttributes()) - } -} - -if (usesShadowedDependencies.toBoolean()) { - tasks.named("shadowJar", ShadowJar).configure { - manifest { - attributes(getManifestAttributes()) - } - - if (minimizeShadowedDependencies.toBoolean()) { - minimize() // This will only allow shading for actually used classes - } - configurations = [ - project.configurations.shadowImplementation, - project.configurations.shadowCompile, - project.configurations.shadeCompile - ] - archiveClassifier.set('dev') - if (relocateShadowedDependencies.toBoolean()) { - relocationPrefix = modGroup + ".shadow" - enableRelocation = true - } - } - configurations.runtimeElements.outgoing.artifacts.clear() - configurations.apiElements.outgoing.artifacts.clear() - configurations.runtimeElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) - configurations.apiElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar)) - tasks.named("jar", Jar) { - archiveClassifier.set('dev-preshadow') - } - tasks.named("reobfJar", ReobfuscatedJar) { - inputJar.set(tasks.named("shadowJar", ShadowJar).flatMap({it.archiveFile})) - } - AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.findByName("java") - javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { - skip() - } -} -ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar -ext.publishableObfJar = tasks.reobfJar - -tasks.register('apiJar', Jar) { - from(sourceSets.main.allSource) { - include modGroupPath + "/" + apiPackagePath + '/**' - } - - from(sourceSets.main.output) { - include modGroupPath + "/" + apiPackagePath + '/**' - } - - from(sourceSets.main.resources.srcDirs) { - include("LICENSE") - } - - getArchiveClassifier().set('api') -} - -artifacts { - if (!noPublishedSources) { - archives tasks.named("sourcesJar") - } - if (apiPackage) { - archives tasks.named("apiJar") - } -} - -idea { - module { - downloadJavadoc = true - downloadSources = true - inheritOutputDirs = true - } - project { - settings { - if (ideaOverrideBuildType != "") { - delegateActions { - if ("gradle".equalsIgnoreCase(ideaOverrideBuildType)) { - delegateBuildRunToGradle = true - testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.GRADLE - } else if ("idea".equalsIgnoreCase(ideaOverrideBuildType)) { - delegateBuildRunToGradle = false - testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM - } else { - throw GradleScriptException('Accepted value for ideaOverrideBuildType is one of gradle or idea.') - } - } - } - runConfigurations { - "0. Build and Test"(Gradle) { - taskNames = ["build"] - } - "1. Run Client"(Gradle) { - taskNames = ["runClient"] - } - "2. Run Server"(Gradle) { - taskNames = ["runServer"] - } - "1a. Run Client (Java 17)"(Gradle) { - taskNames = ["runClient17"] - } - "2a. Run Server (Java 17)"(Gradle) { - taskNames = ["runServer17"] - } - "1b. Run Client (Java 17, Hotswap)"(Gradle) { - taskNames = ["runClient17"] - envs = ["HOTSWAP": "true"] - } - "2b. Run Server (Java 17, Hotswap)"(Gradle) { - taskNames = ["runServer17"] - envs = ["HOTSWAP": "true"] - } - "3. Run Obfuscated Client"(Gradle) { - taskNames = ["runObfClient"] - } - "4. Run Obfuscated Server"(Gradle) { - taskNames = ["runObfServer"] - } - if (!disableSpotless) { - "5. Apply spotless"(Gradle) { - taskNames = ["spotlessApply"] - } - } - def coreModArgs = "" - if (coreModClass) { - coreModArgs = ' "-Dfml.coreMods.load=' + modGroup + '.' + coreModClass + '"' - } - "Run Client (IJ Native)"(Application) { - mainClass = "GradleStart" - moduleName = project.name + ".ideVirtualMain" - afterEvaluate { - workingDirectory = tasks.runClient.workingDir.absolutePath - programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ') - jvmArgs = tasks.runClient.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + - ' ' + tasks.runClient.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + - coreModArgs - } - } - "Run Server (IJ Native)"(Application) { - mainClass = "GradleStartServer" - moduleName = project.name + ".ideVirtualMain" - afterEvaluate { - workingDirectory = tasks.runServer.workingDir.absolutePath - programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ') - jvmArgs = tasks.runServer.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') + - ' ' + tasks.runServer.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') + - coreModArgs - } - } - } - compiler.javac { - afterEvaluate { - javacAdditionalOptions = "-encoding utf8" - moduleJavacAdditionalOptions = [ - (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') - ] - } - } - withIDEADir { File ideaDir -> - if (!ideaDir.path.contains(".idea")) { - // If an .ipr file exists, the project root directory is passed here instead of the .idea subdirectory - ideaDir = new File(ideaDir, ".idea") - } - if (ideaDir.isDirectory()) { - def miscFile = new File(ideaDir, "misc.xml") - if (miscFile.isFile()) { - boolean dirty = false - def miscTransformer = new XmlTransformer() - miscTransformer.addAction { root -> - Node rootNode = root.asNode() - def rootManager = rootNode - .component.find { it.@name == 'ProjectRootManager' } - if (!rootManager) { - rootManager = rootNode.appendNode('component', ['name': 'ProjectRootManager', 'version': '2']) - dirty = true - } - def output = rootManager.output - if (!output) { - output = rootManager.appendNode('output') - dirty = true - } - if (!output.@url) { - // Only modify the output url if it doesn't yet have one, or if the existing one is blank somehow. - // This is a sensible default for most setups - output.@url = 'file://$PROJECT_DIR$/build/ideaBuild' - dirty = true - } - } - def result = miscTransformer.transform(miscFile.text) - if (dirty) { - miscFile.write(result) - } - } else { - miscFile.text = """ - - - - - -""" - } - } - } - } - } -} - -tasks.named("processIdeaSettings").configure { - dependsOn("injectTags") -} - -tasks.named("ideVirtualMainClasses").configure { - // Make IntelliJ "Build project" build the mod jars - dependsOn("jar", "reobfJar") - if (!disableSpotless) { - dependsOn("spotlessCheck") - } -} - -// workaround variable hiding in pom processing -def projectConfigs = project.configurations - -publishing { - publications { - create("maven", MavenPublication) { - from components.java - - if (apiPackage) { - artifact apiJar - } - - groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group - 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 - } - } - repositories { - if (usesMavenPublishing.toBoolean() && System.getenv("MAVEN_USER") != null) { - maven { - url = mavenPublishUrl - allowInsecureProtocol = mavenPublishUrl.startsWith("http://") - credentials { - username = System.getenv("MAVEN_USER") ?: "NONE" - password = System.getenv("MAVEN_PASSWORD") ?: "NONE" - } - } - } - } -} - -if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) { - apply plugin: 'com.modrinth.minotaur' - - File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") - - modrinth { - token = System.getenv("MODRINTH_TOKEN") - projectId = modrinthProjectId - versionNumber = identifiedVersion - versionType = identifiedVersion.endsWith("-pre") ? "beta" : "release" - changelog = changelogFile.exists() ? changelogFile.getText("UTF-8") : "" - uploadFile = publishableObfJar - additionalFiles = getSecondaryArtifacts() - gameVersions = [minecraftVersion] - loaders = ["forge"] - debugMode = false - } - - if (modrinthRelations.size() != 0) { - String[] deps = modrinthRelations.split(";") - deps.each { dep -> - if (dep.size() == 0) { - return - } - String[] parts = dep.split(":") - String[] qual = parts[0].split("-") - addModrinthDep(qual[0], qual[1], parts[1]) - } - } - if (usesMixins.toBoolean()) { - addModrinthDep("required", "project", "unimixins") - } - tasks.modrinth.dependsOn(build) - tasks.publish.dependsOn(tasks.modrinth) -} - -if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null) { - apply plugin: 'com.matthewprenger.cursegradle' - - File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") - - curseforge { - apiKey = System.getenv("CURSEFORGE_TOKEN") - project { - id = curseForgeProjectId - if (changelogFile.exists()) { - changelogType = "markdown" - changelog = changelogFile - } - releaseType = identifiedVersion.endsWith("-pre") ? "beta" : "release" - addGameVersion minecraftVersion - addGameVersion "Forge" - mainArtifact publishableObfJar - for (artifact in getSecondaryArtifacts()) addArtifact artifact - } - - options { - javaIntegration = false - forgeGradleIntegration = false - debug = false - } - } - - if (curseForgeRelations.size() != 0) { - String[] deps = curseForgeRelations.split(";") - deps.each { dep -> - if (dep.size() == 0) { - return - } - String[] parts = dep.split(":") - addCurseForgeRelation(parts[0], parts[1]) - } - } - if (usesMixins.toBoolean()) { - addCurseForgeRelation("requiredDependency", "unimixins") - } - tasks.curseforge.dependsOn(build) - tasks.publish.dependsOn(tasks.curseforge) -} - -def addModrinthDep(String scope, String type, String name) { - com.modrinth.minotaur.dependencies.Dependency dep; - if (!(scope in ["required", "optional", "incompatible", "embedded"])) { - throw new Exception("Invalid modrinth dependency scope: " + scope) - } - switch (type) { - case "project": - dep = new ModDependency(name, scope) - break - case "version": - dep = new VersionDependency(name, scope) - break - default: - throw new Exception("Invalid modrinth dependency type: " + type) - } - project.modrinth.dependencies.add(dep) -} - -def addCurseForgeRelation(String type, String name) { - if (!(type in ["requiredDependency", "embeddedLibrary", "optionalDependency", "tool", "incompatible"])) { - throw new Exception("Invalid CurseForge relation type: " + type) - } - CurseArtifact artifact = project.curseforge.curseProjects[0].mainArtifact - CurseRelation rel = (artifact.curseRelations ?: (artifact.curseRelations = new CurseRelation())) - rel."$type"(name) -} - -// Updating - -def buildscriptGradleVersion = "8.5" - -tasks.named('wrapper', Wrapper).configure { - gradleVersion = buildscriptGradleVersion -} - -tasks.register('updateBuildScript') { - group = 'GTNH Buildscript' - description = 'Updates the build script to the latest version' - - if (gradle.gradleVersion != buildscriptGradleVersion && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_GRADLE_UPDATE')) { - dependsOn('wrapper') - } - - doLast { - if (performBuildScriptUpdate()) return - - print("Build script already up-to-date!") - } -} - -if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_UPDATE_CHECK') && isNewBuildScriptVersionAvailable()) { - if (autoUpdateBuildScript.toBoolean()) { - performBuildScriptUpdate() - } else { - out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") - if (gradle.gradleVersion != buildscriptGradleVersion) { - out.style(Style.SuccessHeader).println("updateBuildScript can update gradle from ${gradle.gradleVersion} to ${buildscriptGradleVersion}\n") - } - } -} - -// If you want to add more cases to this task, implement them as arguments if total amount to print gets too large -tasks.register('faq') { - group = 'GTNH Buildscript' - description = 'Prints frequently asked questions about building a project' - - doLast { - print("If your build fails to fetch dependencies, run './gradlew updateDependencies'. " + - "Or you can manually check if the versions are still on the distributing sites - " + - "the links can be found in repositories.gradle and build.gradle:repositories, " + - "but not build.gradle:buildscript.repositories - those ones are for gradle plugin metadata.\n\n" + - "If your build fails to recognize the syntax of new Java versions, enable Jabel in your " + - "gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties. " + - "However, keep in mind that Jabel enables only syntax features, but not APIs that were introduced in " + - "Java 9 or later.") - } -} - -static URL availableBuildScriptUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/build.gradle") -} - -static URL exampleSettingsGradleUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/settings.gradle.example") -} - -static URL exampleGitAttributesUrl() { - new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/.gitattributes") -} - - -boolean verifyGitAttributes() { - def gitattributesFile = getFile(".gitattributes") - if (!gitattributesFile.exists()) { - println("Downloading default .gitattributes") - exampleGitAttributesUrl().withInputStream { i -> gitattributesFile.withOutputStream { it << i } } - exec { - workingDir '.' - commandLine 'git', 'add', '--renormalize', '.' - } - return true - } - return false -} - -boolean verifySettingsGradle() { - def settingsFile = getFile("settings.gradle") - if (!settingsFile.exists()) { - println("Downloading default settings.gradle") - exampleSettingsGradleUrl().withInputStream { i -> settingsFile.withOutputStream { it << i } } - return true - } - return false -} - -boolean performBuildScriptUpdate() { - if (isNewBuildScriptVersionAvailable()) { - def buildscriptFile = getFile("build.gradle") - availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } - def out = services.get(StyledTextOutputFactory).create('buildscript-update-output') - out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!") - boolean settingsupdated = verifySettingsGradle() - settingsupdated = verifyGitAttributes() || settingsupdated - if (settingsupdated) - throw new GradleException("Settings has been updated, please re-run task.") - return true - } - return false -} - -boolean isNewBuildScriptVersionAvailable() { - Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] - - String currentBuildScript = getFile("build.gradle").getText() - String currentBuildScriptHash = getVersionHash(currentBuildScript) - String availableBuildScriptHash - try { - String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() - availableBuildScriptHash = getVersionHash(availableBuildScript) - } catch (IOException e) { - logger.warn("Could not check for buildscript update availability: {}", e.message) - return false - } - - boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash - return !isUpToDate -} - -static String getVersionHash(String buildScriptContent) { - String versionLine = buildScriptContent.find("^//version: [a-z0-9]*") - if (versionLine != null) { - return versionLine.split(": ").last() - } - return "" -} - -// Parameter Deobfuscation - -tasks.register('deobfParams') { - group = 'GTNH Buildscript' - description = 'Rename all obfuscated parameter names inherited from Minecraft classes' - doLast { // TODO - - 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 ...") - copy { - from(zipTree(mcpZIP)) - into(mcpDir) - } - } - - println("Parsing params.csv ...") - Map 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 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 -} - -// Dependency Deobfuscation (Deprecated, use the new RFG API documented in dependencies.gradle) - -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 ignored) { - return deobf(sourceURL, "deobf/${sourceURL.hashCode()}") - } -} - -def deobfMaven(String repoURL, String mavenDep) { - if (!repoURL.endsWith("/")) { - repoURL += "/" - } - String[] parts = mavenDep.split(":") - parts[0] = parts[0].replace('.', '/') - def jarURL = repoURL + parts[0] + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + ".jar" - return deobf(jarURL) -} - -def deobfCurse(String curseDep) { - return dependencies.rfg.deobf("curse.maven:$curseDep") -} - -// The method above is to be preferred. Use this method if the filename is not at the end of the URL. -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 obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar" - - download.run { - src sourceURL - dest obfFile - quiet true - overwrite false - } - return dependencies.rfg.deobf(files(obfFile)) -} -// 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 propertyDefaultIfUnset(String propertyName, defaultValue) { - if (!project.hasProperty(propertyName) || project.property(propertyName) == "") { - project.ext.setProperty(propertyName, defaultValue) - } -} - -def getFile(String relativePath) { - return new File(projectDir, relativePath) -} - -def getSecondaryArtifacts() { - // Because noPublishedSources from the beginning of the script is somehow not visible here... - boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false - def secondaryArtifacts = [publishableDevJar] - if (!noPublishedSources) secondaryArtifacts += [sourcesJar] - if (apiPackage) secondaryArtifacts += [apiJar] - return secondaryArtifacts -} - -def getURL(String main, String fallback) { - return pingURL(main, 10000) ? main : fallback -} - -// credit: https://stackoverflow.com/a/3584332 -def pingURL(String url, int timeout) { - url = url.replaceFirst("^https", "http") // Otherwise an exception may be thrown on invalid SSL certificates. - try { - HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection() - connection.setConnectTimeout(timeout) - connection.setReadTimeout(timeout) - connection.setRequestMethod("HEAD") - int responseCode = connection.getResponseCode() - return 200 <= responseCode && responseCode <= 399 - } catch (IOException ignored) { - return false - } -} - -// For easier scripting of things that require variables defined earlier in the buildscript -if (file('addon.late.gradle.kts').exists()) { - apply from: 'addon.late.gradle.kts' -} else if (file('addon.late.gradle').exists()) { - apply from: 'addon.late.gradle' -} - -// File for local tweaks not commited to Git -if (file('addon.late.local.gradle.kts').exists()) { - apply from: 'addon.late.local.gradle.kts' -} else if (file('addon.late.local.gradle').exists()) { - apply from: 'addon.late.local.gradle' + id 'com.gtnewhorizons.gtnhconvention' } diff --git a/gradle.properties b/gradle.properties index 37e0e97c..64b98b5d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,77 +1,101 @@ +# 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 = VisualProspecting -# 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 = visualprospecting +# Root package of the mod, used to find various classes in other properties, +# mcmod.info substitution, enabling assertions in run tasks, etc. modGroup = com.sinthoras.visualprospecting -# 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 -# Specify a MCP channel and mappings version for dependency deobfuscation and the deobfParams task. +# 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 -# Define other MCP mappings for dependency deobfuscation +# Defines other MCP mappings for dependency deobfuscation. remoteMappings = https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/ -# 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 +# 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 -# Enables using modern java syntax (up to version 17) via Jabel, while still targeting JVM 8. +# 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, Map types +# Enables injecting missing generics into the decompiled source code for a better coding experience. +# Turns most publicly visible List, Map, etc. into proper List, Map types. enableGenericInjection = true -# Generate a class with String fields for the mod id, name, version and group name named with the fields below +# 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 = com.sinthoras.visualprospecting.Version + +# 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 = -gradleTokenVersion = VERSION -gradleTokenGroupName = + # [DEPRECATED] -# Multiple source files can be defined here by providing a comma-seperated list: Class1.java,Class2.java,Class3.java +# 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 +# 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/ -# There can be multiple files in a comma-separated list. -# Example value: mymodid_at.cfg,nei_at.cfg +# There can be multiple files in a space-separated list. +# Example value: mymodid_at.cfg nei_at.cfg accessTransformersFile = # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! usesMixins = true -# Adds some debug arguments like verbose output and export + +# Adds some debug arguments like verbose output and class export. usesMixinDebug = true + # 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 = mixins + # 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 = mixinplugin.VisualProspectingEarlyMixinLoader + # 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 = false @@ -79,28 +103,32 @@ containsMixinsAndOrCoreModOnly = false # 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 in your jar. It is your -# responsibility check the licence and request permission for distribution, if required. +# 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 shaded dependencies. Some libraries use reflection to access + +# 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 the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories +# Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories. includeWellKnownRepositories = true # 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_USERNAME and MAVEN_PASSWORD environment variables. +# 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 -# mavenPublishUrl = http://jenkins.usrv.eu:8081/nexus/content/repositories/releases -# Publishing to modrinth requires you to set the MODRINTH_TOKEN environment variable to your current modrinth API token. +# 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 on Modrinth. +# Leave this empty if you don't want to publish to Modrinth. modrinthProjectId = # The project's relations on Modrinth. You can use this to refer to other projects on Modrinth. @@ -112,9 +140,8 @@ modrinthProjectId = # Note: GTNH Mixins is automatically set as a required dependency if usesMixins = true modrinthRelations = - # 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 = @@ -124,26 +151,41 @@ curseForgeProjectId = # 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: GTNH Mixins is automatically set as a required dependency if usesMixins = true +# Note: UniMixins is automatically set as a required dependency if usesMixins = true. curseForgeRelations = - -# Optional parameter to customize the produced artifacts. Use this to preserver artifact naming when migrating older +# 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 prevent the source code from being published -# noPublishedSources = +# 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 +# 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 -# Override the IDEA build type. Valid value is "" (leave blank, do not override), "idea" (force use native IDEA build), "gradle" +# 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 always native build. +# 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 + +# Non-GTNH properties +gradleTokenGroupName = diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af9e093..a80b22ce 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f..25da30db 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 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 @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe 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 diff --git a/settings.gradle b/settings.gradle index 8a66026e..e8946ada 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,6 +6,7 @@ pluginManagement { name "GTNH Maven" url "https://nexus.gtnewhorizons.com/repository/public/" mavenContent { + includeGroup("com.gtnewhorizons") includeGroupByRegex("com\\.gtnewhorizons\\..+") } } @@ -16,12 +17,7 @@ pluginManagement { } plugins { - id 'com.diffplug.blowdryerSetup' version '1.7.1' - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' // Provides java toolchains + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.8' } -blowdryerSetup { - repoSubfolder 'gtnhShared' - github('GTNewHorizons/ExampleMod1.7.10', 'tag', '0.2.0') - //devLocal '.' // Use this when testing config updates locally -} + From 2c938cd308d8049479760308fdea7b249cf8cf59 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Sat, 10 Feb 2024 10:31:02 +0100 Subject: [PATCH 043/132] show empty fluid fields and center label (#42) --- .../drawsteps/UndergroundFluidDrawStep.java | 107 +++++++++--------- .../UndergroundFluidRenderStep.java | 16 ++- .../assets/visualprospecting/lang/en_US.lang | 1 + 3 files changed, 66 insertions(+), 58 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java index 14fd1dd0..5162fd64 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java @@ -2,6 +2,8 @@ import java.awt.geom.Point2D; +import net.minecraft.client.resources.I18n; + import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; @@ -17,67 +19,68 @@ public UndergroundFluidDrawStep(UndergroundFluidLocation undergroundFluidLocatio this.undergroundFluidLocation = undergroundFluidLocation; } + @SuppressWarnings("deprecation") @Override public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, double fontScale, double rotation) { final int maxAmountInField = undergroundFluidLocation.getMaxProduction(); - if (maxAmountInField > 0) { - final double blockSize = Math.pow(2, gridRenderer.getZoom()); - final Point2D.Double blockAsPixel = gridRenderer - .getBlockPixelInGrid(undergroundFluidLocation.getBlockX(), undergroundFluidLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double( - blockAsPixel.getX() + draggedPixelX, - blockAsPixel.getY() + draggedPixelY); + final double blockSize = Math.pow(2, gridRenderer.getZoom()); + final Point2D.Double blockAsPixel = gridRenderer + .getBlockPixelInGrid(undergroundFluidLocation.getBlockX(), undergroundFluidLocation.getBlockZ()); + final Point2D.Double pixel = new Point2D.Double( + blockAsPixel.getX() + draggedPixelX, + blockAsPixel.getY() + draggedPixelY); - final int borderColor = undergroundFluidLocation.getFluid().getColor(); - final int borderAlpha = 204; - DrawUtil.drawRectangle( - pixel.getX(), - pixel.getY(), - VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, - 2 * blockSize, - borderColor, - borderAlpha); - DrawUtil.drawRectangle( - pixel.getX() + VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, - pixel.getY(), - 2 * blockSize, - VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, - borderColor, - borderAlpha); - DrawUtil.drawRectangle( - pixel.getX() + 2 * blockSize, - pixel.getY() + VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, - VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, - 2 * blockSize, - borderColor, - borderAlpha); - DrawUtil.drawRectangle( - pixel.getX(), - pixel.getY() + 2 * blockSize, - 2 * blockSize, - VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, - borderColor, - borderAlpha); + final int borderColor = undergroundFluidLocation.getFluid().getColor(); + final int borderAlpha = 204; + DrawUtil.drawRectangle( + pixel.getX(), + pixel.getY(), + VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, + 2 * blockSize, + borderColor, + borderAlpha); + DrawUtil.drawRectangle( + pixel.getX() + VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, + pixel.getY(), + 2 * blockSize, + VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, + borderColor, + borderAlpha); + DrawUtil.drawRectangle( + pixel.getX() + 2 * blockSize, + pixel.getY() + VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, + VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, + 2 * blockSize, + borderColor, + borderAlpha); + DrawUtil.drawRectangle( + pixel.getX(), + pixel.getY() + 2 * blockSize, + 2 * blockSize, + VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, + borderColor, + borderAlpha); - @SuppressWarnings("deprecation") - final String label = undergroundFluidLocation.getMinProduction() + "L - " + String label = I18n.format("visualprospecting.empty"); + if (maxAmountInField > 0) { + label = undergroundFluidLocation.getMinProduction() + "L - " + maxAmountInField + "L " + undergroundFluidLocation.getFluid().getLocalizedName(); - DrawUtil.drawLabel( - label, - pixel.getX() + VP.chunkWidth * blockSize, - pixel.getY(), - DrawUtil.HAlign.Right, - DrawUtil.VAlign.Below, - 0, - 180, - 0x00FFFFFF, - 255, - fontScale, - false, - rotation); } + DrawUtil.drawLabel( + label, + pixel.getX() + VP.chunkWidth * (blockSize * 4), + pixel.getY(), + DrawUtil.HAlign.Center, + DrawUtil.VAlign.Below, + 0, + 180, + 0x00FFFFFF, + 255, + fontScale, + false, + rotation); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java index 81e9fcf0..507031b6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java @@ -3,6 +3,7 @@ import javax.annotation.Nullable; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; import org.lwjgl.opengl.GL11; @@ -18,11 +19,12 @@ public UndergroundFluidRenderStep(UndergroundFluidLocation undergroundFluid) { undergroundFluidLocation = undergroundFluid; } + @SuppressWarnings("deprecation") @Override public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double scale) { final int maxAmountInField = undergroundFluidLocation.getMaxProduction(); // < 0.5 scale is when scaling issues show up - if (maxAmountInField > 0 && scale >= 0.5) { + if (scale >= 0.5) { GL11.glPushMatrix(); GL11.glTranslated( undergroundFluidLocation.getBlockX() - 0.5 - cameraX, @@ -40,11 +42,13 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double // min scale that journeymap can go to if (scale >= 1 && gui != null) { GL11.glScaled(1 / scale, 1 / scale, 1); - @SuppressWarnings("deprecation") - final String label = undergroundFluidLocation.getMinProduction() + "L - " - + maxAmountInField - + "L " - + undergroundFluidLocation.getFluid().getLocalizedName(); + String label = I18n.format("visualprospecting.empty"); + if (maxAmountInField > 0) { + label = undergroundFluidLocation.getMinProduction() + "L - " + + maxAmountInField + + "L " + + undergroundFluidLocation.getFluid().getLocalizedName(); + } DrawUtils.drawSimpleLabel(gui, label, VP.chunkWidth * scale, 0, 0xFFFFFFFF, 0xB4000000, false); } diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index 013df93a..282df4d0 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -27,6 +27,7 @@ visualprospecting.redoserverspawncache.confirmation=Redo success! visualprospecting.iswaypoint=Active as Waypoint visualprospecting.depleted=DEPLETED visualprospecting.depleted.toggle=Toggle depleted with %s +visualprospecting.empty=Empty visualprospecting.key.action.name=Action button visualprospecting.key.toggleore.name=Toggle ore overlay visualprospecting.key.togglefluid.name=Toggle fluid overlay From b1a052028aad5b1104ef75398ff7b05ceba46f44 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sat, 10 Feb 2024 10:31:52 +0100 Subject: [PATCH 044/132] update --- dependencies.gradle | 6 +++--- gradle.properties | 9 +++++---- settings.gradle | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index adaa9dba..aec8ec54 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,13 +1,13 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.41:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.62:dev') api('curse.maven:journeymap-32274:4500659') devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.2.0:dev') compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.1.0:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.9.4:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.9.9:dev') {transitive = false} compileOnly(deobfCurse('xaeros-minimap-263420:4905582')) compileOnly(deobfCurse('xaeros-world-map-317780:4905612')) @@ -15,5 +15,5 @@ dependencies { // For debugging runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.8.0:dev') - runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.11:dev') + runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.20:dev') } diff --git a/gradle.properties b/gradle.properties index 64b98b5d..7d268d70 100644 --- a/gradle.properties +++ b/gradle.properties @@ -33,7 +33,7 @@ channel = stable mappingsVersion = 12 # Defines other MCP mappings for dependency deobfuscation. -remoteMappings = https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/ +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. @@ -61,6 +61,9 @@ 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"; @@ -123,7 +126,7 @@ includeWellKnownRepositories = true usesMavenPublishing = true # Maven repository to publish the mod to. -# mavenPublishUrl = https://nexus.gtnewhorizons.com/repository/releases/ +# 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. # @@ -187,5 +190,3 @@ curseForgeRelations = # This is meant to be set in $HOME/.gradle/gradle.properties. # ideaCheckSpotlessOnBuild = true -# Non-GTNH properties -gradleTokenGroupName = diff --git a/settings.gradle b/settings.gradle index e8946ada..b9c57a02 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.8' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.12' } From 30ad316b8ef6f3221a78b760b8f86535d15596e1 Mon Sep 17 00:00:00 2001 From: Lyfts <127234178+Lyfts@users.noreply.github.com> Date: Wed, 14 Feb 2024 18:49:49 +0100 Subject: [PATCH 045/132] allow layers to do actions outside rendered drawsteps (#43) --- .../render/WaypointProviderLayerRenderer.java | 9 ++++++++ .../model/layers/WaypointProviderManager.java | 6 ++++++ .../late/journeymap/FullscreenMixin.java | 21 ++++++++++++------- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java index 3b30e061..147b15dc 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java @@ -10,6 +10,8 @@ import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; +import journeymap.client.model.BlockCoordIntPair; + public abstract class WaypointProviderLayerRenderer extends LayerRenderer { private final WaypointProviderManager manager; @@ -68,6 +70,13 @@ public boolean onMouseAction(boolean isDoubleClick) { return false; } + public boolean onMouseActionOutsideLayer(boolean isDoubleClick, BlockCoordIntPair blockCoord) { + if (isLayerActive() && isDoubleClick) { + return manager.doActionOutsideLayer(blockCoord); + } + return false; + } + public List getTextTooltip() { if (hoveredDrawStep != null) { return hoveredDrawStep.getTooltip(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java index 99e963f2..b2a594be 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java @@ -11,6 +11,8 @@ import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; import com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager; +import journeymap.client.model.BlockCoordIntPair; + public abstract class WaypointProviderManager extends LayerManager { private List visibleElements = new ArrayList<>(); @@ -38,6 +40,10 @@ public boolean hasActiveWaypoint() { return activeWaypoint != null; } + public boolean doActionOutsideLayer(BlockCoordIntPair blockCoord) { + return false; + } + public void registerWaypointManager(SupportedMods map, WaypointManager waypointManager) { waypointManagers.put(map, waypointManager); } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java index b49edc51..1be92666 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java @@ -272,9 +272,9 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { final int scaledMouseX = mx * mc.displayWidth / width; final int scaledMouseY = my * mc.displayHeight / height; final double blockSize = Math.pow(2.0D, gridRenderer.getZoom()); - if (!visualprospecting$onMapClicked(mouseButton, scaledMouseX, scaledMouseY, blockSize)) { - BlockCoordIntPair blockCoord = gridRenderer - .getBlockUnderMouse(Mouse.getEventX(), Mouse.getEventY(), mc.displayWidth, mc.displayHeight); + BlockCoordIntPair blockCoord = gridRenderer + .getBlockUnderMouse(Mouse.getEventX(), Mouse.getEventY(), mc.displayWidth, mc.displayHeight); + if (!visualprospecting$onMapClicked(mouseButton, scaledMouseX, scaledMouseY, blockSize, blockCoord)) { layerDelegate.onMouseClicked( mc, Mouse.getEventX(), @@ -287,7 +287,8 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { } } - private boolean visualprospecting$onMapClicked(int mouseButton, int mouseX, int mouseY, double blockSize) { + private boolean visualprospecting$onMapClicked(int mouseButton, int mouseX, int mouseY, double blockSize, + BlockCoordIntPair blockCoord) { final long timestamp = System.currentTimeMillis(); final boolean isDoubleClick = mouseX == oldMouseX && mouseY == oldMouseY && timestamp - timeLastClick < 500; oldMouseX = mouseX; @@ -297,12 +298,16 @@ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { return false; } boolean layerHit = false; + boolean clickOutside = false; for (LayerRenderer layer : JourneyMapState.instance.renderers) { - if (layer instanceof WaypointProviderLayerRenderer) { - ((WaypointProviderLayerRenderer) layer).onMouseMove(mouseX, mouseY); - layerHit |= ((WaypointProviderLayerRenderer) layer).onMouseAction(isDoubleClick); + if (layer instanceof WaypointProviderLayerRenderer wpLayerRender) { + wpLayerRender.onMouseMove(mouseX, mouseY); + layerHit |= wpLayerRender.onMouseAction(isDoubleClick); + if (!layerHit) { + clickOutside |= wpLayerRender.onMouseActionOutsideLayer(isDoubleClick, blockCoord); + } } } - return layerHit; + return layerHit || clickOutside; } } From 8cfc46e936f6367966117f0161776222ee07a84b Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Wed, 14 Feb 2024 22:13:55 +0100 Subject: [PATCH 046/132] update --- dependencies.gradle | 4 ++-- settings.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index aec8ec54..a75f507f 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,13 +1,13 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.62:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.64:dev') api('curse.maven:journeymap-32274:4500659') devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.2.0:dev') compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.1.0:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.9.9:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.9.10:dev') {transitive = false} compileOnly(deobfCurse('xaeros-minimap-263420:4905582')) compileOnly(deobfCurse('xaeros-world-map-317780:4905612')) diff --git a/settings.gradle b/settings.gradle index b9c57a02..16a5b4ca 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.12' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.14' } From 7e639c69afb3039f448f041802c91eaa97898e29 Mon Sep 17 00:00:00 2001 From: chochem <40274384+chochem@users.noreply.github.com> Date: Sun, 21 Apr 2024 12:45:02 +0100 Subject: [PATCH 047/132] Fix mytryl and quantium vein names (#45) * fix name * also fix quantium vein --- src/main/resources/assets/gregtech/lang/en_US.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/gregtech/lang/en_US.lang b/src/main/resources/assets/gregtech/lang/en_US.lang index 9315188b..0d8c5d05 100644 --- a/src/main/resources/assets/gregtech/lang/en_US.lang +++ b/src/main/resources/assets/gregtech/lang/en_US.lang @@ -48,9 +48,9 @@ ore.mix.osmium=Osmium ore.mix.saltpeterelectrotine=Electrotine ore.mix.desh=Desh ore.mix.draconium=Draconium -ore.mix.quantium=Quantum +ore.mix.quantium=Quantium ore.mix.callistoice=Callisto Ice -ore.mix.mytryl=Mithril +ore.mix.mytryl=Mytryl ore.mix.ledox=Ledox ore.mix.oriharukon=Oriharukon ore.mix.blackplutonium=Black Plutonium From cb91f825a25be3135d27b4539d32ea4f55dd93bd Mon Sep 17 00:00:00 2001 From: ah-OOG-ah <75745146+ah-OOG-ah@users.noreply.github.com> Date: Mon, 22 Apr 2024 06:57:09 -0400 Subject: [PATCH 048/132] Switch to deobf-modrinth maven for JM dep (#44) --- dependencies.gradle | 10 ++-- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- .../late/journeymap/FullscreenMixin.java | 50 +++++++++++-------- 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index a75f507f..13eb5a28 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,19 +1,19 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.64:dev') - api('curse.maven:journeymap-32274:4500659') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.155:dev') + api(rfg.deobf('maven.modrinth:journeymap:5.2.3')) devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.2.0:dev') compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.1.0:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.9.10:dev') {transitive = false} + compileOnly('com.github.GTNewHorizons:bartworks:0.9.21:dev') {transitive = false} compileOnly(deobfCurse('xaeros-minimap-263420:4905582')) compileOnly(deobfCurse('xaeros-world-map-317780:4905612')) compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) // For debugging - runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.8.0:dev') - runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.20:dev') + api('com.github.GTNewHorizons:DetravScannerMod:1.8.0:dev') + runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.35:dev') } diff --git a/gradle.properties b/gradle.properties index 7d268d70..b38f6bcf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -117,7 +117,7 @@ minimizeShadowedDependencies = true # If disabled, won't rename the shadowed classes. relocateShadowedDependencies = true -# Adds the GTNH maven, CurseMaven, IC2/Player maven, and some more well-known 1.7.10 repositories. +# Adds the GTNH maven, CurseMaven, Modrinth, and some more well-known 1.7.10 repositories. includeWellKnownRepositories = true # Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a80b22ce..b82aa23a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index 16a5b4ca..378da589 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.14' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.21' } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java index 1be92666..1cc9af4c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java @@ -12,6 +12,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -47,65 +48,71 @@ @Mixin(value = Fullscreen.class, remap = false) public abstract class FullscreenMixin extends JmUI { + @Unique private int oldMouseX = 0; + @Unique private int oldMouseY = 0; + @Unique private long timeLastClick = 0; @Final - @Shadow(remap = false) + @Shadow static GridRenderer gridRenderer; - @Shadow(remap = false) + @Shadow ThemeToolbar mapTypeToolbar; - @Shadow(remap = false) + @Shadow ThemeButton buttonCaves; - @Shadow(remap = false) + @Shadow ThemeButton buttonNight; - @Shadow(remap = false) + @Shadow ThemeButton buttonDay; - @Shadow(remap = false) + @Shadow StatTimer drawScreenTimer; - @Shadow(remap = false) + @Shadow() MapChat chat; @Final - @Shadow(remap = false) + @Shadow LayerDelegate layerDelegate; - @Shadow(remap = false) + @Shadow boolean firstLayoutPass; - @Shadow(remap = false) + @Shadow int mx; - @Shadow(remap = false) + @Shadow int my; public FullscreenMixin() { super(""); } - @Inject(method = "*", at = @At("RETURN"), remap = false, require = 1) + @Inject(method = "*", at = @At("RETURN"), require = 1) private void visualprospecting$init(CallbackInfo ci) { MapState.instance.layers.forEach(LayerManager::forceRefresh); } - @Shadow(remap = false) + @Shadow private int getMapFontScale() { throw new IllegalStateException("Mixin failed to shadow getMapFontScale()"); } - @Shadow(remap = false) + @Shadow void drawMap() { throw new IllegalStateException("Mixin failed to shadow drawMap()"); } - @Inject(method = "*", at = @At("RETURN"), remap = false, require = 1) + @Shadow + public abstract void drawBackground(int layer); + + @Inject(method = "*", at = @At("RETURN"), require = 1) private void visualprospecting$onConstructed(CallbackInfo ci) { MapState.instance.layers.forEach(LayerManager::onOpenMap); } @@ -151,7 +158,6 @@ void drawMap() { value = "FIELD", target = "Ljourneymap/client/ui/fullscreen/Fullscreen;mapTypeToolbar:Ljourneymap/client/ui/theme/ThemeToolbar;", opcode = Opcodes.PUTFIELD), - remap = false, require = 1) private void visualprospecting$OnCreateMapTypeToolbar(Fullscreen owner, ThemeToolbar value) { final Theme theme = ThemeFileHandler.getCurrentTheme(); @@ -178,9 +184,9 @@ void drawMap() { } @Override - public void func_73863_a(int width, int height, float f) { + public void drawScreen(int width, int height, float f) { try { - func_146278_c(0); + drawBackground(0); drawMap(); drawScreenTimer.start(); layoutButtons(); @@ -190,7 +196,7 @@ public void func_73863_a(int width, int height, float f) { firstLayoutPass = false; } else { for (int k = 0; k < buttonList.size(); ++k) { - GuiButton guibutton = (GuiButton) buttonList.get(k); + GuiButton guibutton = buttonList.get(k); guibutton.drawButton(mc, width, height); if (tooltip == null && guibutton instanceof Button) { Button button = (Button) guibutton; @@ -222,7 +228,7 @@ public void func_73863_a(int width, int height, float f) { } if (chat != null) { - chat.func_73863_a(width, height, f); + chat.drawScreen(width, height, f); } if (tooltip != null && !tooltip.isEmpty()) { @@ -249,7 +255,7 @@ public void func_73863_a(int width, int height, float f) { } } - @Inject(method = "func_73869_a", at = @At(value = "HEAD"), remap = false, require = 1, cancellable = true) + @Inject(method = "keyTyped", at = @At(value = "HEAD"), remap = true, require = 1, cancellable = true) private void visualprospecting$onKeyPress(CallbackInfo ci) { if ((chat == null || chat.isHidden()) && Constants.isPressed(VP.keyAction)) { for (LayerRenderer layer : JourneyMapState.instance.renderers) { @@ -264,7 +270,7 @@ public void func_73863_a(int width, int height, float f) { @Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { if (chat != null && !chat.isHidden()) { - chat.func_73864_a(mouseX, mouseY, mouseButton); + chat.mouseClicked(mouseX, mouseY, mouseButton); } super.mouseClicked(mouseX, mouseY, mouseButton); From f975f731284c74aa6654bf9890162cb2782c7acc Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Mon, 22 Apr 2024 13:00:57 +0200 Subject: [PATCH 049/132] update --- gradle/wrapper/gradle-wrapper.jar | Bin 43462 -> 43453 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917707c1f8861d8cb53dd15194d4248596..e6441136f3d4ba8a0da8d277868979cfbc8ad796 100644 GIT binary patch delta 34118 zcmY(qRX`kF)3u#IAjsf0xCD212@LM;?(PINyAue(f;$XO2=4Cg1P$=#e%|lo zKk1`B>Q#GH)wNd-&cJofz}3=WfYndTeo)CyX{fOHsQjGa<{e=jamMNwjdatD={CN3>GNchOE9OGPIqr)3v>RcKWR3Z zF-guIMjE2UF0Wqk1)21791y#}ciBI*bAenY*BMW_)AeSuM5}vz_~`+1i!Lo?XAEq{TlK5-efNFgHr6o zD>^vB&%3ZGEWMS>`?tu!@66|uiDvS5`?bF=gIq3rkK(j<_TybyoaDHg8;Y#`;>tXI z=tXo~e9{U!*hqTe#nZjW4z0mP8A9UUv1}C#R*@yu9G3k;`Me0-BA2&Aw6f`{Ozan2 z8c8Cs#dA-7V)ZwcGKH}jW!Ja&VaUc@mu5a@CObzNot?b{f+~+212lwF;!QKI16FDS zodx>XN$sk9;t;)maB^s6sr^L32EbMV(uvW%or=|0@U6cUkE`_!<=LHLlRGJx@gQI=B(nn z-GEjDE}*8>3U$n(t^(b^C$qSTI;}6q&ypp?-2rGpqg7b}pyT zOARu2x>0HB{&D(d3sp`+}ka+Pca5glh|c=M)Ujn_$ly^X6&u z%Q4Y*LtB_>i6(YR!?{Os-(^J`(70lZ&Hp1I^?t@~SFL1!m0x6j|NM!-JTDk)%Q^R< z@e?23FD&9_W{Bgtr&CG&*Oer3Z(Bu2EbV3T9FeQ|-vo5pwzwQ%g&=zFS7b{n6T2ZQ z*!H(=z<{D9@c`KmHO&DbUIzpg`+r5207}4D=_P$ONIc5lsFgn)UB-oUE#{r+|uHc^hzv_df zV`n8&qry%jXQ33}Bjqcim~BY1?KZ}x453Oh7G@fA(}+m(f$)TY%7n=MeLi{jJ7LMB zt(mE*vFnep?YpkT_&WPV9*f>uSi#n#@STJmV&SLZnlLsWYI@y+Bs=gzcqche=&cBH2WL)dkR!a95*Ri)JH_4c*- zl4pPLl^as5_y&6RDE@@7342DNyF&GLJez#eMJjI}#pZN{Y8io{l*D+|f_Y&RQPia@ zNDL;SBERA|B#cjlNC@VU{2csOvB8$HzU$01Q?y)KEfos>W46VMh>P~oQC8k=26-Ku)@C|n^zDP!hO}Y z_tF}0@*Ds!JMt>?4y|l3?`v#5*oV-=vL7}zehMON^=s1%q+n=^^Z{^mTs7}*->#YL z)x-~SWE{e?YCarwU$=cS>VzmUh?Q&7?#Xrcce+jeZ|%0!l|H_=D_`77hBfd4Zqk&! zq-Dnt_?5*$Wsw8zGd@?woEtfYZ2|9L8b>TO6>oMh%`B7iBb)-aCefM~q|S2Cc0t9T zlu-ZXmM0wd$!gd-dTtik{bqyx32%f;`XUvbUWWJmpHfk8^PQIEsByJm+@+-aj4J#D z4#Br3pO6z1eIC>X^yKk|PeVwX_4B+IYJyJyc3B`4 zPrM#raacGIzVOexcVB;fcsxS=s1e&V;Xe$tw&KQ`YaCkHTKe*Al#velxV{3wxx}`7@isG zp6{+s)CG%HF#JBAQ_jM%zCX5X;J%-*%&jVI?6KpYyzGbq7qf;&hFprh?E5Wyo=bZ) z8YNycvMNGp1836!-?nihm6jI`^C`EeGryoNZO1AFTQhzFJOA%Q{X(sMYlzABt!&f{ zoDENSuoJQIg5Q#@BUsNJX2h>jkdx4<+ipUymWKFr;w+s>$laIIkfP6nU}r+?J9bZg zUIxz>RX$kX=C4m(zh-Eg$BsJ4OL&_J38PbHW&7JmR27%efAkqqdvf)Am)VF$+U3WR z-E#I9H6^)zHLKCs7|Zs<7Bo9VCS3@CDQ;{UTczoEprCKL3ZZW!ffmZFkcWU-V|_M2 zUA9~8tE9<5`59W-UgUmDFp11YlORl3mS3*2#ZHjv{*-1#uMV_oVTy{PY(}AqZv#wF zJVks)%N6LaHF$$<6p8S8Lqn+5&t}DmLKiC~lE{jPZ39oj{wR&fe*LX-z0m}9ZnZ{U z>3-5Bh{KKN^n5i!M79Aw5eY=`6fG#aW1_ZG;fw7JM69qk^*(rmO{|Z6rXy?l=K=#_ zE-zd*P|(sskasO(cZ5L~_{Mz&Y@@@Q)5_8l<6vB$@226O+pDvkFaK8b>%2 zfMtgJ@+cN@w>3)(_uR;s8$sGONbYvoEZ3-)zZk4!`tNzd<0lwt{RAgplo*f@Z)uO` zzd`ljSqKfHJOLxya4_}T`k5Ok1Mpo#MSqf~&ia3uIy{zyuaF}pV6 z)@$ZG5LYh8Gge*LqM_|GiT1*J*uKes=Oku_gMj&;FS`*sfpM+ygN&yOla-^WtIU#$ zuw(_-?DS?6DY7IbON7J)p^IM?N>7x^3)(7wR4PZJu(teex%l>zKAUSNL@~{czc}bR z)I{XzXqZBU3a;7UQ~PvAx8g-3q-9AEd}1JrlfS8NdPc+!=HJ6Bs( zCG!0;e0z-22(Uzw>hkEmC&xj?{0p|kc zM}MMXCF%RLLa#5jG`+}{pDL3M&|%3BlwOi?dq!)KUdv5__zR>u^o|QkYiqr(m3HxF z6J*DyN#Jpooc$ok=b7{UAVM@nwGsr6kozSddwulf5g1{B=0#2)zv!zLXQup^BZ4sv*sEsn)+MA?t zEL)}3*R?4(J~CpeSJPM!oZ~8;8s_=@6o`IA%{aEA9!GELRvOuncE`s7sH91 zmF=+T!Q6%){?lJn3`5}oW31(^Of|$r%`~gT{eimT7R~*Mg@x+tWM3KE>=Q>nkMG$U za7r>Yz2LEaA|PsMafvJ(Y>Xzha?=>#B!sYfVob4k5Orb$INFdL@U0(J8Hj&kgWUlO zPm+R07E+oq^4f4#HvEPANGWLL_!uF{nkHYE&BCH%l1FL_r(Nj@M)*VOD5S42Gk-yT z^23oAMvpA57H(fkDGMx86Z}rtQhR^L!T2iS!788E z+^${W1V}J_NwdwdxpXAW8}#6o1(Uu|vhJvubFvQIH1bDl4J4iDJ+181KuDuHwvM?` z%1@Tnq+7>p{O&p=@QT}4wT;HCb@i)&7int<0#bj8j0sfN3s6|a(l7Bj#7$hxX@~iP z1HF8RFH}irky&eCN4T94VyKqGywEGY{Gt0Xl-`|dOU&{Q;Ao;sL>C6N zXx1y^RZSaL-pG|JN;j9ADjo^XR}gce#seM4QB1?S`L*aB&QlbBIRegMnTkTCks7JU z<0(b+^Q?HN1&$M1l&I@>HMS;!&bb()a}hhJzsmB?I`poqTrSoO>m_JE5U4=?o;OV6 zBZjt;*%1P>%2{UL=;a4(aI>PRk|mr&F^=v6Fr&xMj8fRCXE5Z2qdre&;$_RNid5!S zm^XiLK25G6_j4dWkFqjtU7#s;b8h?BYFxV?OE?c~&ME`n`$ix_`mb^AWr+{M9{^^Rl;~KREplwy2q;&xe zUR0SjHzKVYzuqQ84w$NKVPGVHL_4I)Uw<$uL2-Ml#+5r2X{LLqc*p13{;w#E*Kwb*1D|v?e;(<>vl@VjnFB^^Y;;b3 z=R@(uRj6D}-h6CCOxAdqn~_SG=bN%^9(Ac?zfRkO5x2VM0+@_qk?MDXvf=@q_* z3IM@)er6-OXyE1Z4sU3{8$Y$>8NcnU-nkyWD&2ZaqX1JF_JYL8y}>@V8A5%lX#U3E zet5PJM`z79q9u5v(OE~{by|Jzlw2<0h`hKpOefhw=fgLTY9M8h+?37k@TWpzAb2Fc zQMf^aVf!yXlK?@5d-re}!fuAWu0t57ZKSSacwRGJ$0uC}ZgxCTw>cjRk*xCt%w&hh zoeiIgdz__&u~8s|_TZsGvJ7sjvBW<(C@}Y%#l_ID2&C`0;Eg2Z+pk;IK}4T@W6X5H z`s?ayU-iF+aNr5--T-^~K~p;}D(*GWOAYDV9JEw!w8ZYzS3;W6*_`#aZw&9J ziXhBKU3~zd$kKzCAP-=t&cFDeQR*_e*(excIUxKuD@;-twSlP6>wWQU)$|H3Cy+`= z-#7OW!ZlYzZxkdQpfqVDFU3V2B_-eJS)Fi{fLtRz!K{~7TR~XilNCu=Z;{GIf9KYz zf3h=Jo+1#_s>z$lc~e)l93h&RqW1VHYN;Yjwg#Qi0yzjN^M4cuL>Ew`_-_wRhi*!f zLK6vTpgo^Bz?8AsU%#n}^EGigkG3FXen3M;hm#C38P@Zs4{!QZPAU=m7ZV&xKI_HWNt90Ef zxClm)ZY?S|n**2cNYy-xBlLAVZ=~+!|7y`(fh+M$#4zl&T^gV8ZaG(RBD!`3?9xcK zp2+aD(T%QIgrLx5au&TjG1AazI;`8m{K7^!@m>uGCSR;Ut{&?t%3AsF{>0Cm(Kf)2 z?4?|J+!BUg*P~C{?mwPQ#)gDMmro20YVNsVx5oWQMkzQ? zsQ%Y>%7_wkJqnSMuZjB9lBM(o zWut|B7w48cn}4buUBbdPBW_J@H7g=szrKEpb|aE>!4rLm+sO9K%iI75y~2HkUo^iw zJ3se$8$|W>3}?JU@3h@M^HEFNmvCp|+$-0M?RQ8SMoZ@38%!tz8f8-Ptb@106heiJ z^Bx!`0=Im z1!NUhO=9ICM*+||b3a7w*Y#5*Q}K^ar+oMMtekF0JnO>hzHqZKH0&PZ^^M(j;vwf_ z@^|VMBpcw8;4E-9J{(u7sHSyZpQbS&N{VQ%ZCh{c1UA5;?R} z+52*X_tkDQ(s~#-6`z4|Y}3N#a&dgP4S_^tsV=oZr4A1 zaSoPN1czE(UIBrC_r$0HM?RyBGe#lTBL4~JW#A`P^#0wuK)C-2$B6TvMi@@%K@JAT_IB^T7Zfqc8?{wHcSVG_?{(wUG%zhCm=%qP~EqeqKI$9UivF zv+5IUOs|%@ypo6b+i=xsZ=^G1yeWe)z6IX-EC`F=(|_GCNbHbNp(CZ*lpSu5n`FRA zhnrc4w+Vh?r>her@Ba_jv0Omp#-H7avZb=j_A~B%V0&FNi#!S8cwn0(Gg-Gi_LMI{ zCg=g@m{W@u?GQ|yp^yENd;M=W2s-k7Gw2Z(tsD5fTGF{iZ%Ccgjy6O!AB4x z%&=6jB7^}pyftW2YQpOY1w@%wZy%}-l0qJlOSKZXnN2wo3|hujU+-U~blRF!^;Tan z0w;Srh0|Q~6*tXf!5-rCD)OYE(%S|^WTpa1KHtpHZ{!;KdcM^#g8Z^+LkbiBHt85m z;2xv#83lWB(kplfgqv@ZNDcHizwi4-8+WHA$U-HBNqsZ`hKcUI3zV3d1ngJP-AMRET*A{> zb2A>Fk|L|WYV;Eu4>{a6ESi2r3aZL7x}eRc?cf|~bP)6b7%BnsR{Sa>K^0obn?yiJ zCVvaZ&;d_6WEk${F1SN0{_`(#TuOOH1as&#&xN~+JDzX(D-WU_nLEI}T_VaeLA=bc zl_UZS$nu#C1yH}YV>N2^9^zye{rDrn(rS99>Fh&jtNY7PP15q%g=RGnxACdCov47= zwf^9zfJaL{y`R#~tvVL#*<`=`Qe zj_@Me$6sIK=LMFbBrJps7vdaf_HeX?eC+P^{AgSvbEn?n<}NDWiQGQG4^ZOc|GskK z$Ve2_n8gQ-KZ=s(f`_X!+vM5)4+QmOP()2Fe#IL2toZBf+)8gTVgDSTN1CkP<}!j7 z0SEl>PBg{MnPHkj4wj$mZ?m5x!1ePVEYI(L_sb0OZ*=M%yQb?L{UL(2_*CTVbRxBe z@{)COwTK1}!*CK0Vi4~AB;HF(MmQf|dsoy(eiQ>WTKcEQlnKOri5xYsqi61Y=I4kzAjn5~{IWrz_l))|Ls zvq7xgQs?Xx@`N?f7+3XKLyD~6DRJw*uj*j?yvT3}a;(j_?YOe%hUFcPGWRVBXzpMJ zM43g6DLFqS9tcTLSg=^&N-y0dXL816v&-nqC0iXdg7kV|PY+js`F8dm z2PuHw&k+8*&9SPQ6f!^5q0&AH(i+z3I7a?8O+S5`g)>}fG|BM&ZnmL;rk)|u{1!aZ zEZHpAMmK_v$GbrrWNP|^2^s*!0waLW=-h5PZa-4jWYUt(Hr@EA(m3Mc3^uDxwt-me^55FMA9^>hpp26MhqjLg#^Y7OIJ5%ZLdNx&uDgIIqc zZRZl|n6TyV)0^DDyVtw*jlWkDY&Gw4q;k!UwqSL6&sW$B*5Rc?&)dt29bDB*b6IBY z6SY6Unsf6AOQdEf=P1inu6(6hVZ0~v-<>;LAlcQ2u?wRWj5VczBT$Op#8IhppP-1t zfz5H59Aa~yh7EN;BXJsLyjkjqARS5iIhDVPj<=4AJb}m6M@n{xYj3qsR*Q8;hVxDyC4vLI;;?^eENOb5QARj#nII5l$MtBCI@5u~(ylFi$ zw6-+$$XQ}Ca>FWT>q{k)g{Ml(Yv=6aDfe?m|5|kbGtWS}fKWI+})F6`x@||0oJ^(g|+xi zqlPdy5;`g*i*C=Q(aGeDw!eQg&w>UUj^{o?PrlFI=34qAU2u@BgwrBiaM8zoDTFJ< zh7nWpv>dr?q;4ZA?}V}|7qWz4W?6#S&m>hs4IwvCBe@-C>+oohsQZ^JC*RfDRm!?y zS4$7oxcI|##ga*y5hV>J4a%HHl^t$pjY%caL%-FlRb<$A$E!ws?8hf0@(4HdgQ!@> zds{&g$ocr9W4I84TMa9-(&^_B*&R%^=@?Ntxi|Ejnh;z=!|uVj&3fiTngDPg=0=P2 zB)3#%HetD84ayj??qrxsd9nqrBem(8^_u_UY{1@R_vK-0H9N7lBX5K(^O2=0#TtUUGSz{ z%g>qU8#a$DyZ~EMa|8*@`GOhCW3%DN%xuS91T7~iXRr)SG`%=Lfu%U~Z_`1b=lSi?qpD4$vLh$?HU6t0MydaowUpb zQr{>_${AMesCEffZo`}K0^~x>RY_ZIG{(r39MP>@=aiM@C;K)jUcfQV8#?SDvq>9D zI{XeKM%$$XP5`7p3K0T}x;qn)VMo>2t}Ib(6zui;k}<<~KibAb%p)**e>ln<=qyWU zrRDy|UXFi9y~PdEFIAXejLA{K)6<)Q`?;Q5!KsuEw({!#Rl8*5_F{TP?u|5(Hijv( ztAA^I5+$A*+*e0V0R~fc{ET-RAS3suZ}TRk3r)xqj~g_hxB`qIK5z(5wxYboz%46G zq{izIz^5xW1Vq#%lhXaZL&)FJWp0VZNO%2&ADd?+J%K$fM#T_Eke1{dQsx48dUPUY zLS+DWMJeUSjYL453f@HpRGU6Dv)rw+-c6xB>(=p4U%}_p>z^I@Ow9`nkUG21?cMIh9}hN?R-d)*6%pr6d@mcb*ixr7 z)>Lo<&2F}~>WT1ybm^9UO{6P9;m+fU^06_$o9gBWL9_}EMZFD=rLJ~&e?fhDnJNBI zKM=-WR6g7HY5tHf=V~6~QIQ~rakNvcsamU8m28YE=z8+G7K=h%)l6k zmCpiDInKL6*e#)#Pt;ANmjf`8h-nEt&d}(SBZMI_A{BI#ck-_V7nx)K9_D9K-p@?Zh81#b@{wS?wCcJ%og)8RF*-0z+~)6f#T` zWqF7_CBcnn=S-1QykC*F0YTsKMVG49BuKQBH%WuDkEy%E?*x&tt%0m>>5^HCOq|ux zuvFB)JPR-W|%$24eEC^AtG3Gp4qdK%pjRijF5Sg3X}uaKEE z-L5p5aVR!NTM8T`4|2QA@hXiLXRcJveWZ%YeFfV%mO5q#($TJ`*U>hicS+CMj%Ip# zivoL;dd*araeJK9EA<(tihD50FHWbITBgF9E<33A+eMr2;cgI3Gg6<-2o|_g9|> zv5}i932( zYfTE9?4#nQhP@a|zm#9FST2 z!y+p3B;p>KkUzH!K;GkBW}bWssz)9b>Ulg^)EDca;jDl+q=243BddS$hY^fC6lbpM z(q_bo4V8~eVeA?0LFD6ZtKcmOH^75#q$Eo%a&qvE8Zsqg=$p}u^|>DSWUP5i{6)LAYF4E2DfGZuMJ zMwxxmkxQf}Q$V3&2w|$`9_SQS^2NVbTHh;atB>=A%!}k-f4*i$X8m}Ni^ppZXk5_oYF>Gq(& z0wy{LjJOu}69}~#UFPc;$7ka+=gl(FZCy4xEsk);+he>Nnl>hb5Ud-lj!CNicgd^2 z_Qgr_-&S7*#nLAI7r()P$`x~fy)+y=W~6aNh_humoZr7MWGSWJPLk}$#w_1n%(@? z3FnHf1lbxKJbQ9c&i<$(wd{tUTX6DAKs@cXIOBv~!9i{wD@*|kwfX~sjKASrNFGvN zrFc=!0Bb^OhR2f`%hrp2ibv#KUxl)Np1aixD9{^o=)*U%n%rTHX?FSWL^UGpHpY@7 z74U}KoIRwxI#>)Pn4($A`nw1%-D}`sGRZD8Z#lF$6 zOeA5)+W2qvA%m^|$WluUU-O+KtMqd;Pd58?qZj})MbxYGO<{z9U&t4D{S2G>e+J9K ztFZ?}ya>SVOLp9hpW)}G%kTrg*KXXXsLkGdgHb+R-ZXqdkdQC0_)`?6mqo8(EU#d( zy;u&aVPe6C=YgCRPV!mJ6R6kdY*`e+VGM~`VtC>{k27!9vAZT)x2~AiX5|m1Rq}_= z;A9LX^nd$l-9&2%4s~p5r6ad-siV`HtxKF}l&xGSYJmP=z!?Mlwmwef$EQq~7;#OE z)U5eS6dB~~1pkj#9(}T3j!((8Uf%!W49FfUAozijoxInUE7z`~U3Y^}xc3xp){#9D z<^Tz2xw}@o@fdUZ@hnW#dX6gDOj4R8dV}Dw`u!h@*K)-NrxT8%2`T}EvOImNF_N1S zy?uo6_ZS>Qga4Xme3j#aX+1qdFFE{NT0Wfusa$^;eL5xGE_66!5_N8!Z~jCAH2=${ z*goHjl|z|kbmIE{cl-PloSTtD+2=CDm~ZHRgXJ8~1(g4W=1c3=2eF#3tah7ho`zm4 z05P&?nyqq$nC?iJ-nK_iBo=u5l#|Ka3H7{UZ&O`~t-=triw=SE7ynzMAE{Mv-{7E_ zViZtA(0^wD{iCCcg@c{54Ro@U5p1QZq_XlEGtdBAQ9@nT?(zLO0#)q55G8_Ug~Xnu zR-^1~hp|cy&52iogG@o?-^AD8Jb^;@&Ea5jEicDlze6%>?u$-eE};bQ`T6@(bED0J zKYtdc?%9*<<$2LCBzVx9CA4YV|q-qg*-{yQ;|0=KIgI6~z0DKTtajw2Oms3L zn{C%{P`duw!(F@*P)lFy11|Z&x`E2<=$Ln38>UR~z6~za(3r;45kQK_^QTX%!s zNzoIFFH8|Y>YVrUL5#mgA-Jh>j7)n)5}iVM4%_@^GSwEIBA2g-;43* z*)i7u*xc8jo2z8&=8t7qo|B-rsGw)b8UXnu`RgE4u!(J8yIJi(5m3~aYsADcfZ!GG zzqa7p=sg`V_KjiqI*LA-=T;uiNRB;BZZ)~88 z`C%p8%hIev2rxS12@doqsrjgMg3{A&N8A?%Ui5vSHh7!iC^ltF&HqG~;=16=h0{ygy^@HxixUb1XYcR36SB}}o3nxu z_IpEmGh_CK<+sUh@2zbK9MqO!S5cao=8LSQg0Zv4?ju%ww^mvc0WU$q@!oo#2bv24 z+?c}14L2vlDn%Y0!t*z=$*a!`*|uAVu&NO!z_arim$=btpUPR5XGCG0U3YU`v>yMr z^zmTdcEa!APX zYF>^Q-TP11;{VgtMqC}7>B^2gN-3KYl33gS-p%f!X<_Hr?`rG8{jb9jmuQA9U;BeG zHj6Pk(UB5c6zwX%SNi*Py*)gk^?+729$bAN-EUd*RKN7{CM4`Q65a1qF*-QWACA&m zrT)B(M}yih{2r!Tiv5Y&O&=H_OtaHUz96Npo_k0eN|!*s2mLe!Zkuv>^E8Xa43ZwH zOI058AZznYGrRJ+`*GmZzMi6yliFmGMge6^j?|PN%ARns!Eg$ufpcLc#1Ns!1@1 zvC7N8M$mRgnixwEtX{ypBS^n`k@t2cCh#_6L6WtQb8E~*Vu+Rr)YsKZRX~hzLG*BE zaeU#LPo?RLm(Wzltk79Jd1Y$|6aWz1)wf1K1RtqS;qyQMy@H@B805vQ%wfSJB?m&&=^m4i* zYVH`zTTFbFtNFkAI`Khe4e^CdGZw;O0 zqkQe2|NG_y6D%h(|EZNf&77_!NU%0y={^E=*gKGQ=)LdKPM3zUlM@otH2X07Awv8o zY8Y7a1^&Yy%b%m{mNQ5sWNMTIq96Wtr>a(hL>Qi&F(ckgKkyvM0IH<_}v~Fv-GqDapig=3*ZMOx!%cYY)SKzo7ECyem z9Mj3C)tCYM?C9YIlt1?zTJXNOo&oVxu&uXKJs7i+j8p*Qvu2PAnY}b`KStdpi`trk ztAO}T8eOC%x)mu+4ps8sYZ=vYJp16SVWEEgQyFKSfWQ@O5id6GfL`|2<}hMXLPszS zgK>NWOoR zBRyKeUPevpqKKShD|MZ`R;~#PdNMB3LWjqFKNvH9k+;(`;-pyXM55?qaji#nl~K8m z_MifoM*W*X9CQiXAOH{cZcP0;Bn10E1)T@62Um>et2ci!J2$5-_HPy(AGif+BJpJ^ ziHWynC_%-NlrFY+(f7HyVvbDIM$5ci_i3?22ZkF>Y8RPBhgx-7k3M2>6m5R24C|~I z&RPh9xpMGzhN4bii*ryWaN^d(`0 zTOADlU)g`1p+SVMNLztd)c+;XjXox(VHQwqzu>FROvf0`s&|NEv26}(TAe;@=FpZq zaVs6mp>W0rM3Qg*6x5f_bPJd!6dQGmh?&v0rpBNfS$DW-{4L7#_~-eA@7<2BsZV=X zow){3aATmLZOQrs>uzDkXOD=IiX;Ue*B(^4RF%H zeaZ^*MWn4tBDj(wj114r(`)P96EHq4th-;tWiHhkp2rDlrklX}I@ib-nel0slFoQO zOeTc;Rh7sMIebO`1%u)=GlEj+7HU;c|Nj>2j)J-kpR)s3#+9AiB zd$hAk6;3pu9(GCR#)#>aCGPYq%r&i02$0L9=7AlIGYdlUO5%eH&M!ZWD&6^NBAj0Y9ZDcPg@r@8Y&-}e!aq0S(`}NuQ({;aigCPnq75U9cBH&Y7 ze)W0aD>muAepOKgm7uPg3Dz7G%)nEqTUm_&^^3(>+eEI;$ia`m>m0QHEkTt^=cx^JsBC68#H(3zc~Z$E9I)oSrF$3 zUClHXhMBZ|^1ikm3nL$Z@v|JRhud*IhOvx!6X<(YSX(9LG#yYuZeB{=7-MyPF;?_8 zy2i3iVKG2q!=JHN>~!#Bl{cwa6-yB@b<;8LSj}`f9pw7#x3yTD>C=>1S@H)~(n_K4 z2-yr{2?|1b#lS`qG@+823j;&UE5|2+EdU4nVw5=m>o_gj#K>>(*t=xI7{R)lJhLU{ z4IO6!x@1f$aDVIE@1a0lraN9!(j~_uGlks)!&davUFRNYHflp<|ENwAxsp~4Hun$Q z$w>@YzXp#VX~)ZP8`_b_sTg(Gt7?oXJW%^Pf0UW%YM+OGjKS}X`yO~{7WH6nX8S6Z ztl!5AnM2Lo*_}ZLvo%?iV;D2z>#qdpMx*xY2*GGlRzmHCom`VedAoR=(A1nO)Y>;5 zCK-~a;#g5yDgf7_phlkM@)C8s!xOu)N2UnQhif-v5kL$*t=X}L9EyBRq$V(sI{90> z=ghTPGswRVbTW@dS2H|)QYTY&I$ljbpNPTc_T|FEJkSW7MV!JM4I(ksRqQ8)V5>}v z2Sf^Z9_v;dKSp_orZm09jb8;C(vzFFJgoYuWRc|Tt_&3k({wPKiD|*m!+za$(l*!gNRo{xtmqjy1=kGzFkTH=Nc>EL@1Um0BiN1)wBO$i z6rG={bRcT|%A3s3xh!Bw?=L&_-X+6}L9i~xRj2}-)7fsoq0|;;PS%mcn%_#oV#kAp zGw^23c8_0~ ze}v9(p};6HM0+qF5^^>BBEI3d=2DW&O#|(;wg}?3?uO=w+{*)+^l_-gE zSw8GV=4_%U4*OU^hibDV38{Qb7P#Y8zh@BM9pEM_o2FuFc2LWrW2jRRB<+IE)G=Vx zuu?cp2-`hgqlsn|$nx@I%TC!`>bX^G00_oKboOGGXLgyLKXoo$^@L7v;GWqfUFw3< zekKMWo0LR;TaFY}Tt4!O$3MU@pqcw!0w0 zA}SnJ6Lb597|P5W8$OsEHTku2Kw9y4V=hx*K%iSn!#LW9W#~OiWf^dXEP$^2 zaok=UyGwy3GRp)bm6Gqr>8-4h@3=2`Eto2|JE6Sufh?%U6;ut1v1d@#EfcQP2chCt z+mB{Bk5~()7G>wM3KYf7Xh?LGbwg1uWLotmc_}Z_o;XOUDyfU?{9atAT$={v82^w9 z(MW$gINHt4xB3{bdbhRR%T}L?McK?!zkLK3(e>zKyei(yq%Nsijm~LV|9mll-XHavFcc$teX7v);H>=oN-+E_Q{c|! zp

    JV~-9AH}jxf6IF!PxrB9is{_9s@PYth^`pb%DkwghLdAyDREz(csf9)HcVRq z+2Vn~>{(S&_;bq_qA{v7XbU?yR7;~JrLfo;g$Lkm#ufO1P`QW_`zWW+4+7xzQZnO$ z5&GyJs4-VGb5MEDBc5=zxZh9xEVoY(|2yRv&!T7LAlIs@tw+4n?v1T8M>;hBv}2n) zcqi+>M*U@uY>4N3eDSAH2Rg@dsl!1py>kO39GMP#qOHipL~*cCac2_vH^6x@xmO|E zkWeyvl@P$2Iy*mCgVF+b{&|FY*5Ygi8237i)9YW#Fp& z?TJTQW+7U)xCE*`Nsx^yaiJ0KSW}}jc-ub)8Z8x(|K7G>`&l{Y&~W=q#^4Gf{}aJ%6kLXsmv6cr=Hi*uB`V26;dr4C$WrPnHO>g zg1@A%DvIWPDtXzll39kY6#%j;aN7grYJP9AlJgs3FnC?crv$wC7S4_Z?<_s0j;MmE z75yQGul2=bY%`l__1X3jxju2$Ws%hNv75ywfAqjgFO7wFsFDOW^)q2%VIF~WhwEW0 z45z^+r+}sJ{q+>X-w(}OiD(!*&cy4X&yM`!L0Fe+_RUfs@=J{AH#K~gArqT=#DcGE z!FwY(h&+&811rVCVoOuK)Z<-$EX zp`TzcUQC256@YWZ*GkE@P_et4D@qpM92fWA6c$MV=^qTu7&g)U?O~-fUR&xFqNiY1 zRd=|zUs_rmFZhKI|H}dcKhy%Okl(#y#QuMi81zsY56Y@757xBQqDNkd+XhLQhp2BB zBF^aJ__D676wLu|yYo6jNJNw^B+Ce;DYK!f$!dNs1*?D^97u^jKS++7S z5qE%zG#HY-SMUn^_yru=T6v`)CM%K<>_Z>tPe|js`c<|y7?qol&)C=>uLWkg5 zmzNcSAG_sL)E9or;i+O}tY^70@h7+=bG1;YDlX{<4zF_?{)K5B&?^tKZ6<$SD%@>F zY0cl2H7)%zKeDX%Eo7`ky^mzS)s;842cP{_;dzFuyd~Npb4u!bwkkhf8-^C2e3`q8>MuPhgiv0VxHxvrN9_`rJv&GX0fWz-L-Jg^B zrTsm>)-~j0F1sV=^V?UUi{L2cp%YwpvHwwLaSsCIrGI#({{QfbgDxLKsUC6w@m?y} zg?l=7aMX-RnMxvLn_4oSB|9t;)Qf2%m-GKo_07?N1l^ahJ+Wf8C>h5~=-o1BJzV@5HBTB-ACNpsHnGt6_ku37M z{vIEB^tR=--4SEg{jfF=gEogtGwi&A$mwk7E+SV$$ZuU}#F3Y7t}o{!w4LJh8v4PW%8HfUK@dta#l*z@w*9Xzz(i)r#WXi`r1D#oBPtNM7M?Hkq zhhS1)ea5(6VY45|)tCTr*@yc$^Zc!zQzsNXU?aRN6mh7zVu~i=qTrX^>de+f6HYfDsW@6PBlw0CsDBcOWUmt&st>Z zYNJEsRCP1#g0+Htb=wITvexBY@fOpAmR7?szQNR~nM)?sPWIj)0)jG-EF8U@nnBaQZy z)ImpVYQL>lBejMDjlxA$#G4%y+^_>N;}r@Zoe2|u-9-x@vvD^ZWnV>Gm=pZa7REAf zOnomhCxBaGZgT+4kiE%aS&lH2sI1mSCM<%)Cr*Sli;#!aXcUb&@Z|Hj{VPsJyClqD%>hy`Y7z(GASs8Mqas3!D zSQE83*%uctlD|p%4)v`arra4y>yP5m25V*_+n)Ry1v>z_Fz!TV6t+N?x?#iH$q=m= z8&X{uW%LVRO87dVl=$Y*>dabJVq{o|Kx`7(D2$5DVX&}XGbg|Ua(*5b=;5qzW9;|w>m{hIO(Tu-z(ey8H=EMluJNyK4BJmGpX~ZM2O61 zk*O7js{-MBqwq>Urf0igN+6soGGc!Y?SP6hiXuJzZ1V4WZqE*?h;PG84gvG~dds6~484!kPM zMP87IP?dhdc;%|cS&LxY*Ib6P3%p|9)E3IgRmhhwtUR3eRK6iZ_6fiGW}jnL4(I|t ze`2yLvmuY42lNwO6>I#Son3$R4NOoP*WUm1R4jl#agtSLE}fSu-Z>{+*?pQIn7`s3LAzF#1pSxCAo?clr9 z9PUj#REq28*ZkJnxs$aK%8^5?P<_Q!#Z?%JH0FKVF;&zH3F#J^fz|ahl$Ycs~kFij_XP;U<`FcaDYyXYPM~&jEe1Xj1n;wyRdD;lmnq&FEro=;+Z$=v-&fYM9eK*S_D&oTXFW#b0 zRY}Y7R#bLzTfg9i7{s?=P9~qjA?$-U2p5;0?gPPu`1JY|*?*8IPO!eX>oiX=O#F!A zl`S%e5Y(csR1f)I(iKMf-;5%_rPP7h&}5Fc(8byKUH1*d7?9%QC|4aADj3L8yuo6GOv#%HDgU3bN(UHw1+(99&Om%f!DY(RYSf4&Uny% zH}*&rEXc$W5+eyeEg|I|E-HnkIO0!$1sV7Z&NXxiCZJ@`kH4eEi5}q~!Vv5qQq{MI zi4^`GYoUN-7Q(jy^SKXL4$G4K+FQXR)B}ee=pS0RyK=YC8c2bGnMA~rrOh&jd3_AT zxVaq37w^-;OU3+C`Kko-Z%l_2FC^maa=Ae0Fm@PEtXEg@cX*oka1Lt&h@jES<6?o1Oi1C9>}7+U(Ve zQ$=8RlzcnfCd59CsJ=gG^A!2Bb_PY~K2sSau{)?Ge03G7US&qrgV!3NUi>UHWZ*lo zS;~0--vn{ot+7UWMV{a(X3rZ8Z06Ps3$-sd|CWE(Y#l`swvcDbMjuReGsoA`rmZ`^ z=AaArdbeU0EtwnOuzq@u5P1rlZjH#gNgh6HIhG(>dX%4m{_!&DNTQE)8= zXD-vcpcSi|DSm3aUMnrV;DQY?svz?9*#GT$NXb~Hem=24iy>7xj367(!#RjnrHtrP-Q`T2W*PEvAR-=j ztY2|#<|JvHNVnM-tNdoS_yRSo=yFqukTZmB$|>Vclj)o=YzC9!ph8)ZOH5X=%Aq|9gNgc}^KFVLht!Lyw54v5u&D zW%vT%z`H{Ax>Ry+bD&QjHQke_wEA;oj(&E!s4|OURButQKSc7Ar-PzIiFa8F@ezkaY2J9&PH+VI1!G+{JgsQ7%da*_Gr!exT*OgJld)b-?cd)xI+|v_C`h(Cg`N~oj0`SQPTma z{@vc8L^D-rBXwS#00jT#@=-n1H-C3hvg61r2jx#ok&cr#BV~9JdPaVihyrGq*lb>bm$H6rIoc}ifaSn6mTD9% z$FRJxbNozOo6y}!OUci1VBv-7{TYZ4GkOM@46Y9?8%mSH9?l&lU59)T#Fjg(h%6I} z?ib zZ(xb8Rwr+vv>@$h{WglT2lL`#V=-9tP^c)cjvnz(g|VL^h8^CPVv12dE(o}WQ@0OP z^2-&ssBXP^#Oh`X5@F+~$PCB6kK-T7sFUK|>$lNDSkvAy%{y2qgq-&v zv}^&gm`wiYztWgMS<{^qQKYNV=>CQaOeglAY~EZvr}n~tW=yg)_+fzqF%~+*V_$3h z2hDW`e$qR;QMg?(wKE>%H_6ASS@6bkOi-m- zg6B7AzD;gBS1%OD7|47a%3BykN{w}P!Wn-nQOfpKUpx8Mk{$IO62D!%U9$kr!e%T> zlqQih?3(U&5%r!KZFZPdbwZ0laAJCj!c&pEFVzrH&_&i5m68Y_*J+-Qjlnz}Q{3oAD)`d14H zKUGmbwC|beC9Mtp>SbL~NVrlctU3WBpHz(UeIa~_{u^_4OaHs_LQt>bUwcyD`_Bbh zC=x|1vSjL)JvVHLw|xKynEvq2m)7O-6qdmjht7pZ*z|o%NA17v$9H*(5D5(MXiNo1 z72Tv}QASqr$!mY58s_Q{hHa9MY+QZ`2zX-FT@Kd?`8pczcV^9IeOKDG4WKqiP7N|S z+O977=VQTk8k5dafK`vd(4?_3pBdB?YG9*Z=R@y|$S+d%1sJf-Ka++I&v9hH)h#}} zw-MjQWJ?ME<7PR(G<1#*Z-&M?%=yzhQw$Lki(R+Pq$X~Q!9BO=fP9FyCIS8zE3n04 z8ScD%XmJnIv=pMTgt6VSxBXOZucndRE@7^aU0wefJYueY(Cb%?%0rz)zWEnsNsKhQ z+&o6d^x=R;Pt7fUa_`JVb1HPHYbXg{Jvux|atQ^bV#_|>7QZNC~P^IKUThB6{kvz2pr2*Cyxj zy37Nri8za8J!@Iw9rbt~#^<9zOaM8LOi$kPBcAGqPq-DB^-93Qeup{9@9&=zV6KQN zL)ic5S%n1!F(7b>MQ973$~<0|9MY-G!?wk?j-cQhMQlM2n{&7JoTBGsP;=fC6CBJn zxlpk^%x=B16rfb-W9pYV#9IRHQL9VG4?Uh>pN>2}0-MST2AB2pQjf*rT+TLCX-+&m z9I{ic2ogXoh=HwdI#igr(JC>>NUP|M>SA?-ux<2&>Jyx>Iko!B<3vS}{g*dKqxYW7 z0i`&U#*v)jot+keO#G&wowD!VvD(j`Z9a*-_RALKn0b(KnZ37d#Db7royLhBW~*7o zRa`=1fo9C4dgq;;R)JpP++a9^{xd)8``^fPW9!a%MCDYJc;3yicPs8IiQM>DhUX*; zeIrxE#JRrr|D$@bKgOm4C9D+e!_hQKj3LC`Js)|Aijx=J!rlgnpKeF>b+QlKhI^4* zf%Of^RmkW|xU|p#Lad44Y5LvIUIR>VGH8G zz7ZEIREG%UOy4)C!$muX6StM4@Fsh&Goa}cj10RL(#>oGtr6h~7tZDDQ_J>h)VmYlKK>9ns8w4tdx6LdN5xJQ9t-ABtTf_ zf1dKVv!mhhQFSN=ggf(#$)FtN-okyT&o6Ms+*u72Uf$5?4)78EErTECzweDUbbU)) zc*tt+9J~Pt%!M352Y5b`Mwrjn^Orp+)L_U1ORHJ}OUsB78YPcIRh4p5jzoDB7B*fb z4v`bouQeCAW#z9b1?4(M3dcwNn2F2plwC^RVHl#h&b-8n#5^o+Ll20OlJ^gOYiK2< z;MQuR!t!>`i}CAOa4a+Rh5IL|@kh4EdEL*O=3oGx4asg?XCTcUOQnmHs^6nLu6WcI zSt9q7nl*?2TIikKNb?3JZBo$cW6)b#;ZKzi+(~D-%0Ec+QW=bZZm@w|prGiThO3dy zU#TQ;RYQ+xU~*@Zj;Rf~z~iL8Da`RT!Z)b3ILBhnIl@VX9K0PSj5owH#*FJXX3vZ= zg_Zyn^G&l!WR6wN9GWvt)sM?g2^CA8&F#&t2z3_MiluRqvNbV{Me6yZ&X-_ zd6#Xdh%+6tCmSNTdCBusVkRwJ_A~<^Nd6~MNOvS;YDixM43`|8e_bmc*UWi7TLA})`T_F ztk&Nd=dgFUss#Ol$LXTRzP9l1JOSvAws~^X%(`ct$?2Im?UNpXjBec_-+8YK%rq#P zT9=h8&gCtgx?=Oj$Yr2jI3`VVuZ`lH>*N+*K11CD&>>F)?(`yr~54vHJftY*z?EorK zm`euBK<$(!XO%6-1=m>qqp6F`S@Pe3;pK5URT$8!Dd|;`eOWdmn916Ut5;iXWQoXE z0qtwxlH=m_NONP3EY2eW{Qwr-X1V3;5tV;g7tlL4BRilT#Y&~o_!f;*hWxWmvA;Pg zRb^Y$#PipnVlLXQIzKCuQP9IER0Ai4jZp+STb1Xq0w(nVn<3j(<#!vuc?7eJEZC<- zPhM7ObhgabN2`pm($tu^MaBkRLzx&jdh;>BP|^$TyD1UHt9Qvr{ZcBs^l!JI4~d-Py$P5QOYO&8eQOFe)&G zZm+?jOJioGs7MkkQBCzJSFJV6DiCav#kmdxc@IJ9j5m#&1)dhJt`y8{T!uxpBZ>&z zD^V~%GEaODak5qGj|@cA7HSH{#jHW;Q0KRdTp@PJO#Q1gGI=((a1o%X*{knz&_`ym zkRLikN^fQ%Gy1|~6%h^vx>ToJ(#aJDxoD8qyOD{CPbSvR*bC>Nm+mkw>6mD0mlD0X zGepCcS_x7+6X7dH;%e`aIfPr-NXSqlu&?$Br1R}3lSF2 zWOXDtG;v#EVLSQ!>4323VX-|E#qb+x%IxzUBDI~N23x? zXUHfTTV#_f9T$-2FPG@t)rpc9u9!@h^!4=fL^kg9 zVv%&KY3!?bU*V4X)wNT%Chr;YK()=~lc%$auOB_|oH`H)Xot@1cmk{^qdt&1C55>k zYnIkdoiAYW41zrRBfqR?9r^cpWIEqfS;|R#bIs4$cqA zoq~$yl8h{IXTSdSdH?;`ky6i%+Oc?HvwH+IS`%_a!d#CqQob9OTNIuhUnOQsX;nl_ z;1w99qO9lAb|guQ9?p4*9TmIZ5{su!h?v-jpOuShq!{AuHUYtmZ%brpgHl$BKLK_L z6q5vZodM$)RE^NNO>{ZWPb%Ce111V4wIX}?DHA=uzTu0$1h8zy!SID~m5t)(ov$!6 zB^@fP#vpx3enbrbX=vzol zj^Bg7V$Qa53#3Lptz<6Dz=!f+FvUBVIBtYPN{(%t(EcveSuxi3DI>XQ*$HX~O{KLK5Dh{H2ir87E^!(ye{9H&2U4kFxtKHkw zZPOTIa*29KbXx-U4hj&iH<9Z@0wh8B6+>qQJn{>F0mGnrj|0_{nwN}Vw_C!rm0!dC z>iRlEf}<+z&?Z4o3?C>QrLBhXP!MV0L#CgF{>;ydIBd5A{bd-S+VFn zLqq4a*HD%65IqQ5BxNz~vOGU=JJv|NG{OcW%2PU~MEfy6(bl#^TfT7+az5M-I`i&l z#g!HUfN}j#adA-21x7jbP6F;`99c8Qt|`_@u@fbhZF+Wkmr;IdVHj+F=pDb4MY?fU znDe##Hn){D}<>vVhYL#)+6p9eAT3T$?;-~bZU%l7MpPNh_mPc(h@79 z;LPOXk>e3nmIxl9lno5cI5G@Q!pE&hQ`s{$Ae4JhTebeTsj*|!6%0;g=wH?B1-p{P z`In#EP12q6=xXU)LiD+mLidPrYGHaKbe5%|vzApq9(PI6I5XjlGf<_uyy59iw8W;k zdLZ|8R8RWDc`#)n2?~}@5)vvksY9UaLW`FM=2s|vyg>Remm=QGthdNL87$nR&TKB*LB%*B}|HkG64 zZ|O4=Yq?Zwl>_KgIG@<8i{Zw#P3q_CVT7Dt zoMwoI)BkpQj8u(m!>1dfOwin(50}VNiLA>A2OG&TBXcP=H(3I;!WdPFe?r_e{%>bc6(Zk?6~Ew&;#ZxBJ| zAd1(sAHqlo_*rP;nTk)kAORe3cF&tj>m&LsvB)`-y9#$4XU=Dd^+CzvoAz%9216#f0cS`;kERxrtjbl^7pmO;_y zYBGOL7R1ne7%F9M2~0a7Srciz=MeaMU~ zV%Y#m_KV$XReYHtsraWLrdJItLtRiRo98T3J|x~(a>~)#>JHDJ z|4j!VO^qWQfCm9-$N29SpHUqvz62%#%98;2FNIF*?c9hZ7GAu$q>=0 zX_igPSK8Et(fmD)V=CvbtA-V(wS?z6WV|RX2`g=w=4D)+H|F_N(^ON!jHf72<2nCJ z^$hEygTAq7URR{Vq$)BsmFKTZ+i1i(D@SJuTGBN3W8{JpJ^J zkF=gBTz|P;Xxo1NIypGzJq8GK^#4tl)S%8$PP6E8c|GkkQ)vZ1OiB%mH#@hO1Z%Hp zv%2~Mlar^}7TRN-SscvQ*xVv+i1g8CwybQHCi3k;o$K@bmB%^-U8dILX)7b~#iPu@ z&D&W7YY2M3v`s(lNm2#^dCRFd;UYMUw1Rh2mto8laH1m`n0u;>okp5XmbsShOhQwo z@EYOehg-KNab)Rieib?m&NXls+&31)MB&H-zj_WmJsGjc1sCSOz0!2Cm1vV?y@kkQ z<1k6O$hvTQnGD*esux*aD3lEm$mUi0td0NiOtz3?7}h;Bt*vIC{tDBr@D)9rjhP^< zY*uKu^BiuSO%)&FL>C?Ng!HYZHLy`R>`rgq+lJhdXfo|df zmkzpQf{6o9%^|7Yb5v{Tu& zsP*Y~<#jK$S_}uEisRC;=y{zbq`4Owc@JyvB->nPzb#&vcMKi5n66PVV{Aub>*>q8 z=@u7jYA4Ziw2{fSED#t4QLD7Rt`au^y(Ggp3y(UcwIKtI(OMi@GHxs!bj$v~j(FZK zbdcP^gExtXQqQ8^Q#rHy1&W8q!@^aL>g1v2R45T(KErWB)1rB@rU`#n&-?g2Ti~xXCrexrLgajgzNy=N9|A6K=RZ zc3yk>w5sz1zsg~tO~-Ie?%Aplh#)l3`s632mi#CCl^75%i6IY;dzpuxu+2fliEjQn z&=~U+@fV4>{Fp=kk0oQIvBdqS#yY`Z+>Z|T&K{d;v3}=JqzKx05XU3M&@D5!uPTGydasyeZ5=1~IX-?HlM@AGB9|Mzb{{Dt@bUU8{KUPU@EX zv0fpQNvG~nD2WiOe{Vn=hE^rQD(5m+!$rs%s{w9;yg9oxRhqi0)rwsd245)igLmv* zJb@Xlet$+)oS1Ra#qTB@U|lix{Y4lGW-$5*4xOLY{9v9&RK<|K!fTd0wCKYZ)h&2f zEMcTCd+bj&YVmc#>&|?F!3?br3ChoMPTA{RH@NF(jmGMB2fMyW(<0jUT=8QFYD7-% zS0ydgp%;?W=>{V9>BOf=p$q5U511~Q0-|C!85)W0ov7eb35%XV;3mdUI@f5|x5C)R z$t?xLFZOv}A(ZjjSbF+8&%@RChpRvo>)sy>-IO8A@>i1A+8bZd^5J#(lgNH&A=V4V z*HUa0{zT{u-_FF$978RziwA@@*XkV{<-CE1N=Z!_!7;wq*xt3t((m+^$SZKaPim3K zO|Gq*w5r&7iqiQ!03SY{@*LKDkzhkHe*TzQaYAkz&jNxf^&A_-40(aGs53&}$dlKz zsel3=FvHqdeIf!UYwL&Mg3w_H?utbE_(PL9B|VAyaOo8k4qb>EvNYHrVmj^ocJQTf zL%4vl{qgmJf#@uWL@)WiB>Lm>?ivwB%uO|)i~;#--nFx4Kr6{TruZU0N_t_zqkg`? zwPFK|WiC4sI%o1H%$!1ANyq6_0OSPQJybh^vFriV=`S;kSsYkExZwB{68$dTODWJQ z@N57kBhwN(y~OHW_M}rX2W13cl@*i_tjW`TMfa~Y;I}1hzApXgWqag@(*@(|EMOg- z^qMk(s~dL#ps>>`oWZD=i1XI3(;gs7q#^Uj&L`gVu#4zn$i!BIHMoOZG!YoPO^=Gu z5`X-(KoSsHL77c<7^Y*IM2bI!dzg5j>;I@2-EeB$LgW|;csQTM&Z|R)q>yEjk@Sw% z6FQk*&zHWzcXalUJSoa&pgH24n`wKkg=2^ta$b1`(BBpBT2Ah9yQF&Kh+3jTaSE|=vChGz2_R^{$C;D`Ua(_=|OO11uLm;+3k%kO19EA`U065i;fRBoH z{Hq$cgHKRFPf0#%L?$*KeS@FDD;_TfJ#dwP7zzO5F>xntH(ONK{4)#jYUDQr6N(N< zp+fAS9l9)^c4Ss8628Zq5AzMq4zc(In_yJSXAT57Dtl}@= zvZoD7iq0cx7*#I{{r9m{%~g6@Hdr|*njKBb_5}mobCv=&X^`D9?;x6cHwRcwnlO^h zl;MiKr#LaoB*PELm8+8%btnC)b^E12!^ zMmVA!z>59e7n+^!P{PA?f9M^2FjKVw1%x~<`RY5FcXJE)AE}MTopGFDkyEjGiE|C6 z(ad%<3?v*?p;LJGopSEY18HPu2*}U!Nm|rfewc6(&y(&}B#j85d-5PeQ{}zg>>Rvl zDQ3H4E%q_P&kjuAQ>!0bqgAj){vzHpnn+h(AjQ6GO9v**l0|aCsCyXVE@uh?DU;Em zE*+7EU9tDH````D`|rM6WUlzBf1e{ht8$62#ilA6Dcw)qAzSRwu{czZJAcKv8w(Q6 zx)b$aq*=E=b5(UH-5*u)3iFlD;XQyklZrwHy}+=h6=aKtTriguHP@Inf+H@q32_LL z2tX|+X}4dMYB;*EW9~^5bydv)_!<%q#%Ocyh=1>FwL{rtZ?#2Scp{Q55%Fd-LgLU$ zM2u#|F{%vi%+O2^~uK3)?$6>9cc7_}F zWU72eFrzZ~x3ZIBH;~EMtD%51o*bnW;&QuzwWd$ds=O>Ev807cu%>Ac^ZK&7bCN;Ftk#eeQL4pG0p!W{Ri@tGw>nhIo`rC zi!Z6?70nYrNf92V{Y_i(a4DG=5>RktP=?%GcHEx?aKN$@{w{uj#Cqev$bXefo?yC6KI%Rol z%~$974WCymg;BBhd9Mv}_MeNro_8IB4!evgo*je4h?B-CAkEW-Wr-Q_V9~ef(znU& z{f-OHnj>@lZH(EcUb2TpOkc70@1BPiY0B#++1EPY5|UU?&^Vpw|C`k4ZWiB-3oAQM zgmG%M`2qDw5BMY|tG++34My2fE|^kvMSp(d+~P(Vk*d+RW1833i_bX^RYbg9tDtX` zox?y^YYfs-#fX|y7i(FN7js)66jN!`p9^r7oildEU#6J1(415H3h>W*p(p9@dI|c7 z&c*Aqzksg}o`D@i+o@WIw&jjvL!(`)JglV5zwMn)praO2M05H&CDeps0Wq8(8AkuE zPm|8MB6f0kOzg(gw}k>rzhQyo#<#sVdht~Wdk`y`=%0!jbd1&>Kxed8lS{Xq?Zw>* zU5;dM1tt``JH+A9@>H%-9f=EnW)UkRJe0+e^iqm0C5Z5?iEn#lbp}Xso ztleC}hl&*yPFcoCZ@sgvvjBA_Ew6msFml$cfLQY_(=h03WS_z+Leeh$M3#-?f9YT^Q($z z+pgaEv$rIa*9wST`WHASQio=9IaVS7l<87%;83~X*`{BX#@>>p=k`@FYo ze!K5_h8hOc`m0mK0p}LxsguM}w=9vw6Ku8y@RNrXSRPh&S`t4UQY=e-B8~3YCt1Fc zU$CtRW%hbcy{6K{>v0F*X<`rXVM3a{!muAeG$zBf`a(^l${EA9w3>J{aPwJT?mKVN2ba+v)Mp*~gQ_+Ws6= zy@D?85!U@VY0z9T=E9LMbe$?7_KIg)-R$tD)9NqIt84fb{B;f7C)n+B8)Cvo*F0t! zva6LeeC}AK4gL#d#N_HvvD& z0;mdU3@7%d5>h(xX-NBmJAOChtb(pX-qUtRLF5f$ z`X?Kpu?ENMc88>O&ym_$Jc7LZ> z#73|xJ|aa@l}PawS4Mpt9n)38w#q^P1w2N|rYKdcG;nb!_nHMZA_09L!j)pBK~e+j?tb-_A`wF8 zIyh>&%v=|n?+~h}%i1#^9UqZ?E9W!qJ0d0EHmioSt@%v7FzF`eM$X==#oaPESHBm@ zYzTXVo*y|C0~l_)|NF|F(If~YWJVkQAEMf5IbH{}#>PZpbXZU;+b^P8LWmlmDJ%Zu)4CajvRL!g_Faph`g0hpA2)D0|h zYy0h5+@4T81(s0D=crojdj|dYa{Y=<2zKp@xl&{sHO;#|!uTHtTey25f1U z#=Nyz{rJy#@SPk3_U|aALcg%vEjwIqSO$LZI59^;Mu~Swb53L+>oxWiN7J{;P*(2b@ao*aU~}-_j10 z@fQiaWnb}fRrHhNKrxKmi{aC#34BRP(a#0K>-J8D+v_2!~(V-6J%M@L{s?fU5ChwFfqn)2$siOUKw z?SmIRlbE8ot5P^z0J&G+rQ5}H=JE{FNsg`^jab7g-c}o`s{JS{-#}CRdW@hO`HfEp z1eR0DsN! zt5xmsYt{Uu;ZM`CgW)VYk=!$}N;w+Ct$Wf!*Z-7}@pA62F^1e$Ojz9O5H;TyT&rV( zr#IBM8te~-2t2;kv2xm&z%tt3pyt|s#vg2EOx1XkfsB*RM;D>ab$W-D6#Jdf zJ3{yD;P4=pFNk2GL$g~+5x;f9m*U2!ovWMK^U5`mAgBRhGpu)e`?#4vsE1aofu)iT zDm;aQIK6pNd8MMt@}h|t9c$)FT7PLDvu3e)y`otVe1SU4U=o@d!gn(DB9kC>Ac1wJ z?`{Hq$Q!rGb9h&VL#z+BKsLciCttdLJe9EmZF)J)c1MdVCrxg~EM80_b3k{ur=jVjrVhDK1GTjd3&t#ORvC0Q_&m|n>&TF1C_>k^8&ylR7oz#rG?mE%V| zepj0BlD|o?p8~LK_to`GINhGyW{{jZ{xqaO*SPvH)BYy1eH22DL_Kkn28N!0z3fzj z_+xZ3{ph_Tgkd)D$OjREak$O{F~mODA_D`5VsoobVnpxI zV0F_79%JB!?@jPs=cY73FhGuT!?fpVX1W=Wm zK5}i7(Pfh4o|Z{Ur=Y>bM1BDo2OdXBB(4Y#Z!61A8C6;7`6v-(P{ou1mAETEV?Nt< zMY&?ucJcJ$NyK0Zf@b;U#3ad?#dp`>zmNn=H1&-H`Y+)ai-TfyZJX@O&nRB*7j$ zDQF!q#a7VHL3z#Hc?Ca!MRbgL`daF zW#;L$yiQP|5VvgvRLluk3>-1cS+7MQ1)DC&DpYyS9j;!Rt$HdXK1}tG3G_)ZwXvGH zG;PB^f@CFrbEK4>3gTVj73~Tny+~k_pEHt|^eLw{?6NbG&`Ng9diB9XsMr(ztNC!{FhW8Hi!)TI`(Q|F*b z-z;#*c1T~kN67omP(l7)ZuTlxaC_XI(K8$VPfAzj?R**AMb0*p@$^PsN!LB@RYQ4U zA^xYY9sX4+;7gY%$i%ddfvneGfzbE4ZTJT5Vk3&1`?ULTy28&D#A&{dr5ZlZH&NTz zdfZr%Rw*Ukmgu@$C5$}QLOyb|PMA5syQns?iN@F|VFEvFPK321mTW^uv?GGNH6rnM zR9a2vB`}Y++T3Wumy$6`W)_c0PS*L;;0J^(T7<)`s{}lZVp`e)fM^?{$ zLbNw>N&6aw5Hlf_M)h8=)x0$*)V-w-Pw5Kh+EY{^$?#{v)_Y{9p5K{DjLnJ(ZUcyk*y(6D8wHB8=>Y)fb_Pw0v)Xybk`Sw@hNEaHP$-n`DtYP ziJyiauEXtuMpWyQjg$gdJR?e+=8w+=5GO-OT8pRaVFP1k^vI|I&agGjN-O*bJEK!M z`kt^POhUexh+PA&@And|vk-*MirW?>qB(f%y{ux z*d44UXxQOs+C`e-x4KSWhPg-!gO~kavIL8X3?!Ac2ih-dkK~Ua2qlcs1b-AIWg*8u z0QvL~51vS$LnmJSOnV4JUCUzg&4;bSsR5r_=FD@y|)Y2R_--e zMWJ;~*r=vJssF5_*n?wF0DO_>Mja=g+HvT=Yd^uBU|aw zRixHUQJX0Pgt-nFV+8&|;-n>!jNUj!8Y_YzH*%M!-_uWt6& z|Ec+lAD``i^do;u_?<(RpzsYZVJ8~}|NjUFgXltofbjhf!v&208g^#0h-x?`z8cInq!9kfVwJ|HQ;VK>p_-fn@(3q?e51Keq(=U-7C0#as-q z8Or}Ps07>O2@AAXz_%3bTOh{tKm#uRe}Sqr=w6-Wz$FCdfF3qNabEaj`-OfipxaL- zPh2R*l&%ZbcV?lv4C3+t2DAVSFaRo20^W_n4|0t(_*`?KmmUHG2sNZ*CRZlCFIyZbJqLdBCj)~%if)g|4NJr(8!R!E0iBbm$;`m;1n2@(8*E%B zH!g{hK|WK?1jUfM9zX?hlV#l%!6^p$$P+~rg}OdKg|d^Ed4WTY1$1J@WWHr$Os_(L z;-Zu1FJqhR4LrCUl)C~E7gA!^wtA6YIh10In9rX@LGSjnTPtLp+gPGp6u z3}{?J1!yT~?FwqT;O_-1%37f#4ek&DL){N}MX3RbNfRb-T;U^wXhx#De&QssA$lu~ mWkA_K7-+yz9tH*t6hj_Qg(_m7JaeTomk=)l!_+yTk^le-`GmOu delta 34176 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 SGW6ptSs!X7{rG*o_g?|vpSEZK From 4e0bf91a1327c7fe4f96ab9c17943cd1b7707b15 Mon Sep 17 00:00:00 2001 From: ah-OOG-ah <75745146+ah-OOG-ah@users.noreply.github.com> Date: Sat, 15 Jun 2024 16:09:20 -0400 Subject: [PATCH 050/132] Post-mergening cleanup + fix oops (#46) * Post-mergening cleanup + fix oops Detrav shouldn't have been api... * update * update --------- Co-authored-by: Martin Robertz --- dependencies.gradle | 9 +++------ settings.gradle | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 13eb5a28..d30bfdc8 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,19 +1,16 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.45.155:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.37:dev') api(rfg.deobf('maven.modrinth:journeymap:5.2.3')) devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.2.0:dev') - compileOnly('com.github.GTNewHorizons:GalacticGregGT5:1.1.0:dev') {transitive = false} - compileOnly('com.github.GTNewHorizons:bartworks:0.9.21:dev') {transitive = false} - compileOnly(deobfCurse('xaeros-minimap-263420:4905582')) compileOnly(deobfCurse('xaeros-world-map-317780:4905612')) compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) // For debugging - api('com.github.GTNewHorizons:DetravScannerMod:1.8.0:dev') - runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.35:dev') + runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.8.1:dev') + runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.51:dev') } diff --git a/settings.gradle b/settings.gradle index 378da589..94c2daf3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.21' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.22' } From 8053e6ce733dddc67bbe1e8684a6d1a4b335c7d5 Mon Sep 17 00:00:00 2001 From: Caedis Date: Sun, 30 Jun 2024 02:01:56 -0500 Subject: [PATCH 051/132] Fix Scaling of GT Ore Veins and TC Nodes on Journeymap (#47) * use drawScale instead of fontScale * updatebs + deps --- dependencies.gradle | 6 +++--- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- .../integration/journeymap/drawsteps/OreVeinDrawStep.java | 2 +- .../journeymap/drawsteps/ThaumcraftNodeDrawStep.java | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index d30bfdc8..4513e22c 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,10 +1,10 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.37:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.56:dev') api(rfg.deobf('maven.modrinth:journeymap:5.2.3')) - devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.2.0:dev') + devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.3.0:dev') compileOnly(deobfCurse('xaeros-minimap-263420:4905582')) compileOnly(deobfCurse('xaeros-world-map-317780:4905612')) @@ -12,5 +12,5 @@ dependencies { // For debugging runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.8.1:dev') - runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.51:dev') + runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.60:dev') } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23a..a4413138 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index 94c2daf3..6fe010ce 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.22' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.23' } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java index e2c6ec82..fbab57e1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java @@ -72,7 +72,7 @@ public IWaypointAndLocationProvider getLocationProvider() { @Override public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, double fontScale, double rotation) { - iconSize = 32 * fontScale; + iconSize = 32 * drawScale; final double iconSizeHalf = iconSize / 2; final Point2D.Double blockAsPixel = gridRenderer .getBlockPixelInGrid(oreVeinLocation.getBlockX(), oreVeinLocation.getBlockZ()); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java index 913f123e..47539d54 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java @@ -42,7 +42,7 @@ public ThaumcraftNodeDrawStep(ThaumcraftNodeLocation thaumcraftNodeLocation) { @Override public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, double fontScale, double rotation) { - final double borderSize = 44 * fontScale; + final double borderSize = 44 * drawScale; final double borderSizeHalf = borderSize / 2; final Point2D.Double blockAsPixel = gridRenderer .getBlockPixelInGrid(thaumcraftNodeLocation.getBlockX(), thaumcraftNodeLocation.getBlockZ()); From e885a5b223a8021094bdcdc4b872eb35926a9e1f Mon Sep 17 00:00:00 2001 From: chochem <40274384+chochem@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:55:22 +0100 Subject: [PATCH 052/132] remove gt recipe from vp (moved to nhcoremod) (#48) --- .../visualprospecting/hooks/HooksShared.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index eaab5204..f3765b59 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -3,8 +3,6 @@ import java.io.IOException; import java.util.zip.DataFormatException; -import net.minecraft.init.Items; -import net.minecraft.item.ItemStack; import net.minecraft.server.MinecraftServer; import net.minecraftforge.common.MinecraftForge; @@ -36,10 +34,6 @@ import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.Side; import gregtech.api.GregTech_API; -import gregtech.api.enums.GT_Values; -import gregtech.api.enums.Materials; -import gregtech.api.enums.OrePrefixes; -import gregtech.api.util.GT_OreDictUnificator; public class HooksShared { @@ -86,15 +80,6 @@ public void fmlLifeCycleEvent(FMLInitializationEvent event) { // postInit "Handle interaction with other mods, complete your setup based on this." public void fmlLifeCycleEvent(FMLPostInitializationEvent event) { GregTech_API.sAfterGTPostload.add(new VeinTypeCaching()); - GregTech_API.sAfterGTPostload.add( - () -> GT_Values.RA.addAssemblerRecipe( - new ItemStack[] { GT_OreDictUnificator.get(OrePrefixes.plate, Materials.Wood, 2L), - new ItemStack(Items.writable_book, 1, 0x7FFF), - new ItemStack(Items.gold_nugget, 1, 0x7FFF) }, - Materials.Glue.getFluid(20L), - new ItemStack(ProspectorsLog.instance, 1, 0), - 128, - 8)); } public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) {} From e482c86896e9595f065fb8bcbff9793866763afb Mon Sep 17 00:00:00 2001 From: Dream Master Date: Tue, 9 Jul 2024 22:15:15 +0700 Subject: [PATCH 053/132] update --- dependencies.gradle | 2 +- gradlew | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 4513e22c..3b04bd12 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.56:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.70:dev') api(rfg.deobf('maven.modrinth:journeymap:5.2.3')) devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.3.0:dev') diff --git a/gradlew b/gradlew index 1aa94a42..b740cf13 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# 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/. From 3b503ab62315b9fee931008c285c36069eca1568 Mon Sep 17 00:00:00 2001 From: Caedis Date: Fri, 12 Jul 2024 10:44:58 -0500 Subject: [PATCH 054/132] Fix issue with Xaero's minimap and the layers not being scaled correctly (#49) * update xaero * update gitignore * fix issue with overlays moving with the player * add support for drawing a label on xaero's minimap --- .gitignore | 1 + dependencies.gradle | 4 +-- .../integration/DrawUtils.java | 34 +++++++++++++++++++ .../rendersteps/OreVeinRenderStep.java | 15 ++++---- .../xaerosminimap/MinimapRendererMixin.java | 5 +-- 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 75c41f65..38d39a46 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ src/main/resources/mixins.*.json *.bat *.DS_Store !gradlew.bat +layout.json diff --git a/dependencies.gradle b/dependencies.gradle index 3b04bd12..d043dac9 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -6,8 +6,8 @@ dependencies { devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.3.0:dev') - compileOnly(deobfCurse('xaeros-minimap-263420:4905582')) - compileOnly(deobfCurse('xaeros-world-map-317780:4905612')) + compileOnly(deobfCurse('xaeros-minimap-263420:5060684')) + compileOnly(deobfCurse('xaeros-world-map-317780:5060733')) compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) // For debugging diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java b/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java index 731936c8..0ad18488 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java @@ -3,6 +3,7 @@ import java.util.List; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.OpenGlHelper; import net.minecraft.client.renderer.Tessellator; @@ -139,6 +140,39 @@ public static void drawSimpleLabel(GuiScreen gui, String text, double textX, dou GL11.glPopMatrix(); } + public static void drawLabel(String text, double textX, double textY, int fontColor, int bgColor, boolean centered, + double fontScale) { + final FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; + + GL11.glPushMatrix(); + + if (fontScale != 1.0) { + textX /= fontScale; + textY /= fontScale; + GL11.glScaled(fontScale, fontScale, 0); + } + double dTextX = textX - (double) (int) textX; + double dTextY = textY - (double) (int) textY; + double textWidth = fontRenderer.getStringWidth(text); + double xOffsetL = centered ? -textWidth / 2.0 - 2 : -2; + double xOffsetR = centered ? textWidth / 2.0 + 2 : textWidth + 2; + GL11.glTranslated(dTextX, dTextY, 0.0); + drawGradientRect( + (int) textX + xOffsetL, + (int) textY - 2, + (int) textX + xOffsetR, + (int) textY + fontRenderer.FONT_HEIGHT + 2, + 0, + bgColor, + bgColor); + fontRenderer.drawStringWithShadow( + text, + (centered ? (int) (textX - textWidth / 2.0) : (int) textX), + (int) textY, + fontColor); + GL11.glPopMatrix(); + } + public static void drawSimpleTooltip(GuiScreen gui, List text, double x, double y, int fontColor, int bgColor) { if (text.isEmpty()) return; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java index 3350a073..c31b0918 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java @@ -5,6 +5,7 @@ import javax.annotation.Nullable; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.resources.I18n; import net.minecraft.init.Blocks; @@ -25,7 +26,7 @@ public class OreVeinRenderStep implements InteractableRenderStep { private final OreVeinLocation oreVeinLocation; private final ResourceLocation depletedTextureLocation = new ResourceLocation(Tags.MODID, "textures/depleted.png"); private final IIcon blockStoneIcon = Blocks.stone.getIcon(0, 0); - private final double iconSize = 32; + private double iconSize; private double iconX; private double iconY; @@ -35,6 +36,7 @@ public OreVeinRenderStep(OreVeinLocation veinPosition) { @Override public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double scale) { + iconSize = 10 * scale; final double iconSizeHalf = iconSize / 2; final double scaleForGui = Math.max(1, scale); iconX = (oreVeinLocation.getBlockX() - 0.5 - cameraX) * scaleForGui - iconSizeHalf; @@ -75,18 +77,17 @@ public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double } } - if (gui != null && scale >= Utils.journeyMapScaleToLinear(Config.minZoomLevelForOreLabel) - && !oreVeinLocation.isDepleted()) { + if (scale >= Utils.journeyMapScaleToLinear(Config.minZoomLevelForOreLabel) && !oreVeinLocation.isDepleted()) { final int fontColor = oreVeinLocation.drawSearchHighlight() ? 0xFFFFFFFF : 0xFF7F7F7F; String text = I18n.format(oreVeinLocation.getName()); - DrawUtils.drawSimpleLabel( - gui, + DrawUtils.drawLabel( text, 0, - -iconSizeHalf - gui.mc.fontRenderer.FONT_HEIGHT - 5, + -iconSizeHalf - Minecraft.getMinecraft().fontRenderer.FONT_HEIGHT - 5, fontColor, 0xB4000000, - true); + true, + 1.6); } if (oreVeinLocation.isActiveAsWaypoint()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java index 8ffbe9c2..448a9a6b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java @@ -67,15 +67,16 @@ public class MinimapRendererMixin { } if (stencilEnabled) { + double mapZoom = zoom * (double) minimapScale / 2.0; GL11.glPushMatrix(); GL11.glEnable(GL11.GL_STENCIL_TEST); GL11.glRotated(Math.toDegrees(angle) - 90, 0.0, 0.0, 1.0); - GL11.glScaled(zoom, zoom, 0); + GL11.glScaled(mapZoom, mapZoom, 0); GL11.glStencilFunc(GL11.GL_EQUAL, 1, 1); for (LayerRenderer renderer : XaeroWorldMapState.instance.renderers) { if (renderer.isLayerActive()) { for (RenderStep renderStep : renderer.getRenderSteps()) { - renderStep.draw(null, playerX, playerZ, scale); + renderStep.draw(null, playerX, playerZ, mapZoom); } } } From 863b783d7faac3fc1c8d4b90e936cc4242df2a13 Mon Sep 17 00:00:00 2001 From: Dream Master Date: Sun, 14 Jul 2024 08:38:20 +0700 Subject: [PATCH 055/132] update --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index d043dac9..f801f46b 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.70:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.75:dev') api(rfg.deobf('maven.modrinth:journeymap:5.2.3')) devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.3.0:dev') From 9c920e08c256069c6052bc2b3e7f3adf9e7deea5 Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Sat, 20 Jul 2024 09:50:59 +0200 Subject: [PATCH 056/132] Migrate to Navigator api (#50) * Migrate to Navigator api * Gut the api doc * update navigator dep * Unify buttons * Simplify Xaero tooltips * spotless * no need for hard-dep * no need to register all this anymore * Move TC node layer to an appropriate mod --------- Co-authored-by: Caedis Co-authored-by: Martin Robertz --- README.md | 115 ------ dependencies.gradle | 13 +- .../visualprospecting/ServerTranslations.java | 377 ++++++------------ .../sinthoras/visualprospecting/Utils.java | 15 +- .../com/sinthoras/visualprospecting/VP.java | 4 - .../sinthoras/visualprospecting/VPMod.java | 7 +- .../VisualProspecting_API.java | 82 +--- .../visualprospecting/hooks/HooksClient.java | 33 +- .../visualprospecting/hooks/HooksKey.java | 13 - .../integration/DrawUtils.java | 212 ---------- .../journeymap/JourneyMapState.java | 67 ---- .../ResetClientCacheConfirmation.java | 64 --- .../journeymap/buttons/DirtyChunkButton.java | 12 - .../journeymap/buttons/LayerButton.java | 47 --- .../journeymap/buttons/OreVeinButton.java | 12 - .../buttons/ThaumcraftNodeButton.java | 12 - .../buttons/UndergroundFluidButton.java | 12 - .../drawsteps/ClickableDrawStep.java | 22 - .../drawsteps/DirtyChunkDrawStep.java | 82 ---- .../journeymap/drawsteps/OreVeinDrawStep.java | 21 +- .../drawsteps/ThaumcraftNodeDrawStep.java | 265 ------------ .../UndergroundFluidChunkDrawStep.java | 4 +- .../drawsteps/UndergroundFluidDrawStep.java | 4 +- .../journeymap/render/DirtyChunkRenderer.java | 28 -- .../journeymap/render/JMOreVeinRenderer.java | 26 ++ ...a => JMUndergroundFluidChunkRenderer.java} | 18 +- ...r.java => JMUndergroundFluidRenderer.java} | 18 +- .../journeymap/render/LayerRenderer.java | 42 -- .../journeymap/render/OreVeinRenderer.java | 28 -- .../render/ThaumcraftNodeRenderer.java | 28 -- .../render/WaypointProviderLayerRenderer.java | 104 ----- .../waypoints/OreVeinWaypointManager.java | 12 - .../ThaumcraftNodeWaypointManager.java | 12 - .../journeymap/waypoints/WaypointManager.java | 46 --- .../integration/model/MapState.java | 54 --- .../integration/model/SupportedMods.java | 10 - .../model/buttons/ButtonManager.java | 69 ---- .../buttons/DirtyChunkButtonManager.java | 10 - .../model/buttons/LayerButton.java | 13 - .../model/buttons/OreVeinButtonManager.java | 17 +- .../buttons/ThaumcraftNodeButtonManager.java | 10 - .../UndergroundFluidButtonManager.java | 17 +- .../model/layers/DirtyChunkLayerManager.java | 62 --- .../model/layers/LayerManager.java | 107 ----- .../model/layers/LayerRenderer.java | 15 - .../model/layers/OreVeinLayerManager.java | 34 +- .../layers/ThaumcraftNodeLayerManager.java | 67 ---- .../UndergroundFluidChunkLayerManager.java | 19 +- .../layers/UndergroundFluidLayerManager.java | 19 +- .../model/layers/WaypointProviderManager.java | 73 ---- .../model/locations/DirtyChunkLocation.java | 34 -- .../model/locations/ILocationProvider.java | 10 - .../IWaypointAndLocationProvider.java | 14 - .../model/locations/OreVeinLocation.java | 9 +- .../locations/ThaumcraftNodeLocation.java | 145 ------- .../UndergroundFluidChunkLocation.java | 1 + .../locations/UndergroundFluidLocation.java | 1 + .../integration/model/waypoints/Waypoint.java | 20 - .../model/waypoints/WaypointManager.java | 15 - .../NTNodeTrackerWaypointManager.java | 26 -- .../voxelmap/IWaypointManagerReflection.java | 32 -- .../voxelmap/VoxelMapEventHandler.java | 55 ++- .../xaerominimap/OreVeinWaypointManager.java | 17 + .../xaerominimap/XaeroMiniMapState.java | 25 -- .../waypoints/OreVeinWaypointManager.java | 18 - .../ThaumcraftNodeWaypointManager.java | 18 - .../waypoints/WaypointManager.java | 60 --- .../xaerominimap/waypoints/WaypointType.java | 6 - .../waypoints/WaypointWithDimension.java | 28 -- .../xaeroworldmap/XaeroWorldMapState.java | 38 -- .../xaeroworldmap/buttons/LayerButton.java | 44 -- .../xaeroworldmap/buttons/OreVeinButton.java | 12 - .../buttons/SizedGuiTexturedButton.java | 65 --- .../buttons/ThaumcraftNodeButton.java | 12 - .../buttons/UndergroundFluidButton.java | 12 - .../renderers/InteractableLayerRenderer.java | 64 --- .../renderers/LayerRenderer.java | 45 --- .../renderers/ThaumcraftNodeRenderer.java | 26 -- ...enderer.java => XaeroOreVeinRenderer.java} | 13 +- ...> XaeroUndergroundFluidChunkRenderer.java} | 13 +- ...ava => XaeroUndergroundFluidRenderer.java} | 13 +- .../rendersteps/InteractableRenderStep.java | 16 - .../rendersteps/OreVeinRenderStep.java | 37 +- .../xaeroworldmap/rendersteps/RenderStep.java | 10 - .../rendersteps/ThaumcraftNodeRenderStep.java | 233 ----------- .../UndergroundFluidChunkRenderStep.java | 5 +- .../UndergroundFluidRenderStep.java | 5 +- .../visualprospecting/mixinplugin/Mixins.java | 18 - .../mixinplugin/TargetedMod.java | 6 +- .../minecraft/ForgeHooksClientMixin.java | 20 - .../late/journeymap/DisplayVarsAccessor.java | 24 -- .../late/journeymap/FullscreenAccessor.java | 17 - .../journeymap/FullscreenActionsMixin.java | 63 --- .../late/journeymap/FullscreenMixin.java | 319 --------------- .../mixins/late/journeymap/MiniMapMixin.java | 70 ---- .../journeymap/RenderWaypointBeaconMixin.java | 45 --- .../late/journeymap/WaypointManagerMixin.java | 27 -- .../late/tcnodetracker/GuiMainMixin.java | 76 ---- .../xaerosminimap/MinimapRendererMixin.java | 122 ------ .../WaypointsIngameRendererMixin.java | 39 -- .../late/xaerosworldmap/GuiMapMixin.java | 203 ---------- .../icon/theme/Vault/icon/nodes.png | Bin 5351 -> 0 bytes .../icon/theme/Victorian/icon/nodes.png | Bin 5351 -> 0 bytes .../icon/theme/Victorian/icon/oreveins.png | Bin 5913 -> 0 bytes .../theme/Victorian/icon/undergroundfluid.png | Bin 1128 -> 0 bytes .../assets/visualprospecting/lang/en_US.lang | 2 - .../assets/visualprospecting/lang/zh_CN.lang | 1 - .../textures/icons}/oreveins.png | Bin .../textures/icons}/undergroundfluid.png | Bin .../assets/xaeroworldmap/textures/nodes.png | Bin 5517 -> 0 bytes .../xaeroworldmap/textures/oreveins.png | Bin 556 -> 0 bytes .../textures/undergroundfluid.png | Bin 1009 -> 0 bytes 112 files changed, 401 insertions(+), 4301 deletions(-) delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/DirtyChunkButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/OreVeinButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/ThaumcraftNodeButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/UndergroundFluidButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMOreVeinRenderer.java rename src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/{UndergroundFluidChunkRenderer.java => JMUndergroundFluidChunkRenderer.java} (51%) rename src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/{UndergroundFluidRenderer.java => JMUndergroundFluidRenderer.java} (51%) delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/OreVeinWaypointManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/ThaumcraftNodeWaypointManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/SupportedMods.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/DirtyChunkButtonManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/LayerButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ThaumcraftNodeButtonManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ILocationProvider.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/locations/IWaypointAndLocationProvider.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/Waypoint.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/WaypointManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/tcnodetracker/NTNodeTrackerWaypointManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/OreVeinWaypointManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/OreVeinWaypointManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/ThaumcraftNodeWaypointManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointType.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointWithDimension.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/LayerButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/OreVeinButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/ThaumcraftNodeButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/UndergroundFluidButton.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java rename src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/{OreVeinRenderer.java => XaeroOreVeinRenderer.java} (63%) rename src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/{UndergroundFluidChunkRenderer.java => XaeroUndergroundFluidChunkRenderer.java} (64%) rename src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/{UndergroundFluidRenderer.java => XaeroUndergroundFluidRenderer.java} (64%) delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ForgeHooksClientMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java delete mode 100644 src/main/resources/assets/journeymap/icon/theme/Vault/icon/nodes.png delete mode 100644 src/main/resources/assets/journeymap/icon/theme/Victorian/icon/nodes.png delete mode 100644 src/main/resources/assets/journeymap/icon/theme/Victorian/icon/oreveins.png delete mode 100644 src/main/resources/assets/journeymap/icon/theme/Victorian/icon/undergroundfluid.png rename src/main/resources/assets/{journeymap/icon/theme/Vault/icon => visualprospecting/textures/icons}/oreveins.png (100%) rename src/main/resources/assets/{journeymap/icon/theme/Vault/icon => visualprospecting/textures/icons}/undergroundfluid.png (100%) delete mode 100644 src/main/resources/assets/xaeroworldmap/textures/nodes.png delete mode 100644 src/main/resources/assets/xaeroworldmap/textures/oreveins.png delete mode 100644 src/main/resources/assets/xaeroworldmap/textures/undergroundfluid.png diff --git a/README.md b/README.md index 6bf140b3..62f6ef1f 100644 --- a/README.md +++ b/README.md @@ -175,120 +175,5 @@ if(world.isRemote == false) { } ``` -#### JourneyMap Custom Layer - -VisualProspecting provides a light-weight API for custom and interactive layers. This API will keep all maps as optional mod at runtime and not crash you game if it is missing. You may instantiate [`ButtonManager`](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/gui/model/buttons/ButtonManager.java) to create your own logical button. Follow it up with an instance of [`LayerButton`](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/gui/journeymap/buttons/LayerButton.java) and register both in the [`VisualProspecting_API`](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java): - -``` -ButtonManager buttonManager = new ButtonManager("translation.key", "iconName"); -LayerButton layerButton = new LayerButton(buttonManager); - -VisualProspecting_API.LogicalClient.registerCustomButtonManager(buttonManager); -VisualProspecting_API.LogicalClient.registerJourneyMapButton(layerButton); -``` - -If you start the game now, you will see a new button in the menu! - -First, you will implement [`ILocationProvider`](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/gui/model/locations/ILocationProvider.java). This class is a container and will provide all information required to display your item on screen. It won't do any rendering. - -``` -class MyLocation implements ILocationProvider { - - public int getDimensionId() { - return 0; // overworld - } - - public int getBlockX() { - return 0; - } - - public int getBlockY() { - return 65; - } - - public int getBlockZ() { - return 0; - } - - public String getLabel() { - return "Hello Minecraft"; - } -} -``` - -Next up, you'll extend [`LayerManager`](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/gui/model/layers/LayerManager.java) and implement the abstract function to generate cached List of your [`ILocationProvider`](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/gui/model/locations/ILocationProvider.java) implementation. You should only add whatever items are visible to this list. There are more methods to override, that will assist you with that. Take a look! - -``` -class MyLayerManager extends LayerManager { - - public static final MyLayerManager instance = new MyLayerManager(); - - public MyLayerManager() { - super(buttonManager); - } - - protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - return Collections.singletonList(new MyLocation); - } -} -``` - -You have finished the logical implementation of your custom map layer. Congratulations! Now it is time for the visual integration into the map. This example is provided for JourneyMap, but you might as well take a look at the other possibilities. Since you already implemented the button as a first step, you will need to follow it up with an implementation of `DrawStep`, an interface from JourneyMap. This class will receive an instance of `MyLocation` and perform the actual rendering. - -``` -class MyDrawStep implements DrawStep { - - private final MyLocation myLocation; - - public MyDrawStep(MyLocation myLocation) { - this.myLocation = myLocation; - } - - @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, double fontScale, double rotation) { - final double blockSize = Math.pow(2, gridRenderer.getZoom()); - final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid(myLocation.getBlockX(), myLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double(blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); - - DrawUtil.drawLabel(myLocation.getText(), pixel.getX(), pixel.getY(), DrawUtil.HAlign.Center, DrawUtil.VAlign.Middle, 0, 180, 0x00FFFFFF, 255, fontScale, false, rotation); - } -} -``` - -Continue with your own implementation of [`LayerRenderer`](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/gui/journeymap/render/LayerRenderer.java). This class will cache all `DrawStep`s and provide it to JourneyMap whenever it is time to render. - -``` -class MyLayerRenderer extends LayerRenderer { - - public MyLayerRenderer() { - // You may skip MyLayerManager and use an existing ButtonManager like "OreVeinLayerManager.instance" - // Your custom layer will toggle with whatever button you specify here - super(MyLayerManager.instance); - } - - @Override - public List mapLocationProviderToDrawStep(List visibleElements) { - final List drawSteps = new ArrayList<>(); - visibleElements.stream() - .map(element -> (MyLocation) element) - .forEach(location -> drawSteps.add(new MyDrawStep(location))); - return drawSteps; - } - -} -``` - -That's already it! Now you need to register some of these classes. Forge's postInit is a good place for it: - -``` -VisualProspecting_API.LogicalClient.registerCustomLayer(MyLayerManager.instance); -VisualProspecting_API.LogicalClient.registerJourneyMapRenderer(new MyLayerRenderer()); -``` - -Now you need to launch Minecraft, teleport to the right sport (`/tp 0 80 0`) and open JourneyMap. - -If you want to extend support for your layer in other maps as well you already have half the work done. You just need to add implementations for the layer and element renderer. \ -For interactive layers you may take a look at extensions/implementations of [`WaypointProviderManager`](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/gui/model/layers/WaypointProviderManager.java) and [`ClickableDrawStep`](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/gui/journeymap/drawsteps/ClickableDrawStep.java) to get a head start. - Thank you and happy coding,\ SinTh0r4s diff --git a/dependencies.gradle b/dependencies.gradle index f801f46b..915c91dd 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,16 +1,11 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.75:dev') - api(rfg.deobf('maven.modrinth:journeymap:5.2.3')) - - devOnlyNonPublishable('com.github.GTNewHorizons:TCNodeTracker:1.3.0:dev') - - compileOnly(deobfCurse('xaeros-minimap-263420:5060684')) - compileOnly(deobfCurse('xaeros-world-map-317780:5060733')) - compileOnly(deobf('https://media.forgecdn.net/files/2462/146/mod_voxelMap_1.7.0b_for_1.7.10.litemod', 'mod_voxelMap_1.7.0b_for_1.7.10.jar')) + api('com.github.GTNewHorizons:Navigator:1.0.6:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.78:dev') // For debugging runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.8.1:dev') - runtimeOnlyNonPublishable('com.github.GTNewHorizons:ServerUtilities:2.0.60:dev') + runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.5')) + } diff --git a/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java b/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java index 154f8b1c..f92bbcaf 100644 --- a/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java +++ b/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java @@ -15,72 +15,40 @@ public static String getEnglishLocalization(Fluid fluid) { return fluid.getLocalizedName(); } - switch (fluid.getUnlocalizedName()) { - case "fluid.gas_natural_gas": - return "Natural Gas"; - case "fluid.liquid_light_oil": - return "Light Oil"; - case "fluid.liquid_medium_oil": - return "Raw Oil"; - case "fluid.liquid_heavy_oil": - return "Heavy Oil"; - case "fluid.oil": - return "Oil"; - case "fluid.drillingfluid": - return "Drilling Fluid"; - case "fluid.helium-3": - return "Helium-3"; - case "fluid.saltwater": - return "Saltwater"; - case "fluid.molten.iron": - return "Molten Iron"; - case "fluid.molten.lead": - return "Molten Lead"; - case "fluid.sulfuricacid": - return "Sulfuric Acid"; - case "fluid.carbondioxide": - return "Carbondioxide"; - case "fluid.chlorobenzene": - return "Chlorobenzene"; - case "fluid.liquid_extra_heavy_oil": - return "Extra Heavy Oil"; - case "fluid.ic2distilledwater": - return "Distilled Water"; - case "fluid.oxygen": - return "Oxygen"; - case "fluid.liquidair": - return "Liquid Air"; - case "fluid.methane": - return "Methane"; - case "fluid.ethane": - return "Ethane"; - case "fluid.liquid_hydricsulfur": - return "Liquid Hydric Sulfur"; - case "fluid.carbonmonoxide": - return "Carbonmonoxide"; - case "fluid.nitrogen": - return "Nitrogen"; - case "fluid.ethylene": - return "Ethylene"; - case "fluid.deuterium": - return "Deuterium"; - case "fluid.fluorine": - return "Fluorine"; - case "fluid.hydrofluoricacid_gt5u": - return "Hydrofluoric Acid"; - case "fluid.molten.copper": - return "Molten Copper"; - case "fluid.unknowwater": - return "Unknowwater"; - case "fluid.molten.tin": - return "Molten Tin"; - case "fluid.hydrogen": - return "Hydrogen"; - case "fluid.lava": - return "Lava"; - default: - return fluid.getUnlocalizedName(); - } + return switch (fluid.getUnlocalizedName()) { + case "fluid.gas_natural_gas" -> "Natural Gas"; + case "fluid.liquid_light_oil" -> "Light Oil"; + case "fluid.liquid_medium_oil" -> "Raw Oil"; + case "fluid.liquid_heavy_oil" -> "Heavy Oil"; + case "fluid.oil" -> "Oil"; + case "fluid.drillingfluid" -> "Drilling Fluid"; + case "fluid.helium-3" -> "Helium-3"; + case "fluid.saltwater" -> "Saltwater"; + case "fluid.molten.iron" -> "Molten Iron"; + case "fluid.molten.lead" -> "Molten Lead"; + case "fluid.sulfuricacid" -> "Sulfuric Acid"; + case "fluid.carbondioxide" -> "Carbondioxide"; + case "fluid.chlorobenzene" -> "Chlorobenzene"; + case "fluid.liquid_extra_heavy_oil" -> "Extra Heavy Oil"; + case "fluid.ic2distilledwater" -> "Distilled Water"; + case "fluid.oxygen" -> "Oxygen"; + case "fluid.liquidair" -> "Liquid Air"; + case "fluid.methane" -> "Methane"; + case "fluid.ethane" -> "Ethane"; + case "fluid.liquid_hydricsulfur" -> "Liquid Hydric Sulfur"; + case "fluid.carbonmonoxide" -> "Carbonmonoxide"; + case "fluid.nitrogen" -> "Nitrogen"; + case "fluid.ethylene" -> "Ethylene"; + case "fluid.deuterium" -> "Deuterium"; + case "fluid.fluorine" -> "Fluorine"; + case "fluid.hydrofluoricacid_gt5u" -> "Hydrofluoric Acid"; + case "fluid.molten.copper" -> "Molten Copper"; + case "fluid.unknowwater" -> "Unknowwater"; + case "fluid.molten.tin" -> "Molten Tin"; + case "fluid.hydrogen" -> "Hydrogen"; + case "fluid.lava" -> "Lava"; + default -> fluid.getUnlocalizedName(); + }; } /* @@ -93,189 +61,98 @@ public static String getEnglishLocalization(VeinType veinType) { return I18n.format(veinType.name); } - switch (veinType.name) { - case "ore.mix.naquadah": - return "Naquadah"; - case "ore.mix.lignite": - return "Lignite"; - case "ore.mix.coal": - return "Coal"; - case "ore.mix.magnetite": - return "Magnetite"; - case "ore.mix.gold": - return "Gold"; - case "ore.mix.iron": - return "Iron"; - case "ore.mix.cassiterite": - return "Cassiterite"; - case "ore.mix.tetrahedrite": - return "Tetrahedrite"; - case "ore.mix.netherquartz": - return "Nether Quartz"; - case "ore.mix.sulfur": - return "Sulfur"; - case "ore.mix.copper": - return "Copper"; - case "ore.mix.bauxite": - return "Bauxite"; - case "ore.mix.salts": - return "Salts"; - case "ore.mix.redstone": - return "Redstone"; - case "ore.mix.soapstone": - return "Soapstone"; - case "ore.mix.nickel": - return "Nickel"; - case "ore.mix.platinum": - return "Platinum"; - case "ore.mix.pitchblende": - return "Pitchblende"; - case "ore.mix.monazite": - return "Monazite"; - case "ore.mix.molybdenum": - return "Molybdenum"; - case "ore.mix.tungstate": - return "Tungstate"; - case "ore.mix.sapphire": - return "Sapphire"; - case "ore.mix.manganese": - return "Manganese"; - case "ore.mix.quartz": - return "Quartz"; - case "ore.mix.diamond": - return "Diamond"; - case "ore.mix.olivine": - return "Olivine"; - case "ore.mix.apatite": - return "Apatite"; - case "ore.mix.galena": - return "Galena"; - case "ore.mix.lapis": - return "Lapis"; - case "ore.mix.beryllium": - return "Beryllium"; - case "ore.mix.uranium": - return "Uranium"; - case "ore.mix.oilsand": - return "Oilsands"; - case "ore.mix.neutronium": - return "Neutronium"; - case "ore.mix.aquaignis": - return "Aqua and Ignis"; - case "ore.mix.terraaer": - return "Terra and Aer"; - case "ore.mix.perditioordo": - return "Perdito and Ordo"; - case "ore.mix.coppertin": - return "Vermiculite"; - case "ore.mix.titaniumchrome": - return "Ilmenite"; - case "ore.mix.mineralsand": - return "Mineralsand"; - case "ore.mix.garnettin": - return "Garnettin"; - case "ore.mix.kaolinitezeolite": - return "Kaolinite"; - case "ore.mix.mica": - return "Mica"; - case "ore.mix.dolomite": - return "Dolomite"; - case "ore.mix.platinumchrome": - return "Palladium"; - case "ore.mix.iridiummytryl": - return "Iridium"; - case "ore.mix.osmium": - return "Osmium"; - case "ore.mix.saltpeterelectrotine": - return "Electrotine"; - case "ore.mix.desh": - return "Desh"; - case "ore.mix.draconium": - return "Draconium"; - case "ore.mix.quantium": - return "Quantum"; - case "ore.mix.callistoice": - return "Callisto Ice"; - case "ore.mix.mytryl": - return "Mithril"; - case "ore.mix.ledox": - return "Ledox"; - case "ore.mix.oriharukon": - return "Oriharukon"; - case "ore.mix.blackplutonium": - return "Black Plutonium"; - case "ore.mix.infusedgold": - return "Infused Gold"; - case "ore.mix.niobium": - return "Niobium"; - case "ore.mix.tungstenirons": - return "Tungsten"; - case "ore.mix.uraniumgtnh": - return "Thorium"; - case "ore.mix.vanadiumgold": - return "Vanadium"; - case "ore.mix.netherstar": - return "NetherStar"; - case "ore.mix.garnet": - return "Garnet"; - case "ore.mix.rareearth": - return "Rare Earths"; - case "ore.mix.richnuclear": - return "Plutonium"; - case "ore.mix.heavypentele": - return "Arsenic"; - case "ore.mix.europa": - return "Magnesite"; - case "ore.mix.europacore": - return "Chrome"; - case "ore.mix.secondlanthanid": - return "Samarium"; - case "ore.mix.quartzspace": - return "Quartz"; - case "ore.mix.rutile": - return "Rutile"; - case "ore.mix.tfgalena": - return "Cryolite"; - case "ore.mix.luvtantalite": - return "Pyrolusit"; - case "ore.mix.ross128.Thorianit": - return "Thorianit"; - case "ore.mix.ross128.carbon": - return "Graphite"; - case "ore.mix.ross128.bismuth": - return "Bismuth"; - case "ore.mix.ross128.TurmalinAlkali": - return "Olenit"; - case "ore.mix.ross128.Roquesit": - return "Roquesit"; - case "ore.mix.ross128.Tungstate": - return "Scheelite"; - case "ore.mix.ross128.CopperSulfits": - return "Djurleit"; - case "ore.mix.ross128.Forsterit": - return "Forsterit"; - case "ore.mix.ross128.Hedenbergit": - return "Hedenbergit"; - case "ore.mix.ross128.RedZircon": - return "Red Zircon"; - case "ore.mix.ross128ba.tib": - return "Tiberium"; - case "ore.mix.ross128ba.Tungstate": - return "Scheelite"; - case "ore.mix.ross128ba.bart": - return "BArTiMaEuSNeK"; - case "ore.mix.ross128ba.TurmalinAlkali": - return "Olenit"; - case "ore.mix.ross128ba.Amethyst": - return "Amethyst"; - case "ore.mix.ross128ba.CopperSulfits": - return "Djurleit"; - case "ore.mix.ross128ba.RedZircon": - return "Red Zircon"; - case "ore.mix.ross128ba.Fluorspar": - return "Fluorspa"; - default: - return veinType.name; - } + return switch (veinType.name) { + case "ore.mix.naquadah" -> "Naquadah"; + case "ore.mix.lignite" -> "Lignite"; + case "ore.mix.coal" -> "Coal"; + case "ore.mix.magnetite" -> "Magnetite"; + case "ore.mix.gold" -> "Gold"; + case "ore.mix.iron" -> "Iron"; + case "ore.mix.cassiterite" -> "Cassiterite"; + case "ore.mix.tetrahedrite" -> "Tetrahedrite"; + case "ore.mix.netherquartz" -> "Nether Quartz"; + case "ore.mix.sulfur" -> "Sulfur"; + case "ore.mix.copper" -> "Copper"; + case "ore.mix.bauxite" -> "Bauxite"; + case "ore.mix.salts" -> "Salts"; + case "ore.mix.redstone" -> "Redstone"; + case "ore.mix.soapstone" -> "Soapstone"; + case "ore.mix.nickel" -> "Nickel"; + case "ore.mix.platinum" -> "Platinum"; + case "ore.mix.pitchblende" -> "Pitchblende"; + case "ore.mix.monazite" -> "Monazite"; + case "ore.mix.molybdenum" -> "Molybdenum"; + case "ore.mix.tungstate" -> "Tungstate"; + case "ore.mix.sapphire" -> "Sapphire"; + case "ore.mix.manganese" -> "Manganese"; + case "ore.mix.quartz" -> "Quartz"; + case "ore.mix.diamond" -> "Diamond"; + case "ore.mix.olivine" -> "Olivine"; + case "ore.mix.apatite" -> "Apatite"; + case "ore.mix.galena" -> "Galena"; + case "ore.mix.lapis" -> "Lapis"; + case "ore.mix.beryllium" -> "Beryllium"; + case "ore.mix.uranium" -> "Uranium"; + case "ore.mix.oilsand" -> "Oilsands"; + case "ore.mix.neutronium" -> "Neutronium"; + case "ore.mix.aquaignis" -> "Aqua and Ignis"; + case "ore.mix.terraaer" -> "Terra and Aer"; + case "ore.mix.perditioordo" -> "Perdito and Ordo"; + case "ore.mix.coppertin" -> "Vermiculite"; + case "ore.mix.titaniumchrome" -> "Ilmenite"; + case "ore.mix.mineralsand" -> "Mineralsand"; + case "ore.mix.garnettin" -> "Garnettin"; + case "ore.mix.kaolinitezeolite" -> "Kaolinite"; + case "ore.mix.mica" -> "Mica"; + case "ore.mix.dolomite" -> "Dolomite"; + case "ore.mix.platinumchrome" -> "Palladium"; + case "ore.mix.iridiummytryl" -> "Iridium"; + case "ore.mix.osmium" -> "Osmium"; + case "ore.mix.saltpeterelectrotine" -> "Electrotine"; + case "ore.mix.desh" -> "Desh"; + case "ore.mix.draconium" -> "Draconium"; + case "ore.mix.quantium" -> "Quantum"; + case "ore.mix.callistoice" -> "Callisto Ice"; + case "ore.mix.mytryl" -> "Mithril"; + case "ore.mix.ledox" -> "Ledox"; + case "ore.mix.oriharukon" -> "Oriharukon"; + case "ore.mix.blackplutonium" -> "Black Plutonium"; + case "ore.mix.infusedgold" -> "Infused Gold"; + case "ore.mix.niobium" -> "Niobium"; + case "ore.mix.tungstenirons" -> "Tungsten"; + case "ore.mix.uraniumgtnh" -> "Thorium"; + case "ore.mix.vanadiumgold" -> "Vanadium"; + case "ore.mix.netherstar" -> "NetherStar"; + case "ore.mix.garnet" -> "Garnet"; + case "ore.mix.rareearth" -> "Rare Earths"; + case "ore.mix.richnuclear" -> "Plutonium"; + case "ore.mix.heavypentele" -> "Arsenic"; + case "ore.mix.europa" -> "Magnesite"; + case "ore.mix.europacore" -> "Chrome"; + case "ore.mix.secondlanthanid" -> "Samarium"; + case "ore.mix.quartzspace" -> "Quartz"; + case "ore.mix.rutile" -> "Rutile"; + case "ore.mix.tfgalena" -> "Cryolite"; + case "ore.mix.luvtantalite" -> "Pyrolusit"; + case "ore.mix.ross128.Thorianit" -> "Thorianit"; + case "ore.mix.ross128.carbon" -> "Graphite"; + case "ore.mix.ross128.bismuth" -> "Bismuth"; + case "ore.mix.ross128.TurmalinAlkali" -> "Olenit"; + case "ore.mix.ross128.Roquesit" -> "Roquesit"; + case "ore.mix.ross128.Tungstate" -> "Scheelite"; + case "ore.mix.ross128.CopperSulfits" -> "Djurleit"; + case "ore.mix.ross128.Forsterit" -> "Forsterit"; + case "ore.mix.ross128.Hedenbergit" -> "Hedenbergit"; + case "ore.mix.ross128.RedZircon" -> "Red Zircon"; + case "ore.mix.ross128ba.tib" -> "Tiberium"; + case "ore.mix.ross128ba.Tungstate" -> "Scheelite"; + case "ore.mix.ross128ba.bart" -> "BArTiMaEuSNeK"; + case "ore.mix.ross128ba.TurmalinAlkali" -> "Olenit"; + case "ore.mix.ross128ba.Amethyst" -> "Amethyst"; + case "ore.mix.ross128ba.CopperSulfits" -> "Djurleit"; + case "ore.mix.ross128ba.RedZircon" -> "Red Zircon"; + case "ore.mix.ross128ba.Fluorspar" -> "Fluorspa"; + default -> veinType.name; + }; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 8a3b3004..978a7fb4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -41,10 +41,6 @@ public static boolean isNEIInstalled() { return Loader.isModLoaded("NotEnoughItems"); } - public static boolean isTCNodeTrackerInstalled() { - return Loader.isModLoaded("tcnodetracker"); - } - public static boolean isJourneyMapInstalled() { return Loader.isModLoaded("journeymap"); } @@ -57,15 +53,8 @@ public static boolean isXaerosMinimapInstalled() { return Loader.isModLoaded("XaeroMinimap"); } - public static boolean isVoxelMapInstalled() { - try { - // If a LiteLoader mod is present cannot be checked by calling Loader#isModLoaded. - // Instead, we check if the VoxelMap main class is present. - Class.forName("com.thevoxelbox.voxelmap.litemod.LiteModVoxelMap"); - return true; - } catch (Exception e) { - return false; - } + public static boolean isNavigatorInstalled() { + return Loader.isModLoaded("navigator"); } public static int coordBlockToChunk(int blockCoord) { diff --git a/src/main/java/com/sinthoras/visualprospecting/VP.java b/src/main/java/com/sinthoras/visualprospecting/VP.java index 1a178058..2321f7f3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VP.java +++ b/src/main/java/com/sinthoras/visualprospecting/VP.java @@ -2,8 +2,6 @@ import java.util.Random; -import net.minecraft.client.settings.KeyBinding; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -12,8 +10,6 @@ public class VP { public static SimpleNetworkWrapper network; - public static KeyBinding keyAction; - public static final Random randomGeneration = new Random(); private static Logger LOG = LogManager.getLogger(Tags.MODID); diff --git a/src/main/java/com/sinthoras/visualprospecting/VPMod.java b/src/main/java/com/sinthoras/visualprospecting/VPMod.java index 6b4e24a0..fc413c9d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VPMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/VPMod.java @@ -13,7 +13,12 @@ import cpw.mods.fml.common.event.FMLServerStoppedEvent; import cpw.mods.fml.common.event.FMLServerStoppingEvent; -@Mod(modid = Tags.MODID, version = Tags.VERSION, name = Tags.MODNAME, acceptedMinecraftVersions = "[1.7.10]") +@Mod( + modid = Tags.MODID, + version = Tags.VERSION, + name = Tags.MODNAME, + acceptedMinecraftVersions = "[1.7.10]", + dependencies = "required-after:gregtech;" + "after:navigator;") public class VPMod { @SidedProxy(clientSide = Tags.GROUPNAME + ".hooks.HooksClient", serverSide = Tags.GROUPNAME + ".hooks.HooksShared") diff --git a/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java b/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java index caecef0f..227e9deb 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java +++ b/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java @@ -1,8 +1,5 @@ package com.sinthoras.visualprospecting; -import static com.sinthoras.visualprospecting.Utils.isJourneyMapInstalled; -import static com.sinthoras.visualprospecting.Utils.isXaerosWorldMapInstalled; - import java.util.Collections; import java.util.List; @@ -14,15 +11,6 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; -import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.LayerButton; -import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; -import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.XaeroWorldMapState; import com.sinthoras.visualprospecting.network.ProspectingNotification; import cpw.mods.fml.relauncher.Side; @@ -34,74 +22,6 @@ public class VisualProspecting_API { @SideOnly(Side.CLIENT) public static class LogicalClient { - // Register the logical button - public static void registerCustomButtonManager(ButtonManager customManager) { - MapState.instance.buttons.add(customManager); - } - - // Register the logical layer - public static void registerCustomLayer(LayerManager customLayer) { - MapState.instance.layers.add(customLayer); - } - - // Register visualization for logical button in JourneyMap - public static void registerJourneyMapButton(LayerButton customButton) { - if (isJourneyMapInstalled()) { - JourneyMapState.instance.buttons.add(customButton); - } - } - - // Register visualization for logical button in Xaero's World Map - public static void registerXaeroMapButton( - com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.LayerButton customButton) { - if (isXaerosWorldMapInstalled()) { - XaeroWorldMapState.instance.buttons.add(customButton); - } - } - - // Add the JourneyMap renderer for a layer - public static void registerJourneyMapRenderer(LayerRenderer customRenderer) { - if (isJourneyMapInstalled()) { - JourneyMapState.instance.renderers.add(customRenderer); - } - } - - // Add the Xaero's World Map renderer for a layer - public static void registerXaeroMapRenderer( - com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer customRenderer) { - if (isXaerosWorldMapInstalled()) { - XaeroWorldMapState.instance.renderers.add(customRenderer); - } - } - - public static void openJourneyForOreVeinsMapAt(int blockX, int blockZ) { - if (isJourneyMapInstalled()) { - OreVeinLayerManager.instance.activateLayer(); - JourneyMapState.instance.openJourneyMapAt(blockX, blockZ); - } - } - - public static void openJourneyForOreVeinsMapAt(int blockX, int blockZ, int zoom) { - if (isJourneyMapInstalled()) { - OreVeinLayerManager.instance.activateLayer(); - JourneyMapState.instance.openJourneyMapAt(blockX, blockZ, zoom); - } - } - - public static void openJourneyMapForUndergroundFluidsAt(int blockX, int blockZ) { - if (isJourneyMapInstalled()) { - UndergroundFluidLayerManager.instance.activateLayer(); - JourneyMapState.instance.openJourneyMapAt(blockX, blockZ); - } - } - - public static void openJourneyMapForUndergroundFluidsAt(int blockX, int blockZ, int zoom) { - if (isJourneyMapInstalled()) { - UndergroundFluidLayerManager.instance.activateLayer(); - JourneyMapState.instance.openJourneyMapAt(blockX, blockZ, zoom); - } - } - // This mechanic is limited to blocks the player can touch public static void triggerProspectingForOreBlock(EntityPlayer player, World world, int blockX, int blockY, int blockZ) { @@ -121,7 +41,7 @@ public static UndergroundFluidPosition getUndergroundFluid(int dimensionId, int public static void setOreVeinDepleted(int dimensionId, int blockX, int blockZ) { final OreVeinPosition oreVeinPosition = ClientCache.instance .getOreVein(dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); - if (oreVeinPosition.isDepleted() == false) { + if (!oreVeinPosition.isDepleted()) { oreVeinPosition.toggleDepleted(); } ClientCache.instance.putOreVeins(Collections.singletonList(oreVeinPosition)); diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java index aa6ed389..4ac23cf0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java @@ -1,17 +1,17 @@ package com.sinthoras.visualprospecting.hooks; -import net.minecraft.client.settings.KeyBinding; import net.minecraftforge.client.ClientCommandHandler; import net.minecraftforge.common.MinecraftForge; -import org.lwjgl.input.Keyboard; - +import com.gtnewhorizons.navigator.api.NavigatorApi; +import com.gtnewhorizons.navigator.api.util.Util; import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ResetClientCacheCommand; +import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; +import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidChunkLayerManager; +import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.voxelmap.VoxelMapEventHandler; -import cpw.mods.fml.client.registry.ClientRegistry; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.event.FMLPostInitializationEvent; @@ -28,12 +28,9 @@ public class HooksClient extends HooksShared { // load "Do your mod setup. Build whatever data structures you care about. Register recipes." public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { super.fmlLifeCycleEvent(event); - - VP.keyAction = new KeyBinding( - "visualprospecting.key.action.name", - Keyboard.KEY_DELETE, - "visualprospecting.key.action.category"); - ClientRegistry.registerKeyBinding(VP.keyAction); + if (Utils.isNavigatorInstalled()) { + registerMapLayers(); + } } @Override @@ -48,9 +45,6 @@ public void fmlLifeCycleEvent(FMLInitializationEvent event) { public void fmlLifeCycleEvent(FMLPostInitializationEvent event) { super.fmlLifeCycleEvent(event); ClientCommandHandler.instance.registerCommand(new ResetClientCacheCommand()); - if (Utils.isVoxelMapInstalled()) { - MinecraftForge.EVENT_BUS.register(new VoxelMapEventHandler()); - } } @Override @@ -77,4 +71,15 @@ public void fmlLifeCycleEvent(FMLServerStoppingEvent event) { public void fmlLifeCycleEvent(FMLServerStoppedEvent event) { super.fmlLifeCycleEvent(event); } + + public void registerMapLayers() { + + NavigatorApi.registerLayerManager(OreVeinLayerManager.instance); + NavigatorApi.registerLayerManager(UndergroundFluidLayerManager.instance); + NavigatorApi.registerLayerManager(UndergroundFluidChunkLayerManager.instance); + + if (Util.isVoxelMapInstalled()) { + MinecraftForge.EVENT_BUS.register(new VoxelMapEventHandler()); + } + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java index e8af5e23..b885f210 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksKey.java @@ -1,13 +1,10 @@ package com.sinthoras.visualprospecting.hooks; -import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; - import net.minecraft.client.settings.KeyBinding; import org.lwjgl.input.Keyboard; import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; -import com.sinthoras.visualprospecting.integration.model.buttons.ThaumcraftNodeButtonManager; import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; import cpw.mods.fml.client.registry.ClientRegistry; @@ -26,17 +23,10 @@ public class HooksKey { "visualprospecting.key.togglefluid.name", Keyboard.KEY_NONE, "visualprospecting.key.action.category"); - private final KeyBinding keyToggleNodes = new KeyBinding( - "visualprospecting.key.togglenode.name", - Keyboard.KEY_NONE, - "visualprospecting.key.action.category"); public HooksKey() { ClientRegistry.registerKeyBinding(keyToggleOres); ClientRegistry.registerKeyBinding(keyToggleFluids); - if (isTCNodeTrackerInstalled()) { - ClientRegistry.registerKeyBinding(keyToggleNodes); - } } @SideOnly(Side.CLIENT) @@ -52,8 +42,5 @@ private void checkAndToggleOverlays() { if (keyToggleFluids.isPressed()) { UndergroundFluidButtonManager.instance.toggle(); } - if (keyToggleNodes.isPressed() && isTCNodeTrackerInstalled()) { - ThaumcraftNodeButtonManager.instance.toggle(); - } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java b/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java deleted file mode 100644 index 0ad18488..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/DrawUtils.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.sinthoras.visualprospecting.integration; - -import java.util.List; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.renderer.OpenGlHelper; -import net.minecraft.client.renderer.Tessellator; -import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.util.IIcon; -import net.minecraft.util.ResourceLocation; - -import org.lwjgl.opengl.GL11; - -import thaumcraft.api.aspects.Aspect; -import thaumcraft.client.lib.UtilsFX; - -public class DrawUtils { - - public static void drawGradientRect(double minPixelX, double minPixelY, double maxPixelX, double maxPixelY, - double z, int colorA, int colorB) { - GL11.glDisable(GL11.GL_TEXTURE_2D); - GL11.glEnable(GL11.GL_BLEND); - GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glDisable(GL11.GL_ALPHA_TEST); - GL11.glShadeModel(GL11.GL_SMOOTH); - Tessellator tessellator = Tessellator.instance; - tessellator.startDrawingQuads(); - - float alpha = (colorA >> 24 & 255) / 255.0f; - float red = (colorA >> 16 & 255) / 255.0f; - float green = (colorA >> 8 & 255) / 255.0f; - float blue = (colorA & 255) / 255.0f; - tessellator.setColorRGBA_F(red, green, blue, alpha); - tessellator.addVertex(maxPixelX, minPixelY, z); - tessellator.addVertex(minPixelX, minPixelY, z); - - alpha = (colorB >> 24 & 255) / 255.0f; - red = (colorB >> 16 & 255) / 255.0f; - green = (colorB >> 8 & 255) / 255.0f; - blue = (colorB & 255) / 255.0f; - tessellator.setColorRGBA_F(red, green, blue, alpha); - tessellator.addVertex(minPixelX, maxPixelY, z); - tessellator.addVertex(maxPixelX, maxPixelY, z); - - tessellator.draw(); - GL11.glShadeModel(GL11.GL_FLAT); - GL11.glDisable(GL11.GL_BLEND); - GL11.glEnable(GL11.GL_ALPHA_TEST); - GL11.glEnable(GL11.GL_TEXTURE_2D); - } - - public static void drawGradientRect(double minPixelX, double minPixelY, double maxPixelX, double maxPixelY, - int colorA, int colorB) { - drawGradientRect(minPixelX, minPixelY, maxPixelX, maxPixelY, 300, colorA, colorB); - } - - public static void drawQuad(ResourceLocation texture, double x, double y, double width, double height, int color, - float alpha) { - - GL11.glEnable(GL11.GL_BLEND); - OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); - - GL11.glEnable(GL11.GL_TEXTURE_2D); - Minecraft.getMinecraft().getTextureManager().bindTexture(texture); - - float[] c = floats(color); - GL11.glColor4f(c[0], c[1], c[2], alpha); - - Tessellator tessellator = Tessellator.instance; - tessellator.startDrawingQuads(); - tessellator.addVertexWithUV(x, y + height, 0.0, 0.0, 1.0); - tessellator.addVertexWithUV(x + width, y + height, 0.0, 1.0, 1.0); - tessellator.addVertexWithUV(x + width, y, 0.0, 1.0, 0.0); - tessellator.addVertexWithUV(x, y, 0.0, 0.0, 0.0); - tessellator.draw(); - } - - public static void drawQuad(IIcon icon, double x, double y, double width, double height, int color, float alpha) { - - GL11.glEnable(GL11.GL_BLEND); - OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0); - - GL11.glEnable(GL11.GL_TEXTURE_2D); - Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture); - - float[] c = floats(color); - GL11.glColor4f(c[0], c[1], c[2], alpha); - - Tessellator tessellator = Tessellator.instance; - tessellator.startDrawingQuads(); - tessellator.addVertexWithUV(x, y + height, 0.0, icon.getMinU(), icon.getMaxV()); - tessellator.addVertexWithUV(x + width, y + height, 0.0, icon.getMaxU(), icon.getMaxV()); - tessellator.addVertexWithUV(x + width, y, 0.0, icon.getMaxU(), icon.getMinV()); - tessellator.addVertexWithUV(x, y, 0.0, icon.getMinU(), icon.getMinV()); - tessellator.draw(); - } - - public static void drawAspect(double centerPixelX, double centerPixelY, double pixelSize, Aspect aspect, - int amount) { - final int textureSize = 16; - - GL11.glPushMatrix(); - final double scale = pixelSize / textureSize; - GL11.glScaled(scale, scale, scale); - UtilsFX.drawTag( - (centerPixelX - pixelSize / 2) / scale, - (centerPixelY - pixelSize / 2) / scale, - aspect, - amount, - 0, - 0, - GL11.GL_ONE_MINUS_SRC_ALPHA, - 1.0F, - false); - GL11.glDisable(GL11.GL_LIGHTING); - GL11.glPopMatrix(); - } - - public static void drawSimpleLabel(GuiScreen gui, String text, double textX, double textY, int fontColor, - int bgColor, boolean centered) { - GL11.glPushMatrix(); - double dTextX = textX - (double) (int) textX; - double dTextY = textY - (double) (int) textY; - double textWidth = gui.mc.fontRenderer.getStringWidth(text); - double xOffsetL = centered ? -textWidth / 2.0 - 2 : -2; - double xOffsetR = centered ? textWidth / 2.0 + 2 : textWidth + 2; - GL11.glTranslated(dTextX, dTextY, 0.0); - drawGradientRect( - (int) textX + xOffsetL, - (int) textY - 2, - (int) textX + xOffsetR, - (int) textY + gui.mc.fontRenderer.FONT_HEIGHT + 2, - 0, - bgColor, - bgColor); - if (centered) gui.drawCenteredString(gui.mc.fontRenderer, text, (int) textX, (int) textY, fontColor); - else gui.drawString(gui.mc.fontRenderer, text, (int) textX, (int) textY, fontColor); - GL11.glPopMatrix(); - } - - public static void drawLabel(String text, double textX, double textY, int fontColor, int bgColor, boolean centered, - double fontScale) { - final FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer; - - GL11.glPushMatrix(); - - if (fontScale != 1.0) { - textX /= fontScale; - textY /= fontScale; - GL11.glScaled(fontScale, fontScale, 0); - } - double dTextX = textX - (double) (int) textX; - double dTextY = textY - (double) (int) textY; - double textWidth = fontRenderer.getStringWidth(text); - double xOffsetL = centered ? -textWidth / 2.0 - 2 : -2; - double xOffsetR = centered ? textWidth / 2.0 + 2 : textWidth + 2; - GL11.glTranslated(dTextX, dTextY, 0.0); - drawGradientRect( - (int) textX + xOffsetL, - (int) textY - 2, - (int) textX + xOffsetR, - (int) textY + fontRenderer.FONT_HEIGHT + 2, - 0, - bgColor, - bgColor); - fontRenderer.drawStringWithShadow( - text, - (centered ? (int) (textX - textWidth / 2.0) : (int) textX), - (int) textY, - fontColor); - GL11.glPopMatrix(); - } - - public static void drawSimpleTooltip(GuiScreen gui, List text, double x, double y, int fontColor, - int bgColor) { - if (text.isEmpty()) return; - - int maxTextWidth = 0; - for (String str : text) { - int strWidth = gui.mc.fontRenderer.getStringWidth(str); - if (strWidth > maxTextWidth) maxTextWidth = strWidth; - } - - int boxWidth = maxTextWidth + 6; - int boxHeight = text.size() * (gui.mc.fontRenderer.FONT_HEIGHT + 2) + 6; - - double dx = x - (double) (int) x; - double dy = y - (double) (int) y; - - GL11.glPushMatrix(); - - drawGradientRect(x, y, x + boxWidth, y + boxHeight, bgColor, bgColor); - GL11.glTranslated(dx, dy, 301); - for (int i = 0; i < text.size(); i++) { - gui.drawString( - gui.mc.fontRenderer, - text.get(i), - (int) x + 3, - (int) y + 3 + i * (gui.mc.fontRenderer.FONT_HEIGHT + 2), - fontColor); - } - - GL11.glPopMatrix(); - } - - public static float[] floats(int rgb) { - return new float[] { (float) (rgb >> 16 & 255) / 255.0F, (float) (rgb >> 8 & 255) / 255.0F, - (float) (rgb & 255) / 255.0F }; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java deleted file mode 100644 index 7cc47477..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/JourneyMapState.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap; - -import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; - -import java.util.ArrayList; -import java.util.List; - -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.DirtyChunkButton; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.LayerButton; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.OreVeinButton; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.ThaumcraftNodeButton; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.UndergroundFluidButton; -import com.sinthoras.visualprospecting.integration.journeymap.render.DirtyChunkRenderer; -import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; -import com.sinthoras.visualprospecting.integration.journeymap.render.OreVeinRenderer; -import com.sinthoras.visualprospecting.integration.journeymap.render.ThaumcraftNodeRenderer; -import com.sinthoras.visualprospecting.integration.journeymap.render.UndergroundFluidChunkRenderer; -import com.sinthoras.visualprospecting.integration.journeymap.render.UndergroundFluidRenderer; -import com.sinthoras.visualprospecting.integration.journeymap.waypoints.OreVeinWaypointManager; -import com.sinthoras.visualprospecting.integration.journeymap.waypoints.ThaumcraftNodeWaypointManager; -import com.sinthoras.visualprospecting.integration.journeymap.waypoints.WaypointManager; -import com.sinthoras.visualprospecting.mixins.late.journeymap.FullscreenAccessor; - -import journeymap.client.render.map.GridRenderer; - -public class JourneyMapState { - - public static JourneyMapState instance = new JourneyMapState(); - - public final List buttons = new ArrayList<>(); - public final List renderers = new ArrayList<>(); - public final List waypointManagers = new ArrayList<>(); - - public JourneyMapState() { - if (isTCNodeTrackerInstalled()) { - buttons.add(ThaumcraftNodeButton.instance); - renderers.add(ThaumcraftNodeRenderer.instance); - waypointManagers.add(ThaumcraftNodeWaypointManager.instance); - } - - buttons.add(UndergroundFluidButton.instance); - renderers.add(UndergroundFluidRenderer.instance); - renderers.add(UndergroundFluidChunkRenderer.instance); - - buttons.add(OreVeinButton.instance); - renderers.add(OreVeinRenderer.instance); - waypointManagers.add(OreVeinWaypointManager.instance); - - if (Config.enableDeveloperOverlays) { - buttons.add(DirtyChunkButton.instance); - renderers.add(DirtyChunkRenderer.instance); - } - } - - public void openJourneyMapAt(int blockX, int blockZ) { - final GridRenderer gridRenderer = FullscreenAccessor.getGridRenderer(); - assert gridRenderer != null; - gridRenderer.center(gridRenderer.getMapType(), blockX, blockZ, gridRenderer.getZoom()); - } - - public void openJourneyMapAt(int blockX, int blockZ, int zoom) { - final GridRenderer gridRenderer = FullscreenAccessor.getGridRenderer(); - assert gridRenderer != null; - gridRenderer.center(gridRenderer.getMapType(), blockX, blockZ, zoom); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java deleted file mode 100644 index a6a6a890..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/ResetClientCacheConfirmation.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.resources.I18n; -import net.minecraft.util.ChatComponentTranslation; -import net.minecraft.util.IChatComponent; - -import com.sinthoras.visualprospecting.database.ClientCache; - -import journeymap.client.ui.UIManager; -import journeymap.client.ui.component.Button; -import journeymap.client.ui.component.ButtonList; -import journeymap.client.ui.component.JmUI; - -public class ResetClientCacheConfirmation extends JmUI { - - private Button confirmButton; - private Button cancelButton; - - public ResetClientCacheConfirmation() { - super(I18n.format("visualprospecting.resetprogress.title")); - } - - public void func_73866_w_() { - buttonList.clear(); - confirmButton = new Button(I18n.format("visualprospecting.resetprogress.confirm")); - cancelButton = new Button(I18n.format("visualprospecting.resetprogress.cancel")); - buttonList.add(confirmButton); - buttonList.add(cancelButton); - } - - protected void layoutButtons() { - if (buttonList.isEmpty()) { - func_73866_w_(); - } - final int x = width / 2; - final int y = height / 2; - drawCenteredString(getFontRenderer(), I18n.format("visualprospecting.resetprogress.prompt"), x, y, 0xFFFFFF); - final ButtonList row = new ButtonList(confirmButton, cancelButton); - row.layoutCenteredHorizontal(x, y + 18, true, 4); - } - - protected void func_146284_a(GuiButton guibutton) { - if (guibutton == confirmButton) { - ClientCache.instance.resetPlayerProgression(); - final IChatComponent confirmation = new ChatComponentTranslation( - "visualprospecting.resetprogress.confirmation"); - confirmation.getChatStyle().setItalic(true); - Minecraft.getMinecraft().thePlayer.addChatMessage(confirmation); - UIManager.getInstance().openFullscreenMap(); - } else if (guibutton == cancelButton) { - UIManager.getInstance().openMapActions(); - } - } - - protected void func_73869_a(char c, int i) { - switch (i) { - case 1: - UIManager.getInstance().openMapActions(); - default: - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/DirtyChunkButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/DirtyChunkButton.java deleted file mode 100644 index cfb61f5d..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/DirtyChunkButton.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.buttons; - -import com.sinthoras.visualprospecting.integration.model.buttons.DirtyChunkButtonManager; - -public class DirtyChunkButton extends LayerButton { - - public static final DirtyChunkButton instance = new DirtyChunkButton(); - - public DirtyChunkButton() { - super(DirtyChunkButtonManager.instance); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java deleted file mode 100644 index 4e179a9f..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/LayerButton.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.buttons; - -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; - -import journeymap.client.ui.theme.ThemeToggle; - -public class LayerButton extends com.sinthoras.visualprospecting.integration.model.buttons.LayerButton { - - private ThemeToggle button; - private final ButtonManager manager; - - private boolean isActive = false; - - public LayerButton(ButtonManager manager) { - super(manager, SupportedMods.JourneyMap); - this.manager = manager; - } - - @Override - public void updateState(boolean active) { - isActive = active; - if (button != null) { - button.setToggled(active, false); - } - } - - public void setButton(ThemeToggle button) { - this.button = button; - } - - public String getButtonTextKey() { - return manager.getButtonTextKey(); - } - - public String getIconName() { - return manager.getIconName(); - } - - public boolean isActive() { - return isActive; - } - - public void toggle() { - manager.toggle(); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/OreVeinButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/OreVeinButton.java deleted file mode 100644 index cea077ee..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/OreVeinButton.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.buttons; - -import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; - -public class OreVeinButton extends LayerButton { - - public static final OreVeinButton instance = new OreVeinButton(); - - public OreVeinButton() { - super(OreVeinButtonManager.instance); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/ThaumcraftNodeButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/ThaumcraftNodeButton.java deleted file mode 100644 index 3ac64db9..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/ThaumcraftNodeButton.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.buttons; - -import com.sinthoras.visualprospecting.integration.model.buttons.ThaumcraftNodeButtonManager; - -public class ThaumcraftNodeButton extends LayerButton { - - public static final ThaumcraftNodeButton instance = new ThaumcraftNodeButton(); - - public ThaumcraftNodeButton() { - super(ThaumcraftNodeButtonManager.instance); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/UndergroundFluidButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/UndergroundFluidButton.java deleted file mode 100644 index edd40a15..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/buttons/UndergroundFluidButton.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.buttons; - -import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; - -public class UndergroundFluidButton extends LayerButton { - - public static final UndergroundFluidButton instance = new UndergroundFluidButton(); - - public UndergroundFluidButton() { - super(UndergroundFluidButtonManager.instance); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java deleted file mode 100644 index f8c04d55..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ClickableDrawStep.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; - -import java.util.List; - -import net.minecraft.client.gui.FontRenderer; - -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; - -import journeymap.client.render.draw.DrawStep; - -public interface ClickableDrawStep extends DrawStep { - - List getTooltip(); - - void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, int displayHeight); - - boolean isMouseOver(int mouseX, int mouseY); - - void onActionKeyPressed(); - - IWaypointAndLocationProvider getLocationProvider(); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java deleted file mode 100644 index 580524db..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/DirtyChunkDrawStep.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; - -import java.awt.geom.Point2D; - -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; - -import journeymap.client.render.draw.DrawStep; -import journeymap.client.render.draw.DrawUtil; -import journeymap.client.render.map.GridRenderer; - -public class DirtyChunkDrawStep implements DrawStep { - - private final DirtyChunkLocation dirtyChunkLocation; - - public DirtyChunkDrawStep(DirtyChunkLocation dirtyChunkLocation) { - this.dirtyChunkLocation = dirtyChunkLocation; - } - - @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, - double fontScale, double rotation) { - final int zoom = gridRenderer.getZoom(); - double blockSize = Math.pow(2, zoom); - final Point2D.Double blockAsPixel = gridRenderer - .getBlockPixelInGrid(dirtyChunkLocation.getBlockX(), dirtyChunkLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double( - blockAsPixel.getX() + draggedPixelX, - blockAsPixel.getY() + draggedPixelY); - float alpha = 0.5f; - alpha *= alpha * 204; - int color = dirtyChunkLocation.isDirty() ? 0xFF0000 : 0x00FFAA; - DrawUtil.drawRectangle( - pixel.getX(), - pixel.getY(), - VP.chunkWidth * blockSize, - VP.chunkDepth * blockSize, - color, - (int) alpha); - - if (dirtyChunkLocation.isDirty()) { - final int borderColor = 0xFFD700; - final int borderAlpha = 204; - DrawUtil.drawRectangle(pixel.getX(), pixel.getY(), 15 * blockSize, blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle( - pixel.getX() + 15 * blockSize, - pixel.getY(), - blockSize, - 15 * blockSize, - borderColor, - borderAlpha); - DrawUtil.drawRectangle( - pixel.getX() + 1 * blockSize, - pixel.getY() + 15 * blockSize, - 15 * blockSize, - blockSize, - borderColor, - borderAlpha); - DrawUtil.drawRectangle( - pixel.getX(), - pixel.getY() + 1 * blockSize, - blockSize, - 15 * blockSize, - borderColor, - borderAlpha); - - DrawUtil.drawLabel( - "D", - pixel.getX() + 13 * blockSize, - pixel.getY() + 13 * blockSize, - DrawUtil.HAlign.Left, - DrawUtil.VAlign.Above, - 0, - 180, - 0x00FFFFFF, - 255, - fontScale, - false, - rotation); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java index fbab57e1..8e4898f8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java @@ -1,7 +1,6 @@ package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; import java.awt.geom.Point2D; -import java.util.ArrayList; import java.util.List; import net.minecraft.client.gui.FontRenderer; @@ -9,16 +8,17 @@ import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; +import com.gtnewhorizons.navigator.api.journeymap.drawsteps.JMInteractableStep; +import com.gtnewhorizons.navigator.api.model.locations.IWaypointAndLocationProvider; +import com.gtnewhorizons.navigator.api.util.DrawUtils; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.integration.DrawUtils; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; -public class OreVeinDrawStep implements ClickableDrawStep { +public class OreVeinDrawStep implements JMInteractableStep { private static final ResourceLocation depletedTextureLocation = new ResourceLocation( Tags.MODID, @@ -35,8 +35,7 @@ public OreVeinDrawStep(OreVeinLocation oreVeinLocation) { } @Override - public List getTooltip() { - final List tooltip = new ArrayList<>(); + public void getTooltip(List tooltip) { if (oreVeinLocation.isDepleted()) { tooltip.add(oreVeinLocation.getDepletedHint()); } @@ -44,15 +43,15 @@ public List getTooltip() { tooltip.add(oreVeinLocation.getActiveWaypointHint()); } tooltip.add(oreVeinLocation.getName()); - if (oreVeinLocation.isDepleted() == false) { + if (!oreVeinLocation.isDepleted()) { tooltip.addAll(oreVeinLocation.getMaterialNames()); } tooltip.add(oreVeinLocation.getToggleDepletedHint()); - return tooltip; } @Override - public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, int displayHeight) {} + public void drawCustomTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, + int displayHeight) {} @Override public boolean isMouseOver(int mouseX, int mouseY) { @@ -80,7 +79,7 @@ public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRe blockAsPixel.getX() + draggedPixelX, blockAsPixel.getY() + draggedPixelY); - if (gridRenderer.getZoom() >= Config.minZoomLevelForOreLabel && oreVeinLocation.isDepleted() == false) { + if (gridRenderer.getZoom() >= Config.minZoomLevelForOreLabel && !oreVeinLocation.isDepleted()) { final int fontColor = oreVeinLocation.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F; DrawUtil.drawLabel( oreVeinLocation.getName(), @@ -111,7 +110,7 @@ public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRe oreVeinLocation.getColor(), 255); - if (oreVeinLocation.drawSearchHighlight() == false || oreVeinLocation.isDepleted()) { + if (!oreVeinLocation.drawSearchHighlight() || oreVeinLocation.isDepleted()) { DrawUtil.drawRectangle(iconX, iconY, iconSize, iconSize, 0x000000, 150); if (oreVeinLocation.isDepleted()) { DrawUtils.drawQuad(depletedTextureLocation, iconX, iconY, iconSize, iconSize, 0xFFFFFF, 255); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java deleted file mode 100644 index 47539d54..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/ThaumcraftNodeDrawStep.java +++ /dev/null @@ -1,265 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; - -import java.awt.geom.Point2D; -import java.util.List; - -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.renderer.RenderHelper; -import net.minecraft.util.ResourceLocation; - -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL12; - -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.integration.DrawUtils; -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; -import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; - -import journeymap.client.render.map.GridRenderer; -import thaumcraft.api.aspects.Aspect; -import thaumcraft.client.lib.UtilsFX; - -public class ThaumcraftNodeDrawStep implements ClickableDrawStep { - - private static final ResourceLocation markedTextureLocation = new ResourceLocation( - Tags.MODID, - "textures/node_marked.png"); - private static final ResourceLocation unmarkedTextureLocation = new ResourceLocation( - Tags.MODID, - "textures/node_unmarked.png"); - - private final ThaumcraftNodeLocation thaumcraftNodeLocation; - - private double centerPixelX = 0; - private double centerPixelY = 0; - private double clickableRadiusPixelSquared = 0; - - public ThaumcraftNodeDrawStep(ThaumcraftNodeLocation thaumcraftNodeLocation) { - this.thaumcraftNodeLocation = thaumcraftNodeLocation; - } - - @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, - double fontScale, double rotation) { - final double borderSize = 44 * drawScale; - final double borderSizeHalf = borderSize / 2; - final Point2D.Double blockAsPixel = gridRenderer - .getBlockPixelInGrid(thaumcraftNodeLocation.getBlockX(), thaumcraftNodeLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double( - blockAsPixel.getX() + draggedPixelX, - blockAsPixel.getY() + draggedPixelY); - centerPixelX = pixel.getX(); - centerPixelY = pixel.getY(); - clickableRadiusPixelSquared = borderSizeHalf * borderSizeHalf; - - final int alpha = 204; - DrawUtils.drawQuad( - thaumcraftNodeLocation.isActiveAsWaypoint() ? markedTextureLocation : unmarkedTextureLocation, - pixel.getX() - borderSizeHalf, - pixel.getY() - borderSizeHalf, - borderSize, - borderSize, - 0xFFFFFF, - alpha); - - final int aspectPixelDiameter = 32; - DrawUtils.drawAspect( - pixel.getX(), - pixel.getY(), - aspectPixelDiameter, - thaumcraftNodeLocation.getStrongestAspect(), - 0); - } - - public List getTooltip() { - return null; - } - - public boolean isMouseOver(int mouseX, int mouseY) { - final double deltaX = mouseX - centerPixelX; - final double deltaY = mouseY - centerPixelY; - return deltaX * deltaX + deltaY * deltaY <= clickableRadiusPixelSquared; - } - - public void onActionKeyPressed() { - ThaumcraftNodeLayerManager.instance.deleteNode(thaumcraftNodeLocation); - } - - @Override - public IWaypointAndLocationProvider getLocationProvider() { - return thaumcraftNodeLocation; - } - - public void drawTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, int displayHeight) { - final boolean isWaypoint = thaumcraftNodeLocation.isActiveAsWaypoint(); - final String activeWaypointHint = thaumcraftNodeLocation.getActiveWaypointHint(); - final String title = thaumcraftNodeLocation.getTitle(); - final String nodeDescription = thaumcraftNodeLocation.getDescription(); - final String deleteHint = thaumcraftNodeLocation.getDeleteHint(); - - int maxTextWidth = Math.max( - Math.max(fontRenderer.getStringWidth(title), fontRenderer.getStringWidth(nodeDescription)), - fontRenderer.getStringWidth(deleteHint)); - if (isWaypoint) { - maxTextWidth = Math.max(maxTextWidth, fontRenderer.getStringWidth(activeWaypointHint)); - } - if (fontRenderer.getBidiFlag()) { - maxTextWidth = (int) Math.ceil(maxTextWidth * 1.25f); - } - - final int aspectRows = (thaumcraftNodeLocation.getAspects().size() + 4) / 5; // Equivalent to Math.ceil(size / - // 5) - final int aspectColumns = Math.min(thaumcraftNodeLocation.getAspects().size(), 5); - - int pixelX = mouseX + 12; - int pixelY = mouseY - 12; - final int tooltipHeight = (isWaypoint ? 44 : 32) + aspectRows * 16; - final int tooltipWidth = Math.max(aspectColumns * 16, maxTextWidth); - if (pixelX + tooltipWidth > displayWidth) { - pixelX -= 28 + tooltipWidth; - } - if (pixelY + tooltipHeight + 6 > displayHeight) { - pixelY = displayHeight - tooltipHeight - 6; - } - - GL11.glDisable(GL12.GL_RESCALE_NORMAL); - RenderHelper.disableStandardItemLighting(); - GL11.glDisable(GL11.GL_LIGHTING); - GL11.glDisable(GL11.GL_DEPTH_TEST); - - // Draw background - final int backgroundColor = 0xF0100010; - DrawUtils.drawGradientRect( - pixelX - 3, - pixelY - 4, - pixelX + tooltipWidth + 3, - pixelY - 3, - backgroundColor, - backgroundColor); - DrawUtils.drawGradientRect( - pixelX - 3, - pixelY + tooltipHeight + 3, - pixelX + tooltipWidth + 3, - pixelY + tooltipHeight + 4, - backgroundColor, - backgroundColor); - DrawUtils.drawGradientRect( - pixelX - 3, - pixelY - 3, - pixelX + tooltipWidth + 3, - pixelY + tooltipHeight + 3, - backgroundColor, - backgroundColor); - DrawUtils.drawGradientRect( - pixelX - 4, - pixelY - 3, - pixelX - 3, - pixelY + tooltipHeight + 3, - backgroundColor, - backgroundColor); - DrawUtils.drawGradientRect( - pixelX + tooltipWidth + 3, - pixelY - 3, - pixelX + tooltipWidth + 4, - pixelY + tooltipHeight + 3, - backgroundColor, - backgroundColor); - - int verdunGreen = 0x505000FF; - int borderColor = 0x5028007F; - DrawUtils.drawGradientRect( - pixelX - 3, - pixelY - 3 + 1, - pixelX - 3 + 1, - pixelY + tooltipHeight + 3 - 1, - verdunGreen, - borderColor); - DrawUtils.drawGradientRect( - pixelX + tooltipWidth + 2, - pixelY - 3 + 1, - pixelX + tooltipWidth + 3, - pixelY + tooltipHeight + 3 - 1, - verdunGreen, - borderColor); - DrawUtils.drawGradientRect( - pixelX - 3, - pixelY - 3, - pixelX + tooltipWidth + 3, - pixelY - 3 + 1, - verdunGreen, - verdunGreen); - DrawUtils.drawGradientRect( - pixelX - 3, - pixelY + tooltipHeight + 2, - pixelX + tooltipWidth + 3, - pixelY + tooltipHeight + 3, - borderColor, - borderColor); - - // Draw text - int offset = 0; - if (fontRenderer.getBidiFlag()) { - if (isWaypoint) { - final int asWaypointWidth = (int) Math.ceil(fontRenderer.getStringWidth(activeWaypointHint) * 1.1f); - fontRenderer.drawString(title, pixelX + tooltipWidth - asWaypointWidth, pixelY, 0xFFFFFFFF); - offset += 12; - } - final int titleWidth = (int) Math.ceil(fontRenderer.getStringWidth(title) * 1.1f); - fontRenderer.drawString(title, pixelX + tooltipWidth - titleWidth, pixelY + offset, 0xFFFFFFFF); - offset += 12; - final int nodeDescriptonWidth = (int) Math.ceil(fontRenderer.getStringWidth(nodeDescription) * 1.1f); - fontRenderer.drawString( - nodeDescription, - pixelX + nodeDescriptonWidth - titleWidth, - pixelY + offset, - 0xFFFFFFFF); - - final int deleteHintWidth = (int) Math.ceil(fontRenderer.getStringWidth(deleteHint) * 1.1f); - fontRenderer.drawString( - deleteHint, - pixelX + tooltipWidth - deleteHintWidth, - pixelY + aspectRows * 16 + offset + 12, - 0xFFFFFFFF); - } else { - if (isWaypoint) { - fontRenderer.drawString(activeWaypointHint, pixelX, pixelY, 0xFFFFFFFF); - offset += 12; - } - fontRenderer.drawString(title, pixelX, pixelY + offset, 0xFFFFFFFF); - offset += 12; - fontRenderer.drawString(nodeDescription, pixelX, pixelY + offset, 0xFFFFFFFF); - - fontRenderer.drawString(deleteHint, pixelX, pixelY + aspectRows * 16 + offset + 12, 0xFFFFFFFF); - } - - // Draw aspects - int aspectX = 0; - int aspectY = 0; - - for (Aspect aspect : thaumcraftNodeLocation.getAspects().getAspectsSortedAmount()) { - GL11.glPushMatrix(); - UtilsFX.drawTag( - pixelX + aspectX * 16, - pixelY + aspectY * 16 + offset + 10, - aspect, - thaumcraftNodeLocation.getAspects().getAmount(aspect), - 0, - 0.01, - 1, - 1, - false); - GL11.glPopMatrix(); - ++aspectX; - if (aspectX >= 5) { - aspectX = 0; - ++aspectY; - } - } - - GL11.glEnable(GL11.GL_LIGHTING); - GL11.glEnable(GL11.GL_DEPTH_TEST); - RenderHelper.enableStandardItemLighting(); - GL11.glEnable(GL12.GL_RESCALE_NORMAL); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java index 8ec22120..8a49662e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java @@ -2,15 +2,15 @@ import java.awt.geom.Point2D; +import com.gtnewhorizons.navigator.api.journeymap.drawsteps.JMRenderStep; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -import journeymap.client.render.draw.DrawStep; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; -public class UndergroundFluidChunkDrawStep implements DrawStep { +public class UndergroundFluidChunkDrawStep implements JMRenderStep { private final UndergroundFluidChunkLocation undergroundFluidChunkLocation; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java index 5162fd64..467099b7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java @@ -4,14 +4,14 @@ import net.minecraft.client.resources.I18n; +import com.gtnewhorizons.navigator.api.journeymap.drawsteps.JMRenderStep; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; -import journeymap.client.render.draw.DrawStep; import journeymap.client.render.draw.DrawUtil; import journeymap.client.render.map.GridRenderer; -public class UndergroundFluidDrawStep implements DrawStep { +public class UndergroundFluidDrawStep implements JMRenderStep { private final UndergroundFluidLocation undergroundFluidLocation; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java deleted file mode 100644 index a2476eb6..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/DirtyChunkRenderer.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.render; - -import java.util.ArrayList; -import java.util.List; - -import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.DirtyChunkDrawStep; -import com.sinthoras.visualprospecting.integration.model.layers.DirtyChunkLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; - -import journeymap.client.render.draw.DrawStep; - -public class DirtyChunkRenderer extends LayerRenderer { - - public static final DirtyChunkRenderer instance = new DirtyChunkRenderer(); - - public DirtyChunkRenderer() { - super(DirtyChunkLayerManager.instance); - } - - @Override - public List mapLocationProviderToDrawStep(List visibleElements) { - final List drawSteps = new ArrayList<>(); - visibleElements.stream().map(element -> (DirtyChunkLocation) element) - .forEach(location -> drawSteps.add(new DirtyChunkDrawStep(location))); - return drawSteps; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMOreVeinRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMOreVeinRenderer.java new file mode 100644 index 00000000..1f53a50e --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMOreVeinRenderer.java @@ -0,0 +1,26 @@ +package com.sinthoras.visualprospecting.integration.journeymap.render; + +import java.util.ArrayList; +import java.util.List; + +import com.gtnewhorizons.navigator.api.journeymap.render.JMInteractableLayerRenderer; +import com.gtnewhorizons.navigator.api.model.layers.InteractableLayerManager; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.model.steps.RenderStep; +import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.OreVeinDrawStep; +import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; + +public class JMOreVeinRenderer extends JMInteractableLayerRenderer { + + public JMOreVeinRenderer(InteractableLayerManager manager) { + super(manager); + } + + @Override + protected List generateRenderSteps(List visibleElements) { + final List drawSteps = new ArrayList<>(); + visibleElements.stream().map(element -> (OreVeinLocation) element) + .forEach(location -> drawSteps.add(new OreVeinDrawStep(location))); + return drawSteps; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidChunkRenderer.java similarity index 51% rename from src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java rename to src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidChunkRenderer.java index 1dfcc956..de0245d9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidChunkRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidChunkRenderer.java @@ -3,23 +3,21 @@ import java.util.ArrayList; import java.util.List; +import com.gtnewhorizons.navigator.api.journeymap.render.JMLayerRenderer; +import com.gtnewhorizons.navigator.api.model.layers.LayerManager; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.model.steps.RenderStep; import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.UndergroundFluidChunkDrawStep; -import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidChunkLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -import journeymap.client.render.draw.DrawStep; +public class JMUndergroundFluidChunkRenderer extends JMLayerRenderer { -public class UndergroundFluidChunkRenderer extends LayerRenderer { - - public static final UndergroundFluidChunkRenderer instance = new UndergroundFluidChunkRenderer(); - - public UndergroundFluidChunkRenderer() { - super(UndergroundFluidChunkLayerManager.instance); + public JMUndergroundFluidChunkRenderer(LayerManager manager) { + super(manager); } @Override - public List mapLocationProviderToDrawStep(List visibleElements) { + protected List generateRenderSteps(List visibleElements) { final List drawSteps = new ArrayList<>(); visibleElements.stream().map(element -> (UndergroundFluidChunkLocation) element) .forEach(location -> drawSteps.add(new UndergroundFluidChunkDrawStep(location))); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidRenderer.java similarity index 51% rename from src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java rename to src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidRenderer.java index d4978646..62acc735 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/UndergroundFluidRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidRenderer.java @@ -3,23 +3,21 @@ import java.util.ArrayList; import java.util.List; +import com.gtnewhorizons.navigator.api.journeymap.render.JMLayerRenderer; +import com.gtnewhorizons.navigator.api.model.layers.LayerManager; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.model.steps.RenderStep; import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.UndergroundFluidDrawStep; -import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; -import journeymap.client.render.draw.DrawStep; +public class JMUndergroundFluidRenderer extends JMLayerRenderer { -public class UndergroundFluidRenderer extends LayerRenderer { - - public static final UndergroundFluidRenderer instance = new UndergroundFluidRenderer(); - - public UndergroundFluidRenderer() { - super(UndergroundFluidLayerManager.instance); + public JMUndergroundFluidRenderer(LayerManager manager) { + super(manager); } @Override - public List mapLocationProviderToDrawStep(List visibleElements) { + protected List generateRenderSteps(List visibleElements) { final List drawSteps = new ArrayList<>(); visibleElements.stream().map(element -> (UndergroundFluidLocation) element) .forEach(location -> drawSteps.add(new UndergroundFluidDrawStep(location))); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java deleted file mode 100644 index 8f539c56..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/LayerRenderer.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.render; - -import java.util.ArrayList; -import java.util.List; - -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; - -import journeymap.client.render.draw.DrawStep; - -public abstract class LayerRenderer extends com.sinthoras.visualprospecting.integration.model.layers.LayerRenderer { - - private final LayerManager manager; - - protected List drawSteps = new ArrayList<>(); - - public LayerRenderer(LayerManager manager) { - super(manager, SupportedMods.JourneyMap); - this.manager = manager; - } - - public boolean isLayerActive() { - return manager.isLayerActive(); - } - - public List getDrawStepsCachedForInteraction() { - return drawSteps; - } - - public List getDrawStepsCachedForRendering() { - return drawSteps; - } - - @Override - public void updateVisibleElements(List visibleElements) { - drawSteps = (List) mapLocationProviderToDrawStep(visibleElements); - } - - protected abstract List mapLocationProviderToDrawStep( - List visibleElements); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java deleted file mode 100644 index 410172bc..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/OreVeinRenderer.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.render; - -import java.util.ArrayList; -import java.util.List; - -import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.ClickableDrawStep; -import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.OreVeinDrawStep; -import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; -import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; - -public class OreVeinRenderer extends WaypointProviderLayerRenderer { - - public static final OreVeinRenderer instance = new OreVeinRenderer(); - - public OreVeinRenderer() { - super(OreVeinLayerManager.instance); - } - - @Override - public List mapLocationProviderToDrawStep( - List visibleElements) { - final List drawSteps = new ArrayList<>(); - visibleElements.stream().map(element -> (OreVeinLocation) element) - .forEach(location -> drawSteps.add(new OreVeinDrawStep(location))); - return drawSteps; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java deleted file mode 100644 index 408188f8..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/ThaumcraftNodeRenderer.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.render; - -import java.util.ArrayList; -import java.util.List; - -import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.ClickableDrawStep; -import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.ThaumcraftNodeDrawStep; -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; -import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; - -public class ThaumcraftNodeRenderer extends WaypointProviderLayerRenderer { - - public static ThaumcraftNodeRenderer instance = new ThaumcraftNodeRenderer(); - - public ThaumcraftNodeRenderer() { - super(ThaumcraftNodeLayerManager.instance); - } - - @Override - public List mapLocationProviderToDrawStep( - List visibleElements) { - final List drawSteps = new ArrayList<>(); - visibleElements.stream().map(element -> (ThaumcraftNodeLocation) element) - .forEach(location -> drawSteps.add(new ThaumcraftNodeDrawStep(location))); - return drawSteps; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java deleted file mode 100644 index 147b15dc..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/WaypointProviderLayerRenderer.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.render; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import net.minecraft.client.gui.FontRenderer; - -import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.ClickableDrawStep; -import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; - -import journeymap.client.model.BlockCoordIntPair; - -public abstract class WaypointProviderLayerRenderer extends LayerRenderer { - - private final WaypointProviderManager manager; - - private List drawSteps = new ArrayList<>(); - private List drawStepsReversed = new ArrayList<>(); - - private ClickableDrawStep hoveredDrawStep = null; - - public WaypointProviderLayerRenderer(WaypointProviderManager manager) { - super(manager); - this.manager = manager; - } - - @Override - public List getDrawStepsCachedForInteraction() { - return drawSteps; - } - - @Override - public List getDrawStepsCachedForRendering() { - return drawStepsReversed; - } - - @Override - public void updateVisibleElements(List visibleElements) { - drawSteps = (List) mapLocationProviderToDrawStep(visibleElements); - drawStepsReversed = new ArrayList<>(drawSteps); - Collections.reverse(drawStepsReversed); - } - - protected abstract List mapLocationProviderToDrawStep( - List visibleElements); - - public void onMouseMove(int mouseX, int mouseY) { - hoveredDrawStep = null; - for (ClickableDrawStep drawStep : getDrawStepsCachedForInteraction()) { - if (drawStep.isMouseOver(mouseX, mouseY)) { - hoveredDrawStep = drawStep; - return; - } - } - } - - public boolean onMouseAction(boolean isDoubleClick) { - if (hoveredDrawStep != null) { - if (isDoubleClick) { - if (hoveredDrawStep.getLocationProvider().isActiveAsWaypoint()) { - manager.clearActiveWaypoint(); - } else { - manager.setActiveWaypoint(hoveredDrawStep.getLocationProvider().toWaypoint()); - } - } - return true; - } - return false; - } - - public boolean onMouseActionOutsideLayer(boolean isDoubleClick, BlockCoordIntPair blockCoord) { - if (isLayerActive() && isDoubleClick) { - return manager.doActionOutsideLayer(blockCoord); - } - return false; - } - - public List getTextTooltip() { - if (hoveredDrawStep != null) { - return hoveredDrawStep.getTooltip(); - } - return null; - } - - public void drawCustomTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, - int displayHeight) { - if (hoveredDrawStep != null) { - hoveredDrawStep.drawTooltip(fontRenderer, mouseX, mouseY, displayWidth, displayHeight); - } - } - - public void onActionKeyPressed() { - if (manager.isLayerActive() && hoveredDrawStep != null) { - hoveredDrawStep.onActionKeyPressed(); - manager.forceRefresh(); - } - } - - public boolean isLayerActive() { - return manager.isLayerActive(); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/OreVeinWaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/OreVeinWaypointManager.java deleted file mode 100644 index 2c0ad2a2..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/OreVeinWaypointManager.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.waypoints; - -import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; - -public class OreVeinWaypointManager extends WaypointManager { - - public static final OreVeinWaypointManager instance = new OreVeinWaypointManager(); - - public OreVeinWaypointManager() { - super(OreVeinLayerManager.instance); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/ThaumcraftNodeWaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/ThaumcraftNodeWaypointManager.java deleted file mode 100644 index c32a6f02..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/ThaumcraftNodeWaypointManager.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.waypoints; - -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; - -public class ThaumcraftNodeWaypointManager extends WaypointManager { - - public static final ThaumcraftNodeWaypointManager instance = new ThaumcraftNodeWaypointManager(); - - public ThaumcraftNodeWaypointManager() { - super(ThaumcraftNodeLayerManager.instance); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java deleted file mode 100644 index 74883e64..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/waypoints/WaypointManager.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.waypoints; - -import java.awt.Color; - -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; - -public class WaypointManager extends com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager { - - private journeymap.client.model.Waypoint jmWaypoint; - - public WaypointManager(WaypointProviderManager layerManager) { - super(layerManager, SupportedMods.JourneyMap); - } - - @Override - public void clearActiveWaypoint() { - jmWaypoint = null; - } - - public boolean hasWaypoint() { - return jmWaypoint != null; - } - - public journeymap.client.model.Waypoint getJmWaypoint() { - return jmWaypoint; - } - - @Override - public void updateActiveWaypoint(Waypoint waypoint) { - if (hasWaypoint() == false || waypoint.blockX != jmWaypoint.getX() - || waypoint.blockY != jmWaypoint.getY() - || waypoint.blockZ != jmWaypoint.getZ() - || jmWaypoint.getDimensions().contains(waypoint.dimensionId) == false) { - jmWaypoint = new journeymap.client.model.Waypoint( - waypoint.label, - waypoint.blockX, - waypoint.blockY, - waypoint.blockZ, - new Color(waypoint.color), - journeymap.client.model.Waypoint.Type.Normal, - waypoint.dimensionId); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java deleted file mode 100644 index dd46261e..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/MapState.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model; - -import static com.sinthoras.visualprospecting.Utils.*; - -import java.util.ArrayList; -import java.util.List; - -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; -import com.sinthoras.visualprospecting.integration.model.buttons.DirtyChunkButtonManager; -import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; -import com.sinthoras.visualprospecting.integration.model.buttons.ThaumcraftNodeButtonManager; -import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; -import com.sinthoras.visualprospecting.integration.model.layers.DirtyChunkLayerManager; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidChunkLayerManager; -import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; -import com.sinthoras.visualprospecting.integration.tcnodetracker.NTNodeTrackerWaypointManager; -import com.sinthoras.visualprospecting.integration.xaerominimap.XaeroMiniMapState; - -public class MapState { - - public static final MapState instance = new MapState(); - - public final List buttons = new ArrayList<>(); - public final List layers = new ArrayList<>(); - - public MapState() { - if (isTCNodeTrackerInstalled()) { - buttons.add(ThaumcraftNodeButtonManager.instance); - layers.add(ThaumcraftNodeLayerManager.instance); - new NTNodeTrackerWaypointManager(); - } - - buttons.add(UndergroundFluidButtonManager.instance); - layers.add(UndergroundFluidLayerManager.instance); - layers.add(UndergroundFluidChunkLayerManager.instance); - - buttons.add(OreVeinButtonManager.instance); - layers.add(OreVeinLayerManager.instance); - - if (Config.enableDeveloperOverlays) { - buttons.add(DirtyChunkButtonManager.instance); - layers.add(DirtyChunkLayerManager.instance); - } - - if (isXaerosMinimapInstalled()) { - // need to classload XaeroMiniMapState in order for its waypoint manager to get registered - XaeroMiniMapState.instance.toString(); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/SupportedMods.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/SupportedMods.java deleted file mode 100644 index 551b6719..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/SupportedMods.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model; - -public enum SupportedMods { - TCNodeTracker, - JourneyMap, - XaeroWorldMap, - XaeroMiniMap; - - // TODO: Open Map at here -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java deleted file mode 100644 index 40c09867..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ButtonManager.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.buttons; - -import java.util.EnumMap; -import java.util.Map; - -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.SupportedMods; - -public class ButtonManager { - - private final String buttonTextKey; - private final String iconName; - - private Map buttons = new EnumMap<>(SupportedMods.class); - private boolean isActive = false; - - /* - * Provide textures in assets/journeymap/icon/theme/Vault/icon/.png and - * assets/journeymap/icon/theme/Victorian/icon/.png for JourneyMap and provide a texture in - * assets/xaeroworldmap/textures/.png for XaeroWorldMap. - */ - public ButtonManager(String buttonTextKey, String iconName) { - this.buttonTextKey = buttonTextKey; - this.iconName = iconName; - } - - public void registerButton(SupportedMods map, LayerButton layerButton) { - buttons.put(map, layerButton); - } - - public void updateState(boolean active) { - buttons.values().forEach(button -> button.updateState(active)); - } - - public boolean containsButton(LayerButton button) { - return buttons.containsValue(button); - } - - public String getButtonTextKey() { - return buttonTextKey; - } - - public String getIconName() { - return iconName; - } - - public boolean isActive() { - return isActive; - } - - public void activate() { - MapState.instance.buttons.forEach(ButtonManager::deactivate); - isActive = true; - updateState(true); - } - - public void deactivate() { - isActive = false; - updateState(false); - } - - public void toggle() { - if (isActive) { - deactivate(); - } else { - activate(); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/DirtyChunkButtonManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/DirtyChunkButtonManager.java deleted file mode 100644 index cadcec51..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/DirtyChunkButtonManager.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.buttons; - -public class DirtyChunkButtonManager extends ButtonManager { - - public static final DirtyChunkButtonManager instance = new DirtyChunkButtonManager(); - - public DirtyChunkButtonManager() { - super("visualprospecting.button.dirtychunk", "nodes"); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/LayerButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/LayerButton.java deleted file mode 100644 index 0845cf0d..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/LayerButton.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.buttons; - -import com.sinthoras.visualprospecting.integration.model.SupportedMods; - -public abstract class LayerButton { - - public LayerButton(ButtonManager manager, SupportedMods map) { - manager.registerButton(map, this); - // Grab lang key and texture information from manager in extended constructor - } - - public abstract void updateState(boolean active); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/OreVeinButtonManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/OreVeinButtonManager.java index 5ab7d819..537ad4f8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/OreVeinButtonManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/OreVeinButtonManager.java @@ -1,10 +1,23 @@ package com.sinthoras.visualprospecting.integration.model.buttons; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; + +import com.gtnewhorizons.navigator.api.model.SupportedMods; +import com.gtnewhorizons.navigator.api.model.buttons.ButtonManager; +import com.sinthoras.visualprospecting.Tags; + public class OreVeinButtonManager extends ButtonManager { public static final OreVeinButtonManager instance = new OreVeinButtonManager(); - public OreVeinButtonManager() { - super("visualprospecting.button.orevein", "oreveins"); + @Override + public ResourceLocation getIcon(SupportedMods mod, String theme) { + return new ResourceLocation(Tags.MODID, "textures/icons/oreveins.png"); + } + + @Override + public String getButtonText() { + return StatCollector.translateToLocal("visualprospecting.button.orevein"); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ThaumcraftNodeButtonManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ThaumcraftNodeButtonManager.java deleted file mode 100644 index b2da7182..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/ThaumcraftNodeButtonManager.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.buttons; - -public class ThaumcraftNodeButtonManager extends ButtonManager { - - public static final ThaumcraftNodeButtonManager instance = new ThaumcraftNodeButtonManager(); - - public ThaumcraftNodeButtonManager() { - super("visualprospecting.button.nodes", "nodes"); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/UndergroundFluidButtonManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/UndergroundFluidButtonManager.java index 7c7836d5..5a566c2c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/UndergroundFluidButtonManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/buttons/UndergroundFluidButtonManager.java @@ -1,10 +1,23 @@ package com.sinthoras.visualprospecting.integration.model.buttons; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.StatCollector; + +import com.gtnewhorizons.navigator.api.model.SupportedMods; +import com.gtnewhorizons.navigator.api.model.buttons.ButtonManager; +import com.sinthoras.visualprospecting.Tags; + public class UndergroundFluidButtonManager extends ButtonManager { public static final UndergroundFluidButtonManager instance = new UndergroundFluidButtonManager(); - public UndergroundFluidButtonManager() { - super("visualprospecting.button.undergroundfluid", "undergroundfluid"); + @Override + public ResourceLocation getIcon(SupportedMods mod, String theme) { + return new ResourceLocation(Tags.MODID, "textures/icons/undergroundfluid.png"); + } + + @Override + public String getButtonText() { + return StatCollector.translateToLocal("visualprospecting.button.undergroundfluid"); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java deleted file mode 100644 index de9204ca..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/DirtyChunkLayerManager.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.layers; - -import java.util.ArrayList; -import java.util.List; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityClientPlayerMP; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.World; -import net.minecraft.world.chunk.IChunkProvider; - -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.integration.model.buttons.DirtyChunkButtonManager; -import com.sinthoras.visualprospecting.integration.model.locations.DirtyChunkLocation; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; - -public class DirtyChunkLayerManager extends LayerManager { - - public static final DirtyChunkLayerManager instance = new DirtyChunkLayerManager(); - - public DirtyChunkLayerManager() { - super(DirtyChunkButtonManager.instance); - } - - @Override - protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - return true; - } - - @Override - protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, - int maxBlockZ) { - final int minX = Utils.coordBlockToChunk(minBlockX); - final int minZ = Utils.coordBlockToChunk(minBlockZ); - final int maxX = Utils.coordBlockToChunk(maxBlockX); - final int maxZ = Utils.coordBlockToChunk(maxBlockZ); - final EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer; - final int playerDimensionId = player.dimension; - - ArrayList dirtyChunks = new ArrayList<>(); - - if (MinecraftServer.getServer() == null - || MinecraftServer.getServer().worldServerForDimension(playerDimensionId) == null) { - return dirtyChunks; - } - - World w = MinecraftServer.getServer().worldServerForDimension(playerDimensionId); - IChunkProvider chunkProvider = w.getChunkProvider(); - - for (int chunkX = minX; chunkX <= maxX; chunkX++) { - for (int chunkZ = minZ; chunkZ <= maxZ; chunkZ++) { - if (!chunkProvider.chunkExists(chunkX, chunkZ)) { - continue; - } - final boolean dirty = w.getChunkFromChunkCoords(chunkX, chunkZ).isModified; - dirtyChunks.add(new DirtyChunkLocation(chunkX, chunkZ, playerDimensionId, dirty)); - } - } - - return dirtyChunks; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java deleted file mode 100644 index 947fce88..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerManager.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.layers; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; - -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; -import com.sinthoras.visualprospecting.integration.model.buttons.LayerButton; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; - -public abstract class LayerManager { - - private final ButtonManager buttonManager; - - protected boolean forceRefresh = false; - private List visibleElements = new ArrayList<>(); - protected Map layerRenderer = new EnumMap<>(SupportedMods.class); - private int miniMapWidth = 0; - private int miniMapHeight = 0; - private int fullscreenMapWidth = 0; - private int fullscreenMapHeight = 0; - - public LayerManager(ButtonManager buttonManager) { - this.buttonManager = buttonManager; - } - - public void onButtonClicked(LayerButton button) { - if (buttonManager.containsButton(button)) { - toggleLayer(); - } - } - - public boolean isLayerActive() { - return buttonManager.isActive(); - } - - public void activateLayer() { - buttonManager.activate(); - } - - public void deactivateLayer() { - buttonManager.deactivate(); - } - - public void toggleLayer() { - buttonManager.toggle(); - } - - public void forceRefresh() { - forceRefresh = true; - } - - public void onOpenMap() {} - - protected abstract List generateVisibleElements(int minBlockX, int minBlockZ, - int maxBlockX, int maxBlockZ); - - protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - return true; - } - - public void recacheMiniMap(int centerBlockX, int centerBlockZ, int blockRadius) { - recacheMiniMap(centerBlockX, centerBlockZ, blockRadius, blockRadius); - } - - public void recacheMiniMap(int centerBlockX, int centerBlockZ, int blockWidth, int blockHeight) { - miniMapWidth = blockWidth; - miniMapHeight = blockHeight; - recacheVisibleElements(centerBlockX, centerBlockZ); - } - - public void recacheFullscreenMap(int centerBlockX, int centerBlockZ, int blockWidth, int blockHeight) { - fullscreenMapWidth = blockWidth; - fullscreenMapHeight = blockHeight; - recacheVisibleElements(centerBlockX, centerBlockZ); - } - - private void recacheVisibleElements(int centerBlockX, int centerBlockZ) { - final int radiusBlockX = (Math.max(miniMapWidth, fullscreenMapWidth) + 1) >> 1; - final int radiusBlockZ = (Math.max(miniMapHeight, fullscreenMapHeight) + 1) >> 1; - - final int minBlockX = centerBlockX - radiusBlockX; - final int minBlockZ = centerBlockZ - radiusBlockZ; - final int maxBlockX = centerBlockX + radiusBlockX; - final int maxBlockZ = centerBlockZ + radiusBlockZ; - - checkAndUpdateElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ); - } - - protected void checkAndUpdateElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - if (forceRefresh || needsRegenerateVisibleElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ)) { - visibleElements = generateVisibleElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ); - layerRenderer.values().forEach(layer -> layer.updateVisibleElements(visibleElements)); - forceRefresh = false; - } - } - - public void registerLayerRenderer(SupportedMods map, LayerRenderer renderer) { - layerRenderer.put(map, renderer); - } - - public LayerRenderer getLayerRenderer(SupportedMods map) { - return layerRenderer.get(map); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java deleted file mode 100644 index 89c335d8..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/LayerRenderer.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.layers; - -import java.util.List; - -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; - -public abstract class LayerRenderer { - - public LayerRenderer(LayerManager manager, SupportedMods map) { - manager.registerLayerRenderer(map, this); - } - - public abstract void updateVisibleElements(List visibleElements); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java index 5d06c9e4..bc64634d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java @@ -5,16 +5,26 @@ import net.minecraft.client.Minecraft; +import org.jetbrains.annotations.Nullable; + +import com.gtnewhorizons.navigator.api.journeymap.waypoints.JMWaypointManager; +import com.gtnewhorizons.navigator.api.model.SupportedMods; +import com.gtnewhorizons.navigator.api.model.layers.InteractableLayerManager; +import com.gtnewhorizons.navigator.api.model.layers.LayerRenderer; +import com.gtnewhorizons.navigator.api.model.locations.IWaypointAndLocationProvider; +import com.gtnewhorizons.navigator.api.model.waypoints.WaypointManager; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import com.sinthoras.visualprospecting.integration.journeymap.render.JMOreVeinRenderer; import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; +import com.sinthoras.visualprospecting.integration.xaerominimap.OreVeinWaypointManager; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.XaeroOreVeinRenderer; -public class OreVeinLayerManager extends WaypointProviderManager { +public class OreVeinLayerManager extends InteractableLayerManager { public static final OreVeinLayerManager instance = new OreVeinLayerManager(); @@ -51,6 +61,26 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i return false; } + @Nullable + @Override + protected LayerRenderer addLayerRenderer(InteractableLayerManager manager, SupportedMods mod) { + return switch (mod) { + case JourneyMap -> new JMOreVeinRenderer(manager); + case XaeroWorldMap -> new XaeroOreVeinRenderer(manager); + default -> null; + }; + } + + @Nullable + @Override + protected WaypointManager addWaypointManager(InteractableLayerManager manager, SupportedMods mod) { + return switch (mod) { + case JourneyMap -> new JMWaypointManager(manager); + case XaeroWorldMap -> new OreVeinWaypointManager(manager); + default -> null; + }; + } + @Override protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java deleted file mode 100644 index a51ba352..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/ThaumcraftNodeLayerManager.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.layers; - -import java.util.ArrayList; -import java.util.List; - -import net.minecraft.client.Minecraft; - -import com.dyonovan.tcnodetracker.TCNodeTracker; -import com.dyonovan.tcnodetracker.lib.NodeList; -import com.sinthoras.visualprospecting.integration.model.buttons.ThaumcraftNodeButtonManager; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; -import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; - -public class ThaumcraftNodeLayerManager extends WaypointProviderManager { - - public static final ThaumcraftNodeLayerManager instance = new ThaumcraftNodeLayerManager(); - - private int oldMinBlockX = 0; - private int oldMinBlockZ = 0; - private int oldMaxBlockX = 0; - private int oldMaxBlockZ = 0; - - public ThaumcraftNodeLayerManager() { - super(ThaumcraftNodeButtonManager.instance); - } - - @Override - protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - if (minBlockX != oldMinBlockX || minBlockZ != oldMinBlockZ - || maxBlockX != oldMaxBlockX - || maxBlockZ != oldMaxBlockZ) { - oldMinBlockX = minBlockX; - oldMinBlockZ = minBlockZ; - oldMaxBlockX = maxBlockX; - oldMaxBlockZ = maxBlockZ; - return true; - } - return false; - } - - @Override - protected List generateVisibleElements(int minBlockX, int minBlockZ, - int maxBlockX, int maxBlockZ) { - final int playerDimensionId = Minecraft.getMinecraft().thePlayer.dimension; - - ArrayList thaumcraftNodeLocations = new ArrayList<>(); - - for (NodeList node : TCNodeTracker.nodelist) { - if (node.dim == playerDimensionId && node.x >= minBlockX - && node.x <= maxBlockX - && node.z >= minBlockZ - && node.z <= maxBlockZ) { - thaumcraftNodeLocations.add(new ThaumcraftNodeLocation(node)); - } - } - - return thaumcraftNodeLocations; - } - - public void deleteNode(ThaumcraftNodeLocation thaumcraftNodeLocation) { - TCNodeTracker.nodelist.removeIf(thaumcraftNodeLocation::belongsToNode); - if (thaumcraftNodeLocation.isActiveAsWaypoint()) { - clearActiveWaypoint(); - } - forceRefresh(); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java index 9a547697..ba0a8409 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java @@ -5,13 +5,20 @@ import net.minecraft.client.Minecraft; +import org.jetbrains.annotations.Nullable; + +import com.gtnewhorizons.navigator.api.model.SupportedMods; +import com.gtnewhorizons.navigator.api.model.layers.LayerManager; +import com.gtnewhorizons.navigator.api.model.layers.LayerRenderer; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; +import com.sinthoras.visualprospecting.integration.journeymap.render.JMUndergroundFluidChunkRenderer; import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.XaeroUndergroundFluidChunkRenderer; public class UndergroundFluidChunkLayerManager extends LayerManager { @@ -48,6 +55,16 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i return false; } + @Nullable + @Override + protected LayerRenderer addLayerRenderer(LayerManager manager, SupportedMods mods) { + return switch (mods) { + case JourneyMap -> new JMUndergroundFluidChunkRenderer(manager); + case XaeroWorldMap -> new XaeroUndergroundFluidChunkRenderer(manager); + default -> null; + }; + } + @Override protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java index 6cab439b..6a1995e3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java @@ -5,13 +5,20 @@ import net.minecraft.client.Minecraft; +import org.jetbrains.annotations.Nullable; + +import com.gtnewhorizons.navigator.api.model.SupportedMods; +import com.gtnewhorizons.navigator.api.model.layers.LayerManager; +import com.gtnewhorizons.navigator.api.model.layers.LayerRenderer; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; +import com.sinthoras.visualprospecting.integration.journeymap.render.JMUndergroundFluidRenderer; import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; +import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.XaeroUndergroundFluidRenderer; public class UndergroundFluidLayerManager extends LayerManager { @@ -48,6 +55,16 @@ protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, i return false; } + @Nullable + @Override + protected LayerRenderer addLayerRenderer(LayerManager manager, SupportedMods mod) { + return switch (mod) { + case JourneyMap -> new JMUndergroundFluidRenderer(manager); + case XaeroWorldMap -> new XaeroUndergroundFluidRenderer(manager); + default -> null; + }; + } + @Override protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java deleted file mode 100644 index b2a594be..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/WaypointProviderManager.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.layers; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; - -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; -import com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager; - -import journeymap.client.model.BlockCoordIntPair; - -public abstract class WaypointProviderManager extends LayerManager { - - private List visibleElements = new ArrayList<>(); - private Map waypointManagers = new EnumMap<>(SupportedMods.class); - - protected Waypoint activeWaypoint = null; - - public WaypointProviderManager(ButtonManager buttonManager) { - super(buttonManager); - } - - public void setActiveWaypoint(Waypoint waypoint) { - activeWaypoint = waypoint; - visibleElements.forEach(element -> element.onWaypointUpdated(waypoint)); - waypointManagers.values().forEach(translator -> translator.updateActiveWaypoint(waypoint)); - } - - public void clearActiveWaypoint() { - activeWaypoint = null; - visibleElements.forEach(IWaypointAndLocationProvider::onWaypointCleared); - waypointManagers.values().forEach(WaypointManager::clearActiveWaypoint); - } - - public boolean hasActiveWaypoint() { - return activeWaypoint != null; - } - - public boolean doActionOutsideLayer(BlockCoordIntPair blockCoord) { - return false; - } - - public void registerWaypointManager(SupportedMods map, WaypointManager waypointManager) { - waypointManagers.put(map, waypointManager); - } - - public WaypointManager getWaypointManager(SupportedMods map) { - return waypointManagers.get(map); - } - - protected abstract List generateVisibleElements(int minBlockX, - int minBlockZ, int maxBlockX, int maxBlockZ); - - @Override - protected void checkAndUpdateElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - if (forceRefresh || needsRegenerateVisibleElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ)) { - visibleElements = generateVisibleElements(minBlockX, minBlockZ, maxBlockX, maxBlockZ); - - if (hasActiveWaypoint()) { - for (IWaypointAndLocationProvider element : visibleElements) { - element.onWaypointUpdated(activeWaypoint); - } - } - - layerRenderer.values().forEach(layer -> layer.updateVisibleElements(visibleElements)); - forceRefresh = false; - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java deleted file mode 100644 index 75066c31..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/DirtyChunkLocation.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.locations; - -import com.sinthoras.visualprospecting.Utils; - -public class DirtyChunkLocation implements ILocationProvider { - - private final int blockX; - private final int blockZ; - private final int dimensionId; - private final boolean dirty; - - public DirtyChunkLocation(int chunkX, int chunkZ, int dimensionId, boolean dirty) { - blockX = Utils.coordChunkToBlock(chunkX); - blockZ = Utils.coordChunkToBlock(chunkZ); - this.dimensionId = dimensionId; - this.dirty = dirty; - } - - public double getBlockX() { - return blockX + 0.5; - } - - public double getBlockZ() { - return blockZ + 0.5; - } - - public int getDimensionId() { - return dimensionId; - } - - public boolean isDirty() { - return dirty; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ILocationProvider.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ILocationProvider.java deleted file mode 100644 index d069df51..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ILocationProvider.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.locations; - -public interface ILocationProvider { - - int getDimensionId(); - - double getBlockX(); - - double getBlockZ(); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/IWaypointAndLocationProvider.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/IWaypointAndLocationProvider.java deleted file mode 100644 index e8a2d998..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/IWaypointAndLocationProvider.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.locations; - -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; - -public interface IWaypointAndLocationProvider extends ILocationProvider { - - Waypoint toWaypoint(); - - boolean isActiveAsWaypoint(); - - void onWaypointCleared(); - - void onWaypointUpdated(Waypoint waypoint); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index 5520c785..f9a62ee4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -9,18 +9,19 @@ import org.lwjgl.input.Keyboard; -import com.sinthoras.visualprospecting.VP; +import com.gtnewhorizons.navigator.api.NavigatorApi; +import com.gtnewhorizons.navigator.api.model.locations.IWaypointAndLocationProvider; +import com.gtnewhorizons.navigator.api.model.waypoints.Waypoint; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; public class OreVeinLocation implements IWaypointAndLocationProvider { private static final String depletedHint = EnumChatFormatting.RED + I18n.format("visualprospecting.depleted"); private static final String activeWaypointHint = EnumChatFormatting.GOLD + I18n.format("visualprospecting.iswaypoint"); - private static final String toggleDepletedHint = EnumChatFormatting.DARK_GRAY - + I18n.format("visualprospecting.node.deletehint", Keyboard.getKeyName(VP.keyAction.getKeyCode())); + private static final String toggleDepletedHint = EnumChatFormatting.DARK_GRAY + I18n + .format("visualprospecting.node.deletehint", Keyboard.getKeyName(NavigatorApi.ACTION_KEY.getKeyCode())); private final OreVeinPosition oreVeinPosition; private final String name; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java deleted file mode 100644 index 7d04c409..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/ThaumcraftNodeLocation.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.locations; - -import net.minecraft.client.resources.I18n; -import net.minecraft.util.EnumChatFormatting; - -import org.lwjgl.input.Keyboard; - -import com.dyonovan.tcnodetracker.lib.NodeList; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; - -import thaumcraft.api.aspects.Aspect; -import thaumcraft.api.aspects.AspectList; -import thaumcraft.api.nodes.NodeType; -import thaumcraft.common.config.ConfigBlocks; -import thaumcraft.common.tiles.TileNode; - -public class ThaumcraftNodeLocation implements IWaypointAndLocationProvider { - - private static final String deleteHint = EnumChatFormatting.DARK_GRAY - + I18n.format("visualprospecting.node.deletehint", Keyboard.getKeyName(VP.keyAction.getKeyCode()));; - private static final String activeWaypointHint = EnumChatFormatting.GOLD - + I18n.format("visualprospecting.iswaypoint"); - private static final String title = EnumChatFormatting.BOLD + I18n.format("tile.blockAiry.0.name"); - - private final NodeList node; - private final TileNode nodeTile; - private final String description; - - private boolean isActiveAsWaypoint; - - public ThaumcraftNodeLocation(NodeList node) { - this.node = node; - - nodeTile = new TileNode(); - final AspectList aspectList = new AspectList(); - for (String aspectTag : node.aspect.keySet()) { - aspectList.add(Aspect.getAspect(aspectTag), node.aspect.get(aspectTag)); - } - nodeTile.setAspects(aspectList); - switch (node.type) { - case "NORMAL": - nodeTile.setNodeType(NodeType.NORMAL); - break; - case "UNSTABLE": - nodeTile.setNodeType(NodeType.UNSTABLE); - break; - case "DARK": - nodeTile.setNodeType(NodeType.DARK); - break; - case "TAINTED": - nodeTile.setNodeType(NodeType.TAINTED); - break; - case "PURE": - nodeTile.setNodeType(NodeType.PURE); - break; - case "HUNGRY": - nodeTile.setNodeType(NodeType.HUNGRY); - break; - } - nodeTile.blockType = ConfigBlocks.blockAiry; - nodeTile.blockMetadata = 0; - - description = node.mod.equals("BLANK") - ? EnumChatFormatting.GRAY + I18n.format("nodetype." + node.type + ".name") - : EnumChatFormatting.GRAY + I18n.format("nodetype." + node.type + ".name") - + ", " - + I18n.format("nodemod." + node.mod + ".name"); - } - - @Override - public double getBlockX() { - return node.x + 0.5; - } - - public double getBlockY() { - return node.y + 0.5; - } - - @Override - public double getBlockZ() { - return node.z + 0.5; - } - - @Override - public int getDimensionId() { - return node.dim; - } - - @Override - public Waypoint toWaypoint() { - return new Waypoint( - node.x, - node.y, - node.z, - node.dim, - I18n.format("visualprospecting.tracked", I18n.format("tile.blockAiry.0.name")), - nodeTile.targetColor.getRGB()); - } - - @Override - public boolean isActiveAsWaypoint() { - return isActiveAsWaypoint; - } - - @Override - public void onWaypointCleared() { - isActiveAsWaypoint = false; - } - - @Override - public void onWaypointUpdated(Waypoint waypoint) { - isActiveAsWaypoint = waypoint.dimensionId == node.dim && waypoint.blockX == node.x - && waypoint.blockY == node.y - && waypoint.blockZ == node.z; - } - - public boolean belongsToNode(NodeList other) { - return node.x == other.x && node.y == other.y && node.z == other.z && node.dim == other.dim; - } - - public Aspect getStrongestAspect() { - return nodeTile.getAspects().getAspectsSortedAmount()[0]; - } - - public AspectList getAspects() { - return nodeTile.getAspects(); - } - - public String getDescription() { - return description; - } - - public String getDeleteHint() { - return deleteHint; - } - - public String getActiveWaypointHint() { - return activeWaypointHint; - } - - public String getTitle() { - return title; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java index 78713f61..02c148c5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java @@ -2,6 +2,7 @@ import net.minecraftforge.fluids.Fluid; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.Utils; public class UndergroundFluidChunkLocation implements ILocationProvider { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java index a4fe404b..cf82972e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java @@ -2,6 +2,7 @@ import net.minecraftforge.fluids.Fluid; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; public class UndergroundFluidLocation implements ILocationProvider { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/Waypoint.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/Waypoint.java deleted file mode 100644 index 971b8725..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/Waypoint.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.waypoints; - -public class Waypoint { - - public final int blockX; - public final int blockY; - public final int blockZ; - public final int dimensionId; - public final String label; - public final int color; - - public Waypoint(int blockX, int blockY, int blockZ, int dimensionId, String label, int color) { - this.blockX = blockX; - this.blockY = blockY; - this.blockZ = blockZ; - this.dimensionId = dimensionId; - this.label = label; - this.color = color; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/WaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/WaypointManager.java deleted file mode 100644 index 1e6643f7..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/waypoints/WaypointManager.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.waypoints; - -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; - -public abstract class WaypointManager { - - public WaypointManager(WaypointProviderManager layerManager, SupportedMods map) { - layerManager.registerWaypointManager(map, this); - } - - public abstract void clearActiveWaypoint(); - - public abstract void updateActiveWaypoint(Waypoint waypoint); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/tcnodetracker/NTNodeTrackerWaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/tcnodetracker/NTNodeTrackerWaypointManager.java deleted file mode 100644 index fc610d3b..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/tcnodetracker/NTNodeTrackerWaypointManager.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.sinthoras.visualprospecting.integration.tcnodetracker; - -import com.dyonovan.tcnodetracker.TCNodeTracker; -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; - -public class NTNodeTrackerWaypointManager - extends com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager { - - public NTNodeTrackerWaypointManager() { - super(ThaumcraftNodeLayerManager.instance, SupportedMods.TCNodeTracker); - } - - @Override - public void clearActiveWaypoint() { - TCNodeTracker.yMarker = -1; - } - - @Override - public void updateActiveWaypoint(Waypoint waypoint) { - TCNodeTracker.xMarker = waypoint.blockX; - TCNodeTracker.yMarker = waypoint.blockY; - TCNodeTracker.zMarker = waypoint.blockZ; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java deleted file mode 100644 index 1d77761d..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/IWaypointManagerReflection.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.sinthoras.visualprospecting.integration.voxelmap; - -import java.lang.reflect.Method; - -import com.sinthoras.visualprospecting.VP; -import com.thevoxelbox.voxelmap.interfaces.IWaypointManager; - -public class IWaypointManagerReflection { - - private static Method getCurrentSubworldDescriptor; - - public static String getCurrentSubworldDescriptor(IWaypointManager obj, boolean arg) { - try { - return (String) getCurrentSubworldDescriptor.invoke(obj, arg); - } catch (Exception e) { - VP.error( - "Could not invoke IWaypointManager#if. If it failed due to a NullPointerException, look for an error message starting with \"Getting the method IWaypointManager#if failed\" further up."); - e.printStackTrace(); - } - return ""; - } - - static { - try { - getCurrentSubworldDescriptor = IWaypointManager.class.getMethod("if", boolean.class); - } catch (Exception e) { - VP.error( - "Getting the method IWaypointManager#if failed, any calls to IWaypointManagerReflection#getCurrentSubworldDescriptor will return an empty String."); - e.printStackTrace(); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java index e9f384c6..aaf8d451 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java @@ -7,14 +7,12 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.StatCollector; +import com.gtnewhorizons.navigator.api.voxelmap.VoxelMapWaypointManager; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; -import com.thevoxelbox.voxelmap.interfaces.AbstractVoxelMap; -import com.thevoxelbox.voxelmap.interfaces.IWaypointManager; -import com.thevoxelbox.voxelmap.util.Waypoint; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import gregtech.api.GregTech_API; @@ -28,24 +26,20 @@ public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { } OreVeinPosition pos = event.getPosition(); - IWaypointManager waypointManager = AbstractVoxelMap.getInstance().getWaypointManager(); short[] color = GregTech_API.sGeneratedMaterials[pos.veinType.primaryOreMeta].getRGBA(); TreeSet dim = new TreeSet<>(); dim.add(pos.dimensionId); - - waypointManager.addWaypoint( - new Waypoint( - StatCollector.translateToLocal(pos.veinType.name), // name - pos.getBlockX(), // X - pos.getBlockZ(), // Z - getY(), // Y - Config.enableVoxelMapWaypointsByDefault, // enabled - (float) color[0] / 255.0f, // red - (float) color[1] / 255.0f, // green - (float) color[2] / 255.0f, // blue - "Pickaxe", // icon - IWaypointManagerReflection.getCurrentSubworldDescriptor(waypointManager, false), // world - dim)); // dimension + VoxelMapWaypointManager.addVoxelMapWaypoint( + StatCollector.translateToLocal(pos.veinType.name), // name + pos.getBlockX(), // X + pos.getBlockZ(), // Z + getY(), // Y + Config.enableVoxelMapWaypointsByDefault, // enabled + (float) color[0] / 255.0f, // red + (float) color[1] / 255.0f, // green + (float) color[2] / 255.0f, // blue + "Pickaxe", // icon + dim); } @SuppressWarnings("deprecation") @@ -56,26 +50,23 @@ public void onFluidProspected(ProspectingNotificationEvent.UndergroundFluid even } UndergroundFluidPosition pos = event.getPosition(); - IWaypointManager waypointManager = AbstractVoxelMap.getInstance().getWaypointManager(); int x = Utils.coordChunkToBlock(pos.chunkX); int z = Utils.coordChunkToBlock(pos.chunkZ); int color = pos.fluid.getColor(); TreeSet dim = new TreeSet<>(); dim.add(pos.dimensionId); - waypointManager.addWaypoint( - new Waypoint( - pos.fluid.getLocalizedName(), // name - x, // X - z, // Z - Minecraft.getMinecraft().theWorld.getHeightValue(x, z), // Y - Config.enableVoxelMapWaypointsByDefault, // enabled - (float) (color >> 16 & 0xFF) / 255.0f, // red - (float) (color >> 8 & 0xFF) / 255.0f, // green - (float) (color & 0xFF) / 255.0f, // blue - "Science", // icon - IWaypointManagerReflection.getCurrentSubworldDescriptor(waypointManager, false), // world - dim)); // dimension + VoxelMapWaypointManager.addVoxelMapWaypoint( + pos.fluid.getLocalizedName(), // name + x, // X + z, // Z + Minecraft.getMinecraft().theWorld.getHeightValue(x, z), // Y + Config.enableVoxelMapWaypointsByDefault, // enabled + (float) (color >> 16 & 0xFF) / 255.0f, // red + (float) (color >> 8 & 0xFF) / 255.0f, // green + (float) (color & 0xFF) / 255.0f, // blue + "Science", // icon + dim); // dimension } private static int getY() { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/OreVeinWaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/OreVeinWaypointManager.java new file mode 100644 index 00000000..c9c85185 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/OreVeinWaypointManager.java @@ -0,0 +1,17 @@ +package com.sinthoras.visualprospecting.integration.xaerominimap; + +import com.gtnewhorizons.navigator.api.model.layers.InteractableLayerManager; +import com.gtnewhorizons.navigator.api.model.waypoints.Waypoint; +import com.gtnewhorizons.navigator.api.xaero.waypoints.XaeroWaypointManager; + +public class OreVeinWaypointManager extends XaeroWaypointManager { + + public OreVeinWaypointManager(InteractableLayerManager manager) { + super(manager); + } + + @Override + protected String getSymbol(Waypoint waypoint) { + return "!"; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java deleted file mode 100644 index f9191bf9..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/XaeroMiniMapState.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaerominimap; - -import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; - -import java.util.ArrayList; -import java.util.List; - -import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.OreVeinWaypointManager; -import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.ThaumcraftNodeWaypointManager; -import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.WaypointManager; - -public class XaeroMiniMapState { - - public static XaeroMiniMapState instance = new XaeroMiniMapState(); - - public final List waypointManagers = new ArrayList<>(); - - public XaeroMiniMapState() { - waypointManagers.add(OreVeinWaypointManager.instance); - - if (isTCNodeTrackerInstalled()) { - waypointManagers.add(ThaumcraftNodeWaypointManager.instance); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/OreVeinWaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/OreVeinWaypointManager.java deleted file mode 100644 index 441d6dc2..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/OreVeinWaypointManager.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaerominimap.waypoints; - -import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; - -public class OreVeinWaypointManager extends WaypointManager { - - public static OreVeinWaypointManager instance = new OreVeinWaypointManager(); - - public OreVeinWaypointManager() { - super(OreVeinLayerManager.instance, WaypointType.ORE_VEINS_WAYPOINT); - } - - @Override - protected String getSymbol(Waypoint waypoint) { - return "!"; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/ThaumcraftNodeWaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/ThaumcraftNodeWaypointManager.java deleted file mode 100644 index 2c30aa97..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/ThaumcraftNodeWaypointManager.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaerominimap.waypoints; - -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; - -public class ThaumcraftNodeWaypointManager extends WaypointManager { - - public static ThaumcraftNodeWaypointManager instance = new ThaumcraftNodeWaypointManager(); - - public ThaumcraftNodeWaypointManager() { - super(ThaumcraftNodeLayerManager.instance, WaypointType.TC_NODES_WAYPOINT); - } - - @Override - protected String getSymbol(Waypoint waypoint) { - return "@"; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java deleted file mode 100644 index ae20e658..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointManager.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaerominimap.waypoints; - -import java.util.Hashtable; - -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; - -import xaero.common.minimap.waypoints.WaypointsManager; - -public class WaypointManager extends com.sinthoras.visualprospecting.integration.model.waypoints.WaypointManager { - - private static final Hashtable xWaypointTable = WaypointsManager - .getCustomWaypoints(Tags.MODID); - - private WaypointWithDimension xWaypoint; - private final WaypointType waypointType; - - public WaypointManager(WaypointProviderManager layerManager, WaypointType waypointType) { - super(layerManager, SupportedMods.XaeroMiniMap); - this.waypointType = waypointType; - } - - @Override - public void clearActiveWaypoint() { - xWaypoint = null; - xWaypointTable.remove(waypointType.ordinal()); - } - - public boolean hasWaypoint() { - return xWaypoint != null; - } - - public WaypointWithDimension getXWaypoint() { - return xWaypoint; - } - - @Override - public void updateActiveWaypoint(Waypoint waypoint) { - if (!hasWaypoint() || waypoint.blockX != xWaypoint.getX() - || waypoint.blockY != xWaypoint.getY() - || waypoint.blockZ != xWaypoint.getZ() - || waypoint.dimensionId != xWaypoint.getDimID()) { - xWaypoint = new WaypointWithDimension( - waypoint.blockX, - waypoint.blockY, - waypoint.blockZ, - waypoint.label, - getSymbol(waypoint), - 15, - waypoint.dimensionId); - xWaypointTable.put(waypointType.ordinal(), xWaypoint); - } - } - - protected String getSymbol(Waypoint waypoint) { - return waypoint.label.substring(0, 1); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointType.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointType.java deleted file mode 100644 index 7a9e69f5..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointType.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaerominimap.waypoints; - -public enum WaypointType { - ORE_VEINS_WAYPOINT, - TC_NODES_WAYPOINT -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointWithDimension.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointWithDimension.java deleted file mode 100644 index d24c0e37..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/waypoints/WaypointWithDimension.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaerominimap.waypoints; - -import xaero.common.minimap.waypoints.Waypoint; - -public class WaypointWithDimension extends Waypoint { - - private final int dimID; - private int currentDim; - - public WaypointWithDimension(int x, int y, int z, String name, String symbol, int color, int dimID) { - super(x, y, z, name, symbol, color); - this.dimID = dimID; - this.currentDim = dimID; - } - - public void notifyDimension(int newDimID) { - currentDim = newDimID; - } - - public int getDimID() { - return dimID; - } - - @Override - public boolean isDisabled() { - return super.isDisabled() || currentDim != dimID; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java deleted file mode 100644 index f21f27bd..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/XaeroWorldMapState.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap; - -import static com.sinthoras.visualprospecting.Utils.isTCNodeTrackerInstalled; - -import java.util.ArrayList; -import java.util.List; - -import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.LayerButton; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.OreVeinButton; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.ThaumcraftNodeButton; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.UndergroundFluidButton; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.OreVeinRenderer; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.ThaumcraftNodeRenderer; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.UndergroundFluidChunkRenderer; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.UndergroundFluidRenderer; - -public class XaeroWorldMapState { - - public static XaeroWorldMapState instance = new XaeroWorldMapState(); - - public final List buttons = new ArrayList<>(); - public final List renderers = new ArrayList<>(); - - public XaeroWorldMapState() { - buttons.add(OreVeinButton.instance); - renderers.add(OreVeinRenderer.instance); - - buttons.add(UndergroundFluidButton.instance); - renderers.add(UndergroundFluidChunkRenderer.instance); - renderers.add(UndergroundFluidRenderer.instance); - - if (isTCNodeTrackerInstalled()) { - buttons.add(ThaumcraftNodeButton.instance); - renderers.add(ThaumcraftNodeRenderer.instance); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/LayerButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/LayerButton.java deleted file mode 100644 index 869e3acb..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/LayerButton.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons; - -import net.minecraft.util.ResourceLocation; - -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.buttons.ButtonManager; - -public class LayerButton extends com.sinthoras.visualprospecting.integration.model.buttons.LayerButton { - - private final ButtonManager manager; - private SizedGuiTexturedButton button; - - public final ResourceLocation textureLocation; - - public LayerButton(ButtonManager manager) { - super(manager, SupportedMods.XaeroWorldMap); - this.manager = manager; - textureLocation = new ResourceLocation("xaeroworldmap", "textures/" + getIconName() + ".png"); - } - - @Override - public void updateState(boolean active) { - if (button != null) { - button.setActive(active); - } - } - - public void setButton(SizedGuiTexturedButton button) { - this.button = button; - updateState(manager.isActive()); - } - - public String getButtonTextKey() { - return manager.getButtonTextKey(); - } - - public String getIconName() { - return manager.getIconName(); - } - - public void toggle() { - manager.toggle(); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/OreVeinButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/OreVeinButton.java deleted file mode 100644 index 952a3c17..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/OreVeinButton.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons; - -import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; - -public class OreVeinButton extends LayerButton { - - public static final OreVeinButton instance = new OreVeinButton(); - - public OreVeinButton() { - super(OreVeinButtonManager.instance); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java deleted file mode 100644 index 8498fbd3..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/SizedGuiTexturedButton.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons; - -import java.util.function.Consumer; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.Gui; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.util.ResourceLocation; - -import org.lwjgl.opengl.GL11; - -import xaero.map.gui.CursorBox; -import xaero.map.gui.GuiTexturedButton; - -public class SizedGuiTexturedButton extends GuiTexturedButton { - - private static final int BUTTON_WIDTH = 20; - private static final int BUTTON_HEIGHT = 20; - private static final int ICON_WIDTH = 16; - private static final int ICON_HEIGHT = 16; - - protected boolean active; - - public SizedGuiTexturedButton(int x, int y, ResourceLocation texture, Consumer action, - CursorBox tooltip) { - super(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, 0, 0, ICON_WIDTH, ICON_HEIGHT, texture, action, tooltip); - active = false; - } - - @Override - public void drawButton(Minecraft minecraft, int mouseX, int mouseY) { - minecraft.getTextureManager().bindTexture(texture); - int iconX = xPosition + width / 2 - textureW / 2; - int iconY = yPosition + height / 2 - textureH / 2; - if (enabled) { - if (active) { - if (isMouseOver(mouseX, mouseY)) { - iconY--; - GL11.glColor4f(0.5F, 0.9F, 0.5F, 1.0F); - } else { - GL11.glColor4f(0.5882F, 0.9882F, 0.5882F, 1.0F); - } - } else { - if (isMouseOver(mouseX, mouseY)) { - iconY--; - GL11.glColor4f(0.9F, 0.9F, 0.9F, 1.0F); - } else { - GL11.glColor4f(0.9882F, 0.9882F, 0.9882F, 1.0F); - } - } - } else { - GL11.glColor4f(0.25F, 0.25F, 0.25F, 1.0F); - } - - Gui.func_146110_a(iconX, iconY, textureX, textureY, textureW, textureH, textureW, textureH); - } - - public boolean isMouseOver(int mouseX, int mouseY) { - return mouseX >= xPosition && mouseY >= yPosition && mouseX < xPosition + width && mouseY < yPosition + height; - } - - public void setActive(boolean active) { - this.active = active; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/ThaumcraftNodeButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/ThaumcraftNodeButton.java deleted file mode 100644 index ff065052..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/ThaumcraftNodeButton.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons; - -import com.sinthoras.visualprospecting.integration.model.buttons.ThaumcraftNodeButtonManager; - -public class ThaumcraftNodeButton extends LayerButton { - - public static final ThaumcraftNodeButton instance = new ThaumcraftNodeButton(); - - public ThaumcraftNodeButton() { - super(ThaumcraftNodeButtonManager.instance); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/UndergroundFluidButton.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/UndergroundFluidButton.java deleted file mode 100644 index a3155643..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/buttons/UndergroundFluidButton.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons; - -import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; - -public class UndergroundFluidButton extends LayerButton { - - public static final UndergroundFluidButton instance = new UndergroundFluidButton(); - - public UndergroundFluidButton() { - super(UndergroundFluidButtonManager.instance); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java deleted file mode 100644 index 14ada20a..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/InteractableLayerRenderer.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; - -import java.util.List; - -import net.minecraft.client.gui.GuiScreen; - -import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.InteractableRenderStep; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; - -public abstract class InteractableLayerRenderer extends LayerRenderer { - - private double mouseX; - private double mouseY; - protected WaypointProviderManager manager; - protected InteractableRenderStep hovered; - - public InteractableLayerRenderer(WaypointProviderManager manager) { - super(manager); - this.manager = manager; - hovered = null; - } - - @Override - protected abstract List generateRenderSteps( - List visibleElements); - - public void updateHovered(double mouseX, double mouseY, double scale) { - this.mouseX = mouseX; - this.mouseY = mouseY; - for (RenderStep step : renderStepsReversed) { - if (step instanceof InteractableRenderStep - && ((InteractableRenderStep) step).isMouseOver(mouseX, mouseY, scale)) { - hovered = (InteractableRenderStep) step; - return; - } - } - hovered = null; - } - - public void drawTooltip(GuiScreen gui, double scale, int scaleAdj) { - if (hovered != null) { - hovered.drawTooltip(gui, mouseX, mouseY, scale, scaleAdj); - } - } - - public void doActionKeyPress() { - if (manager.isLayerActive() && hovered != null) { - hovered.onActionButton(); - manager.forceRefresh(); - } - } - - public void doDoubleClick() { - if (hovered != null) { - if (hovered.getLocationProvider().isActiveAsWaypoint()) { - manager.clearActiveWaypoint(); - } else { - manager.setActiveWaypoint(hovered.getLocationProvider().toWaypoint()); - } - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java deleted file mode 100644 index cd0edc47..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/LayerRenderer.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import com.sinthoras.visualprospecting.integration.model.SupportedMods; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; - -public abstract class LayerRenderer extends com.sinthoras.visualprospecting.integration.model.layers.LayerRenderer { - - private final LayerManager manager; - protected List renderSteps = new ArrayList<>(); - protected List renderStepsReversed = new ArrayList<>(); - - public LayerRenderer(LayerManager manager) { - super(manager, SupportedMods.XaeroWorldMap); - this.manager = manager; - } - - public List getRenderSteps() { - return renderSteps; - } - - public List getRenderStepsReversed() { - return renderStepsReversed; - } - - public boolean isLayerActive() { - return manager.isLayerActive(); - } - - @Override - public void updateVisibleElements(List visibleElements) { - // noinspection unchecked - renderSteps = (List) generateRenderSteps(visibleElements); - renderStepsReversed = new ArrayList<>(renderSteps); - Collections.reverse(renderStepsReversed); - } - - protected abstract List generateRenderSteps( - List visibleElements); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java deleted file mode 100644 index a511fee0..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/ThaumcraftNodeRenderer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; - -import java.util.ArrayList; -import java.util.List; - -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; -import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.ThaumcraftNodeRenderStep; - -public class ThaumcraftNodeRenderer extends InteractableLayerRenderer { - - public static ThaumcraftNodeRenderer instance = new ThaumcraftNodeRenderer(); - - public ThaumcraftNodeRenderer() { - super(ThaumcraftNodeLayerManager.instance); - } - - @Override - protected List generateRenderSteps(List visibleElements) { - final List renderSteps = new ArrayList<>(); - visibleElements.stream().map(element -> (ThaumcraftNodeLocation) element) - .forEach(location -> renderSteps.add(new ThaumcraftNodeRenderStep(location))); - return renderSteps; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroOreVeinRenderer.java similarity index 63% rename from src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java rename to src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroOreVeinRenderer.java index 53f5d261..e3c4be11 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/OreVeinRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroOreVeinRenderer.java @@ -3,17 +3,16 @@ import java.util.ArrayList; import java.util.List; -import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.model.layers.InteractableLayerManager; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.xaero.renderers.XaeroInteractableLayerRenderer; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.OreVeinRenderStep; -public class OreVeinRenderer extends InteractableLayerRenderer { +public class XaeroOreVeinRenderer extends XaeroInteractableLayerRenderer { - public static OreVeinRenderer instance = new OreVeinRenderer(); - - public OreVeinRenderer() { - super(OreVeinLayerManager.instance); + public XaeroOreVeinRenderer(InteractableLayerManager manager) { + super(manager); } @Override diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidChunkRenderer.java similarity index 64% rename from src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java rename to src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidChunkRenderer.java index 7b46e3c7..80c35436 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidChunkRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidChunkRenderer.java @@ -3,17 +3,16 @@ import java.util.ArrayList; import java.util.List; -import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidChunkLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.model.layers.LayerManager; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.xaero.renderers.XaeroLayerRenderer; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.UndergroundFluidChunkRenderStep; -public class UndergroundFluidChunkRenderer extends LayerRenderer { +public class XaeroUndergroundFluidChunkRenderer extends XaeroLayerRenderer { - public static UndergroundFluidChunkRenderer instance = new UndergroundFluidChunkRenderer(); - - public UndergroundFluidChunkRenderer() { - super(UndergroundFluidChunkLayerManager.instance); + public XaeroUndergroundFluidChunkRenderer(LayerManager manager) { + super(manager); } @Override diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidRenderer.java similarity index 64% rename from src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java rename to src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidRenderer.java index 8883a833..2d4e7e03 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/UndergroundFluidRenderer.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidRenderer.java @@ -3,17 +3,16 @@ import java.util.ArrayList; import java.util.List; -import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.model.layers.LayerManager; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.xaero.renderers.XaeroLayerRenderer; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.UndergroundFluidRenderStep; -public class UndergroundFluidRenderer extends LayerRenderer { +public class XaeroUndergroundFluidRenderer extends XaeroLayerRenderer { - public static UndergroundFluidRenderer instance = new UndergroundFluidRenderer(); - - public UndergroundFluidRenderer() { - super(UndergroundFluidLayerManager.instance); + public XaeroUndergroundFluidRenderer(LayerManager manager) { + super(manager); } @Override diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java deleted file mode 100644 index 0a5e1856..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/InteractableRenderStep.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; - -import net.minecraft.client.gui.GuiScreen; - -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; - -public interface InteractableRenderStep extends RenderStep { - - boolean isMouseOver(double mouseX, double mouseY, double scale); - - void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scale, int scaleAdj); - - void onActionButton(); - - IWaypointAndLocationProvider getLocationProvider(); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java index c31b0918..53bb6b02 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java @@ -1,6 +1,5 @@ package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; -import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; @@ -14,14 +13,15 @@ import org.lwjgl.opengl.GL11; +import com.gtnewhorizons.navigator.api.model.locations.IWaypointAndLocationProvider; +import com.gtnewhorizons.navigator.api.util.DrawUtils; +import com.gtnewhorizons.navigator.api.xaero.rendersteps.XaeroInteractableStep; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.integration.DrawUtils; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; -public class OreVeinRenderStep implements InteractableRenderStep { +public class OreVeinRenderStep implements XaeroInteractableStep { private final OreVeinLocation oreVeinLocation; private final ResourceLocation depletedTextureLocation = new ResourceLocation(Tags.MODID, "textures/depleted.png"); @@ -139,32 +139,27 @@ public boolean isMouseOver(double mouseX, double mouseY, double scale) { } @Override - public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scale, int scaleAdj) { - // correct for gl matrix differences - mouseX = mouseX * scale + (gui.mc.displayWidth >> 1); - mouseY = mouseY * scale + (gui.mc.displayHeight >> 1); - - final List tooltip = new ArrayList<>(); + public void getTooltip(List list) { if (oreVeinLocation.isDepleted()) { - tooltip.add(oreVeinLocation.getDepletedHint()); + list.add(oreVeinLocation.getDepletedHint()); } + if (oreVeinLocation.isActiveAsWaypoint()) { - tooltip.add(oreVeinLocation.getActiveWaypointHint()); + list.add(oreVeinLocation.getActiveWaypointHint()); } - tooltip.add(oreVeinLocation.getName()); - if (!oreVeinLocation.isDepleted()) { - tooltip.addAll(oreVeinLocation.getMaterialNames()); - } - tooltip.add(oreVeinLocation.getToggleDepletedHint()); - GL11.glPushMatrix(); + list.add(oreVeinLocation.getName()); - DrawUtils - .drawSimpleTooltip(gui, tooltip, mouseX / scaleAdj + 6, mouseY / scaleAdj - 12, 0xFFFFFFFF, 0x86000000); + if (!oreVeinLocation.isDepleted()) { + list.addAll(oreVeinLocation.getMaterialNames()); + } - GL11.glPopMatrix(); + list.add(oreVeinLocation.getToggleDepletedHint()); } + @Override + public void drawCustomTooltip(GuiScreen gui, double mouseX, double mouseY, double scale, int scaleAdj) {} + @Override public void onActionButton() { oreVeinLocation.toggleOreVein(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java deleted file mode 100644 index 2c4be5ca..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/RenderStep.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; - -import javax.annotation.Nullable; - -import net.minecraft.client.gui.GuiScreen; - -public interface RenderStep { - - void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double scale); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java deleted file mode 100644 index 3a47c484..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/ThaumcraftNodeRenderStep.java +++ /dev/null @@ -1,233 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; - -import javax.annotation.Nullable; - -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.util.ResourceLocation; - -import org.lwjgl.opengl.GL11; - -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.integration.DrawUtils; -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.locations.IWaypointAndLocationProvider; -import com.sinthoras.visualprospecting.integration.model.locations.ThaumcraftNodeLocation; - -import thaumcraft.api.aspects.Aspect; -import thaumcraft.client.lib.UtilsFX; - -public class ThaumcraftNodeRenderStep implements InteractableRenderStep { - - private static final ResourceLocation markedTextureLocation = new ResourceLocation( - Tags.MODID, - "textures/node_marked.png"); - private static final ResourceLocation unmarkedTextureLocation = new ResourceLocation( - Tags.MODID, - "textures/node_unmarked.png"); - - private final ThaumcraftNodeLocation thaumcraftNodeLocation; - - private double centerPixelX = 0; - private double centerPixelY = 0; - private double clickableRadiusPixelSquared = 0; - - public ThaumcraftNodeRenderStep(ThaumcraftNodeLocation thaumcraftNodeLocation) { - this.thaumcraftNodeLocation = thaumcraftNodeLocation; - } - - @Override - public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double scale) { - final double borderSize = 44; - final double borderSizeHalf = borderSize / 2; - final double scaleForGui = Math.max(0.5, scale); - centerPixelX = (thaumcraftNodeLocation.getBlockX() - cameraX) * scaleForGui; - centerPixelY = (thaumcraftNodeLocation.getBlockZ() - cameraZ) * scaleForGui; - clickableRadiusPixelSquared = borderSizeHalf * borderSizeHalf; - - GL11.glPushMatrix(); - GL11.glTranslated( - thaumcraftNodeLocation.getBlockX() - cameraX, - thaumcraftNodeLocation.getBlockZ() - cameraZ, - 0); - GL11.glScaled(1 / scaleForGui, 1 / scaleForGui, 1); - - final int alpha = 204; - DrawUtils.drawQuad( - thaumcraftNodeLocation.isActiveAsWaypoint() ? markedTextureLocation : unmarkedTextureLocation, - -borderSizeHalf, - -borderSizeHalf, - borderSize, - borderSize, - 0xFFFFFF, - alpha); - - final int aspectPixelDiameter = 32; - DrawUtils.drawAspect(0, 0, aspectPixelDiameter, thaumcraftNodeLocation.getStrongestAspect(), 0); - - GL11.glPopMatrix(); - } - - @Override - public boolean isMouseOver(double mouseX, double mouseY, double scale) { - final double scaleForGui = Math.max(0.5, scale); - final double deltaX = mouseX * scaleForGui - centerPixelX; - final double deltaY = mouseY * scaleForGui - centerPixelY; - return deltaX * deltaX + deltaY * deltaY <= clickableRadiusPixelSquared; - } - - @Override - public void drawTooltip(GuiScreen gui, double mouseX, double mouseY, double scale, int scaleAdj) { - - GL11.glPushMatrix(); - - mouseX = (mouseX * scale + (gui.mc.displayWidth >> 1)) / scaleAdj; - mouseY = (mouseY * scale + (gui.mc.displayHeight >> 1)) / scaleAdj; - - final boolean isWaypoint = thaumcraftNodeLocation.isActiveAsWaypoint(); - final String asWaypoint = thaumcraftNodeLocation.getActiveWaypointHint(); - final String title = thaumcraftNodeLocation.getTitle(); - final String nodeDescription = thaumcraftNodeLocation.getDescription(); - final String deleteHint = thaumcraftNodeLocation.getDeleteHint(); - - int maxTextWidth = Math.max( - Math.max( - gui.mc.fontRenderer.getStringWidth(title), - gui.mc.fontRenderer.getStringWidth(nodeDescription)), - gui.mc.fontRenderer.getStringWidth(deleteHint)); - if (isWaypoint) { - maxTextWidth = Math.max(maxTextWidth, gui.mc.fontRenderer.getStringWidth(asWaypoint)); - } - if (gui.mc.fontRenderer.getBidiFlag()) { - maxTextWidth = (int) Math.ceil(maxTextWidth * 1.25f); - } - - final int aspectRows = (thaumcraftNodeLocation.getAspects().size() + 4) / 5; // Equivalent to Math.ceil(size / - // 5) - final int aspectColumns = Math.min(thaumcraftNodeLocation.getAspects().size(), 5); - - int pixelX = (int) (mouseX + 12); - int pixelY = (int) (mouseY - 12); - final int tooltipHeight = (isWaypoint ? 44 : 32) + aspectRows * 16; - final int tooltipWidth = Math.max(aspectColumns * 16, maxTextWidth); - if (pixelX + tooltipWidth > gui.mc.displayWidth) { - pixelX -= 28 + tooltipWidth; - } - if (pixelY + tooltipHeight + 6 > gui.mc.displayHeight) { - pixelY = gui.mc.displayHeight - tooltipHeight - 6; - } - - GL11.glDisable(GL11.GL_DEPTH_TEST); - - // Draw background - final int backgroundColor = 0xF0100010; - DrawUtils.drawGradientRect( - pixelX - 3, - pixelY - 4, - pixelX + tooltipWidth + 3, - pixelY - 3, - backgroundColor, - backgroundColor); - DrawUtils.drawGradientRect( - pixelX - 3, - pixelY + tooltipHeight + 3, - pixelX + tooltipWidth + 3, - pixelY + tooltipHeight + 4, - backgroundColor, - backgroundColor); - DrawUtils.drawGradientRect( - pixelX - 3, - pixelY - 3, - pixelX + tooltipWidth + 3, - pixelY + tooltipHeight + 3, - backgroundColor, - backgroundColor); - DrawUtils.drawGradientRect( - pixelX - 4, - pixelY - 3, - pixelX - 3, - pixelY + tooltipHeight + 3, - backgroundColor, - backgroundColor); - DrawUtils.drawGradientRect( - pixelX + tooltipWidth + 3, - pixelY - 3, - pixelX + tooltipWidth + 4, - pixelY + tooltipHeight + 3, - backgroundColor, - backgroundColor); - - // Draw text - int offset = 0; - if (gui.mc.fontRenderer.getBidiFlag()) { - if (isWaypoint) { - final int asWaypointWidth = (int) Math.ceil(gui.mc.fontRenderer.getStringWidth(asWaypoint) * 1.1f); - gui.mc.fontRenderer.drawString(title, pixelX + tooltipWidth - asWaypointWidth, pixelY, 0xFFFFFFFF); - offset += 12; - } - final int titleWidth = (int) Math.ceil(gui.mc.fontRenderer.getStringWidth(title) * 1.1f); - gui.mc.fontRenderer.drawString(title, pixelX + tooltipWidth - titleWidth, pixelY + offset, 0xFFFFFFFF); - offset += 12; - final int nodeDescriptonWidth = (int) Math.ceil(gui.mc.fontRenderer.getStringWidth(nodeDescription) * 1.1f); - gui.mc.fontRenderer.drawString( - nodeDescription, - pixelX + nodeDescriptonWidth - titleWidth, - pixelY + offset, - 0xFFFFFFFF); - - final int deleteHintWidth = (int) Math.ceil(gui.mc.fontRenderer.getStringWidth(deleteHint) * 1.1f); - gui.mc.fontRenderer.drawString( - deleteHint, - pixelX + tooltipWidth - deleteHintWidth, - pixelY + aspectRows * 16 + offset + 12, - 0xFFFFFFFF); - } else { - if (isWaypoint) { - gui.mc.fontRenderer.drawString(asWaypoint, pixelX, pixelY, 0xFFFFFFFF); - offset += 12; - } - gui.mc.fontRenderer.drawString(title, pixelX, pixelY + offset, 0xFFFFFFFF); - offset += 12; - gui.mc.fontRenderer.drawString(nodeDescription, pixelX, pixelY + offset, 0xFFFFFFFF); - - gui.mc.fontRenderer.drawString(deleteHint, pixelX, pixelY + aspectRows * 16 + offset + 12, 0xFFFFFFFF); - } - - // Draw aspects - int aspectX = 0; - int aspectY = 0; - - for (Aspect aspect : thaumcraftNodeLocation.getAspects().getAspectsSortedAmount()) { - GL11.glPushMatrix(); - UtilsFX.drawTag( - pixelX + aspectX * 16, - pixelY + aspectY * 16 + offset + 10, - aspect, - thaumcraftNodeLocation.getAspects().getAmount(aspect), - 0, - 0.01, - 1, - 1, - false); - GL11.glPopMatrix(); - ++aspectX; - if (aspectX >= 5) { - aspectX = 0; - ++aspectY; - } - } - - GL11.glDisable(GL11.GL_LIGHTING); - - GL11.glPopMatrix(); - } - - @Override - public void onActionButton() { - ThaumcraftNodeLayerManager.instance.deleteNode(thaumcraftNodeLocation); - } - - @Override - public IWaypointAndLocationProvider getLocationProvider() { - return thaumcraftNodeLocation; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java index 47e477ef..0dc58c99 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java @@ -6,13 +6,14 @@ import org.lwjgl.opengl.GL11; +import com.gtnewhorizons.navigator.api.util.DrawUtils; +import com.gtnewhorizons.navigator.api.xaero.rendersteps.XaeroRenderStep; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.DrawUtils; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -public class UndergroundFluidChunkRenderStep implements RenderStep { +public class UndergroundFluidChunkRenderStep implements XaeroRenderStep { private final UndergroundFluidChunkLocation undergroundFluidChunkLocation; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java index 507031b6..64cbe4ca 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java @@ -7,11 +7,12 @@ import org.lwjgl.opengl.GL11; +import com.gtnewhorizons.navigator.api.util.DrawUtils; +import com.gtnewhorizons.navigator.api.xaero.rendersteps.XaeroRenderStep; import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.DrawUtils; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; -public class UndergroundFluidRenderStep implements RenderStep { +public class UndergroundFluidRenderStep implements XaeroRenderStep { private final UndergroundFluidLocation undergroundFluidLocation; diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java index a95efcdd..8ec8c144 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java @@ -22,26 +22,8 @@ public enum Mixins { GT_MetaTileEntity_ScannerMixin("gregtech.GT_MetaTileEntity_ScannerMixin", GT5U), GT_WorldGenContainerMixin("gregtech.WorldGenContainerMixin", GT5U), - // Journeymap mixins - DisplayVarsAccessorMixin("journeymap.DisplayVarsAccessor", Side.CLIENT, JOURNEYMAP), - FullscreenAccessorMixin("journeymap.FullscreenAccessor", Side.CLIENT, JOURNEYMAP), - FullscreenMixin("journeymap.FullscreenMixin", Side.CLIENT, JOURNEYMAP), - FullscreenActionsMixin("journeymap.FullscreenActionsMixin", Side.CLIENT, JOURNEYMAP), - MiniMapMixin("journeymap.MiniMapMixin", Side.CLIENT, JOURNEYMAP), - RenderWaypointBeaconMixin("journeymap.RenderWaypointBeaconMixin", Side.CLIENT, JOURNEYMAP), - WaypointManagerMixin("journeymap.WaypointManagerMixin", Side.CLIENT, JOURNEYMAP), - - // TC node tracker mixins - GuiMainMixin("tcnodetracker.GuiMainMixin", Side.CLIENT, TCNODETRACKER), - - // Xaerosworldmap & Xaerosminimap mixins - GuiMapMixin("xaerosworldmap.GuiMapMixin", Side.CLIENT, XAEROWORLDMAP), - WaypointsIngameRendererMixin("xaerosminimap.WaypointsIngameRendererMixin", Side.CLIENT, XAEROMINIMAP), - MinimapRendererMixin("xaerosminimap.MinimapRendererMixin", Side.CLIENT, XAEROMINIMAP, XAEROWORLDMAP), - // Vanilla Mixins MinecraftServerAccessorMixin("minecraft.MinecraftServerAccessor", Phase.EARLY, Side.BOTH, VANILLA), - ForgeHooksClientMixin("minecraft.ForgeHooksClientMixin", Phase.EARLY, Side.CLIENT, XAEROMINIMAP, XAEROWORLDMAP), ItemEditableBookMixin("minecraft.ItemEditableBookMixin", Phase.EARLY, VANILLA); public final String mixinClass; diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java index 3297d630..454bac18 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java @@ -5,11 +5,7 @@ public enum TargetedMod { BARTWORKS("BartWorks", "com.github.bartimaeusnek.bartworks.ASM.BWCorePlugin", "bartworks"), GALACTICGREG("Galactic Greg", null, "galacticgreg"), GT5U("GregTech5u", null, "gregtech"), // Also matches GT6. - JOURNEYMAP("JourneyMap", null, "journeymap"), - TCNODETRACKER("TC Node Tracker", null, "tcnodetracker"), - VANILLA("Minecraft", null), - XAEROMINIMAP("Xaero's Minimap", "xaero.common.core.XaeroMinimapPlugin", "XaeroMinimap"), - XAEROWORLDMAP("Xaero's World Map", "xaero.map.core.XaeroWorldMapPlugin", "XaeroWorldMap"); + VANILLA("Minecraft", null); /** The "name" in the @Mod annotation */ public final String modName; diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ForgeHooksClientMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ForgeHooksClientMixin.java deleted file mode 100644 index 7969a83d..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ForgeHooksClientMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.early.minecraft; - -import net.minecraftforge.client.ForgeHooksClient; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -// used to enable the stencil buffer for on-minimap rendering -@Mixin(value = ForgeHooksClient.class, remap = false) -public class ForgeHooksClientMixin { - - // this is only a mixin because it needs to run before the minecraft window is created - @Inject(method = "createDisplay", at = @At("HEAD")) - private static void visualprospecting$enableStencilBuffer(CallbackInfo ci) { - // give me my stencil buffer, forge. - System.setProperty("forge.forceDisplayStencil", "true"); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java deleted file mode 100644 index c4d1ba06..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/DisplayVarsAccessor.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.journeymap; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import journeymap.client.ui.minimap.DisplayVars; -import journeymap.client.ui.minimap.Shape; - -@Mixin(DisplayVars.class) -public interface DisplayVarsAccessor { - - @Accessor(remap = false) - float getDrawScale(); - - @Accessor(remap = false) - double getFontScale(); - - @Accessor(remap = false) - Shape getShape(); - - @Accessor(remap = false) - int getMinimapWidth(); - -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java deleted file mode 100644 index 823ed72b..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenAccessor.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.journeymap; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import journeymap.client.render.map.GridRenderer; -import journeymap.client.ui.fullscreen.Fullscreen; - -@Mixin(Fullscreen.class) -public interface FullscreenAccessor { - - @Accessor(remap = false) - static GridRenderer getGridRenderer() { - throw new IllegalStateException("Mixin accessor failed to apply"); - } - -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java deleted file mode 100644 index c4eccd06..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenActionsMixin.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.journeymap; - -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.resources.I18n; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import com.sinthoras.visualprospecting.integration.journeymap.ResetClientCacheConfirmation; - -import journeymap.client.ui.UIManager; -import journeymap.client.ui.component.Button; -import journeymap.client.ui.component.ButtonList; -import journeymap.client.ui.component.JmUI; -import journeymap.client.ui.dialog.FullscreenActions; - -@Mixin(FullscreenActions.class) -public abstract class FullscreenActionsMixin extends JmUI { - - @Shadow(remap = false) - Button buttonAbout; - - private Button resetVisualProspectingCacheButton; - - public FullscreenActionsMixin() { - super(""); - } - - @Inject( - method = "func_73866_w_", - at = @At(value = "INVOKE", target = "Ljourneymap/client/ui/component/Button;setDrawFrame(Z)V"), - remap = false, - require = 1) - private void visualprospecting$onInitGui(CallbackInfo ci) { - resetVisualProspectingCacheButton = new Button(I18n.format("visualprospecting.button.resetprogress")); - resetVisualProspectingCacheButton.setTooltip(I18n.format("visualprospecting.button.resetprogress.tooltip")); - buttonList.add(resetVisualProspectingCacheButton); - } - - @Inject(method = "layoutButtons", at = @At("RETURN"), remap = false, require = 1) - private void visualprospecting$onLayoutButtons(CallbackInfo ci) { - final ButtonList row = new ButtonList(buttonAbout, resetVisualProspectingCacheButton); - row.layoutCenteredHorizontal(width / 2, height / 4, true, 4); - } - - @Inject( - method = "func_146284_a", - at = @At("HEAD"), - remap = false, - cancellable = true, - require = 1, - locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void visualprospecting$onButtonClicked(GuiButton guibutton, CallbackInfo ci) { - if (guibutton == resetVisualProspectingCacheButton) { - UIManager.getInstance().open(ResetClientCacheConfirmation.class); - ci.cancel(); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java deleted file mode 100644 index 1cc9af4c..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/FullscreenMixin.java +++ /dev/null @@ -1,319 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.journeymap; - -import java.util.List; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.renderer.RenderHelper; - -import org.apache.logging.log4j.Level; -import org.lwjgl.input.Mouse; -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; -import com.sinthoras.visualprospecting.integration.journeymap.buttons.LayerButton; -import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; -import com.sinthoras.visualprospecting.integration.journeymap.render.WaypointProviderLayerRenderer; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; - -import journeymap.client.Constants; -import journeymap.client.io.ThemeFileHandler; -import journeymap.client.log.LogFormatter; -import journeymap.client.log.StatTimer; -import journeymap.client.model.BlockCoordIntPair; -import journeymap.client.render.map.GridRenderer; -import journeymap.client.ui.UIManager; -import journeymap.client.ui.component.Button; -import journeymap.client.ui.component.ButtonList; -import journeymap.client.ui.component.JmUI; -import journeymap.client.ui.fullscreen.Fullscreen; -import journeymap.client.ui.fullscreen.MapChat; -import journeymap.client.ui.fullscreen.layer.LayerDelegate; -import journeymap.client.ui.theme.Theme; -import journeymap.client.ui.theme.ThemeButton; -import journeymap.client.ui.theme.ThemeToggle; -import journeymap.client.ui.theme.ThemeToolbar; - -@Mixin(value = Fullscreen.class, remap = false) -public abstract class FullscreenMixin extends JmUI { - - @Unique - private int oldMouseX = 0; - @Unique - private int oldMouseY = 0; - @Unique - private long timeLastClick = 0; - - @Final - @Shadow - static GridRenderer gridRenderer; - - @Shadow - ThemeToolbar mapTypeToolbar; - - @Shadow - ThemeButton buttonCaves; - - @Shadow - ThemeButton buttonNight; - - @Shadow - ThemeButton buttonDay; - - @Shadow - StatTimer drawScreenTimer; - - @Shadow() - MapChat chat; - - @Final - @Shadow - LayerDelegate layerDelegate; - - @Shadow - boolean firstLayoutPass; - - @Shadow - int mx; - - @Shadow - int my; - - public FullscreenMixin() { - super(""); - } - - @Inject(method = "*", at = @At("RETURN"), require = 1) - private void visualprospecting$init(CallbackInfo ci) { - MapState.instance.layers.forEach(LayerManager::forceRefresh); - } - - @Shadow - private int getMapFontScale() { - throw new IllegalStateException("Mixin failed to shadow getMapFontScale()"); - } - - @Shadow - void drawMap() { - throw new IllegalStateException("Mixin failed to shadow drawMap()"); - } - - @Shadow - public abstract void drawBackground(int layer); - - @Inject(method = "*", at = @At("RETURN"), require = 1) - private void visualprospecting$onConstructed(CallbackInfo ci) { - MapState.instance.layers.forEach(LayerManager::onOpenMap); - } - - @Inject( - method = "drawMap", - at = @At( - value = "INVOKE", - target = "Ljourneymap/client/model/MapState;getDrawWaypointSteps()Ljava/util/List;"), - remap = false, - require = 1, - locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void visualprospecting$onBeforeDrawJourneyMapWaypoints(CallbackInfo ci, boolean refreshReady, - StatTimer timer, int xOffset, int yOffset, float drawScale) { - final int fontScale = getMapFontScale(); - final Minecraft minecraft = Minecraft.getMinecraft(); - final int centerBlockX = (int) Math.round(gridRenderer.getCenterBlockX()); - final int centerBlockZ = (int) Math.round(gridRenderer.getCenterBlockZ()); - final int widthBlocks = minecraft.displayWidth >> gridRenderer.getZoom(); - final int heightBlocks = minecraft.displayHeight >> gridRenderer.getZoom(); - for (LayerManager layerManager : MapState.instance.layers) { - if (layerManager.isLayerActive()) { - layerManager.recacheFullscreenMap(centerBlockX, centerBlockZ, widthBlocks, heightBlocks); - } - } - - for (LayerRenderer layerRenderer : JourneyMapState.instance.renderers) { - if (layerRenderer.isLayerActive()) { - gridRenderer.draw( - layerRenderer.getDrawStepsCachedForRendering(), - xOffset, - yOffset, - drawScale, - fontScale, - 0.0); - } - } - } - - @Redirect( - method = "initButtons", - at = @At( - value = "FIELD", - target = "Ljourneymap/client/ui/fullscreen/Fullscreen;mapTypeToolbar:Ljourneymap/client/ui/theme/ThemeToolbar;", - opcode = Opcodes.PUTFIELD), - require = 1) - private void visualprospecting$OnCreateMapTypeToolbar(Fullscreen owner, ThemeToolbar value) { - final Theme theme = ThemeFileHandler.getCurrentTheme(); - final ButtonList buttonList = new ButtonList(); - - for (LayerButton layerButton : JourneyMapState.instance.buttons) { - final ThemeToggle button = new ThemeToggle( - theme, - layerButton.getButtonTextKey(), - layerButton.getIconName()); - layerButton.setButton(button); - button.setToggled(layerButton.isActive(), false); - button.addToggleListener((unused, toggled) -> { - layerButton.toggle(); - return true; - }); - buttonList.add(button); - } - - buttonList.add(buttonCaves); - buttonList.add(buttonNight); - buttonList.add(buttonDay); - mapTypeToolbar = new ThemeToolbar(theme, buttonList); - } - - @Override - public void drawScreen(int width, int height, float f) { - try { - drawBackground(0); - drawMap(); - drawScreenTimer.start(); - layoutButtons(); - List tooltip = null; - if (firstLayoutPass) { - layoutButtons(); - firstLayoutPass = false; - } else { - for (int k = 0; k < buttonList.size(); ++k) { - GuiButton guibutton = buttonList.get(k); - guibutton.drawButton(mc, width, height); - if (tooltip == null && guibutton instanceof Button) { - Button button = (Button) guibutton; - if (button.mouseOver(mx, my)) { - tooltip = button.getTooltip(); - } - } - } - } - - final int scaledMouseX = (mx * mc.displayWidth) / this.width; - final int scaledMouseY = (my * mc.displayHeight) / this.height; - for (LayerRenderer layer : JourneyMapState.instance.renderers) { - if (layer instanceof WaypointProviderLayerRenderer) { - final WaypointProviderLayerRenderer waypointProviderLayer = (WaypointProviderLayerRenderer) layer; - waypointProviderLayer.onMouseMove(scaledMouseX, scaledMouseY); - } - } - - if (tooltip == null) { - for (LayerRenderer layer : JourneyMapState.instance.renderers) { - if (layer instanceof WaypointProviderLayerRenderer) { - final WaypointProviderLayerRenderer waypointProviderLayer = (WaypointProviderLayerRenderer) layer; - if (waypointProviderLayer.isLayerActive()) { - tooltip = waypointProviderLayer.getTextTooltip(); - } - } - } - } - - if (chat != null) { - chat.drawScreen(width, height, f); - } - - if (tooltip != null && !tooltip.isEmpty()) { - drawHoveringText(tooltip, mx, my, getFontRenderer()); - RenderHelper.disableStandardItemLighting(); - } else { - for (LayerRenderer layer : JourneyMapState.instance.renderers) { - if (layer instanceof WaypointProviderLayerRenderer) { - final WaypointProviderLayerRenderer waypointProviderLayer = (WaypointProviderLayerRenderer) layer; - if (waypointProviderLayer.isLayerActive()) { - waypointProviderLayer.drawCustomTooltip(getFontRenderer(), mx, my, this.width, this.height); - } - } - } - } - - } catch (Throwable var11) { - logger.log( - Level.ERROR, - "Unexpected exception in jm.fullscreen.drawScreen(): " + LogFormatter.toString(var11)); - UIManager.getInstance().closeAll(); - } finally { - drawScreenTimer.stop(); - } - } - - @Inject(method = "keyTyped", at = @At(value = "HEAD"), remap = true, require = 1, cancellable = true) - private void visualprospecting$onKeyPress(CallbackInfo ci) { - if ((chat == null || chat.isHidden()) && Constants.isPressed(VP.keyAction)) { - for (LayerRenderer layer : JourneyMapState.instance.renderers) { - if (layer instanceof WaypointProviderLayerRenderer) { - ((WaypointProviderLayerRenderer) layer).onActionKeyPressed(); - } - } - ci.cancel(); - } - } - - @Override - protected void mouseClicked(int mouseX, int mouseY, int mouseButton) { - if (chat != null && !chat.isHidden()) { - chat.mouseClicked(mouseX, mouseY, mouseButton); - } - - super.mouseClicked(mouseX, mouseY, mouseButton); - if (!this.isMouseOverButton(mouseX, mouseY)) { - final int scaledMouseX = mx * mc.displayWidth / width; - final int scaledMouseY = my * mc.displayHeight / height; - final double blockSize = Math.pow(2.0D, gridRenderer.getZoom()); - BlockCoordIntPair blockCoord = gridRenderer - .getBlockUnderMouse(Mouse.getEventX(), Mouse.getEventY(), mc.displayWidth, mc.displayHeight); - if (!visualprospecting$onMapClicked(mouseButton, scaledMouseX, scaledMouseY, blockSize, blockCoord)) { - layerDelegate.onMouseClicked( - mc, - Mouse.getEventX(), - Mouse.getEventY(), - gridRenderer.getWidth(), - gridRenderer.getHeight(), - blockCoord, - mouseButton); - } - } - } - - private boolean visualprospecting$onMapClicked(int mouseButton, int mouseX, int mouseY, double blockSize, - BlockCoordIntPair blockCoord) { - final long timestamp = System.currentTimeMillis(); - final boolean isDoubleClick = mouseX == oldMouseX && mouseY == oldMouseY && timestamp - timeLastClick < 500; - oldMouseX = mouseX; - oldMouseY = mouseY; - timeLastClick = isDoubleClick ? 0 : timestamp; - if (mouseButton != 0) { - return false; - } - boolean layerHit = false; - boolean clickOutside = false; - for (LayerRenderer layer : JourneyMapState.instance.renderers) { - if (layer instanceof WaypointProviderLayerRenderer wpLayerRender) { - wpLayerRender.onMouseMove(mouseX, mouseY); - layerHit |= wpLayerRender.onMouseAction(isDoubleClick); - if (!layerHit) { - clickOutside |= wpLayerRender.onMouseActionOutsideLayer(isDoubleClick, blockCoord); - } - } - } - return layerHit || clickOutside; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java deleted file mode 100644 index 572c7992..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/MiniMapMixin.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.journeymap; - -import net.minecraft.client.Minecraft; - -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; -import com.sinthoras.visualprospecting.integration.journeymap.render.LayerRenderer; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; - -import journeymap.client.render.draw.DrawStep; -import journeymap.client.render.map.GridRenderer; -import journeymap.client.ui.minimap.DisplayVars; -import journeymap.client.ui.minimap.MiniMap; -import journeymap.client.ui.minimap.Shape; - -@Mixin(MiniMap.class) -public abstract class MiniMapMixin { - - @Final - @Shadow(remap = false) - private static GridRenderer gridRenderer; - - @Final - @Shadow(remap = false) - private Minecraft mc; - - @Shadow(remap = false) - private DisplayVars dv; - - @Inject(method = "drawOnMapWaypoints", at = @At(value = "HEAD"), remap = false, require = 1) - private void visualprospecting$onBeforeDrawWaypoints(double rotation, CallbackInfo ci) { - for (LayerManager layerManager : MapState.instance.layers) { - if (layerManager.isLayerActive()) { - if (((DisplayVarsAccessor) dv).getShape() == Shape.Circle) { - layerManager.recacheMiniMap( - (int) mc.thePlayer.posX, - (int) mc.thePlayer.posZ, - ((DisplayVarsAccessor) dv).getMinimapWidth()); - } else { - layerManager.recacheMiniMap( - (int) mc.thePlayer.posX, - (int) mc.thePlayer.posZ, - gridRenderer.getWidth(), - gridRenderer.getHeight()); - } - } - } - - for (LayerRenderer layerRenderer : JourneyMapState.instance.renderers) { - if (layerRenderer.isLayerActive()) { - for (DrawStep drawStep : layerRenderer.getDrawStepsCachedForRendering()) { - drawStep.draw( - 0.0D, - 0.0D, - gridRenderer, - ((DisplayVarsAccessor) dv).getDrawScale(), - ((DisplayVarsAccessor) dv).getFontScale(), - rotation); - } - } - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java deleted file mode 100644 index 9982d486..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/RenderWaypointBeaconMixin.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.journeymap; - -import net.minecraft.client.Minecraft; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.sinthoras.visualprospecting.integration.journeymap.JourneyMapState; -import com.sinthoras.visualprospecting.integration.journeymap.waypoints.WaypointManager; - -import journeymap.client.model.Waypoint; -import journeymap.client.render.ingame.RenderWaypointBeacon; - -@Mixin(RenderWaypointBeacon.class) -public class RenderWaypointBeaconMixin { - - @Shadow(remap = false) - static Minecraft mc; - - @Shadow(remap = false) - static void doRender(Waypoint waypoint) { - throw new IllegalStateException("Mixin failed to shadow doRender()"); - } - - @Inject( - method = "renderAll", - at = @At( - value = "INVOKE", - target = "Ljourneymap/client/waypoint/WaypointStore;instance()Ljourneymap/client/waypoint/WaypointStore;"), - remap = false, - require = 1) - private static void visualprospecting$onRenderAll(CallbackInfo ci) { - for (WaypointManager waypointManager : JourneyMapState.instance.waypointManagers) { - if (waypointManager.hasWaypoint()) { - final Waypoint waypoint = waypointManager.getJmWaypoint(); - if (waypoint.getDimensions().contains(mc.thePlayer.dimension)) { - doRender(waypoint); - } - } - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java deleted file mode 100644 index 597cad96..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/journeymap/WaypointManagerMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.journeymap; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.model.layers.WaypointProviderManager; - -import journeymap.client.ui.waypoint.WaypointManager; - -@Mixin(WaypointManager.class) -public class WaypointManagerMixin { - - @Inject(method = "toggleItems", at = @At("HEAD"), remap = false, require = 1) - private void visualprospecting$onToggleAllWaypoints(boolean enable, CallbackInfoReturnable cir) { - if (!enable) { - for (LayerManager layer : MapState.instance.layers) { - if (layer instanceof WaypointProviderManager) { - ((WaypointProviderManager) layer).clearActiveWaypoint(); - } - } - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java deleted file mode 100644 index c3e057fe..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/tcnodetracker/GuiMainMixin.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.tcnodetracker; - -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.resources.I18n; - -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import com.dyonovan.tcnodetracker.gui.GuiMain; -import com.dyonovan.tcnodetracker.lib.AspectLoc; -import com.sinthoras.visualprospecting.integration.model.layers.ThaumcraftNodeLayerManager; -import com.sinthoras.visualprospecting.integration.model.waypoints.Waypoint; - -@Mixin(GuiMain.class) -public class GuiMainMixin { - - @Shadow(remap = false) - private int low; - - @Inject( - method = "actionPerformed", - at = @At( - value = "FIELD", - target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;zMarker:I", - opcode = Opcodes.PUTSTATIC, - shift = At.Shift.AFTER, - remap = false), - require = 1, - locals = LocalCapture.CAPTURE_FAILEXCEPTION, - cancellable = true) - private void visualprospecting$onWaypointSet(GuiButton button, CallbackInfo ci, int i) { - final AspectLoc aspect = GuiMain.aspectList.get(low + i); - GuiMain.aspectList.clear(); - ThaumcraftNodeLayerManager.instance.setActiveWaypoint( - new Waypoint( - aspect.x, - aspect.y, - aspect.z, - aspect.dimID, - I18n.format("visualprospecting.tracked", I18n.format("tile.blockAiry.0.name")), - 0xFFFFFF)); - ci.cancel(); - } - - @Inject( - method = "actionPerformed", - at = @At( - value = "FIELD", - target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;doGui:Z", - opcode = Opcodes.PUTSTATIC, - ordinal = 0, - remap = false), - require = 1) - private void visualprospecting$onWaypointClear(CallbackInfo ci) { - ThaumcraftNodeLayerManager.instance.clearActiveWaypoint(); - } - - @Inject( - method = "actionPerformed", - at = @At( - value = "FIELD", - target = "Lcom/dyonovan/tcnodetracker/TCNodeTracker;doGui:Z", - opcode = Opcodes.PUTSTATIC, - ordinal = 1, - remap = false), - require = 1, - locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void visualprospecting$onWaypointDelete(GuiButton button, CallbackInfo ci, int i, int k, int j) { - ThaumcraftNodeLayerManager.instance.clearActiveWaypoint(); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java deleted file mode 100644 index 448a9a6b..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/MinimapRendererMixin.java +++ /dev/null @@ -1,122 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.xaerosminimap; - -import java.util.ArrayList; - -import net.minecraft.client.Minecraft; -import net.minecraftforge.client.MinecraftForgeClient; - -import org.lwjgl.opengl.GL11; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.XaeroWorldMapState; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; - -import xaero.common.XaeroMinimapSession; -import xaero.common.minimap.MinimapProcessor; -import xaero.common.minimap.render.MinimapRenderer; -import xaero.common.settings.ModSettings; - -@Mixin(value = MinimapRenderer.class, remap = false) -public class MinimapRendererMixin { - - @Unique - private boolean stencilEnabled = true; - - @Shadow - protected Minecraft mc; - - @Shadow - protected double zoom; - - @Inject( - method = "renderMinimap", - at = @At( - value = "INVOKE", - target = "Lxaero/common/minimap/waypoints/render/WaypointsGuiRenderer;render(Lxaero/common/XaeroMinimapSession;Lxaero/common/minimap/render/MinimapRendererHelper;DDIIDDFDZFZ)V"), - locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void visualprospecting$injectDraw(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, - int y, int width, int height, int scale, int size, float partial, CallbackInfo ci, ModSettings settings, - ArrayList underText, int mapSize, int bufferSize, float minimapScale, float mapScale, float sizeFix, - int shape, boolean lockedNorth, double angle, double ps, double pc, boolean useWorldMap, int lightLevel, - boolean cave, boolean circleShape, int scaledX, int scaledY, int minimapFrameSize, int circleSides, - int frameType, boolean renderFrame, int frameTextureX, int halfFrame, int rightCornerStartX, int specH, - boolean safeMode, double playerX, double playerZ) { - for (LayerManager layerManager : MapState.instance.layers) { - if (layerManager.isLayerActive()) { - if (circleShape) { - layerManager.recacheMiniMap((int) mc.thePlayer.posX, (int) mc.thePlayer.posZ, minimapFrameSize * 2); - } else { - layerManager.recacheMiniMap( - (int) mc.thePlayer.posX, - (int) mc.thePlayer.posZ, - minimapFrameSize * 2, - minimapFrameSize * 2); - } - } - } - - if (stencilEnabled) { - double mapZoom = zoom * (double) minimapScale / 2.0; - GL11.glPushMatrix(); - GL11.glEnable(GL11.GL_STENCIL_TEST); - GL11.glRotated(Math.toDegrees(angle) - 90, 0.0, 0.0, 1.0); - GL11.glScaled(mapZoom, mapZoom, 0); - GL11.glStencilFunc(GL11.GL_EQUAL, 1, 1); - for (LayerRenderer renderer : XaeroWorldMapState.instance.renderers) { - if (renderer.isLayerActive()) { - for (RenderStep renderStep : renderer.getRenderSteps()) { - renderStep.draw(null, playerX, playerZ, mapZoom); - } - } - } - GL11.glDisable(GL11.GL_STENCIL_TEST); - GL11.glPopMatrix(); - } - } - - @Inject( - method = "renderMinimap", - at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glScalef(FFF)V", shift = At.Shift.AFTER), - slice = @Slice( - to = @At( - value = "INVOKE", - target = "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V"))) - private void visualprospecting$injectBeginStencil(XaeroMinimapSession minimapSession, MinimapProcessor minimap, - int x, int y, int width, int height, int scale, int size, float partial, CallbackInfo ci) { - if (stencilEnabled && MinecraftForgeClient.getStencilBits() == 0) { - stencilEnabled = false; - VP.warn("Could not enable stencils! Xaero's minimap overlays will not render"); - } - // if stencil is not enabled, this code will do nothing - GL11.glEnable(GL11.GL_STENCIL_TEST); - GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 1); - GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE); - GL11.glStencilMask(0xFF); - GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT); - } - - @Inject( - method = "renderMinimap", - at = @At(value = "INVOKE", target = "Lxaero/common/minimap/MinimapInterface;usingFBO()Z"), - slice = @Slice( - from = @At( - value = "INVOKE", - target = "Lxaero/common/minimap/render/MinimapRendererHelper;drawTexturedElipseInsideRectangle(IFFIIFF)V"))) - private void visualprospecting$injectEndStencil(XaeroMinimapSession minimapSession, MinimapProcessor minimap, int x, - int y, int width, int height, int scale, int size, float partial, CallbackInfo ci) { - GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); - GL11.glStencilMask(0x00); - GL11.glDisable(GL11.GL_STENCIL_TEST); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java deleted file mode 100644 index 78c4e4f3..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosminimap/WaypointsIngameRendererMixin.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.xaerosminimap; - -import net.minecraft.client.Minecraft; - -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.sinthoras.visualprospecting.integration.xaerominimap.XaeroMiniMapState; -import com.sinthoras.visualprospecting.integration.xaerominimap.waypoints.WaypointManager; - -import xaero.common.XaeroMinimapSession; -import xaero.common.minimap.waypoints.render.WaypointsIngameRenderer; - -@Mixin(value = WaypointsIngameRenderer.class, remap = false) -public class WaypointsIngameRendererMixin { - - @Inject( - method = "render", - at = @At( - value = "INVOKE", - target = "Lxaero/common/minimap/waypoints/render/WaypointsIngameRenderer;renderWaypointsList(Ljava/util/Collection;DDDLnet/minecraft/entity/Entity;Lnet/minecraft/client/renderer/Tessellator;DDDDFFDIFFLnet/minecraft/util/Vec3;D)V"), - slice = @Slice( - from = @At( - value = "FIELD", - target = "Lxaero/common/minimap/waypoints/WaypointsManager;customWaypoints:Ljava/util/Hashtable;", - opcode = Opcodes.GETSTATIC))) - private void visualprospecting$injectPreRenderCustomWaypoints(XaeroMinimapSession sets, float modCustomWaypoints, - CallbackInfo ci) { - for (WaypointManager manager : XaeroMiniMapState.instance.waypointManagers) { - if (manager.hasWaypoint()) { - manager.getXWaypoint().notifyDimension(Minecraft.getMinecraft().renderViewEntity.dimension); - } - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java deleted file mode 100644 index bda178cd..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/xaerosworldmap/GuiMapMixin.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.xaerosworldmap; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.entity.Entity; - -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.MapState; -import com.sinthoras.visualprospecting.integration.model.layers.LayerManager; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.XaeroWorldMapState; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.LayerButton; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.buttons.SizedGuiTexturedButton; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.InteractableLayerRenderer; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.LayerRenderer; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.RenderStep; - -import xaero.map.MapProcessor; -import xaero.map.gui.CursorBox; -import xaero.map.gui.GuiMap; -import xaero.map.gui.ScreenBase; -import xaero.map.misc.Misc; - -@Mixin(value = GuiMap.class, remap = false) -public abstract class GuiMapMixin extends ScreenBase { - - @Unique - private int oldMouseX = 0; - - @Unique - private int oldMouseY = 0; - - @Unique - private long timeLastClick = 0; - - protected GuiMapMixin(GuiScreen parent, GuiScreen escape) { - super(parent, escape); - } - - @Shadow - private double cameraX; - - @Shadow - private double cameraZ; - - @Shadow - private double scale; - - @Shadow - public abstract void addGuiButton(GuiButton b); - - @Shadow - private int screenScale; - - @Inject(method = "", at = @At("RETURN")) - private void visualprospecting$injectConstruct(GuiScreen parent, GuiScreen escape, MapProcessor mapProcessor, - Entity player, CallbackInfo ci) { - MapState.instance.layers.forEach(LayerManager::onOpenMap); - } - - // apparently mixin can read the obfuscated names even with the deobf jar loaded. weird - // i guess all the errors mcdev shows here aren't real? - // deobf method = "drawScreen" - @Inject( - method = "func_73863_a", - at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glPushMatrix()V", ordinal = 1), - locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void visualprospecting$injectPreRender(int scaledMouseX, int scaledMouseY, float partialTicks, - CallbackInfo ci, Minecraft mc) { - // snap the camera to whole pixel values. works around a rendering issue but causes another when framerate is - // uncapped - if (mc.gameSettings.limitFramerate < 255 || mc.gameSettings.enableVsync) { - cameraX = Math.round(cameraX * scale) / scale; - cameraZ = Math.round(cameraZ * scale) / scale; - } - - // there's some nice local variables for exactly this but the local table for this function is hell - double mousePosX = (double) ((int) Misc.getMouseX(mc) - mc.displayWidth / 2) / this.scale; - double mousePosZ = (double) ((int) Misc.getMouseY(mc) - mc.displayHeight / 2) / this.scale; - - for (LayerRenderer layer : XaeroWorldMapState.instance.renderers) { - if (layer instanceof InteractableLayerRenderer) { - ((InteractableLayerRenderer) layer).updateHovered(mousePosX, mousePosZ, scale); - } - } - } - - // deobf method = "drawScreen" - @Inject( - method = "func_73863_a", - at = @At( - value = "INVOKE", - target = "Lorg/lwjgl/opengl/GL11;glEnable(I)V", - ordinal = 1, - shift = At.Shift.AFTER), - slice = @Slice( - from = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL14;glBlendFuncSeparate(IIII)V"), - to = @At( - value = "INVOKE", - target = "Lxaero/map/mods/SupportXaeroMinimap;renderWaypoints(Lnet/minecraft/client/gui/GuiScreen;DDIIDDDDLjava/util/regex/Pattern;Ljava/util/regex/Pattern;FLxaero/map/mods/gui/Waypoint;Lnet/minecraft/client/Minecraft;Lnet/minecraft/client/gui/ScaledResolution;)Lxaero/map/mods/gui/Waypoint;"))) - private void visualprospecting$injectDraw(int scaledMouseX, int scaledMouseY, float partialTicks, CallbackInfo ci) { - for (LayerManager layerManager : MapState.instance.layers) { - if (layerManager.isLayerActive()) { - // +20s are to work around precision loss from casting to int and right-shifting - layerManager.recacheFullscreenMap( - (int) cameraX, - (int) cameraZ, - (int) (mc.displayWidth / scale) + 20, - (int) (mc.displayHeight / scale) + 20); - } - } - - for (LayerRenderer renderer : XaeroWorldMapState.instance.renderers) { - if (renderer.isLayerActive()) { - for (RenderStep step : renderer.getRenderSteps()) { - step.draw(this, cameraX, cameraZ, scale); - } - } - } - } - - // deobf method = drawScreen - @Inject( - method = "func_73863_a", - at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/GL11;glTranslated(DDD)V"), - slice = @Slice( - from = @At( - value = "FIELD", - // deobf target = - // "Lnet/minecraft/client/Minecraft;currentScreen:Lnet/minecraft/client/gui/GuiScreen;" - target = "Lnet/minecraft/client/Minecraft;field_71462_r:Lnet/minecraft/client/gui/GuiScreen;", - opcode = Opcodes.GETFIELD), - to = @At(value = "INVOKE", target = "Lxaero/map/gui/CursorBox;drawBox(IIII)V"))) - private void visualprospecting$injectDrawTooltip(int scaledMouseX, int scaledMouseY, float partialTicks, - CallbackInfo ci) { - for (LayerRenderer layer : XaeroWorldMapState.instance.renderers) { - if (layer instanceof InteractableLayerRenderer && layer.isLayerActive()) { - ((InteractableLayerRenderer) layer).drawTooltip(this, scale, screenScale); - } - } - } - - // deobf method = "initGui" - @Inject( - method = "func_73866_w_", - at = @At(value = "INVOKE", target = "Lorg/lwjgl/input/Keyboard;enableRepeatEvents(Z)V")) - private void visualprospecting$injectInitButtons(CallbackInfo ci) { - int numBtns = XaeroWorldMapState.instance.buttons.size(); - int totalHeight = numBtns * 20; - for (int i = 0; i < numBtns; i++) { - LayerButton layerButton = XaeroWorldMapState.instance.buttons.get(i); - SizedGuiTexturedButton button = new SizedGuiTexturedButton( - 0, - (height / 2 + totalHeight / 2) - 20 - 20 * i, - layerButton.textureLocation, - (btn) -> layerButton.toggle(), - new CursorBox(layerButton.getButtonTextKey())); - layerButton.setButton(button); - addGuiButton(button); - } - } - - @Inject(method = "onInputPress", at = @At("TAIL")) - private void visualprospecting$injectListenKeypress(boolean mouse, int code, CallbackInfoReturnable cir) { - if (Misc.inputMatchesKeyBinding(mouse, code, VP.keyAction)) { - for (LayerRenderer layer : XaeroWorldMapState.instance.renderers) { - if (layer instanceof InteractableLayerRenderer) { - ((InteractableLayerRenderer) layer).doActionKeyPress(); - } - } - } - } - - @Inject(method = "mapClicked", at = @At("TAIL")) - private void visualprospecting$injectListenClick(int button, int x, int y, CallbackInfo ci) { - if (button == 0) { - final long timestamp = System.currentTimeMillis(); - final boolean isDoubleClick = x == oldMouseX && y == oldMouseY && timestamp - timeLastClick < 500; - oldMouseX = x; - oldMouseY = y; - timeLastClick = isDoubleClick ? 0 : timestamp; - - if (isDoubleClick) { - for (LayerRenderer layer : XaeroWorldMapState.instance.renderers) { - if (layer instanceof InteractableLayerRenderer && layer.isLayerActive()) { - ((InteractableLayerRenderer) layer).doDoubleClick(); - } - } - } - } - } -} diff --git a/src/main/resources/assets/journeymap/icon/theme/Vault/icon/nodes.png b/src/main/resources/assets/journeymap/icon/theme/Vault/icon/nodes.png deleted file mode 100644 index dd9193dc641ce14fdaa008bcdde81a518c59ceec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5351 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 HZXf-Bk?4c+ diff --git a/src/main/resources/assets/journeymap/icon/theme/Victorian/icon/nodes.png b/src/main/resources/assets/journeymap/icon/theme/Victorian/icon/nodes.png deleted file mode 100644 index dd9193dc641ce14fdaa008bcdde81a518c59ceec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5351 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 HZXf-Bk?4c+ diff --git a/src/main/resources/assets/journeymap/icon/theme/Victorian/icon/oreveins.png b/src/main/resources/assets/journeymap/icon/theme/Victorian/icon/oreveins.png deleted file mode 100644 index 08cf2ea235c5a019f7f95cc4e751d1365633014e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5913 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 diff --git a/src/main/resources/assets/xaeroworldmap/textures/undergroundfluid.png b/src/main/resources/assets/xaeroworldmap/textures/undergroundfluid.png deleted file mode 100644 index 921c25952cd07f0b47557f04de95aed8c159da8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1009 zcmVEX>4Tx04R}tkv&MmKpe$iTcuJf4(%Y~kfC+5;1}X3RV;#q(pG5I!Q|2}Xws0R zxHt-~1qVMCs}3&Cx;nTDg5U>;o12rOir6bq^0;?_xa5{oJ2pKrR>z@Cd|nOw&!`4dR(i zQ{%i(9A;%vCO#(~)9Hf5k6f1=e&bxS*~>G-dNw^z93~b@T`YAmE9(mJG;u^$RLb|} z9F{q6aaO8z*1jiyVX&aCWVlXq1PLr5i4+7#sH1`^OvGqaNimS7{kV&N*!HK$C6TKF zMvev4pg^?!;D7MDTcbEN=_Cc?K<|rXeMABOF3@UN*7vbxwN3!vGjOGL{Iw=9`$>AE zqeYH@!ENB;x}!;Zz~v4w^rVTpXiGkt-eM7WKcjET1EE_Wu;%pE-pAn`u^>+bE}GwuF<0LOiD$u&-L!2kdPCrLy>R7i=nmQQHUVHm(ak9I-I1tot{ zN+L7TiZ#*NiHnq^B!?B3o#enpxyXTwgB=Jl%t0-bQ#x80zY_nZH4!`$T zzkU1u_T7H_?Wwo#^S;mXKA-3P|Ajh=dZnK6W&?GqQ|h>SZn0tQ305v0iw%5T0UOEM zm(-c}q(Wb=KCE;6lBh2;(>SG$*CTMddN%3LGl0IdNy_!kg@7)qf7I_;NQKYciuT&4 zQXN(=Bz;8vpf>0DjV0K#S|B~@WC}2-cBvDy_+L-Hz4L)Q&a6Sd`cM6(UM=YReokwq zc4r_1>M^xN{j1(ldkSLASg+i3rv3zu01d!5;B-Xnh=@nPe&7qx2Q(FCJ%>?ssYB}N z99yq?GwIU>af(L<^aHme;#Q8W5qOjIVf9pD_64w=!1gM(H4$+y=^ufXnqg`?upU@h zz9lMb9l&Ts(-8Amw`wDMmr7Rlr6ew=`bl8xLSfZp7jOeOqrL;40+Z_D#ei)F?gKA? zEx;vU5NNF{Og#$x21bB3U<^0`yao2u3Tp(`0ULl#745CS0B{X>6%iYO^T1cC@7x*E zkjef9a4^%>77=i6#)MMS(DWp&{o+x00000NkvXXu0mjf%G%){ From 32bc112ebedf24f1243c8cc04c856bcd93c4e6f9 Mon Sep 17 00:00:00 2001 From: Dream Master Date: Sat, 20 Jul 2024 20:13:02 +0700 Subject: [PATCH 057/132] update --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 915c91dd..6619dec1 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') api('com.github.GTNewHorizons:Navigator:1.0.6:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.78:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.92:dev') // For debugging runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.8.1:dev') From be71d9fb0b62b29683dafe6b88dd346670655fd0 Mon Sep 17 00:00:00 2001 From: querns <33518699+querns@users.noreply.github.com> Date: Tue, 30 Jul 2024 08:34:20 -0500 Subject: [PATCH 058/132] Implements shim for the GT5U ore vein database to serve VP's ore info (#51) --- dependencies.gradle | 2 +- .../sinthoras/visualprospecting/VPMod.java | 4 +++ .../integration/gregtech/VeinDatabase.java | 31 +++++++++++++++++++ .../resources/assets/gregtech/lang/en_US.lang | 22 ++++++------- .../assets/visualprospecting/lang/en_US.lang | 10 +++--- 5 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java diff --git a/dependencies.gradle b/dependencies.gradle index 6619dec1..787b8a24 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') api('com.github.GTNewHorizons:Navigator:1.0.6:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.92:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.117:dev') // For debugging runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.8.1:dev') diff --git a/src/main/java/com/sinthoras/visualprospecting/VPMod.java b/src/main/java/com/sinthoras/visualprospecting/VPMod.java index fc413c9d..89800b5e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VPMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/VPMod.java @@ -1,6 +1,7 @@ package com.sinthoras.visualprospecting; import com.sinthoras.visualprospecting.hooks.HooksShared; +import com.sinthoras.visualprospecting.integration.gregtech.VeinDatabase; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.SidedProxy; @@ -12,6 +13,7 @@ import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.event.FMLServerStoppedEvent; import cpw.mods.fml.common.event.FMLServerStoppingEvent; +import gregtech.crossmod.visualprospecting.GT_VisualProspecting_Database; @Mod( modid = Tags.MODID, @@ -44,6 +46,8 @@ public void fmlLifeCycleEvent(FMLInitializationEvent event) { // postInit "Handle interaction with other mods, complete your setup based on this." public void fmlLifeCycle(FMLPostInitializationEvent event) { VP.debug("postInit()"); + VP.debug("Registering with the GT5U ore vein database"); + GT_VisualProspecting_Database.registerDatabase(new VeinDatabase()); proxy.fmlLifeCycleEvent(event); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java new file mode 100644 index 00000000..000cd1de --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java @@ -0,0 +1,31 @@ +package com.sinthoras.visualprospecting.integration.gregtech; + +import java.util.Optional; + +import net.minecraft.world.ChunkCoordIntPair; + +import com.sinthoras.visualprospecting.ServerTranslations; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.database.ServerCache; +import com.sinthoras.visualprospecting.database.veintypes.VeinType; + +import gregtech.crossmod.visualprospecting.IDatabase; + +public class VeinDatabase implements IDatabase { + + @Override + public Optional getVeinName(int dimensionId, ChunkCoordIntPair coordinates) { + OreVeinPosition oreVein = ServerCache.instance + .getOreVein(dimensionId, coordinates.chunkXPos, coordinates.chunkZPos); + if (oreVein != null && oreVein.veinType != VeinType.NO_VEIN) { + // Unfortunately, there's not a very good way to localize this. This method is used to drive information + // in the Metrics Transmitter cover in GT5U, which operates entirely server-side. At best, we could try to + // capture which language the original cover attaching player is using, maybe. (I think this requires + // reflection, of course. Why should things be easy?) Even then, it wouldn't help in a multiplayer scenario + // with users having different locales. + return Optional.of(ServerTranslations.getEnglishLocalization(oreVein.veinType)); + } else { + return Optional.empty(); + } + } +} diff --git a/src/main/resources/assets/gregtech/lang/en_US.lang b/src/main/resources/assets/gregtech/lang/en_US.lang index 0d8c5d05..e5d7608e 100644 --- a/src/main/resources/assets/gregtech/lang/en_US.lang +++ b/src/main/resources/assets/gregtech/lang/en_US.lang @@ -37,8 +37,8 @@ ore.mix.terraaer=Terra and Aer ore.mix.perditioordo=Perdito and Ordo ore.mix.coppertin=Vermiculite ore.mix.titaniumchrome=Ilmenite -ore.mix.mineralsand=Mineralsand -ore.mix.garnettin=Garnettin +ore.mix.mineralsand=Mineral Sands +ore.mix.garnettin=Garnet/Tin ore.mix.kaolinitezeolite=Kaolinite ore.mix.mica=Mica ore.mix.dolomite=Dolomite @@ -59,7 +59,7 @@ ore.mix.niobium=Niobium ore.mix.tungstenirons=Tungsten ore.mix.uraniumgtnh=Thorium ore.mix.vanadiumgold=Vanadium -ore.mix.netherstar=NetherStar +ore.mix.netherstar=Nether Star ore.mix.garnet=Garnet ore.mix.rareearth=Rare Earths ore.mix.richnuclear=Plutonium @@ -72,23 +72,23 @@ ore.mix.rutile=Rutile ore.mix.tfgalena=Cryolite ore.mix.luvtantalite=Pyrolusite -ore.mix.ross128.Thorianit=Thorianit +ore.mix.ross128.Thorianit=Thorianite ore.mix.ross128.carbon=Graphite ore.mix.ross128.bismuth=Bismuth -ore.mix.ross128.TurmalinAlkali=Olenit -ore.mix.ross128.Roquesit=Roquesit +ore.mix.ross128.TurmalinAlkali=Olenite +ore.mix.ross128.Roquesit=Roquesite ore.mix.ross128.Tungstate=Scheelite -ore.mix.ross128.CopperSulfits=Djurleit -ore.mix.ross128.Forsterit=Forsterit -ore.mix.ross128.Hedenbergit=Hedenbergit +ore.mix.ross128.CopperSulfits=Djurleite +ore.mix.ross128.Forsterit=Forsterite +ore.mix.ross128.Hedenbergit=Hedenbergite ore.mix.ross128.RedZircon=Red Zircon ore.mix.ross128ba.tib=Tiberium ore.mix.ross128ba.Tungstate=Scheelite ore.mix.ross128ba.bart=BArTiMaEuSNeK -ore.mix.ross128ba.TurmalinAlkali=Olenit +ore.mix.ross128ba.TurmalinAlkali=Olenite ore.mix.ross128ba.Amethyst=Amethyst -ore.mix.ross128ba.CopperSulfits=Djurleit +ore.mix.ross128ba.CopperSulfits=Djurleite ore.mix.ross128ba.RedZircon=Red Zircon ore.mix.ross128ba.Fluorspar=Fluorspar diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index cd96c795..f3634db9 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -13,7 +13,7 @@ visualprospecting.resetprogress.title=Delete VisualProspecting Progress visualprospecting.resetprogress.confirm=Yes, i am sure! visualprospecting.resetprogress.cancel=Cancel visualprospecting.resetprogress.prompt=Delete player progress on ore veins and underground fluids? -visualprospecting.resetprogress.command=Deletes all your progress on ore veins and undergrond fluids +visualprospecting.resetprogress.command=Deletes all your progress on ore veins and underground fluids visualprospecting.resetprogress.confirmation=Progress deleted! visualprospecting.redoservercache.command=Redo the GT vein cache on the server visualprospecting.redoservercache.start=Start redoing the GT vein cache on the server @@ -36,16 +36,16 @@ item.visualprospecting.prospectorslog.author=Author: %s item.visualprospecting.prospectorslog.empty=Use item to fill it. item.visualprospecting.prospectorslog.creation.begin=A Prospector's Log has been written. item.visualprospecting.prospectorslog.creation.fail0=[Failed]: Damn! I spilled coffee over it... -item.visualprospecting.prospectorslog.creation.fail1=[Failed]: It seem's that you cannot read your own words... +item.visualprospecting.prospectorslog.creation.fail1=[Failed]: It seems that you cannot read your own words... item.visualprospecting.prospectorslog.creation.fail2=[Failed]: Why did I write that in eldritch? I cannot read eldritch! -item.visualprospecting.prospectorslog.creation.fail3=[Failed]: Where did I put my glasses? I can't write without! +item.visualprospecting.prospectorslog.creation.fail3=[Failed]: Where did I put my glasses? I can't write without them! item.visualprospecting.prospectorslog.creation.fail4=[Failed]: Herobrine stole my notes! item.visualprospecting.prospectorslog.reading.fail0=[Failed]: It smells like good coffee, but i cannot read it! item.visualprospecting.prospectorslog.reading.fail1=[Failed]: I need to improve my Russian before I can read that! item.visualprospecting.prospectorslog.reading.fail2=[Failed]: What?!? That was empty? -item.visualprospecting.prospectorslog.reading.fail3=[Failed]: Yeah..No. I can't decipher that! +item.visualprospecting.prospectorslog.reading.fail3=[Failed]: Yeah... No. I can't decipher that! item.visualprospecting.prospectorslog.reading.fail4=[Failed]: Do I have a Ph.D. in Geography? NOPE! -item.visualprospecting.prospectorslog.reading.begin=Those are quite some pages. It might take some time to fully read it. +item.visualprospecting.prospectorslog.reading.begin=That's quite a lot of pages. It might take some time to fully read it. item.visualprospecting.prospectorslog.reading.end=I finished the Prospector's Log of %s visualprospecting.node.deletehint=Mark depleted with %s visualprospecting.tracked=Tracked: %s From a2cd53d4f843dbbd3f1df0216ac4e1d9a35f6300 Mon Sep 17 00:00:00 2001 From: Dream Master Date: Tue, 30 Jul 2024 19:43:27 +0700 Subject: [PATCH 059/132] update (cherry picked from commit 36602ce9e311b6f0b8a372fa20a6f2344b81beb2) --- gradle.properties | 13 ++++++++++++- gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 43504 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 5 ++++- gradlew.bat | 2 ++ settings.gradle | 2 +- 6 files changed, 20 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index b38f6bcf..4c38eda4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -85,6 +85,11 @@ accessTransformersFile = # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! usesMixins = true +# 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 = true @@ -117,9 +122,15 @@ minimizeShadowedDependencies = true # If disabled, won't rename the shadowed classes. relocateShadowedDependencies = true -# Adds the GTNH maven, CurseMaven, Modrinth, and some more well-known 1.7.10 repositories. +# 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. diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e6441136f3d4ba8a0da8d277868979cfbc8ad796..2c3521197d7c4586c843d1d3e9090525f1898cde 100644 GIT binary patch delta 8703 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 Ojj7^59?Sdh$^Qpp*~F>< delta 8662 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a4413138..09523c0e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index b740cf13..f5feea6d 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +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 diff --git a/gradlew.bat b/gradlew.bat index 25da30db..9d21a218 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @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 @rem ########################################################################## diff --git a/settings.gradle b/settings.gradle index 6fe010ce..54797868 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.23' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.25' } From c62fcb9726fc8216b1383ec0c419548d8a7e855f Mon Sep 17 00:00:00 2001 From: NotAPenguin Date: Tue, 3 Sep 2024 19:18:55 +0200 Subject: [PATCH 060/132] bump gt, fix rename (#53) * bump gt, fix rename * update deps * remove detrav dep --------- Co-authored-by: boubou19 --- dependencies.gradle | 4 +--- .../sinthoras/visualprospecting/Utils.java | 4 ++-- .../sinthoras/visualprospecting/VPMod.java | 4 ++-- .../database/ClientCache.java | 6 ++--- .../BartworksOreMaterialProvider.java | 5 ++-- .../database/veintypes/VeinType.java | 4 ++-- .../database/veintypes/VeinTypeCaching.java | 14 +++++------ .../visualprospecting/hooks/HooksShared.java | 4 ++-- .../gregtech/UndergroundFluidsWrapper.java | 24 +++++++++---------- .../voxelmap/VoxelMapEventHandler.java | 4 ++-- .../item/ProspectorsLog.java | 4 ++-- .../bartworks/WorldGenContainerMixin.java | 11 +++++---- .../GT_Worldgenerator_SpaceMixin.java | 10 ++++---- .../gregtech/GT_Block_Ores_AbstractMixin.java | 8 +++---- ...aTileEntity_AdvSeismicProspectorMixin.java | 22 ++++++++--------- .../GT_MetaTileEntity_ScannerMixin.java | 18 +++++++------- .../late/gregtech/WorldGenContainerMixin.java | 12 +++++----- .../network/ProspectingRequest.java | 10 ++++---- 18 files changed, 83 insertions(+), 85 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 787b8a24..9ceeb6a7 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,10 +2,8 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') api('com.github.GTNewHorizons:Navigator:1.0.6:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.48.117:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.57:dev') - // For debugging - runtimeOnlyNonPublishable('com.github.GTNewHorizons:DetravScannerMod:1.8.1:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.5')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 978a7fb4..2f7c3c48 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -25,7 +25,7 @@ import com.sinthoras.visualprospecting.hooks.HooksClient; import cpw.mods.fml.common.Loader; -import gregtech.common.GT_Worldgenerator; +import gregtech.common.GTWorldgenerator; public class Utils { @@ -70,7 +70,7 @@ public static long chunkCoordsToKey(int chunkX, int chunkZ) { } public static int mapToCenterOreChunkCoord(final int chunkCoord) { - if (GT_Worldgenerator.oregenPattern == GT_Worldgenerator.OregenPattern.EQUAL_SPACING) { + if (GTWorldgenerator.oregenPattern == GTWorldgenerator.OregenPattern.EQUAL_SPACING) { // new evenly spaced ore pattern return chunkCoord - Math.floorMod(chunkCoord, 3) + 1; } else { diff --git a/src/main/java/com/sinthoras/visualprospecting/VPMod.java b/src/main/java/com/sinthoras/visualprospecting/VPMod.java index 89800b5e..d8eec694 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VPMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/VPMod.java @@ -13,7 +13,7 @@ import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.event.FMLServerStoppedEvent; import cpw.mods.fml.common.event.FMLServerStoppingEvent; -import gregtech.crossmod.visualprospecting.GT_VisualProspecting_Database; +import gregtech.crossmod.visualprospecting.VisualProspectingDatabase; @Mod( modid = Tags.MODID, @@ -47,7 +47,7 @@ public void fmlLifeCycleEvent(FMLInitializationEvent event) { public void fmlLifeCycle(FMLPostInitializationEvent event) { VP.debug("postInit()"); VP.debug("Registering with the GT5U ore vein database"); - GT_VisualProspecting_Database.registerDatabase(new VeinDatabase()); + VisualProspectingDatabase.registerDatabase(new VeinDatabase()); proxy.fmlLifeCycleEvent(event); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index ce623c81..5cd231f2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -22,7 +22,7 @@ import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; import com.sinthoras.visualprospecting.network.ProspectingRequest; -import gregtech.common.blocks.GT_TileEntity_Ores; +import gregtech.common.blocks.TileEntityOres; public class ClientCache extends WorldCache { @@ -130,8 +130,8 @@ public void putUndergroundFluids(List undergroundFluid public void onOreInteracted(World world, int blockX, int blockY, int blockZ, EntityPlayer entityPlayer) { if (world.isRemote && Config.enableProspecting && Minecraft.getMinecraft().thePlayer == entityPlayer) { final TileEntity tTileEntity = world.getTileEntity(blockX, blockY, blockZ); - if (tTileEntity instanceof GT_TileEntity_Ores) { - final short oreMetaData = ((GT_TileEntity_Ores) tTileEntity).mMetaData; + if (tTileEntity instanceof TileEntityOres) { + final short oreMetaData = ((TileEntityOres) tTileEntity).mMetaData; if (Utils.isSmallOreId(oreMetaData) == false && oreMetaData != 0) { final int chunkX = Utils.coordBlockToChunk(blockX); final int chunkZ = Utils.coordBlockToChunk(blockZ); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java index 54161298..c0da6ed2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java @@ -1,11 +1,10 @@ package com.sinthoras.visualprospecting.database.veintypes; -import static com.github.bartimaeusnek.bartworks.util.BW_ColorUtil.getColorFromRGBArray; +import static bartworks.util.BWColorUtil.getColorFromRGBArray; import net.minecraft.util.IIcon; -import com.github.bartimaeusnek.bartworks.system.material.Werkstoff; - +import bartworks.system.material.Werkstoff; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.enums.OrePrefixes; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index a6a1bced..1f3a3da1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -10,7 +10,7 @@ import com.sinthoras.visualprospecting.Tags; -import gregtech.api.GregTech_API; +import gregtech.api.GregTechAPI; public class VeinType { @@ -83,7 +83,7 @@ public boolean containsOre(short oreMetaData) { } public List getOreMaterialNames() { - return oresAsSet.stream().map(metaData -> GregTech_API.sGeneratedMaterials[metaData]).filter(Objects::nonNull) + return oresAsSet.stream().map(metaData -> GregTechAPI.sGeneratedMaterials[metaData]).filter(Objects::nonNull) .map(material -> EnumChatFormatting.GRAY + material.mLocalizedName).collect(Collectors.toList()); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index 072d6fc6..afdf346c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -15,18 +15,18 @@ import net.minecraft.client.resources.I18n; import net.minecraft.util.EnumChatFormatting; -import com.github.bartimaeusnek.bartworks.system.material.Werkstoff; -import com.github.bartimaeusnek.bartworks.system.oregen.BW_OreLayer; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; +import bartworks.system.material.Werkstoff; +import bartworks.system.oregen.BWOreLayer; import codechicken.nei.NEIClientConfig; import codechicken.nei.SearchField; -import gregtech.api.GregTech_API; +import gregtech.api.GregTechAPI; import gregtech.api.enums.Materials; -import gregtech.common.GT_Worldgen_GT_Ore_Layer; +import gregtech.common.WorldgenGTOreLayer; public class VeinTypeCaching implements Runnable { @@ -47,7 +47,7 @@ public void run() { largeVeinOres = new HashSet<>(); veinTypes.add(VeinType.NO_VEIN); - for (GT_Worldgen_GT_Ore_Layer vein : GT_Worldgen_GT_Ore_Layer.sList) { + for (WorldgenGTOreLayer vein : WorldgenGTOreLayer.sList) { if (vein.mWorldGenName.equals(Tags.ORE_MIX_NONE_NAME)) { break; } @@ -69,7 +69,7 @@ public void run() { } if (isBartworksInstalled()) { - for (BW_OreLayer vein : BW_OreLayer.sList) { + for (BWOreLayer vein : BWOreLayer.sList) { final IOreMaterialProvider oreMaterialProvider = (vein.bwOres & 0b1000) == 0 ? new GregTechOreMaterialProvider(getGregTechMaterial((short) vein.mPrimaryMeta)) : new BartworksOreMaterialProvider(Werkstoff.werkstoffHashMap.get((short) vein.mPrimaryMeta)); @@ -126,7 +126,7 @@ public void run() { } private Materials getGregTechMaterial(short metaId) { - final Materials material = GregTech_API.sGeneratedMaterials[metaId]; + final Materials material = GregTechAPI.sGeneratedMaterials[metaId]; if (material == null) { // Some materials are not registered in dev when their usage mod is not available. return Materials.getAll().stream().filter(m -> m.mMetaItemSubID == metaId).findAny().get(); diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index f3765b59..01554725 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -33,7 +33,7 @@ import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.Side; -import gregtech.api.GregTech_API; +import gregtech.api.GregTechAPI; public class HooksShared { @@ -79,7 +79,7 @@ public void fmlLifeCycleEvent(FMLInitializationEvent event) { // postInit "Handle interaction with other mods, complete your setup based on this." public void fmlLifeCycleEvent(FMLPostInitializationEvent event) { - GregTech_API.sAfterGTPostload.add(new VeinTypeCaching()); + GregTechAPI.sAfterGTPostload.add(new VeinTypeCaching()); } public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) {} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java index 8c914bb5..4389a636 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java @@ -1,9 +1,9 @@ package com.sinthoras.visualprospecting.integration.gregtech; import static gregtech.api.objects.XSTR.XSTR_INSTANCE; -import static gregtech.common.GT_Proxy.*; -import static gregtech.common.GT_Proxy.GTOIL; -import static gregtech.common.GT_UndergroundOil.undergroundOil; +import static gregtech.common.GTProxy.*; +import static gregtech.common.GTProxy.GTOIL; +import static gregtech.common.UndergroundOil.undergroundOil; import java.util.HashMap; import java.util.Map; @@ -13,11 +13,11 @@ import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; -import gregtech.GT_Mod; -import gregtech.api.objects.GT_UO_Dimension; -import gregtech.api.objects.GT_UO_Fluid; +import gregtech.GTMod; +import gregtech.api.objects.GTUODimension; +import gregtech.api.objects.GTUOFluid; import gregtech.api.objects.XSTR; -import gregtech.common.GT_UndergroundOil; +import gregtech.common.UndergroundOil; public class UndergroundFluidsWrapper { @@ -27,7 +27,7 @@ public class UndergroundFluidsWrapper { static { boolean foundMethod; try { - GT_UndergroundOil.class.getDeclaredMethod("undergroundOil", World.class, int.class, int.class, float.class); + UndergroundOil.class.getDeclaredMethod("undergroundOil", World.class, int.class, int.class, float.class); foundMethod = true; } catch (NoSuchMethodException e) { foundMethod = false; @@ -49,7 +49,7 @@ public static FluidStack prospectFluid(World world, int chunkX, int chunkZ) { private static FluidStack vanillaProspectFluid(World world, int chunkX, int chunkZ) { final ChunkCoordIntPair chunkCoordinate = new ChunkCoordIntPair(chunkX, chunkZ); int dimensionId = world.provider.dimensionId; - GT_UO_Dimension dimension = GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId); + GTUODimension dimension = GTMod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId); if (dimension == null) { return null; } @@ -67,7 +67,7 @@ private static FluidStack vanillaProspectFluid(World world, int chunkX, int chun final XSTR tRandom = new XSTR(world.getSeed() + dimensionId * 2L + (chunkX >> 3) + 8267L * (chunkZ >> 3)); - GT_UO_Fluid uoFluid = dimension.getRandomFluid(tRandom); + GTUOFluid uoFluid = dimension.getRandomFluid(tRandom); FluidStack fluidInChunk; @@ -92,11 +92,11 @@ private static FluidStack vanillaProspectFluid(World world, int chunkX, int chun tInts[GTOILFLUID] = fluidInChunk.getFluidID(); } - if (fluidInChunk.amount <= GT_UndergroundOil.DIVIDER) { + if (fluidInChunk.amount <= UndergroundOil.DIVIDER) { fluidInChunk.amount = 0; // return informative stack tInts[GTOIL] = 0; // so in next access it will stop way above } else { - fluidInChunk.amount = fluidInChunk.amount / GT_UndergroundOil.DIVIDER; // give moderate extraction speed + fluidInChunk.amount = fluidInChunk.amount / UndergroundOil.DIVIDER; // give moderate extraction speed } chunkData.put(chunkCoordinate, tInts); // update hash map diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java index aaf8d451..d11012d7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java @@ -15,7 +15,7 @@ import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import gregtech.api.GregTech_API; +import gregtech.api.GregTechAPI; public class VoxelMapEventHandler { @@ -26,7 +26,7 @@ public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { } OreVeinPosition pos = event.getPosition(); - short[] color = GregTech_API.sGeneratedMaterials[pos.veinType.primaryOreMeta].getRGBA(); + short[] color = GregTechAPI.sGeneratedMaterials[pos.veinType.primaryOreMeta].getRGBA(); TreeSet dim = new TreeSet<>(); dim.add(pos.dimensionId); VoxelMapWaypointManager.addVoxelMapWaypoint( diff --git a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java index bcedac0b..0e5be148 100644 --- a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java +++ b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java @@ -20,7 +20,7 @@ import com.sinthoras.visualprospecting.task.SnapshotUploadTask; import com.sinthoras.visualprospecting.task.TaskManager; -import gregtech.api.GregTech_API; +import gregtech.api.GregTechAPI; public class ProspectorsLog extends Item { @@ -29,7 +29,7 @@ public class ProspectorsLog extends Item { public ProspectorsLog() { maxStackSize = 1; setUnlocalizedName("visualprospecting.prospectorslog"); - setCreativeTab(GregTech_API.TAB_GREGTECH); + setCreativeTab(GregTechAPI.TAB_GREGTECH); setTextureName(Tags.MODID + ":prospectorslog"); } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java index 3ede076e..3825f097 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java @@ -9,22 +9,23 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import com.github.bartimaeusnek.bartworks.system.oregen.BW_OreLayer; -import com.github.bartimaeusnek.bartworks.system.oregen.BW_WordGenerator; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.ServerCache; -@Mixin(BW_WordGenerator.WorldGenContainer.class) +import bartworks.system.oregen.BWOreLayer; +import bartworks.system.oregen.BWWordGenerator; + +@Mixin(BWWordGenerator.WorldGenContainer.class) public class WorldGenContainerMixin { @Redirect( method = "run", at = @At( value = "INVOKE", - target = "Lcom/github/bartimaeusnek/bartworks/system/oregen/BW_OreLayer;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), + target = "Lbartworks/system/oregen/BWOreLayer;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), remap = false, require = 1) - private boolean visualprospecting$onOreVeinGenerationAttempt(BW_OreLayer worldGen, World world, Random random, + private boolean visualprospecting$onOreVeinGenerationAttempt(BWOreLayer worldGen, World world, Random random, String biome, int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { final boolean oreVeinPlaced = worldGen.executeWorldgen( diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java index d8411bf2..cde0c420 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java @@ -12,20 +12,20 @@ import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.ServerCache; -import bloodasp.galacticgreg.GT_Worldgenerator_Space; -import gregtech.api.world.GT_Worldgen; +import galacticgreg.WorldGeneratorSpace; +import gregtech.api.world.GTWorldgen; -@Mixin(GT_Worldgenerator_Space.class) +@Mixin(WorldGeneratorSpace.class) public class GT_Worldgenerator_SpaceMixin { @Redirect( method = "Generate_OreVeins", at = @At( value = "INVOKE", - target = "Lgregtech/api/world/GT_Worldgen;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), + target = "Lgregtech/api/world/GTWorldgen;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), remap = false, require = 1) - private boolean visualprospecting$onOreVeinGenerated(GT_Worldgen worldGen, World world, Random random, String biome, + private boolean visualprospecting$onOreVeinGenerated(GTWorldgen worldGen, World world, Random random, String biome, int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { final boolean oreVeinPlaced = worldGen.executeWorldgen( world, diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java index 87e982b3..801ad7e8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java @@ -7,11 +7,11 @@ import com.sinthoras.visualprospecting.database.ClientCache; -import gregtech.api.items.GT_Generic_Block; -import gregtech.common.blocks.GT_Block_Ores_Abstract; +import gregtech.api.items.GTGenericBlock; +import gregtech.common.blocks.BlockOresAbstract; -@Mixin(value = GT_Block_Ores_Abstract.class, remap = false) -public class GT_Block_Ores_AbstractMixin extends GT_Generic_Block { +@Mixin(value = BlockOresAbstract.class, remap = false) +public class GT_Block_Ores_AbstractMixin extends GTGenericBlock { protected GT_Block_Ores_AbstractMixin() { super(null, null, null); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java index f27e6ba3..01701eae 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java @@ -1,7 +1,7 @@ package com.sinthoras.visualprospecting.mixins.late.gregtech; -import static gregtech.api.util.GT_Utility.ItemNBT.getNBT; -import static gregtech.api.util.GT_Utility.ItemNBT.setNBT; +import static gregtech.api.util.GTUtility.ItemNBT.getNBT; +import static gregtech.api.util.GTUtility.ItemNBT.setNBT; import java.util.List; @@ -25,13 +25,13 @@ import gregtech.api.enums.ItemList; import gregtech.api.enums.Materials; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; -import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine; -import gregtech.api.util.GT_Utility; -import gregtech.common.tileentities.machines.basic.GT_MetaTileEntity_AdvSeismicProspector; +import gregtech.api.metatileentity.implementations.MTEBasicMachine; +import gregtech.api.util.GTUtility; +import gregtech.common.tileentities.machines.basic.MTEAdvSeismicProspector; import ic2.core.Ic2Items; -@Mixin(value = GT_MetaTileEntity_AdvSeismicProspector.class, remap = false) -public abstract class GT_MetaTileEntity_AdvSeismicProspectorMixin extends GT_MetaTileEntity_BasicMachine { +@Mixin(value = MTEAdvSeismicProspector.class, remap = false) +public abstract class GT_MetaTileEntity_AdvSeismicProspectorMixin extends MTEBasicMachine { @Shadow(remap = false) boolean ready = false; @@ -53,10 +53,10 @@ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlaye if (aBaseMetaTileEntity.isServerSide()) { ItemStack aStack = aPlayer.getCurrentEquippedItem(); - if (!ready && (GT_Utility.consumeItems(aPlayer, aStack, Item.getItemFromBlock(Blocks.tnt), 16) - || GT_Utility.consumeItems(aPlayer, aStack, Ic2Items.industrialTnt.getItem(), 8) - || GT_Utility.consumeItems(aPlayer, aStack, Materials.Glyceryl, 4) - || GT_Utility.consumeItems(aPlayer, aStack, ItemList.Block_Powderbarrel.getItem(), 2))) { + if (!ready && (GTUtility.consumeItems(aPlayer, aStack, Item.getItemFromBlock(Blocks.tnt), 16) + || GTUtility.consumeItems(aPlayer, aStack, Ic2Items.industrialTnt.getItem(), 8) + || GTUtility.consumeItems(aPlayer, aStack, Materials.Glyceryl, 4) + || GTUtility.consumeItems(aPlayer, aStack, ItemList.Block_Powderbarrel.getItem(), 2))) { this.ready = true; this.mMaxProgresstime = (aPlayer.capabilities.isCreativeMode ? 20 : 800); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java index 124fe393..1ea1c2e0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java @@ -1,6 +1,6 @@ package com.sinthoras.visualprospecting.mixins.late.gregtech; -import static gregtech.api.util.GT_Utility.ItemNBT.setNBT; +import static gregtech.api.util.GTUtility.ItemNBT.setNBT; import java.util.List; @@ -19,12 +19,12 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; -import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine; -import gregtech.api.util.GT_Utility; -import gregtech.common.tileentities.machines.basic.GT_MetaTileEntity_Scanner; +import gregtech.api.metatileentity.implementations.MTEBasicMachine; +import gregtech.api.util.GTUtility; +import gregtech.common.tileentities.machines.basic.MTEScanner; -@Mixin(value = GT_MetaTileEntity_Scanner.class, remap = false) -public abstract class GT_MetaTileEntity_ScannerMixin extends GT_MetaTileEntity_BasicMachine { +@Mixin(value = MTEScanner.class, remap = false) +public abstract class GT_MetaTileEntity_ScannerMixin extends MTEBasicMachine { public GT_MetaTileEntity_ScannerMixin() { super(0, "", "", 0, 0, "", 0, 0); @@ -34,7 +34,7 @@ public GT_MetaTileEntity_ScannerMixin() { method = "checkRecipe", at = @At( value = "INVOKE", - target = "Lgregtech/api/util/GT_Utility$ItemNBT;convertProspectionData(Lnet/minecraft/item/ItemStack;)V"), + target = "Lgregtech/api/util/GTUtility$ItemNBT;convertProspectionData(Lnet/minecraft/item/ItemStack;)V"), remap = false, require = 1, cancellable = true) @@ -90,7 +90,7 @@ public GT_MetaTileEntity_ScannerMixin() { } if (compound.hasKey(Tags.PROSPECTION_FLUIDS)) { - GT_Utility.ItemNBT.fillBookWithList( + GTUtility.ItemNBT.fillBookWithList( bookPages, "Fluids%s\n\n", "\n", @@ -154,7 +154,7 @@ public GT_MetaTileEntity_ScannerMixin() { // Mimic original behaviour itemStack.stackSize -= 1; - mOutputItems[0] = GT_Utility.copyAmount(1L, itemStack); + mOutputItems[0] = GTUtility.copyAmount(1L, itemStack); calculateOverclockedNess(30, 1000); // In case recipe is too OP for that machine if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java index 68925442..4898492d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java @@ -12,10 +12,10 @@ import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.ServerCache; -import gregtech.common.GT_Worldgen_GT_Ore_Layer; -import gregtech.common.GT_Worldgenerator; +import gregtech.common.GTWorldgenerator; +import gregtech.common.WorldgenGTOreLayer; -@Mixin(GT_Worldgenerator.WorldGenContainer.class) +@Mixin(GTWorldgenerator.WorldGenContainer.class) public class WorldGenContainerMixin { // Redirect both calls to ensure that Bartworks ore veins are captured as well @@ -23,10 +23,10 @@ public class WorldGenContainerMixin { method = "worldGenFindVein", at = @At( value = "INVOKE", - target = "Lgregtech/common/GT_Worldgen_GT_Ore_Layer;executeWorldgenChunkified(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIIIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)I"), + target = "Lgregtech/common/WorldgenGTOreLayer;executeWorldgenChunkified(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIIIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)I"), remap = false, require = 2) - protected int visualprospecting$onOreVeinPlaced(GT_Worldgen_GT_Ore_Layer instance, World aWorld, Random aRandom, + protected int visualprospecting$onOreVeinPlaced(WorldgenGTOreLayer instance, World aWorld, Random aRandom, String aBiome, int aDimensionType, int aChunkX, int aChunkZ, int aSeedX, int aSeedZ, IChunkProvider aChunkGenerator, IChunkProvider aChunkProvider) { final int result = instance.executeWorldgenChunkified( @@ -40,7 +40,7 @@ public class WorldGenContainerMixin { aSeedZ, aChunkGenerator, aChunkProvider); - if (result == GT_Worldgen_GT_Ore_Layer.ORE_PLACED && !instance.mWorldGenName.equals("NoOresInVein")) { + if (result == WorldgenGTOreLayer.ORE_PLACED && !instance.mWorldGenName.equals("NoOresInVein")) { ServerCache.instance.notifyOreVeinGeneration( aWorld.provider.dimensionId, Utils.coordBlockToChunk(aSeedX), diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java index a1df4df8..4ed5789e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java @@ -19,8 +19,8 @@ import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; -import gregtech.common.blocks.GT_Block_Ores_Abstract; -import gregtech.common.blocks.GT_TileEntity_Ores; +import gregtech.common.blocks.BlockOresAbstract; +import gregtech.common.blocks.TileEntityOres; import io.netty.buffer.ByteBuf; public class ProspectingRequest implements IMessage { @@ -93,10 +93,10 @@ public IMessage onMessage(ProspectingRequest message, MessageContext ctx) { && timestamp - lastRequest >= Config.minDelayBetweenVeinRequests && isChunkLoaded) { final Block block = world.getBlock(message.blockX, message.blockY, message.blockZ); - if (block instanceof GT_Block_Ores_Abstract) { + if (block instanceof BlockOresAbstract) { final TileEntity tileEntity = world.getTileEntity(message.blockX, message.blockY, message.blockZ); - if (tileEntity instanceof GT_TileEntity_Ores) { - final short metaData = ((GT_TileEntity_Ores) tileEntity).mMetaData; + if (tileEntity instanceof TileEntityOres) { + final short metaData = ((TileEntityOres) tileEntity).mMetaData; if (isSmallOreId(metaData) == false && oreIdToMaterialId(metaData) == message.foundOreMetaData) { lastRequestPerPlayer.put(uuid, timestamp); From 091ddddf851102add49dd8f995db7ee74676c766 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Tue, 3 Sep 2024 22:46:42 +0200 Subject: [PATCH 061/132] update --- dependencies.gradle | 2 +- settings.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 9ceeb6a7..d2eac2ec 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -2,7 +2,7 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') api('com.github.GTNewHorizons:Navigator:1.0.6:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.57:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.60:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.5')) diff --git a/settings.gradle b/settings.gradle index 54797868..3d3ba12c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.25' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.27' } From bae9fb8626ec1b052bc4fc033eca655478284f17 Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Sat, 7 Sep 2024 05:37:50 +0200 Subject: [PATCH 062/132] Convert to universal Navigator layers (#52) * convert all layers to universal * update deps --- dependencies.gradle | 5 +- .../journeymap/drawsteps/OreVeinDrawStep.java | 142 --------------- .../UndergroundFluidChunkDrawStep.java | 90 --------- .../drawsteps/UndergroundFluidDrawStep.java | 86 --------- .../journeymap/render/JMOreVeinRenderer.java | 26 --- .../JMUndergroundFluidChunkRenderer.java | 26 --- .../render/JMUndergroundFluidRenderer.java | 26 --- .../model/layers/OreVeinLayerManager.java | 76 ++------ .../UndergroundFluidChunkLayerManager.java | 97 ++-------- .../layers/UndergroundFluidLayerManager.java | 82 ++------- .../UndergroundFluidChunkLocation.java | 39 ++-- .../locations/UndergroundFluidLocation.java | 8 +- .../model/render/OreVeinRenderStep.java | 93 ++++++++++ .../UndergroundFluidChunkRenderStep.java | 38 ++++ .../render/UndergroundFluidRenderStep.java | 43 +++++ .../xaerominimap/OreVeinWaypointManager.java | 17 -- .../renderers/XaeroOreVeinRenderer.java | 25 --- .../XaeroUndergroundFluidChunkRenderer.java | 26 --- .../XaeroUndergroundFluidRenderer.java | 25 --- .../rendersteps/OreVeinRenderStep.java | 172 ------------------ .../UndergroundFluidChunkRenderStep.java | 65 ------- .../UndergroundFluidRenderStep.java | 59 ------ 22 files changed, 251 insertions(+), 1015 deletions(-) delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMOreVeinRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidChunkRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidRenderer.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidChunkRenderStep.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/OreVeinWaypointManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroOreVeinRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidChunkRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidRenderer.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java diff --git a/dependencies.gradle b/dependencies.gradle index d2eac2ec..806cf42d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,9 +1,8 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:Navigator:1.0.6:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.60:dev') + api('com.github.GTNewHorizons:Navigator:1.0.10:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.64:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.5')) - } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java deleted file mode 100644 index 8e4898f8..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/OreVeinDrawStep.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; - -import java.awt.geom.Point2D; -import java.util.List; - -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.init.Blocks; -import net.minecraft.util.IIcon; -import net.minecraft.util.ResourceLocation; - -import com.gtnewhorizons.navigator.api.journeymap.drawsteps.JMInteractableStep; -import com.gtnewhorizons.navigator.api.model.locations.IWaypointAndLocationProvider; -import com.gtnewhorizons.navigator.api.util.DrawUtils; -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; - -import journeymap.client.render.draw.DrawUtil; -import journeymap.client.render.map.GridRenderer; - -public class OreVeinDrawStep implements JMInteractableStep { - - private static final ResourceLocation depletedTextureLocation = new ResourceLocation( - Tags.MODID, - "textures/depleted.png"); - - private final OreVeinLocation oreVeinLocation; - - private double iconX; - private double iconY; - private double iconSize; - - public OreVeinDrawStep(OreVeinLocation oreVeinLocation) { - this.oreVeinLocation = oreVeinLocation; - } - - @Override - public void getTooltip(List tooltip) { - if (oreVeinLocation.isDepleted()) { - tooltip.add(oreVeinLocation.getDepletedHint()); - } - if (oreVeinLocation.isActiveAsWaypoint()) { - tooltip.add(oreVeinLocation.getActiveWaypointHint()); - } - tooltip.add(oreVeinLocation.getName()); - if (!oreVeinLocation.isDepleted()) { - tooltip.addAll(oreVeinLocation.getMaterialNames()); - } - tooltip.add(oreVeinLocation.getToggleDepletedHint()); - } - - @Override - public void drawCustomTooltip(FontRenderer fontRenderer, int mouseX, int mouseY, int displayWidth, - int displayHeight) {} - - @Override - public boolean isMouseOver(int mouseX, int mouseY) { - return mouseX >= iconX && mouseX <= iconX + iconSize && mouseY >= iconY && mouseY <= iconY + iconSize; - } - - @Override - public void onActionKeyPressed() { - oreVeinLocation.toggleOreVein(); - } - - @Override - public IWaypointAndLocationProvider getLocationProvider() { - return oreVeinLocation; - } - - @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, - double fontScale, double rotation) { - iconSize = 32 * drawScale; - final double iconSizeHalf = iconSize / 2; - final Point2D.Double blockAsPixel = gridRenderer - .getBlockPixelInGrid(oreVeinLocation.getBlockX(), oreVeinLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double( - blockAsPixel.getX() + draggedPixelX, - blockAsPixel.getY() + draggedPixelY); - - if (gridRenderer.getZoom() >= Config.minZoomLevelForOreLabel && !oreVeinLocation.isDepleted()) { - final int fontColor = oreVeinLocation.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F; - DrawUtil.drawLabel( - oreVeinLocation.getName(), - pixel.getX(), - pixel.getY() - iconSize, - DrawUtil.HAlign.Center, - DrawUtil.VAlign.Middle, - 0, - 180, - fontColor, - 255, - fontScale, - false, - rotation); - } - - iconX = pixel.getX() - iconSizeHalf; - iconY = pixel.getY() - iconSizeHalf; - final IIcon blockIcon = Blocks.stone.getIcon(0, 0); - DrawUtils.drawQuad(blockIcon, iconX, iconY, iconSize, iconSize, 0xFFFFFF, 255); - - DrawUtils.drawQuad( - oreVeinLocation.getIconFromPrimaryOre(), - iconX, - iconY, - iconSize, - iconSize, - oreVeinLocation.getColor(), - 255); - - if (!oreVeinLocation.drawSearchHighlight() || oreVeinLocation.isDepleted()) { - DrawUtil.drawRectangle(iconX, iconY, iconSize, iconSize, 0x000000, 150); - if (oreVeinLocation.isDepleted()) { - DrawUtils.drawQuad(depletedTextureLocation, iconX, iconY, iconSize, iconSize, 0xFFFFFF, 255); - } - } - - if (oreVeinLocation.isActiveAsWaypoint()) { - final double thickness = iconSize / 8; - final int borderAlpha = 204; - final int color = 0xFFD700; - DrawUtil.drawRectangle( - iconX - thickness, - iconY - thickness, - iconSize + thickness, - thickness, - color, - borderAlpha); - DrawUtil.drawRectangle( - iconX + iconSize, - iconY - thickness, - thickness, - iconSize + thickness, - color, - borderAlpha); - DrawUtil.drawRectangle(iconX, iconY + iconSize, iconSize + thickness, thickness, color, borderAlpha); - DrawUtil.drawRectangle(iconX - thickness, iconY, thickness, iconSize + thickness, color, borderAlpha); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java deleted file mode 100644 index 8a49662e..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidChunkDrawStep.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; - -import java.awt.geom.Point2D; - -import com.gtnewhorizons.navigator.api.journeymap.drawsteps.JMRenderStep; -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; - -import journeymap.client.render.draw.DrawUtil; -import journeymap.client.render.map.GridRenderer; - -public class UndergroundFluidChunkDrawStep implements JMRenderStep { - - private final UndergroundFluidChunkLocation undergroundFluidChunkLocation; - - public UndergroundFluidChunkDrawStep(UndergroundFluidChunkLocation undergroundFluidChunkLocation) { - this.undergroundFluidChunkLocation = undergroundFluidChunkLocation; - } - - @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, - double fontScale, double rotation) { - final int zoom = gridRenderer.getZoom(); - if (undergroundFluidChunkLocation.getFluidAmount() > 0 - && zoom >= Config.minZoomLevelForUndergroundFluidDetails) { - double blockSize = Math.pow(2, zoom); - final Point2D.Double blockAsPixel = gridRenderer.getBlockPixelInGrid( - undergroundFluidChunkLocation.getBlockX(), - undergroundFluidChunkLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double( - blockAsPixel.getX() + draggedPixelX, - blockAsPixel.getY() + draggedPixelY); - float alpha = ((float) (undergroundFluidChunkLocation.getFluidAmount() - - undergroundFluidChunkLocation.getMinAmountInField())) - / (undergroundFluidChunkLocation.getMaxAmountInField() - - undergroundFluidChunkLocation.getMinAmountInField() - + 1); - alpha *= alpha * 204; - DrawUtil.drawRectangle( - pixel.getX(), - pixel.getY(), - VP.chunkWidth * blockSize, - VP.chunkDepth * blockSize, - undergroundFluidChunkLocation.getFluid().getColor(), - (int) alpha); - - if (undergroundFluidChunkLocation.getFluidAmount() >= undergroundFluidChunkLocation.getMaxAmountInField()) { - final int borderColor = 0xFFD700; - final int borderAlpha = 204; - DrawUtil.drawRectangle(pixel.getX(), pixel.getY(), 15 * blockSize, blockSize, borderColor, borderAlpha); - DrawUtil.drawRectangle( - pixel.getX() + 15 * blockSize, - pixel.getY(), - blockSize, - 15 * blockSize, - borderColor, - borderAlpha); - DrawUtil.drawRectangle( - pixel.getX() + 1 * blockSize, - pixel.getY() + 15 * blockSize, - 15 * blockSize, - blockSize, - borderColor, - borderAlpha); - DrawUtil.drawRectangle( - pixel.getX(), - pixel.getY() + 1 * blockSize, - blockSize, - 15 * blockSize, - borderColor, - borderAlpha); - } - - DrawUtil.drawLabel( - undergroundFluidChunkLocation.getFluidAmountFormatted(), - pixel.getX() + 13 * blockSize, - pixel.getY() + 13 * blockSize, - DrawUtil.HAlign.Left, - DrawUtil.VAlign.Above, - 0, - 180, - 0x00FFFFFF, - 255, - fontScale, - false, - rotation); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java deleted file mode 100644 index 467099b7..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/drawsteps/UndergroundFluidDrawStep.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.drawsteps; - -import java.awt.geom.Point2D; - -import net.minecraft.client.resources.I18n; - -import com.gtnewhorizons.navigator.api.journeymap.drawsteps.JMRenderStep; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; - -import journeymap.client.render.draw.DrawUtil; -import journeymap.client.render.map.GridRenderer; - -public class UndergroundFluidDrawStep implements JMRenderStep { - - private final UndergroundFluidLocation undergroundFluidLocation; - - public UndergroundFluidDrawStep(UndergroundFluidLocation undergroundFluidLocation) { - this.undergroundFluidLocation = undergroundFluidLocation; - } - - @SuppressWarnings("deprecation") - @Override - public void draw(double draggedPixelX, double draggedPixelY, GridRenderer gridRenderer, float drawScale, - double fontScale, double rotation) { - final int maxAmountInField = undergroundFluidLocation.getMaxProduction(); - final double blockSize = Math.pow(2, gridRenderer.getZoom()); - final Point2D.Double blockAsPixel = gridRenderer - .getBlockPixelInGrid(undergroundFluidLocation.getBlockX(), undergroundFluidLocation.getBlockZ()); - final Point2D.Double pixel = new Point2D.Double( - blockAsPixel.getX() + draggedPixelX, - blockAsPixel.getY() + draggedPixelY); - - final int borderColor = undergroundFluidLocation.getFluid().getColor(); - final int borderAlpha = 204; - DrawUtil.drawRectangle( - pixel.getX(), - pixel.getY(), - VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, - 2 * blockSize, - borderColor, - borderAlpha); - DrawUtil.drawRectangle( - pixel.getX() + VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, - pixel.getY(), - 2 * blockSize, - VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, - borderColor, - borderAlpha); - DrawUtil.drawRectangle( - pixel.getX() + 2 * blockSize, - pixel.getY() + VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, - VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize, - 2 * blockSize, - borderColor, - borderAlpha); - DrawUtil.drawRectangle( - pixel.getX(), - pixel.getY() + 2 * blockSize, - 2 * blockSize, - VP.undergroundFluidSizeChunkZ * VP.chunkDepth * blockSize, - borderColor, - borderAlpha); - - String label = I18n.format("visualprospecting.empty"); - if (maxAmountInField > 0) { - label = undergroundFluidLocation.getMinProduction() + "L - " - + maxAmountInField - + "L " - + undergroundFluidLocation.getFluid().getLocalizedName(); - } - DrawUtil.drawLabel( - label, - pixel.getX() + VP.chunkWidth * (blockSize * 4), - pixel.getY(), - DrawUtil.HAlign.Center, - DrawUtil.VAlign.Below, - 0, - 180, - 0x00FFFFFF, - 255, - fontScale, - false, - rotation); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMOreVeinRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMOreVeinRenderer.java deleted file mode 100644 index 1f53a50e..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMOreVeinRenderer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.render; - -import java.util.ArrayList; -import java.util.List; - -import com.gtnewhorizons.navigator.api.journeymap.render.JMInteractableLayerRenderer; -import com.gtnewhorizons.navigator.api.model.layers.InteractableLayerManager; -import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; -import com.gtnewhorizons.navigator.api.model.steps.RenderStep; -import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.OreVeinDrawStep; -import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; - -public class JMOreVeinRenderer extends JMInteractableLayerRenderer { - - public JMOreVeinRenderer(InteractableLayerManager manager) { - super(manager); - } - - @Override - protected List generateRenderSteps(List visibleElements) { - final List drawSteps = new ArrayList<>(); - visibleElements.stream().map(element -> (OreVeinLocation) element) - .forEach(location -> drawSteps.add(new OreVeinDrawStep(location))); - return drawSteps; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidChunkRenderer.java deleted file mode 100644 index de0245d9..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidChunkRenderer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.render; - -import java.util.ArrayList; -import java.util.List; - -import com.gtnewhorizons.navigator.api.journeymap.render.JMLayerRenderer; -import com.gtnewhorizons.navigator.api.model.layers.LayerManager; -import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; -import com.gtnewhorizons.navigator.api.model.steps.RenderStep; -import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.UndergroundFluidChunkDrawStep; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; - -public class JMUndergroundFluidChunkRenderer extends JMLayerRenderer { - - public JMUndergroundFluidChunkRenderer(LayerManager manager) { - super(manager); - } - - @Override - protected List generateRenderSteps(List visibleElements) { - final List drawSteps = new ArrayList<>(); - visibleElements.stream().map(element -> (UndergroundFluidChunkLocation) element) - .forEach(location -> drawSteps.add(new UndergroundFluidChunkDrawStep(location))); - return drawSteps; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidRenderer.java deleted file mode 100644 index 62acc735..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/journeymap/render/JMUndergroundFluidRenderer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.sinthoras.visualprospecting.integration.journeymap.render; - -import java.util.ArrayList; -import java.util.List; - -import com.gtnewhorizons.navigator.api.journeymap.render.JMLayerRenderer; -import com.gtnewhorizons.navigator.api.model.layers.LayerManager; -import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; -import com.gtnewhorizons.navigator.api.model.steps.RenderStep; -import com.sinthoras.visualprospecting.integration.journeymap.drawsteps.UndergroundFluidDrawStep; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; - -public class JMUndergroundFluidRenderer extends JMLayerRenderer { - - public JMUndergroundFluidRenderer(LayerManager manager) { - super(manager); - } - - @Override - protected List generateRenderSteps(List visibleElements) { - final List drawSteps = new ArrayList<>(); - visibleElements.stream().map(element -> (UndergroundFluidLocation) element) - .forEach(location -> drawSteps.add(new UndergroundFluidDrawStep(location))); - return drawSteps; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java index bc64634d..8d6eaf72 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java @@ -1,38 +1,28 @@ package com.sinthoras.visualprospecting.integration.model.layers; -import java.util.ArrayList; -import java.util.List; - -import net.minecraft.client.Minecraft; - import org.jetbrains.annotations.Nullable; import com.gtnewhorizons.navigator.api.journeymap.waypoints.JMWaypointManager; import com.gtnewhorizons.navigator.api.model.SupportedMods; import com.gtnewhorizons.navigator.api.model.layers.InteractableLayerManager; import com.gtnewhorizons.navigator.api.model.layers.LayerRenderer; -import com.gtnewhorizons.navigator.api.model.locations.IWaypointAndLocationProvider; +import com.gtnewhorizons.navigator.api.model.layers.UniversalInteractableRenderer; +import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; import com.gtnewhorizons.navigator.api.model.waypoints.WaypointManager; +import com.gtnewhorizons.navigator.api.xaero.waypoints.XaeroWaypointManager; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; -import com.sinthoras.visualprospecting.integration.journeymap.render.JMOreVeinRenderer; import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; -import com.sinthoras.visualprospecting.integration.xaerominimap.OreVeinWaypointManager; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.XaeroOreVeinRenderer; +import com.sinthoras.visualprospecting.integration.model.render.OreVeinRenderStep; public class OreVeinLayerManager extends InteractableLayerManager { public static final OreVeinLayerManager instance = new OreVeinLayerManager(); - private int oldMinOreChunkX = 0; - private int oldMaxOreChunkX = 0; - private int oldMinOreChunkZ = 0; - private int oldMaxOreChunkZ = 0; - public OreVeinLayerManager() { super(OreVeinButtonManager.instance); } @@ -42,33 +32,11 @@ public void onOpenMap() { VeinTypeCaching.recalculateNEISearch(); } - @Override - protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minOreChunkX = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minOreChunkZ = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxOreChunkX = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxOreChunkZ = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - - if (minOreChunkX != oldMinOreChunkX || maxOreChunkX != oldMaxOreChunkX - || minOreChunkZ != oldMinOreChunkZ - || maxOreChunkZ != oldMaxOreChunkZ) { - oldMinOreChunkX = minOreChunkX; - oldMaxOreChunkX = maxOreChunkX; - oldMinOreChunkZ = minOreChunkZ; - oldMaxOreChunkZ = maxOreChunkZ; - return true; - } - return false; - } - @Nullable @Override protected LayerRenderer addLayerRenderer(InteractableLayerManager manager, SupportedMods mod) { - return switch (mod) { - case JourneyMap -> new JMOreVeinRenderer(manager); - case XaeroWorldMap -> new XaeroOreVeinRenderer(manager); - default -> null; - }; + return new UniversalInteractableRenderer(manager) + .withRenderStep(location -> new OreVeinRenderStep((OreVeinLocation) location)); } @Nullable @@ -76,33 +44,23 @@ protected LayerRenderer addLayerRenderer(InteractableLayerManager manager, Suppo protected WaypointManager addWaypointManager(InteractableLayerManager manager, SupportedMods mod) { return switch (mod) { case JourneyMap -> new JMWaypointManager(manager); - case XaeroWorldMap -> new OreVeinWaypointManager(manager); + case XaeroWorldMap -> new XaeroWaypointManager(manager, "!"); default -> null; }; } @Override - protected List generateVisibleElements(int minBlockX, int minBlockZ, - int maxBlockX, int maxBlockZ) { - final int minOreChunkX = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minOreChunkZ = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxOreChunkX = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxOreChunkZ = Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - final int playerDimensionId = Minecraft.getMinecraft().thePlayer.dimension; - - ArrayList oreChunkLocations = new ArrayList<>(); - - for (int chunkX = minOreChunkX; chunkX <= maxOreChunkX; chunkX = Utils.mapToCenterOreChunkCoord(chunkX + 3)) { - for (int chunkZ = minOreChunkZ; chunkZ - <= maxOreChunkZ; chunkZ = Utils.mapToCenterOreChunkCoord(chunkZ + 3)) { - final OreVeinPosition oreVeinPosition = ClientCache.instance - .getOreVein(playerDimensionId, chunkX, chunkZ); - if (oreVeinPosition.veinType != VeinType.NO_VEIN) { - oreChunkLocations.add(new OreVeinLocation(oreVeinPosition)); - } - } + protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { + int oreChunkX = Utils.mapToCenterOreChunkCoord(chunkX); + int oreChunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); + if (chunkX % oreChunkX != 0 || chunkZ % oreChunkZ != 0) { + return null; + } + OreVeinPosition oreVeinPosition = ClientCache.instance.getOreVein(dim, oreChunkX, oreChunkZ); + if (oreVeinPosition.veinType != VeinType.NO_VEIN) { + return new OreVeinLocation(oreVeinPosition); } - return oreChunkLocations; + return null; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java index ba0a8409..63430bf2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java @@ -1,111 +1,52 @@ package com.sinthoras.visualprospecting.integration.model.layers; -import java.util.ArrayList; -import java.util.List; - -import net.minecraft.client.Minecraft; - import org.jetbrains.annotations.Nullable; import com.gtnewhorizons.navigator.api.model.SupportedMods; import com.gtnewhorizons.navigator.api.model.layers.LayerManager; import com.gtnewhorizons.navigator.api.model.layers.LayerRenderer; +import com.gtnewhorizons.navigator.api.model.layers.UniversalLayerRenderer; import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; -import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; -import com.sinthoras.visualprospecting.integration.journeymap.render.JMUndergroundFluidChunkRenderer; import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.XaeroUndergroundFluidChunkRenderer; +import com.sinthoras.visualprospecting.integration.model.render.UndergroundFluidChunkRenderStep; public class UndergroundFluidChunkLayerManager extends LayerManager { public static final UndergroundFluidChunkLayerManager instance = new UndergroundFluidChunkLayerManager(); - private int oldMinUndergroundFluidX = 0; - private int oldMaxUndergroundFluidX = 0; - private int oldMinUndergroundFluidZ = 0; - private int oldMaxUndergroundFluidZ = 0; - public UndergroundFluidChunkLayerManager() { super(UndergroundFluidButtonManager.instance); } - @Override - protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minUndergroundFluidX = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - if (minUndergroundFluidX != oldMinUndergroundFluidX || maxUndergroundFluidX != oldMaxUndergroundFluidX - || minUndergroundFluidZ != oldMinUndergroundFluidZ - || maxUndergroundFluidZ != oldMaxUndergroundFluidZ) { - oldMinUndergroundFluidX = minUndergroundFluidX; - oldMaxUndergroundFluidX = maxUndergroundFluidX; - oldMinUndergroundFluidZ = minUndergroundFluidZ; - oldMaxUndergroundFluidZ = maxUndergroundFluidZ; - return true; - } - return false; - } - @Nullable @Override protected LayerRenderer addLayerRenderer(LayerManager manager, SupportedMods mods) { - return switch (mods) { - case JourneyMap -> new JMUndergroundFluidChunkRenderer(manager); - case XaeroWorldMap -> new XaeroUndergroundFluidChunkRenderer(manager); - default -> null; - }; + return new UniversalLayerRenderer(manager).withRenderStep( + location -> new UndergroundFluidChunkRenderStep((UndergroundFluidChunkLocation) location)); } @Override - protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, - int maxBlockZ) { - final int minUndergroundFluidX = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - final int playerDimensionId = Minecraft.getMinecraft().thePlayer.dimension; - - ArrayList undergroundFluidPositions = new ArrayList<>(); + protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { + if (chunkX % VP.undergroundFluidSizeChunkX != 0 || chunkZ % VP.undergroundFluidSizeChunkZ != 0) { + return null; + } + final UndergroundFluidPosition undergroundFluid = ClientCache.instance.getUndergroundFluid(dim, chunkX, chunkZ); + if (!undergroundFluid.isProspected()) return null; + generateExtraFluidChunks(chunkX, chunkZ, dim, undergroundFluid); + return new UndergroundFluidChunkLocation(chunkX, chunkZ, dim, undergroundFluid, 0, 0); + } - for (int chunkX = minUndergroundFluidX; chunkX - <= maxUndergroundFluidX; chunkX += VP.undergroundFluidSizeChunkX) { - for (int chunkZ = minUndergroundFluidZ; chunkZ - <= maxUndergroundFluidZ; chunkZ += VP.undergroundFluidSizeChunkZ) { - final UndergroundFluidPosition undergroundFluid = ClientCache.instance - .getUndergroundFluid(playerDimensionId, chunkX, chunkZ); - if (undergroundFluid.isProspected()) { - final int minAmountInField = undergroundFluid.getMinProduction(); - final int maxAmountInField = undergroundFluid.getMaxProduction(); - for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { - for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - undergroundFluidPositions.add( - new UndergroundFluidChunkLocation( - chunkX + offsetChunkX, - chunkZ + offsetChunkZ, - playerDimensionId, - undergroundFluid.fluid, - undergroundFluid.chunks[offsetChunkX][offsetChunkZ], - minAmountInField, - maxAmountInField)); - } - } - } + private void generateExtraFluidChunks(int chunkX, int chunkZ, int dim, UndergroundFluidPosition undergroundFluid) { + for (int offsetX = 0; offsetX < VP.undergroundFluidSizeChunkX; offsetX++) { + for (int offsetZ = 0; offsetZ < VP.undergroundFluidSizeChunkZ; offsetZ++) { + if (offsetX == 0 && offsetZ == 0) continue; + addExtraLocation( + new UndergroundFluidChunkLocation(chunkX, chunkZ, dim, undergroundFluid, offsetX, offsetZ)); } } - - return undergroundFluidPositions; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java index 6a1995e3..fa656856 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java @@ -1,97 +1,51 @@ package com.sinthoras.visualprospecting.integration.model.layers; -import java.util.ArrayList; -import java.util.List; - -import net.minecraft.client.Minecraft; - import org.jetbrains.annotations.Nullable; import com.gtnewhorizons.navigator.api.model.SupportedMods; import com.gtnewhorizons.navigator.api.model.layers.LayerManager; import com.gtnewhorizons.navigator.api.model.layers.LayerRenderer; +import com.gtnewhorizons.navigator.api.model.layers.UniversalLayerRenderer; import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; -import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; -import com.sinthoras.visualprospecting.integration.journeymap.render.JMUndergroundFluidRenderer; import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers.XaeroUndergroundFluidRenderer; +import com.sinthoras.visualprospecting.integration.model.render.UndergroundFluidRenderStep; public class UndergroundFluidLayerManager extends LayerManager { public static final UndergroundFluidLayerManager instance = new UndergroundFluidLayerManager(); - private int oldMinUndergroundFluidX = 0; - private int oldMaxUndergroundFluidX = 0; - private int oldMinUndergroundFluidZ = 0; - private int oldMaxUndergroundFluidZ = 0; - public UndergroundFluidLayerManager() { super(UndergroundFluidButtonManager.instance); } - @Override - protected boolean needsRegenerateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, int maxBlockZ) { - final int minUndergroundFluidX = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - if (minUndergroundFluidX != oldMinUndergroundFluidX || maxUndergroundFluidX != oldMaxUndergroundFluidX - || minUndergroundFluidZ != oldMinUndergroundFluidZ - || maxUndergroundFluidZ != oldMaxUndergroundFluidZ) { - oldMinUndergroundFluidX = minUndergroundFluidX; - oldMaxUndergroundFluidX = maxUndergroundFluidX; - oldMinUndergroundFluidZ = minUndergroundFluidZ; - oldMaxUndergroundFluidZ = maxUndergroundFluidZ; - return true; - } - return false; - } - @Nullable @Override protected LayerRenderer addLayerRenderer(LayerManager manager, SupportedMods mod) { - return switch (mod) { - case JourneyMap -> new JMUndergroundFluidRenderer(manager); - case XaeroWorldMap -> new XaeroUndergroundFluidRenderer(manager); - default -> null; - }; + return new UniversalLayerRenderer(manager) + .withRenderStep(location -> new UndergroundFluidRenderStep((UndergroundFluidLocation) location)) + .withRenderPriority(1); } @Override - protected List generateVisibleElements(int minBlockX, int minBlockZ, int maxBlockX, - int maxBlockZ) { - final int minUndergroundFluidX = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockX)); - final int minUndergroundFluidZ = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(minBlockZ)); - final int maxUndergroundFluidX = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockX)); - final int maxUndergroundFluidZ = Utils - .mapToCornerUndergroundFluidChunkCoord(Utils.coordBlockToChunk(maxBlockZ)); - final int playerDimensionId = Minecraft.getMinecraft().thePlayer.dimension; - - ArrayList undergroundFluidLocations = new ArrayList<>(); + protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { + if (chunkX % VP.undergroundFluidSizeChunkX != 0 || chunkZ % VP.undergroundFluidSizeChunkZ != 0) { + return null; + } - for (int chunkX = minUndergroundFluidX; chunkX - <= maxUndergroundFluidX; chunkX += VP.undergroundFluidSizeChunkX) { - for (int chunkZ = minUndergroundFluidZ; chunkZ - <= maxUndergroundFluidZ; chunkZ += VP.undergroundFluidSizeChunkZ) { - final UndergroundFluidPosition undergroundFluid = ClientCache.instance - .getUndergroundFluid(playerDimensionId, chunkX, chunkZ); - if (undergroundFluid.isProspected()) { - undergroundFluidLocations.add(new UndergroundFluidLocation(undergroundFluid)); - } - } + UndergroundFluidPosition undergroundFluid = ClientCache.instance.getUndergroundFluid(dim, chunkX, chunkZ); + if (undergroundFluid.isProspected()) { + return new UndergroundFluidLocation(undergroundFluid); } - return undergroundFluidLocations; + return null; + } + + @Override + public int getElementSize() { + return 8; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java index 02c148c5..83a6b01a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java @@ -4,26 +4,25 @@ import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; public class UndergroundFluidChunkLocation implements ILocationProvider { private final int blockX; private final int blockZ; private final int dimensionId; - private final Fluid fluid; - private final int fluidAmount; - private final int maxAmountInField; - private final int minAmountInField; - - public UndergroundFluidChunkLocation(int chunkX, int chunkZ, int dimensionId, Fluid fluid, int fluidAmount, - int minAmountInField, int maxAmountInField) { - blockX = Utils.coordChunkToBlock(chunkX); - blockZ = Utils.coordChunkToBlock(chunkZ); + private final int offsetX; + private final int offsetZ; + private final UndergroundFluidPosition undergroundFluid; + + public UndergroundFluidChunkLocation(int chunkX, int chunkZ, int dimensionId, UndergroundFluidPosition fluid, + int offsetX, int offsetZ) { + blockX = Utils.coordChunkToBlock(chunkX + offsetX); + blockZ = Utils.coordChunkToBlock(chunkZ + offsetZ); this.dimensionId = dimensionId; - this.fluid = fluid; - this.fluidAmount = fluidAmount; - this.maxAmountInField = maxAmountInField; - this.minAmountInField = minAmountInField; + this.offsetX = offsetX; + this.offsetZ = offsetZ; + this.undergroundFluid = fluid; } public double getBlockX() { @@ -39,25 +38,25 @@ public int getDimensionId() { } public String getFluidAmountFormatted() { - if (fluidAmount >= 1000) { - return (fluidAmount / 1000) + "kL"; + if (getFluidAmount() >= 1000) { + return (getFluidAmount() / 1000) + "kL"; } - return fluidAmount + "L"; + return getFluidAmount() + "L"; } public int getFluidAmount() { - return fluidAmount; + return undergroundFluid.chunks[offsetX][offsetZ]; } public Fluid getFluid() { - return fluid; + return undergroundFluid.fluid; } public int getMaxAmountInField() { - return maxAmountInField; + return undergroundFluid.getMaxProduction(); } public int getMinAmountInField() { - return minAmountInField; + return undergroundFluid.getMinProduction(); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java index cf82972e..dfc50a4d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java @@ -8,13 +8,9 @@ public class UndergroundFluidLocation implements ILocationProvider { private final UndergroundFluidPosition undergroundFluidPosition; - private final int minProduction; - private final int maxProduction; public UndergroundFluidLocation(UndergroundFluidPosition undergroundFluidPosition) { this.undergroundFluidPosition = undergroundFluidPosition; - minProduction = undergroundFluidPosition.getMinProduction(); - maxProduction = undergroundFluidPosition.getMaxProduction(); } @Override @@ -33,11 +29,11 @@ public double getBlockZ() { } public int getMinProduction() { - return minProduction; + return undergroundFluidPosition.getMinProduction(); } public int getMaxProduction() { - return maxProduction; + return undergroundFluidPosition.getMaxProduction(); } public Fluid getFluid() { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java new file mode 100644 index 00000000..805553e5 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java @@ -0,0 +1,93 @@ +package com.sinthoras.visualprospecting.integration.model.render; + +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.util.IIcon; +import net.minecraft.util.ResourceLocation; + +import com.gtnewhorizons.navigator.api.model.steps.UniversalInteractableStep; +import com.gtnewhorizons.navigator.api.util.DrawUtils; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; + +public class OreVeinRenderStep extends UniversalInteractableStep { + + private static final ResourceLocation depletedTextureLocation = new ResourceLocation( + Tags.MODID, + "textures/depleted.png"); + private static final int fontHeight = Minecraft.getMinecraft().fontRenderer.FONT_HEIGHT; + + public OreVeinRenderStep(OreVeinLocation location) { + super(location); + setFontScale(1.2f); + setMinScale(1); + } + + @Override + public void preRender(double topX, double topY, float drawScale, double zoom) { + double iconSize = isXaero ? 10 * zoom : 32 * drawScale; + setSize(iconSize); + setOffset(-iconSize / 2); + } + + @Override + public void draw(double topX, double topY, float drawScale, double zoom) { + if (zoom >= Config.minZoomLevelForOreLabel && !location.isDepleted()) { + final int fontColor = location.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F; + DrawUtils.drawLabel( + location.getName(), + topX + width / 2, + topY - fontHeight - 5, + fontColor, + 0, + true, + getFontScale()); + } + + final IIcon blockIcon = Blocks.stone.getIcon(0, 0); + DrawUtils.drawQuad(blockIcon, topX, topY, width, height, 0xFFFFFF, 255); + + DrawUtils.drawQuad(location.getIconFromPrimaryOre(), topX, topY, width, height, location.getColor(), 255); + + if (!location.drawSearchHighlight() || location.isDepleted()) { + DrawUtils.drawRect(topX, topY, width, height, 0x000000, 150); + if (location.isDepleted()) { + DrawUtils.drawQuad(depletedTextureLocation, topX, topY, width, height, 0xFFFFFF, 255); + } + } + + if (location.isActiveAsWaypoint()) { + final double thickness = width / 8; + DrawUtils.drawHollowRect(topX, topY, width, height, 0xFFD700, 204, thickness); + } + } + + @Override + public void getTooltip(List list) { + if (location.isDepleted()) { + list.add(location.getDepletedHint()); + } + if (location.isActiveAsWaypoint()) { + list.add(location.getActiveWaypointHint()); + } + list.add(location.getName()); + if (!location.isDepleted()) { + list.addAll(location.getMaterialNames()); + } + list.add(location.getToggleDepletedHint()); + } + + @Override + public boolean isMouseOver(int mouseX, int mouseY) { + return mouseX >= getX() && mouseX <= getX() + width && mouseY >= getY() && mouseY <= getY() + height; + } + + @Override + public void onActionKeyPressed() { + location.toggleOreVein(); + } + +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidChunkRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidChunkRenderStep.java new file mode 100644 index 00000000..e9167db6 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidChunkRenderStep.java @@ -0,0 +1,38 @@ +package com.sinthoras.visualprospecting.integration.model.render; + +import com.gtnewhorizons.navigator.api.model.steps.UniversalRenderStep; +import com.gtnewhorizons.navigator.api.util.DrawUtils; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; + +public class UndergroundFluidChunkRenderStep extends UniversalRenderStep { + + public UndergroundFluidChunkRenderStep(UndergroundFluidChunkLocation location) { + super(location); + setFontScale(0.3F); + } + + @Override + public void draw(double topX, double topY, float drawScale, double zoom) { + if (location.getFluidAmount() > 0 && getZoomStep() >= Config.minZoomLevelForUndergroundFluidDetails) { + float alpha = (float) (location.getFluidAmount() - location.getMinAmountInField()) + / (location.getMaxAmountInField() - location.getMinAmountInField() + 1); + alpha = alpha * 255; + int fluidColor = location.getFluid().getColor(); + DrawUtils.drawRect(topX, topY, getAdjustedWidth(), getAdjustedHeight(), fluidColor, (int) alpha); + + if (location.getFluidAmount() >= location.getMaxAmountInField()) { + DrawUtils.drawHollowRect(topX, topY, getAdjustedWidth(), getAdjustedHeight(), 0xFFD700, 204, 1.5); + } + + DrawUtils.drawLabel( + getLocation().getFluidAmountFormatted(), + topX + getAdjustedWidth() / 2, + topY + getAdjustedHeight() / 2, + 0xFFFFFFFF, + 0xB4000000, + true, + getFontScale()); + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java new file mode 100644 index 00000000..387c4240 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java @@ -0,0 +1,43 @@ +package com.sinthoras.visualprospecting.integration.model.render; + +import net.minecraft.client.resources.I18n; + +import com.gtnewhorizons.navigator.api.model.steps.UniversalRenderStep; +import com.gtnewhorizons.navigator.api.util.DrawUtils; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; + +public class UndergroundFluidRenderStep extends UniversalRenderStep { + + public UndergroundFluidRenderStep(UndergroundFluidLocation location) { + super(location); + setSize(VP.undergroundFluidSizeChunkX * VP.chunkWidth); + setFontScale(0.5f); + } + + @Override + public void draw(double topX, double topY, float drawScale, double zoom) { + final int maxAmountInField = location.getMaxProduction(); + final int borderColor = location.getFluid().getColor(); + DrawUtils.drawHollowRect(topX, topY, getAdjustedWidth(), getAdjustedHeight(), borderColor, 255, 2); + + if (getZoomStep() >= 1 && !isMinimap()) { + String label = I18n.format("visualprospecting.empty"); + if (maxAmountInField > 0) { + label = location.getMinProduction() + "L - " + + maxAmountInField + + "L " + + location.getFluid().getLocalizedName(); + } + + DrawUtils.drawLabel( + label, + topX + getAdjustedWidth() / 2, + topY, + 0xFFFFFFFF, + 0xB4000000, + true, + getFontScale()); + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/OreVeinWaypointManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/OreVeinWaypointManager.java deleted file mode 100644 index c9c85185..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaerominimap/OreVeinWaypointManager.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaerominimap; - -import com.gtnewhorizons.navigator.api.model.layers.InteractableLayerManager; -import com.gtnewhorizons.navigator.api.model.waypoints.Waypoint; -import com.gtnewhorizons.navigator.api.xaero.waypoints.XaeroWaypointManager; - -public class OreVeinWaypointManager extends XaeroWaypointManager { - - public OreVeinWaypointManager(InteractableLayerManager manager) { - super(manager); - } - - @Override - protected String getSymbol(Waypoint waypoint) { - return "!"; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroOreVeinRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroOreVeinRenderer.java deleted file mode 100644 index e3c4be11..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroOreVeinRenderer.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; - -import java.util.ArrayList; -import java.util.List; - -import com.gtnewhorizons.navigator.api.model.layers.InteractableLayerManager; -import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; -import com.gtnewhorizons.navigator.api.xaero.renderers.XaeroInteractableLayerRenderer; -import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.OreVeinRenderStep; - -public class XaeroOreVeinRenderer extends XaeroInteractableLayerRenderer { - - public XaeroOreVeinRenderer(InteractableLayerManager manager) { - super(manager); - } - - @Override - protected List generateRenderSteps(List visibleElements) { - final List renderSteps = new ArrayList<>(); - visibleElements.stream().map(element -> (OreVeinLocation) element) - .forEach(location -> renderSteps.add(new OreVeinRenderStep(location))); - return renderSteps; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidChunkRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidChunkRenderer.java deleted file mode 100644 index 80c35436..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidChunkRenderer.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; - -import java.util.ArrayList; -import java.util.List; - -import com.gtnewhorizons.navigator.api.model.layers.LayerManager; -import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; -import com.gtnewhorizons.navigator.api.xaero.renderers.XaeroLayerRenderer; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.UndergroundFluidChunkRenderStep; - -public class XaeroUndergroundFluidChunkRenderer extends XaeroLayerRenderer { - - public XaeroUndergroundFluidChunkRenderer(LayerManager manager) { - super(manager); - } - - @Override - protected List generateRenderSteps( - List visibleElements) { - final List renderSteps = new ArrayList<>(); - visibleElements.stream().map(element -> (UndergroundFluidChunkLocation) element) - .forEach(location -> renderSteps.add(new UndergroundFluidChunkRenderStep(location))); - return renderSteps; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidRenderer.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidRenderer.java deleted file mode 100644 index 2d4e7e03..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/renderers/XaeroUndergroundFluidRenderer.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.renderers; - -import java.util.ArrayList; -import java.util.List; - -import com.gtnewhorizons.navigator.api.model.layers.LayerManager; -import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; -import com.gtnewhorizons.navigator.api.xaero.renderers.XaeroLayerRenderer; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; -import com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps.UndergroundFluidRenderStep; - -public class XaeroUndergroundFluidRenderer extends XaeroLayerRenderer { - - public XaeroUndergroundFluidRenderer(LayerManager manager) { - super(manager); - } - - @Override - protected List generateRenderSteps(List visibleElements) { - final List renderSteps = new ArrayList<>(); - visibleElements.stream().map(element -> (UndergroundFluidLocation) element) - .forEach(location -> renderSteps.add(new UndergroundFluidRenderStep(location))); - return renderSteps; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java deleted file mode 100644 index 53bb6b02..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/OreVeinRenderStep.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; - -import java.util.List; - -import javax.annotation.Nullable; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.resources.I18n; -import net.minecraft.init.Blocks; -import net.minecraft.util.IIcon; -import net.minecraft.util.ResourceLocation; - -import org.lwjgl.opengl.GL11; - -import com.gtnewhorizons.navigator.api.model.locations.IWaypointAndLocationProvider; -import com.gtnewhorizons.navigator.api.util.DrawUtils; -import com.gtnewhorizons.navigator.api.xaero.rendersteps.XaeroInteractableStep; -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; - -public class OreVeinRenderStep implements XaeroInteractableStep { - - private final OreVeinLocation oreVeinLocation; - private final ResourceLocation depletedTextureLocation = new ResourceLocation(Tags.MODID, "textures/depleted.png"); - private final IIcon blockStoneIcon = Blocks.stone.getIcon(0, 0); - private double iconSize; - private double iconX; - private double iconY; - - public OreVeinRenderStep(OreVeinLocation veinPosition) { - oreVeinLocation = veinPosition; - } - - @Override - public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double scale) { - iconSize = 10 * scale; - final double iconSizeHalf = iconSize / 2; - final double scaleForGui = Math.max(1, scale); - iconX = (oreVeinLocation.getBlockX() - 0.5 - cameraX) * scaleForGui - iconSizeHalf; - iconY = (oreVeinLocation.getBlockZ() - 0.5 - cameraZ) * scaleForGui - iconSizeHalf; - - GL11.glPushMatrix(); - GL11.glTranslated(oreVeinLocation.getBlockX() - 0.5 - cameraX, oreVeinLocation.getBlockZ() - 0.5 - cameraZ, 0); - GL11.glScaled(1 / scaleForGui, 1 / scaleForGui, 1); - DrawUtils.drawQuad(blockStoneIcon, -iconSizeHalf, -iconSizeHalf, iconSize, iconSize, 0xFFFFFF, 255); - - DrawUtils.drawQuad( - oreVeinLocation.getIconFromPrimaryOre(), - -iconSizeHalf, - -iconSizeHalf, - iconSize, - iconSize, - oreVeinLocation.getColor(), - 255); - - if (!oreVeinLocation.drawSearchHighlight() || oreVeinLocation.isDepleted()) { - DrawUtils.drawGradientRect( - -iconSizeHalf, - -iconSizeHalf, - iconSizeHalf, - iconSizeHalf, - 0, - 0x96000000, - 0x96000000); - if (oreVeinLocation.isDepleted()) { - DrawUtils.drawQuad( - depletedTextureLocation, - -iconSizeHalf, - -iconSizeHalf, - iconSize, - iconSize, - 0xFFFFFF, - 255); - } - } - - if (scale >= Utils.journeyMapScaleToLinear(Config.minZoomLevelForOreLabel) && !oreVeinLocation.isDepleted()) { - final int fontColor = oreVeinLocation.drawSearchHighlight() ? 0xFFFFFFFF : 0xFF7F7F7F; - String text = I18n.format(oreVeinLocation.getName()); - DrawUtils.drawLabel( - text, - 0, - -iconSizeHalf - Minecraft.getMinecraft().fontRenderer.FONT_HEIGHT - 5, - fontColor, - 0xB4000000, - true, - 1.6); - } - - if (oreVeinLocation.isActiveAsWaypoint()) { - final double thickness = iconSize / 8; - final int color = 0xFFFFD700; - DrawUtils.drawGradientRect( - -iconSizeHalf - thickness, - -iconSizeHalf - thickness, - iconSizeHalf, - -iconSizeHalf, - 0, - color, - color); - DrawUtils.drawGradientRect( - iconSizeHalf, - -iconSizeHalf - thickness, - iconSizeHalf + thickness, - iconSizeHalf, - 0, - color, - color); - DrawUtils.drawGradientRect( - -iconSizeHalf, - iconSizeHalf, - iconSizeHalf + thickness, - iconSizeHalf + thickness, - 0, - color, - color); - DrawUtils.drawGradientRect( - -iconSizeHalf - thickness, - -iconSizeHalf, - -iconSizeHalf, - iconSizeHalf + thickness, - 0, - color, - color); - } - - GL11.glPopMatrix(); - } - - @Override - public boolean isMouseOver(double mouseX, double mouseY, double scale) { - final double scaleForGui = Math.max(1, scale); - mouseX = mouseX * scaleForGui; - mouseY = mouseY * scaleForGui; - return mouseX >= iconX && mouseY >= iconY && mouseX <= iconX + iconSize && mouseY <= iconY + iconSize; - } - - @Override - public void getTooltip(List list) { - if (oreVeinLocation.isDepleted()) { - list.add(oreVeinLocation.getDepletedHint()); - } - - if (oreVeinLocation.isActiveAsWaypoint()) { - list.add(oreVeinLocation.getActiveWaypointHint()); - } - - list.add(oreVeinLocation.getName()); - - if (!oreVeinLocation.isDepleted()) { - list.addAll(oreVeinLocation.getMaterialNames()); - } - - list.add(oreVeinLocation.getToggleDepletedHint()); - } - - @Override - public void drawCustomTooltip(GuiScreen gui, double mouseX, double mouseY, double scale, int scaleAdj) {} - - @Override - public void onActionButton() { - oreVeinLocation.toggleOreVein(); - } - - @Override - public IWaypointAndLocationProvider getLocationProvider() { - return oreVeinLocation; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java deleted file mode 100644 index 0dc58c99..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidChunkRenderStep.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; - -import javax.annotation.Nullable; - -import net.minecraft.client.gui.GuiScreen; - -import org.lwjgl.opengl.GL11; - -import com.gtnewhorizons.navigator.api.util.DrawUtils; -import com.gtnewhorizons.navigator.api.xaero.rendersteps.XaeroRenderStep; -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; - -public class UndergroundFluidChunkRenderStep implements XaeroRenderStep { - - private final UndergroundFluidChunkLocation undergroundFluidChunkLocation; - - public UndergroundFluidChunkRenderStep(UndergroundFluidChunkLocation location) { - undergroundFluidChunkLocation = location; - } - - private String getFluidAmountFormatted() { - if (undergroundFluidChunkLocation.getFluidAmount() >= 1000) { - return (undergroundFluidChunkLocation.getFluidAmount() / 1000) + "kL"; - } - return undergroundFluidChunkLocation.getFluidAmount() + "L"; - } - - @Override - public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double scale) { - if (undergroundFluidChunkLocation.getFluidAmount() > 0 - && scale >= Utils.journeyMapScaleToLinear(Config.minZoomLevelForUndergroundFluidDetails)) { - GL11.glPushMatrix(); - GL11.glTranslated( - undergroundFluidChunkLocation.getBlockX() - 0.5 - cameraX, - undergroundFluidChunkLocation.getBlockZ() - 0.5 - cameraZ, - 0); - - float alpha = ((float) (undergroundFluidChunkLocation.getFluidAmount() - - undergroundFluidChunkLocation.getMinAmountInField())) - / (undergroundFluidChunkLocation.getMaxAmountInField() - - undergroundFluidChunkLocation.getMinAmountInField() - + 1); - alpha *= alpha * 204; - int fluidColor = undergroundFluidChunkLocation.getFluid().getColor() | (((int) alpha) << 24); - DrawUtils.drawGradientRect(0, 0, VP.chunkWidth, VP.chunkDepth, 0, fluidColor, fluidColor); - - if (undergroundFluidChunkLocation.getFluidAmount() >= undergroundFluidChunkLocation.getMaxAmountInField()) { - final int borderColor = 0xCCFFD700; - DrawUtils.drawGradientRect(0, 0, 15, 1, 0, borderColor, borderColor); - DrawUtils.drawGradientRect(15, 0, 16, 15, 0, borderColor, borderColor); - DrawUtils.drawGradientRect(1, 15, 16, 16, 0, borderColor, borderColor); - DrawUtils.drawGradientRect(0, 1, 1, 16, 0, borderColor, borderColor); - } - - GL11.glScaled(1 / scale, 1 / scale, 1); - if (gui != null) { - DrawUtils.drawSimpleLabel(gui, getFluidAmountFormatted(), 13, 13, 0xFFFFFFFF, 0xB4000000, false); - } - GL11.glPopMatrix(); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java deleted file mode 100644 index 64cbe4ca..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/xaeroworldmap/rendersteps/UndergroundFluidRenderStep.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.sinthoras.visualprospecting.integration.xaeroworldmap.rendersteps; - -import javax.annotation.Nullable; - -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.resources.I18n; - -import org.lwjgl.opengl.GL11; - -import com.gtnewhorizons.navigator.api.util.DrawUtils; -import com.gtnewhorizons.navigator.api.xaero.rendersteps.XaeroRenderStep; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; - -public class UndergroundFluidRenderStep implements XaeroRenderStep { - - private final UndergroundFluidLocation undergroundFluidLocation; - - public UndergroundFluidRenderStep(UndergroundFluidLocation undergroundFluid) { - undergroundFluidLocation = undergroundFluid; - } - - @SuppressWarnings("deprecation") - @Override - public void draw(@Nullable GuiScreen gui, double cameraX, double cameraZ, double scale) { - final int maxAmountInField = undergroundFluidLocation.getMaxProduction(); - // < 0.5 scale is when scaling issues show up - if (scale >= 0.5) { - GL11.glPushMatrix(); - GL11.glTranslated( - undergroundFluidLocation.getBlockX() - 0.5 - cameraX, - undergroundFluidLocation.getBlockZ() - 0.5 - cameraZ, - 0); - - final int borderColor = undergroundFluidLocation.getFluid().getColor() | 0xCC000000; - final double lenX = VP.undergroundFluidSizeChunkX * VP.chunkWidth; - final double lenZ = VP.undergroundFluidSizeChunkZ * VP.chunkDepth; - DrawUtils.drawGradientRect(0, 0, lenX, 2, 0, borderColor, borderColor); - DrawUtils.drawGradientRect(lenX, 0, lenX + 2, lenZ, 0, borderColor, borderColor); - DrawUtils.drawGradientRect(2, lenZ, lenX + 2, lenZ + 2, 0, borderColor, borderColor); - DrawUtils.drawGradientRect(0, 2, 2, lenZ + 2, 0, borderColor, borderColor); - - // min scale that journeymap can go to - if (scale >= 1 && gui != null) { - GL11.glScaled(1 / scale, 1 / scale, 1); - String label = I18n.format("visualprospecting.empty"); - if (maxAmountInField > 0) { - label = undergroundFluidLocation.getMinProduction() + "L - " - + maxAmountInField - + "L " - + undergroundFluidLocation.getFluid().getLocalizedName(); - } - DrawUtils.drawSimpleLabel(gui, label, VP.chunkWidth * scale, 0, 0xFFFFFFFF, 0xB4000000, false); - } - - GL11.glPopMatrix(); - } - } -} From e343eb247a3ed0412d9bb040d80c3da9db316329 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sat, 7 Sep 2024 18:16:47 +0200 Subject: [PATCH 063/132] update --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 806cf42d..975ebc71 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,8 +1,8 @@ dependencies { shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:Navigator:1.0.10:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.64:dev') + api('com.github.GTNewHorizons:Navigator:1.0.12:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.76:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.5')) } From e927d4c95b590aeb73d4e9a43d9b73d05a2d2e54 Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Sun, 15 Sep 2024 19:34:28 +0200 Subject: [PATCH 064/132] Optimization & cleanup (#54) * optimize caching & reduce allocations * faster matching of chunk -> VeinType * localized name works fine so kill the weird translation system, also fixes bartworks ores showing that they contain random gt materials * remove old lang files too --- dependencies.gradle | 6 +- gradle.properties | 2 +- .../sinthoras/visualprospecting/Config.java | 9 - .../visualprospecting/ServerTranslations.java | 158 ------------- .../sinthoras/visualprospecting/Utils.java | 138 ++++++----- .../database/ClientCache.java | 37 ++- .../database/DimensionCache.java | 218 +++++++++++------- .../database/RedoServerCacheCommand.java | 6 +- .../database/RedoServerSpawnCacheCommand.java | 4 +- .../database/TransferCache.java | 3 +- .../database/WorldCache.java | 73 ++++-- .../database/cachebuilder/ChunkAnalysis.java | 79 +++++-- .../cachebuilder/DetailedChunkAnalysis.java | 69 +++--- .../cachebuilder/DimensionAnalysis.java | 44 ++-- .../database/cachebuilder/GregTechOre.java | 35 --- .../database/cachebuilder/RegionReader.java | 80 +++++++ .../database/cachebuilder/WorldAnalysis.java | 61 ++++- .../BartworksOreMaterialProvider.java | 30 ++- .../GregTechOreMaterialProvider.java | 30 ++- .../veintypes/IOreMaterialProvider.java | 7 + .../database/veintypes/VeinType.java | 47 ++-- .../database/veintypes/VeinTypeCaching.java | 120 +++++----- .../integration/gregtech/VeinDatabase.java | 3 +- .../model/locations/OreVeinLocation.java | 2 +- .../item/ProspectorsLog.java | 6 +- ...aTileEntity_AdvSeismicProspectorMixin.java | 6 +- .../GT_MetaTileEntity_ScannerMixin.java | 3 +- .../network/ProspectingRequest.java | 7 +- .../network/ProspectionSharing.java | 6 +- .../task/SnapshotDownloadTask.java | 2 +- .../task/SnapshotUploadTask.java | 2 +- .../META-INF/visualprospecting_at.cfg | 2 + .../resources/assets/gregtech/lang/en_US.lang | 101 -------- .../resources/assets/gregtech/lang/zh_CN.lang | 93 -------- 34 files changed, 690 insertions(+), 799 deletions(-) delete mode 100644 src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/RegionReader.java create mode 100644 src/main/resources/META-INF/visualprospecting_at.cfg delete mode 100644 src/main/resources/assets/gregtech/lang/en_US.lang delete mode 100644 src/main/resources/assets/gregtech/lang/zh_CN.lang diff --git a/dependencies.gradle b/dependencies.gradle index 975ebc71..50d3282f 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,8 +1,8 @@ dependencies { - shadowImplementation('com.github.GTNewHorizons:Enklume:2.1.0:dev') - api('com.github.GTNewHorizons:Navigator:1.0.12:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.76:dev') + api('com.github.GTNewHorizons:GTNHLib:0.5.11:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.103:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.5')) + runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/gradle.properties b/gradle.properties index 4c38eda4..98961baa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -80,7 +80,7 @@ apiPackage = # Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/ # There can be multiple files in a space-separated list. # Example value: mymodid_at.cfg nei_at.cfg -accessTransformersFile = +accessTransformersFile =visualprospecting_at.cfg # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! usesMixins = true diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index 741d14e8..6f6c279d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -19,7 +19,6 @@ private static class Defaults { public static final int maxTransferCacheSizeMB = 50; public static final boolean enableVoxelMapWaypointsByDefault = false; public static final int maxDimensionSizeMBForFastScanning = 10000; - public static boolean enableDeveloperOverlays = false; } private static class Categories { @@ -41,7 +40,6 @@ private static class Categories { public static int maxTransferCacheSizeMB = Defaults.maxTransferCacheSizeMB; public static boolean enableVoxelMapWaypointsByDefault = Defaults.enableVoxelMapWaypointsByDefault; public static int maxDimensionSizeMBForFastScanning = Defaults.maxDimensionSizeMBForFastScanning; - public static boolean enableDeveloperOverlays = Defaults.enableDeveloperOverlays; public static void syncronizeConfiguration(File configFile) { Configuration configuration = new Configuration(configFile); @@ -127,13 +125,6 @@ public static void syncronizeConfiguration(File configFile) { + "memory issues during the initial world scan (OutOfMemoryException)."); maxDimensionSizeMBForFastScanning = maxDimensionSizeMBForFastScanningProperty.getInt(); - Property enableDeveloperOverlaysProperty = configuration.get( - Categories.general, - "enableDeveloperOverlays", - Defaults.enableDeveloperOverlays, - "[CLIENT] Enable mod developer overlays, not useful for gameplay"); - enableDeveloperOverlays = enableDeveloperOverlaysProperty.getBoolean(); - if (configuration.hasChanged()) { configuration.save(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java b/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java deleted file mode 100644 index f92bbcaf..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/ServerTranslations.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.sinthoras.visualprospecting; - -import net.minecraft.client.resources.I18n; -import net.minecraft.server.MinecraftServer; -import net.minecraftforge.fluids.Fluid; - -import com.sinthoras.visualprospecting.database.veintypes.VeinType; - -// Backup translations for server side lookups only -public class ServerTranslations { - - @SuppressWarnings("deprecation") - public static String getEnglishLocalization(Fluid fluid) { - if (MinecraftServer.getServer().isSinglePlayer()) { - return fluid.getLocalizedName(); - } - - return switch (fluid.getUnlocalizedName()) { - case "fluid.gas_natural_gas" -> "Natural Gas"; - case "fluid.liquid_light_oil" -> "Light Oil"; - case "fluid.liquid_medium_oil" -> "Raw Oil"; - case "fluid.liquid_heavy_oil" -> "Heavy Oil"; - case "fluid.oil" -> "Oil"; - case "fluid.drillingfluid" -> "Drilling Fluid"; - case "fluid.helium-3" -> "Helium-3"; - case "fluid.saltwater" -> "Saltwater"; - case "fluid.molten.iron" -> "Molten Iron"; - case "fluid.molten.lead" -> "Molten Lead"; - case "fluid.sulfuricacid" -> "Sulfuric Acid"; - case "fluid.carbondioxide" -> "Carbondioxide"; - case "fluid.chlorobenzene" -> "Chlorobenzene"; - case "fluid.liquid_extra_heavy_oil" -> "Extra Heavy Oil"; - case "fluid.ic2distilledwater" -> "Distilled Water"; - case "fluid.oxygen" -> "Oxygen"; - case "fluid.liquidair" -> "Liquid Air"; - case "fluid.methane" -> "Methane"; - case "fluid.ethane" -> "Ethane"; - case "fluid.liquid_hydricsulfur" -> "Liquid Hydric Sulfur"; - case "fluid.carbonmonoxide" -> "Carbonmonoxide"; - case "fluid.nitrogen" -> "Nitrogen"; - case "fluid.ethylene" -> "Ethylene"; - case "fluid.deuterium" -> "Deuterium"; - case "fluid.fluorine" -> "Fluorine"; - case "fluid.hydrofluoricacid_gt5u" -> "Hydrofluoric Acid"; - case "fluid.molten.copper" -> "Molten Copper"; - case "fluid.unknowwater" -> "Unknowwater"; - case "fluid.molten.tin" -> "Molten Tin"; - case "fluid.hydrogen" -> "Hydrogen"; - case "fluid.lava" -> "Lava"; - default -> fluid.getUnlocalizedName(); - }; - } - - /* - * Copy the relevant content into a file 'data.dat' and run the following python script to generate the switch-case: - * with open("data.dat") as f: lines = f.readlines() for line in lines: if line is not "\n": key, value = - * line.split("=") value = value[:-1] print("case \"" + key + "\":") print(" return \"" + value + "\";") - */ - public static String getEnglishLocalization(VeinType veinType) { - if (MinecraftServer.getServer().isSinglePlayer()) { - return I18n.format(veinType.name); - } - - return switch (veinType.name) { - case "ore.mix.naquadah" -> "Naquadah"; - case "ore.mix.lignite" -> "Lignite"; - case "ore.mix.coal" -> "Coal"; - case "ore.mix.magnetite" -> "Magnetite"; - case "ore.mix.gold" -> "Gold"; - case "ore.mix.iron" -> "Iron"; - case "ore.mix.cassiterite" -> "Cassiterite"; - case "ore.mix.tetrahedrite" -> "Tetrahedrite"; - case "ore.mix.netherquartz" -> "Nether Quartz"; - case "ore.mix.sulfur" -> "Sulfur"; - case "ore.mix.copper" -> "Copper"; - case "ore.mix.bauxite" -> "Bauxite"; - case "ore.mix.salts" -> "Salts"; - case "ore.mix.redstone" -> "Redstone"; - case "ore.mix.soapstone" -> "Soapstone"; - case "ore.mix.nickel" -> "Nickel"; - case "ore.mix.platinum" -> "Platinum"; - case "ore.mix.pitchblende" -> "Pitchblende"; - case "ore.mix.monazite" -> "Monazite"; - case "ore.mix.molybdenum" -> "Molybdenum"; - case "ore.mix.tungstate" -> "Tungstate"; - case "ore.mix.sapphire" -> "Sapphire"; - case "ore.mix.manganese" -> "Manganese"; - case "ore.mix.quartz" -> "Quartz"; - case "ore.mix.diamond" -> "Diamond"; - case "ore.mix.olivine" -> "Olivine"; - case "ore.mix.apatite" -> "Apatite"; - case "ore.mix.galena" -> "Galena"; - case "ore.mix.lapis" -> "Lapis"; - case "ore.mix.beryllium" -> "Beryllium"; - case "ore.mix.uranium" -> "Uranium"; - case "ore.mix.oilsand" -> "Oilsands"; - case "ore.mix.neutronium" -> "Neutronium"; - case "ore.mix.aquaignis" -> "Aqua and Ignis"; - case "ore.mix.terraaer" -> "Terra and Aer"; - case "ore.mix.perditioordo" -> "Perdito and Ordo"; - case "ore.mix.coppertin" -> "Vermiculite"; - case "ore.mix.titaniumchrome" -> "Ilmenite"; - case "ore.mix.mineralsand" -> "Mineralsand"; - case "ore.mix.garnettin" -> "Garnettin"; - case "ore.mix.kaolinitezeolite" -> "Kaolinite"; - case "ore.mix.mica" -> "Mica"; - case "ore.mix.dolomite" -> "Dolomite"; - case "ore.mix.platinumchrome" -> "Palladium"; - case "ore.mix.iridiummytryl" -> "Iridium"; - case "ore.mix.osmium" -> "Osmium"; - case "ore.mix.saltpeterelectrotine" -> "Electrotine"; - case "ore.mix.desh" -> "Desh"; - case "ore.mix.draconium" -> "Draconium"; - case "ore.mix.quantium" -> "Quantum"; - case "ore.mix.callistoice" -> "Callisto Ice"; - case "ore.mix.mytryl" -> "Mithril"; - case "ore.mix.ledox" -> "Ledox"; - case "ore.mix.oriharukon" -> "Oriharukon"; - case "ore.mix.blackplutonium" -> "Black Plutonium"; - case "ore.mix.infusedgold" -> "Infused Gold"; - case "ore.mix.niobium" -> "Niobium"; - case "ore.mix.tungstenirons" -> "Tungsten"; - case "ore.mix.uraniumgtnh" -> "Thorium"; - case "ore.mix.vanadiumgold" -> "Vanadium"; - case "ore.mix.netherstar" -> "NetherStar"; - case "ore.mix.garnet" -> "Garnet"; - case "ore.mix.rareearth" -> "Rare Earths"; - case "ore.mix.richnuclear" -> "Plutonium"; - case "ore.mix.heavypentele" -> "Arsenic"; - case "ore.mix.europa" -> "Magnesite"; - case "ore.mix.europacore" -> "Chrome"; - case "ore.mix.secondlanthanid" -> "Samarium"; - case "ore.mix.quartzspace" -> "Quartz"; - case "ore.mix.rutile" -> "Rutile"; - case "ore.mix.tfgalena" -> "Cryolite"; - case "ore.mix.luvtantalite" -> "Pyrolusit"; - case "ore.mix.ross128.Thorianit" -> "Thorianit"; - case "ore.mix.ross128.carbon" -> "Graphite"; - case "ore.mix.ross128.bismuth" -> "Bismuth"; - case "ore.mix.ross128.TurmalinAlkali" -> "Olenit"; - case "ore.mix.ross128.Roquesit" -> "Roquesit"; - case "ore.mix.ross128.Tungstate" -> "Scheelite"; - case "ore.mix.ross128.CopperSulfits" -> "Djurleit"; - case "ore.mix.ross128.Forsterit" -> "Forsterit"; - case "ore.mix.ross128.Hedenbergit" -> "Hedenbergit"; - case "ore.mix.ross128.RedZircon" -> "Red Zircon"; - case "ore.mix.ross128ba.tib" -> "Tiberium"; - case "ore.mix.ross128ba.Tungstate" -> "Scheelite"; - case "ore.mix.ross128ba.bart" -> "BArTiMaEuSNeK"; - case "ore.mix.ross128ba.TurmalinAlkali" -> "Olenit"; - case "ore.mix.ross128ba.Amethyst" -> "Amethyst"; - case "ore.mix.ross128ba.CopperSulfits" -> "Djurleit"; - case "ore.mix.ross128ba.RedZircon" -> "Red Zircon"; - case "ore.mix.ross128ba.Fluorspar" -> "Fluorspa"; - default -> veinType.name; - }; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 2f7c3c48..573077eb 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -4,6 +4,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.Reader; import java.io.Writer; import java.nio.ByteBuffer; @@ -16,43 +17,31 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.annotation.Nullable; import net.minecraft.client.Minecraft; -import net.minecraft.launchwrapper.Launch; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; + +import org.jetbrains.annotations.NotNull; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import com.gtnewhorizon.gtnhlib.util.CoordinatePacker; import com.sinthoras.visualprospecting.hooks.HooksClient; import cpw.mods.fml.common.Loader; import gregtech.common.GTWorldgenerator; +@SuppressWarnings("ResultOfMethodCallIgnored") public class Utils { - public static boolean isDevelopmentEnvironment() { - return (boolean) Launch.blackboard.get("fml.deobfuscatedEnvironment"); - } - - public static boolean isBartworksInstalled() { - return Loader.isModLoaded("bartworks"); - } - public static boolean isNEIInstalled() { return Loader.isModLoaded("NotEnoughItems"); } - public static boolean isJourneyMapInstalled() { - return Loader.isModLoaded("journeymap"); - } - - public static boolean isXaerosWorldMapInstalled() { - return Loader.isModLoaded("XaeroWorldMap"); - } - - public static boolean isXaerosMinimapInstalled() { - return Loader.isModLoaded("XaeroMinimap"); - } - public static boolean isNavigatorInstalled() { return Loader.isModLoaded("navigator"); } @@ -66,7 +55,7 @@ public static int coordChunkToBlock(int chunkCoord) { } public static long chunkCoordsToKey(int chunkX, int chunkZ) { - return (((long) chunkX) << 32) | (chunkZ & 0xffffffffL); + return CoordinatePacker.pack(chunkX, 0, chunkZ); } public static int mapToCenterOreChunkCoord(final int chunkCoord) { @@ -87,10 +76,6 @@ public static int mapToCornerUndergroundFluidChunkCoord(final int chunkCoord) { return chunkCoord & 0xFFFFFFF8; } - public static double journeyMapScaleToLinear(final int jzoom) { - return Math.pow(2, jzoom); - } - public static boolean isSmallOreId(short metaData) { return metaData >= VP.gregTechSmallOreMinimumMeta; } @@ -117,37 +102,16 @@ public static File getSubDirectory(final String subdirectory) { public static void deleteDirectoryRecursively(final File targetDirectory) { try { - Files.walk(targetDirectory.toPath()).sorted(Comparator.reverseOrder()).map(Path::toFile) - .forEach(File::delete); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static ByteBuffer readFileToBuffer(File file) { - if (file.exists() == false) { - return null; - } - try { - final FileInputStream inputStream = new FileInputStream(file); - final FileChannel inputChannel = inputStream.getChannel(); - final ByteBuffer buffer = ByteBuffer.allocate((int) inputChannel.size()); - - inputChannel.read(buffer); - buffer.flip(); - - inputChannel.close(); - inputStream.close(); - - return buffer; + try (Stream files = Files.walk(targetDirectory.toPath())) { + files.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); + } } catch (IOException e) { e.printStackTrace(); - return null; } } public static Map readFileToMap(File file) { - if (file.exists() == false) { + if (!file.exists()) { return new HashMap<>(); } try { @@ -176,24 +140,52 @@ public static void writeMapToFile(File file, Map map) { } } - public static void appendToFile(File file, ByteBuffer byteBuffer) { - try { - if (file.exists() == false) { + public static void writeNBT(File file, NBTTagCompound tag) { + try (FileOutputStream stream = new FileOutputStream(newFile(file))) { + CompressedStreamTools.writeCompressed(tag, stream); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + public static File newFile(File file) { + if (!file.exists()) { + try { + File parent = file.getParentFile(); + if (!parent.exists()) { + parent.mkdirs(); + } file.createNewFile(); + } catch (Exception e) { + e.printStackTrace(); } - final FileOutputStream outputStream = new FileOutputStream(file, true); - final FileChannel outputChannel = outputStream.getChannel(); + } - outputChannel.write(byteBuffer); + return file; + } - outputChannel.close(); - outputStream.close(); - } catch (IOException e) { - e.printStackTrace(); + @Nullable + public static NBTTagCompound readNBT(@NotNull File file) { + if (!file.exists() || !file.isFile()) { + return null; + } + + try (InputStream stream = new FileInputStream(file)) { + return CompressedStreamTools.readCompressed(stream); + } catch (Exception ex) { + try { + return CompressedStreamTools.read(file); + } catch (Exception ex1) { + return null; + } } } - public static Map getDIMFiles(File directory) { + public static Map getLegacyDimFiles(File directory) { + if (!directory.exists()) { + return new HashMap<>(); + } + try { final List dimensionIds = Files.walk(directory.toPath(), 1).filter(Files::isRegularFile) .filter(path -> path.getFileName().toString().startsWith("DIM")) @@ -213,4 +205,26 @@ public static Map getDIMFiles(File directory) { return new HashMap<>(); } } + + private static ByteBuffer readFileToBuffer(File file) { + if (!file.exists()) { + return null; + } + try { + final FileInputStream inputStream = new FileInputStream(file); + final FileChannel inputChannel = inputStream.getChannel(); + final ByteBuffer buffer = ByteBuffer.allocate((int) inputChannel.size()); + + inputChannel.read(buffer); + buffer.flip(); + + inputChannel.close(); + inputStream.close(); + + return buffer; + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index 5cd231f2..3bda034c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -99,46 +99,42 @@ public void putUndergroundFluids(List undergroundFluid updatedUndergroundFluids++; } } + + IChatComponent undergroundFluidsNotification = null; if (newUndergroundFluids > 0 && updatedUndergroundFluids > 0) { - final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation( + undergroundFluidsNotification = new ChatComponentTranslation( "visualprospecting.undergroundfluid.prospected.newandupdated", newUndergroundFluids, updatedUndergroundFluids); - undergroundFluidsNotification.getChatStyle().setItalic(true); - undergroundFluidsNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); - Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); } else { if (newUndergroundFluids > 0) { - final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation( + undergroundFluidsNotification = new ChatComponentTranslation( "visualprospecting.undergroundfluid.prospected.onlynew", newUndergroundFluids); - undergroundFluidsNotification.getChatStyle().setItalic(true); - undergroundFluidsNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); - Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); } if (updatedUndergroundFluids > 0) { - final IChatComponent undergroundFluidsNotification = new ChatComponentTranslation( + undergroundFluidsNotification = new ChatComponentTranslation( "visualprospecting.undergroundfluid.prospected.onlyupdated", updatedUndergroundFluids); - undergroundFluidsNotification.getChatStyle().setItalic(true); - undergroundFluidsNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); - Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); } } + + if (undergroundFluidsNotification == null) return; + undergroundFluidsNotification.getChatStyle().setItalic(true).setColor(EnumChatFormatting.GRAY); + Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); } public void onOreInteracted(World world, int blockX, int blockY, int blockZ, EntityPlayer entityPlayer) { if (world.isRemote && Config.enableProspecting && Minecraft.getMinecraft().thePlayer == entityPlayer) { final TileEntity tTileEntity = world.getTileEntity(blockX, blockY, blockZ); - if (tTileEntity instanceof TileEntityOres) { - final short oreMetaData = ((TileEntityOres) tTileEntity).mMetaData; - if (Utils.isSmallOreId(oreMetaData) == false && oreMetaData != 0) { + if (tTileEntity instanceof TileEntityOres ore) { + final short oreMetaData = ore.mMetaData; + if (!Utils.isSmallOreId(oreMetaData) && oreMetaData != 0) { final int chunkX = Utils.coordBlockToChunk(blockX); final int chunkZ = Utils.coordBlockToChunk(blockZ); final OreVeinPosition oreVeinPosition = getOreVein(entityPlayer.dimension, chunkX, chunkZ); final short materialId = Utils.oreIdToMaterialId(oreMetaData); - if (oreVeinPosition.veinType.containsOre(materialId) == false - && ProspectingRequest.canSendRequest()) { + if (!oreVeinPosition.veinType.containsOre(materialId) && ProspectingRequest.canSendRequest()) { VP.network.sendToServer( new ProspectingRequest(entityPlayer.dimension, blockX, blockY, blockZ, materialId)); } @@ -148,10 +144,9 @@ public void onOreInteracted(World world, int blockX, int blockY, int blockZ, Ent } public void resetPlayerProgression() { - Utils.deleteDirectoryRecursively(oreVeinCacheDirectory); - Utils.deleteDirectoryRecursively(undergroundFluidCacheDirectory); - oreVeinCacheDirectory.mkdirs(); - undergroundFluidCacheDirectory.mkdirs(); + Utils.deleteDirectoryRecursively(worldCache); + // noinspection ResultOfMethodCallIgnored + worldCache.mkdirs(); reset(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index ba0014d6..73caded6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -1,17 +1,13 @@ package com.sinthoras.visualprospecting.database; -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagIntArray; +import net.minecraft.nbt.NBTTagList; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; @@ -20,6 +16,11 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; + public class DimensionCache { public enum UpdateResult { @@ -28,67 +29,92 @@ public enum UpdateResult { New } - private final Map oreChunks = new HashMap<>(); - private final Map undergroundFluids = new HashMap<>(); - private final Set changedOrNewOreChunks = new HashSet<>(); - private final Set changedOrNewUndergroundFluids = new HashSet<>(); + private final Long2ObjectMap oreChunks = new Long2ObjectOpenHashMap<>(); + private final Long2ObjectMap undergroundFluids = new Long2ObjectOpenHashMap<>(); + private final LongSet changedOrNewOreChunks = new LongOpenHashSet(); + private final LongSet changedOrNewUndergroundFluids = new LongOpenHashSet(); public final int dimensionId; + private boolean isDirty = false; public DimensionCache(int dimensionId) { this.dimensionId = dimensionId; } - public ByteBuffer saveOreChunks() { - if (changedOrNewOreChunks.isEmpty() == false) { - final ByteBuffer byteBuffer = ByteBuffer - .allocate(changedOrNewOreChunks.size() * (2 * Integer.BYTES + Short.BYTES)); - changedOrNewOreChunks.stream().map(oreChunks::get).forEach(oreVeinPosition -> { - byteBuffer.putInt(oreVeinPosition.chunkX); - byteBuffer.putInt(oreVeinPosition.chunkZ); - short veinTypeId = VeinTypeCaching.getVeinTypeId(oreVeinPosition.veinType); - if (oreVeinPosition.isDepleted()) { - veinTypeId |= 0x8000; - } - byteBuffer.putShort(veinTypeId); - }); - changedOrNewOreChunks.clear(); - byteBuffer.flip(); - return byteBuffer; + public NBTTagCompound saveToNbt() { + NBTTagCompound compound = new NBTTagCompound(); + compound.setTag("ores", saveOres()); + compound.setTag("fluids", saveFluids()); + compound.setInteger("dim", dimensionId); + isDirty = false; + return compound; + } + + private NBTTagCompound saveOres() { + NBTTagCompound compound = new NBTTagCompound(); + for (long key : changedOrNewOreChunks) { + OreVeinPosition oreVeinPosition = oreChunks.get(key); + NBTTagCompound veinCompound = new NBTTagCompound(); + veinCompound.setInteger("chunkX", oreVeinPosition.chunkX); + veinCompound.setInteger("chunkZ", oreVeinPosition.chunkZ); + veinCompound.setShort("veinTypeId", VeinTypeCaching.getVeinTypeId(oreVeinPosition.veinType)); + veinCompound.setBoolean("depleted", oreVeinPosition.isDepleted()); + compound.setTag(String.valueOf(key), veinCompound); } - return null; - } - - public ByteBuffer saveUndergroundFluids() { - if (!changedOrNewUndergroundFluids.isEmpty()) { - final int initialCapacity = changedOrNewUndergroundFluids.size() * (Long.BYTES - + Integer.BYTES * (8 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ)); - try (final ByteArrayOutputStream baos = new ByteArrayOutputStream(initialCapacity); - final DataOutputStream dos = new DataOutputStream(baos)) { - for (ChunkCoordIntPair changedOrNewUndergroundFluid : changedOrNewUndergroundFluids) { - UndergroundFluidPosition undergroundFluidPosition = undergroundFluids - .get(changedOrNewUndergroundFluid); - dos.writeInt(undergroundFluidPosition.chunkX); - dos.writeInt(undergroundFluidPosition.chunkZ); - byte[] fluidNameBytes = undergroundFluidPosition.fluid.getName().getBytes(StandardCharsets.UTF_8); - // Negative to keep backwards compat with int fluidID written here before. - dos.writeInt(-fluidNameBytes.length); - dos.write(fluidNameBytes); - for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { - for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - dos.writeInt(undergroundFluidPosition.chunks[offsetChunkX][offsetChunkZ]); - } - } - } - changedOrNewUndergroundFluids.clear(); - return ByteBuffer.wrap(baos.toByteArray()); - } catch (IOException e) { - throw new RuntimeException(e); + return compound; + } + + private NBTTagCompound saveFluids() { + NBTTagCompound compound = new NBTTagCompound(); + for (long key : changedOrNewUndergroundFluids) { + UndergroundFluidPosition undergroundFluidPosition = undergroundFluids.get(key); + NBTTagCompound fluidCompound = new NBTTagCompound(); + fluidCompound.setInteger("chunkX", undergroundFluidPosition.chunkX); + fluidCompound.setInteger("chunkZ", undergroundFluidPosition.chunkZ); + fluidCompound.setString("fluidName", undergroundFluidPosition.fluid.getName()); + NBTTagList chunkList = new NBTTagList(); + for (int i = 0; i < VP.undergroundFluidSizeChunkX; i++) { + chunkList.appendTag(new NBTTagIntArray(undergroundFluidPosition.chunks[i])); + } + fluidCompound.setTag("chunks", chunkList); + compound.setTag(String.valueOf(key), fluidCompound); + } + return compound; + } + + @SuppressWarnings("unchecked") + public void loadFromNbt(NBTTagCompound compound) { + NBTTagCompound ores = compound.getCompoundTag("ores"); + for (NBTBase base : (Collection) ores.tagMap.values()) { + NBTTagCompound veinCompound = (NBTTagCompound) base; + int chunkX = veinCompound.getInteger("chunkX"); + int chunkZ = veinCompound.getInteger("chunkZ"); + short veinTypeId = veinCompound.getShort("veinTypeId"); + boolean depleted = veinCompound.getBoolean("depleted"); + VeinType veinType = VeinTypeCaching.getVeinType(veinTypeId); + oreChunks.put( + getOreVeinKey(chunkX, chunkZ), + new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); + } + + NBTTagCompound fluids = compound.getCompoundTag("fluids"); + for (NBTBase base : (Collection) fluids.tagMap.values()) { + NBTTagCompound fluidCompound = (NBTTagCompound) base; + int chunkX = fluidCompound.getInteger("chunkX"); + int chunkZ = fluidCompound.getInteger("chunkZ"); + String fluidName = fluidCompound.getString("fluidName"); + Fluid fluid = FluidRegistry.getFluid(fluidName); + int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; + NBTTagList chunkList = fluidCompound.getTagList("chunks", 11); + for (int i = 0; i < VP.undergroundFluidSizeChunkX; i++) { + chunks[i] = chunkList.func_150306_c(i); } + undergroundFluids.put( + getUndergroundFluidKey(chunkX, chunkZ), + new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); } - return null; } - public void loadCache(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBuffer) { + void loadLegacy(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBuffer) { if (oreChunksBuffer != null) { while (oreChunksBuffer.remaining() >= Integer.BYTES * 2 + Short.BYTES) { final int chunkX = oreChunksBuffer.getInt(); @@ -99,6 +125,7 @@ public void loadCache(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBu oreChunks.put( getOreVeinKey(chunkX, chunkZ), new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); + changedOrNewOreChunks.add(getOreVeinKey(chunkX, chunkZ)); } } if (undergroundFluidsBuffer != null) { @@ -126,66 +153,74 @@ public void loadCache(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBu undergroundFluids.put( getUndergroundFluidKey(chunkX, chunkZ), new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); + changedOrNewUndergroundFluids.add(getUndergroundFluidKey(chunkX, chunkZ)); } } } } - private ChunkCoordIntPair getOreVeinKey(int chunkX, int chunkZ) { - return new ChunkCoordIntPair(Utils.mapToCenterOreChunkCoord(chunkX), Utils.mapToCenterOreChunkCoord(chunkZ)); + private long getOreVeinKey(int chunkX, int chunkZ) { + return Utils.chunkCoordsToKey(Utils.mapToCenterOreChunkCoord(chunkX), Utils.mapToCenterOreChunkCoord(chunkZ)); + } + + private long getUndergroundFluidKey(int chunkX, int chunkZ) { + return Utils.chunkCoordsToKey( + Utils.mapToCornerUndergroundFluidChunkCoord(chunkX), + Utils.mapToCornerUndergroundFluidChunkCoord(chunkZ)); + } + + public void toggleOreVein(int chunkX, int chunkZ) { + final long key = getOreVeinKey(chunkX, chunkZ); + final OreVeinPosition oreVeinPosition = oreChunks.get(key); + if (oreVeinPosition != null) { + oreVeinPosition.toggleDepleted(); + changedOrNewOreChunks.add(key); + markDirty(); + } } public UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) { - final ChunkCoordIntPair key = getOreVeinKey(oreVeinPosition.chunkX, oreVeinPosition.chunkZ); - if (oreChunks.containsKey(key) == false) { + final long key = getOreVeinKey(oreVeinPosition.chunkX, oreVeinPosition.chunkZ); + final OreVeinPosition storedOreVeinPosition = oreChunks.get(key); + if (storedOreVeinPosition == null) { oreChunks.put(key, oreVeinPosition); changedOrNewOreChunks.add(key); + markDirty(); return UpdateResult.New; } - final OreVeinPosition storedOreVeinPosition = oreChunks.get(key); if (storedOreVeinPosition.veinType != oreVeinPosition.veinType) { oreChunks.put(key, oreVeinPosition.joinDepletedState(storedOreVeinPosition)); changedOrNewOreChunks.add(key); + markDirty(); return UpdateResult.New; } return UpdateResult.AlreadyKnown; } - public void toggleOreVein(int chunkX, int chunkZ) { - final ChunkCoordIntPair key = getOreVeinKey(chunkX, chunkZ); - if (oreChunks.containsKey(key)) { - oreChunks.get(key).toggleDepleted(); - changedOrNewOreChunks.add(key); - } - } - - public OreVeinPosition getOreVein(int chunkX, int chunkZ) { - final ChunkCoordIntPair key = getOreVeinKey(chunkX, chunkZ); - return oreChunks.getOrDefault(key, new OreVeinPosition(dimensionId, chunkX, chunkZ, VeinType.NO_VEIN, true)); - } - - private ChunkCoordIntPair getUndergroundFluidKey(int chunkX, int chunkZ) { - return new ChunkCoordIntPair( - Utils.mapToCornerUndergroundFluidChunkCoord(chunkX), - Utils.mapToCornerUndergroundFluidChunkCoord(chunkZ)); - } - public UpdateResult putUndergroundFluid(final UndergroundFluidPosition undergroundFluid) { - final ChunkCoordIntPair key = getUndergroundFluidKey(undergroundFluid.chunkX, undergroundFluid.chunkZ); - if (undergroundFluids.containsKey(key) == false) { + final long key = getUndergroundFluidKey(undergroundFluid.chunkX, undergroundFluid.chunkZ); + final UndergroundFluidPosition storedUndergroundFluid = undergroundFluids.get(key); + if (storedUndergroundFluid == null) { changedOrNewUndergroundFluids.add(key); undergroundFluids.put(key, undergroundFluid); + markDirty(); return UpdateResult.New; - } else if (undergroundFluids.get(key).equals(undergroundFluid) == false) { + } else if (!storedUndergroundFluid.equals(undergroundFluid)) { changedOrNewUndergroundFluids.add(key); undergroundFluids.put(key, undergroundFluid); + markDirty(); return UpdateResult.Updated; } return UpdateResult.AlreadyKnown; } + public OreVeinPosition getOreVein(int chunkX, int chunkZ) { + final long key = getOreVeinKey(chunkX, chunkZ); + return oreChunks.getOrDefault(key, new OreVeinPosition(dimensionId, chunkX, chunkZ, VeinType.NO_VEIN, true)); + } + public UndergroundFluidPosition getUndergroundFluid(int chunkX, int chunkZ) { - final ChunkCoordIntPair key = getUndergroundFluidKey(chunkX, chunkZ); + final long key = getUndergroundFluidKey(chunkX, chunkZ); return undergroundFluids .getOrDefault(key, UndergroundFluidPosition.getNotProspected(dimensionId, chunkX, chunkZ)); } @@ -198,6 +233,14 @@ public Collection getAllUndergroundFluids() { return undergroundFluids.values(); } + public boolean isDirty() { + return isDirty; + } + + public void markDirty() { + isDirty = true; + } + /** * Reset selected veins; these veins need not be present. Input coords are in chunk coordinates, NOT block coords. * Will not error on bad input, but it also probably won't do anything useful. startChunks should be less than their @@ -209,8 +252,7 @@ public void clearOreVeins(int startChunkX, int startChunkZ, int endChunkX, int e // This method iterates for each chunk mapped. In many cases, it is probably faster to iterate over chunks in // the area to be cleared instead. i.e. if (chunksInClearArea < totalChunksMapped) {useAltIterator()}. If // someone calls this enough to make it a problem, they can add that. - oreChunks.entrySet().removeIf(entry -> { - + oreChunks.long2ObjectEntrySet().removeIf(entry -> { OreVeinPosition val = entry.getValue(); final boolean withinX = val.chunkX >= startChunkX && val.chunkX <= endChunkX; final boolean withinZ = val.chunkZ >= startChunkZ && val.chunkZ <= endChunkZ; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java index 1005180c..bd712516 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java @@ -32,8 +32,7 @@ public String getCommandUsage(ICommandSender sender) { @Override public void processCommand(ICommandSender sender, String[] parameters) { MinecraftServer server; - if (sender instanceof EntityPlayerMP) { - EntityPlayerMP player = (EntityPlayerMP) sender; + if (sender instanceof EntityPlayerMP player) { server = player.mcServer; } else { server = FMLServerHandler.instance().getServer(); @@ -64,8 +63,7 @@ public void processCommand(ICommandSender sender, String[] parameters) { @Override public boolean canCommandSenderUseCommand(ICommandSender sender) { // Only SP owner, or OP are allowed - if (sender instanceof EntityPlayerMP) { - EntityPlayerMP player = (EntityPlayerMP) sender; + if (sender instanceof EntityPlayerMP player) { if (Objects.equals(player.mcServer.getServerOwner(), sender.getCommandSenderName())) { return true; } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java index dbb92a6f..03ca3ec8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java @@ -77,9 +77,7 @@ public void processCommand(ICommandSender sender, String[] parameters) { public boolean canCommandSenderUseCommand(ICommandSender sender) { // Only SP owner, or OP are allowed - if (sender instanceof EntityPlayerMP) { - - EntityPlayerMP player = (EntityPlayerMP) sender; + if (sender instanceof EntityPlayerMP player) { if (Objects.equals(player.mcServer.getServerOwner(), sender.getCommandSenderName())) { return true; } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java b/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java index 0845907f..c8c1fe56 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java @@ -26,8 +26,7 @@ public void addClientProspectionData(String uuid, List oreVeins final int newEntryBytes = oreVeins.size() * OreVeinPosition.MAX_BYTES + undergroundFluids.size() * UndergroundFluidPosition.BYTES; - while (getUsedMemory() > (Config.maxTransferCacheSizeMB << 20) - newEntryBytes - && timestamp.isEmpty() == false) { + while (getUsedMemory() > (Config.maxTransferCacheSizeMB << 20) - newEntryBytes && !timestamp.isEmpty()) { String oldestUUID = timestamp.remove(); sharedOreVeins.remove(oldestUUID); sharedUndergroundFluids.remove(oldestUUID); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index 563c48d5..447e8a99 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -7,6 +7,7 @@ import java.util.Map; import java.util.Set; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ChunkCoordinates; import com.sinthoras.visualprospecting.Tags; @@ -17,25 +18,50 @@ public abstract class WorldCache { protected final Map dimensions = new HashMap<>(); private boolean needsSaving = false; - protected File oreVeinCacheDirectory; - protected File undergroundFluidCacheDirectory; + protected File worldCache; private boolean isLoaded = false; protected abstract File getStorageDirectory(); public boolean loadVeinCache(String worldId) { - if (isLoaded) { - return true; - } + if (isLoaded) return true; isLoaded = true; - final File worldCacheDirectory = new File(getStorageDirectory(), worldId); - oreVeinCacheDirectory = new File(worldCacheDirectory, Tags.OREVEIN_DIR); - undergroundFluidCacheDirectory = new File(worldCacheDirectory, Tags.UNDERGROUNDFLUID_DIR); - oreVeinCacheDirectory.mkdirs(); - undergroundFluidCacheDirectory.mkdirs(); - final Map oreVeinDimensionBuffers = Utils.getDIMFiles(oreVeinCacheDirectory); + worldCache = new File(getStorageDirectory(), worldId); + + if (loadLegacyVeinCache(worldCache)) return true; + + final File[] dimensionFiles = worldCache.listFiles(); + if (dimensionFiles == null) return false; + + for (File dimensionFile : dimensionFiles) { + final String fileName = dimensionFile.getName(); + if (!dimensionFile.isFile() || !fileName.endsWith(".dat")) { + continue; + } + + final NBTTagCompound dimCompound = Utils.readNBT(dimensionFile); + if (dimCompound == null) continue; + + final int dimensionId = dimCompound.getInteger("dim"); + final DimensionCache dimension = new DimensionCache(dimensionId); + dimension.loadFromNbt(dimCompound); + dimensions.put(dimensionId, dimension); + } + + return true; + } + + private boolean loadLegacyVeinCache(File worldCacheDirectory) { + File oreVeinCacheDirectory = new File(worldCacheDirectory, Tags.OREVEIN_DIR); + File undergroundFluidCacheDirectory = new File(worldCacheDirectory, Tags.UNDERGROUNDFLUID_DIR); + + if (!oreVeinCacheDirectory.exists() && !undergroundFluidCacheDirectory.exists()) { + return false; + } + + final Map oreVeinDimensionBuffers = Utils.getLegacyDimFiles(oreVeinCacheDirectory); final Map undergroundFluidDimensionBuffers = Utils - .getDIMFiles(undergroundFluidCacheDirectory); + .getLegacyDimFiles(undergroundFluidCacheDirectory); final Set dimensionsIds = new HashSet<>(); dimensionsIds.addAll(oreVeinDimensionBuffers.keySet()); dimensionsIds.addAll(undergroundFluidDimensionBuffers.keySet()); @@ -49,29 +75,28 @@ public boolean loadVeinCache(String worldId) { if (dimension == null) { dimension = new DimensionCache(dimensionId); } - dimension.loadCache( + dimension.loadLegacy( oreVeinDimensionBuffers.get(dimensionId), undergroundFluidDimensionBuffers.get(dimensionId)); + dimension.markDirty(); dimensions.put(dimensionId, dimension); } + + Utils.deleteDirectoryRecursively(oreVeinCacheDirectory); + Utils.deleteDirectoryRecursively(undergroundFluidCacheDirectory); + needsSaving = true; + saveVeinCache(); return true; } public void saveVeinCache() { if (needsSaving) { for (DimensionCache dimension : dimensions.values()) { - final ByteBuffer oreVeinBuffer = dimension.saveOreChunks(); - if (oreVeinBuffer != null) { - Utils.appendToFile( - new File(oreVeinCacheDirectory.toPath() + "/DIM" + dimension.dimensionId), - oreVeinBuffer); - } - final ByteBuffer undergroundFluidBuffer = dimension.saveUndergroundFluids(); - if (undergroundFluidBuffer != null) { - Utils.appendToFile( - new File(undergroundFluidCacheDirectory.toPath() + "/DIM" + dimension.dimensionId), - undergroundFluidBuffer); + if (!dimension.isDirty()) { + continue; } + File dimFile = new File(worldCache.toPath() + "/DIM" + dimension.dimensionId + ".dat"); + Utils.writeNBT(dimFile, dimension.saveToNbt()); } needsSaving = false; } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java index 24550d11..19edd88b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java @@ -1,41 +1,80 @@ package com.sinthoras.visualprospecting.database.cachebuilder; -import java.util.HashSet; -import java.util.Set; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; -import io.xol.enklume.nbt.NBTCompound; -import io.xol.enklume.nbt.NBTList; -import io.xol.enklume.nbt.NBTNamed; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSet; +import it.unimi.dsi.fastutil.shorts.Short2IntArrayMap; +import it.unimi.dsi.fastutil.shorts.Short2IntMap; +import it.unimi.dsi.fastutil.shorts.ShortArrayList; +import it.unimi.dsi.fastutil.shorts.ShortList; // A slim, but faster version to identify >90% of veins public class ChunkAnalysis { - private final Set ores = new HashSet<>(); - private final Set matchedVeins = new HashSet<>(); + private final ObjectSet matchedVeins = new ObjectOpenHashSet<>(); + private final Short2IntMap oreCounts = new Short2IntArrayMap(); private int minVeinBlockY = VP.minecraftWorldHeight; + private short primaryMeta, secondaryMeta; - public void processMinecraftChunk(final NBTCompound chunkRoot) { - for (final NBTNamed tileEntity : ((NBTList) chunkRoot.getTag("Level.TileEntities")).elements) { - final GregTechOre gtOre = new GregTechOre((NBTCompound) tileEntity); - if (gtOre.isValidGTOre) { - ores.add(gtOre.metaData); - if (minVeinBlockY > gtOre.blockY) { - minVeinBlockY = gtOre.blockY; - } + public void processMinecraftChunk(final NBTTagList tileEntities) { + if (tileEntities == null || tileEntities.tagCount() == 0) return; + for (int i = 0; i < tileEntities.tagCount(); i++) { + final NBTTagCompound tile = tileEntities.getCompoundTagAt(i); + if (tile == null || !tile.hasKey("m")) continue; + + if (!"GT_TileEntity_Ores".equals(tile.getString("id"))) { + continue; } + + short meta = tile.getShort("m"); + if (Utils.isSmallOreId(meta) || meta == 0) continue; + + meta = Utils.oreIdToMaterialId(meta); + final int blockY = tile.getInteger("y"); + + oreCounts.put(meta, oreCounts.get(meta) + 1); + if (minVeinBlockY > blockY) { + minVeinBlockY = blockY; + } + } + + if (oreCounts.size() == 1) { + primaryMeta = secondaryMeta = oreCounts.keySet().iterator().nextShort(); + } else if (oreCounts.size() > 1) { + ShortList metaCounts = new ShortArrayList(oreCounts.keySet()); + metaCounts.sort((a, b) -> Integer.compare(oreCounts.get(b), oreCounts.get(a))); + primaryMeta = metaCounts.getShort(0); + secondaryMeta = metaCounts.getShort(1); } } public boolean matchesSingleVein() { - for (VeinType veinType : VeinTypeCaching.veinTypes) { - if (veinType.matches(ores)) { - matchedVeins.add(veinType); - } + if (oreCounts.isEmpty()) return true; + if (oreCounts.size() > 4) return false; + ObjectSet veins = VeinTypeCaching.getVeinTypesForPrimaryMeta(primaryMeta); + if (veins.isEmpty()) return trySecondaryMeta(); + + veins.stream().filter(veinType -> veinType.matches(oreCounts.keySet())).forEach(matchedVeins::add); + + if (matchedVeins.size() != 1) { + matchedVeins.clear(); + return trySecondaryMeta(); } + + return true; + } + + private boolean trySecondaryMeta() { + if (secondaryMeta == primaryMeta) return false; + VeinTypeCaching.getVeinTypesForPrimaryMeta(secondaryMeta).stream() + .filter(veinType -> veinType.matches(oreCounts.keySet())).forEach(matchedVeins::add); return matchedVeins.size() <= 1; } @@ -44,7 +83,7 @@ public VeinType getMatchedVein() { if (matchedVeins.isEmpty()) { return VeinType.NO_VEIN; } - return matchedVeins.stream().findAny().get(); + return matchedVeins.iterator().next(); } public int getVeinBlockY() { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index 4d5224a8..51a353b7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -1,13 +1,15 @@ package com.sinthoras.visualprospecting.database.cachebuilder; import java.util.Comparator; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.IntStream; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.OreVeinPosition; @@ -15,9 +17,8 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; -import io.xol.enklume.nbt.NBTCompound; -import io.xol.enklume.nbt.NBTList; -import io.xol.enklume.nbt.NBTNamed; +import it.unimi.dsi.fastutil.shorts.Short2IntMap; +import it.unimi.dsi.fastutil.shorts.Short2IntOpenHashMap; // Slower, but more sophisticated approach to identify overlapping veins public class DetailedChunkAnalysis { @@ -26,8 +27,7 @@ public class DetailedChunkAnalysis { public final int chunkX; public final int chunkZ; // For each height we count how often a ore (short) has occured - @SuppressWarnings("unchecked") - private final Map[] oresPerY = new HashMap[VP.minecraftWorldHeight]; + private final Short2IntMap[] oresPerY = new Short2IntOpenHashMap[VP.minecraftWorldHeight]; public DetailedChunkAnalysis(int dimensionId, int chunkX, int chunkZ) { this.dimensionId = dimensionId; @@ -35,18 +35,32 @@ public DetailedChunkAnalysis(int dimensionId, int chunkX, int chunkZ) { this.chunkZ = chunkZ; } - public void processMinecraftChunk(final NBTCompound chunkRoot) { - for (final NBTNamed tileEntity : ((NBTList) chunkRoot.getTag("Level.TileEntities")).elements) { - final GregTechOre gtOre = new GregTechOre((NBTCompound) tileEntity); - if (gtOre.isValidGTOre) { - if (oresPerY[gtOre.blockY] == null) { - oresPerY[gtOre.blockY] = new HashMap<>(); - } - if (oresPerY[gtOre.blockY].containsKey(gtOre.metaData) == false) { - oresPerY[gtOre.blockY].put(gtOre.metaData, 0); - } - oresPerY[gtOre.blockY].put(gtOre.metaData, oresPerY[gtOre.blockY].get(gtOre.metaData) + 1); + public void processMinecraftChunk(final NBTTagList tileEntities) { + if (tileEntities == null || tileEntities.tagCount() == 0) return; + for (int i = 0; i < tileEntities.tagCount(); i++) { + final NBTTagCompound tile = tileEntities.getCompoundTagAt(i); + if (tile == null || !tile.hasKey("id")) continue; + final String tagId = tile.getString("id"); + + if (!tagId.equals("GT_TileEntity_Ores")) { + continue; } + + short meta = tile.getShort("m"); + if (Utils.isSmallOreId(meta) || meta == 0) continue; + + meta = Utils.oreIdToMaterialId(meta); + final int blockY = tile.getInteger("y"); + + if (oresPerY[blockY] == null) { + oresPerY[blockY] = new Short2IntOpenHashMap(); + } + + if (!oresPerY[blockY].containsKey(meta)) { + oresPerY[blockY].put(meta, 0); + } + + oresPerY[blockY].put(meta, oresPerY[blockY].get(meta) + 1); } } @@ -131,14 +145,17 @@ public void cleanUpWithNeighbors(final Map veinChunkY) { public VeinType getMatchedVein() { final Set matchedVeins = new HashSet<>(); - final Map allOres = new HashMap<>(); - for (Map oreLevel : oresPerY) { - if (oreLevel != null && oreLevel.isEmpty() == false) { - oreLevel.forEach((metaData, numberOfBlocks) -> allOres.merge(metaData, numberOfBlocks, Integer::sum)); + final Short2IntMap allOres = new Short2IntOpenHashMap(); + for (Short2IntMap oreLevel : oresPerY) { + if (oreLevel == null || oreLevel.isEmpty()) continue; + for (Short2IntMap.Entry entry : oreLevel.short2IntEntrySet()) { + short metaData = entry.getShortKey(); + int numberOfBlocks = entry.getIntValue(); + allOres.merge(metaData, numberOfBlocks, Integer::sum); } } - final Optional dominantOre = allOres.entrySet().stream() + final Optional dominantOre = allOres.short2IntEntrySet().stream() .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(Map.Entry::getKey).findFirst(); if (dominantOre.isPresent()) { for (VeinType veinType : VeinTypeCaching.veinTypes) { @@ -149,14 +166,14 @@ public VeinType getMatchedVein() { } if (matchedVeins.size() == 1) { - return matchedVeins.stream().findAny().get(); + return matchedVeins.iterator().next(); } else if (matchedVeins.size() >= 2) { matchedVeins.removeIf( - veinType -> IntStream.range(veinType.minBlockY, veinType.maxBlockY).boxed() + veinType -> IntStream.range(veinType.minBlockY, veinType.maxBlockY) .noneMatch(blockY -> isOreVeinGeneratedAtHeight(veinType, blockY))); if (matchedVeins.size() == 1) { - return matchedVeins.stream().findAny().get(); + return matchedVeins.iterator().next(); } } return VeinType.NO_VEIN; @@ -165,7 +182,7 @@ public VeinType getMatchedVein() { private boolean isOreVeinGeneratedAtHeight(VeinType veinType, int blockY) { for (int layer = 0; layer < VeinType.veinHeight; layer++) { if (oresPerY[blockY + layer] == null - || oresPerY[blockY + layer].keySet().containsAll(veinType.getOresAtLayer(layer)) == false) { + || !oresPerY[blockY + layer].keySet().containsAll(veinType.getOresAtLayer(layer))) { return false; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java index 52182062..0f18ceae 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java @@ -2,22 +2,20 @@ import java.io.File; import java.io.IOException; -import java.util.List; +import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; import java.util.zip.DataFormatException; +import net.minecraft.nbt.NBTTagList; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.veintypes.VeinType; -import io.xol.enklume.MinecraftRegion; -import io.xol.enklume.MinecraftWorld; -import io.xol.enklume.nbt.NBTCompound; - public class DimensionAnalysis { public final int dimensionId; @@ -28,12 +26,12 @@ public DimensionAnalysis(int dimensionId) { private interface IChunkHandler { - void processChunk(NBTCompound root, int chunkX, int chunkZ); + void processChunk(NBTTagList root, int chunkX, int chunkZ); } - public void processMinecraftWorld(MinecraftWorld world) throws IOException { + public void processMinecraftWorld(Collection regionFiles) { + if (regionFiles.isEmpty()) return; final Map veinBlockY = new ConcurrentHashMap<>(); - final List regionFiles = world.getAllRegionFiles(dimensionId); final long dimensionSizeMB = regionFiles.stream().mapToLong(File::length).sum() >> 20; if (dimensionSizeMB <= Config.maxDimensionSizeMBForFastScanning) { @@ -113,26 +111,24 @@ private void executeForEachGeneratedOreChunk(File regionFile, IChunkHandler chun final String[] parts = regionFile.getName().split("\\."); final int regionChunkX = Integer.parseInt(parts[1]) << 5; final int regionChunkZ = Integer.parseInt(parts[2]) << 5; - final MinecraftRegion region = new MinecraftRegion(regionFile); - for (int localChunkX = 0; localChunkX < VP.chunksPerRegionFileX; localChunkX++) { - for (int localChunkZ = 0; localChunkZ < VP.chunksPerRegionFileZ; localChunkZ++) { - final int chunkX = regionChunkX + localChunkX; - final int chunkZ = regionChunkZ + localChunkZ; - - // Only process ore chunks - if (chunkX == Utils.mapToCenterOreChunkCoord(chunkX) - && chunkZ == Utils.mapToCenterOreChunkCoord(chunkZ)) { - // Helpful read about 'root' structure: https://minecraft.fandom.com/wiki/Chunk_format - final NBTCompound root = region.getChunk(localChunkX, localChunkZ).getRootTag(); - - // root == null occurs when a chunk is not yet generated - if (root != null) { - chunkHandler.processChunk(root, chunkX, chunkZ); + try (RegionReader region = new RegionReader(regionFile)) { + for (int localChunkX = 0; localChunkX < VP.chunksPerRegionFileX; localChunkX++) { + for (int localChunkZ = 0; localChunkZ < VP.chunksPerRegionFileZ; localChunkZ++) { + final int chunkX = regionChunkX + localChunkX; + final int chunkZ = regionChunkZ + localChunkZ; + + // Only process ore chunks + if (chunkX == Utils.mapToCenterOreChunkCoord(chunkX) + && chunkZ == Utils.mapToCenterOreChunkCoord(chunkZ)) { + final NBTTagList chunkTiles = region.getChunkTiles(localChunkX, localChunkZ); + + if (chunkTiles != null) { + chunkHandler.processChunk(chunkTiles, chunkX, chunkZ); + } } } } } - region.close(); AnalysisProgressTracker.regionFileProcessed(); } catch (DataFormatException | IOException e) { AnalysisProgressTracker.notifyCorruptFile(regionFile); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java deleted file mode 100644 index 44c38765..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/GregTechOre.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.sinthoras.visualprospecting.database.cachebuilder; - -import static com.sinthoras.visualprospecting.Utils.isSmallOreId; -import static com.sinthoras.visualprospecting.Utils.oreIdToMaterialId; - -import io.xol.enklume.nbt.NBTCompound; -import io.xol.enklume.nbt.NBTInt; -import io.xol.enklume.nbt.NBTShort; -import io.xol.enklume.nbt.NBTString; - -public class GregTechOre { - - public final boolean isValidGTOre; - public final short metaData; - public final int blockY; - - public GregTechOre(NBTCompound tileEntity) { - final NBTString tagId = (NBTString) tileEntity.getTag("id"); - final NBTShort tagMeta = (NBTShort) tileEntity.getTag("m"); - final NBTInt tagBlockY = (NBTInt) tileEntity.getTag("y"); - - if (tagId != null && tagId.getText().equals("GT_TileEntity_Ores") - && tagBlockY != null - && tagMeta != null - && isSmallOreId(tagMeta.data) == false) { - metaData = oreIdToMaterialId(tagMeta.data); - isValidGTOre = true; - blockY = tagBlockY.data; - } else { - isValidGTOre = false; - metaData = 0; - blockY = 0; - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/RegionReader.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/RegionReader.java new file mode 100644 index 00000000..7432d3ea --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/RegionReader.java @@ -0,0 +1,80 @@ +package com.sinthoras.visualprospecting.database.cachebuilder; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.zip.DataFormatException; +import java.util.zip.InflaterInputStream; + +import javax.annotation.Nullable; + +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +public class RegionReader implements AutoCloseable { + + private final RandomAccessFile is; + + public RegionReader(File regionFile) throws IOException, DataFormatException { + is = new RandomAccessFile(regionFile, "r"); + } + + private int offset(int x, int z) { + return ((x & 31) + (z & 31) * 32); + } + + public @Nullable NBTTagCompound getChunk(int x, int z) throws DataFormatException, IOException { + return getChunkInternal(x, z); + } + + public @Nullable NBTTagList getChunkTiles(int x, int z) { + try { + NBTTagCompound chunk = getChunkInternal(x, z); + if (chunk == null) return null; + + NBTTagCompound level = chunk.getCompoundTag("Level"); + + if (level.hasKey("TileEntities")) { + return level.getTagList("TileEntities", 10); + } + return null; + } catch (DataFormatException | IOException e) { + e.printStackTrace(); + return null; + } + } + + private @Nullable NBTTagCompound getChunkInternal(int x, int z) throws DataFormatException, IOException { + int l = offset(x, z); + is.seek(l * 4L); + int location = (is.read() << 16) + (is.read() << 8) + is.read(); + int size = is.read(); + if (size > 0) { + // Chunk non-void, load it + is.seek(location * 4096L); + // Read 4-bytes of data length + int compressedLength = (is.read() << 24) | (is.read() << 16) | (is.read() << 8) | is.read(); + // Read compression mode + int compression = is.read(); + if (compression != 2) return null; + + byte[] compressedDataBuffer = new byte[compressedLength]; + is.readFully(compressedDataBuffer, 0, compressedLength); + try (DataInputStream chunkData = new DataInputStream( + new BufferedInputStream( + new InflaterInputStream( + new ByteArrayInputStream(compressedDataBuffer, 0, compressedLength))))) { + return CompressedStreamTools.read(chunkData); + } + } + return null; + } + + public void close() throws IOException { + is.close(); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java index 84b38f48..31067f0e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java @@ -2,24 +2,33 @@ import java.io.File; import java.io.IOException; -import java.util.Collections; -import java.util.List; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.stream.Stream; import java.util.zip.DataFormatException; import net.minecraft.util.ChunkCoordinates; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.DimensionManager; + +import org.apache.commons.io.FileUtils; -import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; -import io.xol.enklume.MinecraftWorld; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import it.unimi.dsi.fastutil.ints.IntSets; public class WorldAnalysis { - private final MinecraftWorld world; + private final File worldFolder; public WorldAnalysis(File worldDirectory) throws IOException { - world = new MinecraftWorld(worldDirectory); + this.worldFolder = worldDirectory; } public void cacheOverworldSpawnVeins(ChunkCoordinates spawn) throws IOException, DataFormatException { @@ -27,7 +36,7 @@ public void cacheOverworldSpawnVeins(ChunkCoordinates spawn) throws IOException, VP.info("Starting to parse world save to cache GT vein locations near spawn. This might take some time..."); ServerCache.instance.resetSpawnChunks(spawn, 0); - cacheVeins(Collections.singletonList(Tags.overworldId)); + cacheVeins(IntSets.singleton(0)); } public void cacheVeins() throws IOException, DataFormatException { @@ -35,16 +44,16 @@ public void cacheVeins() throws IOException, DataFormatException { VP.info("Starting to parse world save to cache GT vein locations. This might take some time..."); ServerCache.instance.reset(); - cacheVeins(world.getDimensionIds()); + cacheVeins(getDimensionIds()); } - private void cacheVeins(List dimensionIds) throws IOException, DataFormatException { + private void cacheVeins(IntSet dimensionIds) { AnalysisProgressTracker.setNumberOfDimensions(dimensionIds.size()); for (int dimensionId : dimensionIds) { - + final Collection regionFiles = getRegionFilesForDim(dimensionId); final DimensionAnalysis dimension = new DimensionAnalysis(dimensionId); - dimension.processMinecraftWorld(world); + dimension.processMinecraftWorld(regionFiles); AnalysisProgressTracker.dimensionProcessed(); } @@ -52,4 +61,34 @@ private void cacheVeins(List dimensionIds) throws IOException, DataForm VP.info("Saving ore vein cache..."); ServerCache.instance.saveVeinCache(); } + + public IntSet getDimensionIds() throws IOException { + IntSet dimensionIds = new IntOpenHashSet(); + dimensionIds.addAll(Arrays.asList(DimensionManager.getIDs())); + try (Stream files = Files.walk(worldFolder.toPath(), 1)) { + files.filter(Files::isDirectory).map(path -> path.getFileName().toString()) + .filter(path -> path.startsWith("DIM")).map(path -> path.substring(3)).forEach(dim -> { + try { + dimensionIds.add(Integer.parseInt(dim)); + } catch (NumberFormatException ignored) {} + }); + } + return dimensionIds; + } + + public Collection getRegionFilesForDim(int dimensionId) { + WorldServer world = DimensionManager.getWorld(dimensionId); + File dimRegionDir; + if (world != null) { + dimRegionDir = new File(world.getChunkSaveLocation(), "region"); + } else { + final String subfolder = dimensionId == 0 ? "" : "/DIM" + dimensionId; + dimRegionDir = new File(worldFolder, subfolder + "/region"); + } + + if (dimRegionDir.exists()) { + return FileUtils.listFiles(dimRegionDir, new String[] { "mca" }, false); + } + return new ArrayList<>(); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java index c0da6ed2..3f218a4f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java @@ -2,29 +2,55 @@ import static bartworks.util.BWColorUtil.getColorFromRGBArray; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IIcon; import bartworks.system.material.Werkstoff; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.enums.OrePrefixes; +import it.unimi.dsi.fastutil.shorts.ShortCollection; public class BartworksOreMaterialProvider implements IOreMaterialProvider { private final Werkstoff material; + private final int primaryOreColor; + private final String primaryOreName; + private IIcon primaryOreIcon; public BartworksOreMaterialProvider(Werkstoff material) { this.material = material; + this.primaryOreColor = getColorFromRGBArray(material.getRGBA()); + this.primaryOreName = material.getLocalizedName(); } @Override @SideOnly(Side.CLIENT) public IIcon getIcon() { - return material.getTexSet().mTextures[OrePrefixes.ore.mTextureIndex].getIcon(); + if (primaryOreIcon == null) { + primaryOreIcon = material.getTexSet().mTextures[OrePrefixes.ore.mTextureIndex].getIcon(); + } + return primaryOreIcon; } @Override public int getColor() { - return getColorFromRGBArray(material.getRGBA()); + return primaryOreColor; + } + + @Override + public String getLocalizedName() { + return primaryOreName; + } + + @Override + public List getContainedOres(ShortCollection ores) { + return ores.intStream().mapToObj(metaData -> Werkstoff.werkstoffHashMap.get((short) metaData)) + .filter(Objects::nonNull).map(material -> EnumChatFormatting.GRAY + material.getLocalizedName()) + .collect(Collectors.toList()); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java index f4cdcb62..b4e574a0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java @@ -1,28 +1,54 @@ package com.sinthoras.visualprospecting.database.veintypes; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IIcon; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.GregTechAPI; import gregtech.api.enums.Materials; import gregtech.api.enums.OrePrefixes; +import it.unimi.dsi.fastutil.shorts.ShortCollection; public class GregTechOreMaterialProvider implements IOreMaterialProvider { private final Materials material; + private final int primaryOreColor; + private IIcon primaryOreIcon; + private final String primaryOreName; public GregTechOreMaterialProvider(Materials material) { this.material = material; + this.primaryOreColor = (material.mRGBa[0] << 16) | (material.mRGBa[1]) << 8 | material.mRGBa[2]; + this.primaryOreName = material.mLocalizedName; } @Override @SideOnly(Side.CLIENT) public IIcon getIcon() { - return material.mIconSet.mTextures[OrePrefixes.ore.mTextureIndex].getIcon(); + if (primaryOreIcon == null) { + primaryOreIcon = material.mIconSet.mTextures[OrePrefixes.ore.mTextureIndex].getIcon(); + } + return primaryOreIcon; } @Override public int getColor() { - return (material.mRGBa[0] << 16) | (material.mRGBa[1]) << 8 | material.mRGBa[2]; + return primaryOreColor; + } + + @Override + public String getLocalizedName() { + return primaryOreName; + } + + @Override + public List getContainedOres(ShortCollection ores) { + return ores.intStream().mapToObj(metaData -> GregTechAPI.sGeneratedMaterials[metaData]).filter(Objects::nonNull) + .map(material -> EnumChatFormatting.GRAY + material.mLocalizedName).collect(Collectors.toList()); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java index 2e8b24f1..173f4c67 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java @@ -1,9 +1,12 @@ package com.sinthoras.visualprospecting.database.veintypes; +import java.util.List; + import net.minecraft.util.IIcon; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.shorts.ShortCollection; public interface IOreMaterialProvider { @@ -11,4 +14,8 @@ public interface IOreMaterialProvider { IIcon getIcon(); int getColor(); + + String getLocalizedName(); + + List getContainedOres(ShortCollection ores); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 1f3a3da1..9d73ba36 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -1,16 +1,13 @@ package com.sinthoras.visualprospecting.database.veintypes; -import java.util.HashSet; +import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import net.minecraft.util.EnumChatFormatting; import com.sinthoras.visualprospecting.Tags; -import gregtech.api.GregTechAPI; +import it.unimi.dsi.fastutil.shorts.ShortCollection; +import it.unimi.dsi.fastutil.shorts.ShortOpenHashSet; +import it.unimi.dsi.fastutil.shorts.ShortSet; public class VeinType { @@ -26,8 +23,10 @@ public class VeinType { public final short sporadicOreMeta; public final int minBlockY; public final int maxBlockY; - public final Set oresAsSet; + public final ShortSet oresAsSet = new ShortOpenHashSet(); + private final List containedOres = new ArrayList<>(); private boolean isHighlighted = true; + private String primaryOreName = ""; // Available after VisualProspecting post GT initialization public static final VeinType NO_VEIN = new VeinType( @@ -46,24 +45,23 @@ public VeinType(String name, IOreMaterialProvider oreMaterialProvider, int block this.name = name; this.oreMaterialProvider = oreMaterialProvider; this.blockSize = blockSize; - this.primaryOreMeta = primaryOreMeta; - this.secondaryOreMeta = secondaryOreMeta; - this.inBetweenOreMeta = inBetweenOreMeta; - this.sporadicOreMeta = sporadicOreMeta; this.minBlockY = minBlockY; this.maxBlockY = maxBlockY; - oresAsSet = new HashSet<>(); - oresAsSet.add(primaryOreMeta); - oresAsSet.add(secondaryOreMeta); - oresAsSet.add(inBetweenOreMeta); - oresAsSet.add(sporadicOreMeta); + oresAsSet.add(this.primaryOreMeta = primaryOreMeta); + oresAsSet.add(this.secondaryOreMeta = secondaryOreMeta); + oresAsSet.add(this.inBetweenOreMeta = inBetweenOreMeta); + oresAsSet.add(this.sporadicOreMeta = sporadicOreMeta); + if (oreMaterialProvider != null) { + containedOres.addAll(oreMaterialProvider.getContainedOres(oresAsSet)); + primaryOreName = oreMaterialProvider.getLocalizedName(); + } } - public boolean matches(Set foundOres) { + public boolean matches(ShortCollection foundOres) { return foundOres.containsAll(oresAsSet); } - public boolean matchesWithSpecificPrimaryOrSecondary(Set foundOres, short specificMeta) { + public boolean matchesWithSpecificPrimaryOrSecondary(ShortCollection foundOres, short specificMeta) { return (primaryOreMeta == specificMeta || secondaryOreMeta == specificMeta) && foundOres.containsAll(oresAsSet); } @@ -83,12 +81,15 @@ public boolean containsOre(short oreMetaData) { } public List getOreMaterialNames() { - return oresAsSet.stream().map(metaData -> GregTechAPI.sGeneratedMaterials[metaData]).filter(Objects::nonNull) - .map(material -> EnumChatFormatting.GRAY + material.mLocalizedName).collect(Collectors.toList()); + return containedOres; + } + + public String getPrimaryOreName() { + return primaryOreName; } - public Set getOresAtLayer(int layerBlockY) { - final Set result = new HashSet<>(); + public ShortSet getOresAtLayer(int layerBlockY) { + final ShortSet result = new ShortOpenHashSet(); switch (layerBlockY) { case 0: case 1: diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index afdf346c..855c42f8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -3,13 +3,10 @@ import static com.sinthoras.visualprospecting.Utils.*; import java.io.File; -import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.OptionalInt; import java.util.regex.Pattern; import net.minecraft.client.resources.I18n; @@ -27,14 +24,21 @@ import gregtech.api.GregTechAPI; import gregtech.api.enums.Materials; import gregtech.common.WorldgenGTOreLayer; +import it.unimi.dsi.fastutil.objects.Object2ShortMap; +import it.unimi.dsi.fastutil.objects.Object2ShortOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSet; +import it.unimi.dsi.fastutil.objects.ObjectSets; +import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; +import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; public class VeinTypeCaching implements Runnable { - private static BiMap veinTypeLookupTableForIds = HashBiMap.create(); - private static Map veinTypeLookupTableForNames = new HashMap<>(); - private static Map veinTypeStorageInfo; - public static List veinTypes; - public static Set largeVeinOres; + private static final BiMap veinTypeLookupTableForIds = HashBiMap.create(); + private static final Map veinTypeLookupTableForNames = new HashMap<>(); + private static final Object2ShortMap veinTypeStorageInfo = new Object2ShortOpenHashMap<>(); + private static final Short2ObjectMap> primaryMetaToVeinType = new Short2ObjectOpenHashMap<>(); + public static ObjectSet veinTypes; private static int longesOreName = 0; // BartWorks initializes veins in FML preInit @@ -43,8 +47,7 @@ public class VeinTypeCaching implements Runnable { // GregTech initializes veins in a thread in FML postInit // Therefore, this method must be called after GregTech postInit public void run() { - veinTypes = new ArrayList<>(); - largeVeinOres = new HashSet<>(); + veinTypes = new ObjectOpenHashSet<>(); veinTypes.add(VeinType.NO_VEIN); for (WorldgenGTOreLayer vein : WorldgenGTOreLayer.sList) { @@ -52,7 +55,6 @@ public void run() { break; } final Materials material = getGregTechMaterial(vein.mPrimaryMeta); - veinTypes.add( new VeinType( vein.mWorldGenName, @@ -68,60 +70,41 @@ public void run() { Math.min(255, vein.mMaxY - 6))); } - if (isBartworksInstalled()) { - for (BWOreLayer vein : BWOreLayer.sList) { - final IOreMaterialProvider oreMaterialProvider = (vein.bwOres & 0b1000) == 0 - ? new GregTechOreMaterialProvider(getGregTechMaterial((short) vein.mPrimaryMeta)) - : new BartworksOreMaterialProvider(Werkstoff.werkstoffHashMap.get((short) vein.mPrimaryMeta)); - - veinTypes.add( - new VeinType( - vein.mWorldGenName, - oreMaterialProvider, - vein.mSize, - (short) vein.mPrimaryMeta, - (short) vein.mSecondaryMeta, - (short) vein.mBetweenMeta, - (short) vein.mSporadicMeta, - Math.max(0, vein.mMinY), - Math.min(255, vein.mMaxY))); - } + for (BWOreLayer vein : BWOreLayer.sList) { + final IOreMaterialProvider oreMaterialProvider = (vein.bwOres & 0b1000) == 0 + ? new GregTechOreMaterialProvider(getGregTechMaterial((short) vein.mPrimaryMeta)) + : new BartworksOreMaterialProvider(Werkstoff.werkstoffHashMap.get((short) vein.mPrimaryMeta)); + veinTypes.add( + new VeinType( + vein.mWorldGenName, + oreMaterialProvider, + vein.mSize, + (short) vein.mPrimaryMeta, + (short) vein.mSecondaryMeta, + (short) vein.mBetweenMeta, + (short) vein.mSporadicMeta, + Math.max(0, vein.mMinY), + Math.min(255, vein.mMaxY))); } // Assign veinTypeIds for efficient storage loadVeinTypeStorageInfo(); - final Optional maxVeinTypeIdOptional = veinTypeStorageInfo.values().stream().max(Short::compare); - short maxVeinTypeId = maxVeinTypeIdOptional.isPresent() ? maxVeinTypeIdOptional.get() : 0; + final OptionalInt maxVeinTypeIdOptional = veinTypeStorageInfo.values().intStream().max(); + short maxVeinTypeId = (short) (maxVeinTypeIdOptional.orElse(0)); for (VeinType veinType : veinTypes) { - if (veinTypeStorageInfo.containsKey(veinType.name)) { - veinType.veinId = veinTypeStorageInfo.get(veinType.name); - } else { - maxVeinTypeId++; - veinType.veinId = maxVeinTypeId; - veinTypeStorageInfo.put(veinType.name, veinType.veinId); - } - // Build LUT (id <-> object) + veinType.veinId = veinTypeStorageInfo.getOrDefault(veinType.name, ++maxVeinTypeId); + veinTypeStorageInfo.putIfAbsent(veinType.name, veinType.veinId); veinTypeLookupTableForIds.put(veinType.veinId, veinType); - - // Build LUT (name -> object) veinTypeLookupTableForNames.put(veinType.name, veinType); - - // Build large vein LUT - if (veinType.canOverlapIntoNeighborOreChunk()) { - largeVeinOres.add(veinType.primaryOreMeta); - largeVeinOres.add(veinType.secondaryOreMeta); - largeVeinOres.add(veinType.inBetweenOreMeta); - largeVeinOres.add(veinType.sporadicOreMeta); - } + primaryMetaToVeinType.computeIfAbsent(veinType.primaryOreMeta, k -> new ObjectOpenHashSet<>()) + .add(veinType); } saveVeinTypeStorageInfo(); for (VeinType veinType : veinTypes) { - if (veinType.name.length() > longesOreName) { - longesOreName = veinType.name.length(); - } + longesOreName = Math.max(longesOreName, veinType.name.length()); } } @@ -152,12 +135,18 @@ public static VeinType getVeinType(String veinTypeName) { private static File getVeinTypeStorageInfoFile() { final File directory = Utils.getSubDirectory(Tags.VISUALPROSPECTING_DIR); + // noinspection ResultOfMethodCallIgnored directory.mkdirs(); return new File(directory, "veintypesLUT"); } + public static ObjectSet getVeinTypesForPrimaryMeta(short primaryMeta) { + + return primaryMetaToVeinType.getOrDefault(primaryMeta, ObjectSets.emptySet()); + } + private static void loadVeinTypeStorageInfo() { - veinTypeStorageInfo = Utils.readFileToMap(getVeinTypeStorageInfoFile()); + veinTypeStorageInfo.putAll(Utils.readFileToMap(getVeinTypeStorageInfoFile())); } private static void saveVeinTypeStorageInfo() { @@ -171,18 +160,17 @@ public static void recalculateNEISearch() { final Pattern filterPattern = SearchField.getPattern(searchString); for (VeinType veinType : veinTypes) { - if (veinType != VeinType.NO_VEIN) { - if (isSearchActive && !searchString.equals("")) { - List searchableStrings = veinType.getOreMaterialNames(); - searchableStrings.add(I18n.format(veinType.name)); - final boolean match = searchableStrings.stream() - .map(EnumChatFormatting::getTextWithoutFormattingCodes).map(String::toLowerCase) - .anyMatch(searchableString -> filterPattern.matcher(searchableString).find()); - - veinType.setNEISearchHeighlight(match); - } else { - veinType.setNEISearchHeighlight(true); - } + if (veinType == VeinType.NO_VEIN) continue; + if (isSearchActive && !searchString.isEmpty()) { + List searchableStrings = veinType.getOreMaterialNames(); + searchableStrings.add(I18n.format(veinType.name)); + final boolean match = searchableStrings.stream() + .map(EnumChatFormatting::getTextWithoutFormattingCodes).map(String::toLowerCase) + .anyMatch(searchableString -> filterPattern.matcher(searchableString).find()); + + veinType.setNEISearchHeighlight(match); + } else { + veinType.setNEISearchHeighlight(true); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java index 000cd1de..3124c913 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java @@ -4,7 +4,6 @@ import net.minecraft.world.ChunkCoordIntPair; -import com.sinthoras.visualprospecting.ServerTranslations; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.veintypes.VeinType; @@ -23,7 +22,7 @@ public Optional getVeinName(int dimensionId, ChunkCoordIntPair coordinat // capture which language the original cover attaching player is using, maybe. (I think this requires // reflection, of course. Why should things be easy?) Even then, it wouldn't help in a multiplayer scenario // with users having different locales. - return Optional.of(ServerTranslations.getEnglishLocalization(oreVein.veinType)); + return Optional.of(oreVein.veinType.getPrimaryOreName()); } else { return Optional.empty(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index f9a62ee4..557ed164 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -31,7 +31,7 @@ public class OreVeinLocation implements IWaypointAndLocationProvider { public OreVeinLocation(OreVeinPosition oreVeinPosition) { this.oreVeinPosition = oreVeinPosition; - name = EnumChatFormatting.WHITE + I18n.format(oreVeinPosition.veinType.name); + name = EnumChatFormatting.WHITE + oreVeinPosition.veinType.getPrimaryOreName(); materialNames = oreVeinPosition.veinType.getOreMaterialNames().stream() .map(materialName -> EnumChatFormatting.GRAY + materialName).collect(Collectors.toList()); } diff --git a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java index 0e5be148..d3bdf018 100644 --- a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java +++ b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java @@ -35,7 +35,7 @@ public ProspectorsLog() { @Override public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer player) { - if (isFilledLog(item) == false) { + if (!isFilledLog(item)) { final NBTTagCompound compound = new NBTTagCompound(); compound.setString(Tags.PROSPECTORSLOG_AUTHOR, player.getDisplayName()); compound.setString(Tags.PROSPECTORSLOG_AUTHOR_ID, player.getPersistentID().toString()); @@ -59,10 +59,10 @@ public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer play player.addChatMessage(notification); } } - } else if (world.isRemote == false) { + } else if (!world.isRemote) { final NBTTagCompound compound = item.getTagCompound(); final String authorUuid = compound.getString(Tags.PROSPECTORSLOG_AUTHOR_ID); - if (authorUuid.equals(player.getPersistentID().toString()) == false) { + if (!authorUuid.equals(player.getPersistentID().toString())) { final int random = VP.randomGeneration .nextInt(TransferCache.instance.isClientDataAvailable(authorUuid) ? 1000 : 5); if (random < 5) { diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java index 01701eae..f54eaeca 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java @@ -15,7 +15,6 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import com.sinthoras.visualprospecting.ServerTranslations; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; @@ -104,13 +103,12 @@ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlaye final int offsetUndergroundFluidZ = (Utils.mapToCornerUndergroundFluidChunkCoord( undergroundFluidPosition.chunkZ) - minUndergroundFluidZ) >> 3; final int undergroundFluidBookId = offsetUndergroundFluidX + offsetUndergroundFluidZ * 3; - fluidStrings[undergroundFluidBookId] = "" + undergroundFluidBookId - + ": " + fluidStrings[undergroundFluidBookId] = undergroundFluidBookId + ": " + undergroundFluidPosition.getMinProduction() + "-" + undergroundFluidPosition.getMaxProduction() + " " - + ServerTranslations.getEnglishLocalization(undergroundFluidPosition.fluid); + + undergroundFluidPosition.fluid.getLocalizedName(); } compound.setString(Tags.PROSPECTION_FLUIDS, String.join("|", fluidStrings)); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java index 1ea1c2e0..a7c589f6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java @@ -14,7 +14,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import com.sinthoras.visualprospecting.ServerTranslations; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; @@ -78,7 +77,7 @@ public GT_MetaTileEntity_ScannerMixin() { if (veinId < foundOreVeins.size()) { final OreVeinPosition oreVein = foundOreVeins.get(veinId); pageString.append(oreVein.getBlockX()).append(",").append(oreVein.getBlockZ()).append(" - ") - .append(ServerTranslations.getEnglishLocalization(oreVein.veinType)).append("\n"); + .append(oreVein.veinType.getPrimaryOreName()).append("\n"); } } String pageCounter = numberOfPages > 1 ? String.format(" %d/%d", pageNumber + 1, numberOfPages) diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java index 4ed5789e..dad0f690 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java @@ -95,10 +95,9 @@ public IMessage onMessage(ProspectingRequest message, MessageContext ctx) { final Block block = world.getBlock(message.blockX, message.blockY, message.blockZ); if (block instanceof BlockOresAbstract) { final TileEntity tileEntity = world.getTileEntity(message.blockX, message.blockY, message.blockZ); - if (tileEntity instanceof TileEntityOres) { - final short metaData = ((TileEntityOres) tileEntity).mMetaData; - if (isSmallOreId(metaData) == false - && oreIdToMaterialId(metaData) == message.foundOreMetaData) { + if (tileEntity instanceof TileEntityOres tileOre) { + final short metaData = tileOre.mMetaData; + if (!isSmallOreId(metaData) && oreIdToMaterialId(metaData) == message.foundOreMetaData) { lastRequestPerPlayer.put(uuid, timestamp); // Prioritise center vein diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java index 9ad1611c..a63b4cde 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java @@ -82,8 +82,8 @@ public void toBytes(ByteBuf buf) { public static class ServerHandler implements IMessageHandler { - private static Map> oreVeins = new HashMap<>(); - private static Map> undergroundFluids = new HashMap<>(); + private static final Map> oreVeins = new HashMap<>(); + private static final Map> undergroundFluids = new HashMap<>(); @Override public IMessage onMessage(ProspectionSharing message, MessageContext ctx) { @@ -98,7 +98,7 @@ public IMessage onMessage(ProspectionSharing message, MessageContext ctx) { oreVeins.put(player, new ArrayList<>()); undergroundFluids.put(player, new ArrayList<>()); } - if (oreVeins.containsKey(player) == false || undergroundFluids.containsKey(player) == false) { + if (!oreVeins.containsKey(player) || !undergroundFluids.containsKey(player)) { return null; } oreVeins.get(player).addAll(message.oreVeins); diff --git a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java index 34f9f8b8..69f7db21 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java @@ -31,7 +31,7 @@ public SnapshotDownloadTask(String authorUuid, EntityPlayerMP player) { @Override public boolean process() { final long timestamp = System.currentTimeMillis(); - if (timestamp - lastUpload > 1000 / Config.uploadPacketsPerSecond && listsEmpty() == false) { + if (timestamp - lastUpload > 1000 / Config.uploadPacketsPerSecond && !listsEmpty()) { lastUpload = timestamp; final ProspectionSharing packet = new ProspectionSharing(); diff --git a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java index de3a3c97..a6c4f65c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java @@ -24,7 +24,7 @@ public SnapshotUploadTask() { @Override public boolean process() { final long timestamp = System.currentTimeMillis(); - if (timestamp - lastUpload > 1000 / Config.uploadPacketsPerSecond && listsEmpty() == false) { + if (timestamp - lastUpload > 1000 / Config.uploadPacketsPerSecond && !listsEmpty()) { lastUpload = timestamp; final ProspectionSharing packet = new ProspectionSharing(); diff --git a/src/main/resources/META-INF/visualprospecting_at.cfg b/src/main/resources/META-INF/visualprospecting_at.cfg new file mode 100644 index 00000000..4c143b92 --- /dev/null +++ b/src/main/resources/META-INF/visualprospecting_at.cfg @@ -0,0 +1,2 @@ +public net.minecraft.nbt.NBTTagCompound field_74784_a #tagMap +public net.minecraft.nbt.NBTTagList field_74747_a #taglist \ No newline at end of file diff --git a/src/main/resources/assets/gregtech/lang/en_US.lang b/src/main/resources/assets/gregtech/lang/en_US.lang deleted file mode 100644 index e5d7608e..00000000 --- a/src/main/resources/assets/gregtech/lang/en_US.lang +++ /dev/null @@ -1,101 +0,0 @@ -ore.mix.naquadah=Naquadah -ore.mix.lignite=Lignite -ore.mix.coal=Coal -ore.mix.magnetite=Magnetite -ore.mix.gold=Gold -ore.mix.iron=Iron -ore.mix.cassiterite=Cassiterite -ore.mix.tetrahedrite=Tetrahedrite -ore.mix.netherquartz=Nether Quartz -ore.mix.sulfur=Sulfur -ore.mix.copper=Copper -ore.mix.bauxite=Bauxite -ore.mix.salts=Salts -ore.mix.redstone=Redstone -ore.mix.soapstone=Soapstone -ore.mix.nickel=Nickel -ore.mix.platinum=Platinum -ore.mix.pitchblende=Pitchblende -ore.mix.monazite=Monazite -ore.mix.molybdenum=Molybdenum -ore.mix.tungstate=Tungstate -ore.mix.sapphire=Sapphire -ore.mix.manganese=Manganese -ore.mix.quartz=Quartz -ore.mix.diamond=Diamond -ore.mix.olivine=Olivine -ore.mix.apatite=Apatite -ore.mix.galena=Galena -ore.mix.lapis=Lapis -ore.mix.beryllium=Beryllium -ore.mix.uranium=Uranium -ore.mix.oilsand=Oilsands - -ore.mix.neutronium=Neutronium -ore.mix.aquaignis=Aqua and Ignis -ore.mix.terraaer=Terra and Aer -ore.mix.perditioordo=Perdito and Ordo -ore.mix.coppertin=Vermiculite -ore.mix.titaniumchrome=Ilmenite -ore.mix.mineralsand=Mineral Sands -ore.mix.garnettin=Garnet/Tin -ore.mix.kaolinitezeolite=Kaolinite -ore.mix.mica=Mica -ore.mix.dolomite=Dolomite -ore.mix.platinumchrome=Palladium -ore.mix.iridiummytryl=Iridium -ore.mix.osmium=Osmium -ore.mix.saltpeterelectrotine=Electrotine -ore.mix.desh=Desh -ore.mix.draconium=Draconium -ore.mix.quantium=Quantium -ore.mix.callistoice=Callisto Ice -ore.mix.mytryl=Mytryl -ore.mix.ledox=Ledox -ore.mix.oriharukon=Oriharukon -ore.mix.blackplutonium=Black Plutonium -ore.mix.infusedgold=Infused Gold -ore.mix.niobium=Niobium -ore.mix.tungstenirons=Tungsten -ore.mix.uraniumgtnh=Thorium -ore.mix.vanadiumgold=Vanadium -ore.mix.netherstar=Nether Star -ore.mix.garnet=Garnet -ore.mix.rareearth=Rare Earths -ore.mix.richnuclear=Plutonium -ore.mix.heavypentele=Arsenic -ore.mix.europa=Magnesite -ore.mix.europacore=Chrome -ore.mix.secondlanthanid=Samarium -ore.mix.quartzspace=Quartz -ore.mix.rutile=Rutile -ore.mix.tfgalena=Cryolite -ore.mix.luvtantalite=Pyrolusite - -ore.mix.ross128.Thorianit=Thorianite -ore.mix.ross128.carbon=Graphite -ore.mix.ross128.bismuth=Bismuth -ore.mix.ross128.TurmalinAlkali=Olenite -ore.mix.ross128.Roquesit=Roquesite -ore.mix.ross128.Tungstate=Scheelite -ore.mix.ross128.CopperSulfits=Djurleite -ore.mix.ross128.Forsterit=Forsterite -ore.mix.ross128.Hedenbergit=Hedenbergite -ore.mix.ross128.RedZircon=Red Zircon - -ore.mix.ross128ba.tib=Tiberium -ore.mix.ross128ba.Tungstate=Scheelite -ore.mix.ross128ba.bart=BArTiMaEuSNeK -ore.mix.ross128ba.TurmalinAlkali=Olenite -ore.mix.ross128ba.Amethyst=Amethyst -ore.mix.ross128ba.CopperSulfits=Djurleite -ore.mix.ross128ba.RedZircon=Red Zircon -ore.mix.ross128ba.Fluorspar=Fluorspar - -ore.mix.dilithium=Dilithium -ore.mix.certusquartz=Certus Quartz -ore.mix.infinitycatalyst=Infinity Catalyst -ore.mix.awakeneddraconium=Awakened Draconium -ore.mix.naquadria=Naquadria -ore.mix.cosmicneutronium=Cosmic Neutronium -ore.mix.tengam=Tengam diff --git a/src/main/resources/assets/gregtech/lang/zh_CN.lang b/src/main/resources/assets/gregtech/lang/zh_CN.lang deleted file mode 100644 index fc63c48e..00000000 --- a/src/main/resources/assets/gregtech/lang/zh_CN.lang +++ /dev/null @@ -1,93 +0,0 @@ -ore.mix.naquadah=硅岩 -ore.mix.lignite=褐煤 -ore.mix.coal=煤 -ore.mix.magnetite=磁铁 -ore.mix.gold=金 -ore.mix.iron=铁 -ore.mix.cassiterite=锡石 -ore.mix.tetrahedrite=黝铜 -ore.mix.netherquartz=下界石英 -ore.mix.sulfur=硫 -ore.mix.copper=铜 -ore.mix.bauxite=铝土 -ore.mix.salts=盐 -ore.mix.redstone=红石 -ore.mix.soapstone=皂石 -ore.mix.nickel=镍 -ore.mix.platinum=铂 -ore.mix.pitchblende=沥青铀 -ore.mix.monazite=独居石 -ore.mix.molybdenum=钼 -ore.mix.tungstate=钨酸锂 -ore.mix.sapphire=蓝宝石 -ore.mix.manganese=锰 -ore.mix.quartz=石英 -ore.mix.diamond=钻石 -ore.mix.olivine=橄榄石 -ore.mix.apatite=磷灰石 -ore.mix.galena=方铅 -ore.mix.lapis=青金石 -ore.mix.beryllium=铍 -ore.mix.uranium=铀 -ore.mix.oilsand=油砂 - -ore.mix.neutronium=中子锭 -ore.mix.aquaignis=水/火蕴魔石 -ore.mix.terraaer=地/风蕴魔石 -ore.mix.perditioordo=混沌/秩序蕴魔石 -ore.mix.coppertin=蛭石 -ore.mix.titaniumchrome=钛铁 -ore.mix.mineralsand=玄武岩矿砂 -ore.mix.garnettin=石榴石/锡石 -ore.mix.kaolinitezeolite=高岭石 -ore.mix.mica=云母 -ore.mix.dolomite=白云石 -ore.mix.platinumchrome=钯 -ore.mix.iridiummytryl=铱 -ore.mix.osmium=锇 -ore.mix.saltpeterelectrotine=蓝石 -ore.mix.desh=戴斯 -ore.mix.draconium=龙 -ore.mix.quantium=量子合金 -ore.mix.callistoice=木卫四冰 -ore.mix.mytryl=秘银 -ore.mix.ledox=深铅 -ore.mix.oriharukon=奥利哈钢 -ore.mix.blackplutonium=黑钚 -ore.mix.infusedgold=注魔金 -ore.mix.niobium=铌 -ore.mix.tungstenirons=钨 -ore.mix.uraniumgtnh=钍 -ore.mix.vanadiumgold=钒 -ore.mix.netherstar=下界之星 -ore.mix.garnet=石榴石 -ore.mix.rareearth=稀土 -ore.mix.richnuclear=钚 -ore.mix.heavypentele=砷 -ore.mix.europa=菱镁 -ore.mix.europacore=铬 -ore.mix.secondlanthanid=钐 -ore.mix.quartzspace=石英 -ore.mix.rutile=金红石 -ore.mix.tfgalena=冰晶石 -ore.mix.luvtantalite=软锰 - -ore.mix.ross128.Thorianit=方钍石 -ore.mix.ross128.carbon=石墨 -ore.mix.ross128.bismuth=铋 -ore.mix.ross128.TurmalinAlkali=铝电气石 -ore.mix.ross128.Roquesit=硫铟铜 -ore.mix.ross128.Tungstate=白钨矿 -ore.mix.ross128.CopperSulfits=久辉铜 -ore.mix.ross128.Forsterit=镁橄榄石 -ore.mix.ross128.Hedenbergit=钙铁辉石 -ore.mix.ross128.RedZircon=红锆石 - -ore.mix.ross128ba.tib=泰伯利亚 -ore.mix.ross128ba.Tungstate=白钨矿 -ore.mix.ross128ba.bart=BArTiMaEuSNeK -ore.mix.ross128ba.TurmalinAlkali=铝电气石 -ore.mix.ross128ba.Amethyst=紫水晶 -ore.mix.ross128ba.CopperSulfits=久辉铜 -ore.mix.ross128ba.RedZircon=红锆石 -ore.mix.ross128ba.Fluorspar=氟石 From 7dbc66db2d6f3fb27f2e4cdc272f97372bdf44cb Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Mon, 16 Sep 2024 11:17:31 +0200 Subject: [PATCH 065/132] update --- dependencies.gradle | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 50d3282f..b207b6e7 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.12:dev') api('com.github.GTNewHorizons:GTNHLib:0.5.11:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.103:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.105:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.5')) runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) diff --git a/gradle.properties b/gradle.properties index 98961baa..db38e21d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -80,7 +80,7 @@ apiPackage = # Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/ # There can be multiple files in a space-separated list. # Example value: mymodid_at.cfg nei_at.cfg -accessTransformersFile =visualprospecting_at.cfg +accessTransformersFile = visualprospecting_at.cfg # Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! usesMixins = true From 0c3ace2b4bf5c1a8f79fbd1c5ca142837ca0d48e Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:31:38 +0200 Subject: [PATCH 066/132] More optimization & bug fixes (#55) * remove old i18n & fix saving * save about 20k allocations/sec and just return the same empty ore/fluid instance * fix bartworks ores missing some contained materials * more stable chunk analysis * spotlessApply * verify that min y level matches for fast scan * chat formatting is already added elsewhere * update * remove double jm dep * use arrayset for ores to keep ordering consistent for getContainedOres * more early returns for detailed analysis * reasonable aliases for these long ass commands * update * fix primary ore being added to contained ores multiple times after nei search * bimap is not needed or used * update --------- Co-authored-by: GitHub GTNH Actions <> Co-authored-by: Martin Robertz --- dependencies.gradle | 3 +- .../database/ClientCache.java | 3 +- .../database/DimensionCache.java | 42 +++++-------- .../database/OreVeinPosition.java | 1 + .../database/RedoServerCacheCommand.java | 7 +++ .../database/RedoServerSpawnCacheCommand.java | 7 +++ .../database/UndergroundFluidPosition.java | 5 +- .../database/WorldCache.java | 11 ++-- .../database/cachebuilder/ChunkAnalysis.java | 33 ++++------ .../cachebuilder/DetailedChunkAnalysis.java | 30 +++++----- .../cachebuilder/DimensionAnalysis.java | 18 +++++- .../BartworksOreMaterialProvider.java | 27 ++++++--- .../GregTechOreMaterialProvider.java | 28 +++++++-- .../veintypes/IOreMaterialProvider.java | 6 +- .../database/veintypes/VeinType.java | 58 ++++++++++++------ .../database/veintypes/VeinTypeCaching.java | 60 ++++--------------- .../model/locations/OreVeinLocation.java | 2 +- .../voxelmap/VoxelMapEventHandler.java | 3 +- 18 files changed, 179 insertions(+), 165 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index b207b6e7..76cea7ac 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,8 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.12:dev') api('com.github.GTNewHorizons:GTNHLib:0.5.11:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.49.105:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.01:dev') - runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.5')) runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index 3bda034c..e225354f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -6,7 +6,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityClientPlayerMP; -import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChatComponentTranslation; @@ -39,7 +38,7 @@ private void notifyNewOreVein(OreVeinPosition oreVeinPosition) { final String location = "(" + (oreVeinPosition.getBlockX() + 8) + "," + (oreVeinPosition.getBlockZ() + 8) + ")"; final IChatComponent veinNotification = new ChatComponentTranslation( "visualprospecting.vein.prospected", - I18n.format(oreVeinPosition.veinType.name), + oreVeinPosition.veinType.getPrimaryOreName(), location); veinNotification.getChatStyle().setItalic(true); veinNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index 73caded6..9e1b1fce 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -18,8 +18,6 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -import it.unimi.dsi.fastutil.longs.LongSet; public class DimensionCache { @@ -31,8 +29,6 @@ public enum UpdateResult { private final Long2ObjectMap oreChunks = new Long2ObjectOpenHashMap<>(); private final Long2ObjectMap undergroundFluids = new Long2ObjectOpenHashMap<>(); - private final LongSet changedOrNewOreChunks = new LongOpenHashSet(); - private final LongSet changedOrNewUndergroundFluids = new LongOpenHashSet(); public final int dimensionId; private boolean isDirty = false; @@ -51,32 +47,30 @@ public NBTTagCompound saveToNbt() { private NBTTagCompound saveOres() { NBTTagCompound compound = new NBTTagCompound(); - for (long key : changedOrNewOreChunks) { - OreVeinPosition oreVeinPosition = oreChunks.get(key); + for (OreVeinPosition vein : oreChunks.values()) { NBTTagCompound veinCompound = new NBTTagCompound(); - veinCompound.setInteger("chunkX", oreVeinPosition.chunkX); - veinCompound.setInteger("chunkZ", oreVeinPosition.chunkZ); - veinCompound.setShort("veinTypeId", VeinTypeCaching.getVeinTypeId(oreVeinPosition.veinType)); - veinCompound.setBoolean("depleted", oreVeinPosition.isDepleted()); - compound.setTag(String.valueOf(key), veinCompound); + veinCompound.setInteger("chunkX", vein.chunkX); + veinCompound.setInteger("chunkZ", vein.chunkZ); + veinCompound.setShort("veinTypeId", vein.veinType.veinId); + veinCompound.setBoolean("depleted", vein.isDepleted()); + compound.setTag(String.valueOf(getOreVeinKey(vein.chunkX, vein.chunkZ)), veinCompound); } return compound; } private NBTTagCompound saveFluids() { NBTTagCompound compound = new NBTTagCompound(); - for (long key : changedOrNewUndergroundFluids) { - UndergroundFluidPosition undergroundFluidPosition = undergroundFluids.get(key); + for (UndergroundFluidPosition fluid : undergroundFluids.values()) { NBTTagCompound fluidCompound = new NBTTagCompound(); - fluidCompound.setInteger("chunkX", undergroundFluidPosition.chunkX); - fluidCompound.setInteger("chunkZ", undergroundFluidPosition.chunkZ); - fluidCompound.setString("fluidName", undergroundFluidPosition.fluid.getName()); + fluidCompound.setInteger("chunkX", fluid.chunkX); + fluidCompound.setInteger("chunkZ", fluid.chunkZ); + fluidCompound.setString("fluidName", fluid.fluid.getName()); NBTTagList chunkList = new NBTTagList(); for (int i = 0; i < VP.undergroundFluidSizeChunkX; i++) { - chunkList.appendTag(new NBTTagIntArray(undergroundFluidPosition.chunks[i])); + chunkList.appendTag(new NBTTagIntArray(fluid.chunks[i])); } fluidCompound.setTag("chunks", chunkList); - compound.setTag(String.valueOf(key), fluidCompound); + compound.setTag(String.valueOf(getUndergroundFluid(fluid.chunkX, fluid.chunkZ)), fluidCompound); } return compound; } @@ -125,7 +119,6 @@ void loadLegacy(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBuffer) oreChunks.put( getOreVeinKey(chunkX, chunkZ), new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); - changedOrNewOreChunks.add(getOreVeinKey(chunkX, chunkZ)); } } if (undergroundFluidsBuffer != null) { @@ -153,7 +146,6 @@ void loadLegacy(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBuffer) undergroundFluids.put( getUndergroundFluidKey(chunkX, chunkZ), new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); - changedOrNewUndergroundFluids.add(getUndergroundFluidKey(chunkX, chunkZ)); } } } @@ -174,7 +166,6 @@ public void toggleOreVein(int chunkX, int chunkZ) { final OreVeinPosition oreVeinPosition = oreChunks.get(key); if (oreVeinPosition != null) { oreVeinPosition.toggleDepleted(); - changedOrNewOreChunks.add(key); markDirty(); } } @@ -184,13 +175,11 @@ public UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) { final OreVeinPosition storedOreVeinPosition = oreChunks.get(key); if (storedOreVeinPosition == null) { oreChunks.put(key, oreVeinPosition); - changedOrNewOreChunks.add(key); markDirty(); return UpdateResult.New; } if (storedOreVeinPosition.veinType != oreVeinPosition.veinType) { oreChunks.put(key, oreVeinPosition.joinDepletedState(storedOreVeinPosition)); - changedOrNewOreChunks.add(key); markDirty(); return UpdateResult.New; } @@ -201,12 +190,10 @@ public UpdateResult putUndergroundFluid(final UndergroundFluidPosition undergrou final long key = getUndergroundFluidKey(undergroundFluid.chunkX, undergroundFluid.chunkZ); final UndergroundFluidPosition storedUndergroundFluid = undergroundFluids.get(key); if (storedUndergroundFluid == null) { - changedOrNewUndergroundFluids.add(key); undergroundFluids.put(key, undergroundFluid); markDirty(); return UpdateResult.New; } else if (!storedUndergroundFluid.equals(undergroundFluid)) { - changedOrNewUndergroundFluids.add(key); undergroundFluids.put(key, undergroundFluid); markDirty(); return UpdateResult.Updated; @@ -216,13 +203,12 @@ public UpdateResult putUndergroundFluid(final UndergroundFluidPosition undergrou public OreVeinPosition getOreVein(int chunkX, int chunkZ) { final long key = getOreVeinKey(chunkX, chunkZ); - return oreChunks.getOrDefault(key, new OreVeinPosition(dimensionId, chunkX, chunkZ, VeinType.NO_VEIN, true)); + return oreChunks.getOrDefault(key, OreVeinPosition.EMPTY_VEIN); } public UndergroundFluidPosition getUndergroundFluid(int chunkX, int chunkZ) { final long key = getUndergroundFluidKey(chunkX, chunkZ); - return undergroundFluids - .getOrDefault(key, UndergroundFluidPosition.getNotProspected(dimensionId, chunkX, chunkZ)); + return undergroundFluids.getOrDefault(key, UndergroundFluidPosition.NOT_PROSPECTED); } public Collection getAllOreVeins() { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java b/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java index bb9de4c4..1fe1aa15 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java @@ -6,6 +6,7 @@ public class OreVeinPosition { public static final int MAX_BYTES = 3 * Integer.BYTES + Short.BYTES; + public static final OreVeinPosition EMPTY_VEIN = new OreVeinPosition(0, 0, 0, VeinType.NO_VEIN, true); public final int dimensionId; public final int chunkX; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java index bd712516..9d06e023 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java @@ -1,6 +1,8 @@ package com.sinthoras.visualprospecting.database; import java.io.IOException; +import java.util.Collections; +import java.util.List; import java.util.Objects; import java.util.zip.DataFormatException; @@ -29,6 +31,11 @@ public String getCommandUsage(ICommandSender sender) { return StatCollector.translateToLocal("visualprospecting.redoservercache.command"); } + @Override + public List getCommandAliases() { + return Collections.singletonList("vp_recache"); + } + @Override public void processCommand(ICommandSender sender, String[] parameters) { MinecraftServer server; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java index 03ca3ec8..3df89ef2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java @@ -1,6 +1,8 @@ package com.sinthoras.visualprospecting.database; import java.io.IOException; +import java.util.Collections; +import java.util.List; import java.util.Objects; import java.util.zip.DataFormatException; @@ -29,6 +31,11 @@ public String getCommandUsage(ICommandSender sender) { return StatCollector.translateToLocal("visualprospecting.redoserverspawncache.command"); } + @Override + public List getCommandAliases() { + return Collections.singletonList("vp_recachespawn"); + } + @Override public void processCommand(ICommandSender sender, String[] parameters) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java b/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java index fc58a502..bec9e4c6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java @@ -11,6 +11,7 @@ public class UndergroundFluidPosition { public static final int BYTES = (3 + 1 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ) * Integer.BYTES; + public static final UndergroundFluidPosition NOT_PROSPECTED = new UndergroundFluidPosition(0, 0, 0, null, null); public final int dimensionId; public final int chunkX; @@ -18,10 +19,6 @@ public class UndergroundFluidPosition { public final Fluid fluid; public final int[][] chunks; - public static UndergroundFluidPosition getNotProspected(int dimensionId, int chunkX, int chunkZ) { - return new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, null, null); - } - public UndergroundFluidPosition(int dimensionId, int chunkX, int chunkZ, Fluid fluid, int[][] chunks) { this.dimensionId = dimensionId; this.chunkX = Utils.mapToCornerUndergroundFluidChunkCoord(chunkX); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index 447e8a99..c3d5502c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -12,7 +12,6 @@ import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.database.veintypes.VeinType; public abstract class WorldCache { @@ -31,8 +30,9 @@ public boolean loadVeinCache(String worldId) { if (loadLegacyVeinCache(worldCache)) return true; final File[] dimensionFiles = worldCache.listFiles(); - if (dimensionFiles == null) return false; + if (dimensionFiles == null || dimensionFiles.length == 0) return false; + boolean loadedAny = false; for (File dimensionFile : dimensionFiles) { final String fileName = dimensionFile.getName(); if (!dimensionFile.isFile() || !fileName.endsWith(".dat")) { @@ -46,9 +46,10 @@ public boolean loadVeinCache(String worldId) { final DimensionCache dimension = new DimensionCache(dimensionId); dimension.loadFromNbt(dimCompound); dimensions.put(dimensionId, dimension); + loadedAny = true; } - return true; + return loadedAny; } private boolean loadLegacyVeinCache(File worldCacheDirectory) { @@ -167,7 +168,7 @@ protected void toggleOreVein(int dimensionId, int chunkX, int chunkZ) { public OreVeinPosition getOreVein(int dimensionId, int chunkX, int chunkZ) { DimensionCache dimension = dimensions.get(dimensionId); if (dimension == null) { - return new OreVeinPosition(dimensionId, chunkX, chunkZ, VeinType.NO_VEIN, true); + return OreVeinPosition.EMPTY_VEIN; } return dimension.getOreVein(chunkX, chunkZ); } @@ -184,7 +185,7 @@ protected DimensionCache.UpdateResult putUndergroundFluids(final UndergroundFlui public UndergroundFluidPosition getUndergroundFluid(int dimensionId, int chunkX, int chunkZ) { DimensionCache dimension = dimensions.get(dimensionId); if (dimension == null) { - return UndergroundFluidPosition.getNotProspected(dimensionId, chunkX, chunkZ); + return UndergroundFluidPosition.NOT_PROSPECTED; } return dimension.getUndergroundFluid(chunkX, chunkZ); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java index 19edd88b..02af198a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java @@ -21,7 +21,12 @@ public class ChunkAnalysis { private final ObjectSet matchedVeins = new ObjectOpenHashSet<>(); private final Short2IntMap oreCounts = new Short2IntArrayMap(); private int minVeinBlockY = VP.minecraftWorldHeight; - private short primaryMeta, secondaryMeta; + private short primaryMeta; + private final String dimName; + + public ChunkAnalysis(String dimName) { + this.dimName = dimName; + } public void processMinecraftChunk(final NBTTagList tileEntities) { if (tileEntities == null || tileEntities.tagCount() == 0) return; @@ -29,7 +34,8 @@ public void processMinecraftChunk(final NBTTagList tileEntities) { final NBTTagCompound tile = tileEntities.getCompoundTagAt(i); if (tile == null || !tile.hasKey("m")) continue; - if (!"GT_TileEntity_Ores".equals(tile.getString("id"))) { + String id = tile.getString("id"); + if (!"GT_TileEntity_Ores".equals(id) && !"bw.blockoresTE".equals(id)) { continue; } @@ -46,35 +52,20 @@ public void processMinecraftChunk(final NBTTagList tileEntities) { } if (oreCounts.size() == 1) { - primaryMeta = secondaryMeta = oreCounts.keySet().iterator().nextShort(); + primaryMeta = oreCounts.keySet().iterator().nextShort(); } else if (oreCounts.size() > 1) { ShortList metaCounts = new ShortArrayList(oreCounts.keySet()); metaCounts.sort((a, b) -> Integer.compare(oreCounts.get(b), oreCounts.get(a))); primaryMeta = metaCounts.getShort(0); - secondaryMeta = metaCounts.getShort(1); } } public boolean matchesSingleVein() { if (oreCounts.isEmpty()) return true; if (oreCounts.size() > 4) return false; - ObjectSet veins = VeinTypeCaching.getVeinTypesForPrimaryMeta(primaryMeta); - if (veins.isEmpty()) return trySecondaryMeta(); - - veins.stream().filter(veinType -> veinType.matches(oreCounts.keySet())).forEach(matchedVeins::add); - - if (matchedVeins.size() != 1) { - matchedVeins.clear(); - return trySecondaryMeta(); - } - - return true; - } - - private boolean trySecondaryMeta() { - if (secondaryMeta == primaryMeta) return false; - VeinTypeCaching.getVeinTypesForPrimaryMeta(secondaryMeta).stream() - .filter(veinType -> veinType.matches(oreCounts.keySet())).forEach(matchedVeins::add); + VeinTypeCaching.veinTypes.stream() + .filter(vein -> vein.containsAllFoundOres(oreCounts.keySet(), dimName, primaryMeta, minVeinBlockY)) + .forEach(matchedVeins::add); return matchedVeins.size() <= 1; } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index 51a353b7..68958a9a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -28,21 +28,23 @@ public class DetailedChunkAnalysis { public final int chunkZ; // For each height we count how often a ore (short) has occured private final Short2IntMap[] oresPerY = new Short2IntOpenHashMap[VP.minecraftWorldHeight]; + private final String dimName; - public DetailedChunkAnalysis(int dimensionId, int chunkX, int chunkZ) { + public DetailedChunkAnalysis(int dimensionId, String dimName, int chunkX, int chunkZ) { this.dimensionId = dimensionId; this.chunkX = chunkX; this.chunkZ = chunkZ; + this.dimName = dimName; } public void processMinecraftChunk(final NBTTagList tileEntities) { if (tileEntities == null || tileEntities.tagCount() == 0) return; for (int i = 0; i < tileEntities.tagCount(); i++) { final NBTTagCompound tile = tileEntities.getCompoundTagAt(i); - if (tile == null || !tile.hasKey("id")) continue; - final String tagId = tile.getString("id"); + if (tile == null || !tile.hasKey("m")) continue; - if (!tagId.equals("GT_TileEntity_Ores")) { + String id = tile.getString("id"); + if (!"GT_TileEntity_Ores".equals(id) && !"bw.blockoresTE".equals(id)) { continue; } @@ -56,10 +58,6 @@ public void processMinecraftChunk(final NBTTagList tileEntities) { oresPerY[blockY] = new Short2IntOpenHashMap(); } - if (!oresPerY[blockY].containsKey(meta)) { - oresPerY[blockY].put(meta, 0); - } - oresPerY[blockY].put(meta, oresPerY[blockY].get(meta) + 1); } } @@ -120,12 +118,14 @@ public void cleanUpWithNeighbors(final Map veinChunkY) { // but that case is rare and therefore, neglected for (int neighborId = 0; neighborId < neighbors.length; neighborId++) { final OreVeinPosition neighbor = neighbors[neighborId]; + if (neighbor.veinType == VeinType.NO_VEIN) continue; + final boolean atCoordinateAxis = Math.abs(neighbor.chunkX - chunkX) < 3 || Math.abs(neighbor.chunkZ - chunkZ) < 3; final boolean canOverlap = atCoordinateAxis ? neighbor.veinType.canOverlapIntoNeighborOreChunkAtCoordinateAxis() : neighbor.veinType.canOverlapIntoNeighborOreChunk(); - if (neighbor.veinType != VeinType.NO_VEIN && canOverlap) { + if (canOverlap) { final int veinBlockY = neighborVeinBlockY[neighborId]; for (int layerBlockY = 0; layerBlockY < VeinType.veinHeight; layerBlockY++) { final int blockY = veinBlockY + layerBlockY; @@ -155,13 +155,15 @@ public VeinType getMatchedVein() { } } + if (allOres.isEmpty()) return VeinType.NO_VEIN; + final Optional dominantOre = allOres.short2IntEntrySet().stream() .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(Map.Entry::getKey).findFirst(); - if (dominantOre.isPresent()) { - for (VeinType veinType : VeinTypeCaching.veinTypes) { - if (veinType.matchesWithSpecificPrimaryOrSecondary(allOres.keySet(), dominantOre.get())) { - matchedVeins.add(veinType); - } + if (!dominantOre.isPresent()) return VeinType.NO_VEIN; + + for (VeinType veinType : VeinTypeCaching.veinTypes) { + if (veinType.matchesWithSpecificPrimaryOrSecondary(allOres.keySet(), dimName, dominantOre.get())) { + matchedVeins.add(veinType); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java index 0f18ceae..620692a2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java @@ -9,6 +9,9 @@ import java.util.zip.DataFormatException; import net.minecraft.nbt.NBTTagList; +import net.minecraft.world.WorldProvider; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.DimensionManager; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; @@ -19,9 +22,11 @@ public class DimensionAnalysis { public final int dimensionId; + public final String dimensionName; public DimensionAnalysis(int dimensionId) { this.dimensionId = dimensionId; + this.dimensionName = getDimensionName(); } private interface IChunkHandler { @@ -42,7 +47,7 @@ public void processMinecraftWorld(Collection regionFiles) { regionFiles.parallelStream().forEach(regionFile -> { executeForEachGeneratedOreChunk(regionFile, (root, chunkX, chunkZ) -> { - final ChunkAnalysis chunk = new ChunkAnalysis(); + final ChunkAnalysis chunk = new ChunkAnalysis(dimensionName); chunk.processMinecraftChunk(root); if (chunk.matchesSingleVein()) { @@ -52,6 +57,7 @@ public void processMinecraftWorld(Collection regionFiles) { } else { final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis( dimensionId, + dimensionName, chunkX, chunkZ); detailedChunk.processMinecraftChunk(root); @@ -71,7 +77,7 @@ public void processMinecraftWorld(Collection regionFiles) { regionFiles.parallelStream().forEach(regionFile -> { executeForEachGeneratedOreChunk(regionFile, (root, chunkX, chunkZ) -> { - final ChunkAnalysis chunk = new ChunkAnalysis(); + final ChunkAnalysis chunk = new ChunkAnalysis(dimensionName); chunk.processMinecraftChunk(root); if (chunk.matchesSingleVein()) { @@ -87,6 +93,7 @@ public void processMinecraftWorld(Collection regionFiles) { if (ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ).veinType == VeinType.NO_VEIN) { final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis( dimensionId, + dimensionName, chunkX, chunkZ); detailedChunk.processMinecraftChunk(root); @@ -134,4 +141,11 @@ private void executeForEachGeneratedOreChunk(File regionFile, IChunkHandler chun AnalysisProgressTracker.notifyCorruptFile(regionFile); } } + + private String getDimensionName() { + WorldServer world = DimensionManager.getWorld(dimensionId); + if (world == null) return ""; + WorldProvider provider = world.provider; + return provider == null ? "" : provider.getDimensionName(); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java index 3f218a4f..52214630 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java @@ -2,16 +2,17 @@ import static bartworks.util.BWColorUtil.getColorFromRGBArray; +import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IIcon; +import com.google.common.collect.ImmutableList; + import bartworks.system.material.Werkstoff; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.GregTechAPI; import gregtech.api.enums.OrePrefixes; import it.unimi.dsi.fastutil.shorts.ShortCollection; @@ -21,6 +22,7 @@ public class BartworksOreMaterialProvider implements IOreMaterialProvider { private final int primaryOreColor; private final String primaryOreName; private IIcon primaryOreIcon; + private ImmutableList containedOres; public BartworksOreMaterialProvider(Werkstoff material) { this.material = material; @@ -48,9 +50,20 @@ public String getLocalizedName() { } @Override - public List getContainedOres(ShortCollection ores) { - return ores.intStream().mapToObj(metaData -> Werkstoff.werkstoffHashMap.get((short) metaData)) - .filter(Objects::nonNull).map(material -> EnumChatFormatting.GRAY + material.getLocalizedName()) - .collect(Collectors.toList()); + public ImmutableList getContainedOres(ShortCollection ores) { + if (containedOres == null) { + List oreNames = new ArrayList<>(); + for (short meta : ores) { + Werkstoff werkstoff = Werkstoff.werkstoffHashMap.get(meta); + if (werkstoff == null) { + oreNames.add(GregTechAPI.sGeneratedMaterials[meta].mLocalizedName); + } else { + oreNames.add(werkstoff.getLocalizedName()); + + } + } + containedOres = ImmutableList.copyOf(oreNames); + } + return containedOres; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java index b4e574a0..8956c20b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java @@ -1,12 +1,12 @@ package com.sinthoras.visualprospecting.database.veintypes; +import java.util.ArrayList; import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IIcon; +import com.google.common.collect.ImmutableList; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.GregTechAPI; @@ -20,6 +20,7 @@ public class GregTechOreMaterialProvider implements IOreMaterialProvider { private final int primaryOreColor; private IIcon primaryOreIcon; private final String primaryOreName; + private ImmutableList containedOres; public GregTechOreMaterialProvider(Materials material) { this.material = material; @@ -27,6 +28,13 @@ public GregTechOreMaterialProvider(Materials material) { this.primaryOreName = material.mLocalizedName; } + GregTechOreMaterialProvider() { + material = Materials._NULL; + primaryOreColor = 0; + primaryOreName = ""; + containedOres = ImmutableList.of(); + } + @Override @SideOnly(Side.CLIENT) public IIcon getIcon() { @@ -47,8 +55,16 @@ public String getLocalizedName() { } @Override - public List getContainedOres(ShortCollection ores) { - return ores.intStream().mapToObj(metaData -> GregTechAPI.sGeneratedMaterials[metaData]).filter(Objects::nonNull) - .map(material -> EnumChatFormatting.GRAY + material.mLocalizedName).collect(Collectors.toList()); + public ImmutableList getContainedOres(ShortCollection ores) { + if (containedOres == null) { + List temp = new ArrayList<>(); + for (short meta : ores) { + Materials material = GregTechAPI.sGeneratedMaterials[meta]; + if (material == null) continue; + temp.add(material.mLocalizedName); + } + containedOres = ImmutableList.copyOf(temp); + } + return containedOres; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java index 173f4c67..29c66d7b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java @@ -1,9 +1,9 @@ package com.sinthoras.visualprospecting.database.veintypes; -import java.util.List; - import net.minecraft.util.IIcon; +import com.google.common.collect.ImmutableList; + import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.shorts.ShortCollection; @@ -17,5 +17,5 @@ public interface IOreMaterialProvider { String getLocalizedName(); - List getContainedOres(ShortCollection ores); + ImmutableList getContainedOres(ShortCollection ores); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 9d73ba36..4b3244f6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -3,12 +3,18 @@ import java.util.ArrayList; import java.util.List; +import javax.annotation.ParametersAreNonnullByDefault; + +import com.google.common.collect.ImmutableList; import com.sinthoras.visualprospecting.Tags; +import gregtech.common.OreMixBuilder; +import it.unimi.dsi.fastutil.shorts.ShortArraySet; import it.unimi.dsi.fastutil.shorts.ShortCollection; import it.unimi.dsi.fastutil.shorts.ShortOpenHashSet; import it.unimi.dsi.fastutil.shorts.ShortSet; +@ParametersAreNonnullByDefault public class VeinType { public static final int veinHeight = 9; @@ -23,25 +29,26 @@ public class VeinType { public final short sporadicOreMeta; public final int minBlockY; public final int maxBlockY; - public final ShortSet oresAsSet = new ShortOpenHashSet(); - private final List containedOres = new ArrayList<>(); + private final ShortSet oresAsSet = new ShortArraySet(); + private final List allowedDims = new ArrayList<>(); private boolean isHighlighted = true; - private String primaryOreName = ""; // Available after VisualProspecting post GT initialization public static final VeinType NO_VEIN = new VeinType( Tags.ORE_MIX_NONE_NAME, - null, + new GregTechOreMaterialProvider(), 0, (short) -1, (short) -1, (short) -1, (short) -1, 0, - 0); + 0, + ""); public VeinType(String name, IOreMaterialProvider oreMaterialProvider, int blockSize, short primaryOreMeta, - short secondaryOreMeta, short inBetweenOreMeta, short sporadicOreMeta, int minBlockY, int maxBlockY) { + short secondaryOreMeta, short inBetweenOreMeta, short sporadicOreMeta, int minBlockY, int maxBlockY, + String dimName) { this.name = name; this.oreMaterialProvider = oreMaterialProvider; this.blockSize = blockSize; @@ -51,18 +58,33 @@ public VeinType(String name, IOreMaterialProvider oreMaterialProvider, int block oresAsSet.add(this.secondaryOreMeta = secondaryOreMeta); oresAsSet.add(this.inBetweenOreMeta = inBetweenOreMeta); oresAsSet.add(this.sporadicOreMeta = sporadicOreMeta); - if (oreMaterialProvider != null) { - containedOres.addAll(oreMaterialProvider.getContainedOres(oresAsSet)); - primaryOreName = oreMaterialProvider.getLocalizedName(); - } + allowedDims.add(dimName); + } + + public VeinType(OreMixBuilder oreMix) { + name = oreMix.oreMixName; + oreMaterialProvider = new GregTechOreMaterialProvider(oreMix.primary); + blockSize = oreMix.size; + oresAsSet.add(primaryOreMeta = (short) oreMix.primary.mMetaItemSubID); + oresAsSet.add(secondaryOreMeta = (short) oreMix.secondary.mMetaItemSubID); + oresAsSet.add(inBetweenOreMeta = (short) oreMix.between.mMetaItemSubID); + oresAsSet.add(sporadicOreMeta = (short) oreMix.sporadic.mMetaItemSubID); + minBlockY = Math.max(0, oreMix.minY - 6); + maxBlockY = Math.min(255, oreMix.maxY - 6); + allowedDims.addAll(oreMix.dimsEnabled.keySet()); } - public boolean matches(ShortCollection foundOres) { - return foundOres.containsAll(oresAsSet); + public boolean containsAllFoundOres(ShortCollection foundOres, String dimName, short specificMeta, int minY) { + return minY >= minBlockY && (primaryOreMeta == specificMeta || secondaryOreMeta == specificMeta) + && (dimName.isEmpty() || allowedDims.contains(dimName)) + && oresAsSet.containsAll(foundOres); } - public boolean matchesWithSpecificPrimaryOrSecondary(ShortCollection foundOres, short specificMeta) { - return (primaryOreMeta == specificMeta || secondaryOreMeta == specificMeta) && foundOres.containsAll(oresAsSet); + public boolean matchesWithSpecificPrimaryOrSecondary(ShortCollection foundOres, String dimName, + short specificMeta) { + return (primaryOreMeta == specificMeta || secondaryOreMeta == specificMeta) + && (dimName.isEmpty() || allowedDims.contains(dimName)) + && foundOres.containsAll(oresAsSet); } public boolean canOverlapIntoNeighborOreChunk() { @@ -80,12 +102,12 @@ public boolean containsOre(short oreMetaData) { || sporadicOreMeta == oreMetaData; } - public List getOreMaterialNames() { - return containedOres; + public ImmutableList getOreMaterialNames() { + return oreMaterialProvider.getContainedOres(oresAsSet); } public String getPrimaryOreName() { - return primaryOreName; + return oreMaterialProvider.getLocalizedName(); } public ShortSet getOresAtLayer(int layerBlockY) { @@ -126,7 +148,7 @@ public boolean isHighlighted() { return isHighlighted; } - public void setNEISearchHeighlight(boolean isHighlighted) { + public void setNEISearchHighlight(boolean isHighlighted) { this.isHighlighted = isHighlighted; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index 855c42f8..f90a8312 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -9,11 +9,8 @@ import java.util.OptionalInt; import java.util.regex.Pattern; -import net.minecraft.client.resources.I18n; import net.minecraft.util.EnumChatFormatting; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; @@ -23,23 +20,20 @@ import codechicken.nei.SearchField; import gregtech.api.GregTechAPI; import gregtech.api.enums.Materials; -import gregtech.common.WorldgenGTOreLayer; +import gregtech.api.enums.OreMixes; import it.unimi.dsi.fastutil.objects.Object2ShortMap; import it.unimi.dsi.fastutil.objects.Object2ShortOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectSet; -import it.unimi.dsi.fastutil.objects.ObjectSets; import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; public class VeinTypeCaching implements Runnable { - private static final BiMap veinTypeLookupTableForIds = HashBiMap.create(); + private static final Short2ObjectMap veinTypeLookupTableForIds = new Short2ObjectOpenHashMap<>(); private static final Map veinTypeLookupTableForNames = new HashMap<>(); private static final Object2ShortMap veinTypeStorageInfo = new Object2ShortOpenHashMap<>(); - private static final Short2ObjectMap> primaryMetaToVeinType = new Short2ObjectOpenHashMap<>(); public static ObjectSet veinTypes; - private static int longesOreName = 0; // BartWorks initializes veins in FML preInit // GalacticGreg initializes veins in FML postInit, but only copies all base game veins to make them available on all @@ -50,24 +44,8 @@ public void run() { veinTypes = new ObjectOpenHashSet<>(); veinTypes.add(VeinType.NO_VEIN); - for (WorldgenGTOreLayer vein : WorldgenGTOreLayer.sList) { - if (vein.mWorldGenName.equals(Tags.ORE_MIX_NONE_NAME)) { - break; - } - final Materials material = getGregTechMaterial(vein.mPrimaryMeta); - veinTypes.add( - new VeinType( - vein.mWorldGenName, - new GregTechOreMaterialProvider(material), - vein.mSize, - vein.mPrimaryMeta, - vein.mSecondaryMeta, - vein.mBetweenMeta, - vein.mSporadicMeta, - Math.max(0, vein.mMinY - 6), // GregTech ore veins start at layer -1 and the blockY RNG adds - // another -5 - // offset - Math.min(255, vein.mMaxY - 6))); + for (OreMixes mix : OreMixes.values()) { + veinTypes.add(new VeinType(mix.oreMixBuilder)); } for (BWOreLayer vein : BWOreLayer.sList) { @@ -84,7 +62,8 @@ public void run() { (short) vein.mBetweenMeta, (short) vein.mSporadicMeta, Math.max(0, vein.mMinY), - Math.min(255, vein.mMaxY))); + Math.min(255, vein.mMaxY), + vein.getDimName())); } // Assign veinTypeIds for efficient storage @@ -98,33 +77,20 @@ public void run() { veinTypeStorageInfo.putIfAbsent(veinType.name, veinType.veinId); veinTypeLookupTableForIds.put(veinType.veinId, veinType); veinTypeLookupTableForNames.put(veinType.name, veinType); - primaryMetaToVeinType.computeIfAbsent(veinType.primaryOreMeta, k -> new ObjectOpenHashSet<>()) - .add(veinType); } saveVeinTypeStorageInfo(); - - for (VeinType veinType : veinTypes) { - longesOreName = Math.max(longesOreName, veinType.name.length()); - } } private Materials getGregTechMaterial(short metaId) { final Materials material = GregTechAPI.sGeneratedMaterials[metaId]; if (material == null) { // Some materials are not registered in dev when their usage mod is not available. - return Materials.getAll().stream().filter(m -> m.mMetaItemSubID == metaId).findAny().get(); + return Materials.getAll().stream().filter(m -> m.mMetaItemSubID == metaId).findAny() + .orElse(Materials._NULL); } return material; } - public static int getLongesOreNameLength() { - return longesOreName; - } - - public static short getVeinTypeId(VeinType veinType) { - return veinTypeLookupTableForIds.inverse().get(veinType); - } - public static VeinType getVeinType(short veinTypeId) { return veinTypeLookupTableForIds.getOrDefault(veinTypeId, VeinType.NO_VEIN); } @@ -140,11 +106,6 @@ private static File getVeinTypeStorageInfoFile() { return new File(directory, "veintypesLUT"); } - public static ObjectSet getVeinTypesForPrimaryMeta(short primaryMeta) { - - return primaryMetaToVeinType.getOrDefault(primaryMeta, ObjectSets.emptySet()); - } - private static void loadVeinTypeStorageInfo() { veinTypeStorageInfo.putAll(Utils.readFileToMap(getVeinTypeStorageInfoFile())); } @@ -163,14 +124,13 @@ public static void recalculateNEISearch() { if (veinType == VeinType.NO_VEIN) continue; if (isSearchActive && !searchString.isEmpty()) { List searchableStrings = veinType.getOreMaterialNames(); - searchableStrings.add(I18n.format(veinType.name)); final boolean match = searchableStrings.stream() .map(EnumChatFormatting::getTextWithoutFormattingCodes).map(String::toLowerCase) .anyMatch(searchableString -> filterPattern.matcher(searchableString).find()); - veinType.setNEISearchHeighlight(match); + veinType.setNEISearchHighlight(match); } else { - veinType.setNEISearchHeighlight(true); + veinType.setNEISearchHighlight(true); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index 557ed164..0349a38a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -43,7 +43,7 @@ public Waypoint toWaypoint() { 65, oreVeinPosition.getBlockZ(), oreVeinPosition.dimensionId, - I18n.format("visualprospecting.tracked", I18n.format(oreVeinPosition.veinType.name)), + I18n.format("visualprospecting.tracked", oreVeinPosition.veinType.getPrimaryOreName()), getColor()); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java index d11012d7..80b43996 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java @@ -5,7 +5,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.item.ItemStack; -import net.minecraft.util.StatCollector; import com.gtnewhorizons.navigator.api.voxelmap.VoxelMapWaypointManager; import com.sinthoras.visualprospecting.Config; @@ -30,7 +29,7 @@ public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { TreeSet dim = new TreeSet<>(); dim.add(pos.dimensionId); VoxelMapWaypointManager.addVoxelMapWaypoint( - StatCollector.translateToLocal(pos.veinType.name), // name + pos.veinType.getPrimaryOreName(), // name pos.getBlockX(), // X pos.getBlockZ(), // Z getY(), // Y From 3a9161e1691f6dc13c75f794a292c2aeb06f8b3d Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:48:09 +0200 Subject: [PATCH 067/132] Fix veins differing between server and clients (#57) * fix veins differing between server and clients * bump gt dep --- dependencies.gradle | 2 +- .../sinthoras/visualprospecting/utils/VPByteBufUtils.java | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 76cea7ac..281be536 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.12:dev') api('com.github.GTNewHorizons:GTNHLib:0.5.11:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.01:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.06:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java b/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java index 8137b062..aaede9f2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java +++ b/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java @@ -11,6 +11,7 @@ import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import cpw.mods.fml.common.network.ByteBufUtils; import io.netty.buffer.ByteBuf; public final class VPByteBufUtils { @@ -19,18 +20,18 @@ public static void WriteOreVeinPosition(ByteBuf buf, OreVeinPosition oreVeinPosi buf.writeInt(oreVeinPosition.dimensionId); buf.writeInt(oreVeinPosition.chunkX); buf.writeInt(oreVeinPosition.chunkZ); - buf.writeShort(oreVeinPosition.veinType.veinId); buf.writeBoolean(oreVeinPosition.isDepleted()); + ByteBufUtils.writeUTF8String(buf, oreVeinPosition.veinType.name); } public static OreVeinPosition ReadOreVeinPosition(ByteBuf buf) { final int dimId = buf.readInt(); final int chunkX = buf.readInt(); final int chunkZ = buf.readInt(); - final short veinId = buf.readShort(); final boolean isDepleted = buf.readBoolean(); + final String veinName = ByteBufUtils.readUTF8String(buf); - return new OreVeinPosition(dimId, chunkX, chunkZ, VeinTypeCaching.getVeinType(veinId), isDepleted); + return new OreVeinPosition(dimId, chunkX, chunkZ, VeinTypeCaching.getVeinType(veinName), isDepleted); } public static void WriteUndergroundFluidPosition(ByteBuf buf, UndergroundFluidPosition undergroundFluidPosition) { From 579e9054bba862d94ba771d7b60f7e3e18bcb0e4 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Mon, 23 Sep 2024 21:44:58 +0200 Subject: [PATCH 068/132] update --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 281be536..2e3a1e90 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.12:dev') api('com.github.GTNewHorizons:GTNHLib:0.5.11:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.06:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.09:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } From 640dd6dacffb71f26809465af2f22a15a8b1ddda Mon Sep 17 00:00:00 2001 From: Dmetriy Date: Wed, 25 Sep 2024 14:45:28 +0300 Subject: [PATCH 069/132] add NEI hotkeys support when mouse over ore vein (#58) Co-authored-by: Dmetriy <> --- dependencies.gradle | 2 +- .../model/locations/OreVeinLocation.java | 4 +++ .../model/render/OreVeinRenderStep.java | 25 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 2e3a1e90..54967a08 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,5 @@ dependencies { - api('com.github.GTNewHorizons:Navigator:1.0.12:dev') + api('com.github.GTNewHorizons:Navigator:1.0.13:dev') api('com.github.GTNewHorizons:GTNHLib:0.5.11:dev') api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.09:dev') diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index 0349a38a..3ce125bf 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -118,4 +118,8 @@ public int getColor() { public IIcon getIconFromPrimaryOre() { return oreVeinPosition.veinType.oreMaterialProvider.getIcon(); } + + public short getPrimaryOreMeta() { + return oreVeinPosition.veinType.primaryOreMeta; + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java index 805553e5..2dc6545f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java @@ -3,7 +3,9 @@ import java.util.List; import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; @@ -13,8 +15,12 @@ import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; +import codechicken.nei.api.ShortcutInputHandler; +import gregtech.api.GregTechAPI; + public class OreVeinRenderStep extends UniversalInteractableStep { + private static final ResourceLocation clickSound = new ResourceLocation("gui.button.press"); private static final ResourceLocation depletedTextureLocation = new ResourceLocation( Tags.MODID, "textures/depleted.png"); @@ -90,4 +96,23 @@ public void onActionKeyPressed() { location.toggleOreVein(); } + @Override + public boolean onKeyPressed(int keyCode) { + + if (super.onKeyPressed(keyCode)) { + return true; + } + + final var itemStack = new ItemStack(GregTechAPI.sBlockOres1, 1, location.getPrimaryOreMeta()); + if (ShortcutInputHandler.handleKeyEvent(itemStack)) { + playClickSound(); + return true; + } + + return false; + } + + private void playClickSound() { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(clickSound, 1.0F)); + } } From 40738357b418e9851f9cacbece36d829c27ba3b1 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Wed, 25 Sep 2024 14:43:32 +0200 Subject: [PATCH 070/132] update --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 54967a08..68f4310d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { - api('com.github.GTNewHorizons:Navigator:1.0.13:dev') + api('com.github.GTNewHorizons:Navigator:1.0.15:dev') api('com.github.GTNewHorizons:GTNHLib:0.5.11:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.09:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.14:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } From 0cab19def401d7b644da1303a8e5674e568f0c81 Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Fri, 27 Sep 2024 17:22:04 +0200 Subject: [PATCH 071/132] yet another fix for !visualprospectingnearspawn (#59) --- .../com/sinthoras/visualprospecting/VP.java | 2 +- .../database/WorldCache.java | 27 ++++++---------- .../visualprospecting/hooks/HooksShared.java | 31 ++++++++++++------- 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/VP.java b/src/main/java/com/sinthoras/visualprospecting/VP.java index 2321f7f3..34d3f814 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VP.java +++ b/src/main/java/com/sinthoras/visualprospecting/VP.java @@ -12,7 +12,7 @@ public class VP { public static SimpleNetworkWrapper network; public static final Random randomGeneration = new Random(); - private static Logger LOG = LogManager.getLogger(Tags.MODID); + public static final Logger LOG = LogManager.getLogger(Tags.MODID); public static final int gregTechSmallOreMinimumMeta = 16000; public static final int minecraftWorldHeight = 256; public static final int chunksPerRegionFileX = 32; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index c3d5502c..685974e4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -2,7 +2,6 @@ import java.io.File; import java.nio.ByteBuffer; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -13,9 +12,12 @@ import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + public abstract class WorldCache { - protected final Map dimensions = new HashMap<>(); + protected final Int2ObjectMap dimensions = new Int2ObjectOpenHashMap<>(); private boolean needsSaving = false; protected File worldCache; private boolean isLoaded = false; @@ -43,9 +45,8 @@ public boolean loadVeinCache(String worldId) { if (dimCompound == null) continue; final int dimensionId = dimCompound.getInteger("dim"); - final DimensionCache dimension = new DimensionCache(dimensionId); + final DimensionCache dimension = dimensions.computeIfAbsent(dimensionId, DimensionCache::new); dimension.loadFromNbt(dimCompound); - dimensions.put(dimensionId, dimension); loadedAny = true; } @@ -93,10 +94,8 @@ private boolean loadLegacyVeinCache(File worldCacheDirectory) { public void saveVeinCache() { if (needsSaving) { for (DimensionCache dimension : dimensions.values()) { - if (!dimension.isDirty()) { - continue; - } - File dimFile = new File(worldCache.toPath() + "/DIM" + dimension.dimensionId + ".dat"); + if (!dimension.isDirty()) continue; + File dimFile = new File(worldCache, "DIM" + dimension.dimensionId + ".dat"); Utils.writeNBT(dimFile, dimension.saveToNbt()); } needsSaving = false; @@ -149,11 +148,7 @@ private DimensionCache.UpdateResult updateSaveFlag(DimensionCache.UpdateResult u } protected DimensionCache.UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) { - DimensionCache dimension = dimensions.get(oreVeinPosition.dimensionId); - if (dimension == null) { - dimension = new DimensionCache(oreVeinPosition.dimensionId); - dimensions.put(oreVeinPosition.dimensionId, dimension); - } + DimensionCache dimension = dimensions.computeIfAbsent(oreVeinPosition.dimensionId, DimensionCache::new); return updateSaveFlag(dimension.putOreVein(oreVeinPosition)); } @@ -174,11 +169,7 @@ public OreVeinPosition getOreVein(int dimensionId, int chunkX, int chunkZ) { } protected DimensionCache.UpdateResult putUndergroundFluids(final UndergroundFluidPosition undergroundFluid) { - DimensionCache dimension = dimensions.get(undergroundFluid.dimensionId); - if (dimension == null) { - dimension = new DimensionCache(undergroundFluid.dimensionId); - dimensions.put(undergroundFluid.dimensionId, dimension); - } + DimensionCache dimension = dimensions.computeIfAbsent(undergroundFluid.dimensionId, DimensionCache::new); return updateSaveFlag(dimension.putUndergroundFluid(undergroundFluid)); } diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index 01554725..273283e9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -1,9 +1,11 @@ package com.sinthoras.visualprospecting.hooks; +import java.io.File; import java.io.IOException; import java.util.zip.DataFormatException; -import net.minecraft.server.MinecraftServer; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; import com.sinthoras.visualprospecting.Config; @@ -37,6 +39,8 @@ public class HooksShared { + private static boolean newWorld = false; + // preInit "Run before anything else. Read your config, create blocks, items, // etc, and register them with the GameRegistry." public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { @@ -82,28 +86,31 @@ public void fmlLifeCycleEvent(FMLPostInitializationEvent event) { GregTechAPI.sAfterGTPostload.add(new VeinTypeCaching()); } - public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) {} + public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) { + File worldDir = DimensionManager.getCurrentSaveRootDirectory(); + if (worldDir != null) { + File regionFolder = new File(worldDir, "region"); + newWorld = !regionFolder.exists(); + } + } // register server commands in this event handler public void fmlLifeCycleEvent(FMLServerStartingEvent event) { // Get the server and load the ID handler - final MinecraftServer minecraftServer = event.getServer(); - WorldIdHandler.load(minecraftServer.worldServers[0]); + WorldServer world = DimensionManager.getWorld(0); + WorldIdHandler.load(world); // Attempt to load the vein cache. If unable or forcing a recache... - if (!ServerCache.instance.loadVeinCache(WorldIdHandler.getWorldId()) || Config.recacheVeins) { + boolean loaded = ServerCache.instance.loadVeinCache(WorldIdHandler.getWorldId()); + if (!newWorld && (!loaded || Config.recacheVeins)) { // Reanalyze the world and reload it into memory. try { - WorldAnalysis world = new WorldAnalysis( - minecraftServer.getEntityWorld().getSaveHandler().getWorldDirectory()); - world.cacheVeins(); + WorldAnalysis worldAnalysis = new WorldAnalysis(world.getSaveHandler().getWorldDirectory()); + worldAnalysis.cacheVeins(); } catch (IOException | DataFormatException e) { - - // Oops - VP.info("Could not load world save files to build vein cache!"); - e.printStackTrace(); + VP.LOG.info("Could not load world save files to build vein cache!", e); } } From 3c1ba04d3d2327be0a649c40b76b958c2ca3cd45 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Fri, 27 Sep 2024 17:39:04 +0200 Subject: [PATCH 072/132] update --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 68f4310d..b5d8d48a 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.15:dev') api('com.github.GTNewHorizons:GTNHLib:0.5.11:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.14:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.20:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } From 5b56eb35f8974bde24ffce09b41ffa2aa1ae1118 Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Sat, 28 Sep 2024 17:09:56 +0200 Subject: [PATCH 073/132] Use gt5u localized ore mix names (#60) * use gt5u localized ore mix names * the Math.max/min's are inside VeinType now * highlight vein when vein name is searched in nei (again) * update --------- Co-authored-by: Martin Robertz --- dependencies.gradle | 2 +- .../database/ClientCache.java | 2 +- .../GregTechOreMaterialProvider.java | 8 +-- .../database/veintypes/VeinType.java | 16 ++++-- .../database/veintypes/VeinTypeCaching.java | 57 +++++++++++++------ .../integration/gregtech/VeinDatabase.java | 2 +- .../model/locations/OreVeinLocation.java | 4 +- .../voxelmap/VoxelMapEventHandler.java | 2 +- .../GT_MetaTileEntity_ScannerMixin.java | 2 +- 9 files changed, 59 insertions(+), 36 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index b5d8d48a..22f3792f 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.15:dev') api('com.github.GTNewHorizons:GTNHLib:0.5.11:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.20:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.21:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index e225354f..1d728e07 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -38,7 +38,7 @@ private void notifyNewOreVein(OreVeinPosition oreVeinPosition) { final String location = "(" + (oreVeinPosition.getBlockX() + 8) + "," + (oreVeinPosition.getBlockZ() + 8) + ")"; final IChatComponent veinNotification = new ChatComponentTranslation( "visualprospecting.vein.prospected", - oreVeinPosition.veinType.getPrimaryOreName(), + oreVeinPosition.veinType.getVeinName(), location); veinNotification.getChatStyle().setItalic(true); veinNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java index 8956c20b..d6d60200 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java @@ -28,13 +28,6 @@ public GregTechOreMaterialProvider(Materials material) { this.primaryOreName = material.mLocalizedName; } - GregTechOreMaterialProvider() { - material = Materials._NULL; - primaryOreColor = 0; - primaryOreName = ""; - containedOres = ImmutableList.of(); - } - @Override @SideOnly(Side.CLIENT) public IIcon getIcon() { @@ -59,6 +52,7 @@ public ImmutableList getContainedOres(ShortCollection ores) { if (containedOres == null) { List temp = new ArrayList<>(); for (short meta : ores) { + if (meta < 0) break; Materials material = GregTechAPI.sGeneratedMaterials[meta]; if (material == null) continue; temp.add(material.mLocalizedName); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 4b3244f6..7737e97f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -8,6 +8,7 @@ import com.google.common.collect.ImmutableList; import com.sinthoras.visualprospecting.Tags; +import gregtech.api.enums.Materials; import gregtech.common.OreMixBuilder; import it.unimi.dsi.fastutil.shorts.ShortArraySet; import it.unimi.dsi.fastutil.shorts.ShortCollection; @@ -32,11 +33,12 @@ public class VeinType { private final ShortSet oresAsSet = new ShortArraySet(); private final List allowedDims = new ArrayList<>(); private boolean isHighlighted = true; + private final String localizedName; // Available after VisualProspecting post GT initialization public static final VeinType NO_VEIN = new VeinType( Tags.ORE_MIX_NONE_NAME, - new GregTechOreMaterialProvider(), + new GregTechOreMaterialProvider(Materials._NULL), 0, (short) -1, (short) -1, @@ -52,18 +54,20 @@ public VeinType(String name, IOreMaterialProvider oreMaterialProvider, int block this.name = name; this.oreMaterialProvider = oreMaterialProvider; this.blockSize = blockSize; - this.minBlockY = minBlockY; - this.maxBlockY = maxBlockY; + this.minBlockY = Math.max(0, minBlockY); + this.maxBlockY = Math.min(255, maxBlockY); oresAsSet.add(this.primaryOreMeta = primaryOreMeta); oresAsSet.add(this.secondaryOreMeta = secondaryOreMeta); oresAsSet.add(this.inBetweenOreMeta = inBetweenOreMeta); oresAsSet.add(this.sporadicOreMeta = sporadicOreMeta); + localizedName = oreMaterialProvider.getLocalizedName(); allowedDims.add(dimName); } public VeinType(OreMixBuilder oreMix) { name = oreMix.oreMixName; - oreMaterialProvider = new GregTechOreMaterialProvider(oreMix.primary); + oreMaterialProvider = new GregTechOreMaterialProvider(oreMix.representative); + localizedName = oreMix.localizedName; blockSize = oreMix.size; oresAsSet.add(primaryOreMeta = (short) oreMix.primary.mMetaItemSubID); oresAsSet.add(secondaryOreMeta = (short) oreMix.secondary.mMetaItemSubID); @@ -106,8 +110,8 @@ public ImmutableList getOreMaterialNames() { return oreMaterialProvider.getContainedOres(oresAsSet); } - public String getPrimaryOreName() { - return oreMaterialProvider.getLocalizedName(); + public String getVeinName() { + return localizedName; } public ShortSet getOresAtLayer(int layerBlockY) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index f90a8312..d2f92b35 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -3,14 +3,19 @@ import static com.sinthoras.visualprospecting.Utils.*; import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.OptionalInt; import java.util.regex.Pattern; import net.minecraft.util.EnumChatFormatting; +import org.apache.commons.lang3.StringUtils; + import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; @@ -49,9 +54,15 @@ public void run() { } for (BWOreLayer vein : BWOreLayer.sList) { - final IOreMaterialProvider oreMaterialProvider = (vein.bwOres & 0b1000) == 0 - ? new GregTechOreMaterialProvider(getGregTechMaterial((short) vein.mPrimaryMeta)) - : new BartworksOreMaterialProvider(Werkstoff.werkstoffHashMap.get((short) vein.mPrimaryMeta)); + final IOreMaterialProvider oreMaterialProvider; + if (containsBartworksOres(vein.bwOres)) { + oreMaterialProvider = getRepresentativeProvider( + vein.mWorldGenName, + new int[] { vein.mPrimaryMeta, vein.mSecondaryMeta, vein.mBetweenMeta, vein.mSporadicMeta }); + } else { + oreMaterialProvider = new GregTechOreMaterialProvider( + GregTechAPI.sGeneratedMaterials[(short) vein.mPrimaryMeta]); + } veinTypes.add( new VeinType( vein.mWorldGenName, @@ -61,8 +72,8 @@ public void run() { (short) vein.mSecondaryMeta, (short) vein.mBetweenMeta, (short) vein.mSporadicMeta, - Math.max(0, vein.mMinY), - Math.min(255, vein.mMaxY), + vein.mMinY, + vein.mMaxY, vein.getDimName())); } @@ -81,16 +92,6 @@ public void run() { saveVeinTypeStorageInfo(); } - private Materials getGregTechMaterial(short metaId) { - final Materials material = GregTechAPI.sGeneratedMaterials[metaId]; - if (material == null) { - // Some materials are not registered in dev when their usage mod is not available. - return Materials.getAll().stream().filter(m -> m.mMetaItemSubID == metaId).findAny() - .orElse(Materials._NULL); - } - return material; - } - public static VeinType getVeinType(short veinTypeId) { return veinTypeLookupTableForIds.getOrDefault(veinTypeId, VeinType.NO_VEIN); } @@ -123,7 +124,8 @@ public static void recalculateNEISearch() { for (VeinType veinType : veinTypes) { if (veinType == VeinType.NO_VEIN) continue; if (isSearchActive && !searchString.isEmpty()) { - List searchableStrings = veinType.getOreMaterialNames(); + List searchableStrings = new ArrayList<>(veinType.getOreMaterialNames()); + searchableStrings.add(veinType.getVeinName()); final boolean match = searchableStrings.stream() .map(EnumChatFormatting::getTextWithoutFormattingCodes).map(String::toLowerCase) .anyMatch(searchableString -> filterPattern.matcher(searchableString).find()); @@ -135,4 +137,27 @@ public static void recalculateNEISearch() { } } } + + private static boolean containsBartworksOres(byte bwOres) { + return (bwOres & 0b1111) != 0; + } + + private static IOreMaterialProvider getRepresentativeProvider(String veinName, int[] ores) { + for (int meta : ores) { + Werkstoff werkstoff = Werkstoff.werkstoffHashMap.get((short) meta); + if (werkstoff == null) continue; + String defaultName = werkstoff.getDefaultName(); + // also try lobbing a few characters off the end of the vein name because bart + if (StringUtils.endsWithIgnoreCase(veinName, defaultName) + || StringUtils.containsIgnoreCase(veinName, defaultName.substring(0, defaultName.length() - 2))) { + return new BartworksOreMaterialProvider(werkstoff); + } + } + + Werkstoff primaryMaterial = Arrays.stream(ores).mapToObj(meta -> Werkstoff.werkstoffHashMap.get((short) meta)) + .filter(Objects::nonNull).findFirst().orElse(null); + + return primaryMaterial == null ? new GregTechOreMaterialProvider(Materials._NULL) + : new BartworksOreMaterialProvider(primaryMaterial); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java index 3124c913..a4372506 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/VeinDatabase.java @@ -22,7 +22,7 @@ public Optional getVeinName(int dimensionId, ChunkCoordIntPair coordinat // capture which language the original cover attaching player is using, maybe. (I think this requires // reflection, of course. Why should things be easy?) Even then, it wouldn't help in a multiplayer scenario // with users having different locales. - return Optional.of(oreVein.veinType.getPrimaryOreName()); + return Optional.of(oreVein.veinType.getVeinName()); } else { return Optional.empty(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index 3ce125bf..893d064f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -31,7 +31,7 @@ public class OreVeinLocation implements IWaypointAndLocationProvider { public OreVeinLocation(OreVeinPosition oreVeinPosition) { this.oreVeinPosition = oreVeinPosition; - name = EnumChatFormatting.WHITE + oreVeinPosition.veinType.getPrimaryOreName(); + name = EnumChatFormatting.WHITE + oreVeinPosition.veinType.getVeinName(); materialNames = oreVeinPosition.veinType.getOreMaterialNames().stream() .map(materialName -> EnumChatFormatting.GRAY + materialName).collect(Collectors.toList()); } @@ -43,7 +43,7 @@ public Waypoint toWaypoint() { 65, oreVeinPosition.getBlockZ(), oreVeinPosition.dimensionId, - I18n.format("visualprospecting.tracked", oreVeinPosition.veinType.getPrimaryOreName()), + I18n.format("visualprospecting.tracked", oreVeinPosition.veinType.getVeinName()), getColor()); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java index 80b43996..97180215 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java @@ -29,7 +29,7 @@ public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { TreeSet dim = new TreeSet<>(); dim.add(pos.dimensionId); VoxelMapWaypointManager.addVoxelMapWaypoint( - pos.veinType.getPrimaryOreName(), // name + pos.veinType.getVeinName(), // name pos.getBlockX(), // X pos.getBlockZ(), // Z getY(), // Y diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java index a7c589f6..bb10f0a0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java @@ -77,7 +77,7 @@ public GT_MetaTileEntity_ScannerMixin() { if (veinId < foundOreVeins.size()) { final OreVeinPosition oreVein = foundOreVeins.get(veinId); pageString.append(oreVein.getBlockX()).append(",").append(oreVein.getBlockZ()).append(" - ") - .append(oreVein.veinType.getPrimaryOreName()).append("\n"); + .append(oreVein.veinType.getVeinName()).append("\n"); } } String pageCounter = numberOfPages > 1 ? String.format(" %d/%d", pageNumber + 1, numberOfPages) From 4af527b2ad784f0ca7bf43bcd8a2b7db4ff734ed Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Mon, 30 Sep 2024 20:10:28 +0200 Subject: [PATCH 074/132] Fix client cache being removed after changing username (#61) * fix client cache being removed after changing username * merge directories if new cache already exists (existing files are preserved) --- .../database/ClientCache.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index 1d728e07..41fdfca6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -1,6 +1,7 @@ package com.sinthoras.visualprospecting.database; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -14,6 +15,8 @@ import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; +import org.apache.commons.io.FileUtils; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; @@ -29,9 +32,15 @@ public class ClientCache extends WorldCache { protected File getStorageDirectory() { final EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer; - return new File( - Utils.getSubDirectory(Tags.CLIENT_DIR), + File oldCacheDir = new File( + Tags.CLIENT_DIR, player.getDisplayName() + "_" + player.getPersistentID().toString()); + File newCacheDir = new File(Tags.CLIENT_DIR, player.getPersistentID().toString()); + if (oldCacheDir.exists()) { + convertOldCache(oldCacheDir, newCacheDir); + } + + return newCacheDir; } private void notifyNewOreVein(OreVeinPosition oreVeinPosition) { @@ -164,4 +173,21 @@ public List getAllUndergroundFluids() { } return allUndergroundFluids; } + + private static void convertOldCache(File oldCache, File newCache) { + if (!oldCache.exists()) return; + File[] files = oldCache.listFiles(); + if (files != null && files.length > 0 && newCache.exists()) { + for (File file : files) { + if (!file.isDirectory()) continue; + try { + FileUtils.copyDirectoryToDirectory(file, newCache); + } catch (IOException ignored) {} + } + Utils.deleteDirectoryRecursively(oldCache); + } else { + // noinspection ResultOfMethodCallIgnored + oldCache.renameTo(newCache); + } + } } From a7f49b2fe346699b319bfc426f2b875eb6010cac Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Mon, 30 Sep 2024 20:14:02 +0200 Subject: [PATCH 075/132] update --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 22f3792f..eea7ef65 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.15:dev') - api('com.github.GTNewHorizons:GTNHLib:0.5.11:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.21:dev') + api('com.github.GTNewHorizons:GTNHLib:0.5.12:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.25:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } From e49497368ca07ec4529988e9b95c3cfc62c52929 Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Fri, 10 Jan 2025 19:11:54 +0100 Subject: [PATCH 076/132] Save vein cache using IO thread (#63) --- .../com/sinthoras/visualprospecting/Utils.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 573077eb..770f0962 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -24,6 +24,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.storage.ThreadedFileIOBase; import org.jetbrains.annotations.NotNull; @@ -141,11 +142,14 @@ public static void writeMapToFile(File file, Map map) { } public static void writeNBT(File file, NBTTagCompound tag) { - try (FileOutputStream stream = new FileOutputStream(newFile(file))) { - CompressedStreamTools.writeCompressed(tag, stream); - } catch (Exception ex) { - ex.printStackTrace(); - } + ThreadedFileIOBase.threadedIOInstance.queueIO(() -> { + try (FileOutputStream stream = new FileOutputStream(newFile(file))) { + CompressedStreamTools.writeCompressed(tag, stream); + } catch (Exception ex) { + ex.printStackTrace(); + } + return false; + }); } public static File newFile(File file) { From b260e56a870205b25f98b3b1924d5d5352615f4a Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Sat, 11 Jan 2025 07:30:37 +0100 Subject: [PATCH 077/132] Save ore veins with their string id (#62) Co-authored-by: Martin Robertz --- dependencies.gradle | 4 +- gradle/wrapper/gradle-wrapper.jar | Bin 43504 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- .../sinthoras/visualprospecting/VPMod.java | 16 ++-- .../database/DimensionCache.java | 74 ++++++++++++++-- .../database/WorldCache.java | 25 ++---- .../database/cachebuilder/ChunkAnalysis.java | 2 +- .../cachebuilder/DetailedChunkAnalysis.java | 2 +- .../database/veintypes/VeinType.java | 1 - .../database/veintypes/VeinTypeCaching.java | 82 ++++-------------- .../visualprospecting/hooks/HooksFML.java | 5 ++ .../visualprospecting/hooks/HooksShared.java | 8 +- 13 files changed, 116 insertions(+), 107 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index eea7ef65..cedf246a 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.15:dev') - api('com.github.GTNewHorizons:GTNHLib:0.5.12:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.50.25:dev') + api('com.github.GTNewHorizons:GTNHLib:0.6.0:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.22:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2c3521197d7c4586c843d1d3e9090525f1898cde..a4b76b9530d66f5e68d973ea569d8e19de379189 100644 GIT binary patch delta 3990 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 09523c0e..e2847c82 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index 3d3ba12c..0147a994 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.27' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.30' } diff --git a/src/main/java/com/sinthoras/visualprospecting/VPMod.java b/src/main/java/com/sinthoras/visualprospecting/VPMod.java index d8eec694..fee72a22 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VPMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/VPMod.java @@ -6,6 +6,7 @@ import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.SidedProxy; import cpw.mods.fml.common.event.FMLInitializationEvent; +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.event.FMLServerAboutToStartEvent; @@ -30,55 +31,50 @@ public class VPMod { // preInit "Run before anything else. Read your config, create blocks, items, // etc, and register them with the GameRegistry." public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { - VP.debug("Registered sided proxy for: " + (Utils.isLogicalClient() ? "Client" : "Dedicated server")); - VP.debug("preInit()" + event.getModMetadata().name); proxy.fmlLifeCycleEvent(event); } @Mod.EventHandler // load "Do your mod setup. Build whatever data structures you care about. Register recipes." public void fmlLifeCycleEvent(FMLInitializationEvent event) { - VP.debug("init()"); proxy.fmlLifeCycleEvent(event); } @Mod.EventHandler // postInit "Handle interaction with other mods, complete your setup based on this." public void fmlLifeCycle(FMLPostInitializationEvent event) { - VP.debug("postInit()"); - VP.debug("Registering with the GT5U ore vein database"); VisualProspectingDatabase.registerDatabase(new VeinDatabase()); proxy.fmlLifeCycleEvent(event); } + @Mod.EventHandler + public void fmlLifeCycle(FMLLoadCompleteEvent event) { + proxy.fmlLifeCycleEvent(event); + } + @Mod.EventHandler public void fmlLifeCycle(FMLServerAboutToStartEvent event) { - VP.debug("Server about to start"); proxy.fmlLifeCycleEvent(event); } @Mod.EventHandler // register server commands in this event handler public void fmlLifeCycle(FMLServerStartingEvent event) { - VP.debug("Server starting"); proxy.fmlLifeCycleEvent(event); } @Mod.EventHandler public void fmlLifeCycle(FMLServerStartedEvent event) { - VP.debug("Server started"); proxy.fmlLifeCycleEvent(event); } @Mod.EventHandler public void fmlLifeCycle(FMLServerStoppingEvent event) { - VP.debug("Server stopping"); proxy.fmlLifeCycleEvent(event); } @Mod.EventHandler public void fmlLifeCycle(FMLServerStoppedEvent event) { - VP.debug("Server stopped"); proxy.fmlLifeCycleEvent(event); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index 9e1b1fce..f7c2979f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -1,8 +1,15 @@ package com.sinthoras.visualprospecting.database; +import java.io.File; +import java.io.IOException; +import java.io.Reader; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.Collection; +import java.util.Map; + +import javax.annotation.Nullable; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; @@ -11,6 +18,9 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; @@ -18,6 +28,9 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; +import it.unimi.dsi.fastutil.shorts.Short2ObjectMaps; +import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; public class DimensionCache { @@ -27,10 +40,13 @@ public enum UpdateResult { New } + private static final File oldIdFile = new File(Tags.VISUALPROSPECTING_DIR, "veintypesLUT"); + private static Short2ObjectMap idConversionMap; private final Long2ObjectMap oreChunks = new Long2ObjectOpenHashMap<>(); private final Long2ObjectMap undergroundFluids = new Long2ObjectOpenHashMap<>(); public final int dimensionId; private boolean isDirty = false; + private boolean preventSaving = false; public DimensionCache(int dimensionId) { this.dimensionId = dimensionId; @@ -51,7 +67,7 @@ private NBTTagCompound saveOres() { NBTTagCompound veinCompound = new NBTTagCompound(); veinCompound.setInteger("chunkX", vein.chunkX); veinCompound.setInteger("chunkZ", vein.chunkZ); - veinCompound.setShort("veinTypeId", vein.veinType.veinId); + veinCompound.setString("veinTypeName", vein.veinType.name); veinCompound.setBoolean("depleted", vein.isDepleted()); compound.setTag(String.valueOf(getOreVeinKey(vein.chunkX, vein.chunkZ)), veinCompound); } @@ -82,9 +98,16 @@ public void loadFromNbt(NBTTagCompound compound) { NBTTagCompound veinCompound = (NBTTagCompound) base; int chunkX = veinCompound.getInteger("chunkX"); int chunkZ = veinCompound.getInteger("chunkZ"); - short veinTypeId = veinCompound.getShort("veinTypeId"); boolean depleted = veinCompound.getBoolean("depleted"); - VeinType veinType = VeinTypeCaching.getVeinType(veinTypeId); + VeinType veinType; + if (veinCompound.hasKey("veinTypeId")) { + veinType = getVeinFromId(veinCompound.getShort("veinTypeId")); + if (veinType == null) return; + markDirty(); + } else { + veinType = VeinTypeCaching.getVeinType(veinCompound.getString("veinTypeName")); + } + oreChunks.put( getOreVeinKey(chunkX, chunkZ), new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); @@ -115,7 +138,9 @@ void loadLegacy(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBuffer) final int chunkZ = oreChunksBuffer.getInt(); final short veinTypeId = oreChunksBuffer.getShort(); final boolean depleted = (veinTypeId & 0x8000) > 0; - final VeinType veinType = VeinTypeCaching.getVeinType((short) (veinTypeId & 0x7FFF)); + final VeinType veinType = getVeinFromId((short) (veinTypeId & 0x7FFF)); + if (veinType == null) return; + oreChunks.put( getOreVeinKey(chunkX, chunkZ), new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); @@ -220,7 +245,7 @@ public Collection getAllUndergroundFluids() { } public boolean isDirty() { - return isDirty; + return isDirty && !preventSaving; } public void markDirty() { @@ -245,4 +270,43 @@ public void clearOreVeins(int startChunkX, int startChunkZ, int endChunkX, int e return withinX && withinZ; }); } + + private @Nullable VeinType getVeinFromId(short veinTypeId) { + final String veinTypeName = getIdConversionMap().get(veinTypeId); + if (veinTypeName == null) { + preventSaving = true; + VP.LOG.warn( + "Not loading ores in dimension {}. Couldn't find vein type for id {}, file {} may be missing.", + dimensionId, + veinTypeId, + oldIdFile.getAbsolutePath()); + return null; + } + return VeinTypeCaching.getVeinType(veinTypeName); + } + + private static Short2ObjectMap getIdConversionMap() { + if (idConversionMap != null) { + return idConversionMap; + } + + if (!oldIdFile.exists()) { + return Short2ObjectMaps.emptyMap(); + } + try { + final Gson gson = new Gson(); + final Reader reader = Files.newBufferedReader(oldIdFile.toPath()); + final Map map = gson.fromJson(reader, new TypeToken>() {}.getType()); + reader.close(); + Short2ObjectMap result = new Short2ObjectOpenHashMap<>(); + result.put((short) 0, Tags.ORE_MIX_NONE_NAME); + for (Map.Entry entry : map.entrySet()) { + result.put(entry.getValue().shortValue(), entry.getKey()); + } + return idConversionMap = result; + } catch (IOException e) { + e.printStackTrace(); + return Short2ObjectMaps.emptyMap(); + } + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index 685974e4..365c7778 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -18,7 +18,6 @@ public abstract class WorldCache { protected final Int2ObjectMap dimensions = new Int2ObjectOpenHashMap<>(); - private boolean needsSaving = false; protected File worldCache; private boolean isLoaded = false; @@ -86,25 +85,20 @@ private boolean loadLegacyVeinCache(File worldCacheDirectory) { Utils.deleteDirectoryRecursively(oreVeinCacheDirectory); Utils.deleteDirectoryRecursively(undergroundFluidCacheDirectory); - needsSaving = true; saveVeinCache(); return true; } public void saveVeinCache() { - if (needsSaving) { - for (DimensionCache dimension : dimensions.values()) { - if (!dimension.isDirty()) continue; - File dimFile = new File(worldCache, "DIM" + dimension.dimensionId + ".dat"); - Utils.writeNBT(dimFile, dimension.saveToNbt()); - } - needsSaving = false; + for (DimensionCache dimension : dimensions.values()) { + if (!dimension.isDirty()) continue; + File dimFile = new File(worldCache, "DIM" + dimension.dimensionId + ".dat"); + Utils.writeNBT(dimFile, dimension.saveToNbt()); } } public void reset() { dimensions.clear(); - needsSaving = false; isLoaded = false; } @@ -123,7 +117,6 @@ public void resetSome(int dimID, int startX, int startZ, int endX, int endZ) { DimensionCache dim = dimensions.get(dimID); if (dim != null) { dim.clearOreVeins(startX, startZ, endX, endZ); - needsSaving = true; isLoaded = false; } } @@ -142,14 +135,9 @@ public void resetSpawnChunks(ChunkCoordinates spawn, int dimID) { resetSome(dimID, startX, startZ, endX, endZ); } - private DimensionCache.UpdateResult updateSaveFlag(DimensionCache.UpdateResult updateResult) { - needsSaving |= updateResult != DimensionCache.UpdateResult.AlreadyKnown; - return updateResult; - } - protected DimensionCache.UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) { DimensionCache dimension = dimensions.computeIfAbsent(oreVeinPosition.dimensionId, DimensionCache::new); - return updateSaveFlag(dimension.putOreVein(oreVeinPosition)); + return dimension.putOreVein(oreVeinPosition); } protected void toggleOreVein(int dimensionId, int chunkX, int chunkZ) { @@ -157,7 +145,6 @@ protected void toggleOreVein(int dimensionId, int chunkX, int chunkZ) { if (dimension != null) { dimension.toggleOreVein(chunkX, chunkZ); } - needsSaving = true; } public OreVeinPosition getOreVein(int dimensionId, int chunkX, int chunkZ) { @@ -170,7 +157,7 @@ public OreVeinPosition getOreVein(int dimensionId, int chunkX, int chunkZ) { protected DimensionCache.UpdateResult putUndergroundFluids(final UndergroundFluidPosition undergroundFluid) { DimensionCache dimension = dimensions.computeIfAbsent(undergroundFluid.dimensionId, DimensionCache::new); - return updateSaveFlag(dimension.putUndergroundFluid(undergroundFluid)); + return dimension.putUndergroundFluid(undergroundFluid); } public UndergroundFluidPosition getUndergroundFluid(int dimensionId, int chunkX, int chunkZ) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java index 02af198a..4b04543e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java @@ -63,7 +63,7 @@ public void processMinecraftChunk(final NBTTagList tileEntities) { public boolean matchesSingleVein() { if (oreCounts.isEmpty()) return true; if (oreCounts.size() > 4) return false; - VeinTypeCaching.veinTypes.stream() + VeinTypeCaching.getVeinTypes().stream() .filter(vein -> vein.containsAllFoundOres(oreCounts.keySet(), dimName, primaryMeta, minVeinBlockY)) .forEach(matchedVeins::add); return matchedVeins.size() <= 1; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index 68958a9a..3a9799c1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -161,7 +161,7 @@ public VeinType getMatchedVein() { .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(Map.Entry::getKey).findFirst(); if (!dominantOre.isPresent()) return VeinType.NO_VEIN; - for (VeinType veinType : VeinTypeCaching.veinTypes) { + for (VeinType veinType : VeinTypeCaching.getVeinTypes()) { if (veinType.matchesWithSpecificPrimaryOrSecondary(allOres.keySet(), dimName, dominantOre.get())) { matchedVeins.add(veinType); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 7737e97f..8c54b8ce 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -21,7 +21,6 @@ public class VeinType { public static final int veinHeight = 9; public final String name; - public short veinId; public final IOreMaterialProvider oreMaterialProvider; public final int blockSize; public final short primaryOreMeta; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index d2f92b35..9224634b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -2,22 +2,19 @@ import static com.sinthoras.visualprospecting.Utils.*; -import java.io.File; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; +import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Objects; -import java.util.OptionalInt; import java.util.regex.Pattern; import net.minecraft.util.EnumChatFormatting; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.Utils; import bartworks.system.material.Werkstoff; import bartworks.system.oregen.BWOreLayer; @@ -26,31 +23,18 @@ import gregtech.api.GregTechAPI; import gregtech.api.enums.Materials; import gregtech.api.enums.OreMixes; -import it.unimi.dsi.fastutil.objects.Object2ShortMap; -import it.unimi.dsi.fastutil.objects.Object2ShortOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import it.unimi.dsi.fastutil.objects.ObjectSet; -import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; -import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; - -public class VeinTypeCaching implements Runnable { - - private static final Short2ObjectMap veinTypeLookupTableForIds = new Short2ObjectOpenHashMap<>(); - private static final Map veinTypeLookupTableForNames = new HashMap<>(); - private static final Object2ShortMap veinTypeStorageInfo = new Object2ShortOpenHashMap<>(); - public static ObjectSet veinTypes; - - // BartWorks initializes veins in FML preInit - // GalacticGreg initializes veins in FML postInit, but only copies all base game veins to make them available on all - // planets - // GregTech initializes veins in a thread in FML postInit - // Therefore, this method must be called after GregTech postInit - public void run() { - veinTypes = new ObjectOpenHashSet<>(); - veinTypes.add(VeinType.NO_VEIN); +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +public class VeinTypeCaching { + + private static final Object2ObjectMap veinTypes = new Object2ObjectOpenHashMap<>(); + + public static void init() { + veinTypes.put(Tags.ORE_MIX_NONE_NAME, VeinType.NO_VEIN); for (OreMixes mix : OreMixes.values()) { - veinTypes.add(new VeinType(mix.oreMixBuilder)); + veinTypes.put(mix.oreMixBuilder.oreMixName, new VeinType(mix.oreMixBuilder)); } for (BWOreLayer vein : BWOreLayer.sList) { @@ -63,7 +47,8 @@ public void run() { oreMaterialProvider = new GregTechOreMaterialProvider( GregTechAPI.sGeneratedMaterials[(short) vein.mPrimaryMeta]); } - veinTypes.add( + veinTypes.put( + vein.mWorldGenName, new VeinType( vein.mWorldGenName, oreMaterialProvider, @@ -76,43 +61,14 @@ public void run() { vein.mMaxY, vein.getDimName())); } - - // Assign veinTypeIds for efficient storage - loadVeinTypeStorageInfo(); - - final OptionalInt maxVeinTypeIdOptional = veinTypeStorageInfo.values().intStream().max(); - short maxVeinTypeId = (short) (maxVeinTypeIdOptional.orElse(0)); - - for (VeinType veinType : veinTypes) { - veinType.veinId = veinTypeStorageInfo.getOrDefault(veinType.name, ++maxVeinTypeId); - veinTypeStorageInfo.putIfAbsent(veinType.name, veinType.veinId); - veinTypeLookupTableForIds.put(veinType.veinId, veinType); - veinTypeLookupTableForNames.put(veinType.name, veinType); - } - saveVeinTypeStorageInfo(); - } - - public static VeinType getVeinType(short veinTypeId) { - return veinTypeLookupTableForIds.getOrDefault(veinTypeId, VeinType.NO_VEIN); - } - - public static VeinType getVeinType(String veinTypeName) { - return veinTypeLookupTableForNames.getOrDefault(veinTypeName, VeinType.NO_VEIN); - } - - private static File getVeinTypeStorageInfoFile() { - final File directory = Utils.getSubDirectory(Tags.VISUALPROSPECTING_DIR); - // noinspection ResultOfMethodCallIgnored - directory.mkdirs(); - return new File(directory, "veintypesLUT"); } - private static void loadVeinTypeStorageInfo() { - veinTypeStorageInfo.putAll(Utils.readFileToMap(getVeinTypeStorageInfoFile())); + public static @NotNull VeinType getVeinType(String veinTypeName) { + return veinTypes.getOrDefault(veinTypeName, VeinType.NO_VEIN); } - private static void saveVeinTypeStorageInfo() { - Utils.writeMapToFile(getVeinTypeStorageInfoFile(), veinTypeStorageInfo); + public static Collection getVeinTypes() { + return veinTypes.values(); } public static void recalculateNEISearch() { @@ -121,7 +77,7 @@ public static void recalculateNEISearch() { final String searchString = NEIClientConfig.getSearchExpression().toLowerCase(); final Pattern filterPattern = SearchField.getPattern(searchString); - for (VeinType veinType : veinTypes) { + for (VeinType veinType : veinTypes.values()) { if (veinType == VeinType.NO_VEIN) continue; if (isSearchActive && !searchString.isEmpty()) { List searchableStrings = new ArrayList<>(veinType.getOreMaterialNames()); diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java index 31c6297f..a44edda9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java @@ -22,6 +22,11 @@ public void onEvent(FMLNetworkEvent.ClientConnectedToServerEvent event) { ClientCache.instance.reset(); } + @SubscribeEvent + public void onEvent(FMLNetworkEvent.ClientDisconnectionFromServerEvent event) { + ClientCache.instance.saveVeinCache(); + } + @SubscribeEvent public void onEvent(TickEvent event) { TaskManager.instance.onTick(); diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index 273283e9..86638910 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -25,6 +25,7 @@ import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; +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.event.FMLServerAboutToStartEvent; @@ -35,7 +36,6 @@ import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.Side; -import gregtech.api.GregTechAPI; public class HooksShared { @@ -82,8 +82,10 @@ public void fmlLifeCycleEvent(FMLInitializationEvent event) { } // postInit "Handle interaction with other mods, complete your setup based on this." - public void fmlLifeCycleEvent(FMLPostInitializationEvent event) { - GregTechAPI.sAfterGTPostload.add(new VeinTypeCaching()); + public void fmlLifeCycleEvent(FMLPostInitializationEvent event) {} + + public void fmlLifeCycleEvent(FMLLoadCompleteEvent event) { + VeinTypeCaching.init(); } public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) { From 065f30913b1d3183db82e6bd8cd9bdbac5c74a21 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sat, 11 Jan 2025 09:09:11 +0100 Subject: [PATCH 078/132] update --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index cedf246a..3a1e47b6 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.15:dev') - api('com.github.GTNewHorizons:GTNHLib:0.6.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.22:dev') + api('com.github.GTNewHorizons:GTNHLib:0.6.1:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.63:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } From cdcc460e2a06327ed165ab8eda28eab8515765e4 Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Wed, 19 Feb 2025 07:08:31 +0100 Subject: [PATCH 079/132] Highlight searched underground fluids (#64) --- .../sinthoras/visualprospecting/Utils.java | 14 ++++ .../database/veintypes/VeinTypeCaching.java | 10 +-- .../visualprospecting/hooks/HooksClient.java | 2 - .../UndergroundFluidChunkLayerManager.java | 52 ------------ .../layers/UndergroundFluidLayerManager.java | 62 +++++++++++++- .../UndergroundFluidChunkLocation.java | 62 -------------- .../locations/UndergroundFluidLocation.java | 13 +++ .../UndergroundFluidChunkRenderStep.java | 38 --------- .../render/UndergroundFluidRenderStep.java | 84 +++++++++++++++++-- 9 files changed, 168 insertions(+), 169 deletions(-) delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidChunkRenderStep.java diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 770f0962..4edfea16 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -16,6 +16,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -33,6 +34,8 @@ import com.gtnewhorizon.gtnhlib.util.CoordinatePacker; import com.sinthoras.visualprospecting.hooks.HooksClient; +import codechicken.nei.NEIClientConfig; +import codechicken.nei.SearchField; import cpw.mods.fml.common.Loader; import gregtech.common.GTWorldgenerator; @@ -231,4 +234,15 @@ private static ByteBuffer readFileToBuffer(File file) { return null; } } + + public static @Nullable Pattern getNEISearchPattern() { + final String searchString = NEIClientConfig.getSearchExpression().toLowerCase(); + if (!SearchField.searchInventories() || searchString.isEmpty()) { + return null; + } + + final String unquotedRegex = SearchField.getPattern(searchString).pattern().replace("\\Q", "") + .replace("\\E", ""); + return Pattern.compile(unquotedRegex, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index 9224634b..9cde9861 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -15,11 +15,10 @@ import org.jetbrains.annotations.NotNull; import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.Utils; import bartworks.system.material.Werkstoff; import bartworks.system.oregen.BWOreLayer; -import codechicken.nei.NEIClientConfig; -import codechicken.nei.SearchField; import gregtech.api.GregTechAPI; import gregtech.api.enums.Materials; import gregtech.api.enums.OreMixes; @@ -73,13 +72,10 @@ public static Collection getVeinTypes() { public static void recalculateNEISearch() { if (isNEIInstalled()) { - final boolean isSearchActive = SearchField.searchInventories(); - final String searchString = NEIClientConfig.getSearchExpression().toLowerCase(); - final Pattern filterPattern = SearchField.getPattern(searchString); - + final Pattern filterPattern = Utils.getNEISearchPattern(); for (VeinType veinType : veinTypes.values()) { if (veinType == VeinType.NO_VEIN) continue; - if (isSearchActive && !searchString.isEmpty()) { + if (filterPattern != null) { List searchableStrings = new ArrayList<>(veinType.getOreMaterialNames()); searchableStrings.add(veinType.getVeinName()); final boolean match = searchableStrings.stream() diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java index 4ac23cf0..dc24e1b9 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java @@ -8,7 +8,6 @@ import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.ResetClientCacheCommand; import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; -import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidChunkLayerManager; import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.voxelmap.VoxelMapEventHandler; @@ -76,7 +75,6 @@ public void registerMapLayers() { NavigatorApi.registerLayerManager(OreVeinLayerManager.instance); NavigatorApi.registerLayerManager(UndergroundFluidLayerManager.instance); - NavigatorApi.registerLayerManager(UndergroundFluidChunkLayerManager.instance); if (Util.isVoxelMapInstalled()) { MinecraftForge.EVENT_BUS.register(new VoxelMapEventHandler()); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java deleted file mode 100644 index 63430bf2..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidChunkLayerManager.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.layers; - -import org.jetbrains.annotations.Nullable; - -import com.gtnewhorizons.navigator.api.model.SupportedMods; -import com.gtnewhorizons.navigator.api.model.layers.LayerManager; -import com.gtnewhorizons.navigator.api.model.layers.LayerRenderer; -import com.gtnewhorizons.navigator.api.model.layers.UniversalLayerRenderer; -import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.ClientCache; -import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; -import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; -import com.sinthoras.visualprospecting.integration.model.render.UndergroundFluidChunkRenderStep; - -public class UndergroundFluidChunkLayerManager extends LayerManager { - - public static final UndergroundFluidChunkLayerManager instance = new UndergroundFluidChunkLayerManager(); - - public UndergroundFluidChunkLayerManager() { - super(UndergroundFluidButtonManager.instance); - } - - @Nullable - @Override - protected LayerRenderer addLayerRenderer(LayerManager manager, SupportedMods mods) { - return new UniversalLayerRenderer(manager).withRenderStep( - location -> new UndergroundFluidChunkRenderStep((UndergroundFluidChunkLocation) location)); - } - - @Override - protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { - if (chunkX % VP.undergroundFluidSizeChunkX != 0 || chunkZ % VP.undergroundFluidSizeChunkZ != 0) { - return null; - } - final UndergroundFluidPosition undergroundFluid = ClientCache.instance.getUndergroundFluid(dim, chunkX, chunkZ); - if (!undergroundFluid.isProspected()) return null; - generateExtraFluidChunks(chunkX, chunkZ, dim, undergroundFluid); - return new UndergroundFluidChunkLocation(chunkX, chunkZ, dim, undergroundFluid, 0, 0); - } - - private void generateExtraFluidChunks(int chunkX, int chunkZ, int dim, UndergroundFluidPosition undergroundFluid) { - for (int offsetX = 0; offsetX < VP.undergroundFluidSizeChunkX; offsetX++) { - for (int offsetZ = 0; offsetZ < VP.undergroundFluidSizeChunkZ; offsetZ++) { - if (offsetX == 0 && offsetZ == 0) continue; - addExtraLocation( - new UndergroundFluidChunkLocation(chunkX, chunkZ, dim, undergroundFluid, offsetX, offsetZ)); - } - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java index fa656856..923f132e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java @@ -1,5 +1,14 @@ package com.sinthoras.visualprospecting.integration.model.layers; +import static com.sinthoras.visualprospecting.Utils.isNEIInstalled; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; + import org.jetbrains.annotations.Nullable; import com.gtnewhorizons.navigator.api.model.SupportedMods; @@ -7,6 +16,7 @@ import com.gtnewhorizons.navigator.api.model.layers.LayerRenderer; import com.gtnewhorizons.navigator.api.model.layers.UniversalLayerRenderer; import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; +import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; @@ -14,9 +24,15 @@ import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; import com.sinthoras.visualprospecting.integration.model.render.UndergroundFluidRenderStep; +import gregtech.api.enums.UndergroundFluidNames; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSet; + public class UndergroundFluidLayerManager extends LayerManager { public static final UndergroundFluidLayerManager instance = new UndergroundFluidLayerManager(); + private static final ObjectSet highlightedFluids = new ObjectOpenHashSet<>(); + private boolean searching = false; public UndergroundFluidLayerManager() { super(UndergroundFluidButtonManager.instance); @@ -26,8 +42,46 @@ public UndergroundFluidLayerManager() { @Override protected LayerRenderer addLayerRenderer(LayerManager manager, SupportedMods mod) { return new UniversalLayerRenderer(manager) - .withRenderStep(location -> new UndergroundFluidRenderStep((UndergroundFluidLocation) location)) - .withRenderPriority(1); + .withRenderStep(location -> new UndergroundFluidRenderStep((UndergroundFluidLocation) location)); + } + + @Override + public void onOpenMap() { + if (!isNEIInstalled()) return; + highlightedFluids.clear(); + searching = false; + final Pattern filterPattern = Utils.getNEISearchPattern(); + if (filterPattern != null) { + searching = true; + for (UndergroundFluidNames fluidName : UndergroundFluidNames.values()) { + Fluid fluid = FluidRegistry.getFluid(fluidName.name); + if (fluid == null) continue; + for (String name : getFluidNames(fluid)) { + if (name != null && filterPattern.matcher(name.toLowerCase()).find()) { + highlightedFluids.add(fluid); + } + } + } + } + } + + private static List getFluidNames(Fluid fluid) { + List names = new ArrayList<>(); + names.add(fluid.getLocalizedName()); + names.add(fluid.getUnlocalizedName()); + names.add(fluid.getName()); + return names; + } + + @Override + public void updateElement(ILocationProvider location) { + UndergroundFluidLocation fluidLocation = (UndergroundFluidLocation) location; + fluidLocation.setActive(true); + if (isSearchActive()) { + boolean highlighted = highlightedFluids.contains(fluidLocation.getFluid()) + && fluidLocation.getMaxProduction() > 0; + fluidLocation.setActive(highlighted); + } } @Override @@ -48,4 +102,8 @@ protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { public int getElementSize() { return 8; } + + public boolean isSearchActive() { + return searching; + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java deleted file mode 100644 index 83a6b01a..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidChunkLocation.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.locations; - -import net.minecraftforge.fluids.Fluid; - -import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; - -public class UndergroundFluidChunkLocation implements ILocationProvider { - - private final int blockX; - private final int blockZ; - private final int dimensionId; - private final int offsetX; - private final int offsetZ; - private final UndergroundFluidPosition undergroundFluid; - - public UndergroundFluidChunkLocation(int chunkX, int chunkZ, int dimensionId, UndergroundFluidPosition fluid, - int offsetX, int offsetZ) { - blockX = Utils.coordChunkToBlock(chunkX + offsetX); - blockZ = Utils.coordChunkToBlock(chunkZ + offsetZ); - this.dimensionId = dimensionId; - this.offsetX = offsetX; - this.offsetZ = offsetZ; - this.undergroundFluid = fluid; - } - - public double getBlockX() { - return blockX + 0.5; - } - - public double getBlockZ() { - return blockZ + 0.5; - } - - public int getDimensionId() { - return dimensionId; - } - - public String getFluidAmountFormatted() { - if (getFluidAmount() >= 1000) { - return (getFluidAmount() / 1000) + "kL"; - } - return getFluidAmount() + "L"; - } - - public int getFluidAmount() { - return undergroundFluid.chunks[offsetX][offsetZ]; - } - - public Fluid getFluid() { - return undergroundFluid.fluid; - } - - public int getMaxAmountInField() { - return undergroundFluid.getMaxProduction(); - } - - public int getMinAmountInField() { - return undergroundFluid.getMinProduction(); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java index dfc50a4d..aec1b2e7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java @@ -8,6 +8,7 @@ public class UndergroundFluidLocation implements ILocationProvider { private final UndergroundFluidPosition undergroundFluidPosition; + private boolean active; public UndergroundFluidLocation(UndergroundFluidPosition undergroundFluidPosition) { this.undergroundFluidPosition = undergroundFluidPosition; @@ -36,7 +37,19 @@ public int getMaxProduction() { return undergroundFluidPosition.getMaxProduction(); } + public int[][] getChunks() { + return undergroundFluidPosition.chunks; + } + public Fluid getFluid() { return undergroundFluidPosition.fluid; } + + public void setActive(boolean active) { + this.active = active; + } + + public boolean isActive() { + return active; + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidChunkRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidChunkRenderStep.java deleted file mode 100644 index e9167db6..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidChunkRenderStep.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.sinthoras.visualprospecting.integration.model.render; - -import com.gtnewhorizons.navigator.api.model.steps.UniversalRenderStep; -import com.gtnewhorizons.navigator.api.util.DrawUtils; -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidChunkLocation; - -public class UndergroundFluidChunkRenderStep extends UniversalRenderStep { - - public UndergroundFluidChunkRenderStep(UndergroundFluidChunkLocation location) { - super(location); - setFontScale(0.3F); - } - - @Override - public void draw(double topX, double topY, float drawScale, double zoom) { - if (location.getFluidAmount() > 0 && getZoomStep() >= Config.minZoomLevelForUndergroundFluidDetails) { - float alpha = (float) (location.getFluidAmount() - location.getMinAmountInField()) - / (location.getMaxAmountInField() - location.getMinAmountInField() + 1); - alpha = alpha * 255; - int fluidColor = location.getFluid().getColor(); - DrawUtils.drawRect(topX, topY, getAdjustedWidth(), getAdjustedHeight(), fluidColor, (int) alpha); - - if (location.getFluidAmount() >= location.getMaxAmountInField()) { - DrawUtils.drawHollowRect(topX, topY, getAdjustedWidth(), getAdjustedHeight(), 0xFFD700, 204, 1.5); - } - - DrawUtils.drawLabel( - getLocation().getFluidAmountFormatted(), - topX + getAdjustedWidth() / 2, - topY + getAdjustedHeight() / 2, - 0xFFFFFFFF, - 0xB4000000, - true, - getFontScale()); - } - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java index 387c4240..d3f6252b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java @@ -4,7 +4,9 @@ import com.gtnewhorizons.navigator.api.model.steps.UniversalRenderStep; import com.gtnewhorizons.navigator.api.util.DrawUtils; +import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; public class UndergroundFluidRenderStep extends UniversalRenderStep { @@ -17,11 +19,20 @@ public UndergroundFluidRenderStep(UndergroundFluidLocation location) { @Override public void draw(double topX, double topY, float drawScale, double zoom) { - final int maxAmountInField = location.getMaxProduction(); - final int borderColor = location.getFluid().getColor(); - DrawUtils.drawHollowRect(topX, topY, getAdjustedWidth(), getAdjustedHeight(), borderColor, 255, 2); + renderChunks(topX, topY); + setSize(VP.undergroundFluidSizeChunkX * VP.chunkWidth); + int alpha = location.isActive() ? 255 : 74; + DrawUtils.drawHollowRect( + topX, + topY, + getAdjustedWidth(), + getAdjustedHeight() - 0.5, + location.getFluid().getColor(), + alpha, + 2); - if (getZoomStep() >= 1 && !isMinimap()) { + if (!isMinimap()) { + final int maxAmountInField = location.getMaxProduction(); String label = I18n.format("visualprospecting.empty"); if (maxAmountInField > 0) { label = location.getMinProduction() + "L - " @@ -30,14 +41,75 @@ public void draw(double topX, double topY, float drawScale, double zoom) { + location.getFluid().getLocalizedName(); } + int textColor = 0xFFFFFFFF; + if (UndergroundFluidLayerManager.instance.isSearchActive()) { + textColor = location.isActive() ? 0xFFFF00 : 0x444444; + } + DrawUtils.drawLabel( label, topX + getAdjustedWidth() / 2, - topY, - 0xFFFFFFFF, + topY + 1.5, + textColor, 0xB4000000, true, getFontScale()); } } + + private void renderChunks(double x, double y) { + if (getZoomStep() < Config.minZoomLevelForUndergroundFluidDetails || location.getMaxProduction() <= 0 + || !location.isActive()) { + return; + } + + setSize(VP.chunkWidth); + for (int chunkX = 0; chunkX < VP.undergroundFluidSizeChunkX; chunkX++) { + for (int chunkZ = 0; chunkZ < VP.undergroundFluidSizeChunkZ; chunkZ++) { + double xOffset = chunkX * getAdjustedWidth(); + double yOffset = chunkZ * getAdjustedHeight(); + int amount = location.getChunks()[chunkX][chunkZ]; + if (amount > 0) { + float alpha = (float) (amount - location.getMinProduction()) + / (location.getMaxProduction() - location.getMinProduction() + 1); + alpha = alpha * 255; + int fluidColor = location.getFluid().getColor(); + DrawUtils.drawRect( + x + xOffset, + y + yOffset, + getAdjustedWidth(), + getAdjustedHeight(), + fluidColor, + (int) alpha); + + if (amount >= location.getMaxProduction()) { + DrawUtils.drawHollowRect( + x + xOffset, + y + yOffset, + getAdjustedWidth(), + getAdjustedHeight(), + 0xFFD700, + 204, + 1.5); + } + + DrawUtils.drawLabel( + getFluidAmountFormatted(amount), + x + xOffset + getAdjustedWidth() / 2, + y + yOffset + getAdjustedHeight() / 2, + 0xFFFFFFFF, + 0xB4000000, + true, + getFontScale()); + } + } + } + } + + private String getFluidAmountFormatted(int amount) { + if (amount >= 1000) { + return (amount / 1000) + "kL"; + } + return amount + "L"; + } } From 1e72824ec89ac9c0da8ca6f0d6524c0f781bf671 Mon Sep 17 00:00:00 2001 From: Maya <10861407+serenibyss@users.noreply.github.com> Date: Wed, 19 Feb 2025 00:08:51 -0600 Subject: [PATCH 080/132] update --- dependencies.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 3 +-- settings.gradle | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 3a1e47b6..99596a06 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.15:dev') - api('com.github.GTNewHorizons:GTNHLib:0.6.1:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.63:dev') + api('com.github.GTNewHorizons:GTNHLib:0.6.11:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.142:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e2847c82..e18bc253 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f5feea6d..f3b75f3b 100755 --- a/gradlew +++ b/gradlew @@ -86,8 +86,7 @@ done # 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 +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/settings.gradle b/settings.gradle index 0147a994..39d96f7e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.30' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.33' } From cab6153e70043e1367d1849a289690f4b524f552 Mon Sep 17 00:00:00 2001 From: Maya <10861407+serenibyss@users.noreply.github.com> Date: Thu, 15 May 2025 00:42:34 -0500 Subject: [PATCH 081/132] Remove old GT5 compat (#67) --- .../database/ServerCache.java | 7 +- .../gregtech/UndergroundFluidsWrapper.java | 105 ------------------ 2 files changed, 4 insertions(+), 108 deletions(-) delete mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java index 4979c2b7..38c4a620 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java @@ -13,7 +13,8 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; -import com.sinthoras.visualprospecting.integration.gregtech.UndergroundFluidsWrapper; + +import gregtech.common.UndergroundOil; public class ServerCache extends WorldCache { @@ -93,8 +94,8 @@ public List prospectUndergroundFluidBlockRadius(World Fluid fluid = null; for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - final FluidStack prospectedFluid = UndergroundFluidsWrapper - .prospectFluid(world, chunkX + offsetChunkX, chunkZ + offsetChunkZ); + final FluidStack prospectedFluid = UndergroundOil + .undergroundOil(world, chunkX + offsetChunkX, chunkZ + offsetChunkZ, -1); if (prospectedFluid != null) { fluid = prospectedFluid.getFluid(); chunks[offsetChunkX][offsetChunkZ] = prospectedFluid.amount; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java deleted file mode 100644 index 4389a636..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/UndergroundFluidsWrapper.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.sinthoras.visualprospecting.integration.gregtech; - -import static gregtech.api.objects.XSTR.XSTR_INSTANCE; -import static gregtech.common.GTProxy.*; -import static gregtech.common.GTProxy.GTOIL; -import static gregtech.common.UndergroundOil.undergroundOil; - -import java.util.HashMap; -import java.util.Map; - -import net.minecraft.world.ChunkCoordIntPair; -import net.minecraft.world.World; -import net.minecraftforge.fluids.FluidRegistry; -import net.minecraftforge.fluids.FluidStack; - -import gregtech.GTMod; -import gregtech.api.objects.GTUODimension; -import gregtech.api.objects.GTUOFluid; -import gregtech.api.objects.XSTR; -import gregtech.common.UndergroundOil; - -public class UndergroundFluidsWrapper { - - private static final boolean isGTNHGregTechUndergroundFluids; - private static final float MODE_READ_ONLY = -1; - - static { - boolean foundMethod; - try { - UndergroundOil.class.getDeclaredMethod("undergroundOil", World.class, int.class, int.class, float.class); - foundMethod = true; - } catch (NoSuchMethodException e) { - foundMethod = false; - } - isGTNHGregTechUndergroundFluids = foundMethod; - } - - // GTNH's GregTech5-Unofficial was rewritten and requires different access - public static FluidStack prospectFluid(World world, int chunkX, int chunkZ) { - if (isGTNHGregTechUndergroundFluids) { - return undergroundOil(world, chunkX, chunkZ, MODE_READ_ONLY); - } else { - return vanillaProspectFluid(world, chunkX, chunkZ); - } - } - - // Rewrite from GT_UndergroundOil.undergroundOil(Chunk chunk, float readOrDrainCoefficient), - // because there is no reason to require a chunk to be loaded - private static FluidStack vanillaProspectFluid(World world, int chunkX, int chunkZ) { - final ChunkCoordIntPair chunkCoordinate = new ChunkCoordIntPair(chunkX, chunkZ); - int dimensionId = world.provider.dimensionId; - GTUODimension dimension = GTMod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId); - if (dimension == null) { - return null; - } - - Map chunkData = dimensionWiseChunkData - .computeIfAbsent(dimensionId, k -> new HashMap<>(1024)); - - int[] tInts = chunkData.get(chunkCoordinate); - - if (tInts == null) { - tInts = getDefaultChunkDataOnCreation(); - } else if (tInts[GTOIL] == 0) { - return new FluidStack(FluidRegistry.getFluid(tInts[GTOILFLUID]), 0); - } - - final XSTR tRandom = new XSTR(world.getSeed() + dimensionId * 2L + (chunkX >> 3) + 8267L * (chunkZ >> 3)); - - GTUOFluid uoFluid = dimension.getRandomFluid(tRandom); - - FluidStack fluidInChunk; - - if (uoFluid == null || uoFluid.getFluid() == null) { - tInts[GTOILFLUID] = Integer.MAX_VALUE; // null fluid pointer... kind of - tInts[GTOIL] = 0; - chunkData.put(chunkCoordinate, tInts); // update hash map - return null; - } else { - if (tInts[GTOILFLUID] == uoFluid.getFluid().getID()) { // if stored fluid matches uoFluid - fluidInChunk = new FluidStack(uoFluid.getFluid(), tInts[GTOIL]); - } else { - fluidInChunk = new FluidStack(uoFluid.getFluid(), uoFluid.getRandomAmount(tRandom)); - fluidInChunk.amount = (int) ((float) fluidInChunk.amount * (0.75f + (XSTR_INSTANCE.nextFloat() / 2f))); // Randomly - // change - // amounts - // by - // +/- - // 25% - } - tInts[GTOIL] = fluidInChunk.amount; - tInts[GTOILFLUID] = fluidInChunk.getFluidID(); - } - - if (fluidInChunk.amount <= UndergroundOil.DIVIDER) { - fluidInChunk.amount = 0; // return informative stack - tInts[GTOIL] = 0; // so in next access it will stop way above - } else { - fluidInChunk.amount = fluidInChunk.amount / UndergroundOil.DIVIDER; // give moderate extraction speed - } - - chunkData.put(chunkCoordinate, tInts); // update hash map - return fluidInChunk; - } -} From 417453c31f83d2eb6680f1fd10a3863e80508067 Mon Sep 17 00:00:00 2001 From: Lyft <127234178+Lyfts@users.noreply.github.com> Date: Thu, 15 May 2025 07:48:54 +0200 Subject: [PATCH 082/132] Add search bar for highlighting veins/fluids in map ui (#66) Co-authored-by: Maya <10861407+serenibyss@users.noreply.github.com> --- dependencies.gradle | 6 +-- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- .../sinthoras/visualprospecting/Utils.java | 9 ++-- .../sinthoras/visualprospecting/VPMod.java | 2 +- .../database/veintypes/VeinTypeCaching.java | 31 ++++++------- .../model/layers/OreVeinLayerManager.java | 9 +++- .../layers/UndergroundFluidLayerManager.java | 46 +++++++++++-------- 9 files changed, 61 insertions(+), 48 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 99596a06..0d3cf2af 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { - api('com.github.GTNewHorizons:Navigator:1.0.15:dev') - api('com.github.GTNewHorizons:GTNHLib:0.6.11:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.142:dev') + api('com.github.GTNewHorizons:Navigator:1.0.16:dev') + api('com.github.GTNewHorizons:GTNHLib:0.6.22:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.282:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/gradle.properties b/gradle.properties index db38e21d..3b2361c6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ modId = visualprospecting modGroup = com.sinthoras.visualprospecting # 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. +# When false, com.github.GTNewHorizons is used. useModGroupForPublishing = false # Updates your build.gradle and settings.gradle automatically whenever an update is available. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e18bc253..37f853b1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index 39d96f7e..ff436f2c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.33' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.38' } diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 4edfea16..63b9d992 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -42,10 +42,6 @@ @SuppressWarnings("ResultOfMethodCallIgnored") public class Utils { - public static boolean isNEIInstalled() { - return Loader.isModLoaded("NotEnoughItems"); - } - public static boolean isNavigatorInstalled() { return Loader.isModLoaded("navigator"); } @@ -241,6 +237,11 @@ private static ByteBuffer readFileToBuffer(File file) { return null; } + return getSearchPattern(searchString); + } + + public static @Nullable Pattern getSearchPattern(@NotNull String searchString) { + if (searchString.isEmpty()) return null; final String unquotedRegex = SearchField.getPattern(searchString).pattern().replace("\\Q", "") .replace("\\E", ""); return Pattern.compile(unquotedRegex, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); diff --git a/src/main/java/com/sinthoras/visualprospecting/VPMod.java b/src/main/java/com/sinthoras/visualprospecting/VPMod.java index fee72a22..b88ac06a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VPMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/VPMod.java @@ -21,7 +21,7 @@ version = Tags.VERSION, name = Tags.MODNAME, acceptedMinecraftVersions = "[1.7.10]", - dependencies = "required-after:gregtech;" + "after:navigator;") + dependencies = "required-after:gregtech;" + "required-after:NotEnoughItems;" + "after:navigator;") public class VPMod { @SidedProxy(clientSide = Tags.GROUPNAME + ".hooks.HooksClient", serverSide = Tags.GROUPNAME + ".hooks.HooksShared") diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index 9cde9861..8e7fde20 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -13,9 +13,9 @@ import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.Utils; import bartworks.system.material.Werkstoff; import bartworks.system.oregen.BWOreLayer; @@ -70,22 +70,19 @@ public static Collection getVeinTypes() { return veinTypes.values(); } - public static void recalculateNEISearch() { - if (isNEIInstalled()) { - final Pattern filterPattern = Utils.getNEISearchPattern(); - for (VeinType veinType : veinTypes.values()) { - if (veinType == VeinType.NO_VEIN) continue; - if (filterPattern != null) { - List searchableStrings = new ArrayList<>(veinType.getOreMaterialNames()); - searchableStrings.add(veinType.getVeinName()); - final boolean match = searchableStrings.stream() - .map(EnumChatFormatting::getTextWithoutFormattingCodes).map(String::toLowerCase) - .anyMatch(searchableString -> filterPattern.matcher(searchableString).find()); - - veinType.setNEISearchHighlight(match); - } else { - veinType.setNEISearchHighlight(true); - } + public static void recalculateSearch(@Nullable Pattern filterPattern) { + for (VeinType veinType : veinTypes.values()) { + if (veinType == VeinType.NO_VEIN) continue; + if (filterPattern != null) { + List searchableStrings = new ArrayList<>(veinType.getOreMaterialNames()); + searchableStrings.add(veinType.getVeinName()); + final boolean match = searchableStrings.stream().map(EnumChatFormatting::getTextWithoutFormattingCodes) + .map(String::toLowerCase) + .anyMatch(searchableString -> filterPattern.matcher(searchableString).find()); + + veinType.setNEISearchHighlight(match); + } else { + veinType.setNEISearchHighlight(true); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java index 8d6eaf72..45336781 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java @@ -1,5 +1,6 @@ package com.sinthoras.visualprospecting.integration.model.layers; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.gtnewhorizons.navigator.api.journeymap.waypoints.JMWaypointManager; @@ -25,11 +26,12 @@ public class OreVeinLayerManager extends InteractableLayerManager { public OreVeinLayerManager() { super(OreVeinButtonManager.instance); + setHasSearchField(true); } @Override public void onOpenMap() { - VeinTypeCaching.recalculateNEISearch(); + VeinTypeCaching.recalculateSearch(Utils.getNEISearchPattern()); } @Nullable @@ -63,4 +65,9 @@ protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { return null; } + + @Override + public void onSearch(@NotNull String searchString) { + VeinTypeCaching.recalculateSearch(Utils.getSearchPattern(searchString)); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java index 923f132e..0042fde6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java @@ -1,7 +1,5 @@ package com.sinthoras.visualprospecting.integration.model.layers; -import static com.sinthoras.visualprospecting.Utils.isNEIInstalled; - import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; @@ -9,6 +7,7 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.gtnewhorizons.navigator.api.model.SupportedMods; @@ -32,10 +31,10 @@ public class UndergroundFluidLayerManager extends LayerManager { public static final UndergroundFluidLayerManager instance = new UndergroundFluidLayerManager(); private static final ObjectSet highlightedFluids = new ObjectOpenHashSet<>(); - private boolean searching = false; public UndergroundFluidLayerManager() { super(UndergroundFluidButtonManager.instance); + setHasSearchField(true); } @Nullable @@ -47,22 +46,8 @@ protected LayerRenderer addLayerRenderer(LayerManager manager, SupportedMods mod @Override public void onOpenMap() { - if (!isNEIInstalled()) return; highlightedFluids.clear(); - searching = false; - final Pattern filterPattern = Utils.getNEISearchPattern(); - if (filterPattern != null) { - searching = true; - for (UndergroundFluidNames fluidName : UndergroundFluidNames.values()) { - Fluid fluid = FluidRegistry.getFluid(fluidName.name); - if (fluid == null) continue; - for (String name : getFluidNames(fluid)) { - if (name != null && filterPattern.matcher(name.toLowerCase()).find()) { - highlightedFluids.add(fluid); - } - } - } - } + computeSearch(Utils.getNEISearchPattern()); } private static List getFluidNames(Fluid fluid) { @@ -98,12 +83,35 @@ protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { return null; } + private void computeSearch(@Nullable Pattern filterPattern) { + if (filterPattern != null) { + for (UndergroundFluidNames fluidName : UndergroundFluidNames.values()) { + Fluid fluid = FluidRegistry.getFluid(fluidName.name); + if (fluid == null) continue; + for (String name : getFluidNames(fluid)) { + if (name != null && filterPattern.matcher(name.toLowerCase()).find()) { + highlightedFluids.add(fluid); + } + } + } + } + } + + @Override + public void onSearch(@NotNull String searchString) { + if (searchString.isEmpty()) { + highlightedFluids.clear(); + } else { + computeSearch(Utils.getSearchPattern(searchString)); + } + } + @Override public int getElementSize() { return 8; } public boolean isSearchActive() { - return searching; + return !highlightedFluids.isEmpty(); } } From 2bb4425ece00d2dc70fca58804fcf4ed90b504a6 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Fri, 16 May 2025 18:14:24 +0200 Subject: [PATCH 083/132] update --- dependencies.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 43583 -> 43705 bytes gradlew | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 0d3cf2af..083f56c0 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.16:dev') api('com.github.GTNewHorizons:GTNHLib:0.6.22:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.282:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.285:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9530d66f5e68d973ea569d8e19de379189..9bbc975c742b298b441bfb90dbc124400a3751b9 100644 GIT binary patch delta 34744 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 delta 34727 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�{ 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 a%EQ2*fnt2> Date: Mon, 14 Jul 2025 18:07:52 +0200 Subject: [PATCH 084/132] Convert to new IMixins and MixinsBuilder system (#69) --- dependencies.gradle | 4 +- gradle.properties | 2 +- settings.gradle | 2 +- .../visualprospecting/mixinplugin/Mixins.java | 89 +++++-------------- .../mixinplugin/TargetedMod.java | 34 +++---- .../VisualProspectingEarlyMixinLoader.java | 28 +++--- .../VisualProspectingLateMixinLoader.java | 11 +-- 7 files changed, 50 insertions(+), 120 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 083f56c0..98e28ec5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.16:dev') - api('com.github.GTNewHorizons:GTNHLib:0.6.22:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.285:dev') + api('com.github.GTNewHorizons:GTNHLib:0.6.37:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.388:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/gradle.properties b/gradle.properties index 3b2361c6..5553eab2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -151,7 +151,7 @@ modrinthProjectId = # 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 +# Note: UniMixins is automatically set as a required dependency if usesMixins = true. modrinthRelations = # Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens. diff --git a/settings.gradle b/settings.gradle index ff436f2c..7622cde1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.38' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.41' } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java index 8ec8c144..f21a10d1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java @@ -2,14 +2,14 @@ import static com.sinthoras.visualprospecting.mixinplugin.TargetedMod.*; -import java.util.Arrays; -import java.util.List; -import java.util.Set; +import javax.annotation.Nonnull; -import cpw.mods.fml.relauncher.FMLLaunchHandler; +import com.gtnewhorizon.gtnhmixins.builders.IMixins; +import com.gtnewhorizon.gtnhmixins.builders.MixinBuilder; -public enum Mixins { +public enum Mixins implements IMixins { + // spotless:off // Bartworks mixins WorldGenContainerMixin("bartworks.WorldGenContainerMixin", BARTWORKS), @@ -23,75 +23,26 @@ public enum Mixins { GT_WorldGenContainerMixin("gregtech.WorldGenContainerMixin", GT5U), // Vanilla Mixins - MinecraftServerAccessorMixin("minecraft.MinecraftServerAccessor", Phase.EARLY, Side.BOTH, VANILLA), - ItemEditableBookMixin("minecraft.ItemEditableBookMixin", Phase.EARLY, VANILLA); + MINECRAFT(new MixinBuilder() + .addCommonMixins( + "minecraft.MinecraftServerAccessor", + "minecraft.ItemEditableBookMixin") + .setPhase(Phase.EARLY)); + // spotless:on - public final String mixinClass; - public final Phase phase; - private final Side side; - private final List targetedMods; + private final MixinBuilder builder; - Mixins(String mixinClass, TargetedMod... targetedMods) { - this.mixinClass = mixinClass; - this.phase = Phase.LATE; - this.side = Side.BOTH; - this.targetedMods = Arrays.asList(targetedMods); + Mixins(MixinBuilder builder) { + this.builder = builder; } - Mixins(String mixinClass, Phase phase, TargetedMod... targetedMods) { - this.mixinClass = mixinClass; - this.phase = phase; - this.side = Side.BOTH; - this.targetedMods = Arrays.asList(targetedMods); + Mixins(String mixinClass, TargetedMod requiredMod) { + this.builder = new MixinBuilder().addCommonMixins(mixinClass).addRequiredMod(requiredMod).setPhase(Phase.LATE); } - Mixins(String mixinClass, Side side, TargetedMod... targetedMods) { - this.mixinClass = mixinClass; - this.phase = Phase.LATE; - this.side = side; - this.targetedMods = Arrays.asList(targetedMods); + @Nonnull + @Override + public MixinBuilder getBuilder() { + return this.builder; } - - Mixins(String mixinClass, Phase phase, Side side, TargetedMod... targetedMods) { - this.mixinClass = mixinClass; - this.phase = phase; - this.side = side; - this.targetedMods = Arrays.asList(targetedMods); - } - - public boolean shouldLoad(Set loadedCoreMods, Set loadedMods) { - return shouldLoadSide() && allModsLoaded(targetedMods, loadedCoreMods, loadedMods); - } - - private boolean shouldLoadSide() { - return (side == Side.BOTH || (side == Side.SERVER && FMLLaunchHandler.side().isServer()) - || (side == Side.CLIENT && FMLLaunchHandler.side().isClient())); - } - - private boolean allModsLoaded(List targetedMods, Set loadedCoreMods, Set loadedMods) { - if (targetedMods.isEmpty()) return false; - for (TargetedMod target : targetedMods) { - if (target == TargetedMod.VANILLA) continue; - // Check coremod first - if (!loadedCoreMods.isEmpty() && target.coreModClass != null - && !loadedCoreMods.contains(target.coreModClass)) { - return false; - } else if (!loadedMods.isEmpty() && target.modId != null && !loadedMods.contains(target.modId)) { - return false; - } - } - return true; - } - - enum Side { - BOTH, - CLIENT, - SERVER - } - - public enum Phase { - EARLY, - LATE - } - } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java index 454bac18..ba4823c1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/TargetedMod.java @@ -1,31 +1,25 @@ package com.sinthoras.visualprospecting.mixinplugin; -public enum TargetedMod { +import javax.annotation.Nonnull; - BARTWORKS("BartWorks", "com.github.bartimaeusnek.bartworks.ASM.BWCorePlugin", "bartworks"), - GALACTICGREG("Galactic Greg", null, "galacticgreg"), - GT5U("GregTech5u", null, "gregtech"), // Also matches GT6. - VANILLA("Minecraft", null); +import com.gtnewhorizon.gtnhmixins.builders.ITargetMod; +import com.gtnewhorizon.gtnhmixins.builders.TargetModBuilder; - /** The "name" in the @Mod annotation */ - public final String modName; - /** Class that implements the IFMLLoadingPlugin interface */ - public final String coreModClass; - /** The "modid" in the @Mod annotation */ - public final String modId; +public enum TargetedMod implements ITargetMod { - TargetedMod(String modName, String coreModClass) { - this(modName, coreModClass, null); - } + BARTWORKS("com.github.bartimaeusnek.bartworks.ASM.BWCorePlugin", "bartworks"), + GALACTICGREG(null, "galacticgreg"), + GT5U(null, "gregtech"); // Also matches GT6. + + private final TargetModBuilder builder; - TargetedMod(String modName, String coreModClass, String modId) { - this.modName = modName; - this.coreModClass = coreModClass; - this.modId = modId; + TargetedMod(String coreModClass, String modId) { + this.builder = new TargetModBuilder().setCoreModClass(coreModClass).setModId(modId); } + @Nonnull @Override - public String toString() { - return "TargetedMod{modName='" + modName + "', coreModClass='" + coreModClass + "', modId='" + modId + "'}"; + public TargetModBuilder getBuilder() { + return builder; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java index 527b168e..0c1cb1b8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingEarlyMixinLoader.java @@ -1,12 +1,11 @@ package com.sinthoras.visualprospecting.mixinplugin; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import com.gtnewhorizon.gtnhmixins.IEarlyMixinLoader; +import com.gtnewhorizon.gtnhmixins.builders.IMixins; import cpw.mods.fml.relauncher.IFMLLoadingPlugin; @@ -14,22 +13,6 @@ @IFMLLoadingPlugin.TransformerExclusions("com.sinthoras.visualprospecting.mixinplugin") public class VisualProspectingEarlyMixinLoader implements IFMLLoadingPlugin, IEarlyMixinLoader { - @Override - public String getMixinConfig() { - return "mixins.visualprospecting.early.json"; - } - - @Override - public List getMixins(Set loadedCoreMods) { - final List mixins = new ArrayList<>(); - for (Mixins mixin : Mixins.values()) { - if (mixin.phase == Mixins.Phase.EARLY && mixin.shouldLoad(loadedCoreMods, Collections.emptySet())) { - mixins.add(mixin.mixinClass); - } - } - return mixins; - } - @Override public String[] getASMTransformerClass() { return null; @@ -53,4 +36,13 @@ public String getAccessTransformerClass() { return null; } + @Override + public String getMixinConfig() { + return "mixins.visualprospecting.early.json"; + } + + @Override + public List getMixins(Set loadedCoreMods) { + return IMixins.getEarlyMixins(Mixins.class, loadedCoreMods); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingLateMixinLoader.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingLateMixinLoader.java index fad2f590..24da6916 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingLateMixinLoader.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/VisualProspectingLateMixinLoader.java @@ -1,12 +1,11 @@ package com.sinthoras.visualprospecting.mixinplugin; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Set; import com.gtnewhorizon.gtnhmixins.ILateMixinLoader; import com.gtnewhorizon.gtnhmixins.LateMixin; +import com.gtnewhorizon.gtnhmixins.builders.IMixins; @LateMixin public class VisualProspectingLateMixinLoader implements ILateMixinLoader { @@ -18,13 +17,7 @@ public String getMixinConfig() { @Override public List getMixins(Set loadedMods) { - final List mixins = new ArrayList<>(); - for (Mixins mixin : Mixins.values()) { - if (mixin.phase == Mixins.Phase.LATE && mixin.shouldLoad(Collections.emptySet(), loadedMods)) { - mixins.add(mixin.mixinClass); - } - } - return mixins; + return IMixins.getLateMixins(Mixins.class, loadedMods); } } From 007cce039a911aa3443f163a3827062bcbb7c2ac Mon Sep 17 00:00:00 2001 From: Alexdoru <57050655+Alexdoru@users.noreply.github.com> Date: Wed, 16 Jul 2025 17:36:06 +0200 Subject: [PATCH 085/132] remove hard dep on BWColorUtil (#68) --- .../database/veintypes/BartworksOreMaterialProvider.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java index 52214630..b829b30c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java @@ -1,7 +1,5 @@ package com.sinthoras.visualprospecting.database.veintypes; -import static bartworks.util.BWColorUtil.getColorFromRGBArray; - import java.util.ArrayList; import java.util.List; @@ -26,7 +24,8 @@ public class BartworksOreMaterialProvider implements IOreMaterialProvider { public BartworksOreMaterialProvider(Werkstoff material) { this.material = material; - this.primaryOreColor = getColorFromRGBArray(material.getRGBA()); + final short[] rgba = material.getRGBA(); + this.primaryOreColor = (rgba[0] & 0x0ff) << 16 | (rgba[1] & 0x0ff) << 8 | rgba[2] & 0x0ff; this.primaryOreName = material.getLocalizedName(); } From c481df708c48e9b011b16ed1d15e6cb0eef13951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Gris?= Date: Wed, 6 Aug 2025 16:25:15 +0200 Subject: [PATCH 086/132] upd(render): add support for ore icon overlay (#70) --- dependencies.gradle | 2 +- .../veintypes/BartworksOreMaterialProvider.java | 13 ++++++------- .../veintypes/GregTechOreMaterialProvider.java | 13 ++++++------- .../database/veintypes/IOreMaterialProvider.java | 5 ++--- .../model/locations/OreVeinLocation.java | 7 ++++--- .../integration/model/render/OreVeinRenderStep.java | 7 ++++++- 6 files changed, 25 insertions(+), 22 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 98e28ec5..860cf878 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.16:dev') api('com.github.GTNewHorizons:GTNHLib:0.6.37:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.388:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.422:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java index b829b30c..a49967a8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java @@ -3,8 +3,6 @@ import java.util.ArrayList; import java.util.List; -import net.minecraft.util.IIcon; - import com.google.common.collect.ImmutableList; import bartworks.system.material.Werkstoff; @@ -12,6 +10,7 @@ import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.GregTechAPI; import gregtech.api.enums.OrePrefixes; +import gregtech.api.interfaces.IIconContainer; import it.unimi.dsi.fastutil.shorts.ShortCollection; public class BartworksOreMaterialProvider implements IOreMaterialProvider { @@ -19,7 +18,7 @@ public class BartworksOreMaterialProvider implements IOreMaterialProvider { private final Werkstoff material; private final int primaryOreColor; private final String primaryOreName; - private IIcon primaryOreIcon; + private IIconContainer oreIconContainer; private ImmutableList containedOres; public BartworksOreMaterialProvider(Werkstoff material) { @@ -31,11 +30,11 @@ public BartworksOreMaterialProvider(Werkstoff material) { @Override @SideOnly(Side.CLIENT) - public IIcon getIcon() { - if (primaryOreIcon == null) { - primaryOreIcon = material.getTexSet().mTextures[OrePrefixes.ore.mTextureIndex].getIcon(); + public IIconContainer getIconContainer() { + if (oreIconContainer == null) { + oreIconContainer = material.getTexSet().mTextures[OrePrefixes.ore.mTextureIndex]; } - return primaryOreIcon; + return oreIconContainer; } @Override diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java index d6d60200..a38a2b63 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java @@ -3,8 +3,6 @@ import java.util.ArrayList; import java.util.List; -import net.minecraft.util.IIcon; - import com.google.common.collect.ImmutableList; import cpw.mods.fml.relauncher.Side; @@ -12,13 +10,14 @@ import gregtech.api.GregTechAPI; import gregtech.api.enums.Materials; import gregtech.api.enums.OrePrefixes; +import gregtech.api.interfaces.IIconContainer; import it.unimi.dsi.fastutil.shorts.ShortCollection; public class GregTechOreMaterialProvider implements IOreMaterialProvider { private final Materials material; private final int primaryOreColor; - private IIcon primaryOreIcon; + private IIconContainer oreIconContainer; private final String primaryOreName; private ImmutableList containedOres; @@ -30,11 +29,11 @@ public GregTechOreMaterialProvider(Materials material) { @Override @SideOnly(Side.CLIENT) - public IIcon getIcon() { - if (primaryOreIcon == null) { - primaryOreIcon = material.mIconSet.mTextures[OrePrefixes.ore.mTextureIndex].getIcon(); + public IIconContainer getIconContainer() { + if (oreIconContainer == null) { + oreIconContainer = material.mIconSet.mTextures[OrePrefixes.ore.mTextureIndex]; } - return primaryOreIcon; + return oreIconContainer; } @Override diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java index 29c66d7b..10cc40f4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java @@ -1,17 +1,16 @@ package com.sinthoras.visualprospecting.database.veintypes; -import net.minecraft.util.IIcon; - import com.google.common.collect.ImmutableList; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.interfaces.IIconContainer; import it.unimi.dsi.fastutil.shorts.ShortCollection; public interface IOreMaterialProvider { @SideOnly(Side.CLIENT) - IIcon getIcon(); + IIconContainer getIconContainer(); int getColor(); diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index 893d064f..f9e4f0bb 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -5,7 +5,6 @@ import net.minecraft.client.resources.I18n; import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.IIcon; import org.lwjgl.input.Keyboard; @@ -15,6 +14,8 @@ import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; +import gregtech.api.interfaces.IIconContainer; + public class OreVeinLocation implements IWaypointAndLocationProvider { private static final String depletedHint = EnumChatFormatting.RED + I18n.format("visualprospecting.depleted"); @@ -115,8 +116,8 @@ public int getColor() { return oreVeinPosition.veinType.oreMaterialProvider.getColor(); } - public IIcon getIconFromPrimaryOre() { - return oreVeinPosition.veinType.oreMaterialProvider.getIcon(); + public IIconContainer getIconsFromPrimaryOre() { + return oreVeinPosition.veinType.oreMaterialProvider.getIconContainer(); } public short getPrimaryOreMeta() { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java index 2dc6545f..681aaf94 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java @@ -17,6 +17,7 @@ import codechicken.nei.api.ShortcutInputHandler; import gregtech.api.GregTechAPI; +import gregtech.api.interfaces.IIconContainer; public class OreVeinRenderStep extends UniversalInteractableStep { @@ -56,7 +57,11 @@ public void draw(double topX, double topY, float drawScale, double zoom) { final IIcon blockIcon = Blocks.stone.getIcon(0, 0); DrawUtils.drawQuad(blockIcon, topX, topY, width, height, 0xFFFFFF, 255); - DrawUtils.drawQuad(location.getIconFromPrimaryOre(), topX, topY, width, height, location.getColor(), 255); + final IIconContainer oreIconContainer = location.getIconsFromPrimaryOre(); + final IIcon oreIcon = oreIconContainer.getIcon(); + DrawUtils.drawQuad(oreIcon, topX, topY, width, height, location.getColor(), 255); + final IIcon oreIconOverlay = oreIconContainer.getOverlayIcon(); + if (oreIconOverlay != null) DrawUtils.drawQuad(oreIconOverlay, topX, topY, width, height, 0xFFFFFF, 255); if (!location.drawSearchHighlight() || location.isDepleted()) { DrawUtils.drawRect(topX, topY, width, height, 0x000000, 150); From 31b97bf5ee0983391e3d0767854b81ca19caf73b Mon Sep 17 00:00:00 2001 From: Dream Master Date: Fri, 8 Aug 2025 19:09:26 +0700 Subject: [PATCH 087/132] update --- dependencies.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 860cf878..3b2b6f3a 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { - api('com.github.GTNewHorizons:Navigator:1.0.16:dev') - api('com.github.GTNewHorizons:GTNHLib:0.6.37:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.422:dev') + api('com.github.GTNewHorizons:Navigator:1.0.17:dev') + api('com.github.GTNewHorizons:GTNHLib:0.6.38:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.423:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } From 24155a4110f082c37cad26f8f2a919456a8a40ce Mon Sep 17 00:00:00 2001 From: Dan <104518973+alppp@users.noreply.github.com> Date: Tue, 26 Aug 2025 21:35:37 +0300 Subject: [PATCH 088/132] optimize save/load methods in DimensionCache for ores and fluids (#72) --- .../database/DimensionCache.java | 218 ++++++++++++++---- 1 file changed, 169 insertions(+), 49 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index f7c2979f..dbbfbae2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -13,7 +13,6 @@ import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagIntArray; import net.minecraft.nbt.NBTTagList; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; @@ -26,7 +25,6 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; import it.unimi.dsi.fastutil.shorts.Short2ObjectMaps; @@ -42,8 +40,8 @@ public enum UpdateResult { private static final File oldIdFile = new File(Tags.VISUALPROSPECTING_DIR, "veintypesLUT"); private static Short2ObjectMap idConversionMap; - private final Long2ObjectMap oreChunks = new Long2ObjectOpenHashMap<>(); - private final Long2ObjectMap undergroundFluids = new Long2ObjectOpenHashMap<>(); + private final Long2ObjectOpenHashMap oreChunks = new Long2ObjectOpenHashMap<>(); + private final Long2ObjectOpenHashMap undergroundFluids = new Long2ObjectOpenHashMap<>(); public final int dimensionId; private boolean isDirty = false; private boolean preventSaving = false; @@ -63,71 +61,193 @@ public NBTTagCompound saveToNbt() { private NBTTagCompound saveOres() { NBTTagCompound compound = new NBTTagCompound(); - for (OreVeinPosition vein : oreChunks.values()) { - NBTTagCompound veinCompound = new NBTTagCompound(); - veinCompound.setInteger("chunkX", vein.chunkX); - veinCompound.setInteger("chunkZ", vein.chunkZ); - veinCompound.setString("veinTypeName", vein.veinType.name); - veinCompound.setBoolean("depleted", vein.isDepleted()); - compound.setTag(String.valueOf(getOreVeinKey(vein.chunkX, vein.chunkZ)), veinCompound); + Collection veins = oreChunks.values(); + int size = veins.size(); + + if (size == 0) { + return compound; + } + + // Pre-allocate contiguous arrays for optimal cache line utilization + int[] chunkXArray = new int[size]; + int[] chunkZArray = new int[size]; + byte[] depletedFlags = new byte[size]; + NBTTagList veinTypeNamesList = new NBTTagList(); + + // Single-pass iteration for optimal access pattern + int i = 0; + for (OreVeinPosition vein : veins) { + chunkXArray[i] = vein.chunkX; + chunkZArray[i] = vein.chunkZ; + depletedFlags[i] = vein.isDepleted() ? (byte) 1 : (byte) 0; + veinTypeNamesList.appendTag(new net.minecraft.nbt.NBTTagString(vein.veinType.name)); + i++; } + + // Store as contiguous arrays - only 4 string operations vs 400,000+ + compound.setIntArray("chunkX", chunkXArray); + compound.setIntArray("chunkZ", chunkZArray); + compound.setByteArray("depleted", depletedFlags); + compound.setTag("veinTypeNames", veinTypeNamesList); + return compound; } private NBTTagCompound saveFluids() { NBTTagCompound compound = new NBTTagCompound(); - for (UndergroundFluidPosition fluid : undergroundFluids.values()) { - NBTTagCompound fluidCompound = new NBTTagCompound(); - fluidCompound.setInteger("chunkX", fluid.chunkX); - fluidCompound.setInteger("chunkZ", fluid.chunkZ); - fluidCompound.setString("fluidName", fluid.fluid.getName()); - NBTTagList chunkList = new NBTTagList(); - for (int i = 0; i < VP.undergroundFluidSizeChunkX; i++) { - chunkList.appendTag(new NBTTagIntArray(fluid.chunks[i])); + Collection fluids = undergroundFluids.values(); + int size = fluids.size(); + + if (size == 0) { + return compound; + } + + // Pre-allocate contiguous arrays for optimal cache performance + int[] chunkXArray = new int[size]; + int[] chunkZArray = new int[size]; + + // Calculate total chunk data size for flattened storage + int chunkDataSize = VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ; + int[] allChunkData = new int[size * chunkDataSize]; + NBTTagList fluidNamesList = new NBTTagList(); + + // Single-pass iteration for optimal access pattern + int fluidIndex = 0; + for (UndergroundFluidPosition fluid : fluids) { + chunkXArray[fluidIndex] = fluid.chunkX; + chunkZArray[fluidIndex] = fluid.chunkZ; + fluidNamesList.appendTag(new net.minecraft.nbt.NBTTagString(fluid.fluid.getName())); + + // Flatten 2D chunk array into contiguous memory layout + int baseOffset = fluidIndex * chunkDataSize; + for (int x = 0; x < VP.undergroundFluidSizeChunkX; x++) { + System.arraycopy( + fluid.chunks[x], + 0, + allChunkData, + baseOffset + x * VP.undergroundFluidSizeChunkZ, + VP.undergroundFluidSizeChunkZ); } - fluidCompound.setTag("chunks", chunkList); - compound.setTag(String.valueOf(getUndergroundFluid(fluid.chunkX, fluid.chunkZ)), fluidCompound); + fluidIndex++; } + + // Store as contiguous arrays - minimal string operations + compound.setIntArray("chunkX", chunkXArray); + compound.setIntArray("chunkZ", chunkZArray); + compound.setIntArray("chunkData", allChunkData); + compound.setInteger("chunkDataSize", chunkDataSize); + compound.setTag("fluidNames", fluidNamesList); + return compound; } @SuppressWarnings("unchecked") public void loadFromNbt(NBTTagCompound compound) { NBTTagCompound ores = compound.getCompoundTag("ores"); - for (NBTBase base : (Collection) ores.tagMap.values()) { - NBTTagCompound veinCompound = (NBTTagCompound) base; - int chunkX = veinCompound.getInteger("chunkX"); - int chunkZ = veinCompound.getInteger("chunkZ"); - boolean depleted = veinCompound.getBoolean("depleted"); - VeinType veinType; - if (veinCompound.hasKey("veinTypeId")) { - veinType = getVeinFromId(veinCompound.getShort("veinTypeId")); - if (veinType == null) return; - markDirty(); - } else { - veinType = VeinTypeCaching.getVeinType(veinCompound.getString("veinTypeName")); + + // Check if using optimized array format (new) vs legacy nested format (old) + if (ores.hasKey("chunkX") && ores.hasKey("chunkZ")) { + // OPTIMIZED PATH: Array-based loading for maximum cache efficiency + int[] chunkXArray = ores.getIntArray("chunkX"); + int[] chunkZArray = ores.getIntArray("chunkZ"); + byte[] depletedFlags = ores.getByteArray("depleted"); + NBTTagList veinTypeNamesList = ores.getTagList("veinTypeNames", 8); + + int size = chunkXArray.length; + + // Pre-size HashMap to avoid rehashing during bulk load + oreChunks.ensureCapacity(oreChunks.size() + size); + + // Sequential array processing - optimal cache line utilization + for (int i = 0; i < size; i++) { + int chunkX = chunkXArray[i]; // Cache-friendly array access + int chunkZ = chunkZArray[i]; // Cache-friendly array access + boolean depleted = depletedFlags[i] == 1; + String veinTypeName = veinTypeNamesList.getStringTagAt(i); + VeinType veinType = VeinTypeCaching.getVeinType(veinTypeName); + + oreChunks.put( + getOreVeinKey(chunkX, chunkZ), + new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); } + } else { + // LEGACY PATH: Backward compatibility for old nested compound format + for (NBTBase base : (Collection) ores.tagMap.values()) { + NBTTagCompound veinCompound = (NBTTagCompound) base; + int chunkX = veinCompound.getInteger("chunkX"); + int chunkZ = veinCompound.getInteger("chunkZ"); + boolean depleted = veinCompound.getBoolean("depleted"); + VeinType veinType; + if (veinCompound.hasKey("veinTypeId")) { + veinType = getVeinFromId(veinCompound.getShort("veinTypeId")); + if (veinType == null) return; + markDirty(); + } else { + veinType = VeinTypeCaching.getVeinType(veinCompound.getString("veinTypeName")); + } - oreChunks.put( - getOreVeinKey(chunkX, chunkZ), - new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); + oreChunks.put( + getOreVeinKey(chunkX, chunkZ), + new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); + } } NBTTagCompound fluids = compound.getCompoundTag("fluids"); - for (NBTBase base : (Collection) fluids.tagMap.values()) { - NBTTagCompound fluidCompound = (NBTTagCompound) base; - int chunkX = fluidCompound.getInteger("chunkX"); - int chunkZ = fluidCompound.getInteger("chunkZ"); - String fluidName = fluidCompound.getString("fluidName"); - Fluid fluid = FluidRegistry.getFluid(fluidName); - int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; - NBTTagList chunkList = fluidCompound.getTagList("chunks", 11); - for (int i = 0; i < VP.undergroundFluidSizeChunkX; i++) { - chunks[i] = chunkList.func_150306_c(i); + + // Check if using optimized array format (new) vs legacy nested format (old) + if (fluids.hasKey("chunkX") && fluids.hasKey("chunkZ")) { + // OPTIMIZED PATH: Array-based fluid loading for maximum cache efficiency + int[] chunkXArray = fluids.getIntArray("chunkX"); + int[] chunkZArray = fluids.getIntArray("chunkZ"); + int[] allChunkData = fluids.getIntArray("chunkData"); + int chunkDataSize = fluids.getInteger("chunkDataSize"); + NBTTagList fluidNamesList = fluids.getTagList("fluidNames", 8); + + int fluidCount = chunkXArray.length; + + // Pre-size HashMap to avoid rehashing during bulk load + undergroundFluids.ensureCapacity(undergroundFluids.size() + fluidCount); + + // Sequential array processing - optimal cache line utilization + for (int fluidIndex = 0; fluidIndex < fluidCount; fluidIndex++) { + int chunkX = chunkXArray[fluidIndex]; // Cache-friendly array access + int chunkZ = chunkZArray[fluidIndex]; // Cache-friendly array access + String fluidName = fluidNamesList.getStringTagAt(fluidIndex); + Fluid fluid = FluidRegistry.getFluid(fluidName); + + // Reconstruct 2D chunk array from flattened data + int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; + int baseOffset = fluidIndex * chunkDataSize; + for (int x = 0; x < VP.undergroundFluidSizeChunkX; x++) { + System.arraycopy( + allChunkData, + baseOffset + x * VP.undergroundFluidSizeChunkZ, + chunks[x], + 0, + VP.undergroundFluidSizeChunkZ); + } + + undergroundFluids.put( + getUndergroundFluidKey(chunkX, chunkZ), + new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); + } + } else { + // LEGACY PATH: Backward compatibility for old nested compound format + for (NBTBase base : (Collection) fluids.tagMap.values()) { + NBTTagCompound fluidCompound = (NBTTagCompound) base; + int chunkX = fluidCompound.getInteger("chunkX"); + int chunkZ = fluidCompound.getInteger("chunkZ"); + String fluidName = fluidCompound.getString("fluidName"); + Fluid fluid = FluidRegistry.getFluid(fluidName); + int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; + NBTTagList chunkList = fluidCompound.getTagList("chunks", 11); + for (int i = 0; i < VP.undergroundFluidSizeChunkX; i++) { + chunks[i] = chunkList.func_150306_c(i); + } + undergroundFluids.put( + getUndergroundFluidKey(chunkX, chunkZ), + new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); } - undergroundFluids.put( - getUndergroundFluidKey(chunkX, chunkZ), - new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); } } From 1d4e78434086dbd8ff0adb7770ba62add739cfba Mon Sep 17 00:00:00 2001 From: Niclas Klugmann Date: Thu, 28 Aug 2025 09:19:33 +0200 Subject: [PATCH 089/132] german translation (#71) --- .../assets/visualprospecting/lang/de_DE.lang | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/main/resources/assets/visualprospecting/lang/de_DE.lang diff --git a/src/main/resources/assets/visualprospecting/lang/de_DE.lang b/src/main/resources/assets/visualprospecting/lang/de_DE.lang new file mode 100644 index 00000000..19abbcb8 --- /dev/null +++ b/src/main/resources/assets/visualprospecting/lang/de_DE.lang @@ -0,0 +1,51 @@ +visualprospecting.vein.prospected=Du hast eine %s-Ader gefunden %s! +visualprospecting.vein.contents=Du könntest %s finden +visualprospecting.veins.prospected=Du hast %s neue Erzadern gefunden! +visualprospecting.undergroundfluid.prospected.onlynew=Du hast %s neue Ölfelder gefunden! +visualprospecting.undergroundfluid.prospected.onlyupdated=Du hast %s Ölfelder vermessen! +visualprospecting.undergroundfluid.prospected.newandupdated=Du hast %s Ölfinder neu gefunden und %s vermessen! +visualprospecting.button.dirtychunk=Dirty Chunks anzeigen (Entwicklermodus, nur Einzelspieler) +visualprospecting.button.orevein=GT-Erzadern anzeigen +visualprospecting.button.undergroundfluid=GT-Gas/Flüssigkeitsadern anzeigen +visualprospecting.button.resetprogress=VisualProspecting zurücksetzen +visualprospecting.button.resetprogress.tooltip=Gefundene Erzadern und Flüssigkeitsadern (nur) für diesen Spieler zurücksetzen +visualprospecting.resetprogress.title=VisualProspecting-Forschritt löschen +visualprospecting.resetprogress.confirm=Ja, ich bin mir sicher! +visualprospecting.resetprogress.cancel=Abbrechen +visualprospecting.resetprogress.prompt=Spielerfortschritt bei Erz- und Flüssigkeitsadern löschen? +visualprospecting.resetprogress.command=Löscht deinen gesamten Fortschritt beim Entdecken von Erz- und Flüssigkeitsadern +visualprospecting.resetprogress.confirmation=Fortschritt gelöscht! +visualprospecting.redoservercache.command=GT-Ader-Cache auf dem Server wiederherstellen +visualprospecting.redoservercache.start=Cache-wiederherstellen auf dem Server beginnen +visualprospecting.redoservercache.failure=Konnte Weltdaten nicht laden, um Cache wiederherstellen! +visualprospecting.redoservercache.confirmation=Wiederherstellen erfolgreich! +visualprospecting.redoserverspawncache.command=GT-Erzader-Cache auf dem Server um den Spawnpunkt herum wiederherstellen +visualprospecting.redoserverspawncache.start=Wiederherstellen des GT-Erzader-Cache um den Spawnpunkt beginnen +visualprospecting.redoserverspawncache.failure=Konnte Weltdaten nicht laden, um Spawncache wiederherstellen! +visualprospecting.redoserverspawncache.confirmation=Wiederherstellen erfolgreich! +visualprospecting.iswaypoint=Als Wegpunkt aktiv +visualprospecting.depleted=ERSCHÖPFT +visualprospecting.depleted.toggle=Als erschöpft markieren mit %s +visualprospecting.empty=Leer +visualprospecting.key.action.name=Aktionsknopf +visualprospecting.key.toggleore.name=Erzoverlay (de)aktivieren +visualprospecting.key.togglefluid.name=Flüssigkeitsoverlay (de)aktivieren +visualprospecting.key.action.category=VisualProspecting +item.visualprospecting.prospectorslog.name=Goldsucher-Tagebuch +item.visualprospecting.prospectorslog.author=Autor: %s +item.visualprospecting.prospectorslog.empty=Item benutzen, um es aufzufüllen. +item.visualprospecting.prospectorslog.creation.begin=Ein Goldsucher-Tagebuch wurde geschrieben. +item.visualprospecting.prospectorslog.creation.fail0=[Failed]: Verdammt! Kaffee drübergekippt... +item.visualprospecting.prospectorslog.creation.fail1=[Failed]: Es scheint so, als kannst du deine eigenen Wörter nicht mehr lesen... +item.visualprospecting.prospectorslog.creation.fail2=[Failed]: Hätte ich mal nicht wie ein Arzt geschrieben! Unlesbar... +item.visualprospecting.prospectorslog.creation.fail3=[Failed]: Wo ist denn meine Brille? Ohne kann ich nicht schreiben! +item.visualprospecting.prospectorslog.creation.fail4=[Failed]: Herobrine hat meine Notizen geklaut! +item.visualprospecting.prospectorslog.reading.fail0=[Failed]: Riecht wie gute, Kaffee, aber ich kann es nicht lesen! +item.visualprospecting.prospectorslog.reading.fail1=[Failed]: Kommt mir Spanisch vor! +item.visualprospecting.prospectorslog.reading.fail2=[Failed]: Was?!? Das war leer!? +item.visualprospecting.prospectorslog.reading.fail3=[Failed]: Äääh... Keine Chance. Kann ich nicht entziffern! +item.visualprospecting.prospectorslog.reading.fail4=[Failed]: Habe ich einen Dr. in Geografie? NEIN! +item.visualprospecting.prospectorslog.reading.begin=Das ist mal ein Wälzer. Das zu lesen könnte eine Weile dauern. +item.visualprospecting.prospectorslog.reading.end=Goldsucher-Tagebuch von %s durchgelesen +visualprospecting.node.deletehint=Mit %s als erschöpft markieren +visualprospecting.tracked=Nachverfolgt: %s From e586b3f2f23b150c174d88b4ec21e2cc9b2d78dc Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Thu, 28 Aug 2025 09:20:14 +0200 Subject: [PATCH 090/132] update --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 3b2b6f3a..dedfcb9f 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') - api('com.github.GTNewHorizons:GTNHLib:0.6.38:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.423:dev') + api('com.github.GTNewHorizons:GTNHLib:0.6.39:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.430:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } From c59335b422cdeee94a087c6a85aadbe6ceb2f9db Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Wed, 1 Oct 2025 19:14:37 +0200 Subject: [PATCH 091/132] update --- dependencies.gradle | 4 ++-- settings.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index dedfcb9f..e02141b2 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') - api('com.github.GTNewHorizons:GTNHLib:0.6.39:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.51.430:dev') + api('com.github.GTNewHorizons:GTNHLib:0.7.0:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.02:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/settings.gradle b/settings.gradle index 7622cde1..9f80246c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.41' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.43' } From 7736c122e5647e65eb2131139eb6d29e061916db Mon Sep 17 00:00:00 2001 From: RecursivePineapple Date: Sun, 12 Oct 2025 08:23:39 -0400 Subject: [PATCH 092/132] Refactors for GT ore refactor PR (#65) Co-authored-by: Martin Robertz Co-authored-by: boubou19 --- README.md | 2 +- dependencies.gradle | 2 +- .../database/ClientCache.java | 42 +-- .../database/ServerCache.java | 21 ++ .../database/cachebuilder/ChunkAnalysis.java | 59 ++-- .../cachebuilder/DetailedChunkAnalysis.java | 65 ++--- .../cachebuilder/DimensionAnalysis.java | 65 ++--- .../cachebuilder/PartiallyLoadedChunk.java | 253 ++++++++++++++++++ .../BartworksOreMaterialProvider.java | 67 ----- .../GregTechOreMaterialProvider.java | 63 ----- .../veintypes/IOreMaterialProvider.java | 20 -- .../database/veintypes/VeinType.java | 143 +++++----- .../database/veintypes/VeinTypeCaching.java | 55 ---- .../model/locations/OreVeinLocation.java | 16 +- .../model/render/OreVeinRenderStep.java | 15 +- .../voxelmap/VoxelMapEventHandler.java | 3 +- .../visualprospecting/mixinplugin/Mixins.java | 12 +- .../bartworks/WorldGenContainerMixin.java | 49 ---- .../GT_Worldgenerator_SpaceMixin.java | 48 ---- .../gregtech/GT_Block_Ores_AbstractMixin.java | 32 --- ...java => MTEAdvSeismicProspectorMixin.java} | 43 ++- ...ScannerMixin.java => MTEScannerMixin.java} | 4 +- .../late/gregtech/WorldGenContainerMixin.java | 52 ---- .../network/ProspectingRequest.java | 107 ++++---- 24 files changed, 557 insertions(+), 681 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java rename src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/{GT_MetaTileEntity_AdvSeismicProspectorMixin.java => MTEAdvSeismicProspectorMixin.java} (76%) rename src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/{GT_MetaTileEntity_ScannerMixin.java => MTEScannerMixin.java} (98%) delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java diff --git a/README.md b/README.md index 62f6ef1f..f8cebd77 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ _Dirty chunks in JourneyMap developer overlay_ - Minecraft Forge - Injected class: [_ItemEditableBook_](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/mixins/minecraft/ItemEditableBookMixin.java) - [GregTech5-Unofficial](https://github.com/GTNewHorizons/GT5-Unofficial) - - Injected classes: [_GT_Block_Ores_Abstract_](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_Block_Ores_AbstractMixin.java), [_GT_MetaTileEntity_AdvSeismicProspector_](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java), [_GT_MetaTileEntity_Scanner_](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/GT_MetaTileEntity_ScannerMixin.java), [_GT_Worldgenerator.WorldGenContainer_](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/WorldGenContainerMixin.java) + - Injected classes: [_GT_MetaTileEntity_AdvSeismicProspector_](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/MTEAdvSeismicProspectorMixin.java), [_GT_MetaTileEntity_Scanner_](https://github.com/SinTh0r4s/VisualProspecting/blob/master/src/main/java/com/sinthoras/visualprospecting/mixins/gregtech/MTEScannerMixin.java) - [SpongeMixins](https://github.com/GTNewHorizons/SpongeMixins) - [Enklumne](https://github.com/Hugobros3/Enklume) _by Hugobros3_ - Automatically shipped. No manual handling is required. diff --git a/dependencies.gradle b/dependencies.gradle index e02141b2..0076d14a 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') api('com.github.GTNewHorizons:GTNHLib:0.7.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.02:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.31:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index 41fdfca6..d10ef444 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -8,7 +8,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; @@ -24,12 +23,20 @@ import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; import com.sinthoras.visualprospecting.network.ProspectingRequest; -import gregtech.common.blocks.TileEntityOres; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import gregtech.api.events.OreInteractEvent; +import gregtech.api.interfaces.IOreMaterial; +import gregtech.common.ores.OreInfo; +import gregtech.common.ores.OreManager; public class ClientCache extends WorldCache { public static final ClientCache instance = new ClientCache(); + public ClientCache() { + MinecraftForge.EVENT_BUS.register(this); + } + protected File getStorageDirectory() { final EntityClientPlayerMP player = Minecraft.getMinecraft().thePlayer; File oldCacheDir = new File( @@ -132,20 +139,23 @@ public void putUndergroundFluids(List undergroundFluid Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); } - public void onOreInteracted(World world, int blockX, int blockY, int blockZ, EntityPlayer entityPlayer) { - if (world.isRemote && Config.enableProspecting && Minecraft.getMinecraft().thePlayer == entityPlayer) { - final TileEntity tTileEntity = world.getTileEntity(blockX, blockY, blockZ); - if (tTileEntity instanceof TileEntityOres ore) { - final short oreMetaData = ore.mMetaData; - if (!Utils.isSmallOreId(oreMetaData) && oreMetaData != 0) { - final int chunkX = Utils.coordBlockToChunk(blockX); - final int chunkZ = Utils.coordBlockToChunk(blockZ); - final OreVeinPosition oreVeinPosition = getOreVein(entityPlayer.dimension, chunkX, chunkZ); - final short materialId = Utils.oreIdToMaterialId(oreMetaData); - if (!oreVeinPosition.veinType.containsOre(materialId) && ProspectingRequest.canSendRequest()) { - VP.network.sendToServer( - new ProspectingRequest(entityPlayer.dimension, blockX, blockY, blockZ, materialId)); - } + @SubscribeEvent + public void onOreClicked(OreInteractEvent event) { + onOreInteracted(event.world, event.x, event.y, event.z, event.player); + } + + @SuppressWarnings("unchecked") + public void onOreInteracted(World world, int x, int y, int z, EntityPlayer player) { + if (world.isRemote && Config.enableProspecting && Minecraft.getMinecraft().thePlayer == player) { + try (OreInfo info = OreManager.getOreInfo(world, x, y, z)) { + if (info == null || info.isSmall) return; + + final int chunkX = Utils.coordBlockToChunk(x); + final int chunkZ = Utils.coordBlockToChunk(z); + final OreVeinPosition oreVeinPosition = getOreVein(player.dimension, chunkX, chunkZ); + + if (!oreVeinPosition.veinType.containsOre(info.material) && ProspectingRequest.canSendRequest()) { + VP.network.sendToServer(new ProspectingRequest(player.dimension, x, y, z, info.material)); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java index 38c4a620..7ba9b415 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java @@ -5,6 +5,7 @@ import java.util.List; import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; @@ -14,12 +15,19 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import gregtech.api.events.VeinGenerateEvent; import gregtech.common.UndergroundOil; +import gregtech.common.WorldgenGTOreLayer; public class ServerCache extends WorldCache { public static final ServerCache instance = new ServerCache(); + private ServerCache() { + MinecraftForge.EVENT_BUS.register(this); + } + protected File getStorageDirectory() { return Utils.getSubDirectory(Tags.SERVER_DIR); } @@ -30,6 +38,19 @@ public synchronized void notifyOreVeinGeneration(int dimensionId, int chunkX, in } } + @SubscribeEvent + public void onVeinGenerated(VeinGenerateEvent event) { + if (event.result == WorldgenGTOreLayer.ORE_PLACED && !event.layer.mWorldGenName.equals("NoOresInVein")) { + if (event.chunkX == event.oreSeedX && event.chunkZ == event.oreSeedZ) { + notifyOreVeinGeneration( + event.world.provider.dimensionId, + event.oreSeedX, + event.oreSeedZ, + event.layer.mWorldGenName); + } + } + } + public void notifyOreVeinGeneration(int dimensionId, int chunkX, int chunkZ, final String veinName) { notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, VeinTypeCaching.getVeinType(veinName)); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java index 4b04543e..2ecbb691 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java @@ -1,71 +1,58 @@ package com.sinthoras.visualprospecting.database.cachebuilder; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; +import java.util.Comparator; +import java.util.Map; +import java.util.stream.Collectors; -import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import gregtech.api.interfaces.IOreMaterial; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectSet; -import it.unimi.dsi.fastutil.shorts.Short2IntArrayMap; -import it.unimi.dsi.fastutil.shorts.Short2IntMap; -import it.unimi.dsi.fastutil.shorts.ShortArrayList; -import it.unimi.dsi.fastutil.shorts.ShortList; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // A slim, but faster version to identify >90% of veins public class ChunkAnalysis { private final ObjectSet matchedVeins = new ObjectOpenHashSet<>(); - private final Short2IntMap oreCounts = new Short2IntArrayMap(); + private final Reference2IntOpenHashMap oreCounts = new Reference2IntOpenHashMap<>(); private int minVeinBlockY = VP.minecraftWorldHeight; - private short primaryMeta; + private IOreMaterial mostCommonOre; private final String dimName; public ChunkAnalysis(String dimName) { this.dimName = dimName; } - public void processMinecraftChunk(final NBTTagList tileEntities) { - if (tileEntities == null || tileEntities.tagCount() == 0) return; - for (int i = 0; i < tileEntities.tagCount(); i++) { - final NBTTagCompound tile = tileEntities.getCompoundTagAt(i); - if (tile == null || !tile.hasKey("m")) continue; + public void processMinecraftChunk(final PartiallyLoadedChunk chunk) { + chunk.forEachOre((x, y, z, info) -> { + oreCounts.addTo(info.material, 1); - String id = tile.getString("id"); - if (!"GT_TileEntity_Ores".equals(id) && !"bw.blockoresTE".equals(id)) { - continue; + if (minVeinBlockY > y) { + minVeinBlockY = y; } + }); - short meta = tile.getShort("m"); - if (Utils.isSmallOreId(meta) || meta == 0) continue; + // spotless:off + var byCount = oreCounts.reference2IntEntrySet() + .stream() + .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) + .collect(Collectors.toList()); + // spotless:on - meta = Utils.oreIdToMaterialId(meta); - final int blockY = tile.getInteger("y"); - - oreCounts.put(meta, oreCounts.get(meta) + 1); - if (minVeinBlockY > blockY) { - minVeinBlockY = blockY; - } - } - - if (oreCounts.size() == 1) { - primaryMeta = oreCounts.keySet().iterator().nextShort(); - } else if (oreCounts.size() > 1) { - ShortList metaCounts = new ShortArrayList(oreCounts.keySet()); - metaCounts.sort((a, b) -> Integer.compare(oreCounts.get(b), oreCounts.get(a))); - primaryMeta = metaCounts.getShort(0); - } + if (!byCount.isEmpty()) mostCommonOre = byCount.get(0).getKey(); } public boolean matchesSingleVein() { if (oreCounts.isEmpty()) return true; if (oreCounts.size() > 4) return false; + // spotless:off VeinTypeCaching.getVeinTypes().stream() - .filter(vein -> vein.containsAllFoundOres(oreCounts.keySet(), dimName, primaryMeta, minVeinBlockY)) + .filter(vein -> vein.containsAllFoundOres(oreCounts.keySet(), dimName, mostCommonOre, minVeinBlockY)) .forEach(matchedVeins::add); + // spotless:on return matchedVeins.size() <= 1; } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index 3a9799c1..6c4d2c34 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -7,9 +7,6 @@ import java.util.Set; import java.util.stream.IntStream; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; - import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.OreVeinPosition; @@ -17,8 +14,8 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; -import it.unimi.dsi.fastutil.shorts.Short2IntMap; -import it.unimi.dsi.fastutil.shorts.Short2IntOpenHashMap; +import gregtech.api.interfaces.IOreMaterial; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // Slower, but more sophisticated approach to identify overlapping veins public class DetailedChunkAnalysis { @@ -27,7 +24,7 @@ public class DetailedChunkAnalysis { public final int chunkX; public final int chunkZ; // For each height we count how often a ore (short) has occured - private final Short2IntMap[] oresPerY = new Short2IntOpenHashMap[VP.minecraftWorldHeight]; + private final Reference2IntOpenHashMap[] oresPerY = new Reference2IntOpenHashMap[VP.minecraftWorldHeight]; private final String dimName; public DetailedChunkAnalysis(int dimensionId, String dimName, int chunkX, int chunkZ) { @@ -37,29 +34,14 @@ public DetailedChunkAnalysis(int dimensionId, String dimName, int chunkX, int ch this.dimName = dimName; } - public void processMinecraftChunk(final NBTTagList tileEntities) { - if (tileEntities == null || tileEntities.tagCount() == 0) return; - for (int i = 0; i < tileEntities.tagCount(); i++) { - final NBTTagCompound tile = tileEntities.getCompoundTagAt(i); - if (tile == null || !tile.hasKey("m")) continue; - - String id = tile.getString("id"); - if (!"GT_TileEntity_Ores".equals(id) && !"bw.blockoresTE".equals(id)) { - continue; + public void processMinecraftChunk(final PartiallyLoadedChunk chunk) { + chunk.forEachOre((x, y, z, info) -> { + if (oresPerY[y] == null) { + oresPerY[y] = new Reference2IntOpenHashMap<>(); } - short meta = tile.getShort("m"); - if (Utils.isSmallOreId(meta) || meta == 0) continue; - - meta = Utils.oreIdToMaterialId(meta); - final int blockY = tile.getInteger("y"); - - if (oresPerY[blockY] == null) { - oresPerY[blockY] = new Short2IntOpenHashMap(); - } - - oresPerY[blockY].put(meta, oresPerY[blockY].get(meta) + 1); - } + oresPerY[y].addTo(info.material, 1); + }); } public void cleanUpWithNeighbors(final Map veinChunkY) { @@ -127,14 +109,17 @@ public void cleanUpWithNeighbors(final Map veinChunkY) { : neighbor.veinType.canOverlapIntoNeighborOreChunk(); if (canOverlap) { final int veinBlockY = neighborVeinBlockY[neighborId]; + for (int layerBlockY = 0; layerBlockY < VeinType.veinHeight; layerBlockY++) { final int blockY = veinBlockY + layerBlockY; + if (blockY > 255) { break; } + if (oresPerY[blockY] != null) { - for (short metaData : neighbor.veinType.getOresAtLayer(layerBlockY)) { - oresPerY[blockY].remove(metaData); + for (IOreMaterial ore : neighbor.veinType.getOresAtLayer(layerBlockY)) { + oresPerY[blockY].removeInt(ore); } } } @@ -145,20 +130,26 @@ public void cleanUpWithNeighbors(final Map veinChunkY) { public VeinType getMatchedVein() { final Set matchedVeins = new HashSet<>(); - final Short2IntMap allOres = new Short2IntOpenHashMap(); - for (Short2IntMap oreLevel : oresPerY) { + final Reference2IntOpenHashMap allOres = new Reference2IntOpenHashMap<>(); + + for (Reference2IntOpenHashMap oreLevel : oresPerY) { if (oreLevel == null || oreLevel.isEmpty()) continue; - for (Short2IntMap.Entry entry : oreLevel.short2IntEntrySet()) { - short metaData = entry.getShortKey(); - int numberOfBlocks = entry.getIntValue(); - allOres.merge(metaData, numberOfBlocks, Integer::sum); + + for (var entry : oreLevel.reference2IntEntrySet()) { + allOres.addTo(entry.getKey(), entry.getIntValue()); } } if (allOres.isEmpty()) return VeinType.NO_VEIN; - final Optional dominantOre = allOres.short2IntEntrySet().stream() - .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(Map.Entry::getKey).findFirst(); + // spotless:off + final Optional dominantOre = allOres.reference2IntEntrySet() + .stream() + .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) + .map(Map.Entry::getKey) + .findFirst(); + // spotless:on + if (!dominantOre.isPresent()) return VeinType.NO_VEIN; for (VeinType veinType : VeinTypeCaching.getVeinTypes()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java index 620692a2..889015f8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java @@ -8,7 +8,7 @@ import java.util.regex.Pattern; import java.util.zip.DataFormatException; -import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.WorldProvider; import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; @@ -31,7 +31,7 @@ public DimensionAnalysis(int dimensionId) { private interface IChunkHandler { - void processChunk(NBTTagList root, int chunkX, int chunkZ); + void processChunk(PartiallyLoadedChunk chunk, int chunkX, int chunkZ); } public void processMinecraftWorld(Collection regionFiles) { @@ -46,21 +46,21 @@ public void processMinecraftWorld(Collection regionFiles) { final Map chunksForSecondIdentificationPass = new ConcurrentHashMap<>(); regionFiles.parallelStream().forEach(regionFile -> { - executeForEachGeneratedOreChunk(regionFile, (root, chunkX, chunkZ) -> { - final ChunkAnalysis chunk = new ChunkAnalysis(dimensionName); - chunk.processMinecraftChunk(root); + executeForEachGeneratedOreChunk(regionFile, (chunk, chunkX, chunkZ) -> { + final ChunkAnalysis analysis = new ChunkAnalysis(dimensionName); + analysis.processMinecraftChunk(chunk); - if (chunk.matchesSingleVein()) { + if (analysis.matchesSingleVein()) { ServerCache.instance - .notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, chunk.getMatchedVein()); - veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), chunk.getVeinBlockY()); + .notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, analysis.getMatchedVein()); + veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), analysis.getVeinBlockY()); } else { final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis( dimensionId, dimensionName, chunkX, chunkZ); - detailedChunk.processMinecraftChunk(root); + detailedChunk.processMinecraftChunk(chunk); chunksForSecondIdentificationPass.put(Utils.chunkCoordsToKey(chunkX, chunkZ), detailedChunk); } }); @@ -76,33 +76,35 @@ public void processMinecraftWorld(Collection regionFiles) { AnalysisProgressTracker.setNumberOfRegionFiles(regionFiles.size() * 2); regionFiles.parallelStream().forEach(regionFile -> { - executeForEachGeneratedOreChunk(regionFile, (root, chunkX, chunkZ) -> { - final ChunkAnalysis chunk = new ChunkAnalysis(dimensionName); - chunk.processMinecraftChunk(root); + executeForEachGeneratedOreChunk(regionFile, (chunk, chunkX, chunkZ) -> { + final ChunkAnalysis analysis = new ChunkAnalysis(dimensionName); + analysis.processMinecraftChunk(chunk); - if (chunk.matchesSingleVein()) { + if (analysis.matchesSingleVein()) { ServerCache.instance - .notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, chunk.getMatchedVein()); - veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), chunk.getVeinBlockY()); + .notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, analysis.getMatchedVein()); + veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), analysis.getVeinBlockY()); } }); }); regionFiles.parallelStream().forEach(regionFile -> { - executeForEachGeneratedOreChunk(regionFile, (root, chunkX, chunkZ) -> { + executeForEachGeneratedOreChunk(regionFile, (chunk, chunkX, chunkZ) -> { if (ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ).veinType == VeinType.NO_VEIN) { - final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis( + final DetailedChunkAnalysis detailedAnalysis = new DetailedChunkAnalysis( dimensionId, dimensionName, chunkX, chunkZ); - detailedChunk.processMinecraftChunk(root); - detailedChunk.cleanUpWithNeighbors(veinBlockY); + + detailedAnalysis.processMinecraftChunk(chunk); + detailedAnalysis.cleanUpWithNeighbors(veinBlockY); + ServerCache.instance.notifyOreVeinGeneration( dimensionId, - detailedChunk.chunkX, - detailedChunk.chunkZ, - detailedChunk.getMatchedVein()); + detailedAnalysis.chunkX, + detailedAnalysis.chunkZ, + detailedAnalysis.getMatchedVein()); } }); }); @@ -125,14 +127,17 @@ private void executeForEachGeneratedOreChunk(File regionFile, IChunkHandler chun final int chunkZ = regionChunkZ + localChunkZ; // Only process ore chunks - if (chunkX == Utils.mapToCenterOreChunkCoord(chunkX) - && chunkZ == Utils.mapToCenterOreChunkCoord(chunkZ)) { - final NBTTagList chunkTiles = region.getChunkTiles(localChunkX, localChunkZ); - - if (chunkTiles != null) { - chunkHandler.processChunk(chunkTiles, chunkX, chunkZ); - } - } + if (chunkX != Utils.mapToCenterOreChunkCoord(chunkX)) continue; + if (chunkZ != Utils.mapToCenterOreChunkCoord(chunkZ)) continue; + + NBTTagCompound chunk = region.getChunk(localChunkX, localChunkZ); + + if (chunk == null) continue; + + PartiallyLoadedChunk loadedChunk = new PartiallyLoadedChunk(); + loadedChunk.load(chunk, chunkX, chunkZ); + + chunkHandler.processChunk(loadedChunk, chunkX, chunkZ); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java new file mode 100644 index 00000000..be9ac4c4 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java @@ -0,0 +1,253 @@ +package com.sinthoras.visualprospecting.database.cachebuilder; + +import java.nio.ByteBuffer; +import java.nio.ShortBuffer; +import java.util.Iterator; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.Constants.NBT; + +import com.gtnewhorizon.gtnhlib.util.data.ImmutableBlockMeta; +import com.sinthoras.visualprospecting.VP; + +import bartworks.system.material.Werkstoff; +import gregtech.api.enums.Materials; +import gregtech.api.interfaces.IOreMaterial; +import gregtech.common.ores.BWOreAdapter; +import gregtech.common.ores.GTOreAdapter; +import gregtech.common.ores.OreInfo; +import gregtech.common.ores.OreManager; +import it.unimi.dsi.fastutil.ints.Int2ShortFunction; + +public class PartiallyLoadedChunk { + + private static final int SECTION_SIZE = 16; + private static final int BLOCKS_PER_EBS = SECTION_SIZE * SECTION_SIZE * SECTION_SIZE; + public static final int CHUNK_HEIGHT = 256; + private static final int SECTIONS_PER_CHUNK = CHUNK_HEIGHT / SECTION_SIZE; + + private final Int2ShortFunction[] blocks = new Int2ShortFunction[SECTIONS_PER_CHUNK]; + private final Int2ShortFunction[] metas = new Int2ShortFunction[SECTIONS_PER_CHUNK]; + + private List tiles; + + @SuppressWarnings("unchecked") + public void load(NBTTagCompound chunk, int chunkX, int chunkZ) { + NBTTagList sections = chunk.getCompoundTag("Level").getTagList("Sections", NBT.TAG_COMPOUND); + + List sectionTags = (List) sections.tagList; + + for (NBTTagCompound section : sectionTags) { + byte y = section.getByte("Y"); + + if (section.hasKey("Blocks16")) { + ShortBuffer blocks = ByteBuffer.wrap(section.getByteArray("Blocks16")).asShortBuffer(); + ShortBuffer metas = ByteBuffer.wrap(section.getByteArray("Data16")).asShortBuffer(); + + if (blocks.capacity() == 0 || metas.capacity() == 0) { + // no-op for empty sections + this.blocks[y] = i -> (short) 0; + this.metas[y] = i -> (short) 0; + continue; + } + + if (blocks.capacity() != BLOCKS_PER_EBS) { + VP.LOG.error( + "Corrupt section detected at X={}, Y={}, Z={} (Blocks16 length was {}, needs {})", + chunkX, + y, + chunkZ, + blocks.capacity(), + BLOCKS_PER_EBS); + continue; + } + + if (metas.capacity() != BLOCKS_PER_EBS) { + VP.LOG.error( + "Corrupt section detected at X={}, Y={}, Z={} (Data16 length was {}, needs {})", + chunkX, + y, + chunkZ, + metas.capacity(), + BLOCKS_PER_EBS); + continue; + } + + this.blocks[y] = blocks::get; + this.metas[y] = metas::get; + } else { + // don't bother loading the actual blocks, if a chunk is this old it'll only have ore tiles + this.blocks[y] = i -> (short) 0; + this.metas[y] = i -> (short) 0; + } + } + + tiles = chunk.getCompoundTag("Level").getTagList("TileEntities", NBT.TAG_COMPOUND).tagList; + } + + public int getBlockId(int x, int y, int z) { + if (x < 0 || x >= 16) throw new IllegalArgumentException("x"); + if (y < 0 || y >= CHUNK_HEIGHT) throw new IllegalArgumentException("y"); + if (z < 0 || z >= 16) throw new IllegalArgumentException("z"); + + int index = y << 8 | z << 4 | x; + + int section = index / BLOCKS_PER_EBS; + + Int2ShortFunction blocks = this.blocks[section]; + + if (blocks == null) return 0; + + int withinSection = index % BLOCKS_PER_EBS; + + return blocks.get(withinSection); + } + + public Block getBlock(int x, int y, int z) { + return Block.getBlockById(getBlockId(x, y, z)); + } + + public int getBlockMeta(int x, int y, int z) { + if (x < 0 || x >= 16) throw new IllegalArgumentException("x"); + if (y < 0 || y >= CHUNK_HEIGHT) throw new IllegalArgumentException("y"); + if (z < 0 || z >= 16) throw new IllegalArgumentException("z"); + + int index = y << 8 | z << 4 | x; + + int section = index / BLOCKS_PER_EBS; + + Int2ShortFunction metas = this.metas[section]; + + if (metas == null) return 0; + + int withinSection = index % BLOCKS_PER_EBS; + + return metas.get(withinSection); + } + + public interface OreConsumer { + + void visit(int x, int y, int z, OreInfo ore); + } + + @SuppressWarnings("unchecked") + public void forEachOre(OreConsumer consumer) { + for (PartiallyLoadedChunk.TileEntityInfo te : tileEntities()) { + if (!te.getId().equals("GT_TileEntity_Ores")) continue; + + short meta = te.getTag().getShort("m"); + boolean natural = te.getTag().getBoolean("n"); + + if (!natural) continue; + + ImmutableBlockMeta bm = GTOreAdapter.INSTANCE.transform(meta, true); + + try (OreInfo info = GTOreAdapter.INSTANCE.getOreInfo(bm.getBlock(), bm.getBlockMeta())) { + if (info == null || info.isSmall || info.material == null) continue; + + consumer.visit(te.getX(), te.getY(), te.getZ(), (OreInfo) (OreInfo) info); + } + } + + for (PartiallyLoadedChunk.TileEntityInfo te : tileEntities()) { + if (!te.getId().equals("bw.blockoresTE")) continue; + + short meta = te.getTag().getShort("m"); + boolean natural = te.getTag().getBoolean("n"); + + if (!natural) continue; + + ImmutableBlockMeta bm = BWOreAdapter.INSTANCE.transform(meta, true, false); + + try (OreInfo info = BWOreAdapter.INSTANCE.getOreInfo(bm.getBlock(), bm.getBlockMeta())) { + if (info == null || info.isSmall || info.material == null) continue; + + consumer.visit(te.getX(), te.getY(), te.getZ(), (OreInfo) (OreInfo) info); + } + } + + for (int y = 0; y < PartiallyLoadedChunk.CHUNK_HEIGHT; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + Block block = getBlock(x, y, z); + int meta = getBlockMeta(x, y, z); + + try (OreInfo info = OreManager.getOreInfo(block, meta)) { + if (info == null || info.isSmall || !info.isNatural || info.material == null) continue; + + consumer.visit(x, y, z, info); + } + } + } + } + } + + public interface TileEntityInfo { + + String getId(); + + int getX(); + + int getY(); + + int getZ(); + + NBTTagCompound getTag(); + } + + public Iterable tileEntities() { + return TileEntityIterator::new; + } + + private class TileEntityIterator implements Iterator { + + private final TileEntityInfoImpl info = new TileEntityInfoImpl(); + + private int tileIndex; + + @Override + public boolean hasNext() { + return tileIndex < tiles.size(); + } + + @Override + public TileEntityInfo next() { + info.tag = tiles.get(tileIndex++); + + return info; + } + } + + private static class TileEntityInfoImpl implements TileEntityInfo { + + public NBTTagCompound tag; + + @Override + public String getId() { + return tag.getString("id"); + } + + @Override + public int getX() { + return tag.getInteger("x"); + } + + @Override + public int getY() { + return tag.getInteger("y"); + } + + @Override + public int getZ() { + return tag.getInteger("z"); + } + + @Override + public NBTTagCompound getTag() { + return tag; + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java deleted file mode 100644 index a49967a8..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/BartworksOreMaterialProvider.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.sinthoras.visualprospecting.database.veintypes; - -import java.util.ArrayList; -import java.util.List; - -import com.google.common.collect.ImmutableList; - -import bartworks.system.material.Werkstoff; -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import gregtech.api.GregTechAPI; -import gregtech.api.enums.OrePrefixes; -import gregtech.api.interfaces.IIconContainer; -import it.unimi.dsi.fastutil.shorts.ShortCollection; - -public class BartworksOreMaterialProvider implements IOreMaterialProvider { - - private final Werkstoff material; - private final int primaryOreColor; - private final String primaryOreName; - private IIconContainer oreIconContainer; - private ImmutableList containedOres; - - public BartworksOreMaterialProvider(Werkstoff material) { - this.material = material; - final short[] rgba = material.getRGBA(); - this.primaryOreColor = (rgba[0] & 0x0ff) << 16 | (rgba[1] & 0x0ff) << 8 | rgba[2] & 0x0ff; - this.primaryOreName = material.getLocalizedName(); - } - - @Override - @SideOnly(Side.CLIENT) - public IIconContainer getIconContainer() { - if (oreIconContainer == null) { - oreIconContainer = material.getTexSet().mTextures[OrePrefixes.ore.mTextureIndex]; - } - return oreIconContainer; - } - - @Override - public int getColor() { - return primaryOreColor; - } - - @Override - public String getLocalizedName() { - return primaryOreName; - } - - @Override - public ImmutableList getContainedOres(ShortCollection ores) { - if (containedOres == null) { - List oreNames = new ArrayList<>(); - for (short meta : ores) { - Werkstoff werkstoff = Werkstoff.werkstoffHashMap.get(meta); - if (werkstoff == null) { - oreNames.add(GregTechAPI.sGeneratedMaterials[meta].mLocalizedName); - } else { - oreNames.add(werkstoff.getLocalizedName()); - - } - } - containedOres = ImmutableList.copyOf(oreNames); - } - return containedOres; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java deleted file mode 100644 index a38a2b63..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/GregTechOreMaterialProvider.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.sinthoras.visualprospecting.database.veintypes; - -import java.util.ArrayList; -import java.util.List; - -import com.google.common.collect.ImmutableList; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import gregtech.api.GregTechAPI; -import gregtech.api.enums.Materials; -import gregtech.api.enums.OrePrefixes; -import gregtech.api.interfaces.IIconContainer; -import it.unimi.dsi.fastutil.shorts.ShortCollection; - -public class GregTechOreMaterialProvider implements IOreMaterialProvider { - - private final Materials material; - private final int primaryOreColor; - private IIconContainer oreIconContainer; - private final String primaryOreName; - private ImmutableList containedOres; - - public GregTechOreMaterialProvider(Materials material) { - this.material = material; - this.primaryOreColor = (material.mRGBa[0] << 16) | (material.mRGBa[1]) << 8 | material.mRGBa[2]; - this.primaryOreName = material.mLocalizedName; - } - - @Override - @SideOnly(Side.CLIENT) - public IIconContainer getIconContainer() { - if (oreIconContainer == null) { - oreIconContainer = material.mIconSet.mTextures[OrePrefixes.ore.mTextureIndex]; - } - return oreIconContainer; - } - - @Override - public int getColor() { - return primaryOreColor; - } - - @Override - public String getLocalizedName() { - return primaryOreName; - } - - @Override - public ImmutableList getContainedOres(ShortCollection ores) { - if (containedOres == null) { - List temp = new ArrayList<>(); - for (short meta : ores) { - if (meta < 0) break; - Materials material = GregTechAPI.sGeneratedMaterials[meta]; - if (material == null) continue; - temp.add(material.mLocalizedName); - } - containedOres = ImmutableList.copyOf(temp); - } - return containedOres; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java deleted file mode 100644 index 10cc40f4..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/IOreMaterialProvider.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.sinthoras.visualprospecting.database.veintypes; - -import com.google.common.collect.ImmutableList; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import gregtech.api.interfaces.IIconContainer; -import it.unimi.dsi.fastutil.shorts.ShortCollection; - -public interface IOreMaterialProvider { - - @SideOnly(Side.CLIENT) - IIconContainer getIconContainer(); - - int getColor(); - - String getLocalizedName(); - - ImmutableList getContainedOres(ShortCollection ores); -} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 8c54b8ce..63a0a1c2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -1,19 +1,18 @@ package com.sinthoras.visualprospecting.database.veintypes; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.stream.Collectors; import javax.annotation.ParametersAreNonnullByDefault; import com.google.common.collect.ImmutableList; import com.sinthoras.visualprospecting.Tags; -import gregtech.api.enums.Materials; +import gregtech.api.interfaces.IOreMaterial; import gregtech.common.OreMixBuilder; -import it.unimi.dsi.fastutil.shorts.ShortArraySet; -import it.unimi.dsi.fastutil.shorts.ShortCollection; -import it.unimi.dsi.fastutil.shorts.ShortOpenHashSet; -import it.unimi.dsi.fastutil.shorts.ShortSet; @ParametersAreNonnullByDefault public class VeinType { @@ -21,71 +20,59 @@ public class VeinType { public static final int veinHeight = 9; public final String name; - public final IOreMaterialProvider oreMaterialProvider; public final int blockSize; - public final short primaryOreMeta; - public final short secondaryOreMeta; - public final short inBetweenOreMeta; - public final short sporadicOreMeta; + public final IOreMaterial representativeOre; + public final IOreMaterial primaryOre; + public final IOreMaterial secondaryOre; + public final IOreMaterial inBetweenOre; + public final IOreMaterial sporadicOre; public final int minBlockY; public final int maxBlockY; - private final ShortSet oresAsSet = new ShortArraySet(); + private final HashSet oresAsSet = new HashSet(); private final List allowedDims = new ArrayList<>(); private boolean isHighlighted = true; private final String localizedName; // Available after VisualProspecting post GT initialization - public static final VeinType NO_VEIN = new VeinType( - Tags.ORE_MIX_NONE_NAME, - new GregTechOreMaterialProvider(Materials._NULL), - 0, - (short) -1, - (short) -1, - (short) -1, - (short) -1, - 0, - 0, - ""); - - public VeinType(String name, IOreMaterialProvider oreMaterialProvider, int blockSize, short primaryOreMeta, - short secondaryOreMeta, short inBetweenOreMeta, short sporadicOreMeta, int minBlockY, int maxBlockY, - String dimName) { - this.name = name; - this.oreMaterialProvider = oreMaterialProvider; - this.blockSize = blockSize; - this.minBlockY = Math.max(0, minBlockY); - this.maxBlockY = Math.min(255, maxBlockY); - oresAsSet.add(this.primaryOreMeta = primaryOreMeta); - oresAsSet.add(this.secondaryOreMeta = secondaryOreMeta); - oresAsSet.add(this.inBetweenOreMeta = inBetweenOreMeta); - oresAsSet.add(this.sporadicOreMeta = sporadicOreMeta); - localizedName = oreMaterialProvider.getLocalizedName(); - allowedDims.add(dimName); + public static final VeinType NO_VEIN = new VeinType(); + + private VeinType() { + this.name = Tags.ORE_MIX_NONE_NAME; + this.blockSize = 0; + this.minBlockY = 0; + this.maxBlockY = 255; + this.representativeOre = null; + this.primaryOre = null; + this.secondaryOre = null; + this.inBetweenOre = null; + this.sporadicOre = null; + this.localizedName = this.name; } public VeinType(OreMixBuilder oreMix) { name = oreMix.oreMixName; - oreMaterialProvider = new GregTechOreMaterialProvider(oreMix.representative); localizedName = oreMix.localizedName; blockSize = oreMix.size; - oresAsSet.add(primaryOreMeta = (short) oreMix.primary.mMetaItemSubID); - oresAsSet.add(secondaryOreMeta = (short) oreMix.secondary.mMetaItemSubID); - oresAsSet.add(inBetweenOreMeta = (short) oreMix.between.mMetaItemSubID); - oresAsSet.add(sporadicOreMeta = (short) oreMix.sporadic.mMetaItemSubID); + representativeOre = oreMix.representative; + oresAsSet.add(primaryOre = oreMix.primary); + oresAsSet.add(secondaryOre = oreMix.secondary); + oresAsSet.add(inBetweenOre = oreMix.between); + oresAsSet.add(sporadicOre = oreMix.sporadic); minBlockY = Math.max(0, oreMix.minY - 6); maxBlockY = Math.min(255, oreMix.maxY - 6); - allowedDims.addAll(oreMix.dimsEnabled.keySet()); + allowedDims.addAll(oreMix.dimsEnabled); } - public boolean containsAllFoundOres(ShortCollection foundOres, String dimName, short specificMeta, int minY) { - return minY >= minBlockY && (primaryOreMeta == specificMeta || secondaryOreMeta == specificMeta) + public boolean containsAllFoundOres(Collection foundOres, String dimName, IOreMaterial specific, + int minY) { + return minY >= minBlockY && (primaryOre == specific || secondaryOre == specific) && (dimName.isEmpty() || allowedDims.contains(dimName)) && oresAsSet.containsAll(foundOres); } - public boolean matchesWithSpecificPrimaryOrSecondary(ShortCollection foundOres, String dimName, - short specificMeta) { - return (primaryOreMeta == specificMeta || secondaryOreMeta == specificMeta) + public boolean matchesWithSpecificPrimaryOrSecondary(Collection foundOres, String dimName, + IOreMaterial specific) { + return (primaryOre == specific || secondaryOre == specific) && (dimName.isEmpty() || allowedDims.contains(dimName)) && foundOres.containsAll(oresAsSet); } @@ -99,51 +86,53 @@ public boolean canOverlapIntoNeighborOreChunkAtCoordinateAxis() { return blockSize > 16; } - public boolean containsOre(short oreMetaData) { - return primaryOreMeta == oreMetaData || secondaryOreMeta == oreMetaData - || inBetweenOreMeta == oreMetaData - || sporadicOreMeta == oreMetaData; + public boolean containsOre(IOreMaterial ore) { + return primaryOre == ore || secondaryOre == ore || inBetweenOre == ore || sporadicOre == ore; } public ImmutableList getOreMaterialNames() { - return oreMaterialProvider.getContainedOres(oresAsSet); + return ImmutableList + .copyOf(oresAsSet.stream().map(IOreMaterial::getLocalizedName).collect(Collectors.toList())); } public String getVeinName() { return localizedName; } - public ShortSet getOresAtLayer(int layerBlockY) { - final ShortSet result = new ShortOpenHashSet(); + public List getOresAtLayer(int layerBlockY) { + final List result = new ArrayList<>(); + switch (layerBlockY) { - case 0: - case 1: - case 2: - result.add(secondaryOreMeta); - result.add(sporadicOreMeta); + case 0, 1, 2 -> { + result.add(secondaryOre); + result.add(sporadicOre); return result; - case 3: - result.add(secondaryOreMeta); - result.add(inBetweenOreMeta); - result.add(sporadicOreMeta); + } + case 3 -> { + result.add(secondaryOre); + result.add(inBetweenOre); + result.add(sporadicOre); return result; - case 4: - result.add(inBetweenOreMeta); - result.add(sporadicOreMeta); + } + case 4 -> { + result.add(inBetweenOre); + result.add(sporadicOre); return result; - case 5: - case 6: - result.add(primaryOreMeta); - result.add(inBetweenOreMeta); - result.add(sporadicOreMeta); + } + case 5, 6 -> { + result.add(primaryOre); + result.add(inBetweenOre); + result.add(sporadicOre); return result; - case 7: - case 8: - result.add(primaryOreMeta); - result.add(sporadicOreMeta); + } + case 7, 8 -> { + result.add(primaryOre); + result.add(sporadicOre); return result; - default: + } + default -> { return result; + } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index 8e7fde20..0cb7eaf3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -3,24 +3,17 @@ import static com.sinthoras.visualprospecting.Utils.*; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; -import java.util.Objects; import java.util.regex.Pattern; import net.minecraft.util.EnumChatFormatting; -import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.sinthoras.visualprospecting.Tags; -import bartworks.system.material.Werkstoff; -import bartworks.system.oregen.BWOreLayer; -import gregtech.api.GregTechAPI; -import gregtech.api.enums.Materials; import gregtech.api.enums.OreMixes; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -35,31 +28,6 @@ public static void init() { for (OreMixes mix : OreMixes.values()) { veinTypes.put(mix.oreMixBuilder.oreMixName, new VeinType(mix.oreMixBuilder)); } - - for (BWOreLayer vein : BWOreLayer.sList) { - final IOreMaterialProvider oreMaterialProvider; - if (containsBartworksOres(vein.bwOres)) { - oreMaterialProvider = getRepresentativeProvider( - vein.mWorldGenName, - new int[] { vein.mPrimaryMeta, vein.mSecondaryMeta, vein.mBetweenMeta, vein.mSporadicMeta }); - } else { - oreMaterialProvider = new GregTechOreMaterialProvider( - GregTechAPI.sGeneratedMaterials[(short) vein.mPrimaryMeta]); - } - veinTypes.put( - vein.mWorldGenName, - new VeinType( - vein.mWorldGenName, - oreMaterialProvider, - vein.mSize, - (short) vein.mPrimaryMeta, - (short) vein.mSecondaryMeta, - (short) vein.mBetweenMeta, - (short) vein.mSporadicMeta, - vein.mMinY, - vein.mMaxY, - vein.getDimName())); - } } public static @NotNull VeinType getVeinType(String veinTypeName) { @@ -86,27 +54,4 @@ public static void recalculateSearch(@Nullable Pattern filterPattern) { } } } - - private static boolean containsBartworksOres(byte bwOres) { - return (bwOres & 0b1111) != 0; - } - - private static IOreMaterialProvider getRepresentativeProvider(String veinName, int[] ores) { - for (int meta : ores) { - Werkstoff werkstoff = Werkstoff.werkstoffHashMap.get((short) meta); - if (werkstoff == null) continue; - String defaultName = werkstoff.getDefaultName(); - // also try lobbing a few characters off the end of the vein name because bart - if (StringUtils.endsWithIgnoreCase(veinName, defaultName) - || StringUtils.containsIgnoreCase(veinName, defaultName.substring(0, defaultName.length() - 2))) { - return new BartworksOreMaterialProvider(werkstoff); - } - } - - Werkstoff primaryMaterial = Arrays.stream(ores).mapToObj(meta -> Werkstoff.werkstoffHashMap.get((short) meta)) - .filter(Objects::nonNull).findFirst().orElse(null); - - return primaryMaterial == null ? new GregTechOreMaterialProvider(Materials._NULL) - : new BartworksOreMaterialProvider(primaryMaterial); - } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index f9e4f0bb..d29b4c03 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -14,7 +14,11 @@ import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; +import gregtech.api.enums.OrePrefixes; +import gregtech.api.enums.TextureSet; import gregtech.api.interfaces.IIconContainer; +import gregtech.api.interfaces.IOreMaterial; +import gregtech.api.util.LightingHelper; public class OreVeinLocation implements IWaypointAndLocationProvider { @@ -113,14 +117,16 @@ public boolean drawSearchHighlight() { } public int getColor() { - return oreVeinPosition.veinType.oreMaterialProvider.getColor(); + return LightingHelper.getColor(getRepresentativeOre().getRGBA()); } - public IIconContainer getIconsFromPrimaryOre() { - return oreVeinPosition.veinType.oreMaterialProvider.getIconContainer(); + public IIconContainer getIconFromRepresentativeOre() { + TextureSet textureSet = getRepresentativeOre().getTextureSet(); + + return textureSet.mTextures[OrePrefixes.ore.mTextureIndex]; } - public short getPrimaryOreMeta() { - return oreVeinPosition.veinType.primaryOreMeta; + public IOreMaterial getRepresentativeOre() { + return oreVeinPosition.veinType.representativeOre; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java index 681aaf94..a9c1b48c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java @@ -16,8 +16,10 @@ import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; import codechicken.nei.api.ShortcutInputHandler; -import gregtech.api.GregTechAPI; import gregtech.api.interfaces.IIconContainer; +import gregtech.api.interfaces.IOreMaterial; +import gregtech.common.ores.OreInfo; +import gregtech.common.ores.OreManager; public class OreVeinRenderStep extends UniversalInteractableStep { @@ -57,7 +59,7 @@ public void draw(double topX, double topY, float drawScale, double zoom) { final IIcon blockIcon = Blocks.stone.getIcon(0, 0); DrawUtils.drawQuad(blockIcon, topX, topY, width, height, 0xFFFFFF, 255); - final IIconContainer oreIconContainer = location.getIconsFromPrimaryOre(); + final IIconContainer oreIconContainer = location.getIconFromRepresentativeOre(); final IIcon oreIcon = oreIconContainer.getIcon(); DrawUtils.drawQuad(oreIcon, topX, topY, width, height, location.getColor(), 255); final IIcon oreIconOverlay = oreIconContainer.getOverlayIcon(); @@ -108,7 +110,14 @@ public boolean onKeyPressed(int keyCode) { return true; } - final var itemStack = new ItemStack(GregTechAPI.sBlockOres1, 1, location.getPrimaryOreMeta()); + final ItemStack itemStack; + + try (OreInfo info = OreInfo.getNewInfo()) { + info.material = location.getRepresentativeOre(); + + itemStack = OreManager.getStack(info, 1); + } + if (ShortcutInputHandler.handleKeyEvent(itemStack)) { playClickSound(); return true; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java index 97180215..6eb5e645 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java @@ -14,7 +14,6 @@ import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent; -import gregtech.api.GregTechAPI; public class VoxelMapEventHandler { @@ -25,7 +24,7 @@ public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { } OreVeinPosition pos = event.getPosition(); - short[] color = GregTechAPI.sGeneratedMaterials[pos.veinType.primaryOreMeta].getRGBA(); + short[] color = pos.veinType.primaryOre.getRGBA(); TreeSet dim = new TreeSet<>(); dim.add(pos.dimensionId); VoxelMapWaypointManager.addVoxelMapWaypoint( diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java index f21a10d1..38ea1596 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java @@ -10,17 +10,9 @@ public enum Mixins implements IMixins { // spotless:off - // Bartworks mixins - WorldGenContainerMixin("bartworks.WorldGenContainerMixin", BARTWORKS), - - // Galactic greg mixins - GT_Worldgenerator_SpaceMixin("galacticgreg.GT_Worldgenerator_SpaceMixin", GALACTICGREG), - // Gregtech mixins - GT_Block_Ores_AbstractMixin("gregtech.GT_Block_Ores_AbstractMixin", GT5U), - GT_MetaTileEntity_AdvSeismicProspectorMixin("gregtech.GT_MetaTileEntity_AdvSeismicProspectorMixin", GT5U), - GT_MetaTileEntity_ScannerMixin("gregtech.GT_MetaTileEntity_ScannerMixin", GT5U), - GT_WorldGenContainerMixin("gregtech.WorldGenContainerMixin", GT5U), + MTEAdvSeismicProspectorMixin("gregtech.MTEAdvSeismicProspectorMixin", GT5U), + MTEScannerMixin("gregtech.MTEScannerMixin", GT5U), // Vanilla Mixins MINECRAFT(new MixinBuilder() diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java deleted file mode 100644 index 3825f097..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/bartworks/WorldGenContainerMixin.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.bartworks; - -import java.util.Random; - -import net.minecraft.world.World; -import net.minecraft.world.chunk.IChunkProvider; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.database.ServerCache; - -import bartworks.system.oregen.BWOreLayer; -import bartworks.system.oregen.BWWordGenerator; - -@Mixin(BWWordGenerator.WorldGenContainer.class) -public class WorldGenContainerMixin { - - @Redirect( - method = "run", - at = @At( - value = "INVOKE", - target = "Lbartworks/system/oregen/BWOreLayer;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), - remap = false, - require = 1) - private boolean visualprospecting$onOreVeinGenerationAttempt(BWOreLayer worldGen, World world, Random random, - String biome, int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, - IChunkProvider chunkProvider) { - final boolean oreVeinPlaced = worldGen.executeWorldgen( - world, - random, - biome, - Integer.MIN_VALUE, - blockX, - blockZ, - chunkGenerator, - chunkProvider); - if (oreVeinPlaced) { - ServerCache.instance.notifyOreVeinGeneration( - world.provider.dimensionId, - Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockX)), - Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockZ)), - worldGen.mWorldGenName); - } - return oreVeinPlaced; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java deleted file mode 100644 index cde0c420..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/galacticgreg/GT_Worldgenerator_SpaceMixin.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.galacticgreg; - -import java.util.Random; - -import net.minecraft.world.World; -import net.minecraft.world.chunk.IChunkProvider; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.database.ServerCache; - -import galacticgreg.WorldGeneratorSpace; -import gregtech.api.world.GTWorldgen; - -@Mixin(WorldGeneratorSpace.class) -public class GT_Worldgenerator_SpaceMixin { - - @Redirect( - method = "Generate_OreVeins", - at = @At( - value = "INVOKE", - target = "Lgregtech/api/world/GTWorldgen;executeWorldgen(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)Z"), - remap = false, - require = 1) - private boolean visualprospecting$onOreVeinGenerated(GTWorldgen worldGen, World world, Random random, String biome, - int dimensionType, int blockX, int blockZ, IChunkProvider chunkGenerator, IChunkProvider chunkProvider) { - final boolean oreVeinPlaced = worldGen.executeWorldgen( - world, - random, - biome, - Integer.MIN_VALUE, - blockX, - blockZ, - chunkGenerator, - chunkProvider); - if (oreVeinPlaced) { - ServerCache.instance.notifyOreVeinGeneration( - world.provider.dimensionId, - Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockX)), - Utils.mapToCenterOreChunkCoord(Utils.coordBlockToChunk(blockZ)), - worldGen.mWorldGenName); - } - return oreVeinPlaced; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java deleted file mode 100644 index 801ad7e8..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_Block_Ores_AbstractMixin.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.gregtech; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.world.World; - -import org.spongepowered.asm.mixin.Mixin; - -import com.sinthoras.visualprospecting.database.ClientCache; - -import gregtech.api.items.GTGenericBlock; -import gregtech.common.blocks.BlockOresAbstract; - -@Mixin(value = BlockOresAbstract.class, remap = false) -public class GT_Block_Ores_AbstractMixin extends GTGenericBlock { - - protected GT_Block_Ores_AbstractMixin() { - super(null, null, null); - } - - @Override - public boolean onBlockActivated(World world, int blockX, int blockY, int blockZ, EntityPlayer player, int side, - float offsetX, float offsetY, float offsetZ) { - ClientCache.instance.onOreInteracted(world, blockX, blockY, blockZ, player); - return super.onBlockActivated(world, blockX, blockY, blockZ, player, side, offsetX, offsetY, offsetZ); - } - - @Override - public void onBlockClicked(World world, int blockX, int blockY, int blockZ, EntityPlayer player) { - ClientCache.instance.onOreInteracted(world, blockX, blockY, blockZ, player); - super.onBlockClicked(world, blockX, blockY, blockZ, player); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEAdvSeismicProspectorMixin.java similarity index 76% rename from src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEAdvSeismicProspectorMixin.java index f54eaeca..2370c0b3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_AdvSeismicProspectorMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEAdvSeismicProspectorMixin.java @@ -3,6 +3,7 @@ import static gregtech.api.util.GTUtility.ItemNBT.getNBT; import static gregtech.api.util.GTUtility.ItemNBT.setNBT; +import java.text.MessageFormat; import java.util.List; import net.minecraft.entity.player.EntityPlayer; @@ -30,7 +31,7 @@ import ic2.core.Ic2Items; @Mixin(value = MTEAdvSeismicProspector.class, remap = false) -public abstract class GT_MetaTileEntity_AdvSeismicProspectorMixin extends MTEBasicMachine { +public abstract class MTEAdvSeismicProspectorMixin extends MTEBasicMachine { @Shadow(remap = false) boolean ready = false; @@ -38,7 +39,7 @@ public abstract class GT_MetaTileEntity_AdvSeismicProspectorMixin extends MTEBas @Shadow(remap = false) int radius; - public GT_MetaTileEntity_AdvSeismicProspectorMixin() { + public MTEAdvSeismicProspectorMixin() { super(0, "", "", 0, 0, "", 0, 0); } @@ -48,8 +49,8 @@ public GT_MetaTileEntity_AdvSeismicProspectorMixin() { */ @Overwrite(remap = false) @Override - public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) { - if (aBaseMetaTileEntity.isServerSide()) { + public boolean onRightclick(IGregTechTileEntity igte, EntityPlayer aPlayer) { + if (igte.isServerSide()) { ItemStack aStack = aPlayer.getCurrentEquippedItem(); if (!ready && (GTUtility.consumeItems(aPlayer, aStack, Item.getItemFromBlock(Blocks.tnt), 16) @@ -70,20 +71,19 @@ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlaye compound.setString(Tags.BOOK_TITLE, "Raw Prospection Data"); compound.setBoolean(Tags.VISUALPROSPECTING_FLAG, true); compound.setByte(Tags.PROSPECTION_TIER, mTier); - compound.setInteger( - Tags.PROSPECTION_DIMENSION_ID, - getBaseMetaTileEntity().getWorld().provider.dimensionId); - compound.setInteger(Tags.PROSPECTION_BLOCK_X, getBaseMetaTileEntity().getXCoord()); - compound.setInteger(Tags.PROSPECTION_BLOCK_Y, getBaseMetaTileEntity().getYCoord()); - compound.setInteger(Tags.PROSPECTION_BLOCK_Z, getBaseMetaTileEntity().getZCoord()); + compound.setInteger(Tags.PROSPECTION_DIMENSION_ID, igte.getWorld().provider.dimensionId); + compound.setInteger(Tags.PROSPECTION_BLOCK_X, igte.getXCoord()); + compound.setInteger(Tags.PROSPECTION_BLOCK_Y, igte.getYCoord()); + compound.setInteger(Tags.PROSPECTION_BLOCK_Z, igte.getZCoord()); compound.setInteger(Tags.PROSPECTION_ORE_RADIUS, radius); final List undergroundFluidPositions = ServerCache.instance .prospectUndergroundFluidBlockRadius( aPlayer.worldObj, - getBaseMetaTileEntity().getXCoord(), - getBaseMetaTileEntity().getZCoord(), + igte.getXCoord(), + igte.getZCoord(), VP.undergroundFluidChunkProspectingBlockRadius); + compound.setInteger( Tags.PROSPECTION_NUMBER_OF_UNDERGROUND_FLUID, undergroundFluidPositions.size()); @@ -91,25 +91,24 @@ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlaye String[] fluidStrings = new String[9]; final int minUndergroundFluidX = Utils.mapToCornerUndergroundFluidChunkCoord( Utils.coordBlockToChunk( - getBaseMetaTileEntity().getXCoord() - - VP.undergroundFluidChunkProspectingBlockRadius)); + igte.getXCoord() - VP.undergroundFluidChunkProspectingBlockRadius)); final int minUndergroundFluidZ = Utils.mapToCornerUndergroundFluidChunkCoord( Utils.coordBlockToChunk( - getBaseMetaTileEntity().getZCoord() - - VP.undergroundFluidChunkProspectingBlockRadius)); + igte.getZCoord() - VP.undergroundFluidChunkProspectingBlockRadius)); for (UndergroundFluidPosition undergroundFluidPosition : undergroundFluidPositions) { final int offsetUndergroundFluidX = (Utils.mapToCornerUndergroundFluidChunkCoord( undergroundFluidPosition.chunkX) - minUndergroundFluidX) >> 3; final int offsetUndergroundFluidZ = (Utils.mapToCornerUndergroundFluidChunkCoord( undergroundFluidPosition.chunkZ) - minUndergroundFluidZ) >> 3; final int undergroundFluidBookId = offsetUndergroundFluidX + offsetUndergroundFluidZ * 3; - fluidStrings[undergroundFluidBookId] = undergroundFluidBookId + ": " - + undergroundFluidPosition.getMinProduction() - + "-" - + undergroundFluidPosition.getMaxProduction() - + " " - + undergroundFluidPosition.fluid.getLocalizedName(); + fluidStrings[undergroundFluidBookId] = MessageFormat.format( + "{0}: {1}-{2} {3}", + undergroundFluidBookId, + undergroundFluidPosition.getMinProduction(), + undergroundFluidPosition.getMaxProduction(), + undergroundFluidPosition.fluid.getLocalizedName()); } + compound.setString(Tags.PROSPECTION_FLUIDS, String.join("|", fluidStrings)); setNBT(aStack, compound); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEScannerMixin.java similarity index 98% rename from src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java rename to src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEScannerMixin.java index bb10f0a0..30fcb4e8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/GT_MetaTileEntity_ScannerMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEScannerMixin.java @@ -23,9 +23,9 @@ import gregtech.common.tileentities.machines.basic.MTEScanner; @Mixin(value = MTEScanner.class, remap = false) -public abstract class GT_MetaTileEntity_ScannerMixin extends MTEBasicMachine { +public abstract class MTEScannerMixin extends MTEBasicMachine { - public GT_MetaTileEntity_ScannerMixin() { + public MTEScannerMixin() { super(0, "", "", 0, 0, "", 0, 0); } diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java deleted file mode 100644 index 4898492d..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/WorldGenContainerMixin.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.gregtech; - -import java.util.Random; - -import net.minecraft.world.World; -import net.minecraft.world.chunk.IChunkProvider; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.database.ServerCache; - -import gregtech.common.GTWorldgenerator; -import gregtech.common.WorldgenGTOreLayer; - -@Mixin(GTWorldgenerator.WorldGenContainer.class) -public class WorldGenContainerMixin { - - // Redirect both calls to ensure that Bartworks ore veins are captured as well - @Redirect( - method = "worldGenFindVein", - at = @At( - value = "INVOKE", - target = "Lgregtech/common/WorldgenGTOreLayer;executeWorldgenChunkified(Lnet/minecraft/world/World;Ljava/util/Random;Ljava/lang/String;IIIIILnet/minecraft/world/chunk/IChunkProvider;Lnet/minecraft/world/chunk/IChunkProvider;)I"), - remap = false, - require = 2) - protected int visualprospecting$onOreVeinPlaced(WorldgenGTOreLayer instance, World aWorld, Random aRandom, - String aBiome, int aDimensionType, int aChunkX, int aChunkZ, int aSeedX, int aSeedZ, - IChunkProvider aChunkGenerator, IChunkProvider aChunkProvider) { - final int result = instance.executeWorldgenChunkified( - aWorld, - aRandom, - aBiome, - aDimensionType, - aChunkX, - aChunkZ, - aSeedX, - aSeedZ, - aChunkGenerator, - aChunkProvider); - if (result == WorldgenGTOreLayer.ORE_PLACED && !instance.mWorldGenName.equals("NoOresInVein")) { - ServerCache.instance.notifyOreVeinGeneration( - aWorld.provider.dimensionId, - Utils.coordBlockToChunk(aSeedX), - Utils.coordBlockToChunk(aSeedZ), - instance.mWorldGenName); - } - return result; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java index dad0f690..d8dd3f71 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java @@ -1,14 +1,9 @@ package com.sinthoras.visualprospecting.network; -import static com.sinthoras.visualprospecting.Utils.isSmallOreId; -import static com.sinthoras.visualprospecting.Utils.oreIdToMaterialId; - import java.util.HashMap; import java.util.Map; import java.util.UUID; -import net.minecraft.block.Block; -import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import com.sinthoras.visualprospecting.Config; @@ -16,11 +11,13 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; +import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; -import gregtech.common.blocks.BlockOresAbstract; -import gregtech.common.blocks.TileEntityOres; +import gregtech.api.interfaces.IOreMaterial; +import gregtech.common.ores.OreInfo; +import gregtech.common.ores.OreManager; import io.netty.buffer.ByteBuf; public class ProspectingRequest implements IMessage { @@ -31,16 +28,16 @@ public class ProspectingRequest implements IMessage { private int blockX; private int blockY; private int blockZ; - private short foundOreMetaData; + private IOreMaterial foundOre; public ProspectingRequest() {} - public ProspectingRequest(int dimensionId, int blockX, int blockY, int blockZ, short foundOreMetaData) { + public ProspectingRequest(int dimensionId, int blockX, int blockY, int blockZ, IOreMaterial foundOre) { this.dimensionId = dimensionId; this.blockX = blockX; this.blockY = blockY; this.blockZ = blockZ; - this.foundOreMetaData = foundOreMetaData; + this.foundOre = foundOre; } public static boolean canSendRequest() { @@ -58,7 +55,7 @@ public void fromBytes(ByteBuf buf) { blockX = buf.readInt(); blockY = buf.readInt(); blockZ = buf.readInt(); - foundOreMetaData = buf.readShort(); + foundOre = IOreMaterial.findMaterial(ByteBufUtils.readUTF8String(buf)); } @Override @@ -67,7 +64,7 @@ public void toBytes(ByteBuf buf) { buf.writeInt(blockX); buf.writeInt(blockY); buf.writeInt(blockZ); - buf.writeShort(foundOreMetaData); + ByteBufUtils.writeUTF8String(buf, foundOre.getInternalName()); } public static class Handler implements IMessageHandler { @@ -86,53 +83,57 @@ public IMessage onMessage(ProspectingRequest message, MessageContext ctx) { final int chunkX = Utils.coordBlockToChunk(message.blockX); final int chunkZ = Utils.coordBlockToChunk(message.blockZ); final boolean isChunkLoaded = world.getChunkProvider().chunkExists(chunkX, chunkZ); - if (ctx.getServerHandler().playerEntity.dimension == message.dimensionId && distanceSquared <= 1024 // max - // 32 - // blocks - // distance - && timestamp - lastRequest >= Config.minDelayBetweenVeinRequests - && isChunkLoaded) { - final Block block = world.getBlock(message.blockX, message.blockY, message.blockZ); - if (block instanceof BlockOresAbstract) { - final TileEntity tileEntity = world.getTileEntity(message.blockX, message.blockY, message.blockZ); - if (tileEntity instanceof TileEntityOres tileOre) { - final short metaData = tileOre.mMetaData; - if (!isSmallOreId(metaData) && oreIdToMaterialId(metaData) == message.foundOreMetaData) { - lastRequestPerPlayer.put(uuid, timestamp); - - // Prioritise center vein - final OreVeinPosition centerOreVeinPosition = ServerCache.instance - .getOreVein(message.dimensionId, chunkX, chunkZ); - if (centerOreVeinPosition.veinType.containsOre(message.foundOreMetaData)) { - return new ProspectingNotification(centerOreVeinPosition); - } - // Check if neighboring veins could fit - final int centerChunkX = Utils.mapToCenterOreChunkCoord(chunkX); - final int centerChunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); - for (int offsetChunkX = -3; offsetChunkX <= 3; offsetChunkX += 3) { - for (int offsetChunkZ = -3; offsetChunkZ <= 3; offsetChunkZ += 3) { - if (offsetChunkX != 0 || offsetChunkZ != 0) { - final int neighborChunkX = centerChunkX + offsetChunkX; - final int neighborChunkZ = centerChunkZ + offsetChunkZ; - final int distanceBlocks = Math.max( - Math.abs(neighborChunkX - chunkX), - Math.abs(neighborChunkZ - chunkZ)); - final OreVeinPosition neighborOreVeinPosition = ServerCache.instance - .getOreVein(message.dimensionId, neighborChunkX, neighborChunkZ); - final int maxDistance = ((neighborOreVeinPosition.veinType.blockSize + 16) >> 4) - + 1; // Equals to: ceil(blockSize / 16.0) + 1 - if (neighborOreVeinPosition.veinType.containsOre(message.foundOreMetaData) - && distanceBlocks <= maxDistance) { - return new ProspectingNotification(neighborOreVeinPosition); - } - } - } + if (ctx.getServerHandler().playerEntity.dimension != message.dimensionId) return null; + // max 32 blocks distance + if (distanceSquared > 32 * 32) return null; + + if (timestamp - lastRequest < Config.minDelayBetweenVeinRequests) return null; + if (!isChunkLoaded) return null; + + try (OreInfo info = OreManager + .getOreInfo(world, message.blockX, message.blockY, message.blockZ);) { + if (info == null || info.isSmall || info.material != message.foundOre) return null; + + lastRequestPerPlayer.put(uuid, timestamp); + + // Prioritise center vein + final OreVeinPosition centerOreVeinPosition = ServerCache.instance + .getOreVein(message.dimensionId, chunkX, chunkZ); + + if (centerOreVeinPosition.veinType.containsOre(message.foundOre)) { + return new ProspectingNotification(centerOreVeinPosition); + } + + // Check if neighboring veins could fit + final int centerChunkX = Utils.mapToCenterOreChunkCoord(chunkX); + final int centerChunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); + + for (int offsetChunkX = -3; offsetChunkX <= 3; offsetChunkX += 3) { + for (int offsetChunkZ = -3; offsetChunkZ <= 3; offsetChunkZ += 3) { + if (offsetChunkX != 0 || offsetChunkZ != 0) { + + final int neighborChunkX = centerChunkX + offsetChunkX; + final int neighborChunkZ = centerChunkZ + offsetChunkZ; + + final int distanceBlocks = Math + .max(Math.abs(neighborChunkX - chunkX), Math.abs(neighborChunkZ - chunkZ)); + + final OreVeinPosition neighborOreVeinPosition = ServerCache.instance + .getOreVein(message.dimensionId, neighborChunkX, neighborChunkZ); + + // Equals to: ceil(blockSize / 16.0) + 1 + final int maxDistance = ((neighborOreVeinPosition.veinType.blockSize + 16) >> 4) + 1; + + if (neighborOreVeinPosition.veinType.containsOre(message.foundOre) + && distanceBlocks <= maxDistance) { + return new ProspectingNotification(neighborOreVeinPosition); } } } } } + return null; } } From 85093222c8a538a62adf04a29c0ed19fa6261a09 Mon Sep 17 00:00:00 2001 From: Dream Master Date: Wed, 15 Oct 2025 11:22:58 +0200 Subject: [PATCH 093/132] update --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 0076d14a..d3d44840 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') api('com.github.GTNewHorizons:GTNHLib:0.7.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.31:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.44:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } From d2b834ecabe9fc61d348a6187371dc3ec39d695d Mon Sep 17 00:00:00 2001 From: Wilhelm Schuster Date: Wed, 15 Oct 2025 12:05:40 +0200 Subject: [PATCH 094/132] Fix CME when filling in Prospector's Log in singleplayer (#74) --- .../visualprospecting/hooks/HooksClient.java | 9 +++++++++ .../sinthoras/visualprospecting/hooks/HooksFML.java | 12 ++++++++++-- .../visualprospecting/hooks/HooksShared.java | 7 +++++++ .../visualprospecting/item/ProspectorsLog.java | 4 ++-- .../visualprospecting/task/TaskManager.java | 8 +++++++- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java index dc24e1b9..ed719efb 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java @@ -10,6 +10,7 @@ import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.voxelmap.VoxelMapEventHandler; +import com.sinthoras.visualprospecting.task.TaskManager; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; @@ -30,6 +31,8 @@ public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { if (Utils.isNavigatorInstalled()) { registerMapLayers(); } + + initializeTaskManager(); } @Override @@ -71,6 +74,12 @@ public void fmlLifeCycleEvent(FMLServerStoppedEvent event) { super.fmlLifeCycleEvent(event); } + @Override + protected void initializeTaskManager() { + TaskManager.SERVER_INSTANCE = new TaskManager(); + TaskManager.CLIENT_INSTANCE = new TaskManager(); + } + public void registerMapLayers() { NavigatorApi.registerLayerManager(OreVeinLayerManager.instance); diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java index a44edda9..0e6bf55e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksFML.java @@ -14,6 +14,8 @@ import cpw.mods.fml.common.gameevent.PlayerEvent; import cpw.mods.fml.common.gameevent.TickEvent; import cpw.mods.fml.common.network.FMLNetworkEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; public class HooksFML { @@ -28,8 +30,14 @@ public void onEvent(FMLNetworkEvent.ClientDisconnectionFromServerEvent event) { } @SubscribeEvent - public void onEvent(TickEvent event) { - TaskManager.instance.onTick(); + public void onServerTick(TickEvent.ServerTickEvent event) { + TaskManager.SERVER_INSTANCE.onTick(); + } + + @SubscribeEvent + @SideOnly(Side.CLIENT) + public void onClientTick(TickEvent.ClientTickEvent event) { + TaskManager.CLIENT_INSTANCE.onTick(); } @SubscribeEvent(priority = EventPriority.LOW) diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index 86638910..0b551cc2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -22,6 +22,7 @@ import com.sinthoras.visualprospecting.network.ProspectingRequest; import com.sinthoras.visualprospecting.network.ProspectionSharing; import com.sinthoras.visualprospecting.network.WorldIdNotification; +import com.sinthoras.visualprospecting.task.TaskManager; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; @@ -73,6 +74,8 @@ public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { ProspectorsLog.instance = new ProspectorsLog(); GameRegistry.registerItem(ProspectorsLog.instance, ProspectorsLog.instance.getUnlocalizedName()); + + initializeTaskManager(); } // load "Do your mod setup. Build whatever data structures you care about. Register recipes." @@ -129,4 +132,8 @@ public void fmlLifeCycleEvent(FMLServerStoppingEvent event) { } public void fmlLifeCycleEvent(FMLServerStoppedEvent event) {} + + protected void initializeTaskManager() { + TaskManager.SERVER_INSTANCE = new TaskManager(); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java index d3bdf018..77a312c2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java +++ b/src/main/java/com/sinthoras/visualprospecting/item/ProspectorsLog.java @@ -41,7 +41,7 @@ public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer play compound.setString(Tags.PROSPECTORSLOG_AUTHOR_ID, player.getPersistentID().toString()); item.setTagCompound(compound); if (world.isRemote) { - TaskManager.instance.addTask(new SnapshotUploadTask()); + TaskManager.CLIENT_INSTANCE.addTask(new SnapshotUploadTask()); } else { final int random = VP.randomGeneration.nextInt(1000); if (random < 5) { @@ -78,7 +78,7 @@ public ItemStack onItemRightClick(ItemStack item, World world, EntityPlayer play notification.getChatStyle().setItalic(true); notification.getChatStyle().setColor(EnumChatFormatting.GRAY); player.addChatMessage(notification); - TaskManager.instance.addTask(new SnapshotDownloadTask(authorUuid, (EntityPlayerMP) player)); + TaskManager.SERVER_INSTANCE.addTask(new SnapshotDownloadTask(authorUuid, (EntityPlayerMP) player)); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/task/TaskManager.java b/src/main/java/com/sinthoras/visualprospecting/task/TaskManager.java index 7fda2a27..4224e757 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/TaskManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/TaskManager.java @@ -3,9 +3,15 @@ import java.util.ArrayList; import java.util.List; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + public class TaskManager { - public static final TaskManager instance = new TaskManager(); + // Both instances are initialized in the sided proxy + @SideOnly(Side.CLIENT) + public static TaskManager CLIENT_INSTANCE; + public static TaskManager SERVER_INSTANCE; private final List tasks = new ArrayList<>(); From 2176b5d425a611c4543cc7cc462f161f28118afe Mon Sep 17 00:00:00 2001 From: RecursivePineapple Date: Fri, 17 Oct 2025 16:12:53 -0400 Subject: [PATCH 095/132] Prospect when mined (#75) --- .../database/ServerCache.java | 33 ++++++++ .../network/ProspectingRequest.java | 76 +++++++++++-------- 2 files changed, 77 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java index 7ba9b415..3ff3ce78 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java @@ -4,21 +4,30 @@ import java.util.ArrayList; import java.util.List; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; +import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; +import com.sinthoras.visualprospecting.network.ProspectingNotification; +import com.sinthoras.visualprospecting.network.ProspectingRequest; import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import gregtech.api.events.OreInteractEvent; import gregtech.api.events.VeinGenerateEvent; +import gregtech.api.interfaces.IOreMaterial; import gregtech.common.UndergroundOil; import gregtech.common.WorldgenGTOreLayer; +import gregtech.common.ores.OreInfo; +import gregtech.common.ores.OreManager; public class ServerCache extends WorldCache { @@ -55,6 +64,30 @@ public void notifyOreVeinGeneration(int dimensionId, int chunkX, int chunkZ, fin notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, VeinTypeCaching.getVeinType(veinName)); } + @SubscribeEvent + public void onOreClicked(OreInteractEvent event) { + World world = event.world; + int x = event.x; + int y = event.y; + int z = event.z; + EntityPlayer player = event.player; + + if (!world.isRemote && Config.enableProspecting) { + IOreMaterial material; + + try (OreInfo info = OreManager.getOreInfo(world, x, y, z)) { + material = info != null && info.isNatural ? info.material : null; + } + + ProspectingNotification response = ProspectingRequest + .prospect(new ProspectingRequest(world.provider.dimensionId, x, y, z, material), event.world); + + if (response != null) { + VP.network.sendTo(response, (EntityPlayerMP) player); + } + } + } + public List prospectOreChunks(int dimensionId, int minChunkX, int minChunkZ, int maxChunkX, int maxChunkZ) { minChunkX = Utils.mapToCenterOreChunkCoord(minChunkX); diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java index d8dd3f71..d43e43da 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java @@ -6,6 +6,8 @@ import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.OreVeinPosition; @@ -75,8 +77,14 @@ public static class Handler implements IMessageHandler 32 * 32) return null; - if (timestamp - lastRequest < Config.minDelayBetweenVeinRequests) return null; if (!isChunkLoaded) return null; - try (OreInfo info = OreManager - .getOreInfo(world, message.blockX, message.blockY, message.blockZ);) { - if (info == null || info.isSmall || info.material != message.foundOre) return null; + return prospect(message, world); + } + } - lastRequestPerPlayer.put(uuid, timestamp); + public static @Nullable ProspectingNotification prospect(ProspectingRequest message, World world) { + final int chunkX = Utils.coordBlockToChunk(message.blockX); + final int chunkZ = Utils.coordBlockToChunk(message.blockZ); - // Prioritise center vein - final OreVeinPosition centerOreVeinPosition = ServerCache.instance - .getOreVein(message.dimensionId, chunkX, chunkZ); + try (OreInfo info = OreManager + .getOreInfo(world, message.blockX, message.blockY, message.blockZ)) { + if (info == null || info.isSmall || info.material != message.foundOre) return null; - if (centerOreVeinPosition.veinType.containsOre(message.foundOre)) { - return new ProspectingNotification(centerOreVeinPosition); - } + // Prioritise center vein + final OreVeinPosition centerOreVeinPosition = ServerCache.instance + .getOreVein(message.dimensionId, chunkX, chunkZ); - // Check if neighboring veins could fit - final int centerChunkX = Utils.mapToCenterOreChunkCoord(chunkX); - final int centerChunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); + if (centerOreVeinPosition.veinType.containsOre(message.foundOre)) { + return new ProspectingNotification(centerOreVeinPosition); + } + + // Check if neighboring veins could fit + final int centerChunkX = Utils.mapToCenterOreChunkCoord(chunkX); + final int centerChunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); - for (int offsetChunkX = -3; offsetChunkX <= 3; offsetChunkX += 3) { - for (int offsetChunkZ = -3; offsetChunkZ <= 3; offsetChunkZ += 3) { - if (offsetChunkX != 0 || offsetChunkZ != 0) { + for (int offsetChunkX = -3; offsetChunkX <= 3; offsetChunkX += 3) { + for (int offsetChunkZ = -3; offsetChunkZ <= 3; offsetChunkZ += 3) { + if (offsetChunkX != 0 || offsetChunkZ != 0) { - final int neighborChunkX = centerChunkX + offsetChunkX; - final int neighborChunkZ = centerChunkZ + offsetChunkZ; + final int neighborChunkX = centerChunkX + offsetChunkX; + final int neighborChunkZ = centerChunkZ + offsetChunkZ; - final int distanceBlocks = Math - .max(Math.abs(neighborChunkX - chunkX), Math.abs(neighborChunkZ - chunkZ)); + final int distanceBlocks = Math + .max(Math.abs(neighborChunkX - chunkX), Math.abs(neighborChunkZ - chunkZ)); - final OreVeinPosition neighborOreVeinPosition = ServerCache.instance - .getOreVein(message.dimensionId, neighborChunkX, neighborChunkZ); + final OreVeinPosition neighborOreVeinPosition = ServerCache.instance + .getOreVein(message.dimensionId, neighborChunkX, neighborChunkZ); - // Equals to: ceil(blockSize / 16.0) + 1 - final int maxDistance = ((neighborOreVeinPosition.veinType.blockSize + 16) >> 4) + 1; + // Equals to: ceil(blockSize / 16.0) + 1 + final int maxDistance = ((neighborOreVeinPosition.veinType.blockSize + 16) >> 4) + 1; - if (neighborOreVeinPosition.veinType.containsOre(message.foundOre) - && distanceBlocks <= maxDistance) { - return new ProspectingNotification(neighborOreVeinPosition); - } + if (neighborOreVeinPosition.veinType.containsOre(message.foundOre) + && distanceBlocks <= maxDistance) { + return new ProspectingNotification(neighborOreVeinPosition); } } } } - - return null; } + + return null; } } From 4afb81c14450bd53812bbe2e22ccfec3ca0770d5 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Fri, 17 Oct 2025 22:17:56 +0200 Subject: [PATCH 096/132] update --- dependencies.gradle | 2 +- settings.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index d3d44840..83b292b8 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') api('com.github.GTNewHorizons:GTNHLib:0.7.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.44:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.56:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/settings.gradle b/settings.gradle index 9f80246c..9105fb71 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.43' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.44' } From 04895af23df5b5c3d4c432c1bd9602cc7a6fe9c2 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Fri, 17 Oct 2025 22:18:17 +0200 Subject: [PATCH 097/132] update --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 83b292b8..ec6f6c66 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') api('com.github.GTNewHorizons:GTNHLib:0.7.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.56:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.57:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } From afcd230f8803d81931a1a155e74b17fe476a074b Mon Sep 17 00:00:00 2001 From: chochem <40274384+chochem@users.noreply.github.com> Date: Sat, 25 Oct 2025 01:58:36 +0100 Subject: [PATCH 098/132] Fix GT oreprefix call (#76) --- dependencies.gradle | 4 ++-- .../integration/model/locations/OreVeinLocation.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index ec6f6c66..3bb67009 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') - api('com.github.GTNewHorizons:GTNHLib:0.7.0:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.57:dev') + api('com.github.GTNewHorizons:GTNHLib:0.7.1:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.69:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index d29b4c03..8d1b1520 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -123,7 +123,7 @@ public int getColor() { public IIconContainer getIconFromRepresentativeOre() { TextureSet textureSet = getRepresentativeOre().getTextureSet(); - return textureSet.mTextures[OrePrefixes.ore.mTextureIndex]; + return textureSet.mTextures[OrePrefixes.ore.getTextureIndex()]; } public IOreMaterial getRepresentativeOre() { From 10955fe33ad1b053bd7e8d570365f5ac9a87a3cc Mon Sep 17 00:00:00 2001 From: Wilhelm Schuster Date: Mon, 27 Oct 2025 14:38:37 +0100 Subject: [PATCH 099/132] Fix Prospector's Log packet size overflow (#73) Co-authored-by: Martin Robertz --- .../database/OreVeinPosition.java | 22 ++++++++++++++---- .../database/TransferCache.java | 4 ++-- .../network/ProspectionSharing.java | 23 +++++++++++-------- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java b/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java index 1fe1aa15..40686618 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java @@ -1,11 +1,15 @@ package com.sinthoras.visualprospecting.database; +import static cpw.mods.fml.common.network.ByteBufUtils.varIntByteCount; + +import java.nio.charset.StandardCharsets; + import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.veintypes.VeinType; public class OreVeinPosition { - public static final int MAX_BYTES = 3 * Integer.BYTES + Short.BYTES; + public static final int BYTES_WITHOUT_VEIN_NAME = 3 * Integer.BYTES + Byte.BYTES; public static final OreVeinPosition EMPTY_VEIN = new OreVeinPosition(0, 0, 0, VeinType.NO_VEIN, true); public final int dimensionId; @@ -38,6 +42,18 @@ public int getBlockZ() { return Utils.coordChunkToBlock(chunkZ) + 8; } + public int getBytes() { + int veinNameLength = veinType.name.getBytes(StandardCharsets.UTF_8).length; + + return BYTES_WITHOUT_VEIN_NAME + veinNameLength; + } + + public int getPacketBytes() { + int veinNameLength = veinType.name.getBytes(StandardCharsets.UTF_8).length; + + return BYTES_WITHOUT_VEIN_NAME + varIntByteCount(veinNameLength) + veinNameLength; + } + public boolean isDepleted() { return depleted; } @@ -51,8 +67,4 @@ public OreVeinPosition joinDepletedState(final OreVeinPosition other) { return this; } - // Leaving this here for compatability sake - public static int getMaxBytes() { - return MAX_BYTES; - } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java b/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java index c8c1fe56..db5003ce 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/TransferCache.java @@ -23,7 +23,7 @@ public void addClientProspectionData(String uuid, List oreVeins sharedUndergroundFluids.remove(uuid); timestamp.remove(uuid); - final int newEntryBytes = oreVeins.size() * OreVeinPosition.MAX_BYTES + final int newEntryBytes = oreVeins.stream().mapToInt(OreVeinPosition::getBytes).sum() + undergroundFluids.size() * UndergroundFluidPosition.BYTES; while (getUsedMemory() > (Config.maxTransferCacheSizeMB << 20) - newEntryBytes && !timestamp.isEmpty()) { @@ -50,7 +50,7 @@ public List getSharedUndergroundFluidsFrom(String uuid } private int getUsedMemory() { - return sharedOreVeins.values().stream().mapToInt(oreVeins -> oreVeins.size() * OreVeinPosition.MAX_BYTES).sum() + return sharedOreVeins.values().stream().flatMap(List::stream).mapToInt(OreVeinPosition::getBytes).sum() + sharedUndergroundFluids.values().stream() .mapToInt(undergroundFluids -> undergroundFluids.size() * UndergroundFluidPosition.BYTES).sum(); } diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java index a63b4cde..6468a7a1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java @@ -21,7 +21,7 @@ public class ProspectionSharing implements IMessage { - private static final int BYTES_OVERHEAD = 2 * Byte.BYTES + 2 * Integer.BYTES; + private static final int BYTES_OVERHEAD = Byte.BYTES + 2 * Byte.BYTES + 2 * Integer.BYTES; final List oreVeins = new ArrayList<>(); final List undergroundFluids = new ArrayList<>(); @@ -32,11 +32,16 @@ public class ProspectionSharing implements IMessage { public ProspectionSharing() {} public int putOreVeins(List oreVeins) { - final int availableBytes = VP.uploadSizePerPacketInBytes - bytesUsed; - final int maxAddedOreVeins = availableBytes / OreVeinPosition.MAX_BYTES; - final int addedOreVeins = Math.min(oreVeins.size(), maxAddedOreVeins); - this.oreVeins.addAll(oreVeins.subList(0, addedOreVeins)); - bytesUsed += addedOreVeins * OreVeinPosition.MAX_BYTES; + int addedOreVeins = 0; + for (OreVeinPosition vein : oreVeins) { + final int veinByteSize = vein.getPacketBytes(); + + if ((bytesUsed + veinByteSize) > VP.uploadSizePerPacketInBytes) break; + this.oreVeins.add(vein); + bytesUsed += veinByteSize; + addedOreVeins++; + } + return addedOreVeins; } @@ -57,8 +62,8 @@ public void setLastMessage(boolean isLastMessage) { this.isLastMessage = isLastMessage; } - public int getBytes() { - return BYTES_OVERHEAD + OreVeinPosition.MAX_BYTES * oreVeins.size() + public int getPacketBytes() { + return BYTES_OVERHEAD + oreVeins.stream().mapToInt(OreVeinPosition::getPacketBytes).sum() + UndergroundFluidPosition.BYTES * undergroundFluids.size(); } @@ -90,7 +95,7 @@ public IMessage onMessage(ProspectionSharing message, MessageContext ctx) { final EntityPlayerMP player = ctx.getServerHandler().playerEntity; // Optional todo: Integrate over time for proper checking - if (message.getBytes() > VP.uploadSizePerPacketInBytes) { + if (message.getPacketBytes() > VP.uploadSizePerPacketInBytes) { player.playerNetServerHandler.kickPlayerFromServer( "Do not spam the server! Change your VisualProcessing configuration back to the servers!"); } From bff58a88a2a843b0d4ed2c54423f4582409c4f35 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Tue, 28 Oct 2025 22:32:10 +0100 Subject: [PATCH 100/132] update --- dependencies.gradle | 4 ++-- gradle.properties | 4 +++- settings.gradle | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 3bb67009..40b9284d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') - api('com.github.GTNewHorizons:GTNHLib:0.7.1:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.69:dev') + api('com.github.GTNewHorizons:GTNHLib:0.7.3:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.79:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/gradle.properties b/gradle.properties index 5553eab2..c9634b9c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -96,7 +96,9 @@ usesMixinDebug = true # 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! +# Specify the package that contains all of your Mixins. The package must exist or +# the build will fail. If you have a package property defined in your mixins..json, +# it must match with this or the build will fail. mixinsPackage = mixins # Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! diff --git a/settings.gradle b/settings.gradle index 9105fb71..05c912eb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.44' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.47' } From 019e86c8b9f3a197fbffd71e427841653941bead Mon Sep 17 00:00:00 2001 From: Guillaume Mercier Date: Thu, 12 Feb 2026 11:34:15 -0500 Subject: [PATCH 101/132] Fix ores being unscannable in spawn chunks, and incorrect cache-rebuilding logic. (#78) --- .../sinthoras/visualprospecting/database/ClientCache.java | 2 +- .../sinthoras/visualprospecting/database/ServerCache.java | 5 +---- .../visualprospecting/database/veintypes/VeinType.java | 2 +- .../com/sinthoras/visualprospecting/hooks/HooksClient.java | 2 ++ .../com/sinthoras/visualprospecting/hooks/HooksShared.java | 1 + 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index d10ef444..2eb7b204 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -34,7 +34,7 @@ public class ClientCache extends WorldCache { public static final ClientCache instance = new ClientCache(); public ClientCache() { - MinecraftForge.EVENT_BUS.register(this); + } protected File getStorageDirectory() { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java index 3ff3ce78..86a52a6a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java @@ -7,7 +7,6 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.world.World; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; @@ -33,9 +32,7 @@ public class ServerCache extends WorldCache { public static final ServerCache instance = new ServerCache(); - private ServerCache() { - MinecraftForge.EVENT_BUS.register(this); - } + private ServerCache() {} protected File getStorageDirectory() { return Utils.getSubDirectory(Tags.SERVER_DIR); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 63a0a1c2..4bf24a5f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -67,7 +67,7 @@ public boolean containsAllFoundOres(Collection foundOres, String d int minY) { return minY >= minBlockY && (primaryOre == specific || secondaryOre == specific) && (dimName.isEmpty() || allowedDims.contains(dimName)) - && oresAsSet.containsAll(foundOres); + && foundOres.containsAll(oresAsSet); } public boolean matchesWithSpecificPrimaryOrSecondary(Collection foundOres, String dimName, diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java index ed719efb..6e9a289a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java @@ -6,6 +6,7 @@ import com.gtnewhorizons.navigator.api.NavigatorApi; import com.gtnewhorizons.navigator.api.util.Util; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.ResetClientCacheCommand; import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; @@ -39,6 +40,7 @@ public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { // load "Do your mod setup. Build whatever data structures you care about. Register recipes." public void fmlLifeCycleEvent(FMLInitializationEvent event) { super.fmlLifeCycleEvent(event); + MinecraftForge.EVENT_BUS.register(ClientCache.instance); FMLCommonHandler.instance().bus().register(new HooksKey()); } diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index 0b551cc2..b71eee48 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -81,6 +81,7 @@ public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { // load "Do your mod setup. Build whatever data structures you care about. Register recipes." public void fmlLifeCycleEvent(FMLInitializationEvent event) { MinecraftForge.EVENT_BUS.register(new HooksEventBus()); + MinecraftForge.EVENT_BUS.register(ServerCache.instance); FMLCommonHandler.instance().bus().register(new HooksFML()); } From 9db7a63647f96d509fd2b13eda2b8d72cf8b3210 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Fri, 13 Feb 2026 14:35:30 +0100 Subject: [PATCH 102/132] update gradle+bs+deps --- dependencies.gradle | 4 +-- gradle.properties | 39 +++++++++++++++++++++-- gradle/gradle-daemon-jvm.properties | 12 +++++++ gradle/wrapper/gradle-wrapper.jar | Bin 43705 -> 45633 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 7 ++-- gradlew.bat | 3 +- settings.gradle | 2 +- 8 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 gradle/gradle-daemon-jvm.properties diff --git a/dependencies.gradle b/dependencies.gradle index 40b9284d..e4a6d16e 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') - api('com.github.GTNewHorizons:GTNHLib:0.7.3:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.79:dev') + api('com.github.GTNewHorizons:GTNHLib:0.9.16:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.283:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/gradle.properties b/gradle.properties index c9634b9c..e941a401 100644 --- a/gradle.properties +++ b/gradle.properties @@ -39,9 +39,33 @@ remoteMappings = https\://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/co # `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE. developmentEnvironmentUserName = Developer -# 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 modern Java syntax support. Valid values: +# - false: No modern syntax, Java 8 only +# - jabel: Jabel syntax-only support, compiles to J8 bytecode +# - jvmDowngrader: Full modern Java via JVM Downgrader (syntax + stdlib APIs) +# - modern: Native modern Java bytecode, no downgrading +enableModernJavaSyntax = jabel + +# If set, ignores the above setting and compiles with the given toolchain. This may cause unexpected issues, +# and should *not* be used in most situations. -1 disables this. +# forceToolchainVersion = -1 + +# Target JVM version for JVM Downgrader bytecode downgrading. +# Only used when enableModernJavaSyntax = jvmDowngrader +# downgradeTargetVersion = 8 + +# Comma-separated list of Java versions for multi-release jar support (JVM Downgrader only). +# Classes will be available in META-INF/versions/N/ for each version N in this list. +# Default: "21,25" (J25+ gets native classes, J21-24 gets partial downgrade, J8-20 gets full downgrade). +# jvmDowngraderMultiReleaseVersions = 21,25 + +# Specifies how JVM Downgrader API stubs are provided. Options: +# - shade: Shade minimized stubs into the jar +# - gtnhlib: GTNHLib provides stubs at runtime (adds version constraint) +# - external: Another dependency provides stubs (no constraint, no warning) +# - (empty): Warning reminding you to configure stubs +# Note: 'shade' option requires you to verify license compliance, see: https://github.com/unimined/JvmDowngrader/blob/main/LICENSE.md +# jvmDowngraderStubsProvider = # Enables injecting missing generics into the decompiled source code for a better coding experience. # Turns most publicly visible List, Map, etc. into proper List, Map types. @@ -174,6 +198,12 @@ curseForgeRelations = # projects. New projects should not use this parameter. # customArchiveBaseName = +# Optional parameter to customize the default working directory used by the runClient* tasks. Relative to the project directory. +# runClientWorkingDirectory = run/client + +# Optional parameter to customize the default working directory used by the runServer* tasks. Relative to the project directory. +# runServerWorkingDirectory = run/server + # 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. @@ -203,3 +233,6 @@ curseForgeRelations = # This is meant to be set in $HOME/.gradle/gradle.properties. # ideaCheckSpotlessOnBuild = true +# Non-GTNH properties +org.gradle.configuration-cache = true +org.gradle.parallel = true diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties new file mode 100644 index 00000000..3590bb8a --- /dev/null +++ b/gradle/gradle-daemon-jvm.properties @@ -0,0 +1,12 @@ +#This file is generated by updateDaemonJvm +toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect +toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/93aeea858331bd6bb00ba94759830234/redirect +toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/4945f00643ec68e7c7a6b66f90124f89/redirect +toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect +toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/46949723aaa20c7b64d7ecfed7207034/redirect +toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d6690dfd71c4c91e08577437b5b2beb0/redirect +toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/4945f00643ec68e7c7a6b66f90124f89/redirect +toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/93aeea858331bd6bb00ba94759830234/redirect +toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/3cd7045fca9a72cd9bc7d14a385e594c/redirect +toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/0ef34dd9312b12d61ba1b8e66126d140/redirect +toolchainVersion=25 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 9bbc975c742b298b441bfb90dbc124400a3751b9..f8e1ee3125fe0768e9a76ee977ac089eb657005e 100644 GIT binary patch delta 37435 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 delta 35540 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%0A!3{ zp%gi03-h8;;^XKp2;(Me<1qd>50J!Lf) zy^IWBgcpzO)p{vCSGOQ4ezuZF!rXS}>{;>BxC;Nq3eP_o#H7k&Wdzxk7zxlWizryR z?#?f*RTfj$Va}*H3EtHbKPsB2O6bbR^PMieQ0O~%{SE6^pAVjkTMTCm>*Y>?GJ>Bq`4Z$WwLUtynJ z$b=f@zxvfc<4miuKFb48dgV2ra!*Wgp^3g98>hCc$TCwqX`M+4@eov7P9}b|3alIe zf)9b2Q^A(<(p~ocMmasiC;JBkA!Waf!LCHt+`RgW?w0x>D^JR_@j$H>Y=ZXk2>9X+ z>@36Tb-%l3!19phJ7^Gnq1`5i$(~?;3VUCC>~2{r`@rZq(sd5HaYP`XwdVGb4V`~IW3I==4uZ06v2J}o^>&)G4rgv zGN#CqIxS`K7u1t&I{3JwG|{}u5|)uZ=-w45%b*ocvH^rU4lK8$$!BSBqRPb1ifwC@ophfdH=X7i>@ zdrLTYv)m%texaXBCmL!HQBlFOQT}cDvRLc0`^!-m1`+yDa$9_2BGN~to7U4wt~NL3 zCDD#wCVe(Ei?#6%S@~OM<&|v<{WSxBp|GRl4m*rc1F|W|^cwwt5_#5o&ma4*N(BE` zB}oZIppwJ9I>zVa+(MO;j5IE#YW!jWEu5SPLP%vGk~%0EZK+I1EP=cZ_if1Od}Vh{ zJ^`ikdZ<6g(+GKeKPO>H*=}wKJ*oMN^+Fe-AQNmd)%V{pb{z8@`*s80AMR?vQm?uC zJ&*}1HLlX_?Cs#T+0*1IOr|o`XU;na;x_&O86LoO6m{Vht`%p@)56FqXez51FGG)< z!+i37alFZw4Zo3T99n8nM=i~H^^KjK-(|1dQKGneStX?QdFUFzp1yt;gAoP|h~1p^ zt%h2U{(!jqgarg|AsSmn*!)AW)`6~Lu?Ni*W9x}eZ^EfH(Cgh;j&BEQv%7UzUHU*E z8H7Y6qwT+v`Vz4rGMTc!1f=m@@*Flj7S|FZ^&|G{?{Eq;Pq1zY&q%V{Ad;}h{Mkjt zbUwBF^Q8k<#66d0yaVm@j4ZC0>+KRW~NIUmc=OZfg?XuTMQeSMvgOlra(r&;1-g^YQm>ym=tcFJm6gthL_zdC@&MwMm-mTtG3F=Pz8pcfM|_&yfC} zf|Oa7$G-&|1%~h}I@`teSG^nky5djv9y%%a=&EoW*>Yb2&P?~n~ zTq;yFpKr@(9gz#=s3)7K-)j%D<#ZjCW*7?@!j2cL+9}xJ>=3JdKU{Nik2NW60Mhp;uZDiZ_QdtpW>o|_trA?1NdaFBd?^B74 z^nm>l9FlS~{~FV2ru1j>T9S}1G@IRysL-l}s-3P-Mi(Pa0w(`PQrgzWA=nUctUf6X z^oxnE7sbt#J2jQpEMg`0pe-xD&dOrA887EdKY8kWbF?!Jwb=q^!^IR#4bd*sHxoE) zyE{1M%!Vj;S$!TstENmbjX^K6zk$ksm9B1^b1aT+JtVt+KZLD)U$1MKlBbMZRj&A( z8uquo7)n!9sW^#e`N(yqx)w%?@|BREQbnAjgg=Eh(gm`&=sxcG_%0jVMPPu zC@|=eAB|WzCQMg-uf>d=Xj@6~kwS=zy9Af>6Ju&nj1x1CwEGKGLh(E!*2nLI;M8anJ=gtc;8`3=T8_=|KaaC=9#|=3ysm!1jfWt z81r2rKAnX8f95|(=>CRxfv5amV)BN2dVKURF+qj;|B1AZ$!lg-}n`8^8FpmIW|dc{wmy!JM_GCKXvc>Ex&Dn?I~sM5(V zpxXZ`j5>+Qd&nCyjE+;?pbcd5?Dt*^zs0u>VyT>o@f6umGzP+LF0;Hd4NTfxCXZMhnzyCc}8V^PTC58~hxdcD+z{8%@Vr52fnVmQVXPSpuYwMyT zYWy%Bv8vn{f=O}h8{6G}u6DmR{j$LJKaGi_9m zx8*bgG;#aIlz@69HJZC#;AiD`q**$a)uSX=$`eEqo~yk1F#gV?nB~RVI)KOun^!+g z(4ju97*~J2a6R9@$Z#*iEINz}TT?x|CR%cmUpEL-AJUPkKT%7DppsaBaSvpCdN6mZ z)oG{24HtjYH|Y6|8t{I%%vWl9t$5^i!!+Lf>P<*L3_Kew6=n;TX&4=MuD@drAYIOv z|65_9$vys*vOXBW3!5OYw_$y}&tHk^gIk+w+k9V3cI#5D8z$|%Y!Zw`U|ZNVuvJ4k zw-JWL1&%X1k_>BZ^5C0vqyoRT8Dfr_LIYS*V~B5q+S^i}XP~8d66(trbKJKk^wlKp z)&^vJ0pkiE4RQO+LnoYWt-`R@>*iq?ejrrY@#_X43~KQ77bUL;Tl3mECi1g)v)Lgj z*_SDGY(LLXCCasH|O z70!c5mQxt~jN)>#P^Y|jhkoo!Y4?Sjx&PLx$UopX+V+sc%EdX_5+~**?YSEKp^C(V zVO_zrI(L|C{7aX7SxS;|f!@~bDn2ic8Uik7vBc|N+PY@rkJz`LQ51bh)tSJ(8E;l3 z45UK6=TE{#o6y?qvzNDu6xL-;A4kBD?`6gwTrrL|%<`^?cQ~Tq{DY!RxqeLk`-GK4 z1*SY_z9>7mdm}2?6Y8NhJ$TB<4^vN*yrrH^lwee5T}#I z+%`NqD>hX0!7p=$ON?dF2*WvJ#9r_+<{mBc7b;DM!S#^v78R^gdp*y6o`IqMJ&OVr z!#z>EwcnThJlWtrSi$Sx+d?`<$^A_-%uzvyq0C{IQBQjW43~f20QQ?*O(hjoHo%e% zi$rBF4F`u7+c$$8d@!vN9!+&ttwmXaA`qE`g)jXWdFmud`mclRW|2dHo3seNWE3A! z+j>q0WMkHo89EGpu1_I%{|rrI_^&?VQj`;!^(O(WKJKQh36#LZHP4hnue zSwhXmGO$lgPHUcSRklRgwPBu2qS47)dSv-=+mTR0QP}5yYsH$?;q4LeqGXcVjZo#gafX<8q1)W$@pT@HekrMA~-s8!!wVC z5>vhi+UHMmq_cWvQH8ztBPi0i)!W#9|lQJRJ%3FO2O?3s+C;WYCpda zOcy5b-Ze zO>91#8s$xV3cKvlI;`XNGg5|U6MCD_*`J7A_uFZo=t3e$^nq+Kj-rwyzk9N0w2-9Q%ENS;-Em~8P2|+2$x`Jlf4t>Y1J|4op`5U!9EI>U#d&-Psw#7 zQf_YpyDRYBKpsj&P4-1iG>~q{#j(yfKV`RMB_8S8$n(OqP0uvb@oU=U(gACQ!9_Fd zkAHSQH`L=g-V#~ub}mAu;1_3byA0Vb0$NW?S>ei;?aJYo%nCkY8l;57# zw_Rlgzm+fD-v^MN=@sS1uXMsUJ^%5S-J*RVXmdC)Flw~_@_|ZCf&T}eKw!UrK@>eh zE8TveSW!?^WK}2$+YJ~=gTw@-z(WnDr6fKz)7{(c(*4TpZVfT=L;M%U1dS&C0DqM6 zwrGsvgD*34&fIhFxp(H<_s?GetYb;w-RWtw_D1hYYe0dmZ|YW0U)8P9k6ceCZWtJT zXcO~_Jd!c-WnadI)hBBZr+%z|Z}y}Y)2bdhhA$(-9p&h5Y^+)9k2zM=e(8Iu=P?oY zrLo440>=%Alp8qA4oSsai}_mhQMG2+G}PZ}5CVl(m@12QU5^BoL*Yl=u;yM2WgZ;R$%&A4yEbIz%dWH$7CfrObX2H)OWYrjl<4=UUPe=QSY={ z^=4=P;6+`a-1x0%B_n4~1hg&7a|1VdDv+tH90|<+9rP@9J)2YxC4tGUacl{fQ7m8z zR|N7YTdVfjn}(}@xN4om3Hdo(6DT^Ayi_6glbi@FRW3SNxk#089XAS?!7LXZ4I{7x zjQ`U9^vo%4;?~IMJa=kkR?kPP;SQrDJP#F^sr<9}0`85JizR5t=Wz-51+vfiv9pT| za{R#rXXm@|Nkaie-XAhr#sr^$`7fAy^%2wM@+Zul;dc2hFK5s{;K6%fEX(jZfy@t3 zO9u$8Q2LbF0RRB90+X?n9Fyo;Ie!a$9A&jXXZA6(lkF>;lrE)ZNn5*VvI#Aawp&t~ zSKG9kv@{K6`=CsAC&|*?ov=IGHmG<7DxlX3UKK5Jy^3IbpdhxJK!hS{K}Av2t0=y` zUd7k-g$hdV|C`xOvdN~@-|esM?0nxj=R5DmH(z@7(Z`8sjWob?_l-C1T7UQYnm#Rd zNKeOW!Zoq}n);fUks3-QH8WwPLn$M!V?CoMbuFu7b5P5MVuO0@P&Sv!)`a`DWLB@Q z85#(sw4qQ!(CBMwS{+++8DKN(iunDxWD*P6K`pczuX=hQk=FH0B0YfB!+Iu*v#`Fd z;gW`Rp}2my=8Xz5liFkCGJi3Bb0VoTEjKa)jRP4ip41zUWVE3nJ=3_wdfj8cb!myT zOirfx*J+2f#-x@WXx!0vogOn~ax*zo*k@W8+!vYL?=b}v8)~m&nm4)HmejIYnN%j< zfNt*07$%5-#dgD{Q4_4SX=L?SE|V~a8>ho;@RFD2s8m67nUEuboeX zWV(RKWg5M^I%lAD0&OW>sL~P&l%jRYRKw)KnLY546vU`1qE6MemzL8Cm6p-#V3mFt zSD|2u)oeJKRx!Et>wk0bF{bKZWV%^5)b90CJ%v=NqXyW@<|JV>3Yv{OHFFR~yqL)W zhTuQJQXz^mO@#+*Yv>Y{R@0?Sl{5EcY6459VSD6+UH~FifW3~^SI}At7xhxuk?C?K zS@;r&cxj_8{uQ8gc_N)KH%=38!YjShLaiz_Q=6^Uomxgun}1&F5CocOvrV*HOX*(P zYOldw?)?qdX_@5;ZHEIi3}p-ihndi`3Uz_6j6RgqL{Me2(8{_p=a%85oDp}>PNDfL znO2?~5lfsN!Q^h+;can*g1mGUtrt6cm;zG*J(f(srBf*_9giSo03oYqWQxM5L7Uz_ zmG;tpSYJyfjejG(=|gGbNP5SRaCmqP!$Yp2gC4+Ki?;!V`d~Mkcqj*2p+O@B|BFLw z#*iH)Ys+Sc$n0F%r$HnAG$6PcJgW>gv`p8*7FuQ?mx2m*4-dhg7DT3{AdpN_%0q_; zZ1MF94IwD6&n0wIp$t~q6@m#Xvcp+ZPlbe`6*|l`*MB0DGZV?iNFs~ucN9YP=w`qM z3=}+KIAHV#%t1Y{?W(RoP;VG$2!z^G!(z8NHGEi0=JeVIg>JwJaXlN$BntYeEawbw zpf?IWZ!E^Kb$UxCqYWbl{{`CBvVs?;6(!m&26Cj7We~iHZdU2dbjwU#T22t3qEVUN z0_9Co*ng^J2O+LZw;`+BR?W5!+pNM-BBhXB+7OO=E4@uP$-mAZgl(Dr4FXsSflDn4 zPUW`ENG9!M4kCBbJ5;)Z{+-DmEDvM*?7LLDo!%{KQDg?!1(5fsbSu4=sp++XVR@_G zZ)EIn?#cBP_GP-8X-n`dPHSUtm<};RxdndiQGe-u^dH5fXxXmQ)H7P2NN)ehq$I?f zX=H>{Qx()%SciH(NcUFI2k1jZDkb|e-H&XB_M%%qYFgoq&>f+VRM3a%qo@;UYq_+Z z6uievAEyTd+$WgoUsGT9qsP=taQ-0tHKh&r>3GkWI|?3NHW`DRPtn6FJw%^ol0qSc zPJc3mUh}w?eh65|M>36y0615jKcdnYJqoRaLi?_1K2WF7XYi8JOcd9wmmU|~)X^!F zhHS1cTX65{U}xEE{aJcaKz|OI*GQL0yZ0PRz-x+X6P%)79Qy@2EmZat)0%%CU#2f2 zn-$mgAT1Wv>!m-_M}%fxva}904kdLHy~AH^^ZpH-Br#i< zgI4~4Azz`t3oHEtG8*Y_qtF+4>3@vS@Iw%S=38`%=IBVry)22I;vsgFwxm|+l-X72 zTqc^T=>=hOXM>kzR#bMgM<^7EzWiLgV@5WZY%kc0s=#xYUUzOdGS5Roh)gTUg#vpg zFYxeut}Hgrr2sNlsa!2`H8(4K-Yhv$#0q18sACKeq%ejC$53v1TUkicvwxQTl3dP9 z8KcD=jM1X1oK|JVh~dT|Ey*Mb$bB8i|7M?TF4^A)sqTqTt z$h96Q7UPCe3Zb56uo49qNac&TebA#15bGtob7VI+&*F2{b0Dq-#<}D&Nwu0>R zGZo$j8-uK#KJ4X)4T#xgLE-!> zxZpvN?wT2sOHCOPg@0?0j-#0UMFYis@OqJER+iPr^z3AxsjD1gR6aKxzdwQMT9S{Z z9o1&Rr7k#&tmS%sHaVwqiZL;*36_)EwtvxvGPs?#@{S60`26{0 zkUP^^6CcoCLB&P2Sq_n^;wSg#+fcP&B3e_-=y-5jB)C~Ss6ZyG0JY1@KQMG zCY9g7H=_lKCq!%6m$RG2xzlcf_!z%MnB`U&sZrtEkq$7qnw@q><>j~8+d^OyT#y155A0 zy7X*T8_?Sm1G*??$L%y_86_?5*H+J-rpnU*KkwsvRKA-r1-W{6Zw{?fSPVWO+d6Ct z?^{@o=Dt=he~|ALN4wm=4;ims97gPJ~ucI zTkPDmV_QetZiUCDL0b1z{HP5%4#*o4LpJtf_S)n2nhp1az4lo|f_^lX%w-dYtxMaM zSPUxc(tpy>BI34rs_!KrU?#04?aQ^K5jzBRHFnI34*h?QKktE4eu3$N*#mC*YMC)@ zWX>8)rJhzUBns5Z?v>4kwiUjp^3(h!+bgUq9Mq4Jk+pEI!_V+nRFe6tFls|Gc1Yo` z!J4TpQN}emo||nr?e5@!Hm>qi_`-BMkXNC9uNiyD2#Dq9=LAl%Nog?soR!)!MarB@2mX0=sT3O zmNrCIwi@hhUj7mPSk&g9xJdk&*Sg6;{LLqdQwP+&3zgJJ*_O0!LK%aFlsTgCFIE19 zsDH+)P}QK8PU|QW7X_zW%f{^0tYxzT2vqlL{*6HWEz^>-g364!LN+tQ5lAW0&1|H_ zKIr~||ETis`ADGoA-K=)?ulzTa|H3bq z%p1E0VK$V`zav#-le#`6qJNtJf0fUu{C^J#vx_qZ5A{kCAssv|If`CURz6w6s;aByxs00)Adw z8gXeYC6r@|g0gSgHMulTnh&><78Ga9!dC|?I3lQ0P^07%*TI3pSBQvLS}49$EPs>4 zC^9XaiWq(*(TQel%8s~>n-PQd7I;}KU7$+mOG~`eVgI^N$g;2WL&+@IR?tfqsZy1M zsbmi7h6pm-cGEAb>{T4NTv{Ovi1DO4D?a+b!H$|G?4BQ-{X8is)e3YBD@$RqhC)l6 z)N<+AAlh=f!x#2aqpB@9Wfn21HMbcG0rDrpl_$7JeEiZ5rnbw_TiHBeM@U|Y+sKz|}#T%KAw z11nc#S2idT<|Q|BEDHKGUd!mG46nsGNotom&^$<+Q49+Gu(-EZq^;s3VVTRRDYq-q zHgo~fcBaMvd=Grb14p!k2_P%`Pt@vwW@WH|X;{S|4Clx#3MJG! zIq+H|5)Q(6wXqGk4oh*&i1o|^ZDiAZ`dLLvfT57Mj z!#N9U`vq$UiY;cLYv>tHo7&OIsw*8Ve(1GmbQ_k>x9k0zja)iz-+#DCTJf^Qf|-IG zLpB$mZc&59^-Xs!)u(563m)hqa*=G6SHv7C_{Wk?hiQ{l-lbftLlpHTkvmNWu&q@PrF8` zH&0jFe+(-?3C>VNpinP;&6Se~9ZPJW=t zP|oN5^1(bkou{vcT_a~6!2Z{){RXi=zd29eY!ZOg0R6TNTJ3UPYyJ9sp1voLjsWTV z7E(YUIVVB=vU?J2=fm`)yJ-=Ce_{cP&fNsSic>rwhmo_?RFKZ(7kA#|Spa-4icL2Wi({h}W) zFNa;OCZ$^OLtU@l`|3%*t6FhhD5t$n;G&x@l? z%009|(DU(B{IC5oWOz4T{?m5AAVxi$U z_4wg{&0$w%4C~Rb+u~uh^CsaF_RFQt57BwT?eONv^I9;2s2L%BoYzNvykV3tKV|>i zD1JW7ZGU@w+%d+TIO{Z3i_n5dF5vjxke@<6-af|Nv+T~ZR$QPWLNgQC80Y7s0)MyuppU;NLXUq?#QWhX?&dJU?59=yvy_j2 zeoR~I;;`(OpQ7Hv>O$AM?xC&Y{EMg+UoX~!gJ0$Oca|glIokacEk&e*#w+-{fSx`! zCh-WV+x>F)2rop6>V|#KJhXj;J%0H#eWxxjIpIFgg5&{)b^I$&VBEJwt@BA0LVqA3 zL~Xq#L{0s;G$-0MD$T9WOO?^C(=@;Sapwm}t#_>H8X*^V)t{!_<5E?0e*_TKd1+CX z^D$Zyb=3EaNlWumU{qQ*CauKDpdQLgtFc=VjW~SLB|SdrQmn7Tij0+2J&d=Fd-77t zr-a_DGYi0W0pXK&uNsy1oSMRMJvfdQIi4oTzT&!t49sgzQ58Cdxr$f1 zmKM`;3QB#>2c0M7XQjAv%z4^+KI8nZc)F|Hi`_?w+^gKHt>;>I*m`bsZ-2I)o86u6 zK|CYw9oBQV`x@)n=N`14Z+0J(Tk$;RzSDw#r~5APlw0L4>$y|zv7Wv1fc3mizDYdM z$MoaB2HI}*HtR{Eo#ddsA+l@@R%RZ5>ApY$kINq?uPT6&TeI+oCRjsPuktRTOmmd8fhAI-!DDy+>i5h&;6fs_k8@|!vGeGl>*x? zyKME6ORBq#;D1Il7OM7F2YagPtAlp5&x#n1WygF`J7m&$+>Dq;!lcPwBjF47n!$~U zWHeFj?=d0?v%b17?28(GK8s~^H#aW|E^eZ=@g>>)J;_Lf1`@r7ZxOL(ENsP0Gj7Gg zG`h)*CrB5KFKIZgVTmtfZmPaig%Hp>>|{J>uCyYiz<&%o9&QZBjZnmF?2j9LeP+C| zHI{IUNMzn31qA|=HyE3Y#)uIMH=fl=ysr$i zH7KYOD4@_&{HD|_Xd8cq0BI7pOdZN+|dQT}UGsG!vAO3n?eV zHAl>#|L4UKHqXn@76uxMT`NAR;S8K9aO_cTQg9Yon_hT^9i;%A%?a6#RbybHV@tv@ zqY742+*wUuOcfQveh)AWWgG&Eq_7>&ZRrvV_1=7+&qioV1y}UO7kVmc?ht! z^9d>P2vo41lCF;jB7_L#`BI4v`BUi9Z~-o)V+;`hJLE-o`WS8WmaI3F}bML(Q7PjYVJrzb!=phHh^xa)?+g$n@+G-V0PYg&3{4+ zdl7@phu245n43vP8l9~nU#$&-H_%!RgG_vf_$ub|zzr0~h#d}_q-c7+JJcp8N!yLMsfYsqb@F-zrw^r7RVWJ; zRVu#8Fw(`avrWKzSV;YZ$bOXCwKHmUxrfNO2X!D^K=M?2re-;3}!yf?Ns zO1TRDNd`G~o83>D{4@6fu>m37M92&FB*6bhEklPZwTM$(yE+DP$xx zYB&x%KT{L4WPd+BKQTY13i|T&$XS7M`eUMAnLo4eU2`C1OPPJK=3mP014BnGB=ySq{BC; zimpV|O7Lqj!GJ)QO)O-!B-ks3ieTCaeCrNi-S383FfwtN~OiN+G2uEKunASds8U6y=<}Vz?tbpHBpF(fvAfkT7-K=_=i+obLTCQ$|R`2r`q;Qe9 zFa>8DiidHrUmZXz^Optu>XW4Fz&l=b1eXW=+7LebaC5P{SufYii|@c}uUf7z4)`ZX zqkoINnwP%5(0PR}1`fRH)%>bgeE?q;NPk=}uocJg*VhCdp^*4Bvi}<#5UxMKz>2&)u&X|h^+@R|eUUsG#w#i8EB*aJx3cqUSLy50<2MgZ z3BOX%tdb8$NvnfEo8B*9iIf)=No(}j6_<&3QJdD5GkAI}_VSnjI zDGs)0053?F3w>q6MSh9)5m6BE?8N(lfVZ$K;4TxMj)F3wb`&;yQlhxr)73E~CZMVyTCf{6UQd~r<5vrILJ9bb z++L-FqFs~{^XV*KX&=C3`c<-^V}IzQ!Z$4HQ=*ZAK%DAh>f4Pu-hynD3cJe0qH&2) zUt5yYJo+(H!8*FeFac#oy_pEfXioz5B|KDAia^(g{?)n15D^Ig(b3 z6D2)atd=w?`oyc^6mgNbO46&vwUS;hwo7`m7?$)Qu~*W);(4(j5HE_CB)?z0#ng3; z>qhqkv0Tz3(c;?fx>fQ_nZM0-r{tM3Kj0daJX7X}Tn|c~Df2sBk4T;=^N+cnkUUf7 zpK`q-d8W+obG;#Xrp&+XdVg2)OqqYr^?~G>GXJ5wQ1VQPcbB*;n3t4z0?gA1JU5_{ zfLGv50^m-#u?_|FtXLP5-f;+%-me>fWs%!T12GVW|5&xPuGV_G@op77bzQ0`Ma3II6cj;0@G{*_ zx6$l@WLq!9K8SDOg$Q2w06vsBTNM!*$jtot=1)l8KVIJeY+_#EvERRF+`CN~+)~_f zcio`v*4!Y8Ql(|4lGuxq7O`$fleEN}9cjIwL&2@>M%LYJOKqut=BA++$<$N1M{{SV z9&BziYZ^cE?XK1=*pBq-+)^B>n8>I&WVJ`e@>#4mHnuhzUW>Zd%6?zt$4SI~ zlcxhlC4TO|$3k0wD%~}7M%K!ZiRsf{m&+`_EmNcWDpuKnz~ahZga7dAl|W%-^~!;R z$uf$lI4EIk3?ryIC}TXYW(0;0`IS)TrpP}tglbN4Rm~aBg2TZCuXEfjpuhoC)~>H# zFtz@S>Dn`9pMU{c7+4fO0Z>Z^2t=Mc0&4*P0OtV!08mSlwUii>vw$yu33waFb$&wt z1h|3@lA>hju-BAmfjCGV5h+8q93HYw5uy}QM_|d8m%xHt3D{+J7m{e#O4`V2j<#tM zr-_uta^2Q+TPKZL38bS$>J__n)1+zBq-Wa3ZrY|-n%;+_{BHn|APLH8qfZ}ZXXee! zoA>_rzc+m4JDRw#Hi1R(`_BX|7?J@w}DM zF>dQQU2}9yj%!XlJ+7xuIfcB_n#gK7M~}5mjK%ZXMBLy#M!UMUrMK^dti7wUK3mA; zFyM@9@onhp=9ppXx^0+a7(K1q4$i{(u8tiYyW$!Bbn6oV5`vU}5vyRQ_4|#SE@+)) zk9CgOS|+D=p0Txw3El1-FdbLR<^1FowCbdGTInq0Mc>(;G; z#%f-$?9kmw=}g1wDm#OQM0@K7K=BR+dhUV`*uu!cl&ah;|OXFw^!{Y2X_bQ zcDjSDpb83BAM2-9I7B~dIIbfN_E3;EQ=3AY=q^DmQncV2xz0W-mjm8_VaHElK@EC- z!ktWFouH=5iBgisaA1U@3bj)VqB)H4VK|{N+2-(JHfiJCYX>+!y8B2Fm({k0cWxASSs+u_ov64=P?sTYo z&rYDDXH?fxvxb>b^|M;q%}uJ?X5}V30@O1vluQ19_ER5Rk+tl+2Akd;UJQt1HEy_A zDoA_jeuet!0YO{7M+Et4K+vY}8zNGM)1X58C@IM67?0@^Gy_2zq62KcgNW)S%~!UX z1LIg~{{L&cVH^pxv&RS87h5Dqhv+b?!UT{rMg#O##tHOouVIW{%W|QnHnAUyjkuZ( zR@l6M%}>V^I?kADpKlXW%QH2&OfWTY{0N_PLeRc9Mi3vb*?iSmEU7hC;l7%nHAo*u zcCtc$edXLFXlD(Sys;Aj`;iBG;@fw21qcpYFGU6DtN zH*Xmdk{4fK0AKi6FGJC#f0@j_)KD&L`tcGuKP_k_ zu+uZ@Sh<3$bA}GmGrYql`YBOYe}rLwZKP!xrdrur0ib3zAR%*So7rZjP$|`v$!nA9 zxOQ4sM|Is)T`iB$29KOE-0_Y!v(GZKhMia4am~e#u5PJbJTk5!5Jn35E$W1AVWB&z zA{r<8tP)wo%Vg0}o(EZ}Ts5eMgW$E9nUDxFyhPP(s8$YB7)%~lUan?sD~~9DckP11 zEa%9&uY)hvUwxUwb}pf|IT$VPqb9AAiAuw>G+8N86Ovlm%$~Fhhg1!#<%uJPW4P+L z>rOa{&N2gbFd3Fh-nnA8lL@IrHd6K33HFYag|7^pP;EZ&_CU5|tx*P)T5w<-hNeoB7VAth{E$^ zzh&!tb9x@TA^<6 zWYl=|`BSI?aM#~0G0T^KK!+74^cJ#Nj`srvw<<6EzM$Kx-86sp4;1hc2-blI9c0tmCMY}Qn=5b(4Vqv{|sKKb)cXA9B?~> z#9fzsZ29S1Tr62*LHahw(?8R{AQudS8<=zg^lz2qD}8im+_uhWqYUr=fMT#sIo${8 zzZfe2N&j7)tPfNL^8Z2}6)v8;x|<$fDzHr5?L0g@AOmYTwm%3~HQmw+c~!W5LEVM> z2|z;BF)jd7U&jQ0%D8~=0et;cR2&d~)H=6#Rr*B(V9$6xY#V}Z4=>PWem5wViJ&4B zv3xeU=0-BSSJgLq4Ssb;S7t=xC1%@8T#c5w$= z0*}ik;4@vwq3Am7=yuN-b_|MEpaRpI;Cvp9%i(}%s}RtlP5ojEwsLfL7&QhevV-Ns zj0eq<1@D5yAlgMl5n&O9X|Vqp%RY4oNyRFF7sWtO#6?E~bm~N|z&YikXC=I0E*8Z$ zv7PtWfjy*uGFqlA5fnR1Q=q1`;U!~U>|&X_;mk34hKqYAO9h_TjRFso_sn|qdUDA33j5IN=@U7M#9u zTvV5J{l0zdjRWGKB8J3Uz+|(f(HYHAjk#NQ1jL9!uha9;i4YYO5J$mewtTo9vVtPT zxqXvBInY?m4YD)~h~q$Ax!_EwZpqbZI3OP3;=4xaULDboazx{;=E*zl0g)CIxiwU0 zS+taYYlIHHMHZAe8xkWHvSjw;0&`NOTN%Xcr-ivm9Bz1h6ny%66)ZjF=M6S}>=v4~EuG0F; z50<8 zuJ7@5d0V_2pQVkF7Vq{{!dIm33#3Ft_}G2)yjM)!d^I{4d6C{M=mM$U&yqhi=!uOq z^+sms!NF^^FO?LLY1%(UAAuAQ;Js8WHnK=;BI0?Gj@F^p*@W>;sZ=u3l$xf8pzH;I z3P)vOmA?n#aMPBi8^%0|sj#w@`5rIzhQ!tSbr|=tr zz3XA)gH(s7qlZqzSnr3GpT_7Etp6(f@@<&&Cgd6@O_{P$>oL!s`$Ftx@?LJr&QNaX z8kwntH#$vkYg|R22_$?WFI((Ps;mBgX=;jxe4dv2B0W9@Ytx5X>gz7C*}oPKd5d(e zNI!)2=dpg8p7eD2T72>A&r(Oc#kZr8Zl0T=_oWh8{A0N9vXFPx)*^lID7MGYhmW53 z!69FY@je$)Lq+<@3s5PVD$*r5``M(QjgmT^@OmO6-sp%gHc}rSY5JLvw`8Gz=TflG z&)tw(+<*mIXdUgu%{CxCbK8#JowN2@0SO=M^#R!H6?`{v`CUe5FJ?SwyCTwGaWuck zZrbd*cS97n*}$HSL^o`QV`u2{Me=!GI9~_dUxVbO7s|jzu~fEkS2;SKy+&74sr^v1 zSfo!g?rt#d&g0|P1t9ae)DZ7~4AaMp^qVvE1qqxlUZ9nHsoy&~b@Pi;bSxIXMqg&h zucX*B)AZGlZ<_wNNMB2M8@&ts^)Xsm@z<+UH@_KAm7Vk&{!iU}$6y2}y>=s3q`$h% zKQ|De3gWd_T4=Rw*ODsRR%(-Nn7U+pH|>$_UfL(yBps0LFddieaXJBi>k?^{mF+lL zvMtd2WXr!S_d)uoY)gJo;16IEvvuH(Z&YlEF~4MtgVERw{mtdnP$YGQLX5QNiKcH( z)87Fhz);ga;3ro8{wMqZN=5qDvS|E7)4xm6|Cyb+fwKtysRw&ATYU!+B2TOXK$*G3 zl~^PtLwPV-6rR$Fz;;o8z>*(s7WJjAq^m9+Eguv+(JTTuX-2FlipGi#>xbCfU@qZd zcZ!5pBz#h2ErNo*n((t*0g$hCrXHnm|i`@X6!d0j(RK8a`Hw z2l5S1eVl@8los!kPhF(7@ijcCcL%PBB!<=~MKK)m$2=`T0Eu_#R=NXIH=h{{`4iqL za>{Mu8oi!s7Kf(A;TzGAKje#F5l5QETXFpg?7)M8D4Qw*a~?Z-8SK4tke9LDVAp2x zFf0l}5RJ{^1U}<`@`|I)B2%(-WLk{fsNVS{3NYNyg}nR)ue=tyK_MEWlVVgDvV8=; z&C^-g=a&0t>2a|ceQr0P|8{y#_POQ$^YjVX=a&1Qq|36;E%!Nkxz8>4U!u>;KDXTe zI(~qWgw0KJDS&EAzCZPW9FjGEvA{wpmQp~lptydug=H;9(okb!NK8l? zHP&F{-*kJ}F6>9y4~#K#AzXzT#l#<8fEQ&vLyM5mhMnx}&YAZ)?@Z3jpTEC;16YG8 zaC~(1rus>5N^76|mcF4|yZVZ51zyK-W$XmL;RP+?ct|eEh==&9(Oh4zSZhyM8&=Qw-Nbb{5VfUI;UW39;}eCBZ*%mJ!ic>%UR`~> zS~Xg9sDB=X5J)$IB(&&-h`VEK=D09=41jZa}_^O(<+( z@dU-oVCobs4fZRXVC6E#mw-{_oB9V(O9u$-3H${-0ssIWldzOjf5Si!#%E3c#9Bq4 zK-p6(O+zb|P(={Ilb|T{zS&HZZ8w{+o7RKa2k|XD2_Ad^A4;5v9-M{w_q=X}6rk(Ww~N);x^iv)>V)F>R%WhPu8Gn7lW${nB1 zg?2dLWg6t73{<@%f1XT6a(qfz8~x4CS6UNrnFvN?(WJ^CT4hqAYqXBuA|4G-hEb5< znm_x%7<3+rm6dp{G%`3UY#OFkBpSmQoM5x6G zZPijL*Z>uQZW67A|R9w^IzUkPhic=6I zm%(-`|RxlHTyT__;TIpHtPB288^%``Bpy}I=`(B1HzbS#S^Q*EAx z4u+7Zxc(*~GMtIG28o~(XLX!G7eiM=)yPxBISPB#v`zndJ?z~G&ZAdH4=ynDG-o(t zf4fzG(U*c(G`yvvwG>!)eOpH#E;0lxhZh*mH;kJ6>$aB=Q(^iUP8ycui3r|Rf%`B( z*o|DLxmTuAG{kibs-%KzVslaWt>u!4${j*dfuna=Gjl z-rPoCZgwb{OKc%p!#g#+w~fKv?Jbb;@C$svFq?dVj~E_foIb8G#ZpC_6H8jHE-TcOH8ok& z$_(dqrZ8$S41ZRskt|hN>C9-<3~{+a6@$%*btze+^`y*m6tmfMDYJxHJ?HS1hN9qv zQKiW=4w)*+Dr35=N;rGYbOYDI`P}@%d@fmL=i)~n5CZ;!*3e7rxvVe(QB9Xpl1|GC zOI_%+UT1phon<#QwIWLmy|rgAcnAbf={Zd)RFzVD#eY*)GQH4GKq$+GsmsL%*AWQp zwp1!JQ~UXy6{OnZ8+c#>;oX0k3MSuir|u0ks{}^drwUb?S;`g~H3HuEa^1?rJxd$F z6)!aX?5$j5TEiqjb_k4}Q$;RQlWnyn+Se6~9ueqYl~vhXBhVX*9|$l4qkizhP29?h z{QB1J_J7HKVLN~Fa_`l)55@)X!;Jyxg9!qIPO13*3?JMUK(K;$1qfK)JpqO+PZS^s zA@1E5APmFYdq7~wVCL49(uHDIYsWX`g8{Bj5Ez!O>a7Bd#Nuwn95&p5ney!kDT`Tjequm6|t7FBi0~PR z6Wig3nn38_y7nWD7huBpkHix@;%Pja_}Um_SjHe0FufTsH zh<`!cP7sD3`~&nSW}7hU#OEMs$3tlO0)2^Z5cy(<=ON{WM;!d2D?aJqX?J|m!85M- zqJuBFYuyW`Uiz6>ia_{?WJyb4dc@CbIt!Pnra3m$dw zXRz*u+l|G0iQgXR{R2=-2MAKixJd5;00RI}29vRr9FsMkH-Gzg6GasMhCUKPcr-0< z&=`fbY0~hJS_-JNfL8jVDPW3#+hme1-R#EQO zr8BZ3nX;ya(|=lm)4a|VE*YE_hb1E%ALj89Bbzn?ZAnQncqoubh0{_dEDIY$EiLQg z8#a-y-kQfJvx-6!#;_D#PeZPzWR-JWR#P-P%5{T$(R^$3#^%;=f{zAHxWO1aQ7x;- z`7T-E3;|6~MN+zyPdxV3$Vxo7itK3kKSCU^`H(lUU)HoE~>D^3peJ9 zuVr3%Fn>>ctzhsL$Kk>%3X+e@hH2QY2fert_j|A!e&RsUq(mV+F9KNTAuA6u%-6Y; z*g-H|+p8-Kbq$SO1^T0=sPGmq)?lpw)Ds}Z%|1!zs_F2%C=bXp;zc8Z!f_KrYf;WN zN3vy|dpuNG0LQOs)}xS$X>lXZJO(XFg%Lw}jj7!kuOW-bVAN;}iCM3;4a0JyP`}o{*?zz8TXrym$&hgQj z12KArYd6i?<3&1Ovo%~DGAvs;OlR5g+l0bxPkdYrEVN?ZTk01}-;e1@er|}f|r@K$2{%}g8Tje|b zX@-EZnaZfTe{w9_pRL@lnb0BdP3|KZC6I2xM*}-L@okCg>+|siC&#)tUK8JylN{pH zDt4t7$(`}O@W*eezOr|UPZfB-xzHgPxx;@~pr@Rl0<053d}L7P^Ux-lBPM5a0wZ;u zyHYF%hN%t7nsAPpTW^4yYmzxjkz(`o@oIu_!z+2JaD$t+l#O{xRPj3b0%sa|$oe7N z|2j)zd)Jk6rh2cN$=6>JI6F+qLFCIP2f1sqltoi2fx3=*dzthQT&};TZQffaZvIcM zBvDRuVcN8x6#22F19^~JzM15_EzmvxB4uAYo7R+>b+i!w!E4}B$kB|Bn0BW7U9;pJ zzm;cCmYp73&uc$79`Vu6a0YoLUsUB6c+aAq{p+PxONS#uhv$Ay6b{uT_+110eAryY zo{!hBr+ZjM%T$@-=Q*izvg1Q1&Fw|4WBpaJhj0gb+D%Fni(*duGud~?Xl7m@JyKuP z!bnleKIoLuRcpO1DXOF_uU^L|I`bwWy_aO%ltvtOCpD$2UC+#Xm6cn1by9{*_vvlR z`{3%c_1qKUmO6VTo%3im-=9_IzW3wtI1QipTl|LI)0xiBdG9;+A0D)6$sD4;R#jH} z8JJRMgRX=(oJcy}@H@dZeEo}f7mqAtb=srZjOL)&XB2MmeXp(O)2?cB=T=Plc#1C7 zYwJ{U)s-JAJ6V+IjS}UMDKw>jUo=x^Q&w*GjvudQ)0^(R%}?XZQj#ZQouoylcilA@ zQnM&=8PxbII9Mi0UWnJV=1)rHHYOFg(@KqxIlbB6Pxet)7+y0zmVWJ7f=7Z1d#c}q zcXfv4M8#zrD`a^(&euYtEh}k#FGeWM#oy|EdFJ~G!t($@fef)Rp~!;&ucW(o^kbrN za*}YcQ(b5WqHl8S$h9d7aS{BUCt*d+c|HECGQFNniZ1nny50ys3*MYvsv*(d=*6@( zrFBK!4RYfFrs7>*HX*~)krCaU$n@`QnR4+Qh+DNOAh%Y?eM2*Mh%-svH02$FyZqAU z;yqkQN6_^X@~?+}T`k3mk=ClA9qP>MVBgNWJm%-9Ku_RU=}WKCQPTeTQOhaMsBiSP zB}9=4q?$u7Rc;-Qay+QUe1O|3c-?eMaLXLN7-C?CLU9nvh+(+Q_&L$ehjZ74@{r%Wq;&fY;hqF~zb#3xfeTHN#kN;qL@Jzpeo?KBQ zh>aXE ztCt71#V~MOy%Fr;E2xI=ucSmE1L11K5KkWBYml2hGfcU{ zI#lR;f)r?7r;3QJQ58p=Ly#4Q9Z*_i4Hqhfm*>D*W5A=zV$p)jTVQe6CsI3Bv3;W$ zRM*r-RhM!SAqcDbgO(Wn6UkjiHUYm7%?BDw2)I7oWo43JzQh0)2eBc2f^G9tJq&DP zpoG?phJGRIIJ%LJGR3rqVJQB?4Wh~d`~{lW1SCq8aBL&Au*cXKRauHT`FvL}HZQ73 zB56+Q@KR{O=OA+n7%#Q`0`=MlUzI80a66D6G(l*Y4lK48|KFaxY6;59sH$RfYveg3 zrV&~;NVzK5Ty6_5*(5^{2?J@`0$#ZnyyVaeK_(c$iwv5plt7pRx&u_jE~LojV5_45 zi3$Svwo)1#*lmLL%yP>{bBySOBPzN8f2c5p7hHrsnFt{XSQv1p>ms-bUh=cBYBIUu_QRVaFzKF D0|+Ag diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37f853b1..23449a2b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index faf93008..adff685a 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 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. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,8 +210,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a218..c4bdd3ab 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/settings.gradle b/settings.gradle index 05c912eb..23a58cee 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.47' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.19' } From d5b56e5a0b4006f72697c8cbe9c4139a0bdcc23e Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sat, 28 Feb 2026 14:25:52 +0100 Subject: [PATCH 103/132] Update GT5-Unofficial dependency version --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index e4a6d16e..fd899c53 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') api('com.github.GTNewHorizons:GTNHLib:0.9.16:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.283:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.317:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } From 47bc90aa7a0fc44c55329786e9b5c2dfc2eec04c Mon Sep 17 00:00:00 2001 From: Guillaume Mercier Date: Sat, 28 Feb 2026 08:34:11 -0500 Subject: [PATCH 104/132] Replace MTEScanner mixin with handler for scanner refactor PR (#77) Co-authored-by: Martin Robertz --- .../sinthoras/visualprospecting/VPMod.java | 2 + .../gregtech/GTScannerHandler.java | 119 +++++++++++++ .../visualprospecting/mixinplugin/Mixins.java | 1 - .../MTEAdvSeismicProspectorMixin.java | 2 +- .../mixins/late/gregtech/MTEScannerMixin.java | 166 ------------------ 5 files changed, 122 insertions(+), 168 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/gregtech/GTScannerHandler.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEScannerMixin.java diff --git a/src/main/java/com/sinthoras/visualprospecting/VPMod.java b/src/main/java/com/sinthoras/visualprospecting/VPMod.java index b88ac06a..7949ae8c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VPMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/VPMod.java @@ -1,6 +1,7 @@ package com.sinthoras.visualprospecting; import com.sinthoras.visualprospecting.hooks.HooksShared; +import com.sinthoras.visualprospecting.integration.gregtech.GTScannerHandler; import com.sinthoras.visualprospecting.integration.gregtech.VeinDatabase; import cpw.mods.fml.common.Mod; @@ -44,6 +45,7 @@ public void fmlLifeCycleEvent(FMLInitializationEvent event) { // postInit "Handle interaction with other mods, complete your setup based on this." public void fmlLifeCycle(FMLPostInitializationEvent event) { VisualProspectingDatabase.registerDatabase(new VeinDatabase()); + GTScannerHandler.onPostLoad(); proxy.fmlLifeCycleEvent(event); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/GTScannerHandler.java b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/GTScannerHandler.java new file mode 100644 index 00000000..7f96617a --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/gregtech/GTScannerHandler.java @@ -0,0 +1,119 @@ +package com.sinthoras.visualprospecting.integration.gregtech; + +import static com.gtnewhorizon.gtnhlib.util.numberformatting.NumberFormatUtil.formatNumber; +import static gregtech.api.util.GTUtility.ItemNBT.getProspectionFrontPage; +import static gregtech.api.util.GTUtility.ItemNBT.getProspectionGridPage; +import static gregtech.api.util.GTUtility.ItemNBT.getProspectionOilLocationPage; +import static gregtech.api.util.GTUtility.ItemNBT.getProspectionOilPosStr; +import static gregtech.api.util.GTUtility.ItemNBT.setNBT; + +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; +import net.minecraftforge.fluids.FluidStack; + +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.database.ServerCache; + +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.recipe.RecipeMaps; +import gregtech.api.util.GTScannerResult; +import gregtech.api.util.GTUtility; +import gregtech.loaders.postload.ScannerHandlerLoader; + +public abstract class GTScannerHandler { + + public static void onPostLoad() { + // add at start to override default behaviour + RecipeMaps.scannerHandlers.addFirst(GTScannerHandler::analyzeProspectorData); + } + + private static @Nullable GTScannerResult analyzeProspectorData(@Nonnull MetaTileEntity aScanner, + @Nonnull ItemStack aInput, @Nullable ItemStack aSpecialSlot, @Nullable FluidStack aFluid) { + + // validate inputs + if (!ScannerHandlerLoader.isValidProspectionBook(aInput, aSpecialSlot)) return null; + // ensure it has the right flag + if (!aInput.getTagCompound().hasKey(Tags.VISUALPROSPECTING_FLAG)) return null; + + ItemStack output = GTUtility.copyAmount(1, aInput); + assert output != null; + GTUtility.ItemNBT.setBookTitle(output, "Analyzed Prospection Data"); + final NBTTagCompound compound = output.getTagCompound(); + final int dimensionId = compound.getInteger(Tags.PROSPECTION_DIMENSION_ID); + final int blockX = compound.getInteger(Tags.PROSPECTION_BLOCK_X); + final int blockY = compound.getInteger(Tags.PROSPECTION_BLOCK_Y); + final int blockZ = compound.getInteger(Tags.PROSPECTION_BLOCK_Z); + final int blockRadius = compound.getInteger(Tags.PROSPECTION_ORE_RADIUS); + final int numberOfUndergroundFluids = compound.getInteger(Tags.PROSPECTION_NUMBER_OF_UNDERGROUND_FLUID); + final String position = GTUtility.ItemNBT.getProspectionBookTitle(dimensionId, blockX, blockY, blockZ); + + // generate starting pages + final NBTTagList bookPages = new NBTTagList(); + final String frontPage = getProspectionFrontPage( + position, + formatNumber(numberOfUndergroundFluids), + formatNumber(blockRadius)).replace("\nOils: ", "\nFluids: ") + .replace("\nCheck NEI to confirm orevein type", "\nResults are synchronized to your map"); + bookPages.appendTag(new NBTTagString(frontPage)); + + // append ores + final List foundOreVeins = ServerCache.instance + .prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); + if (!foundOreVeins.isEmpty()) { + final int pageSize = 7; + final int numberOfPages = (foundOreVeins.size() + pageSize) / pageSize; // Equals to + // ceil((foundOreVeins.size()) + + for (int pageNumber = 0; pageNumber < numberOfPages; pageNumber++) { + final StringBuilder pageString = new StringBuilder(); + for (int i = 0; i < pageSize; i++) { + final int veinId = pageNumber * pageSize + i; + if (veinId < foundOreVeins.size()) { + final OreVeinPosition oreVein = foundOreVeins.get(veinId); + pageString.append(oreVein.getBlockX()).append(",").append(oreVein.getBlockZ()).append(" - ") + .append(oreVein.veinType.getVeinName()).append("\n"); + } + } + String pageCounter = numberOfPages > 1 ? String.format(" %d/%d", pageNumber + 1, numberOfPages) : ""; + NBTTagString pageTag = new NBTTagString(String.format("Ore Veins %s\n\n", pageCounter) + pageString); + bookPages.appendTag(pageTag); + } + } + + // append fluids + if (compound.hasKey(Tags.PROSPECTION_FLUIDS)) { + GTUtility.ItemNBT.fillBookWithList( + bookPages, + "Fluids%s\n\n", + "\n", + 9, + compound.getString(Tags.PROSPECTION_FLUIDS).split("\\|")); + + bookPages.appendTag(new NBTTagString(getProspectionGridPage().replace("Oil notes", "Fluid notes"))); + bookPages.appendTag( + new NBTTagString(getProspectionOilLocationPage(getProspectionOilPosStr(blockX, blockZ)))); + } + + // set book data + compound.setString("author", position); + compound.setTag("pages", bookPages); + setNBT(output, compound); + + // Mimic original behaviour + return new GTScannerResult( + ScannerHandlerLoader.SCAN_PROSPECTING_DATA_EUT, + ScannerHandlerLoader.SCAN_PROSPECTING_DATA_DURATION, + 1, + 0, + 0, + output); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java index 38ea1596..79f76946 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixinplugin/Mixins.java @@ -12,7 +12,6 @@ public enum Mixins implements IMixins { // spotless:off // Gregtech mixins MTEAdvSeismicProspectorMixin("gregtech.MTEAdvSeismicProspectorMixin", GT5U), - MTEScannerMixin("gregtech.MTEScannerMixin", GT5U), // Vanilla Mixins MINECRAFT(new MixinBuilder() diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEAdvSeismicProspectorMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEAdvSeismicProspectorMixin.java index 2370c0b3..94b41897 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEAdvSeismicProspectorMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEAdvSeismicProspectorMixin.java @@ -68,7 +68,7 @@ public boolean onRightclick(IGregTechTileEntity igte, EntityPlayer aPlayer) { this.ready = false; final NBTTagCompound compound = getNBT(aStack); - compound.setString(Tags.BOOK_TITLE, "Raw Prospection Data"); + compound.setString(Tags.BOOK_TITLE, GTUtility.ItemNBT.getRawProspectionDataName()); compound.setBoolean(Tags.VISUALPROSPECTING_FLAG, true); compound.setByte(Tags.PROSPECTION_TIER, mTier); compound.setInteger(Tags.PROSPECTION_DIMENSION_ID, igte.getWorld().provider.dimensionId); diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEScannerMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEScannerMixin.java deleted file mode 100644 index 30fcb4e8..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/late/gregtech/MTEScannerMixin.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.sinthoras.visualprospecting.mixins.late.gregtech; - -import static gregtech.api.util.GTUtility.ItemNBT.setNBT; - -import java.util.List; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.nbt.NBTTagString; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.database.OreVeinPosition; -import com.sinthoras.visualprospecting.database.ServerCache; - -import gregtech.api.metatileentity.implementations.MTEBasicMachine; -import gregtech.api.util.GTUtility; -import gregtech.common.tileentities.machines.basic.MTEScanner; - -@Mixin(value = MTEScanner.class, remap = false) -public abstract class MTEScannerMixin extends MTEBasicMachine { - - public MTEScannerMixin() { - super(0, "", "", 0, 0, "", 0, 0); - } - - @Inject( - method = "checkRecipe", - at = @At( - value = "INVOKE", - target = "Lgregtech/api/util/GTUtility$ItemNBT;convertProspectionData(Lnet/minecraft/item/ItemStack;)V"), - remap = false, - require = 1, - cancellable = true) - private void visualprospecting$onAnalyzeProspectionData(CallbackInfoReturnable cir) { - final ItemStack itemStack = getInputAt(0); - final NBTTagCompound compound = itemStack.getTagCompound(); - if (compound.hasKey(Tags.VISUALPROSPECTING_FLAG)) { - final int dimensionId = compound.getInteger(Tags.PROSPECTION_DIMENSION_ID); - final int blockX = compound.getInteger(Tags.PROSPECTION_BLOCK_X); - final int blockY = compound.getInteger(Tags.PROSPECTION_BLOCK_Y); - final int blockZ = compound.getInteger(Tags.PROSPECTION_BLOCK_Z); - final int blockRadius = compound.getInteger(Tags.PROSPECTION_ORE_RADIUS); - final int numberOfUndergroundFluids = compound.getInteger(Tags.PROSPECTION_NUMBER_OF_UNDERGROUND_FLUID); - final String position = "Dim: " + dimensionId + " X: " + blockX + " Y: " + blockY + " Z: " + blockZ; - - final NBTTagList bookPages = new NBTTagList(); - - final String frontPage = "Prospector report\n" + position - + "\n\n" - + "Fluids: " - + numberOfUndergroundFluids - + "\n\n" - + "Ores within " - + blockRadius - + " blocks\n\n" - + "Location is center of orevein\n\n" - + "Results are synchronized to your map"; - bookPages.appendTag(new NBTTagString(frontPage)); - - final List foundOreVeins = ServerCache.instance - .prospectOreBlockRadius(dimensionId, blockX, blockZ, blockRadius); - if (!foundOreVeins.isEmpty()) { - final int pageSize = 7; - final int numberOfPages = (foundOreVeins.size() + pageSize) / pageSize; // Equals to - // ceil((foundOreVeins.size()) - - for (int pageNumber = 0; pageNumber < numberOfPages; pageNumber++) { - final StringBuilder pageString = new StringBuilder(); - for (int i = 0; i < pageSize; i++) { - final int veinId = pageNumber * pageSize + i; - if (veinId < foundOreVeins.size()) { - final OreVeinPosition oreVein = foundOreVeins.get(veinId); - pageString.append(oreVein.getBlockX()).append(",").append(oreVein.getBlockZ()).append(" - ") - .append(oreVein.veinType.getVeinName()).append("\n"); - } - } - String pageCounter = numberOfPages > 1 ? String.format(" %d/%d", pageNumber + 1, numberOfPages) - : ""; - NBTTagString pageTag = new NBTTagString( - String.format("Ore Veins %s\n\n", pageCounter) + pageString); - bookPages.appendTag(pageTag); - } - } - - if (compound.hasKey(Tags.PROSPECTION_FLUIDS)) { - GTUtility.ItemNBT.fillBookWithList( - bookPages, - "Fluids%s\n\n", - "\n", - 9, - compound.getString(Tags.PROSPECTION_FLUIDS).split("\\|")); - - final String fluidCoverPage = "Fluid notes\n\n" + "Prospects from NW to SE 576 chunks" - + "(9 8x8 fields)\n around and gives min-max amount" - + "\n\n" - + "[1][2][3]" - + "\n" - + "[4][5][6]" - + "\n" - + "[7][8][9]" - + "\n" - + "\n" - + "[5] - Prospector in this 8x8 area"; - bookPages.appendTag(new NBTTagString(fluidCoverPage)); - - String tFluidsPosStr = "X: " + Math.floorDiv(blockX, 16 * 8) * 16 * 8 - + " Z: " - + Math.floorDiv(blockZ, 16 * 8) * 16 * 8 - + "\n"; - int xOff = blockX - Math.floorDiv(blockX, 16 * 8) * 16 * 8; - xOff = xOff / 16; - int xOffRemain = 7 - xOff; - - int zOff = blockZ - Math.floorDiv(blockZ, 16 * 8) * 16 * 8; - zOff = zOff / 16; - int zOffRemain = 7 - zOff; - - for (; zOff > 0; zOff--) { - tFluidsPosStr = tFluidsPosStr.concat("--------\n"); - } - for (; xOff > 0; xOff--) { - tFluidsPosStr = tFluidsPosStr.concat("-"); - } - - tFluidsPosStr = tFluidsPosStr.concat("P"); - - for (; xOffRemain > 0; xOffRemain--) { - tFluidsPosStr = tFluidsPosStr.concat("-"); - } - tFluidsPosStr = tFluidsPosStr.concat("\n"); - for (; zOffRemain > 0; zOffRemain--) { - tFluidsPosStr = tFluidsPosStr.concat("--------\n"); - } - tFluidsPosStr = tFluidsPosStr.concat( - " X: " + (Math.floorDiv(blockX, 16 * 8) + 1) * 16 * 8 - + " Z: " - + (Math.floorDiv(blockZ, 16 * 8) + 1) * 16 * 8); // +1 field to find bottomright of [5] - final String fluidsPage = "Corners of [5] are \n" + tFluidsPosStr - + "\n" - + "P - Prospector in 8x8 field"; - bookPages.appendTag(new NBTTagString(fluidsPage)); - } - - compound.setString("author", position); - compound.setTag("pages", bookPages); - setNBT(itemStack, compound); - - // Mimic original behaviour - itemStack.stackSize -= 1; - mOutputItems[0] = GTUtility.copyAmount(1L, itemStack); - calculateOverclockedNess(30, 1000); - // In case recipe is too OP for that machine - if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) { - cir.setReturnValue(FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS); - } else { - cir.setReturnValue(2); - } - } - } -} From 5179f7929e7d7bb5e6493c12381a2ad302ddf39f Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sat, 28 Feb 2026 14:36:03 +0100 Subject: [PATCH 105/132] update --- dependencies.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.jar | Bin 45633 -> 46175 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index fd899c53..1962ba52 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') - api('com.github.GTNewHorizons:GTNHLib:0.9.16:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.317:dev') + api('com.github.GTNewHorizons:GTNHLib:0.9.31:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.318:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f8e1ee3125fe0768e9a76ee977ac089eb657005e..61285a659d17295f1de7c53e24fdf13ad755c379 100644 GIT binary patch delta 37058 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 NNswbwE82Y!{{uvZmpcFe delta 36446 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 JWd7DQ`9Hc?h(rJY diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 23449a2b..37f78a6a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index 23a58cee..d1af4532 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.19' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.20' } From 6cc18935624f858205e77d80171f5e0139926f3c Mon Sep 17 00:00:00 2001 From: iouter <62897714+iouter@users.noreply.github.com> Date: Sat, 28 Mar 2026 11:21:50 +0800 Subject: [PATCH 106/132] [Sub-PR] Reduce the size of the GregTech.lang, and standardize the Line Break, etc. (#79) --- dependencies.gradle | 2 +- .../visualprospecting/database/veintypes/VeinType.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 1962ba52..2b3cf911 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') api('com.github.GTNewHorizons:GTNHLib:0.9.31:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.318:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.391:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 4bf24a5f..1b364a03 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -51,7 +51,7 @@ private VeinType() { public VeinType(OreMixBuilder oreMix) { name = oreMix.oreMixName; - localizedName = oreMix.localizedName; + localizedName = oreMix.getLocalizedName(); blockSize = oreMix.size; representativeOre = oreMix.representative; oresAsSet.add(primaryOre = oreMix.primary); From b69131b5e09c42c8e5490b7f091a7b6ed4be13ab Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Fri, 3 Apr 2026 22:50:40 +0200 Subject: [PATCH 107/132] update+gradle+deps+bs --- dependencies.gradle | 4 ++-- gradle/gradle-daemon-jvm.properties | 20 ++++++++++---------- gradle/wrapper/gradle-wrapper.jar | Bin 46175 -> 48966 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- settings.gradle | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 2b3cf911..e15f9412 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') - api('com.github.GTNewHorizons:GTNHLib:0.9.31:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.391:dev') + api('com.github.GTNewHorizons:GTNHLib:0.9.47:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.399:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) } diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties index 3590bb8a..991a69c7 100644 --- a/gradle/gradle-daemon-jvm.properties +++ b/gradle/gradle-daemon-jvm.properties @@ -1,12 +1,12 @@ #This file is generated by updateDaemonJvm -toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect -toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/93aeea858331bd6bb00ba94759830234/redirect -toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/4945f00643ec68e7c7a6b66f90124f89/redirect -toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect -toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/46949723aaa20c7b64d7ecfed7207034/redirect -toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d6690dfd71c4c91e08577437b5b2beb0/redirect -toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/4945f00643ec68e7c7a6b66f90124f89/redirect -toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/93aeea858331bd6bb00ba94759830234/redirect -toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/3cd7045fca9a72cd9bc7d14a385e594c/redirect -toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/0ef34dd9312b12d61ba1b8e66126d140/redirect +toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1630f7ebef05444cb27a2709ea0249b3/redirect +toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect +toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1630f7ebef05444cb27a2709ea0249b3/redirect +toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect +toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/d4fd992c9557644e637ebe98263e0ae7/redirect +toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/faa12903720d410b387cc69ccafb1a74/redirect +toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1630f7ebef05444cb27a2709ea0249b3/redirect +toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect +toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/a4c09dd2e2d7079373d30e524bbc2829/redirect +toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/8e1d9ee5d0f13e442218f6884a306da1/redirect toolchainVersion=25 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 61285a659d17295f1de7c53e24fdf13ad755c379..d997cfc60f4cff0e7451d19d49a82fa986695d07 100644 GIT binary patch delta 39855 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

    SdO`o?U^bCPz6Ehh!k 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


    Xdyd*p!l1Y@nCA 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37f78a6a..dbc3ce4a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index adff685a..0262dcbd 100755 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # 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 +# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/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/. diff --git a/settings.gradle b/settings.gradle index d1af4532..407aea22 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.20' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.24' } From 5febeee880fdd5de9789a01d3123bb2274258da8 Mon Sep 17 00:00:00 2001 From: Vincent Date: Thu, 16 Apr 2026 18:44:34 +0200 Subject: [PATCH 108/132] Prevent crash when search input is an invalid regex pattern (#80) --- src/main/java/com/sinthoras/visualprospecting/Utils.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 63b9d992..dd2543ca 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map; import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -244,6 +245,10 @@ private static ByteBuffer readFileToBuffer(File file) { if (searchString.isEmpty()) return null; final String unquotedRegex = SearchField.getPattern(searchString).pattern().replace("\\Q", "") .replace("\\E", ""); - return Pattern.compile(unquotedRegex, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + try { + return Pattern.compile(unquotedRegex, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + } catch (PatternSyntaxException e) { + return null; + } } } From 4d639b7693169fdd69d37bcd5db64d758a7ea509 Mon Sep 17 00:00:00 2001 From: UltraProdigy <187078471+UltraProdigy@users.noreply.github.com> Date: Sun, 26 Apr 2026 14:20:43 -0400 Subject: [PATCH 109/132] Optimize Images & Workflow (#81) --- .github/workflows/optimize-images.yml | 17 +++++++++++++++++ .../visualprospecting/textures/depleted.png | Bin 471 -> 347 bytes .../textures/icons/oreveins.png | Bin 5913 -> 5800 bytes .../textures/icons/undergroundfluid.png | Bin 1128 -> 1027 bytes .../textures/items/prospectorslog.png | Bin 627 -> 447 bytes .../textures/node_marked.png | Bin 1277 -> 998 bytes .../textures/node_unmarked.png | Bin 1353 -> 998 bytes 7 files changed, 17 insertions(+) create mode 100644 .github/workflows/optimize-images.yml diff --git a/.github/workflows/optimize-images.yml b/.github/workflows/optimize-images.yml new file mode 100644 index 00000000..16d85ce1 --- /dev/null +++ b/.github/workflows/optimize-images.yml @@ -0,0 +1,17 @@ +name: Optimize images + +on: + pull_request: + branches: [ master, main, release/** ] + paths: + - "**/*.png" + + push: + branches: [ master, main, release/** ] + paths: + - "**/*.png" + +jobs: + optimize-images: + uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/optimize-images.yml@master + secrets: inherit diff --git a/src/main/resources/assets/visualprospecting/textures/depleted.png b/src/main/resources/assets/visualprospecting/textures/depleted.png index 6c7dbc6d9de3790d8af9eb611c44840a2eb3e011..05b31f6ed56280ee6a6d608c4253ff686e3b49b9 100644 GIT binary patch delta 226 zcmV<803H9=1KR?SB#|~yks}j-zez+vR9M5+S1}U6APDn6d;lNC|L^ z4?=`Up{Qy>p6&w?DG_OQpfB9cNJLabQc28kheq#VX3Y#fBJpXIkqHa#($Gu7in;BO z8GI^2FNs}@FhJBd1*o;=CZ3YYNY=vjjOu2oXl9-Uh>F(qtZJ=Cf}06dSjyq;8L8dP z(>4D?09pd52%*mq+K6_5S6SL_#hzQObYlJ)MQ-Eqy=NeSj%4tm6h4+)7Ko#Z$rY>F c70W5&JWSke)Rs+Rz5oCK07*qoM6N<$f-D1R;s5{u delta 365 zcmV-z0h0dP0@nkOBo78+OGiWi{{a60|De66laV1)e*rs5L_t(o!^M}e62l+}hLP*z zIL5(@KDeuc8GV}!cCyzdjR=y~DVMW+e*u4tskOpC7am_&Ypbx*lXa0>8-W4z!xMf8GCj|fic<-xoPUHg= ze8>kJEplt#>+F;gdz9nMWkTYZ zM-iwAmxw?uLy^vo?yXn~r$h|hif7@YaZksv)kf>Pkcw;m{dxWbrTJtj)u)4400000 LNkvXXu0mjfD8i-o diff --git a/src/main/resources/assets/visualprospecting/textures/icons/oreveins.png b/src/main/resources/assets/visualprospecting/textures/icons/oreveins.png index 08cf2ea235c5a019f7f95cc4e751d1365633014e..8775a1b364f91010aacec931a18c878634ba36a5 100644 GIT binary patch delta 318 zcmV-E0m1&6E~qWALlu)%6(^HI6%u~|7D+@wRA}DqSOE%yFbq_wZ0uD&OqkAx^d7ZQfSgJNM zwY-rlzOLfW_9(MZcuKY4YE#oR3%Mx&lRTqo7TVM7RK5?$yT8`#)CrJd^UDVd%`R&r zdpG|K#711-h(@PkoKEQp13xYW!+TXGPU*@{dlkaJ5z>%07*qoM6N<$f}(_ty8r+H delta 444 zcmV;t0Ym<%EtxK`LlqAOVoOIv00000008+zyML2F6)JxLheqf^Vy{@%?1qq9@zHqe*kX7u}YnR9C!v6(Y1Xr zfMu|@e;t1|F~3^PsXI23vS6F84^4@MYQRT3o{hmm#lQ(VRW>#75tYp<2@4*{x|dW+ zswAx=zqO=8@w$@bbVTa2Jk#DpG% z@AA&Mx*2xB4e;4eYzi%OPByQAopWvgI0Ze}Y24YJ`L;wH)0002_L%V+f00G)bL_t(&-tE^tYZOrw z#_@arKY^8>!N$hg&Q1^!K}1q)lWMVug@sKBf{0B*P$H28Qv?YrDENwnV50b1m?DaX zh)Gmp5_g-Q%~=?RS(g;Lci=v7*mLLHyFCAy`!X{ykd>8{m6esXJ7IsM&gO^E!WNo! z1UM7`ofxbm#Qg%mMjZhfrKd1cC-Zkp=3CfGdA>Iyzg;r@Bo=a~J(QaHv)IJvvhhNn zYspR{tYA3u4J_b5MZcc`a4Qw#v)Bn!Z!nJSzx2Ntedqga{6=X`zr=6+z-W)L&-=Cp zFkLeK3P*7ezc7i}9{+za(=YSi3dY~zc%e2NclI=vQUw^t5>8dr<}ns|J5_*2XQ!#C zeZq;zmvJ)HCotWm)+*$4m`DmBPT4yVjZ$q8tA+L`7E%N_7f}Y7j4kwhw7>Q^3z7qP zjSE=EGmJ%kxGn%Y*pI0=$oAqGoxeYo@k;C%(am#BS@ccWvaF(0svGbsS9R{*r5 z*1}xHm^}e-GX;Ql1wadn@p~1QD`Ghoc=`HUT>qZ{oBtvPva+(Wva+(WvUa6ETmame U^vfN)00000Nks-uM6N<$f>HzUkN^Mx delta 629 zcmV-*0*d{E2`m( z5TiibnVaC5nVN6&YjYl4E?2GhdcAotA6)La=gbV}H*@CBy%32+B9Tbs?~ru8mXq(6 zv?OU>(xrb|6wu}ZidSbXig=w6kS}Mfx+-aSmax}J>aV5QA5N9flBD^N>;0nJFH=d6 z_(m>1cZZhz6-jfFrqYQg+B``3`$H2jE$On`c}edjHD$D$bpbCzNqj)kq9-*jsaMj% z3hi%s+rerl{xnt7IZ3}HeV24&mA>z)wg)8jr4oN1lXO;6v!tJr?n@e2WsH*Rzpl*W zzX7L#df*GtVP^Zy>d1%S5< z`$k?9$_e}_NhBe2&?ChI@-0E~Gqd*pC19=+rD{&)h!x;MxDK1| zS+N3KlNeI2e@axErh$}Y31I=T2?pQ=Lm{-Vu4@S17oX1ufQJDK+qQ-HLTn?p75^Q= z$pQF<;0xgjX)(PXd%CDPPB9;VFN7wb5W@Z%P7dH8bkw1R=>Tky*uwMx6cSsQE?}|$ Zj(>l{6YZx2`KkZ_002ovPDHLkV1j1AjyV7T delta 521 zcmV+k0`~pC1M>usBo78+OGiWi{{a60|De66laV1*e*xA>L_t(o!`+v$N&_(%fWJFy zQA)M-gn~*t6m+uq1iHJsxrk37y67UhI7wF##HE|7xJzF^baGH=DWYPr4n=IKanO`r zyvyCSLa+W%2uG6t|Gp$7HG~lKGfes%kzOa5n;CUfcw2cl{-*(zcxho=+t16ypBgwm z-(oWNe-vnp;dKi95(88|TU=bcu(Ja%*C_xluimtKq9+44clGuUV8$F`d3locmesw1 zAjGl=8B3ZY&&@>7dtg2rV?G-L;Gx=ZEzZ@z?DU9i3mx&zUA>)1jcToll^AX( z?ChtGQ%#tD)>%&KL?n~z4CzdmKjb2pjgeC-e^)2yY*%Z|U&-AJb&i{eN0^95NF}2p zm5d70PvvS`CUzp%72&oA1Yn~FNX8?MYv`q1cS-bgp zZvYl^V*u0A;J>900000 LNkvXXu0mjfWufd= diff --git a/src/main/resources/assets/visualprospecting/textures/node_marked.png b/src/main/resources/assets/visualprospecting/textures/node_marked.png index 68c4cef35c1b4a4a6566bbfa105a462fbf3cd1cb..2f2e7cd2db1347f85a22c41bff271e827caf77d2 100644 GIT binary patch delta 487 zcmV?>N$*M5+B-k~ww)Frs~az(*ZW zCsc)cpc>Sh)KFhVW7@GkEZxv)f+|rj)TgIj^lh>PXok8Cfb3FhE1Ls!i@JYK2+Gyk z-cALZqiTz@JE}mXs1OyPJW@b?DUG>X?6f}eF`ygN(c<6>6%Vi*)3;rATc4XDu;&hg z7gRLC%0*;L@^S73-7&MzQA=jua!+Zd`xxLKf1~y@MxQ6 zjUGbidd@ks9W%|h$JKTy^jm+Dd7z~&nMnir33h>%nh-s1Qf|P1RkR{-B=98WfRY~y zuyPX)m(olTdDay>02~Who)46x{>cr%ktXCG2cX2->?|AtE*RShs2VUkQ-^?4##RB9 zFlJ}y5OB!Y9zb=M*%>$l95A*9s8}>RJ%@lj#`abTtZqxF`_rilYwA}H4s}PfuH;8u zdZ{vjS63pbEJD?l`6@3`)Lm7nybM%%-D*JVxX>1s%>5?=A$sU|lo1XW_n*B4a2*ee d0{G%jx4)ofeV4q#4}t&y002ovPDHLkV1ntG-?9Jz delta 780 zcmV+n1M~dm2mJ}Kv;hwWVoOIv00000008+zyML3h0Z)Gd)k#D_R9M5^nK4KlK@^6+ zoyve{t0`=()&o1?Oc%xOKoY_s2sSo?g#>JZ#KLffLY@%5j;F0d2DG;#&D33I>#FivN51Z+hy?>Y)>6CMG} zz!UP(N1z_X9JUQ?6BdCLU@#-(1lW`Lc?z5Zm(tb`3;`oD&nJOWMnB(yS`@Q+Ct#cK z0C)+!$Ow50Y)3H%El#V)z$`GI5%L;%6~+9xHL!oc)_~`p=J&ux6w_?8!jyp}V8+w@ z23X00_I0*y6Rdi^%Jk@{Y{H`St@Ew7(t&>YvrVYv^uu8jDw0FzUHt2mkZSNj{a|0@ z^L!#l*@P*XhGXhSeCAdUquyIqu-|~SykP+($C~6!H7HE}Md3D|ByVL*$vNK$FX(FU zubO|D(@1YhCBnyMoV|fwZZ{}SI`_CR-i&ZnFAD9}*)~VHDGQUUDu9tK;oOZgU#t1KFpf>H#KO3G|%`#w|17oVofPghiuc6CiA_|4_pI=>rW{0i)@#^C|T zI@q~Pd}(v+T0z&W?ES4RYd&&!ZKc~d2tWP?<~>HAxy%vHyZ%o!C>7Y*03maxK$nft zLkV5?K3BG8rNiTKYDx<2wxoX_XzfU@w1Hs;JGc)uC3;*mZ4myd?1R9W!n5=T9K)pG zKHQY#a`Yu)sJik9fOAFVB~CQzA8p_wX^Qq(I1$#qaUT)zK49BAsRn#w5fN|^u$`Th zFurjT5%45nyE&=5d}A6Ba2l{xPKrg}IEn~(6tF!_0-HM$=Kgf%!kSmP#9=Nq+Y&$K z~f#S%jJ^^G#l)n7gVnc^PQ(y48cWaiOhjS^Q51O7yVtD5E5o_@BKLa2pSc d3i#kpx4%8_`PRpS>?r^M002ovPDHLkV1jzN;0OQ! delta 857 zcmV-f1E&1u2gwSsv;hwWVoOIv00000008+zyML3h0Z)GeAxT6*R9M5^nK4KlQ4oed zA1MrowrXKxry$b^XGjypE+9$}K}cf}!GH)hQM6FhMhJp}7B&GPNKgbjQJbI#HV;8N z8w+Er2(e6&IoXVF(erNa_VSne-tK-oJ3IU4e^nG9?|m)M31omapc$wKYIMpSa1C4l zr$81s5Rre|m)^7Lg`j;vKhOhI=Xv@)umfz0$X24j-usWhFwjA9bPTMD$hV>bd+*-> z<3KOTXd74*k)wivz4s%)B+w8ur0n1AY(Jy-g`S?~Q%U;=2243B9wnRqh7nzPI1@Ch&@BD+a^ao+p) zz%RRyZS5A%VY=+F0|X%GXw3(T9ty~_3|!o#*26zc=a6M97}5g|4gSsU2j?Gojay?2K) zK18_R{uBzWvqdO*>*jDjfYT*nj~U#c{IU!^-uqgo>)GfM@hsopZ9-8#)OAWu)j+4y zMM+fqq(_z|S9MZkZSrP*l@7S&~nfGtbCi!_Wm-J}TEveY;# zOio+zsOnP0XIbu?`UX)or3l!vTst*6qH0MIuw}V$>d5?4oKpmBSx#M`ICrH8*s^3D zaG(uePOaLCmsQFT^)T*%1E$XeG2{@SlcvA_{uU?Bj# zmPAhLHP-^L3n5=5&b^$~rf5{w<}kTW3S({U3&Q;FYC+%fLWa&Zdk3uZ(T4 j0C;6=EC#?!zIFQtuR1S;u+2g$00000NkvXXu0mjfLm-m| From 3dc0de6f45d12df31186868b9e4319fe0022f31b Mon Sep 17 00:00:00 2001 From: Algent Date: Thu, 14 May 2026 17:26:28 +0200 Subject: [PATCH 110/132] Add cleanup of VP files on WorldDeletionEvent (#82) --- dependencies.gradle | 2 +- .../sinthoras/visualprospecting/VPMod.java | 4 +- .../hooks/HooksEventBus.java | 54 +++++++++++++++++++ .../utils/VPSaveCleanupUtils.java | 41 ++++++++++++++ 4 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/utils/VPSaveCleanupUtils.java diff --git a/dependencies.gradle b/dependencies.gradle index e15f9412..3916d5ad 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,6 +1,6 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.0.17:dev') - api('com.github.GTNewHorizons:GTNHLib:0.9.47:dev') + api('com.github.GTNewHorizons:GTNHLib:0.9.57:dev') api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.399:dev') runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) diff --git a/src/main/java/com/sinthoras/visualprospecting/VPMod.java b/src/main/java/com/sinthoras/visualprospecting/VPMod.java index 7949ae8c..b2d2ff08 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VPMod.java +++ b/src/main/java/com/sinthoras/visualprospecting/VPMod.java @@ -22,7 +22,9 @@ version = Tags.VERSION, name = Tags.MODNAME, acceptedMinecraftVersions = "[1.7.10]", - dependencies = "required-after:gregtech;" + "required-after:NotEnoughItems;" + "after:navigator;") + dependencies = "required-after:gregtech;" + "required-after:NotEnoughItems;" + + "required-after:gtnhlib;" + + "after:navigator;") public class VPMod { @SidedProxy(clientSide = Tags.GROUPNAME + ".hooks.HooksClient", serverSide = Tags.GROUPNAME + ".hooks.HooksShared") diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java index 7f9350f9..23ae39ac 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksEventBus.java @@ -1,12 +1,29 @@ package com.sinthoras.visualprospecting.hooks; +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.UUID; + +import net.minecraft.client.Minecraft; import net.minecraftforge.event.world.WorldEvent; +import org.apache.commons.io.FileUtils; + +import com.gtnewhorizon.gtnhlib.client.event.WorldDeletionEvent; +import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.ServerCache; +import com.sinthoras.visualprospecting.utils.VPSaveCleanupUtils; import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; public class HooksEventBus { @@ -21,4 +38,41 @@ public void onEvent(WorldEvent.Unload event) { public void onEvent(WorldEvent.Save event) { ServerCache.instance.saveVeinCache(); } + + @SideOnly(Side.CLIENT) + @SubscribeEvent + public void onWorldDeletionEvent(WorldDeletionEvent event) { + File mcDataDir = Minecraft.getMinecraft().mcDataDir; + Path vpBasePath = mcDataDir.toPath().resolve(Tags.MODID); + String currentUsername = Minecraft.getMinecraft().getSession().getUsername(); + + String worldId = VPSaveCleanupUtils.getVisualProspectingWorldId(mcDataDir, event.worldName); + if (worldId == null) { + VP.LOG.warn("Unable to read VP worldID for world \"{}\", can't cleanup any VP data", event.worldName); + return; + } + Path vpServerPathFull = vpBasePath.resolve("server").resolve(worldId); + if (Files.isDirectory(vpServerPathFull)) { + try { + FileUtils.deleteDirectory(vpServerPathFull.toFile()); + } catch (IOException e) { + VP.LOG.warn("Failed to delete Visual Prospecting server data found at {}", vpServerPathFull); + } + } + + UUID userUUID = Minecraft.getMinecraft().getSession().func_148256_e().getId(); + if (userUUID == null) { + VP.LOG.debug("Unable to read userUUID for current user. Attempting to use fallback instead"); + userUUID = UUID.nameUUIDFromBytes(("OfflinePlayer:" + currentUsername).getBytes(UTF_8)); + } + Path vpClientPathFull = vpBasePath.resolve("client").resolve(userUUID.toString()).resolve(worldId); + if (Files.isDirectory(vpClientPathFull)) { + try { + FileUtils.deleteDirectory(vpClientPathFull.toFile()); + } catch (IOException e) { + VP.LOG.warn("Failed to delete Visual Prospecting client data found at {}", vpClientPathFull); + } + } + + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/utils/VPSaveCleanupUtils.java b/src/main/java/com/sinthoras/visualprospecting/utils/VPSaveCleanupUtils.java new file mode 100644 index 00000000..be4e78fe --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/utils/VPSaveCleanupUtils.java @@ -0,0 +1,41 @@ +package com.sinthoras.visualprospecting.utils; + +import java.io.File; +import java.io.FileInputStream; + +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; + +import com.sinthoras.visualprospecting.database.WorldIdHandler; + +public final class VPSaveCleanupUtils { + + /** + * The name of save folder is created in {@link WorldIdHandler} by combining world name and a randomly generated + * UUID. The value is then saved into visualprospecting.dat file so we have to go read it there. + * + * @param mcDataDir Full path to Minecraft instance + * @param worldFolder Directory name for world we want the VP worldId of + * @return worldId VP value for this world + */ + public static String getVisualProspectingWorldId(File mcDataDir, String worldFolder) { + File vpDat = mcDataDir.toPath().resolve("saves").resolve(worldFolder).resolve("data") + .resolve("visualprospecting.dat").toFile(); + if (!vpDat.exists()) { + return null; + } + + try (FileInputStream vpFIS = new FileInputStream(vpDat)) { + NBTTagCompound vpNBT = CompressedStreamTools.readCompressed(vpFIS); + if (vpNBT.hasKey("data")) { + NBTTagCompound data = vpNBT.getCompoundTag("data"); + if (data.hasKey("wId")) { + return data.getString("wId"); + } + } + return null; + } catch (Exception e) { + return null; + } + } +} From 219adc58e013eb7c91a35770cfe1a670b3e591aa Mon Sep 17 00:00:00 2001 From: Algent Date: Fri, 15 May 2026 06:35:38 +0200 Subject: [PATCH 111/132] Fix registering vein on VeinGenerateEvent (#83) --- .../visualprospecting/database/ServerCache.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java index 86a52a6a..a1f7b3c0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java @@ -47,13 +47,11 @@ public synchronized void notifyOreVeinGeneration(int dimensionId, int chunkX, in @SubscribeEvent public void onVeinGenerated(VeinGenerateEvent event) { if (event.result == WorldgenGTOreLayer.ORE_PLACED && !event.layer.mWorldGenName.equals("NoOresInVein")) { - if (event.chunkX == event.oreSeedX && event.chunkZ == event.oreSeedZ) { - notifyOreVeinGeneration( - event.world.provider.dimensionId, - event.oreSeedX, - event.oreSeedZ, - event.layer.mWorldGenName); - } + notifyOreVeinGeneration( + event.world.provider.dimensionId, + event.oreSeedX, + event.oreSeedZ, + event.layer.mWorldGenName); } } From bd76fc55c6c92820e4bb4ddc57db16dc4d576039 Mon Sep 17 00:00:00 2001 From: Algent Date: Mon, 25 May 2026 18:09:12 +0200 Subject: [PATCH 112/132] Add team sharing of players prospection findings using GTNHLib Teams (#85) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- README.md | 12 +- dependencies.gradle | 8 +- .../sinthoras/visualprospecting/Config.java | 18 + .../sinthoras/visualprospecting/Utils.java | 7 + .../VisualProspecting_API.java | 26 +- .../database/ClientCache.java | 95 ++--- .../database/DimensionCache.java | 39 +- .../database/ServerCache.java | 3 +- .../visualprospecting/hooks/HooksShared.java | 28 ++ .../minecraft/ItemEditableBookMixin.java | 16 +- .../network/ProspectingNotification.java | 8 + .../network/ProspectingRequest.java | 7 +- .../network/TeamCatchupNotification.java | 47 +++ .../network/VeinDepletionMessage.java | 69 ++++ .../task/SnapshotDownloadTask.java | 3 + .../task/SnapshotUploadTask.java | 4 + .../teams/TeamCatchupHandler.java | 190 ++++++++++ .../teams/TeamClearCommand.java | 112 ++++++ .../teams/TeamInfoCommand.java | 194 ++++++++++ .../teams/TeamProspectionData.java | 349 ++++++++++++++++++ .../teams/TeamProspectionDispatcher.java | 125 +++++++ .../utils/VPByteBufUtils.java | 4 +- .../assets/visualprospecting/lang/en_US.lang | 13 + 23 files changed, 1295 insertions(+), 82 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/network/TeamCatchupNotification.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/network/VeinDepletionMessage.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/teams/TeamClearCommand.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/teams/TeamInfoCommand.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionData.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java diff --git a/README.md b/README.md index f8cebd77..87928845 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This mod is intended for player convenience, but may also be used as API, since it provides the location of all GT ore veins in a cache. VisualProspecting tracks all GT Ore Veins a player has found and visualizes them in JourneyMap and/or XaeroWorldMap (optional, if installed). It also visualizes tracked Thaumcraft aura nodes if TCNodeTracker if installed. VoxelMap will add waypoints for prospected ore veins and fluids. VisualProspecting tracks all ores that a player interacted with, by right or by left click. It also integrates prospecting data from GTs _Advanced Seismic Prospector_, although only books that are created after this mod was added will provide integration. -You may share your findings with other players by crafting a _Prospector's Log_. +You may share your findings with other players by crafting a _Prospector's Log_, or automatically with your GTNHLib team (see [Team Sharing](#team-sharing)). This mod is tailored to _GregTech: New Horizons 2_, but feel free to use it however you like. Even though this mod is build against the custom GT5U from GT:NH, it should still work fine with other GT5U versions. @@ -44,6 +44,16 @@ _Thaumcraft aura nodes in JourneyMap overlay. You may double-click an aura node _Thaumcraft aura nodes in XaeroWorldMap overlay_ +### Team Sharing + +If you belong to a [GTNHLib](https://github.com/GTNewHorizons/GTNHLib) team, all prospection findings (ore veins, underground fluids, vein-depletion toggles) are automatically shared with online team members, and replayed to teammates when they next log in. This replaces the standalone _SharedProspecting_ mod. + +Disable via `B:enableTeamSharing=false` in `config/visualprospecting.cfg`. + +Admin commands: + - `/vp_team_info [player] [detailed]`: inspect a team's prospection record. + - `/vp_team_clear `: wipe a team's server-side prospection record (op/console). + ### Reset Progress You may use JourneyMap's Actions Menu to achieve this or type `/visualprospectingresetprogress` in chat. Beware, there are no backups! Please use at your own risk. diff --git a/dependencies.gradle b/dependencies.gradle index 3916d5ad..98ab7936 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { - api('com.github.GTNewHorizons:Navigator:1.0.17:dev') - api('com.github.GTNewHorizons:GTNHLib:0.9.57:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.399:dev') + api('com.github.GTNewHorizons:Navigator:1.1.3:dev') + api('com.github.GTNewHorizons:GTNHLib:0.10.6:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.548:dev') - runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.6')) + runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.16')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index 6f6c279d..2465340a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -10,6 +10,8 @@ public class Config { private static class Defaults { public static final boolean enableProspecting = true; + public static final boolean enableTeamSharing = true; + public static final boolean keepProspectionOnTeamLeave = true; public static final int cacheGenerationLogUpdateMinTime = 5; public static final boolean recacheVeins = false; public static final int minDelayBetweenVeinRequests = 2000; @@ -30,6 +32,8 @@ private static class Categories { } public static boolean enableProspecting = Defaults.enableProspecting; + public static boolean enableTeamSharing = Defaults.enableTeamSharing; + public static boolean keepProspectionOnTeamLeave = Defaults.keepProspectionOnTeamLeave; public static int cacheGenerationLogUpdateMinTime = Defaults.cacheGenerationLogUpdateMinTime; public static boolean recacheVeins = Defaults.recacheVeins; public static int minDelayBetweenVeinRequests = Defaults.minDelayBetweenVeinRequests; @@ -52,6 +56,20 @@ public static void syncronizeConfiguration(File configFile) { "[CLIENT] You may want to disable prospecting for low-performance clients."); enableProspecting = enableProspectingProperty.getBoolean(); + Property enableTeamSharingProperty = configuration.get( + Categories.general, + "enableTeamSharing", + Defaults.enableTeamSharing, + "[SERVER] Share prospecting data automatically between members of a GTNHLib team."); + enableTeamSharing = enableTeamSharingProperty.getBoolean(); + + Property keepProspectionOnTeamLeaveProperty = configuration.get( + Categories.general, + "keepProspectionOnTeamLeave", + Defaults.keepProspectionOnTeamLeave, + "[SERVER] Allow the player leaving a team to keep a copy of the team prospection data into their new solo team."); + keepProspectionOnTeamLeave = keepProspectionOnTeamLeaveProperty.getBoolean(); + Property cacheGenerationLogUpdateMinTimeProperty = configuration.get( Categories.general, "cacheGenerationLogUpdateMinTime", diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index dd2543ca..d5694223 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -26,6 +26,8 @@ import net.minecraft.client.Minecraft; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IChatComponent; import net.minecraft.world.storage.ThreadedFileIOBase; import org.jetbrains.annotations.NotNull; @@ -232,6 +234,11 @@ private static ByteBuffer readFileToBuffer(File file) { } } + public static void sendChatMessage(IChatComponent msg, boolean italic, EnumChatFormatting color) { + msg.getChatStyle().setItalic(italic).setColor(color); + Minecraft.getMinecraft().thePlayer.addChatMessage(msg); + } + public static @Nullable Pattern getNEISearchPattern() { final String searchString = NEIClientConfig.getSearchExpression().toLowerCase(); if (!SearchField.searchInventories() || searchString.isEmpty()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java b/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java index 227e9deb..71eb20b0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java +++ b/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java @@ -11,7 +11,8 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; -import com.sinthoras.visualprospecting.network.ProspectingNotification; +import com.sinthoras.visualprospecting.network.VeinDepletionMessage; +import com.sinthoras.visualprospecting.teams.TeamProspectionDispatcher; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -41,17 +42,26 @@ public static UndergroundFluidPosition getUndergroundFluid(int dimensionId, int public static void setOreVeinDepleted(int dimensionId, int blockX, int blockZ) { final OreVeinPosition oreVeinPosition = ClientCache.instance .getOreVein(dimensionId, Utils.coordBlockToChunk(blockX), Utils.coordBlockToChunk(blockZ)); - if (!oreVeinPosition.isDepleted()) { - oreVeinPosition.toggleDepleted(); - } + if (oreVeinPosition == OreVeinPosition.EMPTY_VEIN) return; + if (oreVeinPosition.isDepleted()) return; + oreVeinPosition.toggleDepleted(); ClientCache.instance.putOreVeins(Collections.singletonList(oreVeinPosition)); + VP.network.sendToServer( + new VeinDepletionMessage(dimensionId, oreVeinPosition.chunkX, oreVeinPosition.chunkZ, true)); } public static void toggleOreVeinDepleted(OreVeinPosition oreVeinPosition) { oreVeinPosition = ClientCache.instance .getOreVein(oreVeinPosition.dimensionId, oreVeinPosition.chunkX, oreVeinPosition.chunkZ); + if (oreVeinPosition == OreVeinPosition.EMPTY_VEIN) return; oreVeinPosition.toggleDepleted(); ClientCache.instance.putOreVeins(Collections.singletonList(oreVeinPosition)); + VP.network.sendToServer( + new VeinDepletionMessage( + oreVeinPosition.dimensionId, + oreVeinPosition.chunkX, + oreVeinPosition.chunkZ, + oreVeinPosition.isDepleted())); } public static void putProspectionResults(List oreVeins, @@ -80,13 +90,7 @@ public static void notifyOreGeneration(int dimensionId, int blockX, int blockZ, public static void sendProspectionResultsToClient(EntityPlayerMP player, List oreVeins, List undergroundFluids) { - // Skip networking if in single player - if (Utils.isLogicalClient()) { - ClientCache.instance.putOreVeins(oreVeins); - ClientCache.instance.putUndergroundFluids(undergroundFluids); - } else { - VP.network.sendTo(new ProspectingNotification(oreVeins, undergroundFluids), player); - } + TeamProspectionDispatcher.deliverProspectingResults(player, oreVeins, undergroundFluids); } public static List prospectOreVeinsWithinRadius(int dimensionId, int blockX, int blockZ, diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java index 2eb7b204..80449f74 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ClientCache.java @@ -22,6 +22,7 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; import com.sinthoras.visualprospecting.network.ProspectingRequest; +import com.sinthoras.visualprospecting.network.VeinDepletionMessage; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import gregtech.api.events.OreInteractEvent; @@ -52,54 +53,57 @@ protected File getStorageDirectory() { private void notifyNewOreVein(OreVeinPosition oreVeinPosition) { final String location = "(" + (oreVeinPosition.getBlockX() + 8) + "," + (oreVeinPosition.getBlockZ() + 8) + ")"; - final IChatComponent veinNotification = new ChatComponentTranslation( - "visualprospecting.vein.prospected", - oreVeinPosition.veinType.getVeinName(), - location); - veinNotification.getChatStyle().setItalic(true); - veinNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); - Minecraft.getMinecraft().thePlayer.addChatMessage(veinNotification); + Utils.sendChatMessage( + new ChatComponentTranslation( + "visualprospecting.vein.prospected", + oreVeinPosition.veinType.getVeinName(), + location), + true, + EnumChatFormatting.GRAY); final String oreNames = String.join(", ", oreVeinPosition.veinType.getOreMaterialNames()); - final IChatComponent oresNotification = new ChatComponentTranslation( - "visualprospecting.vein.contents", - oreNames); - oresNotification.getChatStyle().setItalic(true); - oresNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); - Minecraft.getMinecraft().thePlayer.addChatMessage(oresNotification); + Utils.sendChatMessage( + new ChatComponentTranslation("visualprospecting.vein.contents", oreNames), + true, + EnumChatFormatting.GRAY); } public void putOreVeins(List oreVeinPositions) { + putOreVeins(oreVeinPositions, false); + } + + public void putOreVeins(List oreVeinPositions, boolean silent) { + int newOreVeins = 0; + for (OreVeinPosition vein : oreVeinPositions) { + if (putOreVein(vein) == DimensionCache.UpdateResult.AlreadyKnown) continue; + MinecraftForge.EVENT_BUS.post(new ProspectingNotificationEvent.OreVein(vein)); + newOreVeins++; + } + if (silent || newOreVeins == 0) return; + if (oreVeinPositions.size() == 1) { - final OreVeinPosition oreVeinPosition = oreVeinPositions.get(0); - if (putOreVein(oreVeinPosition) != DimensionCache.UpdateResult.AlreadyKnown) { - MinecraftForge.EVENT_BUS.post(new ProspectingNotificationEvent.OreVein(oreVeinPosition)); - notifyNewOreVein(oreVeinPosition); - } - } else if (oreVeinPositions.size() > 1) { - int newOreVeins = 0; - for (OreVeinPosition oreVeinPosition : oreVeinPositions) { - if (putOreVein(oreVeinPosition) != DimensionCache.UpdateResult.AlreadyKnown) { - MinecraftForge.EVENT_BUS.post(new ProspectingNotificationEvent.OreVein(oreVeinPosition)); - newOreVeins++; - } - } - if (newOreVeins > 0) { - final IChatComponent oreVeinNotification = new ChatComponentTranslation( - "visualprospecting.veins.prospected", - newOreVeins); - oreVeinNotification.getChatStyle().setItalic(true); - oreVeinNotification.getChatStyle().setColor(EnumChatFormatting.GRAY); - Minecraft.getMinecraft().thePlayer.addChatMessage(oreVeinNotification); - } + notifyNewOreVein(oreVeinPositions.get(0)); + } else { + Utils.sendChatMessage( + new ChatComponentTranslation("visualprospecting.veins.prospected", newOreVeins), + true, + EnumChatFormatting.GRAY); } } public void toggleOreVein(int dimensionId, int chunkX, int chunkZ) { super.toggleOreVein(dimensionId, chunkX, chunkZ); + OreVeinPosition vein = getOreVein(dimensionId, chunkX, chunkZ); + if (vein != OreVeinPosition.EMPTY_VEIN) { + VP.network.sendToServer(new VeinDepletionMessage(dimensionId, chunkX, chunkZ, vein.isDepleted())); + } } public void putUndergroundFluids(List undergroundFluids) { + putUndergroundFluids(undergroundFluids, false); + } + + public void putUndergroundFluids(List undergroundFluids, boolean silent) { int newUndergroundFluids = 0; int updatedUndergroundFluids = 0; for (UndergroundFluidPosition undergroundFluidPosition : undergroundFluids) { @@ -114,6 +118,7 @@ public void putUndergroundFluids(List undergroundFluid updatedUndergroundFluids++; } } + if (silent) return; IChatComponent undergroundFluidsNotification = null; if (newUndergroundFluids > 0 && updatedUndergroundFluids > 0) { @@ -121,22 +126,18 @@ public void putUndergroundFluids(List undergroundFluid "visualprospecting.undergroundfluid.prospected.newandupdated", newUndergroundFluids, updatedUndergroundFluids); - } else { - if (newUndergroundFluids > 0) { - undergroundFluidsNotification = new ChatComponentTranslation( - "visualprospecting.undergroundfluid.prospected.onlynew", - newUndergroundFluids); - } - if (updatedUndergroundFluids > 0) { - undergroundFluidsNotification = new ChatComponentTranslation( - "visualprospecting.undergroundfluid.prospected.onlyupdated", - updatedUndergroundFluids); - } + } else if (newUndergroundFluids > 0) { + undergroundFluidsNotification = new ChatComponentTranslation( + "visualprospecting.undergroundfluid.prospected.onlynew", + newUndergroundFluids); + } else if (updatedUndergroundFluids > 0) { + undergroundFluidsNotification = new ChatComponentTranslation( + "visualprospecting.undergroundfluid.prospected.onlyupdated", + updatedUndergroundFluids); } if (undergroundFluidsNotification == null) return; - undergroundFluidsNotification.getChatStyle().setItalic(true).setColor(EnumChatFormatting.GRAY); - Minecraft.getMinecraft().thePlayer.addChatMessage(undergroundFluidsNotification); + Utils.sendChatMessage(undergroundFluidsNotification, true, EnumChatFormatting.GRAY); } @SubscribeEvent diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index dbbfbae2..2bbe55db 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -154,6 +154,7 @@ public void loadFromNbt(NBTTagCompound compound) { NBTTagList veinTypeNamesList = ores.getTagList("veinTypeNames", 8); int size = chunkXArray.length; + int unknownVeinTypes = 0; // Pre-size HashMap to avoid rehashing during bulk load oreChunks.ensureCapacity(oreChunks.size() + size); @@ -165,11 +166,21 @@ public void loadFromNbt(NBTTagCompound compound) { boolean depleted = depletedFlags[i] == 1; String veinTypeName = veinTypeNamesList.getStringTagAt(i); VeinType veinType = VeinTypeCaching.getVeinType(veinTypeName); + if (veinType == VeinType.NO_VEIN) { + unknownVeinTypes++; + continue; + } oreChunks.put( getOreVeinKey(chunkX, chunkZ), new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); } + if (unknownVeinTypes > 0) { + VP.LOG.warn( + "Dimension {}: skipped {} entries with unknown vein type names while loading cache.", + dimensionId, + unknownVeinTypes); + } } else { // LEGACY PATH: Backward compatibility for old nested compound format for (NBTBase base : (Collection) ores.tagMap.values()) { @@ -180,10 +191,11 @@ public void loadFromNbt(NBTTagCompound compound) { VeinType veinType; if (veinCompound.hasKey("veinTypeId")) { veinType = getVeinFromId(veinCompound.getShort("veinTypeId")); - if (veinType == null) return; + if (veinType == null) continue; markDirty(); } else { veinType = VeinTypeCaching.getVeinType(veinCompound.getString("veinTypeName")); + if (veinType == VeinType.NO_VEIN) continue; } oreChunks.put( @@ -204,6 +216,7 @@ public void loadFromNbt(NBTTagCompound compound) { NBTTagList fluidNamesList = fluids.getTagList("fluidNames", 8); int fluidCount = chunkXArray.length; + int unknownFluids = 0; // Pre-size HashMap to avoid rehashing during bulk load undergroundFluids.ensureCapacity(undergroundFluids.size() + fluidCount); @@ -214,6 +227,10 @@ public void loadFromNbt(NBTTagCompound compound) { int chunkZ = chunkZArray[fluidIndex]; // Cache-friendly array access String fluidName = fluidNamesList.getStringTagAt(fluidIndex); Fluid fluid = FluidRegistry.getFluid(fluidName); + if (fluid == null) { + unknownFluids++; + continue; + } // Reconstruct 2D chunk array from flattened data int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; @@ -231,6 +248,12 @@ public void loadFromNbt(NBTTagCompound compound) { getUndergroundFluidKey(chunkX, chunkZ), new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); } + if (unknownFluids > 0) { + VP.LOG.warn( + "Dimension {}: skipped {} entries with unknown fluid names while loading cache.", + dimensionId, + unknownFluids); + } } else { // LEGACY PATH: Backward compatibility for old nested compound format for (NBTBase base : (Collection) fluids.tagMap.values()) { @@ -239,6 +262,7 @@ public void loadFromNbt(NBTTagCompound compound) { int chunkZ = fluidCompound.getInteger("chunkZ"); String fluidName = fluidCompound.getString("fluidName"); Fluid fluid = FluidRegistry.getFluid(fluidName); + if (fluid == null) continue; int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; NBTTagList chunkList = fluidCompound.getTagList("chunks", 11); for (int i = 0; i < VP.undergroundFluidSizeChunkX; i++) { @@ -259,7 +283,7 @@ void loadLegacy(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBuffer) final short veinTypeId = oreChunksBuffer.getShort(); final boolean depleted = (veinTypeId & 0x8000) > 0; final VeinType veinType = getVeinFromId((short) (veinTypeId & 0x7FFF)); - if (veinType == null) return; + if (veinType == null) continue; oreChunks.put( getOreVeinKey(chunkX, chunkZ), @@ -316,6 +340,10 @@ public void toggleOreVein(int chunkX, int chunkZ) { } public UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) { + if (oreVeinPosition.veinType == VeinType.NO_VEIN) { + return UpdateResult.AlreadyKnown; + } + final long key = getOreVeinKey(oreVeinPosition.chunkX, oreVeinPosition.chunkZ); final OreVeinPosition storedOreVeinPosition = oreChunks.get(key); if (storedOreVeinPosition == null) { @@ -383,12 +411,15 @@ public void clearOreVeins(int startChunkX, int startChunkZ, int endChunkX, int e // This method iterates for each chunk mapped. In many cases, it is probably faster to iterate over chunks in // the area to be cleared instead. i.e. if (chunksInClearArea < totalChunksMapped) {useAltIterator()}. If // someone calls this enough to make it a problem, they can add that. - oreChunks.long2ObjectEntrySet().removeIf(entry -> { + boolean removedAny = oreChunks.long2ObjectEntrySet().removeIf(entry -> { OreVeinPosition val = entry.getValue(); final boolean withinX = val.chunkX >= startChunkX && val.chunkX <= endChunkX; final boolean withinZ = val.chunkZ >= startChunkZ && val.chunkZ <= endChunkZ; return withinX && withinZ; }); + if (removedAny) { + markDirty(); + } } private @Nullable VeinType getVeinFromId(short veinTypeId) { @@ -425,7 +456,7 @@ private static Short2ObjectMap getIdConversionMap() { } return idConversionMap = result; } catch (IOException e) { - e.printStackTrace(); + VP.LOG.error("Failed to read legacy file at {}", oldIdFile.getAbsolutePath(), e); return Short2ObjectMaps.emptyMap(); } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java index a1f7b3c0..dbfb0978 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java @@ -18,6 +18,7 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import com.sinthoras.visualprospecting.network.ProspectingNotification; import com.sinthoras.visualprospecting.network.ProspectingRequest; +import com.sinthoras.visualprospecting.teams.TeamProspectionDispatcher; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import gregtech.api.events.OreInteractEvent; @@ -78,7 +79,7 @@ public void onOreClicked(OreInteractEvent event) { .prospect(new ProspectingRequest(world.provider.dimensionId, x, y, z, material), event.world); if (response != null) { - VP.network.sendTo(response, (EntityPlayerMP) player); + TeamProspectionDispatcher.deliverProspectingResults((EntityPlayerMP) player, response); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index b71eee48..23c494bd 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -8,6 +8,7 @@ import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.MinecraftForge; +import com.gtnewhorizon.gtnhlib.teams.TeamDataRegistry; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.VP; @@ -21,8 +22,13 @@ import com.sinthoras.visualprospecting.network.ProspectingNotification; import com.sinthoras.visualprospecting.network.ProspectingRequest; import com.sinthoras.visualprospecting.network.ProspectionSharing; +import com.sinthoras.visualprospecting.network.TeamCatchupNotification; +import com.sinthoras.visualprospecting.network.VeinDepletionMessage; import com.sinthoras.visualprospecting.network.WorldIdNotification; import com.sinthoras.visualprospecting.task.TaskManager; +import com.sinthoras.visualprospecting.teams.TeamClearCommand; +import com.sinthoras.visualprospecting.teams.TeamInfoCommand; +import com.sinthoras.visualprospecting.teams.TeamProspectionData; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; @@ -71,10 +77,28 @@ public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { ProspectionSharing.class, networkId++, Side.CLIENT); + VP.network.registerMessage( + VeinDepletionMessage.ServerHandler.class, + VeinDepletionMessage.class, + networkId++, + Side.SERVER); + VP.network.registerMessage( + VeinDepletionMessage.ClientHandler.class, + VeinDepletionMessage.class, + networkId++, + Side.CLIENT); + VP.network.registerMessage( + TeamCatchupNotification.ClientHandler.class, + TeamCatchupNotification.class, + networkId++, + Side.CLIENT); ProspectorsLog.instance = new ProspectorsLog(); GameRegistry.registerItem(ProspectorsLog.instance, ProspectorsLog.instance.getUnlocalizedName()); + // Register with GTNHLib team system + TeamDataRegistry.register(TeamProspectionData.DATA_KEY, TeamProspectionData::new); + initializeTaskManager(); } @@ -123,6 +147,10 @@ public void fmlLifeCycleEvent(FMLServerStartingEvent event) { // Register the recache command event.registerServerCommand(new RedoServerCacheCommand()); event.registerServerCommand(new RedoServerSpawnCacheCommand()); + + // Team-sharing debug commands + event.registerServerCommand(new TeamInfoCommand()); + event.registerServerCommand(new TeamClearCommand()); } public void fmlLifeCycleEvent(FMLServerStartedEvent event) {} diff --git a/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java index 2d9c36af..2e5bebbb 100644 --- a/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java +++ b/src/main/java/com/sinthoras/visualprospecting/mixins/early/minecraft/ItemEditableBookMixin.java @@ -15,13 +15,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.sinthoras.visualprospecting.Tags; -import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; -import com.sinthoras.visualprospecting.network.ProspectingNotification; +import com.sinthoras.visualprospecting.teams.TeamProspectionDispatcher; @Mixin(value = ItemEditableBook.class) public class ItemEditableBookMixin { @@ -45,14 +43,10 @@ public class ItemEditableBookMixin { blockX, blockZ, VP.undergroundFluidChunkProspectingBlockRadius); - if (Utils.isLogicalClient()) { - ClientCache.instance.putOreVeins(foundOreVeins); - ClientCache.instance.putUndergroundFluids(foundUndergroundFluids); - } else { - VP.network.sendTo( - new ProspectingNotification(foundOreVeins, foundUndergroundFluids), - (EntityPlayerMP) entityPlayer); - } + TeamProspectionDispatcher.deliverProspectingResults( + (EntityPlayerMP) entityPlayer, + foundOreVeins, + foundUndergroundFluids); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java index 99d41747..4be1da75 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingNotification.java @@ -33,6 +33,14 @@ public ProspectingNotification(List oreVeins, List getOreVeins() { + return oreVeins; + } + + public List getUndergroundFluids() { + return undergroundFluids; + } + @Override public void fromBytes(ByteBuf buf) { oreVeins = VPByteBufUtils.ReadOreVeinPositions(buf); diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java index d43e43da..63881290 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectingRequest.java @@ -12,6 +12,7 @@ import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; +import com.sinthoras.visualprospecting.teams.TeamProspectionDispatcher; import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; @@ -98,7 +99,11 @@ public IMessage onMessage(ProspectingRequest message, MessageContext ctx) { if (!isChunkLoaded) return null; - return prospect(message, world); + ProspectingNotification response = prospect(message, world); + if (response != null) { + TeamProspectionDispatcher.deliverProspectingResults(ctx.getServerHandler().playerEntity, response); + } + return null; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/network/TeamCatchupNotification.java b/src/main/java/com/sinthoras/visualprospecting/network/TeamCatchupNotification.java new file mode 100644 index 00000000..533e0165 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/network/TeamCatchupNotification.java @@ -0,0 +1,47 @@ +package com.sinthoras.visualprospecting.network; + +import java.util.Collections; +import java.util.List; + +import com.sinthoras.visualprospecting.database.ClientCache; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; + +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; + +/** + * Similar to {@link ProspectingNotification} but for data being sent as recorded team state instead of a live + * prospection event. + *

    + * Used by the team-sharing catch-up paths (player login and post-team-merge). + */ +public class TeamCatchupNotification extends ProspectingNotification { + + public TeamCatchupNotification() { + super(); + } + + public TeamCatchupNotification(List oreVeins, List undergroundFluids) { + super(oreVeins, undergroundFluids); + } + + public static TeamCatchupNotification veins(List oreVeins) { + return new TeamCatchupNotification(oreVeins, Collections.emptyList()); + } + + public static TeamCatchupNotification fluids(List undergroundFluids) { + return new TeamCatchupNotification(Collections.emptyList(), undergroundFluids); + } + + public static class ClientHandler implements IMessageHandler { + + @Override + public IMessage onMessage(TeamCatchupNotification message, MessageContext ctx) { + ClientCache.instance.putOreVeins(message.getOreVeins(), true); + ClientCache.instance.putUndergroundFluids(message.getUndergroundFluids(), true); + return null; + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/network/VeinDepletionMessage.java b/src/main/java/com/sinthoras/visualprospecting/network/VeinDepletionMessage.java new file mode 100644 index 00000000..f6c320da --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/network/VeinDepletionMessage.java @@ -0,0 +1,69 @@ +package com.sinthoras.visualprospecting.network; + +import net.minecraft.entity.player.EntityPlayerMP; + +import com.sinthoras.visualprospecting.database.ClientCache; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.teams.TeamProspectionDispatcher; + +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import io.netty.buffer.ByteBuf; + +public class VeinDepletionMessage implements IMessage { + + private int dimensionId; + private int chunkX; + private int chunkZ; + private boolean depleted; + + public VeinDepletionMessage() {} + + public VeinDepletionMessage(int dimensionId, int chunkX, int chunkZ, boolean depleted) { + this.dimensionId = dimensionId; + this.chunkX = chunkX; + this.chunkZ = chunkZ; + this.depleted = depleted; + } + + @Override + public void fromBytes(ByteBuf buf) { + dimensionId = buf.readInt(); + chunkX = buf.readInt(); + chunkZ = buf.readInt(); + depleted = buf.readBoolean(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeInt(dimensionId); + buf.writeInt(chunkX); + buf.writeInt(chunkZ); + buf.writeBoolean(depleted); + } + + public static class ServerHandler implements IMessageHandler { + + @Override + public IMessage onMessage(VeinDepletionMessage msg, MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().playerEntity; + TeamProspectionDispatcher + .handleDepletionToggle(player, msg.dimensionId, msg.chunkX, msg.chunkZ, msg.depleted); + return null; + } + } + + public static class ClientHandler implements IMessageHandler { + + @Override + public IMessage onMessage(VeinDepletionMessage msg, MessageContext ctx) { + OreVeinPosition vein = ClientCache.instance.getOreVein(msg.dimensionId, msg.chunkX, msg.chunkZ); + if (vein == null || vein == OreVeinPosition.EMPTY_VEIN) return null; + if (vein.isDepleted() != msg.depleted) { + vein.toggleDepleted(); + } + return null; + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java index 69f7db21..a5ffc15c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotDownloadTask.java @@ -3,6 +3,7 @@ import java.util.List; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; @@ -30,6 +31,8 @@ public SnapshotDownloadTask(String authorUuid, EntityPlayerMP player) { @Override public boolean process() { + if (!MinecraftServer.getServer().getConfigurationManager().playerEntityList.contains(player)) return true; + final long timestamp = System.currentTimeMillis(); if (timestamp - lastUpload > 1000 / Config.uploadPacketsPerSecond && !listsEmpty()) { lastUpload = timestamp; diff --git a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java index a6c4f65c..4e9b7cde 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java @@ -2,6 +2,8 @@ import java.util.List; +import net.minecraft.client.Minecraft; + import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; @@ -23,6 +25,8 @@ public SnapshotUploadTask() { @Override public boolean process() { + if (Minecraft.getMinecraft().getNetHandler() == null) return true; + final long timestamp = System.currentTimeMillis(); if (timestamp - lastUpload > 1000 / Config.uploadPacketsPerSecond && !listsEmpty()) { lastUpload = timestamp; diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java new file mode 100644 index 00000000..460c5e28 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java @@ -0,0 +1,190 @@ +package com.sinthoras.visualprospecting.teams; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +import com.gtnewhorizon.gtnhlib.eventbus.EventBusSubscriber; +import com.gtnewhorizon.gtnhlib.teams.Team; +import com.gtnewhorizon.gtnhlib.teams.TeamEvents.TeamMergeEvent; +import com.gtnewhorizon.gtnhlib.teams.TeamManager; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.database.ServerCache; +import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; +import com.sinthoras.visualprospecting.database.veintypes.VeinType; +import com.sinthoras.visualprospecting.network.TeamCatchupNotification; + +import cpw.mods.fml.common.eventhandler.EventPriority; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerChangedDimensionEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import it.unimi.dsi.fastutil.longs.LongIterator; +import it.unimi.dsi.fastutil.longs.LongSet; + +/** + * Lazily push the team's prospection record to a player, one dimension at a time, as they enter it. Only catchup once + * per dimension per session as the rest is done live. + *

    + * Allow for player to catch up to what happened in the team when they were offline. + *

    + * Data is split into type and sent in batched notifications. + */ +@EventBusSubscriber +public final class TeamCatchupHandler { + + // Caps for one ProspectingNotification: (With ton of margin) + // ~20 B per vein -> 5000 veins ~= 100 KB per packet + // ~272 B per fluid -> 400 fluids ~= 109 KB per packet + private static final int VEINS_PER_PACKET = 5000; + private static final int FLUIDS_PER_PACKET = 400; + + private static final Map SENT_DIMS = new HashMap<>(); + + private TeamCatchupHandler() {} + + // Need to run after GTNHLib or we may have no team to load + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void onPlayerLogin(PlayerLoggedInEvent event) { + if (!Config.enableTeamSharing) return; + if (!(event.player instanceof EntityPlayerMP playerMP)) return; + SENT_DIMS.remove(playerMP.getUniqueID()); + + sendDimIfNeeded(playerMP, playerMP.dimension); + } + + @SubscribeEvent + public static void onPlayerChangedDimension(PlayerChangedDimensionEvent event) { + if (!Config.enableTeamSharing) return; + if (!(event.player instanceof EntityPlayerMP playerMP)) return; + + sendDimIfNeeded(playerMP, event.toDim); + } + + @SubscribeEvent + public static void onPlayerLogout(PlayerLoggedOutEvent event) { + if (!(event.player instanceof EntityPlayerMP playerMP)) return; + SENT_DIMS.remove(playerMP.getUniqueID()); + } + + @SubscribeEvent + public static void onTeamMerge(TeamMergeEvent event) { + if (!Config.enableTeamSharing) return; + + Team surviving = event.surviving; + if (surviving == null) return; + + TeamProspectionData data = (TeamProspectionData) surviving.getData(TeamProspectionData.DATA_KEY); + if (data == null) return; + + // Update every player with new merged data, only for dimensions they visited since login + TeamManager.forEachOnlineTeamMember(surviving, member -> { + VP.LOG.debug("[onTeamMerge] Sending catchup to: {}", member); + + IntSet alreadySent = SENT_DIMS.get(member.getUniqueID()); + if (alreadySent == null || alreadySent.isEmpty()) return; + + alreadySent.forEach((int dim) -> { + sendDimVeins(member, data, dim); + sendDimFluids(member, data, dim); + }); + }); + } + + private static void sendDimIfNeeded(EntityPlayerMP player, int dim) { + UUID uuid = player.getUniqueID(); + IntSet sent = SENT_DIMS.computeIfAbsent(uuid, k -> new IntOpenHashSet()); + if (!sent.add(dim)) return; + + Team team = TeamManager.getTeamByPlayer(uuid); + if (team == null) return; + TeamProspectionData data = (TeamProspectionData) team.getData(TeamProspectionData.DATA_KEY); + if (data == null) return; + + sendDimVeins(player, data, dim); + sendDimFluids(player, data, dim); + } + + private static void sendDimVeins(EntityPlayerMP player, TeamProspectionData data, int dim) { + LongSet veinKeys = data.getDiscoveredVeinKeys(dim); + if (veinKeys.isEmpty()) return; + + LongSet depletedKeys = data.getDepletedVeinKeys(dim); + List batch = new ArrayList<>(Math.min(VEINS_PER_PACKET, veinKeys.size())); + + for (LongIterator it = veinKeys.iterator(); it.hasNext();) { + long key = it.nextLong(); + int chunkX = TeamProspectionData.veinChunkX(key); + int chunkZ = TeamProspectionData.veinChunkZ(key); + + OreVeinPosition vein = ServerCache.instance.getOreVein(dim, chunkX, chunkZ); + if (vein == null || vein.veinType == VeinType.NO_VEIN) { + continue; + } + + boolean teamDepleted = depletedKeys.contains(key); + if (vein.isDepleted() != teamDepleted) { + vein = new OreVeinPosition(dim, chunkX, chunkZ, vein.veinType, teamDepleted); + } + batch.add(vein); + + if (batch.size() >= VEINS_PER_PACKET) { + flushVeins(player, batch); + batch = new ArrayList<>(VEINS_PER_PACKET); + } + } + flushVeins(player, batch); + } + + private static void flushVeins(EntityPlayerMP player, List batch) { + if (batch.isEmpty()) return; + VP.network.sendTo(TeamCatchupNotification.veins(batch), player); + } + + private static void sendDimFluids(EntityPlayerMP player, TeamProspectionData data, int dim) { + LongSet fluidKeys = data.getDiscoveredFluidKeys(dim); + if (fluidKeys.isEmpty()) return; + + World world = DimensionManager.getWorld(dim); + // Can't retrieve fluid if dim not loaded. + if (world == null) return; + + List batch = new ArrayList<>(Math.min(FLUIDS_PER_PACKET, fluidKeys.size())); + + for (LongIterator it = fluidKeys.iterator(); it.hasNext();) { + long key = it.nextLong(); + int chunkX = TeamProspectionData.fluidChunkX(key); + int chunkZ = TeamProspectionData.fluidChunkZ(key); + int blockX = Utils.coordChunkToBlock(chunkX); + int blockZ = Utils.coordChunkToBlock(chunkZ); + + List foundUndergroundFluids = ServerCache.instance + .prospectUndergroundFluidBlockRadius(world, blockX, blockZ, 0); + for (UndergroundFluidPosition fp : foundUndergroundFluids) { + if (!fp.isProspected()) continue; + batch.add(fp); + if (batch.size() >= FLUIDS_PER_PACKET) { + flushFluids(player, batch); + batch = new ArrayList<>(FLUIDS_PER_PACKET); + } + } + } + flushFluids(player, batch); + } + + private static void flushFluids(EntityPlayerMP player, List batch) { + if (batch.isEmpty()) return; + VP.network.sendTo(TeamCatchupNotification.fluids(batch), player); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamClearCommand.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamClearCommand.java new file mode 100644 index 00000000..0ca4c7bf --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/teams/TeamClearCommand.java @@ -0,0 +1,112 @@ +package com.sinthoras.visualprospecting.teams; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.StatCollector; + +import com.gtnewhorizon.gtnhlib.teams.Team; +import com.gtnewhorizon.gtnhlib.teams.TeamManager; + +import it.unimi.dsi.fastutil.ints.IntSet; + +/** + * {@code /vp_team_clear } : Delete that player team prospection record. + *

    + * Op/console only. + *

    + * Note: players local {@code ClientCache} is untouched. + */ +public class TeamClearCommand extends CommandBase { + + @Override + public String getCommandName() { + return "vp_team_clear"; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return StatCollector.translateToLocal("visualprospecting.teamclear.command"); + } + + @Override + public int getRequiredPermissionLevel() { + return 2; + } + + @Override + public boolean canCommandSenderUseCommand(ICommandSender sender) { + if (sender instanceof EntityPlayerMP player) { + if (Objects.equals(player.mcServer.getServerOwner(), sender.getCommandSenderName())) { + return true; + } + } + return super.canCommandSenderUseCommand(sender); + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args) { + if (args.length == 1) { + return getListOfStringsMatchingLastWord(args, MinecraftServer.getServer().getAllUsernames()); + } + return Collections.emptyList(); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + if (args.length != 1) { + sendMessage(sender, "visualprospecting.command.usage_error", getCommandName()); + return; + } + + EntityPlayerMP target = MinecraftServer.getServer().getConfigurationManager().func_152612_a(args[0]); + if (target == null) { + sendMessage(sender, "visualprospecting.teamcommand.player_offline", args[0]); + return; + } + + Team team = TeamManager.getTeamByPlayer(target.getUniqueID()); + if (team == null) { + sendMessage(sender, "visualprospecting.teamcommand.no_team", target.getCommandSenderName()); + return; + } + + TeamProspectionData data = (TeamProspectionData) team.getData(TeamProspectionData.DATA_KEY); + if (data == null) { + sendMessage(sender, "visualprospecting.teaminfo.no_data"); + return; + } + + IntSet dims = data.knownDimensions(); + long totalVeins = 0, totalFluids = 0; + for (int dim : dims) { + totalVeins += data.getDiscoveredVeinKeys(dim).size(); + totalFluids += data.getDiscoveredFluidKeys(dim).size(); + } + + data.clear(); + team.markDirty(); + + IChatComponent msg = new ChatComponentTranslation( + "visualprospecting.teamclear.success", + team.getTeamName(), + totalVeins, + totalFluids); + msg.getChatStyle().setColor(EnumChatFormatting.GREEN); + sender.addChatMessage(msg); + } + + private static void sendMessage(ICommandSender sender, String translationKey, Object... args) { + IChatComponent msg = new ChatComponentTranslation(translationKey, args); + msg.getChatStyle().setColor(EnumChatFormatting.RED); + sender.addChatMessage(msg); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamInfoCommand.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamInfoCommand.java new file mode 100644 index 00000000..d7b61188 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/teams/TeamInfoCommand.java @@ -0,0 +1,194 @@ +package com.sinthoras.visualprospecting.teams; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +import com.gtnewhorizon.gtnhlib.teams.Team; +import com.gtnewhorizon.gtnhlib.teams.TeamManager; + +import it.unimi.dsi.fastutil.ints.IntSet; + +/** + * {@code /vp_team_info [player] [detailed]} : inspect a player team's prospection record. + *

    + * Require op to inspect other players. + */ +public class TeamInfoCommand extends CommandBase { + + private static final String DETAILED_FLAG = "detailed"; + + @Override + public String getCommandName() { + return "vp_team_info"; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return StatCollector.translateToLocal("visualprospecting.teaminfo.command"); + } + + @Override + public int getRequiredPermissionLevel() { + return 0; + } + + @Override + public boolean canCommandSenderUseCommand(ICommandSender sender) { + return true; + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args) { + if (args.length == 1) { + String[] names = MinecraftServer.getServer().getAllUsernames(); + String[] options = Arrays.copyOf(names, names.length + 1); + options[names.length] = DETAILED_FLAG; + return getListOfStringsMatchingLastWord(args, options); + } + if (args.length == 2) { + return getListOfStringsMatchingLastWord(args, DETAILED_FLAG); + } + return Collections.emptyList(); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + boolean detailed = false; + String targetPlayerName = null; + for (String arg : args) { + if (arg.equalsIgnoreCase(DETAILED_FLAG)) { + detailed = true; + } else if (targetPlayerName == null) { + targetPlayerName = arg; + } else { + sendMessage(sender, "visualprospecting.command.usage_error", getCommandName()); + return; + } + } + + EntityPlayerMP targetPlayer = resolveTarget(sender, targetPlayerName); + if (targetPlayer == null) return; + + Team team = TeamManager.getTeamByPlayer(targetPlayer.getUniqueID()); + if (team == null) { + sendMessage(sender, "visualprospecting.teamcommand.no_team", targetPlayer.getCommandSenderName()); + return; + } + + TeamProspectionData data = (TeamProspectionData) team.getData(TeamProspectionData.DATA_KEY); + if (data == null) { + sendMessage(sender, "visualprospecting.teaminfo.no_data"); + return; + } + + printReport(sender, team, data, detailed); + } + + private EntityPlayerMP resolveTarget(ICommandSender sender, String targetName) { + if (targetName == null) { + if (sender instanceof EntityPlayerMP self) return self; + sendMessage(sender, "visualprospecting.teamcommand.console_needs_player"); + return null; + } + + // Permission check + if (!sender.canCommandSenderUseCommand(2, getCommandName())) { + sendMessage(sender, "visualprospecting.teaminfo.no_permission_other"); + return null; + } + + EntityPlayerMP target = MinecraftServer.getServer().getConfigurationManager().func_152612_a(targetName); + if (target == null) { + sendMessage(sender, "visualprospecting.teamcommand.player_offline", targetName); + return null; + } + return target; + } + + private static void printReport(ICommandSender sender, Team team, TeamProspectionData data, boolean detailed) { + IntSet dims = data.knownDimensions(); + + long totalVeins = 0, totalFluids = 0, totalDepleted = 0; + for (int dim : dims) { + totalVeins += data.getDiscoveredVeinKeys(dim).size(); + totalFluids += data.getDiscoveredFluidKeys(dim).size(); + totalDepleted += data.getDepletedVeinKeys(dim).size(); + } + + int memberCount = team.getMembers().size(); + int onlineCount = countOnline(team); + + IChatComponent header = new ChatComponentTranslation( + "visualprospecting.teaminfo.header", + team.getTeamName(), + memberCount, + onlineCount); + header.getChatStyle().setBold(true); + sender.addChatMessage(header); + + if (dims.isEmpty()) { + IChatComponent empty = new ChatComponentTranslation("visualprospecting.teaminfo.empty"); + empty.getChatStyle().setColor(EnumChatFormatting.GRAY); + sender.addChatMessage(empty); + return; + } + + sender.addChatMessage( + new ChatComponentTranslation( + "visualprospecting.teaminfo.summary", + dims.size(), + totalVeins, + totalDepleted, + totalFluids)); + + if (!detailed) return; + + int[] sortedDims = dims.toIntArray(); + Arrays.sort(sortedDims); + for (int dim : sortedDims) { + int v = data.getDiscoveredVeinKeys(dim).size(); + int f = data.getDiscoveredFluidKeys(dim).size(); + int d = data.getDepletedVeinKeys(dim).size(); + if (v == 0 && f == 0) continue; + sender.addChatMessage( + new ChatComponentTranslation("visualprospecting.teaminfo.dim_line", dimLabel(dim), v, d, f)); + } + } + + private static int countOnline(Team team) { + int[] count = { 0 }; + TeamManager.forEachOnlineTeamMember(team, p -> count[0]++); + return count[0]; + } + + private static String dimLabel(int dim) { + try { + World world = DimensionManager.getWorld(dim); + if (world != null && world.provider != null) { + String name = world.provider.getDimensionName(); + if (name != null && !name.isEmpty()) { + return dim + " (" + name + ")"; + } + } + } catch (Exception ignored) {} + return Integer.toString(dim); + } + + private static void sendMessage(ICommandSender sender, String translationKey, Object... args) { + IChatComponent msg = new ChatComponentTranslation(translationKey, args); + msg.getChatStyle().setColor(EnumChatFormatting.RED); + sender.addChatMessage(msg); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionData.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionData.java new file mode 100644 index 00000000..83438f87 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionData.java @@ -0,0 +1,349 @@ +package com.sinthoras.visualprospecting.teams; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Arrays; +import java.util.Base64; +import java.util.UUID; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.util.Constants; + +import com.gtnewhorizon.gtnhlib.teams.ITeamData; +import com.gtnewhorizon.gtnhlib.teams.Team; +import com.gtnewhorizon.gtnhlib.teams.TeamDataTransferReason; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.VP; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.ints.IntSet; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; +import it.unimi.dsi.fastutil.longs.LongSets; + +/** + * Per-team prospection record. Tracks which ore veins / underground fluids a team has discovered, which veins are + * depleted, per dimension. + *

    + * Only coordinate keys are stored. Full {@code OreVeinPosition} / {@code UndergroundFluidPosition} infos (vein types, + * fluid amounts) are recovered from {@code ServerCache}. + *

    + * The vein/fluid/depleted state is stored into a blob as a single gzipped base64 {@code NBTTagString}. + *

    + * On server restart the data sent by GTNHLib is not expanded until first access. + */ +public class TeamProspectionData implements ITeamData { + + public static final String DATA_KEY = "visualprospecting"; + + private static final String TAG_VERSION = "version"; + private static final String TAG_BLOB = "blob"; + + private static final int FORMAT_VERSION = 1; + + // Team Data - Raw + private byte[] pendingBlob; + // Team Data - Expanded + private Int2ObjectMap discoveredVeins; + private Int2ObjectMap discoveredFluids; + private Int2ObjectMap depletedVeins; + // Team Data - Status + private boolean expanded; + private byte[] unknownVersionBlob; + private int unknownVersion; + + // Lazy team data expansion + private void ensureExpanded() { + if (expanded) return; + + discoveredVeins = new Int2ObjectOpenHashMap<>(); + discoveredFluids = new Int2ObjectOpenHashMap<>(); + depletedVeins = new Int2ObjectOpenHashMap<>(); + if (pendingBlob != null) { + try { + decodeBlobInto(pendingBlob, discoveredVeins, discoveredFluids, depletedVeins); + } catch (IOException e) { + VP.LOG.error("Failed to decode team prospection data.", e); + } + pendingBlob = null; + } + expanded = true; + } + + // Pack an Ore vein position + static long packVein(int chunkX, int chunkZ) { + return ((long) chunkX << 32) | (chunkZ & 0xFFFFFFFFL); + } + + static int veinChunkX(long key) { + return (int) (key >>> 32); + } + + static int veinChunkZ(long key) { + return (int) key; + } + + // Pack an Underground Fluids position. They are on a 8x8 pattern so we can divide by 8 + static long packFluid(int chunkX, int chunkZ) { + return ((long) (chunkX >> 3) << 32) | ((chunkZ >> 3) & 0xFFFFFFFFL); + } + + static int fluidChunkX(long key) { + return ((int) (key >>> 32)) << 3; + } + + static int fluidChunkZ(long key) { + return ((int) key) << 3; + } + + // Add ore vein to team record + public boolean addVein(int dim, int chunkX, int chunkZ) { + ensureExpanded(); + return getOrCreate(discoveredVeins, dim).add(packVein(chunkX, chunkZ)); + } + + // Add underground fluid to team record + public boolean addFluid(int dim, int chunkX, int chunkZ) { + ensureExpanded(); + return getOrCreate(discoveredFluids, dim).add(packFluid(chunkX, chunkZ)); + } + + // Record an ore vein as depleted + public boolean setVeinDepleted(int dim, int chunkX, int chunkZ, boolean depleted) { + ensureExpanded(); + long key = packVein(chunkX, chunkZ); + if (depleted) { + return getOrCreate(depletedVeins, dim).add(key); + } + LongSet set = depletedVeins.get(dim); + return set != null && set.remove(key); + } + + // Delete all data for a team + public void clear() { + pendingBlob = null; + unknownVersionBlob = null; + unknownVersion = 0; + discoveredVeins = new Int2ObjectOpenHashMap<>(); + discoveredFluids = new Int2ObjectOpenHashMap<>(); + depletedVeins = new Int2ObjectOpenHashMap<>(); + expanded = true; + } + + public LongSet getDiscoveredVeinKeys(int dim) { + ensureExpanded(); + return discoveredVeins.getOrDefault(dim, LongSets.EMPTY_SET); + } + + public LongSet getDiscoveredFluidKeys(int dim) { + ensureExpanded(); + return discoveredFluids.getOrDefault(dim, LongSets.EMPTY_SET); + } + + public LongSet getDepletedVeinKeys(int dim) { + ensureExpanded(); + return depletedVeins.getOrDefault(dim, LongSets.EMPTY_SET); + } + + public boolean isVeinDiscovered(int dim, int chunkX, int chunkZ) { + ensureExpanded(); + LongSet set = discoveredVeins.get(dim); + return set != null && set.contains(packVein(chunkX, chunkZ)); + } + + public boolean isVeinDepleted(int dim, int chunkX, int chunkZ) { + ensureExpanded(); + LongSet set = depletedVeins.get(dim); + return set != null && set.contains(packVein(chunkX, chunkZ)); + } + + public IntSet knownDimensions() { + ensureExpanded(); + IntSet dims = new IntOpenHashSet(); + dims.addAll(discoveredVeins.keySet()); + dims.addAll(discoveredFluids.keySet()); + dims.addAll(depletedVeins.keySet()); + return dims; + } + + @Override + public void writeToNBT(NBTTagCompound tag) { + // In case of unknown FORMAT_VERSION we write OG data untouched + if (unknownVersionBlob != null) { + tag.setInteger(TAG_VERSION, unknownVersion); + tag.setString(TAG_BLOB, Base64.getEncoder().encodeToString(unknownVersionBlob)); + return; + } + + byte[] blob; + if (expanded) { + blob = encodeBlob(discoveredVeins, discoveredFluids, depletedVeins); + } else if (pendingBlob != null) { + blob = pendingBlob; + } else return; + if (blob.length == 0) return; + tag.setInteger(TAG_VERSION, FORMAT_VERSION); + tag.setString(TAG_BLOB, Base64.getEncoder().encodeToString(blob)); + } + + @Override + public void readFromNBT(NBTTagCompound tag) { + expanded = false; + pendingBlob = null; + unknownVersionBlob = null; + unknownVersion = 0; + discoveredVeins = null; + discoveredFluids = null; + depletedVeins = null; + + if (!tag.hasKey(TAG_BLOB, Constants.NBT.TAG_STRING)) return; + int version = tag.getInteger(TAG_VERSION); + String b64 = tag.getString(TAG_BLOB); + if (b64.isEmpty()) return; + + byte[] raw; + try { + raw = Base64.getDecoder().decode(b64); + } catch (IllegalArgumentException e) { + VP.LOG.error("Team prospection data blob is not valid base64. Starting empty", e); + return; + } + if (version != FORMAT_VERSION) { + VP.LOG.error( + "Team prospection data is format version {}, this supports v{}. New changes won't be recorded.", + version, + FORMAT_VERSION); + unknownVersion = version; + unknownVersionBlob = raw; + return; + } + pendingBlob = raw; + } + + @Override + public void mergeData(Team consumed, Team surviving, ITeamData oldTeamData) { + if (oldTeamData instanceof TeamProspectionData other) { + ensureExpanded(); + other.ensureExpanded(); + mergeFrom(other); + } + } + + @Override + public void transferData(Team prevTeam, Team newTeam, UUID playerId, ITeamData prevTeamData, + TeamDataTransferReason reason) { + if (!(prevTeamData instanceof TeamProspectionData prev)) return; + if (reason == TeamDataTransferReason.JoinedNewTeam && !Config.keepProspectionOnTeamLeave) return; + ensureExpanded(); + prev.ensureExpanded(); + mergeFrom(prev); + } + + private void mergeFrom(TeamProspectionData other) { + mergeMap(other.discoveredVeins, discoveredVeins); + mergeMap(other.discoveredFluids, discoveredFluids); + mergeMap(other.depletedVeins, depletedVeins); + } + + private static void mergeMap(Int2ObjectMap source, Int2ObjectMap target) { + if (source == null) return; + for (Int2ObjectMap.Entry entry : source.int2ObjectEntrySet()) { + int dim = entry.getIntKey(); + getOrCreate(target, dim).addAll(entry.getValue()); + } + } + + private static LongSet getOrCreate(Int2ObjectMap map, int dim) { + return map.computeIfAbsent(dim, value -> new LongOpenHashSet()); + } + + /** + * Data structure used:
    + *  int numDims
    + *  for each dim:
    + *    int dimId
    + *    int veinCount
    + *    long veinKeys[veinCount]
    + *    int fluidCount;
    + *    long fluidKeys[fluidCount]
    + *    int depletedCount
    + *    long depletedKeys[depletedCount]
    + *
    + * Data is sorted to improve gzip efficiency + */ + private static byte[] encodeBlob(Int2ObjectMap veins, Int2ObjectMap fluids, + Int2ObjectMap depleted) { + IntSet allDims = new IntOpenHashSet(); + if (veins != null) allDims.addAll(veins.keySet()); + if (fluids != null) allDims.addAll(fluids.keySet()); + if (depleted != null) allDims.addAll(depleted.keySet()); + + int[] dimsToWrite = allDims.intStream() + .filter(d -> !isEmpty(veins, d) || !isEmpty(fluids, d) || !isEmpty(depleted, d)).sorted().toArray(); + if (dimsToWrite.length == 0) return EMPTY_BYTES; + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try (GZIPOutputStream gz = new GZIPOutputStream(bos); DataOutputStream out = new DataOutputStream(gz)) { + out.writeInt(dimsToWrite.length); + for (int dim : dimsToWrite) { + out.writeInt(dim); + writeLongSet(out, veins == null ? null : veins.get(dim)); + writeLongSet(out, fluids == null ? null : fluids.get(dim)); + writeLongSet(out, depleted == null ? null : depleted.get(dim)); + } + } catch (IOException e) { + throw new UncheckedIOException("Failed to encode team prospection blob", e); + } + return bos.toByteArray(); + } + + private static boolean isEmpty(Int2ObjectMap map, int dim) { + if (map == null) return true; + LongSet set = map.get(dim); + return set == null || set.isEmpty(); + } + + private static void writeLongSet(DataOutputStream out, LongSet set) throws IOException { + if (set == null || set.isEmpty()) { + out.writeInt(0); + return; + } + long[] sorted = set.toLongArray(); + Arrays.sort(sorted); + out.writeInt(sorted.length); + for (long k : sorted) { + out.writeLong(k); + } + } + + private static void decodeBlobInto(byte[] blob, Int2ObjectMap veinsOut, Int2ObjectMap fluidsOut, + Int2ObjectMap depletedOut) throws IOException { + try (GZIPInputStream gz = new GZIPInputStream(new ByteArrayInputStream(blob)); + DataInputStream in = new DataInputStream(gz)) { + int numDims = in.readInt(); + for (int i = 0; i < numDims; i++) { + int dim = in.readInt(); + readIntoSet(in, getOrCreate(veinsOut, dim)); + readIntoSet(in, getOrCreate(fluidsOut, dim)); + readIntoSet(in, getOrCreate(depletedOut, dim)); + } + } + } + + private static void readIntoSet(DataInputStream in, LongSet target) throws IOException { + int count = in.readInt(); + for (int i = 0; i < count; i++) { + target.add(in.readLong()); + } + } + + private static final byte[] EMPTY_BYTES = new byte[0]; +} diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java new file mode 100644 index 00000000..48198c6c --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java @@ -0,0 +1,125 @@ +package com.sinthoras.visualprospecting.teams; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.minecraft.entity.player.EntityPlayerMP; + +import com.gtnewhorizon.gtnhlib.teams.Team; +import com.gtnewhorizon.gtnhlib.teams.TeamManager; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; +import com.sinthoras.visualprospecting.database.veintypes.VeinType; +import com.sinthoras.visualprospecting.network.ProspectingNotification; +import com.sinthoras.visualprospecting.network.VeinDepletionMessage; + +/** + * Entry point for delivering prospection results from the server to the player. + *

    + * If team sharing is enabled, store results in the team's {@link TeamProspectionData} then broadcast to online + * teammates. + */ +public final class TeamProspectionDispatcher { + + private TeamProspectionDispatcher() {} + + /** + * Send prospection results to {@code player}, then route through team sharing. + * + * @param player the player whose action produced these results + * @param oreVeins ore veins to deliver. May be empty; must not be {@code null}. + * @param fluids underground fluid positions to deliver. May be empty; must not be {@code null}. + */ + public static void deliverProspectingResults(EntityPlayerMP player, List oreVeins, + List fluids) { + deliverProspectingResults(player, new ProspectingNotification(oreVeins, fluids)); + } + + public static void deliverProspectingResults(EntityPlayerMP player, ProspectingNotification notification) { + // Notify the originating player with the pre-built notification. + VP.network.sendTo(notification, player); + + if (!Config.enableTeamSharing) return; + + Team team = TeamManager.getTeamByPlayer(player.getUniqueID()); + if (team == null) return; + TeamProspectionData data = (TeamProspectionData) team.getData(TeamProspectionData.DATA_KEY); + if (data == null) return; + + // Update the team's record + List newVeins = filterNewVeins(data, notification.getOreVeins()); + List newFluids = filterNewFluids(data, notification.getUndergroundFluids()); + if (newVeins.isEmpty() && newFluids.isEmpty()) return; + + team.markDirty(); + + // No one to broadcast to if solo team + if (team.getMembers().size() <= 1) return; + + // Broadcast to other online teammates. + ProspectingNotification broadcast = new ProspectingNotification(newVeins, newFluids); + TeamManager.forEachOnlineTeamMember(team, member -> { + if (!member.getUniqueID().equals(player.getUniqueID())) { + VP.network.sendTo(broadcast, member); + } + }); + } + + /** + * Manage vein depletion toggle sent by {@code player} from a map GUI. + *

    + * Toggles are only accepted for veins the team has actually discovered. + */ + public static void handleDepletionToggle(EntityPlayerMP player, int dim, int chunkX, int chunkZ, boolean depleted) { + if (!Config.enableTeamSharing) return; + + Team team = TeamManager.getTeamByPlayer(player.getUniqueID()); + if (team == null) return; + TeamProspectionData data = (TeamProspectionData) team.getData(TeamProspectionData.DATA_KEY); + if (data == null) return; + + // Require the vein to be in the team's discovered set. + if (!data.isVeinDiscovered(dim, chunkX, chunkZ)) return; + + // Stop here if the team's depletion state already matches. + if (!data.setVeinDepleted(dim, chunkX, chunkZ, depleted)) return; + + team.markDirty(); + + // Broadcast to other online teammates. + VeinDepletionMessage broadcast = new VeinDepletionMessage(dim, chunkX, chunkZ, depleted); + TeamManager.forEachOnlineTeamMember(team, member -> { + if (!member.getUniqueID().equals(player.getUniqueID())) { + VP.network.sendTo(broadcast, member); + } + }); + } + + private static List filterNewVeins(TeamProspectionData data, List veins) { + if (veins == null || veins.isEmpty()) return Collections.emptyList(); + List newVeins = new ArrayList<>(veins.size()); + for (OreVeinPosition v : veins) { + if (v == null || v.veinType == VeinType.NO_VEIN) continue; + if (data.addVein(v.dimensionId, v.chunkX, v.chunkZ)) { + newVeins.add(v); + } + } + return newVeins; + } + + private static List filterNewFluids(TeamProspectionData data, + List fluids) { + if (fluids == null || fluids.isEmpty()) return Collections.emptyList(); + List newFluids = new ArrayList<>(fluids.size()); + for (UndergroundFluidPosition f : fluids) { + if (f == null || !f.isProspected()) continue; + if (data.addFluid(f.dimensionId, f.chunkX, f.chunkZ)) { + newFluids.add(f); + } + } + return newFluids; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java b/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java index aaede9f2..bc8d9f14 100644 --- a/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java +++ b/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java @@ -38,7 +38,7 @@ public static void WriteUndergroundFluidPosition(ByteBuf buf, UndergroundFluidPo buf.writeInt(undergroundFluidPosition.dimensionId); buf.writeInt(undergroundFluidPosition.chunkX); buf.writeInt(undergroundFluidPosition.chunkZ); - buf.writeInt(undergroundFluidPosition.fluid.getID()); + ByteBufUtils.writeUTF8String(buf, undergroundFluidPosition.fluid.getName()); for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { buf.writeInt(undergroundFluidPosition.chunks[offsetChunkX][offsetChunkZ]); @@ -50,7 +50,7 @@ public static UndergroundFluidPosition ReadUndergroundFluidPosition(ByteBuf buf) final int dimId = buf.readInt(); final int chunkX = buf.readInt(); final int chunkZ = buf.readInt(); - final Fluid fluid = FluidRegistry.getFluid(buf.readInt()); + final Fluid fluid = FluidRegistry.getFluid(ByteBufUtils.readUTF8String(buf)); final int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index f3634db9..30ab9f2a 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -49,3 +49,16 @@ item.visualprospecting.prospectorslog.reading.begin=That's quite a lot of pages. item.visualprospecting.prospectorslog.reading.end=I finished the Prospector's Log of %s visualprospecting.node.deletehint=Mark depleted with %s visualprospecting.tracked=Tracked: %s +visualprospecting.command.usage_error=Invalid arguments for /%s. +visualprospecting.teamcommand.console_needs_player=Must specify a player when running command from console. +visualprospecting.teamcommand.player_offline=Player not found or not online: %s +visualprospecting.teamcommand.no_team=%s is not in any team. +visualprospecting.teaminfo.command=/vp_team_info [player] [detailed]: Inspect a player team's prospection record +visualprospecting.teaminfo.no_data=Team has no prospection data attached. +visualprospecting.teaminfo.no_permission_other=You don't have the permission level required to inspect another team. +visualprospecting.teaminfo.header=Team "%s" (%s members, %s online) +visualprospecting.teaminfo.empty= No discoveries recorded. +visualprospecting.teaminfo.summary= Across %s dim(s): %s veins (%s depleted), %s fluids +visualprospecting.teaminfo.dim_line= Dim %s: %s veins (%s depleted), %s fluids +visualprospecting.teamclear.command=/vp_team_clear : Delete that player team prospection record. +visualprospecting.teamclear.success=Cleared team "%s": Removed %s veins and %s fluids. From 441d288cfc49b140ab0a2680a574ab0f8a713479 Mon Sep 17 00:00:00 2001 From: Danila Suslov Date: Mon, 25 May 2026 21:41:51 +0300 Subject: [PATCH 113/132] Add compatibility with EndlessIds to redo server cache command (#84) --- .../cachebuilder/PartiallyLoadedChunk.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java index be9ac4c4..d37a26a2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java @@ -44,6 +44,8 @@ public void load(NBTTagCompound chunk, int chunkX, int chunkZ) { byte y = section.getByte("Y"); if (section.hasKey("Blocks16")) { + // chunk saved with NotEnoughIds + ShortBuffer blocks = ByteBuffer.wrap(section.getByteArray("Blocks16")).asShortBuffer(); ShortBuffer metas = ByteBuffer.wrap(section.getByteArray("Data16")).asShortBuffer(); @@ -78,7 +80,71 @@ public void load(NBTTagCompound chunk, int chunkX, int chunkZ) { this.blocks[y] = blocks::get; this.metas[y] = metas::get; + + } else if (section.hasKey("Add") || section.hasKey("BlocksB2Hi")) { + // chunk saved with EndlessIds + + // 00FF + ByteBuffer blocks1Byte = ByteBuffer.wrap(section.getByteArray("Blocks")); + // 0F00 + ByteBuffer blocks2Lo; + if (section.hasKey("Add")) { + blocks2Lo = ByteBuffer.wrap(section.getByteArray("Add")); + } else { + blocks2Lo = null; + } + // F000 + ByteBuffer blocks2Hi; + if (section.hasKey("BlocksB2Hi")) { + blocks2Hi = ByteBuffer.wrap(section.getByteArray("BlocksB2Hi")); + } else { + blocks2Hi = null; + } + + this.blocks[y] = i -> { + int nibbleShift = (i & 1) * 4; + short id = (short) (blocks1Byte.get(i) & 0xFF); + if (blocks2Lo != null) { + id |= (short) (((blocks2Lo.get(i >> 1) >> nibbleShift) & 0xF) << 8); + } + if (blocks2Hi != null) { + id |= (short) (((blocks2Hi.get(i >> 1) >> nibbleShift) & 0xF) << 12); + } + return id; + }; + + // 000F + ByteBuffer meta1Lo = ByteBuffer.wrap(section.getByteArray("Data")); + // 00F0 + ByteBuffer meta1Hi; + if (section.hasKey("Data1High")) { + meta1Hi = ByteBuffer.wrap(section.getByteArray("Data1High")); + } else { + meta1Hi = null; + } + // FF00 + ByteBuffer meta2; + if (section.hasKey("Data2")) { + meta2 = ByteBuffer.wrap(section.getByteArray("Data2")); + } else { + meta2 = null; + } + + this.metas[y] = i -> { + int nibbleShift = (i & 1) * 4; + short meta = 0; + meta |= (short) (((meta1Lo.get(i >> 1) >> nibbleShift) & 0xF)); + if (meta1Hi != null) { + meta |= (short) (((meta1Hi.get(i >> 1) >> nibbleShift) & 0xF) << 4); + } + if (meta2 != null) { + meta |= (short) ((meta2.get(i) & 0xFF) << 8); + } + return meta; + }; + } else { + // neither NotEnoughIds nor EndlessIds // don't bother loading the actual blocks, if a chunk is this old it'll only have ore tiles this.blocks[y] = i -> (short) 0; this.metas[y] = i -> (short) 0; From d03db5cc418cf2b8a783096f1dc955898cd813c1 Mon Sep 17 00:00:00 2001 From: Algent Date: Wed, 27 May 2026 22:21:42 +0200 Subject: [PATCH 114/132] Rework server and client cache into a more optimized system (#87) --- .../VisualProspecting_API.java | 9 +- .../database/DimensionCache.java | 520 +++++++++--------- .../database/LegacyDimensionCacheLoader.java | 262 +++++++++ .../database/OreVeinPosition.java | 32 +- .../database/ServerCache.java | 12 +- .../database/VeinSource.java | 25 + .../database/WorldCache.java | 3 +- .../cachebuilder/DimensionAnalysis.java | 28 +- .../teams/TeamCatchupHandler.java | 2 +- .../utils/VPByteBufUtils.java | 5 +- 10 files changed, 599 insertions(+), 299 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/database/LegacyDimensionCacheLoader.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/database/VeinSource.java diff --git a/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java b/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java index 71eb20b0..2856c135 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java +++ b/src/main/java/com/sinthoras/visualprospecting/VisualProspecting_API.java @@ -11,6 +11,8 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; +import com.sinthoras.visualprospecting.database.VeinSource; +import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import com.sinthoras.visualprospecting.network.VeinDepletionMessage; import com.sinthoras.visualprospecting.teams.TeamProspectionDispatcher; @@ -85,7 +87,12 @@ public static UndergroundFluidPosition getUndergroundFluid(World world, int bloc } public static void notifyOreGeneration(int dimensionId, int blockX, int blockZ, final String oreVeinName) { - ServerCache.instance.notifyOreVeinGeneration(dimensionId, blockX, blockZ, oreVeinName); + ServerCache.instance.notifyOreVeinGeneration( + dimensionId, + blockX, + blockZ, + VeinTypeCaching.getVeinType(oreVeinName), + VeinSource.API); } public static void sendProspectionResultsToClient(EntityPlayerMP player, List oreVeins, diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index 2bbe55db..7f9e9d1a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -1,35 +1,60 @@ package com.sinthoras.visualprospecting.database; -import java.io.File; -import java.io.IOException; -import java.io.Reader; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; +import java.util.List; import java.util.Map; -import javax.annotation.Nullable; - -import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; -import it.unimi.dsi.fastutil.shorts.Short2ObjectMaps; -import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; +/** + * Cache of ore veins and underground fluids. Stored as NBT file per dimension (e.g. {@code DIM0.dat}). + *

    + * + *

    + * Root: {
    + *   "version": 3,  // int   Absence means a legacy format {@link LegacyDimensionCacheLoader}
    + *   "dim":     <dimensionId>,      // int
    + *   "ores":    <ores compound>,    // optional
    + *   "fluids":  <fluids compound>   // optional
    + * }
    + * 
    + * + * {@code ores} and {@code fluids} use a palette. + * + *
    + * ores: {
    + *   "palette":       [String, ...],  // unique vein type
    + *   "chunkX":        int[N],         // chunk X
    + *   "chunkZ":        int[N],         // chunk Z
    + *   "veinTypeIndex": int[N],         // index into palette
    + *   "depleted":      byte[N],        // bool
    + *   "source":        byte[N]         // {@link VeinSource}
    + * }
    + *
    + * fluids: {
    + *   "palette":        [String, ...], // unique fluid names
    + *   "chunkX":         int[N],
    + *   "chunkZ":         int[N],
    + *   "fluidTypeIndex": int[N],
    + *   "chunkData":      int[N * chunkDataSize], // fluid amounts for 8x8 area
    + *   "chunkDataSize":  int
    + * }
    + * 
    + */ public class DimensionCache { public enum UpdateResult { @@ -38,8 +63,8 @@ public enum UpdateResult { New } - private static final File oldIdFile = new File(Tags.VISUALPROSPECTING_DIR, "veintypesLUT"); - private static Short2ObjectMap idConversionMap; + private static final int CURRENT_FORMAT_VERSION = 3; + private final Long2ObjectOpenHashMap oreChunks = new Long2ObjectOpenHashMap<>(); private final Long2ObjectOpenHashMap undergroundFluids = new Long2ObjectOpenHashMap<>(); public final int dimensionId; @@ -50,76 +75,218 @@ public DimensionCache(int dimensionId) { this.dimensionId = dimensionId; } + public void loadFromNbt(NBTTagCompound compound) { + int version = compound.getInteger("version"); + + if (version > CURRENT_FORMAT_VERSION) { + preventSaving = true; + VP.LOG.warn( + "Dimension {}: unsupported format version {}, data will not be modified.", + dimensionId, + version); + return; + } + + if (version == CURRENT_FORMAT_VERSION) { + loadOres(compound.getCompoundTag("ores")); + loadFluids(compound.getCompoundTag("fluids")); + } else { + // version key absent => v2 or older + LegacyDimensionCacheLoader.loadV2Ores(this, compound.getCompoundTag("ores")); + LegacyDimensionCacheLoader.loadV2Fluids(this, compound.getCompoundTag("fluids")); + } + } + public NBTTagCompound saveToNbt() { NBTTagCompound compound = new NBTTagCompound(); + compound.setInteger("version", CURRENT_FORMAT_VERSION); + compound.setInteger("dim", dimensionId); compound.setTag("ores", saveOres()); compound.setTag("fluids", saveFluids()); - compound.setInteger("dim", dimensionId); isDirty = false; return compound; } + private void loadOres(NBTTagCompound ores) { + if (!ores.hasKey("palette")) return; + + NBTTagList paletteTag = ores.getTagList("palette", 8); + String[] palette = new String[paletteTag.tagCount()]; + for (int i = 0; i < palette.length; i++) { + palette[i] = paletteTag.getStringTagAt(i); + } + + int[] chunkXArray = ores.getIntArray("chunkX"); + int[] chunkZArray = ores.getIntArray("chunkZ"); + int[] veinTypeIndexArray = ores.getIntArray("veinTypeIndex"); + byte[] depletedArray = ores.getByteArray("depleted"); + byte[] sourceArray = ores.getByteArray("source"); + + int size = chunkXArray.length; + oreChunks.ensureCapacity(oreChunks.size() + size); + + int unknownVeinTypes = 0; + for (int i = 0; i < size; i++) { + int index = veinTypeIndexArray[i]; + if (index < 0 || index >= palette.length) { + unknownVeinTypes++; + continue; + } + VeinType veinType = VeinTypeCaching.getVeinType(palette[index]); + if (veinType == VeinType.NO_VEIN) { + unknownVeinTypes++; + continue; + } + VeinSource source = VeinSource.fromByte(sourceArray[i]); + oreChunks.put( + getOreVeinKey(chunkXArray[i], chunkZArray[i]), + new OreVeinPosition( + dimensionId, + chunkXArray[i], + chunkZArray[i], + veinType, + depletedArray[i] == 1, + source)); + } + if (unknownVeinTypes > 0) { + VP.LOG.warn( + "Dimension {}: skipped {} entries with unknown vein type names while loading cache.", + dimensionId, + unknownVeinTypes); + } + } + + private void loadFluids(NBTTagCompound fluids) { + if (!fluids.hasKey("palette")) return; + + NBTTagList paletteTag = fluids.getTagList("palette", 8); + String[] palette = new String[paletteTag.tagCount()]; + for (int i = 0; i < palette.length; i++) { + palette[i] = paletteTag.getStringTagAt(i); + } + + int[] chunkXArray = fluids.getIntArray("chunkX"); + int[] chunkZArray = fluids.getIntArray("chunkZ"); + int[] fluidTypeIndexArray = fluids.getIntArray("fluidTypeIndex"); + int[] allChunkData = fluids.getIntArray("chunkData"); + int chunkDataSize = fluids.getInteger("chunkDataSize"); + + int fluidCount = chunkXArray.length; + undergroundFluids.ensureCapacity(undergroundFluids.size() + fluidCount); + + int unknownFluids = 0; + for (int i = 0; i < fluidCount; i++) { + int index = fluidTypeIndexArray[i]; + if (index < 0 || index >= palette.length) { + unknownFluids++; + continue; + } + Fluid fluid = FluidRegistry.getFluid(palette[index]); + if (fluid == null) { + unknownFluids++; + continue; + } + int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; + int baseOffset = i * chunkDataSize; + for (int x = 0; x < VP.undergroundFluidSizeChunkX; x++) { + System.arraycopy( + allChunkData, + baseOffset + x * VP.undergroundFluidSizeChunkZ, + chunks[x], + 0, + VP.undergroundFluidSizeChunkZ); + } + undergroundFluids.put( + getUndergroundFluidKey(chunkXArray[i], chunkZArray[i]), + new UndergroundFluidPosition(dimensionId, chunkXArray[i], chunkZArray[i], fluid, chunks)); + } + if (unknownFluids > 0) { + VP.LOG.warn( + "Dimension {}: skipped {} entries with unknown fluid names while loading cache.", + dimensionId, + unknownFluids); + } + } + private NBTTagCompound saveOres() { NBTTagCompound compound = new NBTTagCompound(); - Collection veins = oreChunks.values(); - int size = veins.size(); - - if (size == 0) { - return compound; + int size = oreChunks.size(); + if (size == 0) return compound; + + long[] sortedKeys = oreChunks.keySet().toLongArray(); + Arrays.sort(sortedKeys); + + List palette = new ArrayList<>(); + Map paletteIndex = new HashMap<>(); + for (long key : sortedKeys) { + String name = oreChunks.get(key).veinType.name; + if (!paletteIndex.containsKey(name)) { + paletteIndex.put(name, palette.size()); + palette.add(name); + } } - // Pre-allocate contiguous arrays for optimal cache line utilization int[] chunkXArray = new int[size]; int[] chunkZArray = new int[size]; - byte[] depletedFlags = new byte[size]; - NBTTagList veinTypeNamesList = new NBTTagList(); + int[] veinTypeIndexArray = new int[size]; + byte[] depletedArray = new byte[size]; + byte[] sourceArray = new byte[size]; - // Single-pass iteration for optimal access pattern - int i = 0; - for (OreVeinPosition vein : veins) { + for (int i = 0; i < size; i++) { + OreVeinPosition vein = oreChunks.get(sortedKeys[i]); chunkXArray[i] = vein.chunkX; chunkZArray[i] = vein.chunkZ; - depletedFlags[i] = vein.isDepleted() ? (byte) 1 : (byte) 0; - veinTypeNamesList.appendTag(new net.minecraft.nbt.NBTTagString(vein.veinType.name)); - i++; + veinTypeIndexArray[i] = paletteIndex.get(vein.veinType.name); + depletedArray[i] = vein.isDepleted() ? (byte) 1 : (byte) 0; + sourceArray[i] = vein.getSourceByte(); + } + + NBTTagList paletteTag = new NBTTagList(); + for (String name : palette) { + paletteTag.appendTag(new NBTTagString(name)); } - // Store as contiguous arrays - only 4 string operations vs 400,000+ + compound.setTag("palette", paletteTag); compound.setIntArray("chunkX", chunkXArray); compound.setIntArray("chunkZ", chunkZArray); - compound.setByteArray("depleted", depletedFlags); - compound.setTag("veinTypeNames", veinTypeNamesList); + compound.setIntArray("veinTypeIndex", veinTypeIndexArray); + compound.setByteArray("depleted", depletedArray); + compound.setByteArray("source", sourceArray); return compound; } private NBTTagCompound saveFluids() { NBTTagCompound compound = new NBTTagCompound(); - Collection fluids = undergroundFluids.values(); - int size = fluids.size(); + int size = undergroundFluids.size(); + if (size == 0) return compound; + + int chunkDataSize = VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ; - if (size == 0) { - return compound; + long[] sortedKeys = undergroundFluids.keySet().toLongArray(); + Arrays.sort(sortedKeys); + + List palette = new ArrayList<>(); + Map paletteIndex = new HashMap<>(); + for (long key : sortedKeys) { + String name = undergroundFluids.get(key).fluid.getName(); + if (!paletteIndex.containsKey(name)) { + paletteIndex.put(name, palette.size()); + palette.add(name); + } } - // Pre-allocate contiguous arrays for optimal cache performance int[] chunkXArray = new int[size]; int[] chunkZArray = new int[size]; - - // Calculate total chunk data size for flattened storage - int chunkDataSize = VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ; + int[] fluidTypeIndexArray = new int[size]; int[] allChunkData = new int[size * chunkDataSize]; - NBTTagList fluidNamesList = new NBTTagList(); - - // Single-pass iteration for optimal access pattern - int fluidIndex = 0; - for (UndergroundFluidPosition fluid : fluids) { - chunkXArray[fluidIndex] = fluid.chunkX; - chunkZArray[fluidIndex] = fluid.chunkZ; - fluidNamesList.appendTag(new net.minecraft.nbt.NBTTagString(fluid.fluid.getName())); - // Flatten 2D chunk array into contiguous memory layout - int baseOffset = fluidIndex * chunkDataSize; + for (int i = 0; i < size; i++) { + UndergroundFluidPosition fluid = undergroundFluids.get(sortedKeys[i]); + chunkXArray[i] = fluid.chunkX; + chunkZArray[i] = fluid.chunkZ; + fluidTypeIndexArray[i] = paletteIndex.get(fluid.fluid.getName()); + int baseOffset = i * chunkDataSize; for (int x = 0; x < VP.undergroundFluidSizeChunkX; x++) { System.arraycopy( fluid.chunks[x], @@ -128,196 +295,49 @@ private NBTTagCompound saveFluids() { baseOffset + x * VP.undergroundFluidSizeChunkZ, VP.undergroundFluidSizeChunkZ); } - fluidIndex++; } - // Store as contiguous arrays - minimal string operations + NBTTagList paletteTag = new NBTTagList(); + for (String name : palette) { + paletteTag.appendTag(new NBTTagString(name)); + } + + compound.setTag("palette", paletteTag); compound.setIntArray("chunkX", chunkXArray); compound.setIntArray("chunkZ", chunkZArray); + compound.setIntArray("fluidTypeIndex", fluidTypeIndexArray); compound.setIntArray("chunkData", allChunkData); compound.setInteger("chunkDataSize", chunkDataSize); - compound.setTag("fluidNames", fluidNamesList); return compound; } - @SuppressWarnings("unchecked") - public void loadFromNbt(NBTTagCompound compound) { - NBTTagCompound ores = compound.getCompoundTag("ores"); - - // Check if using optimized array format (new) vs legacy nested format (old) - if (ores.hasKey("chunkX") && ores.hasKey("chunkZ")) { - // OPTIMIZED PATH: Array-based loading for maximum cache efficiency - int[] chunkXArray = ores.getIntArray("chunkX"); - int[] chunkZArray = ores.getIntArray("chunkZ"); - byte[] depletedFlags = ores.getByteArray("depleted"); - NBTTagList veinTypeNamesList = ores.getTagList("veinTypeNames", 8); - - int size = chunkXArray.length; - int unknownVeinTypes = 0; - - // Pre-size HashMap to avoid rehashing during bulk load - oreChunks.ensureCapacity(oreChunks.size() + size); - - // Sequential array processing - optimal cache line utilization - for (int i = 0; i < size; i++) { - int chunkX = chunkXArray[i]; // Cache-friendly array access - int chunkZ = chunkZArray[i]; // Cache-friendly array access - boolean depleted = depletedFlags[i] == 1; - String veinTypeName = veinTypeNamesList.getStringTagAt(i); - VeinType veinType = VeinTypeCaching.getVeinType(veinTypeName); - if (veinType == VeinType.NO_VEIN) { - unknownVeinTypes++; - continue; - } - - oreChunks.put( - getOreVeinKey(chunkX, chunkZ), - new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); - } - if (unknownVeinTypes > 0) { - VP.LOG.warn( - "Dimension {}: skipped {} entries with unknown vein type names while loading cache.", - dimensionId, - unknownVeinTypes); - } - } else { - // LEGACY PATH: Backward compatibility for old nested compound format - for (NBTBase base : (Collection) ores.tagMap.values()) { - NBTTagCompound veinCompound = (NBTTagCompound) base; - int chunkX = veinCompound.getInteger("chunkX"); - int chunkZ = veinCompound.getInteger("chunkZ"); - boolean depleted = veinCompound.getBoolean("depleted"); - VeinType veinType; - if (veinCompound.hasKey("veinTypeId")) { - veinType = getVeinFromId(veinCompound.getShort("veinTypeId")); - if (veinType == null) continue; - markDirty(); - } else { - veinType = VeinTypeCaching.getVeinType(veinCompound.getString("veinTypeName")); - if (veinType == VeinType.NO_VEIN) continue; - } - - oreChunks.put( - getOreVeinKey(chunkX, chunkZ), - new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); - } - } + void putOreFromLegacyLoad(OreVeinPosition pos) { + oreChunks.put(getOreVeinKey(pos.chunkX, pos.chunkZ), pos); + } - NBTTagCompound fluids = compound.getCompoundTag("fluids"); - - // Check if using optimized array format (new) vs legacy nested format (old) - if (fluids.hasKey("chunkX") && fluids.hasKey("chunkZ")) { - // OPTIMIZED PATH: Array-based fluid loading for maximum cache efficiency - int[] chunkXArray = fluids.getIntArray("chunkX"); - int[] chunkZArray = fluids.getIntArray("chunkZ"); - int[] allChunkData = fluids.getIntArray("chunkData"); - int chunkDataSize = fluids.getInteger("chunkDataSize"); - NBTTagList fluidNamesList = fluids.getTagList("fluidNames", 8); - - int fluidCount = chunkXArray.length; - int unknownFluids = 0; - - // Pre-size HashMap to avoid rehashing during bulk load - undergroundFluids.ensureCapacity(undergroundFluids.size() + fluidCount); - - // Sequential array processing - optimal cache line utilization - for (int fluidIndex = 0; fluidIndex < fluidCount; fluidIndex++) { - int chunkX = chunkXArray[fluidIndex]; // Cache-friendly array access - int chunkZ = chunkZArray[fluidIndex]; // Cache-friendly array access - String fluidName = fluidNamesList.getStringTagAt(fluidIndex); - Fluid fluid = FluidRegistry.getFluid(fluidName); - if (fluid == null) { - unknownFluids++; - continue; - } - - // Reconstruct 2D chunk array from flattened data - int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; - int baseOffset = fluidIndex * chunkDataSize; - for (int x = 0; x < VP.undergroundFluidSizeChunkX; x++) { - System.arraycopy( - allChunkData, - baseOffset + x * VP.undergroundFluidSizeChunkZ, - chunks[x], - 0, - VP.undergroundFluidSizeChunkZ); - } - - undergroundFluids.put( - getUndergroundFluidKey(chunkX, chunkZ), - new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); - } - if (unknownFluids > 0) { - VP.LOG.warn( - "Dimension {}: skipped {} entries with unknown fluid names while loading cache.", - dimensionId, - unknownFluids); - } - } else { - // LEGACY PATH: Backward compatibility for old nested compound format - for (NBTBase base : (Collection) fluids.tagMap.values()) { - NBTTagCompound fluidCompound = (NBTTagCompound) base; - int chunkX = fluidCompound.getInteger("chunkX"); - int chunkZ = fluidCompound.getInteger("chunkZ"); - String fluidName = fluidCompound.getString("fluidName"); - Fluid fluid = FluidRegistry.getFluid(fluidName); - if (fluid == null) continue; - int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; - NBTTagList chunkList = fluidCompound.getTagList("chunks", 11); - for (int i = 0; i < VP.undergroundFluidSizeChunkX; i++) { - chunks[i] = chunkList.func_150306_c(i); - } - undergroundFluids.put( - getUndergroundFluidKey(chunkX, chunkZ), - new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); - } - } + void putFluidFromLegacyLoad(UndergroundFluidPosition pos) { + undergroundFluids.put(getUndergroundFluidKey(pos.chunkX, pos.chunkZ), pos); } - void loadLegacy(ByteBuffer oreChunksBuffer, ByteBuffer undergroundFluidsBuffer) { - if (oreChunksBuffer != null) { - while (oreChunksBuffer.remaining() >= Integer.BYTES * 2 + Short.BYTES) { - final int chunkX = oreChunksBuffer.getInt(); - final int chunkZ = oreChunksBuffer.getInt(); - final short veinTypeId = oreChunksBuffer.getShort(); - final boolean depleted = (veinTypeId & 0x8000) > 0; - final VeinType veinType = getVeinFromId((short) (veinTypeId & 0x7FFF)); - if (veinType == null) continue; - - oreChunks.put( - getOreVeinKey(chunkX, chunkZ), - new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, depleted)); - } - } - if (undergroundFluidsBuffer != null) { - while (undergroundFluidsBuffer.remaining() - >= Integer.BYTES * (3 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ)) { - final int chunkX = undergroundFluidsBuffer.getInt(); - final int chunkZ = undergroundFluidsBuffer.getInt(); - final int fluidIDorNameLength = undergroundFluidsBuffer.getInt(); - final Fluid fluid; - if (fluidIDorNameLength < 0) { // name length - byte[] fluidNameBytes = new byte[-fluidIDorNameLength]; - undergroundFluidsBuffer.get(fluidNameBytes); - String fluidName = new String(fluidNameBytes, StandardCharsets.UTF_8); - fluid = FluidRegistry.getFluid(fluidName); - } else { // ID (legacy save format) - fluid = FluidRegistry.getFluid(fluidIDorNameLength); - } - final int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; - for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { - for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { - chunks[offsetChunkX][offsetChunkZ] = undergroundFluidsBuffer.getInt(); - } - } - if (fluid != null) { - undergroundFluids.put( - getUndergroundFluidKey(chunkX, chunkZ), - new UndergroundFluidPosition(dimensionId, chunkX, chunkZ, fluid, chunks)); - } - } - } + void ensureOreCapacityForLegacyLoad(int expectedAdditions) { + oreChunks.ensureCapacity(oreChunks.size() + expectedAdditions); + } + + void ensureFluidCapacityForLegacyLoad(int expectedAdditions) { + undergroundFluids.ensureCapacity(undergroundFluids.size() + expectedAdditions); + } + + boolean hasOres() { + return !oreChunks.isEmpty(); + } + + boolean hasFluids() { + return !undergroundFluids.isEmpty(); + } + + void markPreventSaving() { + preventSaving = true; } private long getOreVeinKey(int chunkX, int chunkZ) { @@ -406,8 +426,6 @@ public void markDirty() { * respective endChunks. */ public void clearOreVeins(int startChunkX, int startChunkZ, int endChunkX, int endChunkZ) { - - // Remove entries if they fall within the corners // This method iterates for each chunk mapped. In many cases, it is probably faster to iterate over chunks in // the area to be cleared instead. i.e. if (chunksInClearArea < totalChunksMapped) {useAltIterator()}. If // someone calls this enough to make it a problem, they can add that. @@ -422,42 +440,4 @@ public void clearOreVeins(int startChunkX, int startChunkZ, int endChunkX, int e } } - private @Nullable VeinType getVeinFromId(short veinTypeId) { - final String veinTypeName = getIdConversionMap().get(veinTypeId); - if (veinTypeName == null) { - preventSaving = true; - VP.LOG.warn( - "Not loading ores in dimension {}. Couldn't find vein type for id {}, file {} may be missing.", - dimensionId, - veinTypeId, - oldIdFile.getAbsolutePath()); - return null; - } - return VeinTypeCaching.getVeinType(veinTypeName); - } - - private static Short2ObjectMap getIdConversionMap() { - if (idConversionMap != null) { - return idConversionMap; - } - - if (!oldIdFile.exists()) { - return Short2ObjectMaps.emptyMap(); - } - try { - final Gson gson = new Gson(); - final Reader reader = Files.newBufferedReader(oldIdFile.toPath()); - final Map map = gson.fromJson(reader, new TypeToken>() {}.getType()); - reader.close(); - Short2ObjectMap result = new Short2ObjectOpenHashMap<>(); - result.put((short) 0, Tags.ORE_MIX_NONE_NAME); - for (Map.Entry entry : map.entrySet()) { - result.put(entry.getValue().shortValue(), entry.getKey()); - } - return idConversionMap = result; - } catch (IOException e) { - VP.LOG.error("Failed to read legacy file at {}", oldIdFile.getAbsolutePath(), e); - return Short2ObjectMaps.emptyMap(); - } - } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/LegacyDimensionCacheLoader.java b/src/main/java/com/sinthoras/visualprospecting/database/LegacyDimensionCacheLoader.java new file mode 100644 index 00000000..d4b84e9d --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/database/LegacyDimensionCacheLoader.java @@ -0,0 +1,262 @@ +package com.sinthoras.visualprospecting.database; + +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.Collection; +import java.util.Map; + +import javax.annotation.Nullable; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.veintypes.VeinType; +import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; + +import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; +import it.unimi.dsi.fastutil.shorts.Short2ObjectMaps; +import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; + +/** + * One-time loaders for legacy on-disk formats that {@link DimensionCache}. + *
      + *
    • v0 — pre-NBT raw binary (separate files under {@code oreChunks/} and {@code undergroundFluids/}). Vein + * types referenced by numeric ID via a {@code veintypesLUT} JSON file.
    • + *
    • v1 — NBT compound-per-vein nested under {@code ores}/{@code fluids}. May still use numeric IDs.
    • + *
    • v2 — NBT parallel-array layout (no {@code version} key on the root compound).
    • + *
    + */ +final class LegacyDimensionCacheLoader { + + private static final File OLD_ID_FILE = new File(Tags.VISUALPROSPECTING_DIR, "veintypesLUT"); + private static Short2ObjectMap idConversionMap; + + private LegacyDimensionCacheLoader() {} + + @SuppressWarnings("unchecked") + static void loadV2Ores(DimensionCache target, NBTTagCompound ores) { + // v2 (parallel arrays) vs v1 (one nested compound per vein) + if (ores.hasKey("chunkX") && ores.hasKey("chunkZ")) { + int[] chunkXArray = ores.getIntArray("chunkX"); + int[] chunkZArray = ores.getIntArray("chunkZ"); + byte[] depletedFlags = ores.getByteArray("depleted"); + NBTTagList veinTypeNamesList = ores.getTagList("veinTypeNames", 8); + + int size = chunkXArray.length; + int unknownVeinTypes = 0; + target.ensureOreCapacityForLegacyLoad(size); + + for (int i = 0; i < size; i++) { + int chunkX = chunkXArray[i]; + int chunkZ = chunkZArray[i]; + boolean depleted = depletedFlags[i] == 1; + String veinTypeName = veinTypeNamesList.getStringTagAt(i); + VeinType veinType = VeinTypeCaching.getVeinType(veinTypeName); + if (veinType == VeinType.NO_VEIN) { + unknownVeinTypes++; + continue; + } + target.putOreFromLegacyLoad( + new OreVeinPosition( + target.dimensionId, + chunkX, + chunkZ, + veinType, + depleted, + VeinSource.UNKNOWN)); + } + if (unknownVeinTypes > 0) { + VP.LOG.warn( + "Dimension {}: skipped {} entries with unknown vein type names while loading cache.", + target.dimensionId, + unknownVeinTypes); + } + } else { + for (NBTBase base : (Collection) ores.tagMap.values()) { + NBTTagCompound veinCompound = (NBTTagCompound) base; + int chunkX = veinCompound.getInteger("chunkX"); + int chunkZ = veinCompound.getInteger("chunkZ"); + boolean depleted = veinCompound.getBoolean("depleted"); + VeinType veinType; + if (veinCompound.hasKey("veinTypeId")) { + veinType = getVeinFromId(target, veinCompound.getShort("veinTypeId")); + if (veinType == null) continue; + } else { + veinType = VeinTypeCaching.getVeinType(veinCompound.getString("veinTypeName")); + if (veinType == VeinType.NO_VEIN) continue; + } + target.putOreFromLegacyLoad( + new OreVeinPosition( + target.dimensionId, + chunkX, + chunkZ, + veinType, + depleted, + VeinSource.UNKNOWN)); + } + } + if (target.hasOres()) target.markDirty(); + } + + @SuppressWarnings("unchecked") + static void loadV2Fluids(DimensionCache target, NBTTagCompound fluids) { + // v2 (parallel arrays) vs v1 (one nested compound per fluid) + if (fluids.hasKey("chunkX") && fluids.hasKey("chunkZ")) { + int[] chunkXArray = fluids.getIntArray("chunkX"); + int[] chunkZArray = fluids.getIntArray("chunkZ"); + int[] allChunkData = fluids.getIntArray("chunkData"); + int chunkDataSize = fluids.getInteger("chunkDataSize"); + NBTTagList fluidNamesList = fluids.getTagList("fluidNames", 8); + + int fluidCount = chunkXArray.length; + int unknownFluids = 0; + target.ensureFluidCapacityForLegacyLoad(fluidCount); + + for (int fluidIndex = 0; fluidIndex < fluidCount; fluidIndex++) { + int chunkX = chunkXArray[fluidIndex]; + int chunkZ = chunkZArray[fluidIndex]; + String fluidName = fluidNamesList.getStringTagAt(fluidIndex); + Fluid fluid = FluidRegistry.getFluid(fluidName); + if (fluid == null) { + unknownFluids++; + continue; + } + int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; + int baseOffset = fluidIndex * chunkDataSize; + for (int x = 0; x < VP.undergroundFluidSizeChunkX; x++) { + System.arraycopy( + allChunkData, + baseOffset + x * VP.undergroundFluidSizeChunkZ, + chunks[x], + 0, + VP.undergroundFluidSizeChunkZ); + } + target.putFluidFromLegacyLoad( + new UndergroundFluidPosition(target.dimensionId, chunkX, chunkZ, fluid, chunks)); + } + if (unknownFluids > 0) { + VP.LOG.warn( + "Dimension {}: skipped {} entries with unknown fluid names while loading cache.", + target.dimensionId, + unknownFluids); + } + } else { + for (NBTBase base : (Collection) fluids.tagMap.values()) { + NBTTagCompound fluidCompound = (NBTTagCompound) base; + int chunkX = fluidCompound.getInteger("chunkX"); + int chunkZ = fluidCompound.getInteger("chunkZ"); + String fluidName = fluidCompound.getString("fluidName"); + Fluid fluid = FluidRegistry.getFluid(fluidName); + if (fluid == null) continue; + int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; + NBTTagList chunkList = fluidCompound.getTagList("chunks", 11); + for (int i = 0; i < VP.undergroundFluidSizeChunkX; i++) { + chunks[i] = chunkList.func_150306_c(i); + } + target.putFluidFromLegacyLoad( + new UndergroundFluidPosition(target.dimensionId, chunkX, chunkZ, fluid, chunks)); + } + } + if (target.hasFluids()) target.markDirty(); + } + + static void loadV0Binary(DimensionCache target, @Nullable ByteBuffer oreChunksBuffer, + @Nullable ByteBuffer undergroundFluidsBuffer) { + if (oreChunksBuffer != null) { + while (oreChunksBuffer.remaining() >= Integer.BYTES * 2 + Short.BYTES) { + final int chunkX = oreChunksBuffer.getInt(); + final int chunkZ = oreChunksBuffer.getInt(); + final short veinTypeId = oreChunksBuffer.getShort(); + final boolean depleted = (veinTypeId & 0x8000) > 0; + final VeinType veinType = getVeinFromId(target, (short) (veinTypeId & 0x7FFF)); + if (veinType == null) continue; + + target.putOreFromLegacyLoad( + new OreVeinPosition( + target.dimensionId, + chunkX, + chunkZ, + veinType, + depleted, + VeinSource.UNKNOWN)); + } + } + if (undergroundFluidsBuffer != null) { + while (undergroundFluidsBuffer.remaining() + >= Integer.BYTES * (3 + VP.undergroundFluidSizeChunkX * VP.undergroundFluidSizeChunkZ)) { + final int chunkX = undergroundFluidsBuffer.getInt(); + final int chunkZ = undergroundFluidsBuffer.getInt(); + final int fluidIDorNameLength = undergroundFluidsBuffer.getInt(); + final Fluid fluid; + if (fluidIDorNameLength < 0) { // name length + byte[] fluidNameBytes = new byte[-fluidIDorNameLength]; + undergroundFluidsBuffer.get(fluidNameBytes); + String fluidName = new String(fluidNameBytes, StandardCharsets.UTF_8); + fluid = FluidRegistry.getFluid(fluidName); + } else { // ID (legacy save format) + fluid = FluidRegistry.getFluid(fluidIDorNameLength); + } + final int[][] chunks = new int[VP.undergroundFluidSizeChunkX][VP.undergroundFluidSizeChunkZ]; + for (int offsetChunkX = 0; offsetChunkX < VP.undergroundFluidSizeChunkX; offsetChunkX++) { + for (int offsetChunkZ = 0; offsetChunkZ < VP.undergroundFluidSizeChunkZ; offsetChunkZ++) { + chunks[offsetChunkX][offsetChunkZ] = undergroundFluidsBuffer.getInt(); + } + } + if (fluid != null) { + target.putFluidFromLegacyLoad( + new UndergroundFluidPosition(target.dimensionId, chunkX, chunkZ, fluid, chunks)); + } + } + } + } + + private static @Nullable VeinType getVeinFromId(DimensionCache target, short veinTypeId) { + final String veinTypeName = getIdConversionMap().get(veinTypeId); + if (veinTypeName == null) { + target.markPreventSaving(); + VP.LOG.warn( + "Not loading ores in dimension {}. Couldn't find vein type for id {}, file {} may be missing.", + target.dimensionId, + veinTypeId, + OLD_ID_FILE.getAbsolutePath()); + return null; + } + return VeinTypeCaching.getVeinType(veinTypeName); + } + + private static Short2ObjectMap getIdConversionMap() { + if (idConversionMap != null) { + return idConversionMap; + } + + if (!OLD_ID_FILE.exists()) { + return Short2ObjectMaps.emptyMap(); + } + try { + final Gson gson = new Gson(); + final Reader reader = Files.newBufferedReader(OLD_ID_FILE.toPath()); + final Map map = gson.fromJson(reader, new TypeToken>() {}.getType()); + reader.close(); + Short2ObjectMap result = new Short2ObjectOpenHashMap<>(); + result.put((short) 0, Tags.ORE_MIX_NONE_NAME); + for (Map.Entry entry : map.entrySet()) { + result.put(entry.getValue().shortValue(), entry.getKey()); + } + return idConversionMap = result; + } catch (IOException e) { + VP.LOG.error("Failed to read legacy file at {}", OLD_ID_FILE.getAbsolutePath(), e); + return Short2ObjectMaps.emptyMap(); + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java b/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java index 40686618..7367f34d 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java @@ -9,29 +9,31 @@ public class OreVeinPosition { - public static final int BYTES_WITHOUT_VEIN_NAME = 3 * Integer.BYTES + Byte.BYTES; - public static final OreVeinPosition EMPTY_VEIN = new OreVeinPosition(0, 0, 0, VeinType.NO_VEIN, true); + public static final int BYTES_WITHOUT_VEIN_NAME = 3 * Integer.BYTES + 2 * Byte.BYTES; + public static final OreVeinPosition EMPTY_VEIN = new OreVeinPosition( + 0, + 0, + 0, + VeinType.NO_VEIN, + true, + VeinSource.UNKNOWN); public final int dimensionId; public final int chunkX; public final int chunkZ; public final VeinType veinType; - private boolean depleted = false; + private boolean depleted; + private final byte source; - public OreVeinPosition(int dimensionId, int chunkX, int chunkZ, VeinType veinType) { - this.dimensionId = dimensionId; - this.chunkX = Utils.mapToCenterOreChunkCoord(chunkX); - this.chunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); - this.veinType = veinType; - } - - public OreVeinPosition(int dimensionId, int chunkX, int chunkZ, VeinType veinType, boolean depleted) { + public OreVeinPosition(int dimensionId, int chunkX, int chunkZ, VeinType veinType, boolean depleted, + VeinSource source) { this.dimensionId = dimensionId; this.chunkX = Utils.mapToCenterOreChunkCoord(chunkX); this.chunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); this.veinType = veinType; this.depleted = depleted; + this.source = (byte) source.ordinal(); } public int getBlockX() { @@ -58,6 +60,14 @@ public boolean isDepleted() { return depleted; } + public VeinSource getSource() { + return VeinSource.fromByte(source); + } + + public byte getSourceByte() { + return source; + } + public void toggleDepleted() { depleted = !depleted; } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java index dbfb0978..5348d276 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/ServerCache.java @@ -39,9 +39,10 @@ protected File getStorageDirectory() { return Utils.getSubDirectory(Tags.SERVER_DIR); } - public synchronized void notifyOreVeinGeneration(int dimensionId, int chunkX, int chunkZ, final VeinType veinType) { + public synchronized void notifyOreVeinGeneration(int dimensionId, int chunkX, int chunkZ, final VeinType veinType, + VeinSource source) { if (veinType != VeinType.NO_VEIN) { - super.putOreVein(new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType)); + super.putOreVein(new OreVeinPosition(dimensionId, chunkX, chunkZ, veinType, false, source)); } } @@ -52,14 +53,11 @@ public void onVeinGenerated(VeinGenerateEvent event) { event.world.provider.dimensionId, event.oreSeedX, event.oreSeedZ, - event.layer.mWorldGenName); + VeinTypeCaching.getVeinType(event.layer.mWorldGenName), + VeinSource.GENERATED); } } - public void notifyOreVeinGeneration(int dimensionId, int chunkX, int chunkZ, final String veinName) { - notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, VeinTypeCaching.getVeinType(veinName)); - } - @SubscribeEvent public void onOreClicked(OreInteractEvent event) { World world = event.world; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/VeinSource.java b/src/main/java/com/sinthoras/visualprospecting/database/VeinSource.java new file mode 100644 index 00000000..d92e5bf0 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/database/VeinSource.java @@ -0,0 +1,25 @@ +package com.sinthoras.visualprospecting.database; + +/** + * Introduced for v3 of the server/client cache format.
    + * Store value as {@code byte} for tinier footprint.
    + *
    + * APPEND ONLY, reordering or inserting values will silently corrupt existing data. + */ +public enum VeinSource { + + UNKNOWN, + GENERATED, + RESCAN, + API; + // Add new values here not anywhere else + + private static final VeinSource[] VALUES = values(); + + public static VeinSource fromByte(byte ordinal) { + if (ordinal >= 0 && ordinal < VALUES.length) { + return VALUES[ordinal]; + } + return UNKNOWN; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index 365c7778..a0b1b211 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -76,7 +76,8 @@ private boolean loadLegacyVeinCache(File worldCacheDirectory) { if (dimension == null) { dimension = new DimensionCache(dimensionId); } - dimension.loadLegacy( + LegacyDimensionCacheLoader.loadV0Binary( + dimension, oreVeinDimensionBuffers.get(dimensionId), undergroundFluidDimensionBuffers.get(dimensionId)); dimension.markDirty(); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java index 889015f8..46a76fa0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java @@ -17,6 +17,7 @@ import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; +import com.sinthoras.visualprospecting.database.VeinSource; import com.sinthoras.visualprospecting.database.veintypes.VeinType; public class DimensionAnalysis { @@ -51,8 +52,12 @@ public void processMinecraftWorld(Collection regionFiles) { analysis.processMinecraftChunk(chunk); if (analysis.matchesSingleVein()) { - ServerCache.instance - .notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, analysis.getMatchedVein()); + ServerCache.instance.notifyOreVeinGeneration( + dimensionId, + chunkX, + chunkZ, + analysis.getMatchedVein(), + VeinSource.RESCAN); veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), analysis.getVeinBlockY()); } else { final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis( @@ -68,8 +73,12 @@ public void processMinecraftWorld(Collection regionFiles) { chunksForSecondIdentificationPass.values().parallelStream().forEach(chunk -> { chunk.cleanUpWithNeighbors(veinBlockY); - ServerCache.instance - .notifyOreVeinGeneration(dimensionId, chunk.chunkX, chunk.chunkZ, chunk.getMatchedVein()); + ServerCache.instance.notifyOreVeinGeneration( + dimensionId, + chunk.chunkX, + chunk.chunkZ, + chunk.getMatchedVein(), + VeinSource.RESCAN); }); } else { AnalysisProgressTracker.announceSlowDimension(dimensionId); @@ -81,8 +90,12 @@ public void processMinecraftWorld(Collection regionFiles) { analysis.processMinecraftChunk(chunk); if (analysis.matchesSingleVein()) { - ServerCache.instance - .notifyOreVeinGeneration(dimensionId, chunkX, chunkZ, analysis.getMatchedVein()); + ServerCache.instance.notifyOreVeinGeneration( + dimensionId, + chunkX, + chunkZ, + analysis.getMatchedVein(), + VeinSource.RESCAN); veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), analysis.getVeinBlockY()); } }); @@ -104,7 +117,8 @@ public void processMinecraftWorld(Collection regionFiles) { dimensionId, detailedAnalysis.chunkX, detailedAnalysis.chunkZ, - detailedAnalysis.getMatchedVein()); + detailedAnalysis.getMatchedVein(), + VeinSource.RESCAN); } }); }); diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java index 460c5e28..7382af12 100644 --- a/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java @@ -135,7 +135,7 @@ private static void sendDimVeins(EntityPlayerMP player, TeamProspectionData data boolean teamDepleted = depletedKeys.contains(key); if (vein.isDepleted() != teamDepleted) { - vein = new OreVeinPosition(dim, chunkX, chunkZ, vein.veinType, teamDepleted); + vein = new OreVeinPosition(dim, chunkX, chunkZ, vein.veinType, teamDepleted, vein.getSource()); } batch.add(vein); diff --git a/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java b/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java index bc8d9f14..96ad3ba1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java +++ b/src/main/java/com/sinthoras/visualprospecting/utils/VPByteBufUtils.java @@ -9,6 +9,7 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; +import com.sinthoras.visualprospecting.database.VeinSource; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import cpw.mods.fml.common.network.ByteBufUtils; @@ -21,6 +22,7 @@ public static void WriteOreVeinPosition(ByteBuf buf, OreVeinPosition oreVeinPosi buf.writeInt(oreVeinPosition.chunkX); buf.writeInt(oreVeinPosition.chunkZ); buf.writeBoolean(oreVeinPosition.isDepleted()); + buf.writeByte(oreVeinPosition.getSourceByte()); ByteBufUtils.writeUTF8String(buf, oreVeinPosition.veinType.name); } @@ -29,9 +31,10 @@ public static OreVeinPosition ReadOreVeinPosition(ByteBuf buf) { final int chunkX = buf.readInt(); final int chunkZ = buf.readInt(); final boolean isDepleted = buf.readBoolean(); + final VeinSource source = VeinSource.fromByte(buf.readByte()); final String veinName = ByteBufUtils.readUTF8String(buf); - return new OreVeinPosition(dimId, chunkX, chunkZ, VeinTypeCaching.getVeinType(veinName), isDepleted); + return new OreVeinPosition(dimId, chunkX, chunkZ, VeinTypeCaching.getVeinType(veinName), isDepleted, source); } public static void WriteUndergroundFluidPosition(ByteBuf buf, UndergroundFluidPosition undergroundFluidPosition) { From 2bce182d44189d01adcc502e0235c833d42a8caf Mon Sep 17 00:00:00 2001 From: Algent Date: Thu, 28 May 2026 22:06:49 +0200 Subject: [PATCH 115/132] Add admin command to upload client cache into your team (#88) --- README.md | 1 + .../visualprospecting/hooks/HooksShared.java | 8 ++ .../network/ProspectionSharing.java | 28 +++-- .../network/RequestTeamUploadMessage.java | 35 ++++++ .../task/SnapshotUploadTask.java | 7 ++ .../teams/TeamProspectionDispatcher.java | 12 ++- .../teams/TeamUploadCommand.java | 100 ++++++++++++++++++ .../assets/visualprospecting/lang/en_US.lang | 3 + 8 files changed, 184 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/network/RequestTeamUploadMessage.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/teams/TeamUploadCommand.java diff --git a/README.md b/README.md index 87928845..0edbfde1 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ Disable via `B:enableTeamSharing=false` in `config/visualprospecting.cfg`. Admin commands: - `/vp_team_info [player] [detailed]`: inspect a team's prospection record. - `/vp_team_clear `: wipe a team's server-side prospection record (op/console). + - `/vp_team_upload `: Push a player's local cache into their team's record (op/console). ### Reset Progress diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index 23c494bd..069e32a4 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -22,6 +22,7 @@ import com.sinthoras.visualprospecting.network.ProspectingNotification; import com.sinthoras.visualprospecting.network.ProspectingRequest; import com.sinthoras.visualprospecting.network.ProspectionSharing; +import com.sinthoras.visualprospecting.network.RequestTeamUploadMessage; import com.sinthoras.visualprospecting.network.TeamCatchupNotification; import com.sinthoras.visualprospecting.network.VeinDepletionMessage; import com.sinthoras.visualprospecting.network.WorldIdNotification; @@ -29,6 +30,7 @@ import com.sinthoras.visualprospecting.teams.TeamClearCommand; import com.sinthoras.visualprospecting.teams.TeamInfoCommand; import com.sinthoras.visualprospecting.teams.TeamProspectionData; +import com.sinthoras.visualprospecting.teams.TeamUploadCommand; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; @@ -92,6 +94,11 @@ public void fmlLifeCycleEvent(FMLPreInitializationEvent event) { TeamCatchupNotification.class, networkId++, Side.CLIENT); + VP.network.registerMessage( + RequestTeamUploadMessage.ClientHandler.class, + RequestTeamUploadMessage.class, + networkId++, + Side.CLIENT); ProspectorsLog.instance = new ProspectorsLog(); GameRegistry.registerItem(ProspectorsLog.instance, ProspectorsLog.instance.getUnlocalizedName()); @@ -151,6 +158,7 @@ public void fmlLifeCycleEvent(FMLServerStartingEvent event) { // Team-sharing debug commands event.registerServerCommand(new TeamInfoCommand()); event.registerServerCommand(new TeamClearCommand()); + event.registerServerCommand(new TeamUploadCommand()); } public void fmlLifeCycleEvent(FMLServerStartedEvent event) {} diff --git a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java index 6468a7a1..605e92fb 100644 --- a/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java +++ b/src/main/java/com/sinthoras/visualprospecting/network/ProspectionSharing.java @@ -12,22 +12,25 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.TransferCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; +import com.sinthoras.visualprospecting.teams.TeamProspectionDispatcher; import com.sinthoras.visualprospecting.utils.VPByteBufUtils; import cpw.mods.fml.common.network.simpleimpl.IMessage; import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; +import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; public class ProspectionSharing implements IMessage { - private static final int BYTES_OVERHEAD = Byte.BYTES + 2 * Byte.BYTES + 2 * Integer.BYTES; + private static final int BYTES_OVERHEAD = Byte.BYTES + 3 * Byte.BYTES + 2 * Integer.BYTES; final List oreVeins = new ArrayList<>(); final List undergroundFluids = new ArrayList<>(); private int bytesUsed = BYTES_OVERHEAD; boolean isFirstMessage = false; boolean isLastMessage = false; + boolean routeToTeam = false; public ProspectionSharing() {} @@ -62,6 +65,10 @@ public void setLastMessage(boolean isLastMessage) { this.isLastMessage = isLastMessage; } + public void setRouteToTeam(boolean routeToTeam) { + this.routeToTeam = routeToTeam; + } + public int getPacketBytes() { return BYTES_OVERHEAD + oreVeins.stream().mapToInt(OreVeinPosition::getPacketBytes).sum() + UndergroundFluidPosition.BYTES * undergroundFluids.size(); @@ -71,6 +78,7 @@ public int getPacketBytes() { public void fromBytes(ByteBuf buf) { isFirstMessage = buf.readByte() > 0; isLastMessage = buf.readByte() > 0; + routeToTeam = buf.readByte() > 0; oreVeins.addAll(VPByteBufUtils.ReadOreVeinPositions(buf)); undergroundFluids.addAll(VPByteBufUtils.ReadUndergroundFluidPositions(buf)); @@ -80,6 +88,7 @@ public void fromBytes(ByteBuf buf) { public void toBytes(ByteBuf buf) { buf.writeByte(isFirstMessage ? 1 : 0); buf.writeByte(isLastMessage ? 1 : 0); + buf.writeByte(routeToTeam ? 1 : 0); VPByteBufUtils.WriteOreVeinPositions(buf, oreVeins); VPByteBufUtils.WriteUndergroundFluidPositions(buf, undergroundFluids); @@ -89,6 +98,7 @@ public static class ServerHandler implements IMessageHandler> oreVeins = new HashMap<>(); private static final Map> undergroundFluids = new HashMap<>(); + private static final Object2BooleanOpenHashMap routeToTeam = new Object2BooleanOpenHashMap<>(); @Override public IMessage onMessage(ProspectionSharing message, MessageContext ctx) { @@ -102,6 +112,7 @@ public IMessage onMessage(ProspectionSharing message, MessageContext ctx) { if (message.isFirstMessage) { oreVeins.put(player, new ArrayList<>()); undergroundFluids.put(player, new ArrayList<>()); + routeToTeam.put(player, message.routeToTeam); } if (!oreVeins.containsKey(player) || !undergroundFluids.containsKey(player)) { return null; @@ -109,12 +120,15 @@ public IMessage onMessage(ProspectionSharing message, MessageContext ctx) { oreVeins.get(player).addAll(message.oreVeins); undergroundFluids.get(player).addAll(message.undergroundFluids); if (message.isLastMessage) { - TransferCache.instance.addClientProspectionData( - player.getPersistentID().toString(), - oreVeins.get(player), - undergroundFluids.get(player)); - oreVeins.remove(player); - undergroundFluids.remove(player); + List veins = oreVeins.remove(player); + List fluids = undergroundFluids.remove(player); + boolean toTeam = routeToTeam.removeBoolean(player); + if (toTeam) { + TeamProspectionDispatcher + .deliverProspectingResults(player, new ProspectingNotification(veins, fluids), false); + } else { + TransferCache.instance.addClientProspectionData(player.getPersistentID().toString(), veins, fluids); + } } return null; } diff --git a/src/main/java/com/sinthoras/visualprospecting/network/RequestTeamUploadMessage.java b/src/main/java/com/sinthoras/visualprospecting/network/RequestTeamUploadMessage.java new file mode 100644 index 00000000..a292d2b5 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/network/RequestTeamUploadMessage.java @@ -0,0 +1,35 @@ +package com.sinthoras.visualprospecting.network; + +import com.sinthoras.visualprospecting.database.ClientCache; +import com.sinthoras.visualprospecting.task.SnapshotUploadTask; +import com.sinthoras.visualprospecting.task.TaskManager; +import com.sinthoras.visualprospecting.teams.TeamProspectionData; + +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import io.netty.buffer.ByteBuf; + +/** + * Server → client trigger: ask the recipient to push their {@link ClientCache} to the server, routed into their team's + * {@link TeamProspectionData}. + */ +public class RequestTeamUploadMessage implements IMessage { + + public RequestTeamUploadMessage() {} + + @Override + public void fromBytes(ByteBuf buf) {} + + @Override + public void toBytes(ByteBuf buf) {} + + public static class ClientHandler implements IMessageHandler { + + @Override + public IMessage onMessage(RequestTeamUploadMessage message, MessageContext ctx) { + TaskManager.CLIENT_INSTANCE.addTask(new SnapshotUploadTask(true)); + return null; + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java index 4e9b7cde..8945f53a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java +++ b/src/main/java/com/sinthoras/visualprospecting/task/SnapshotUploadTask.java @@ -15,12 +15,18 @@ public class SnapshotUploadTask implements ITask { private final List oreVeins; private final List undergroundFluids; + private final boolean routeToTeam; private long lastUpload = 0; private boolean firstMessage = true; public SnapshotUploadTask() { + this(false); + } + + public SnapshotUploadTask(boolean routeToTeam) { oreVeins = ClientCache.instance.getAllOreVeins(); undergroundFluids = ClientCache.instance.getAllUndergroundFluids(); + this.routeToTeam = routeToTeam; } @Override @@ -42,6 +48,7 @@ public boolean process() { firstMessage = false; packet.setLastMessage(listsEmpty()); + packet.setRouteToTeam(routeToTeam); VP.network.sendToServer(packet); } diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java index 48198c6c..342b1fa7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java +++ b/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java @@ -35,12 +35,18 @@ private TeamProspectionDispatcher() {} */ public static void deliverProspectingResults(EntityPlayerMP player, List oreVeins, List fluids) { - deliverProspectingResults(player, new ProspectingNotification(oreVeins, fluids)); + deliverProspectingResults(player, new ProspectingNotification(oreVeins, fluids), true); } public static void deliverProspectingResults(EntityPlayerMP player, ProspectingNotification notification) { - // Notify the originating player with the pre-built notification. - VP.network.sendTo(notification, player); + deliverProspectingResults(player, notification, true); + } + + public static void deliverProspectingResults(EntityPlayerMP player, ProspectingNotification notification, + boolean notifySelf) { + if (notifySelf) { + VP.network.sendTo(notification, player); + } if (!Config.enableTeamSharing) return; diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamUploadCommand.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamUploadCommand.java new file mode 100644 index 00000000..5c7cbba9 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/teams/TeamUploadCommand.java @@ -0,0 +1,100 @@ +package com.sinthoras.visualprospecting.teams; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.StatCollector; + +import com.gtnewhorizon.gtnhlib.teams.Team; +import com.gtnewhorizon.gtnhlib.teams.TeamManager; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.network.RequestTeamUploadMessage; + +/** + * {@code /vp_team_upload }: ask {@code }'s client to push its {@code ClientCache} into the team's + * {@link TeamProspectionData}. + */ +public class TeamUploadCommand extends CommandBase { + + @Override + public String getCommandName() { + return "vp_team_upload"; + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return StatCollector.translateToLocal("visualprospecting.teamupload.command"); + } + + @Override + public int getRequiredPermissionLevel() { + return 2; + } + + @Override + public boolean canCommandSenderUseCommand(ICommandSender sender) { + if (sender instanceof EntityPlayerMP player) { + if (Objects.equals(player.mcServer.getServerOwner(), sender.getCommandSenderName())) { + return true; + } + } + return super.canCommandSenderUseCommand(sender); + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args) { + if (args.length == 1) { + return getListOfStringsMatchingLastWord(args, MinecraftServer.getServer().getAllUsernames()); + } + return Collections.emptyList(); + } + + @Override + public void processCommand(ICommandSender sender, String[] args) { + if (args.length != 1) { + sendError(sender, "visualprospecting.command.usage_error", getCommandName()); + return; + } + + if (!Config.enableTeamSharing) { + sendError(sender, "visualprospecting.teamcommand.sharing_disabled"); + return; + } + + EntityPlayerMP target = MinecraftServer.getServer().getConfigurationManager().func_152612_a(args[0]); + if (target == null) { + sendError(sender, "visualprospecting.teamcommand.player_offline", args[0]); + return; + } + + Team team = TeamManager.getTeamByPlayer(target.getUniqueID()); + if (team == null) { + sendError(sender, "visualprospecting.teamcommand.no_team", target.getCommandSenderName()); + return; + } + + VP.network.sendTo(new RequestTeamUploadMessage(), target); + + IChatComponent msg = new ChatComponentTranslation( + "visualprospecting.teamupload.requested", + target.getCommandSenderName(), + team.getTeamName()); + msg.getChatStyle().setColor(EnumChatFormatting.GREEN); + sender.addChatMessage(msg); + } + + private static void sendError(ICommandSender sender, String translationKey, Object... args) { + IChatComponent msg = new ChatComponentTranslation(translationKey, args); + msg.getChatStyle().setColor(EnumChatFormatting.RED); + sender.addChatMessage(msg); + } +} diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index 30ab9f2a..fc67eaa0 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -62,3 +62,6 @@ visualprospecting.teaminfo.summary= Across %s dim(s): %s veins (%s depleted), % visualprospecting.teaminfo.dim_line= Dim %s: %s veins (%s depleted), %s fluids visualprospecting.teamclear.command=/vp_team_clear : Delete that player team prospection record. visualprospecting.teamclear.success=Cleared team "%s": Removed %s veins and %s fluids. +visualprospecting.teamcommand.sharing_disabled=Team sharing is disabled in the server config. +visualprospecting.teamupload.command=/vp_team_upload : Push that player's local cache into their team's record. +visualprospecting.teamupload.requested=Requested upload of %s's local cache into team "%s". From e1a71cca4640b58c38c7c9399ec13aa57b719b27 Mon Sep 17 00:00:00 2001 From: Algent Date: Sat, 30 May 2026 22:30:03 +0200 Subject: [PATCH 116/132] Attempt at improving performance of vein/fluid layer in map (#89) --- .../sinthoras/visualprospecting/Config.java | 4 +- .../model/locations/OreVeinLocation.java | 12 ++-- .../model/render/OreVeinRenderStep.java | 9 +++ .../render/UndergroundFluidRenderStep.java | 64 +++++++++++-------- 4 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index 2465340a..80bb999c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -15,8 +15,8 @@ private static class Defaults { public static final int cacheGenerationLogUpdateMinTime = 5; public static final boolean recacheVeins = false; public static final int minDelayBetweenVeinRequests = 2000; - public static final int minZoomLevelForOreLabel = 1; - public static final int minZoomLevelForUndergroundFluidDetails = 2; + public static final int minZoomLevelForOreLabel = 2; + public static final int minZoomLevelForUndergroundFluidDetails = 3; public static final int uploadBandwidthBytes = 2000000; public static final int maxTransferCacheSizeMB = 50; public static final boolean enableVoxelMapWaypointsByDefault = false; diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index 8d1b1520..911fc7e3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -31,6 +31,8 @@ public class OreVeinLocation implements IWaypointAndLocationProvider { private final OreVeinPosition oreVeinPosition; private final String name; private final List materialNames; + private final IIconContainer iconContainer; + private final int color; private boolean isActiveAsWaypoint; @@ -39,6 +41,10 @@ public OreVeinLocation(OreVeinPosition oreVeinPosition) { name = EnumChatFormatting.WHITE + oreVeinPosition.veinType.getVeinName(); materialNames = oreVeinPosition.veinType.getOreMaterialNames().stream() .map(materialName -> EnumChatFormatting.GRAY + materialName).collect(Collectors.toList()); + final IOreMaterial representativeOre = oreVeinPosition.veinType.representativeOre; + final TextureSet textureSet = representativeOre.getTextureSet(); + iconContainer = textureSet.mTextures[OrePrefixes.ore.getTextureIndex()]; + color = LightingHelper.getColor(representativeOre.getRGBA()); } @Override @@ -117,13 +123,11 @@ public boolean drawSearchHighlight() { } public int getColor() { - return LightingHelper.getColor(getRepresentativeOre().getRGBA()); + return color; } public IIconContainer getIconFromRepresentativeOre() { - TextureSet textureSet = getRepresentativeOre().getTextureSet(); - - return textureSet.mTextures[OrePrefixes.ore.getTextureIndex()]; + return iconContainer; } public IOreMaterial getRepresentativeOre() { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java index a9c1b48c..d8021dbc 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java @@ -44,6 +44,15 @@ public void preRender(double topX, double topY, float drawScale, double zoom) { @Override public void draw(double topX, double topY, float drawScale, double zoom) { + final Minecraft mc = Minecraft.getMinecraft(); + final double scale = isXaero && shouldScale ? getScaling(zoom) : 1.0; + final double screenW = mc.displayWidth * scale; + final double screenH = mc.displayHeight * scale; + final double topMargin = (fontHeight + 5) * getFontScale() * scale; + if (topX + width < 0 || topX > screenW || topY + height < -topMargin || topY > screenH) { + return; + } + if (zoom >= Config.minZoomLevelForOreLabel && !location.isDepleted()) { final int fontColor = location.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F; DrawUtils.drawLabel( diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java index d3f6252b..0cef057e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java @@ -1,5 +1,6 @@ package com.sinthoras.visualprospecting.integration.model.render; +import net.minecraft.client.Minecraft; import net.minecraft.client.resources.I18n; import com.gtnewhorizons.navigator.api.model.steps.UniversalRenderStep; @@ -19,6 +20,13 @@ public UndergroundFluidRenderStep(UndergroundFluidLocation location) { @Override public void draw(double topX, double topY, float drawScale, double zoom) { + final Minecraft mc = Minecraft.getMinecraft(); + final double regionW = VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize; + final double regionH = VP.undergroundFluidSizeChunkZ * VP.chunkWidth * blockSize; + if (topX + regionW < 0 || topY + regionH < 0 || topX > mc.displayWidth || topY > mc.displayHeight) { + return; + } + renderChunks(topX, topY); setSize(VP.undergroundFluidSizeChunkX * VP.chunkWidth); int alpha = location.isActive() ? 255 : 74; @@ -58,45 +66,45 @@ public void draw(double topX, double topY, float drawScale, double zoom) { } private void renderChunks(double x, double y) { - if (getZoomStep() < Config.minZoomLevelForUndergroundFluidDetails || location.getMaxProduction() <= 0 + final double zoomStep = getZoomStep(); + if (zoomStep < Config.minZoomLevelForUndergroundFluidDetails - 1 || location.getMaxProduction() <= 0 || !location.isActive()) { return; } + final boolean drawLabels = zoomStep >= Config.minZoomLevelForUndergroundFluidDetails; + final int minProduction = location.getMinProduction(); + final int maxProduction = location.getMaxProduction(); + final int fluidColor = location.getFluid().getColor(); + final int[][] chunks = location.getChunks(); + final float productionRange = maxProduction - minProduction + 1; + + final Minecraft mc = Minecraft.getMinecraft(); + final double screenW = mc.displayWidth; + final double screenH = mc.displayHeight; setSize(VP.chunkWidth); + final double cellW = getAdjustedWidth(); + final double cellH = getAdjustedHeight(); for (int chunkX = 0; chunkX < VP.undergroundFluidSizeChunkX; chunkX++) { + final double cellX = x + chunkX * cellW; + if (cellX + cellW < 0 || cellX > screenW) continue; for (int chunkZ = 0; chunkZ < VP.undergroundFluidSizeChunkZ; chunkZ++) { - double xOffset = chunkX * getAdjustedWidth(); - double yOffset = chunkZ * getAdjustedHeight(); - int amount = location.getChunks()[chunkX][chunkZ]; - if (amount > 0) { - float alpha = (float) (amount - location.getMinProduction()) - / (location.getMaxProduction() - location.getMinProduction() + 1); - alpha = alpha * 255; - int fluidColor = location.getFluid().getColor(); - DrawUtils.drawRect( - x + xOffset, - y + yOffset, - getAdjustedWidth(), - getAdjustedHeight(), - fluidColor, - (int) alpha); + final double cellY = y + chunkZ * cellH; + if (cellY + cellH < 0 || cellY > screenH) continue; + int amount = chunks[chunkX][chunkZ]; + if (amount <= 0) continue; + int alpha = (int) ((amount - minProduction) / productionRange * 255); + DrawUtils.drawRect(cellX, cellY, cellW, cellH, fluidColor, alpha); - if (amount >= location.getMaxProduction()) { - DrawUtils.drawHollowRect( - x + xOffset, - y + yOffset, - getAdjustedWidth(), - getAdjustedHeight(), - 0xFFD700, - 204, - 1.5); - } + if (amount >= maxProduction) { + DrawUtils.drawHollowRect(cellX, cellY, cellW, cellH, 0xFFD700, 204, 1.5); + } + if (drawLabels) { DrawUtils.drawLabel( getFluidAmountFormatted(amount), - x + xOffset + getAdjustedWidth() / 2, - y + yOffset + getAdjustedHeight() / 2, + cellX + cellW / 2, + cellY + cellH / 2, 0xFFFFFFFF, 0xB4000000, true, From 5a44809c9c7c3bff3d054b63ea64d29dba964f27 Mon Sep 17 00:00:00 2001 From: Algent Date: Sat, 6 Jun 2026 19:51:39 +0200 Subject: [PATCH 117/132] Few more changes to fluid overlay (#90) --- .../database/UndergroundFluidPosition.java | 39 ++++++++++--------- .../locations/UndergroundFluidLocation.java | 33 ++++++++++++++++ .../render/UndergroundFluidRenderStep.java | 25 ++++++------ .../voxelmap/VoxelMapEventHandler.java | 3 +- 4 files changed, 68 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java b/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java index bec9e4c6..a6279707 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/UndergroundFluidPosition.java @@ -18,6 +18,8 @@ public class UndergroundFluidPosition { public final int chunkZ; public final Fluid fluid; public final int[][] chunks; + private final int minProduction; + private final int maxProduction; public UndergroundFluidPosition(int dimensionId, int chunkX, int chunkZ, Fluid fluid, int[][] chunks) { this.dimensionId = dimensionId; @@ -25,6 +27,23 @@ public UndergroundFluidPosition(int dimensionId, int chunkX, int chunkZ, Fluid f this.chunkZ = Utils.mapToCornerUndergroundFluidChunkCoord(chunkZ); this.fluid = fluid; this.chunks = chunks; + + int smallest = Integer.MAX_VALUE; + int largest = Integer.MIN_VALUE; + if (chunks != null) { + for (int cx = 0; cx < VP.undergroundFluidSizeChunkX; cx++) { + for (int cz = 0; cz < VP.undergroundFluidSizeChunkZ; cz++) { + int amount = chunks[cx][cz]; + if (amount < smallest) smallest = amount; + if (amount > largest) largest = amount; + } + } + } else { + smallest = 0; + largest = 0; + } + this.minProduction = smallest; + this.maxProduction = largest; } public int getBlockX() { @@ -36,27 +55,11 @@ public int getBlockZ() { } public int getMinProduction() { - int smallest = Integer.MAX_VALUE; - for (int chunkX = 0; chunkX < VP.undergroundFluidSizeChunkX; chunkX++) { - for (int chunkZ = 0; chunkZ < VP.undergroundFluidSizeChunkZ; chunkZ++) { - if (chunks[chunkX][chunkZ] < smallest) { - smallest = chunks[chunkX][chunkZ]; - } - } - } - return smallest; + return minProduction; } public int getMaxProduction() { - int largest = Integer.MIN_VALUE; - for (int chunkX = 0; chunkX < VP.undergroundFluidSizeChunkX; chunkX++) { - for (int chunkZ = 0; chunkZ < VP.undergroundFluidSizeChunkZ; chunkZ++) { - if (chunks[chunkX][chunkZ] > largest) { - largest = chunks[chunkX][chunkZ]; - } - } - } - return largest; + return maxProduction; } public boolean isProspected() { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java index aec1b2e7..1a2068cc 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/UndergroundFluidLocation.java @@ -1,17 +1,46 @@ package com.sinthoras.visualprospecting.integration.model.locations; import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; +import gregtech.api.enums.UndergroundFluidNames; +import it.unimi.dsi.fastutil.objects.Reference2IntMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; + public class UndergroundFluidLocation implements ILocationProvider { + private static final int NO_OVERRIDE = Integer.MIN_VALUE; + private static Reference2IntMap renderColorOverrides; + private final UndergroundFluidPosition undergroundFluidPosition; + private final int color; private boolean active; public UndergroundFluidLocation(UndergroundFluidPosition undergroundFluidPosition) { this.undergroundFluidPosition = undergroundFluidPosition; + this.color = resolveColor(undergroundFluidPosition.fluid); + } + + public static int resolveColor(Fluid fluid) { + if (fluid == null) return 0xFFFFFF; + if (renderColorOverrides == null) { + Reference2IntOpenHashMap map = new Reference2IntOpenHashMap<>(); + map.defaultReturnValue(NO_OVERRIDE); + for (UndergroundFluidNames entry : UndergroundFluidNames.values()) { + if (entry.renderColor == null) continue; + Fluid f = FluidRegistry.getFluid(entry.name); + if (f == null) continue; + int packed = ((entry.renderColor[0] & 0xFF) << 16) | ((entry.renderColor[1] & 0xFF) << 8) + | (entry.renderColor[2] & 0xFF); + map.put(f, packed); + } + renderColorOverrides = map; + } + int override = renderColorOverrides.getInt(fluid); + return override != NO_OVERRIDE ? override : fluid.getColor(); } @Override @@ -45,6 +74,10 @@ public Fluid getFluid() { return undergroundFluidPosition.fluid; } + public int getColor() { + return color; + } + public void setActive(boolean active) { this.active = active; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java index 0cef057e..d3c2ebfb 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java @@ -29,18 +29,16 @@ public void draw(double topX, double topY, float drawScale, double zoom) { renderChunks(topX, topY); setSize(VP.undergroundFluidSizeChunkX * VP.chunkWidth); - int alpha = location.isActive() ? 255 : 74; - DrawUtils.drawHollowRect( - topX, - topY, - getAdjustedWidth(), - getAdjustedHeight() - 0.5, - location.getFluid().getColor(), - alpha, - 2); + final int maxAmountInField = location.getMaxProduction(); + if (maxAmountInField > 0) { + int alpha = location.isActive() ? 255 : 74; + DrawUtils + .drawHollowRect(topX, topY, getAdjustedWidth(), getAdjustedHeight(), location.getColor(), alpha, 2); + } else { + DrawUtils.drawHollowRect(topX, topY, getAdjustedWidth(), getAdjustedHeight(), 0xFFFFFF, 74, 2); + } if (!isMinimap()) { - final int maxAmountInField = location.getMaxProduction(); String label = I18n.format("visualprospecting.empty"); if (maxAmountInField > 0) { label = location.getMinProduction() + "L - " @@ -75,9 +73,10 @@ private void renderChunks(double x, double y) { final int minProduction = location.getMinProduction(); final int maxProduction = location.getMaxProduction(); - final int fluidColor = location.getFluid().getColor(); + final int fluidColor = location.getColor(); final int[][] chunks = location.getChunks(); final float productionRange = maxProduction - minProduction + 1; + final boolean highlightPeak = maxProduction >= 10; final Minecraft mc = Minecraft.getMinecraft(); final double screenW = mc.displayWidth; @@ -93,10 +92,10 @@ private void renderChunks(double x, double y) { if (cellY + cellH < 0 || cellY > screenH) continue; int amount = chunks[chunkX][chunkZ]; if (amount <= 0) continue; - int alpha = (int) ((amount - minProduction) / productionRange * 255); + int alpha = productionRange > 1 ? (int) ((amount - minProduction) / productionRange * 255) : 10; DrawUtils.drawRect(cellX, cellY, cellW, cellH, fluidColor, alpha); - if (amount >= maxProduction) { + if (highlightPeak && amount >= maxProduction) { DrawUtils.drawHollowRect(cellX, cellY, cellW, cellH, 0xFFD700, 204, 1.5); } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java index 6eb5e645..993ffff3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/voxelmap/VoxelMapEventHandler.java @@ -12,6 +12,7 @@ import com.sinthoras.visualprospecting.database.OreVeinPosition; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.hooks.ProspectingNotificationEvent; +import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; import cpw.mods.fml.common.eventhandler.SubscribeEvent; @@ -50,7 +51,7 @@ public void onFluidProspected(ProspectingNotificationEvent.UndergroundFluid even UndergroundFluidPosition pos = event.getPosition(); int x = Utils.coordChunkToBlock(pos.chunkX); int z = Utils.coordChunkToBlock(pos.chunkZ); - int color = pos.fluid.getColor(); + int color = UndergroundFluidLocation.resolveColor(pos.fluid); TreeSet dim = new TreeSet<>(); dim.add(pos.dimensionId); From 6d5332c19170e5a25bef1ff3eb38c149fcff97cd Mon Sep 17 00:00:00 2001 From: Algent Date: Sun, 7 Jun 2026 17:33:55 +0200 Subject: [PATCH 118/132] Rewrote most logic behind /vp_recache (reconstruct server cache by scanning world files) (#92) --- dependencies.gradle | 6 +- .../sinthoras/visualprospecting/Config.java | 17 +- .../database/DimensionCache.java | 36 ++- .../database/OreVeinPosition.java | 2 +- .../database/VeinSource.java | 50 ++- .../database/WorldCache.java | 24 +- .../cachebuilder/AnalysisProgressTracker.java | 20 +- .../database/cachebuilder/ChunkAnalysis.java | 43 ++- .../cachebuilder/DetailedChunkAnalysis.java | 155 ++++----- .../cachebuilder/DimensionAnalysis.java | 255 ++++++++++----- .../cachebuilder/PartiallyLoadedChunk.java | 293 +++++++++--------- .../database/cachebuilder/WorldAnalysis.java | 35 ++- .../database/veintypes/VeinType.java | 98 ++++-- .../database/veintypes/VeinTypeCaching.java | 45 ++- 14 files changed, 662 insertions(+), 417 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 98ab7936..9e46042a 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,9 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.1.3:dev') - api('com.github.GTNewHorizons:GTNHLib:0.10.6:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.548:dev') + api('com.github.GTNewHorizons:GTNHLib:0.11.4:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.579:dev') + + compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.28-GTNH:dev') { transitive = false } runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.16')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index 80bb999c..c0dee5ab 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -20,7 +20,7 @@ private static class Defaults { public static final int uploadBandwidthBytes = 2000000; public static final int maxTransferCacheSizeMB = 50; public static final boolean enableVoxelMapWaypointsByDefault = false; - public static final int maxDimensionSizeMBForFastScanning = 10000; + public static final int maxRegionRowFileMBForInMemoryScan = 10000; } private static class Categories { @@ -43,7 +43,7 @@ private static class Categories { public static int uploadPacketsPerSecond = uploadBandwidthBytes / VP.uploadSizePerPacketInBytes; public static int maxTransferCacheSizeMB = Defaults.maxTransferCacheSizeMB; public static boolean enableVoxelMapWaypointsByDefault = Defaults.enableVoxelMapWaypointsByDefault; - public static int maxDimensionSizeMBForFastScanning = Defaults.maxDimensionSizeMBForFastScanning; + public static int maxRegionRowFileMBForInMemoryScan = Defaults.maxRegionRowFileMBForInMemoryScan; public static void syncronizeConfiguration(File configFile) { Configuration configuration = new Configuration(configFile); @@ -134,14 +134,13 @@ public static void syncronizeConfiguration(File configFile) { "[CLIENT / VoxelMap] Enable waypoints added by prospecting GT ore veins or underground fluids by default"); enableVoxelMapWaypointsByDefault = enableVoxelMapWaypointsByDefaultProperty.getBoolean(); - Property maxDimensionSizeMBForFastScanningProperty = configuration.get( + Property maxRegionRowFileMBForInMemoryScanProperty = configuration.get( Categories.caching, - "maxDimensionSizeMBForFastScanning", - Defaults.maxDimensionSizeMBForFastScanning, - "[Client + Server] Define the maximum size of a " - + "dimension in MB that can be processed in a single pass. Reduce this number if you run into " - + "memory issues during the initial world scan (OutOfMemoryException)."); - maxDimensionSizeMBForFastScanning = maxDimensionSizeMBForFastScanningProperty.getInt(); + "maxRegionRowFileMBForInMemoryScan", + Defaults.maxRegionRowFileMBForInMemoryScan, + "[CLIENT + SERVER] Limit total region file size the recache vein job can keep open at once. " + + "This is about size on disk and not actual RAM usage. Reduce this if you get a OutOfMemoryException during recache."); + maxRegionRowFileMBForInMemoryScan = maxRegionRowFileMBForInMemoryScanProperty.getInt(); if (configuration.hasChanged()) { configuration.save(); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index 7f9e9d1a..d8141107 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -371,11 +372,24 @@ public UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) { markDirty(); return UpdateResult.New; } + + // Stop update if lower trusted VeinSource + if (!oreVeinPosition.getSource().canOverwrite(storedOreVeinPosition.getSource())) { + return UpdateResult.AlreadyKnown; + } + if (storedOreVeinPosition.veinType != oreVeinPosition.veinType) { oreChunks.put(key, oreVeinPosition.joinDepletedState(storedOreVeinPosition)); markDirty(); return UpdateResult.New; } + + // If identical entry but "better" source we update it + if (storedOreVeinPosition.getSourceByte() != oreVeinPosition.getSourceByte()) { + oreChunks.put(key, oreVeinPosition.joinDepletedState(storedOreVeinPosition)); + markDirty(); + return UpdateResult.Updated; + } return UpdateResult.AlreadyKnown; } @@ -426,6 +440,14 @@ public void markDirty() { * respective endChunks. */ public void clearOreVeins(int startChunkX, int startChunkZ, int endChunkX, int endChunkZ) { + clearOreVeins(startChunkX, startChunkZ, endChunkX, endChunkZ, EnumSet.noneOf(VeinSource.class)); + } + + /** + * Reset selected veins within the area whose source is not in {@code protectedSources}. + */ + public void clearOreVeins(int startChunkX, int startChunkZ, int endChunkX, int endChunkZ, + EnumSet protectedSources) { // This method iterates for each chunk mapped. In many cases, it is probably faster to iterate over chunks in // the area to be cleared instead. i.e. if (chunksInClearArea < totalChunksMapped) {useAltIterator()}. If // someone calls this enough to make it a problem, they can add that. @@ -433,11 +455,23 @@ public void clearOreVeins(int startChunkX, int startChunkZ, int endChunkX, int e OreVeinPosition val = entry.getValue(); final boolean withinX = val.chunkX >= startChunkX && val.chunkX <= endChunkX; final boolean withinZ = val.chunkZ >= startChunkZ && val.chunkZ <= endChunkZ; - return withinX && withinZ; + if (!withinX || !withinZ) return false; + return !protectedSources.contains(val.getSource()); }); if (removedAny) { markDirty(); } } + /** + * Remove all ore veins from this dimension whose source is not in {@code protectedSources}. + */ + public void clearOreVeinsExcept(EnumSet protectedSources) { + boolean removedAny = oreChunks.long2ObjectEntrySet() + .removeIf(entry -> !protectedSources.contains(entry.getValue().getSource())); + if (removedAny) { + markDirty(); + } + } + } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java b/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java index 7367f34d..a58b3bb1 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/OreVeinPosition.java @@ -33,7 +33,7 @@ public OreVeinPosition(int dimensionId, int chunkX, int chunkZ, VeinType veinTyp this.chunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); this.veinType = veinType; this.depleted = depleted; - this.source = (byte) source.ordinal(); + this.source = source.toByte(); } public int getBlockX() { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/VeinSource.java b/src/main/java/com/sinthoras/visualprospecting/database/VeinSource.java index d92e5bf0..0b992a95 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/VeinSource.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/VeinSource.java @@ -1,25 +1,47 @@ package com.sinthoras.visualprospecting.database; /** - * Introduced for v3 of the server/client cache format.
    - * Store value as {@code byte} for tinier footprint.
    - *
    - * APPEND ONLY, reordering or inserting values will silently corrupt existing data. + * Added for v3 of the server/client cache format. Stored as a {@code byte} for tinier footprint. + *

    + * Never change or reuse the {@code id} of an existing constant, it would silently corrupt existing caches. */ public enum VeinSource { - UNKNOWN, - GENERATED, - RESCAN, - API; - // Add new values here not anywhere else + // id = byte on disk to match to this enum | trustLevel = trust hierarchy for overwriting + UNKNOWN(0, 0), + RESCAN(2, 1), + API(3, 2), + GENERATED(1, 3); - private static final VeinSource[] VALUES = values(); + private final int id; + private final int trustLevel; - public static VeinSource fromByte(byte ordinal) { - if (ordinal >= 0 && ordinal < VALUES.length) { - return VALUES[ordinal]; + VeinSource(int id, int trustLevel) { + this.id = id; + this.trustLevel = trustLevel; + } + + public boolean canOverwrite(VeinSource existing) { + return this.trustLevel >= existing.trustLevel; + } + + public byte toByte() { + return (byte) id; + } + + private static final VeinSource[] BY_ID; + static { + int maxId = 0; + for (VeinSource source : values()) { + maxId = Math.max(maxId, source.id); + } + BY_ID = new VeinSource[maxId + 1]; + for (VeinSource source : values()) { + BY_ID[source.id] = source; } - return UNKNOWN; + } + + public static VeinSource fromByte(byte id) { + return ((id >= 0) && (id < BY_ID.length) && (BY_ID[id] != null)) ? BY_ID[id] : UNKNOWN; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index a0b1b211..0f3de098 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -2,6 +2,7 @@ import java.io.File; import java.nio.ByteBuffer; +import java.util.EnumSet; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -103,6 +104,15 @@ public void reset() { isLoaded = false; } + /** + * Remove ore-vein entries across all dimensions whose source is not in {@code protectedSources}. + */ + public void resetExcept(EnumSet protectedSources) { + for (DimensionCache dim : dimensions.values()) { + dim.clearOreVeinsExcept(protectedSources); + } + } + /** * Reset some chunks. Not all, and (usually) not none - but some. Input coords are in chunk coordinates, NOT block * coords. @@ -114,16 +124,26 @@ public void reset() { * @param endZ The Z coord of the ending chunk. */ public void resetSome(int dimID, int startX, int startZ, int endX, int endZ) { + resetSome(dimID, startX, startZ, endX, endZ, EnumSet.noneOf(VeinSource.class)); + } + /** + * Same as {@link #resetSome(int, int, int, int, int)} but preserves entries whose source is in + * {@code protectedSources}. + */ + public void resetSome(int dimID, int startX, int startZ, int endX, int endZ, EnumSet protectedSources) { DimensionCache dim = dimensions.get(dimID); if (dim != null) { - dim.clearOreVeins(startX, startZ, endX, endZ); + dim.clearOreVeins(startX, startZ, endX, endZ, protectedSources); isLoaded = false; } } public void resetSpawnChunks(ChunkCoordinates spawn, int dimID) { + resetSpawnChunks(spawn, dimID, EnumSet.noneOf(VeinSource.class)); + } + public void resetSpawnChunks(ChunkCoordinates spawn, int dimID, EnumSet protectedSources) { int spawnChunkX = Utils.coordBlockToChunk(spawn.posX); int spawnChunkZ = Utils.coordBlockToChunk(spawn.posZ); @@ -133,7 +153,7 @@ public void resetSpawnChunks(ChunkCoordinates spawn, int dimID) { int endX = spawnChunkX + spawnChunksRadius; int endZ = spawnChunkZ + spawnChunksRadius; - resetSome(dimID, startX, startZ, endX, endZ); + resetSome(dimID, startX, startZ, endX, endZ, protectedSources); } protected DimensionCache.UpdateResult putOreVein(final OreVeinPosition oreVeinPosition) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java index 50d02394..65ad3477 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/AnalysisProgressTracker.java @@ -31,17 +31,9 @@ public static synchronized void dimensionProcessed() { updateLog(); } - public static synchronized void announceFastDimension(int dimensionId) { - final String message = "Processing dimension with id " + dimensionId + " with fast scanning."; - VP.info(message); - if (Utils.isLogicalClient()) { - ((MinecraftServerAccessor) MinecraftServer.getServer()).setUserMessage(message); - } - } - - public static synchronized void announceSlowDimension(int dimensionId) { - final String message = "Processing dimension with id " + dimensionId + " with slow (safe) scanning."; - VP.info(message); + public static synchronized void announceDimension(int dimensionId) { + final String message = "Processing dimension with id " + dimensionId + "."; + VP.LOG.info(message); if (Utils.isLogicalClient()) { ((MinecraftServerAccessor) MinecraftServer.getServer()).setUserMessage(message); } @@ -68,7 +60,7 @@ private static synchronized void updateLog() { + ") " + (numberOfRegionFiles == 0 ? 0 : ((regionFilesProcessed * 100) / numberOfRegionFiles)) + "%"; - VP.info(message); + VP.LOG.info(message); if (Utils.isLogicalClient()) { // Escape % for String.format ((MinecraftServerAccessor) MinecraftServer.getServer()).setUserMessage(message + "%"); @@ -84,7 +76,7 @@ public static synchronized void processingFinished() { final String message = "Parsing complete! Thank you for your patience. - Duration: " + format.format(elapsedTimeMS / 1000) + "sec"; - VP.info(message); + VP.LOG.info(message); if (Utils.isLogicalClient()) { ((MinecraftServerAccessor) MinecraftServer.getServer()).setUserMessage(message); } @@ -92,7 +84,7 @@ public static synchronized void processingFinished() { public static synchronized void notifyCorruptFile(File regionFile) { final String message = "Encountered corrupt/malformed/modified save file: " + regionFile; - VP.info(message); + VP.LOG.info(message); if (Utils.isLogicalClient()) { ((MinecraftServerAccessor) MinecraftServer.getServer()).setUserMessage(message); } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java index 2ecbb691..8379866c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/ChunkAnalysis.java @@ -1,22 +1,16 @@ package com.sinthoras.visualprospecting.database.cachebuilder; -import java.util.Comparator; -import java.util.Map; -import java.util.stream.Collectors; - import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.veintypes.VeinType; import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import gregtech.api.interfaces.IOreMaterial; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import it.unimi.dsi.fastutil.objects.ObjectSet; import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // A slim, but faster version to identify >90% of veins public class ChunkAnalysis { - private final ObjectSet matchedVeins = new ObjectOpenHashSet<>(); + private VeinType matchedVein = VeinType.NO_VEIN; private final Reference2IntOpenHashMap oreCounts = new Reference2IntOpenHashMap<>(); private int minVeinBlockY = VP.minecraftWorldHeight; private IOreMaterial mostCommonOre; @@ -35,33 +29,32 @@ public void processMinecraftChunk(final PartiallyLoadedChunk chunk) { } }); - // spotless:off - var byCount = oreCounts.reference2IntEntrySet() - .stream() - .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) - .collect(Collectors.toList()); - // spotless:on - - if (!byCount.isEmpty()) mostCommonOre = byCount.get(0).getKey(); + int highestOreCount = -1; + for (var entry : oreCounts.reference2IntEntrySet()) { + if (entry.getIntValue() > highestOreCount) { + highestOreCount = entry.getIntValue(); + mostCommonOre = entry.getKey(); + } + } } public boolean matchesSingleVein() { if (oreCounts.isEmpty()) return true; if (oreCounts.size() > 4) return false; - // spotless:off - VeinTypeCaching.getVeinTypes().stream() - .filter(vein -> vein.containsAllFoundOres(oreCounts.keySet(), dimName, mostCommonOre, minVeinBlockY)) - .forEach(matchedVeins::add); - // spotless:on - return matchedVeins.size() <= 1; + for (VeinType vein : VeinTypeCaching.getVeinTypesForOre(mostCommonOre)) { + if (vein.containsAllFoundOres(oreCounts.keySet(), dimName, mostCommonOre, minVeinBlockY)) { + if (matchedVein != VeinType.NO_VEIN) { + return false; + } + matchedVein = vein; + } + } + return matchedVein != VeinType.NO_VEIN; } // Result only valid if matchesSingleVein() returned true public VeinType getMatchedVein() { - if (matchedVeins.isEmpty()) { - return VeinType.NO_VEIN; - } - return matchedVeins.iterator().next(); + return matchedVein; } public int getVeinBlockY() { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index 6c4d2c34..273e450c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -1,9 +1,5 @@ package com.sinthoras.visualprospecting.database.cachebuilder; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.stream.IntStream; @@ -15,6 +11,9 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import gregtech.api.interfaces.IOreMaterial; +import it.unimi.dsi.fastutil.longs.Long2IntMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSet; import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; // Slower, but more sophisticated approach to identify overlapping veins @@ -26,6 +25,11 @@ public class DetailedChunkAnalysis { // For each height we count how often a ore (short) has occured private final Reference2IntOpenHashMap[] oresPerY = new Reference2IntOpenHashMap[VP.minecraftWorldHeight]; private final String dimName; + private VeinType resolvedVeinType = VeinType.NO_VEIN; + + // Surrounding ore-chunk neighbours, to resolve overlap + private static final int[][] NEIGHBOR_OFFSETS = { { -3, 3 }, { 0, 3 }, { 3, 3 }, { 3, 0 }, { 3, -3 }, { 0, -3 }, + { -3, -3 }, { -3, 0 } }; public DetailedChunkAnalysis(int dimensionId, String dimName, int chunkX, int chunkZ) { this.dimensionId = dimensionId; @@ -44,62 +48,30 @@ public void processMinecraftChunk(final PartiallyLoadedChunk chunk) { }); } - public void cleanUpWithNeighbors(final Map veinChunkY) { - final OreVeinPosition[] neighbors = new OreVeinPosition[] { - ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ + 3), - ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ + 3), - ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ + 3), - ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ), - ServerCache.instance.getOreVein(dimensionId, chunkX + 3, chunkZ - 3), - ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ - 3), - ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ - 3), - ServerCache.instance.getOreVein(dimensionId, chunkX - 3, chunkZ) }; - final int[] neighborVeinBlockY = new int[] { - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX - 3), - Utils.mapToCenterOreChunkCoord(chunkZ + 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX), - Utils.mapToCenterOreChunkCoord(chunkZ + 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX + 3), - Utils.mapToCenterOreChunkCoord(chunkZ + 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX + 3), - Utils.mapToCenterOreChunkCoord(chunkZ)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX + 3), - Utils.mapToCenterOreChunkCoord(chunkZ - 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX), - Utils.mapToCenterOreChunkCoord(chunkZ - 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX - 3), - Utils.mapToCenterOreChunkCoord(chunkZ - 3)), - 0), - veinChunkY.getOrDefault( - Utils.chunkCoordsToKey( - Utils.mapToCenterOreChunkCoord(chunkX - 3), - Utils.mapToCenterOreChunkCoord(chunkZ)), - 0) }; - - // Remove all generated ores from neighbors. They could also be generated in the same chunk, - // but that case is rare and therefore, neglected - for (int neighborId = 0; neighborId < neighbors.length; neighborId++) { - final OreVeinPosition neighbor = neighbors[neighborId]; + // Resolve chunk vein against its neighbours and cache the result. + public void resolve(final Long2IntMap veinChunkY) { + cleanUpWithNeighbors(veinChunkY); + resolvedVeinType = getMatchedVein(); + } + + public VeinType getResolvedVeinType() { + return resolvedVeinType; + } + + private void cleanUpWithNeighbors(final Long2IntMap veinChunkY) { + // Remove ores that spilled over from neighbouring veins. + for (int[] neighborOffset : NEIGHBOR_OFFSETS) { + final int neighborChunkX = chunkX + neighborOffset[0]; + final int neighborChunkZ = chunkZ + neighborOffset[1]; + + final long neighborKey = Utils.chunkCoordsToKey( + Utils.mapToCenterOreChunkCoord(neighborChunkX), + Utils.mapToCenterOreChunkCoord(neighborChunkZ)); + if (!veinChunkY.containsKey(neighborKey)) continue; + final int neighborVeinBlockY = veinChunkY.get(neighborKey); + + final OreVeinPosition neighbor = ServerCache.instance + .getOreVein(dimensionId, neighborChunkX, neighborChunkZ); if (neighbor.veinType == VeinType.NO_VEIN) continue; final boolean atCoordinateAxis = Math.abs(neighbor.chunkX - chunkX) < 3 @@ -107,28 +79,23 @@ public void cleanUpWithNeighbors(final Map veinChunkY) { final boolean canOverlap = atCoordinateAxis ? neighbor.veinType.canOverlapIntoNeighborOreChunkAtCoordinateAxis() : neighbor.veinType.canOverlapIntoNeighborOreChunk(); - if (canOverlap) { - final int veinBlockY = neighborVeinBlockY[neighborId]; + if (!canOverlap) continue; - for (int layerBlockY = 0; layerBlockY < VeinType.veinHeight; layerBlockY++) { - final int blockY = veinBlockY + layerBlockY; + for (int layerBlockY = 0; layerBlockY < VeinType.veinHeight; layerBlockY++) { + final int blockY = neighborVeinBlockY + layerBlockY; + if (blockY > 255) break; - if (blockY > 255) { - break; - } - - if (oresPerY[blockY] != null) { - for (IOreMaterial ore : neighbor.veinType.getOresAtLayer(layerBlockY)) { - oresPerY[blockY].removeInt(ore); - } + if (oresPerY[blockY] != null) { + for (IOreMaterial ore : neighbor.veinType.getOresAtLayer(layerBlockY)) { + oresPerY[blockY].removeInt(ore); } } } } } - public VeinType getMatchedVein() { - final Set matchedVeins = new HashSet<>(); + private VeinType getMatchedVein() { + final ObjectSet matchedVeins = new ObjectOpenHashSet<>(); final Reference2IntOpenHashMap allOres = new Reference2IntOpenHashMap<>(); @@ -142,34 +109,46 @@ public VeinType getMatchedVein() { if (allOres.isEmpty()) return VeinType.NO_VEIN; - // spotless:off - final Optional dominantOre = allOres.reference2IntEntrySet() - .stream() - .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) - .map(Map.Entry::getKey) - .findFirst(); - // spotless:on + IOreMaterial dominantOre = null; + int highestOreCount = -1; + for (var entry : allOres.reference2IntEntrySet()) { + if (entry.getIntValue() > highestOreCount) { + highestOreCount = entry.getIntValue(); + dominantOre = entry.getKey(); + } + } - if (!dominantOre.isPresent()) return VeinType.NO_VEIN; + if (dominantOre == null) return VeinType.NO_VEIN; - for (VeinType veinType : VeinTypeCaching.getVeinTypes()) { - if (veinType.matchesWithSpecificPrimaryOrSecondary(allOres.keySet(), dimName, dominantOre.get())) { + for (VeinType veinType : VeinTypeCaching.getVeinTypesForOre(dominantOre)) { + if (veinType.matchesWithSpecificPrimaryOrSecondary(allOres.keySet(), dimName, dominantOre)) { matchedVeins.add(veinType); } } if (matchedVeins.size() == 1) { return matchedVeins.iterator().next(); - } else if (matchedVeins.size() >= 2) { + } + if (matchedVeins.size() >= 2) { matchedVeins.removeIf( veinType -> IntStream.range(veinType.minBlockY, veinType.maxBlockY) .noneMatch(blockY -> isOreVeinGeneratedAtHeight(veinType, blockY))); + return matchedVeins.size() == 1 ? matchedVeins.iterator().next() : VeinType.NO_VEIN; + } + return matchIgnoringSporadic(allOres.keySet(), dominantOre); + } - if (matchedVeins.size() == 1) { - return matchedVeins.iterator().next(); + private VeinType matchIgnoringSporadic(Set foundOres, IOreMaterial dominantOre) { + VeinType onlyMatch = VeinType.NO_VEIN; + for (VeinType veinType : VeinTypeCaching.getVeinTypesForOre(dominantOre)) { + if (veinType.matchesIgnoringSporadic(foundOres, dimName, dominantOre)) { + if (onlyMatch != VeinType.NO_VEIN) { + return VeinType.NO_VEIN; + } + onlyMatch = veinType; } } - return VeinType.NO_VEIN; + return onlyMatch; } private boolean isOreVeinGeneratedAtHeight(VeinType veinType, int blockY) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java index 46a76fa0..3648a27f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java @@ -2,9 +2,12 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.DataFormatException; @@ -13,6 +16,7 @@ import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; +import com.github.bsideup.jabel.Desugar; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; @@ -20,8 +24,20 @@ import com.sinthoras.visualprospecting.database.VeinSource; import com.sinthoras.visualprospecting.database.veintypes.VeinType; +import cpw.mods.fml.common.Optional; +import gregtech.api.enums.Mods; +import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2IntMap; +import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; +import micdoodle8.mods.galacticraft.api.galaxies.CelestialBody; +import micdoodle8.mods.galacticraft.api.prefab.world.gen.WorldProviderSpace; + public class DimensionAnalysis { + private static final Pattern REGION_FILE_NAME = Pattern.compile("^r\\.-?\\d+\\.-?\\d+\\.mca$"); + private static final int INVALID_REGION_COORD = Integer.MIN_VALUE; + public final int dimensionId; public final String dimensionName; @@ -37,100 +53,169 @@ private interface IChunkHandler { public void processMinecraftWorld(Collection regionFiles) { if (regionFiles.isEmpty()) return; - final Map veinBlockY = new ConcurrentHashMap<>(); - final long dimensionSizeMB = regionFiles.stream().mapToLong(File::length).sum() >> 20; - if (dimensionSizeMB <= Config.maxDimensionSizeMBForFastScanning) { - AnalysisProgressTracker.announceFastDimension(dimensionId); - AnalysisProgressTracker.setNumberOfRegionFiles(regionFiles.size()); + AnalysisProgressTracker.announceDimension(dimensionId); + + // Group region files by rows, skipping any with malformed names + final Int2ObjectAVLTreeMap> regionFilesByRow = new Int2ObjectAVLTreeMap<>(); + int malformedRegionFileCount = 0; + for (File regionFile : regionFiles) { + final int regionZ = parseRegionZ(regionFile); + if (regionZ == INVALID_REGION_COORD) { + VP.LOG.warn("Invalid region file found! {} continuing", regionFile.getAbsolutePath()); + malformedRegionFileCount++; + } else { + regionFilesByRow.computeIfAbsent(regionZ, value -> new ArrayList<>()).add(regionFile); + } + } + + final long maxRowSizeMBForHolding = Config.maxRegionRowFileMBForInMemoryScan; + int totalRegionFilePasses = regionFiles.size() - malformedRegionFileCount; + for (List row : regionFilesByRow.values()) { + if (rowSizeMB(row) > maxRowSizeMBForHolding) { + totalRegionFilePasses += row.size(); + } + } + AnalysisProgressTracker.setNumberOfRegionFiles(totalRegionFilePasses); + + final Long2IntOpenHashMap veinBlockY = new Long2IntOpenHashMap(); + + final int[] rows = regionFilesByRow.keySet().toIntArray(); + final Int2ObjectOpenHashMap heldRows = new Int2ObjectOpenHashMap<>(); + int rowToFinalize = 0; + for (int i = 0; i < rows.length; i++) { + final int regionZ = rows[i]; + heldRows.put(regionZ, fastPassRow(regionFilesByRow.get(regionZ), veinBlockY, maxRowSizeMBForHolding)); + + // Once both below and above rows are processed it's safe to finalize the middle one. + while (rowToFinalize < i && rows[rowToFinalize] + 1 <= regionZ) { + finalizeRow(heldRows.remove(rows[rowToFinalize]), veinBlockY); + rowToFinalize++; + } + } + while (rowToFinalize < rows.length) { + finalizeRow(heldRows.remove(rows[rowToFinalize]), veinBlockY); + rowToFinalize++; + } + } - final Map chunksForSecondIdentificationPass = new ConcurrentHashMap<>(); + // Fast-pass one region row. write single vein match, hold on ambiguous matches for later. + private RegionRowResult fastPassRow(List rowRegionFiles, Long2IntMap veinBlockY, + long maxRowSizeMBForHolding) { + final boolean holdInMemory = rowSizeMB(rowRegionFiles) <= maxRowSizeMBForHolding; + final Queue singleMatches = new ConcurrentLinkedQueue<>(); + final Queue ambiguousChunks = holdInMemory ? new ConcurrentLinkedQueue<>() : null; - regionFiles.parallelStream().forEach(regionFile -> { - executeForEachGeneratedOreChunk(regionFile, (chunk, chunkX, chunkZ) -> { + rowRegionFiles.parallelStream() + .forEach(regionFile -> executeForEachGeneratedOreChunk(regionFile, (chunk, chunkX, chunkZ) -> { final ChunkAnalysis analysis = new ChunkAnalysis(dimensionName); analysis.processMinecraftChunk(chunk); if (analysis.matchesSingleVein()) { - ServerCache.instance.notifyOreVeinGeneration( - dimensionId, - chunkX, - chunkZ, - analysis.getMatchedVein(), - VeinSource.RESCAN); - veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), analysis.getVeinBlockY()); - } else { + final VeinType veinType = analysis.getMatchedVein(); + if (veinType != VeinType.NO_VEIN) { + singleMatches.add(new PendingOreVein(chunkX, chunkZ, veinType, analysis.getVeinBlockY())); + } + } else if (holdInMemory) { final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis( dimensionId, dimensionName, chunkX, chunkZ); detailedChunk.processMinecraftChunk(chunk); - chunksForSecondIdentificationPass.put(Utils.chunkCoordsToKey(chunkX, chunkZ), detailedChunk); + ambiguousChunks.add(detailedChunk); } - }); - }); + })); + + for (PendingOreVein singleMatch : singleMatches) { + ServerCache.instance.notifyOreVeinGeneration( + dimensionId, + singleMatch.chunkX, + singleMatch.chunkZ, + singleMatch.veinType, + VeinSource.RESCAN); + veinBlockY.put(Utils.chunkCoordsToKey(singleMatch.chunkX, singleMatch.chunkZ), singleMatch.veinBlockY); + } + + return holdInMemory ? RegionRowResult.held(ambiguousChunks) : RegionRowResult.reRead(rowRegionFiles); + } + + // Resolve a row's overlapping chunks against their neighbours + private void finalizeRow(RegionRowResult row, Long2IntMap veinBlockY) { + if (row == null) return; - chunksForSecondIdentificationPass.values().parallelStream().forEach(chunk -> { - chunk.cleanUpWithNeighbors(veinBlockY); + if (row.heldAmbiguousChunks != null) { + row.heldAmbiguousChunks.parallelStream().forEach(detailedChunk -> detailedChunk.resolve(veinBlockY)); + for (DetailedChunkAnalysis detailedChunk : row.heldAmbiguousChunks) { ServerCache.instance.notifyOreVeinGeneration( dimensionId, - chunk.chunkX, - chunk.chunkZ, - chunk.getMatchedVein(), + detailedChunk.chunkX, + detailedChunk.chunkZ, + detailedChunk.getResolvedVeinType(), VeinSource.RESCAN); - }); + } } else { - AnalysisProgressTracker.announceSlowDimension(dimensionId); - AnalysisProgressTracker.setNumberOfRegionFiles(regionFiles.size() * 2); + final Queue resolved = new ConcurrentLinkedQueue<>(); + row.rowRegionFiles.parallelStream() + .forEach(regionFile -> executeForEachGeneratedOreChunk(regionFile, (chunk, chunkX, chunkZ) -> { + if (ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ).veinType == VeinType.NO_VEIN) { + final DetailedChunkAnalysis detailedChunk = new DetailedChunkAnalysis( + dimensionId, + dimensionName, + chunkX, + chunkZ); + detailedChunk.processMinecraftChunk(chunk); + detailedChunk.resolve(veinBlockY); + if (detailedChunk.getResolvedVeinType() != VeinType.NO_VEIN) { + resolved.add( + new PendingOreVein(chunkX, chunkZ, detailedChunk.getResolvedVeinType(), 0)); + } + } + })); + for (PendingOreVein result : resolved) { + ServerCache.instance.notifyOreVeinGeneration( + dimensionId, + result.chunkX, + result.chunkZ, + result.veinType, + VeinSource.RESCAN); + } + } + } - regionFiles.parallelStream().forEach(regionFile -> { - executeForEachGeneratedOreChunk(regionFile, (chunk, chunkX, chunkZ) -> { - final ChunkAnalysis analysis = new ChunkAnalysis(dimensionName); - analysis.processMinecraftChunk(chunk); + private static int parseRegionZ(File regionFile) { + final Matcher matcher = REGION_FILE_NAME.matcher(regionFile.getName()); + if (!matcher.matches()) return INVALID_REGION_COORD; + try { + return Integer.parseInt(regionFile.getName().split("\\.")[2]); + } catch (NumberFormatException ignored) { + return INVALID_REGION_COORD; + } + } - if (analysis.matchesSingleVein()) { - ServerCache.instance.notifyOreVeinGeneration( - dimensionId, - chunkX, - chunkZ, - analysis.getMatchedVein(), - VeinSource.RESCAN); - veinBlockY.put(Utils.chunkCoordsToKey(chunkX, chunkZ), analysis.getVeinBlockY()); - } - }); - }); + private static long rowSizeMB(List regionFiles) { + return regionFiles.stream().mapToLong(File::length).sum() >> 20; + } - regionFiles.parallelStream().forEach(regionFile -> { - executeForEachGeneratedOreChunk(regionFile, (chunk, chunkX, chunkZ) -> { - if (ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ).veinType == VeinType.NO_VEIN) { - final DetailedChunkAnalysis detailedAnalysis = new DetailedChunkAnalysis( - dimensionId, - dimensionName, - chunkX, - chunkZ); + @Desugar + private record RegionRowResult(Collection heldAmbiguousChunks, List rowRegionFiles) { - detailedAnalysis.processMinecraftChunk(chunk); - detailedAnalysis.cleanUpWithNeighbors(veinBlockY); + static RegionRowResult held(Collection heldAmbiguousChunks) { + return new RegionRowResult(heldAmbiguousChunks, null); + } - ServerCache.instance.notifyOreVeinGeneration( - dimensionId, - detailedAnalysis.chunkX, - detailedAnalysis.chunkZ, - detailedAnalysis.getMatchedVein(), - VeinSource.RESCAN); - } - }); - }); + static RegionRowResult reRead(List rowRegionFiles) { + return new RegionRowResult(null, rowRegionFiles); } } + @Desugar + private record PendingOreVein(int chunkX, int chunkZ, VeinType veinType, int veinBlockY) { + + } + private void executeForEachGeneratedOreChunk(File regionFile, IChunkHandler chunkHandler) { try { - if (!Pattern.matches("^r\\.-?\\d+\\.-?\\d+\\.mca$", regionFile.getName())) { - VP.warn("Invalid region file found! " + regionFile.getCanonicalPath() + " continuing"); - return; - } final String[] parts = regionFile.getName().split("\\."); final int regionChunkX = Integer.parseInt(parts[1]) << 5; final int regionChunkZ = Integer.parseInt(parts[2]) << 5; @@ -144,6 +229,12 @@ private void executeForEachGeneratedOreChunk(File regionFile, IChunkHandler chun if (chunkX != Utils.mapToCenterOreChunkCoord(chunkX)) continue; if (chunkZ != Utils.mapToCenterOreChunkCoord(chunkZ)) continue; + // Skip chunks already cached with higher trustLevel than VeinSource.RESCAN + if (!VeinSource.RESCAN.canOverwrite( + ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ).getSource())) { + continue; + } + NBTTagCompound chunk = region.getChunk(localChunkX, localChunkZ); if (chunk == null) continue; @@ -161,10 +252,32 @@ private void executeForEachGeneratedOreChunk(File regionFile, IChunkHandler chun } } + // Resolves the dimension name which will help filter ore veins private String getDimensionName() { - WorldServer world = DimensionManager.getWorld(dimensionId); - if (world == null) return ""; - WorldProvider provider = world.provider; - return provider == null ? "" : provider.getDimensionName(); + final WorldServer world = DimensionManager.getWorld(dimensionId); + WorldProvider provider = world != null ? world.provider : null; + if (provider == null) { + try { + provider = DimensionManager.createProviderFor(dimensionId); + } catch (Throwable t) { + VP.LOG.warn("Could not resolve a provider for dimensionId={}: {}", dimensionId, t); + return ""; + } + } + + final String celestialName = Mods.GalacticraftCore.isModLoaded() ? getCelestialBodyName(provider) : null; + if (celestialName != null) return celestialName; + + final String name = provider.getDimensionName(); + return name == null ? "" : name; + } + + @Optional.Method(modid = Mods.ModIDs.GALACTICRAFT_CORE) + private static String getCelestialBodyName(WorldProvider provider) { + if (provider instanceof WorldProviderSpace space) { + final CelestialBody body = space.getCelestialBody(); + return body == null ? null : body.getName(); + } + return null; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java index d37a26a2..d4c10150 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java @@ -20,7 +20,7 @@ import gregtech.common.ores.GTOreAdapter; import gregtech.common.ores.OreInfo; import gregtech.common.ores.OreManager; -import it.unimi.dsi.fastutil.ints.Int2ShortFunction; +import it.unimi.dsi.fastutil.ints.Int2IntFunction; public class PartiallyLoadedChunk { @@ -28,9 +28,10 @@ public class PartiallyLoadedChunk { private static final int BLOCKS_PER_EBS = SECTION_SIZE * SECTION_SIZE * SECTION_SIZE; public static final int CHUNK_HEIGHT = 256; private static final int SECTIONS_PER_CHUNK = CHUNK_HEIGHT / SECTION_SIZE; + private static final int NIBBLE_ARRAY_SIZE = BLOCKS_PER_EBS / 2; // Expected byte-array lengths for nibble arrays - private final Int2ShortFunction[] blocks = new Int2ShortFunction[SECTIONS_PER_CHUNK]; - private final Int2ShortFunction[] metas = new Int2ShortFunction[SECTIONS_PER_CHUNK]; + private final Int2IntFunction[] blocks = new Int2IntFunction[SECTIONS_PER_CHUNK]; + private final Int2IntFunction[] metas = new Int2IntFunction[SECTIONS_PER_CHUNK]; private List tiles; @@ -44,154 +45,144 @@ public void load(NBTTagCompound chunk, int chunkX, int chunkZ) { byte y = section.getByte("Y"); if (section.hasKey("Blocks16")) { - // chunk saved with NotEnoughIds - - ShortBuffer blocks = ByteBuffer.wrap(section.getByteArray("Blocks16")).asShortBuffer(); - ShortBuffer metas = ByteBuffer.wrap(section.getByteArray("Data16")).asShortBuffer(); - - if (blocks.capacity() == 0 || metas.capacity() == 0) { - // no-op for empty sections - this.blocks[y] = i -> (short) 0; - this.metas[y] = i -> (short) 0; - continue; - } - - if (blocks.capacity() != BLOCKS_PER_EBS) { - VP.LOG.error( - "Corrupt section detected at X={}, Y={}, Z={} (Blocks16 length was {}, needs {})", - chunkX, - y, - chunkZ, - blocks.capacity(), - BLOCKS_PER_EBS); - continue; - } - - if (metas.capacity() != BLOCKS_PER_EBS) { - VP.LOG.error( - "Corrupt section detected at X={}, Y={}, Z={} (Data16 length was {}, needs {})", - chunkX, - y, - chunkZ, - metas.capacity(), - BLOCKS_PER_EBS); - continue; - } - - this.blocks[y] = blocks::get; - this.metas[y] = metas::get; - - } else if (section.hasKey("Add") || section.hasKey("BlocksB2Hi")) { - // chunk saved with EndlessIds - - // 00FF - ByteBuffer blocks1Byte = ByteBuffer.wrap(section.getByteArray("Blocks")); - // 0F00 - ByteBuffer blocks2Lo; - if (section.hasKey("Add")) { - blocks2Lo = ByteBuffer.wrap(section.getByteArray("Add")); - } else { - blocks2Lo = null; - } - // F000 - ByteBuffer blocks2Hi; - if (section.hasKey("BlocksB2Hi")) { - blocks2Hi = ByteBuffer.wrap(section.getByteArray("BlocksB2Hi")); - } else { - blocks2Hi = null; - } - - this.blocks[y] = i -> { - int nibbleShift = (i & 1) * 4; - short id = (short) (blocks1Byte.get(i) & 0xFF); - if (blocks2Lo != null) { - id |= (short) (((blocks2Lo.get(i >> 1) >> nibbleShift) & 0xF) << 8); - } - if (blocks2Hi != null) { - id |= (short) (((blocks2Hi.get(i >> 1) >> nibbleShift) & 0xF) << 12); - } - return id; - }; - - // 000F - ByteBuffer meta1Lo = ByteBuffer.wrap(section.getByteArray("Data")); - // 00F0 - ByteBuffer meta1Hi; - if (section.hasKey("Data1High")) { - meta1Hi = ByteBuffer.wrap(section.getByteArray("Data1High")); - } else { - meta1Hi = null; - } - // FF00 - ByteBuffer meta2; - if (section.hasKey("Data2")) { - meta2 = ByteBuffer.wrap(section.getByteArray("Data2")); - } else { - meta2 = null; - } - - this.metas[y] = i -> { - int nibbleShift = (i & 1) * 4; - short meta = 0; - meta |= (short) (((meta1Lo.get(i >> 1) >> nibbleShift) & 0xF)); - if (meta1Hi != null) { - meta |= (short) (((meta1Hi.get(i >> 1) >> nibbleShift) & 0xF) << 4); - } - if (meta2 != null) { - meta |= (short) ((meta2.get(i) & 0xFF) << 8); - } - return meta; - }; + // NotEnoughIDs format: full 16-bit block IDs and metas stored as ShortBuffers. + loadNotEnoughIds(section, chunkX, y, chunkZ); + + } else if (section.hasKey("Add") || section.hasKey("BlocksB2Hi") || section.hasKey("Data1High")) { + // EndlessIDs format: block ID and meta split across multiple nibble/byte arrays. + // + // Block ID layout (24 bits total): + // bits 0x0000FF — "Blocks" byte array (vanilla low 8 bits) + // bits 0x000F00 — "Add" nibble array (NotEnoughIDs extension to 12 bits) + // bits 0x00F000 — "BlocksB2Hi" nibble array (EndlessIDs extension to 16 bits) + // bits 0xFF0000 — "BlocksB3" byte array (EndlessIDs extension to 24 bits) + // + // Meta layout (16 bits total): + // bits 0x000F — "Data" nibble array (vanilla low 4 bits) + // bits 0x00F0 — "Data1High" nibble array (EndlessIDs extension) + // bits 0xFF00 — "Data2" byte array (EndlessIDs extension, 1 byte per block) + // + // "Add", "BlocksB2Hi", "BlocksB3", "Data1High", and "Data2" are all optional + // Reference: + // https://github.com/GTMEGA/EndlessIDs/blob/master/src/main/java/com/falsepattern/endlessids/managers/BlockIDManager.java + // https://github.com/GTMEGA/EndlessIDs/blob/master/src/main/java/com/falsepattern/endlessids/managers/BlockMetaManager.java + loadEndlessIds(section, chunkX, y, chunkZ); } else { - // neither NotEnoughIds nor EndlessIds - // don't bother loading the actual blocks, if a chunk is this old it'll only have ore tiles - this.blocks[y] = i -> (short) 0; - this.metas[y] = i -> (short) 0; + // Vanilla format or unrecognized: skip block data. + // Old chunks only have ore TileEntities. + this.blocks[y] = i -> 0; + this.metas[y] = i -> 0; } } tiles = chunk.getCompoundTag("Level").getTagList("TileEntities", NBT.TAG_COMPOUND).tagList; } - public int getBlockId(int x, int y, int z) { - if (x < 0 || x >= 16) throw new IllegalArgumentException("x"); - if (y < 0 || y >= CHUNK_HEIGHT) throw new IllegalArgumentException("y"); - if (z < 0 || z >= 16) throw new IllegalArgumentException("z"); - - int index = y << 8 | z << 4 | x; - - int section = index / BLOCKS_PER_EBS; - - Int2ShortFunction blocks = this.blocks[section]; - - if (blocks == null) return 0; + /** + * Loads a chunk section saved in NotEnoughIDs format ("Blocks16" / "Data16"). Block IDs and metas are stored as + * flat ShortBuffers - one short per block, no bit packing. + */ + private void loadNotEnoughIds(NBTTagCompound section, int chunkX, byte y, int chunkZ) { + ShortBuffer blocks = ByteBuffer.wrap(section.getByteArray("Blocks16")).asShortBuffer(); + ShortBuffer metas = ByteBuffer.wrap(section.getByteArray("Data16")).asShortBuffer(); + + if (blocks.capacity() == 0 || metas.capacity() == 0) { + this.blocks[y] = i -> 0; + this.metas[y] = i -> 0; + return; + } - int withinSection = index % BLOCKS_PER_EBS; + if (blocks.capacity() != BLOCKS_PER_EBS) { + VP.LOG.error( + "Corrupt NotEnoughIDs section at X={}, Y={}, Z={}: Blocks16 length {} (expected {})", + chunkX, + y, + chunkZ, + blocks.capacity(), + BLOCKS_PER_EBS); + return; + } - return blocks.get(withinSection); - } + if (metas.capacity() != BLOCKS_PER_EBS) { + VP.LOG.error( + "Corrupt NotEnoughIDs section at X={}, Y={}, Z={}: Data16 length {} (expected {})", + chunkX, + y, + chunkZ, + metas.capacity(), + BLOCKS_PER_EBS); + return; + } - public Block getBlock(int x, int y, int z) { - return Block.getBlockById(getBlockId(x, y, z)); + // Mask with 0xFFFF to avoid sign extension when widening short -> int (IDs/metas >= 0x8000). + this.blocks[y] = i -> blocks.get(i) & 0xFFFF; + this.metas[y] = i -> metas.get(i) & 0xFFFF; } - public int getBlockMeta(int x, int y, int z) { - if (x < 0 || x >= 16) throw new IllegalArgumentException("x"); - if (y < 0 || y >= CHUNK_HEIGHT) throw new IllegalArgumentException("y"); - if (z < 0 || z >= 16) throw new IllegalArgumentException("z"); - - int index = y << 8 | z << 4 | x; - - int section = index / BLOCKS_PER_EBS; - - Int2ShortFunction metas = this.metas[section]; - - if (metas == null) return 0; + /** + * Loads a chunk section saved in EndlessIDs format. "Blocks" and "Data" are mandatory; all other arrays are + * optional and treated as all-zero when absent. A corrupt mandatory array zeroes the whole section. + */ + private void loadEndlessIds(NBTTagCompound section, int chunkX, byte y, int chunkZ) { + ByteBuffer blockB1 = loadOptionalArray(section, "Blocks", BLOCKS_PER_EBS, chunkX, y, chunkZ); + ByteBuffer metaM1Lo = loadOptionalArray(section, "Data", NIBBLE_ARRAY_SIZE, chunkX, y, chunkZ); + if (blockB1 == null || metaM1Lo == null) { + VP.LOG.error( + "Corrupt EndlessIDs section at X={}, Y={}, Z={}: missing or invalid mandatory Blocks/Data array", + chunkX, + y, + chunkZ); + this.blocks[y] = i -> 0; + this.metas[y] = i -> 0; + return; + } - int withinSection = index % BLOCKS_PER_EBS; + ByteBuffer blockB2Lo = loadOptionalArray(section, "Add", NIBBLE_ARRAY_SIZE, chunkX, y, chunkZ); + ByteBuffer blockB2Hi = loadOptionalArray(section, "BlocksB2Hi", NIBBLE_ARRAY_SIZE, chunkX, y, chunkZ); + ByteBuffer blockB3 = loadOptionalArray(section, "BlocksB3", BLOCKS_PER_EBS, chunkX, y, chunkZ); + + this.blocks[y] = i -> { + int nibbleShift = (i & 1) * 4; + int id = blockB1.get(i) & 0xFF; + if (blockB2Lo != null) id |= ((blockB2Lo.get(i >> 1) >> nibbleShift) & 0xF) << 8; + if (blockB2Hi != null) id |= ((blockB2Hi.get(i >> 1) >> nibbleShift) & 0xF) << 12; + if (blockB3 != null) id |= (blockB3.get(i) & 0xFF) << 16; + return id; + }; + + ByteBuffer metaM1Hi = loadOptionalArray(section, "Data1High", NIBBLE_ARRAY_SIZE, chunkX, y, chunkZ); + ByteBuffer metaM2 = loadOptionalArray(section, "Data2", BLOCKS_PER_EBS, chunkX, y, chunkZ); + + this.metas[y] = i -> { + int nibbleShift = (i & 1) * 4; + int meta = (metaM1Lo.get(i >> 1) >> nibbleShift) & 0xF; + if (metaM1Hi != null) meta |= ((metaM1Hi.get(i >> 1) >> nibbleShift) & 0xF) << 4; + if (metaM2 != null) meta |= (metaM2.get(i) & 0xFF) << 8; + return meta; + }; + } - return metas.get(withinSection); + /** + * Reads an optional byte array from a section NBT compound. Validates the length against {@code expectedLength} and + * returns null if the key is absent or the array is malformed. + */ + private ByteBuffer loadOptionalArray(NBTTagCompound section, String key, int expectedLength, int chunkX, byte y, + int chunkZ) { + if (!section.hasKey(key)) return null; + byte[] data = section.getByteArray(key); + if (data.length != expectedLength) { + VP.LOG.error( + "Corrupt EndlessIDs section at X={}, Y={}, Z={}: {} length {} (expected {})", + chunkX, + y, + chunkZ, + key, + data.length, + expectedLength); + return null; + } + return ByteBuffer.wrap(data); } public interface OreConsumer { @@ -235,16 +226,26 @@ public void forEachOre(OreConsumer consumer) { } } - for (int y = 0; y < PartiallyLoadedChunk.CHUNK_HEIGHT; y++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - Block block = getBlock(x, y, z); - int meta = getBlockMeta(x, y, z); - - try (OreInfo info = OreManager.getOreInfo(block, meta)) { - if (info == null || info.isSmall || !info.isNatural || info.material == null) continue; - - consumer.visit(x, y, z, info); + // Iterate per-section so the blocks/metas array lookups are done out of the inner loop + for (int section = 0; section < SECTIONS_PER_CHUNK; section++) { + Int2IntFunction blocks = this.blocks[section]; + Int2IntFunction metas = this.metas[section]; + + int baseY = section << 4; + for (int dy = 0; dy < SECTION_SIZE; dy++) { + int y = baseY + dy; + for (int z = 0; z < SECTION_SIZE; z++) { + for (int x = 0; x < SECTION_SIZE; x++) { + int withinSection = (dy << 8) | (z << 4) | x; + int id = blocks == null ? 0 : blocks.get(withinSection); + int meta = metas == null ? 0 : metas.get(withinSection); + Block block = Block.getBlockById(id); + + try (OreInfo info = OreManager.getOreInfo(block, meta)) { + if (info == null || info.isSmall || !info.isNatural || info.material == null) continue; + + consumer.visit(x, y, z, info); + } } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java index 31067f0e..39afd012 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/WorldAnalysis.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.EnumSet; import java.util.stream.Stream; import java.util.zip.DataFormatException; @@ -18,6 +19,8 @@ import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ServerCache; +import com.sinthoras.visualprospecting.database.VeinSource; +import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; @@ -25,6 +28,9 @@ public class WorldAnalysis { + private static final EnumSet RESCAN_PROTECTED = EnumSet + .of(VeinSource.GENERATED, VeinSource.API, VeinSource.UNKNOWN); + private final File worldFolder; public WorldAnalysis(File worldDirectory) throws IOException { @@ -33,16 +39,16 @@ public WorldAnalysis(File worldDirectory) throws IOException { public void cacheOverworldSpawnVeins(ChunkCoordinates spawn) throws IOException, DataFormatException { - VP.info("Starting to parse world save to cache GT vein locations near spawn. This might take some time..."); - ServerCache.instance.resetSpawnChunks(spawn, 0); + VP.LOG.info("Starting to parse world save to cache GT vein locations near spawn. This might take some time..."); + ServerCache.instance.resetSpawnChunks(spawn, 0, RESCAN_PROTECTED); cacheVeins(IntSets.singleton(0)); } public void cacheVeins() throws IOException, DataFormatException { - VP.info("Starting to parse world save to cache GT vein locations. This might take some time..."); - ServerCache.instance.reset(); + VP.LOG.info("Starting to parse world save to cache GT vein locations. This might take some time..."); + ServerCache.instance.resetExcept(RESCAN_PROTECTED); cacheVeins(getDimensionIds()); } @@ -51,21 +57,32 @@ private void cacheVeins(IntSet dimensionIds) { AnalysisProgressTracker.setNumberOfDimensions(dimensionIds.size()); for (int dimensionId : dimensionIds) { - final Collection regionFiles = getRegionFilesForDim(dimensionId); final DimensionAnalysis dimension = new DimensionAnalysis(dimensionId); + + // Skip dimensions in with no known GT OreMixes + if (!VeinTypeCaching.hasVeinsInDimension(dimension.dimensionName)) { + VP.LOG.info( + "Skipping dimensionId={} name=\"{}\" - no ore veins generate in this dimension.", + dimensionId, + dimension.dimensionName); + AnalysisProgressTracker.dimensionProcessed(); + continue; + } + + final Collection regionFiles = getRegionFilesForDim(dimensionId); dimension.processMinecraftWorld(regionFiles); AnalysisProgressTracker.dimensionProcessed(); } AnalysisProgressTracker.processingFinished(); - VP.info("Saving ore vein cache..."); + VP.LOG.info("Saving ore vein cache..."); ServerCache.instance.saveVeinCache(); } public IntSet getDimensionIds() throws IOException { IntSet dimensionIds = new IntOpenHashSet(); dimensionIds.addAll(Arrays.asList(DimensionManager.getIDs())); - try (Stream files = Files.walk(worldFolder.toPath(), 1)) { + try (Stream files = Files.list(worldFolder.toPath())) { files.filter(Files::isDirectory).map(path -> path.getFileName().toString()) .filter(path -> path.startsWith("DIM")).map(path -> path.substring(3)).forEach(dim -> { try { @@ -82,8 +99,8 @@ public Collection getRegionFilesForDim(int dimensionId) { if (world != null) { dimRegionDir = new File(world.getChunkSaveLocation(), "region"); } else { - final String subfolder = dimensionId == 0 ? "" : "/DIM" + dimensionId; - dimRegionDir = new File(worldFolder, subfolder + "/region"); + final File dimFolder = dimensionId == 0 ? worldFolder : new File(worldFolder, "DIM" + dimensionId); + dimRegionDir = new File(dimFolder, "region"); } if (dimRegionDir.exists()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 1b364a03..6f884c51 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -2,7 +2,7 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.HashSet; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -11,12 +11,15 @@ import com.google.common.collect.ImmutableList; import com.sinthoras.visualprospecting.Tags; +import galacticgreg.api.enums.DimensionDef.DimNames; import gregtech.api.interfaces.IOreMaterial; import gregtech.common.OreMixBuilder; +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; @ParametersAreNonnullByDefault public class VeinType { + // A vein spans 9 block layers in GT WorldgenGTOreLayer. public static final int veinHeight = 9; public final String name; @@ -28,7 +31,9 @@ public class VeinType { public final IOreMaterial sporadicOre; public final int minBlockY; public final int maxBlockY; - private final HashSet oresAsSet = new HashSet(); + private final ReferenceOpenHashSet oresAsSet = new ReferenceOpenHashSet<>(); + private final ReferenceOpenHashSet nonSporadicOres = new ReferenceOpenHashSet<>(); + private final List> oresByLayer; private final List allowedDims = new ArrayList<>(); private boolean isHighlighted = true; private final String localizedName; @@ -47,6 +52,7 @@ private VeinType() { this.inBetweenOre = null; this.sporadicOre = null; this.localizedName = this.name; + this.oresByLayer = buildOresByLayer(); } public VeinType(OreMixBuilder oreMix) { @@ -58,9 +64,21 @@ public VeinType(OreMixBuilder oreMix) { oresAsSet.add(secondaryOre = oreMix.secondary); oresAsSet.add(inBetweenOre = oreMix.between); oresAsSet.add(sporadicOre = oreMix.sporadic); + nonSporadicOres.add(primaryOre); + nonSporadicOres.add(secondaryOre); + nonSporadicOres.add(inBetweenOre); + oresByLayer = buildOresByLayer(); minBlockY = Math.max(0, oreMix.minY - 6); maxBlockY = Math.min(255, oreMix.maxY - 6); allowedDims.addAll(oreMix.dimsEnabled); + + // Fuse entries for "The End" and "EndAsteroid" since they are both about same dimension. + // World gen swap which one is used around 16 chunks from central point. + final boolean inEnd = allowedDims.contains(DimNames.THE_END); + final boolean inEndAsteroid = allowedDims.contains(DimNames.ENDASTEROID); + if (inEnd != inEndAsteroid) { + allowedDims.add(inEnd ? DimNames.ENDASTEROID : DimNames.THE_END); + } } public boolean containsAllFoundOres(Collection foundOres, String dimName, IOreMaterial specific, @@ -77,6 +95,16 @@ public boolean matchesWithSpecificPrimaryOrSecondary(Collection fo && foundOres.containsAll(oresAsSet); } + public boolean matchesIgnoringSporadic(Collection foundOres, String dimName, IOreMaterial specific) { + return (primaryOre == specific || secondaryOre == specific) + && (dimName.isEmpty() || allowedDims.contains(dimName)) + && foundOres.containsAll(nonSporadicOres); + } + + public List getAllowedDimensions() { + return allowedDims; + } + public boolean canOverlapIntoNeighborOreChunk() { return blockSize > 24; } @@ -100,40 +128,44 @@ public String getVeinName() { } public List getOresAtLayer(int layerBlockY) { - final List result = new ArrayList<>(); + if (layerBlockY < 0 || layerBlockY >= veinHeight) { + return Collections.emptyList(); + } + return oresByLayer.get(layerBlockY); + } - switch (layerBlockY) { - case 0, 1, 2 -> { - result.add(secondaryOre); - result.add(sporadicOre); - return result; - } - case 3 -> { - result.add(secondaryOre); - result.add(inBetweenOre); - result.add(sporadicOre); - return result; - } - case 4 -> { - result.add(inBetweenOre); - result.add(sporadicOre); - return result; - } - case 5, 6 -> { - result.add(primaryOre); - result.add(inBetweenOre); - result.add(sporadicOre); - return result; - } - case 7, 8 -> { - result.add(primaryOre); - result.add(sporadicOre); - return result; - } - default -> { - return result; + // Layer -> ores mirrors GT WorldgenGTOreLayer placement + private List> buildOresByLayer() { + final List> layers = new ArrayList<>(veinHeight); + for (int layer = 0; layer < veinHeight; layer++) { + final List ores = new ArrayList<>(3); + switch (layer) { + case 0, 1, 2 -> { + ores.add(secondaryOre); + ores.add(sporadicOre); + } + case 3 -> { + ores.add(secondaryOre); + ores.add(inBetweenOre); + ores.add(sporadicOre); + } + case 4 -> { + ores.add(inBetweenOre); + ores.add(sporadicOre); + } + case 5, 6 -> { + ores.add(primaryOre); + ores.add(inBetweenOre); + ores.add(sporadicOre); + } + case 7, 8 -> { + ores.add(primaryOre); + ores.add(sporadicOre); + } } + layers.add(ores); } + return layers; } public boolean isHighlighted() { diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index 0cb7eaf3..b1df9d18 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -1,9 +1,8 @@ package com.sinthoras.visualprospecting.database.veintypes; -import static com.sinthoras.visualprospecting.Utils.*; - import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.regex.Pattern; @@ -15,19 +14,56 @@ import com.sinthoras.visualprospecting.Tags; import gregtech.api.enums.OreMixes; +import gregtech.api.interfaces.IOreMaterial; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSet; +import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; public class VeinTypeCaching { private static final Object2ObjectMap veinTypes = new Object2ObjectOpenHashMap<>(); + // Dimensions without registered OreMixes are not expected to match anything + private static final ObjectSet dimensionsWithVeins = new ObjectOpenHashSet<>(); + + // VeinTypes indexed by primary/secondary Ore in OreMix. For faster matching + private static final Reference2ObjectMap> veinTypesByPrimaryOrSecondary = new Reference2ObjectOpenHashMap<>(); + public static void init() { + veinTypes.clear(); veinTypes.put(Tags.ORE_MIX_NONE_NAME, VeinType.NO_VEIN); for (OreMixes mix : OreMixes.values()) { veinTypes.put(mix.oreMixBuilder.oreMixName, new VeinType(mix.oreMixBuilder)); } + + dimensionsWithVeins.clear(); + veinTypesByPrimaryOrSecondary.clear(); + for (VeinType veinType : veinTypes.values()) { + if (veinType == VeinType.NO_VEIN) continue; + dimensionsWithVeins.addAll(veinType.getAllowedDimensions()); + indexByOre(veinType.primaryOre, veinType); + if (veinType.secondaryOre != veinType.primaryOre) { + indexByOre(veinType.secondaryOre, veinType); + } + } + } + + private static void indexByOre(IOreMaterial ore, VeinType veinType) { + if (ore == null) return; + List matchingVeinTypes = veinTypesByPrimaryOrSecondary.get(ore); + if (matchingVeinTypes == null) { + matchingVeinTypes = new ArrayList<>(); + veinTypesByPrimaryOrSecondary.put(ore, matchingVeinTypes); + } + matchingVeinTypes.add(veinType); + } + + public static boolean hasVeinsInDimension(String dimensionName) { + return dimensionsWithVeins.contains(dimensionName); } public static @NotNull VeinType getVeinType(String veinTypeName) { @@ -38,6 +74,11 @@ public static Collection getVeinTypes() { return veinTypes.values(); } + public static List getVeinTypesForOre(IOreMaterial dominantOre) { + final List matchingVeinTypes = veinTypesByPrimaryOrSecondary.get(dominantOre); + return matchingVeinTypes == null ? Collections.emptyList() : matchingVeinTypes; + } + public static void recalculateSearch(@Nullable Pattern filterPattern) { for (VeinType veinType : veinTypes.values()) { if (veinType == VeinType.NO_VEIN) continue; From d37b19982c09ad1c1ec55c0864e44aeff4bff508 Mon Sep 17 00:00:00 2001 From: Algent Date: Fri, 12 Jun 2026 10:35:09 +0200 Subject: [PATCH 119/132] Refactor VPs server side commands to Brigadier (#91) --- .../sinthoras/visualprospecting/Utils.java | 14 +- .../com/sinthoras/visualprospecting/VP.java | 20 -- .../commands/CommandHelpers.java | 99 +++++++++ .../ResetClientCacheCommand.java | 10 +- .../commands/VPAdminCommand.java | 70 +++++++ .../visualprospecting/commands/VPCommand.java | 28 +++ .../commands/admin/VPAdminCacheCommand.java | 52 +++++ .../commands/admin/VPAdminDebugCommand.java | 192 +++++++++++++++++ .../commands/admin/VPAdminTeamCommand.java | 86 ++++++++ .../commands/common/VPTeamCommand.java | 123 +++++++++++ .../database/RedoServerCacheCommand.java | 85 -------- .../database/RedoServerSpawnCacheCommand.java | 100 --------- .../cachebuilder/PartiallyLoadedChunk.java | 30 +++ .../database/cachebuilder/RegionReader.java | 4 +- .../visualprospecting/hooks/HooksClient.java | 2 +- .../visualprospecting/hooks/HooksShared.java | 21 +- .../teams/TeamClearCommand.java | 112 ---------- .../teams/TeamInfoCommand.java | 194 ------------------ .../teams/TeamUploadCommand.java | 100 --------- .../assets/visualprospecting/lang/de_DE.lang | 27 +-- .../assets/visualprospecting/lang/en_US.lang | 85 ++++---- .../assets/visualprospecting/lang/zh_CN.lang | 22 +- 22 files changed, 767 insertions(+), 709 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/commands/CommandHelpers.java rename src/main/java/com/sinthoras/visualprospecting/{database => commands}/ResetClientCacheCommand.java (73%) create mode 100644 src/main/java/com/sinthoras/visualprospecting/commands/VPAdminCommand.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/commands/VPCommand.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminCacheCommand.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminDebugCommand.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminTeamCommand.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/commands/common/VPTeamCommand.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/teams/TeamClearCommand.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/teams/TeamInfoCommand.java delete mode 100644 src/main/java/com/sinthoras/visualprospecting/teams/TeamUploadCommand.java diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index d5694223..3f26610b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -109,7 +109,7 @@ public static void deleteDirectoryRecursively(final File targetDirectory) { files.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); } } catch (IOException e) { - e.printStackTrace(); + VP.LOG.error("Failed to delete directory recursively: {}", targetDirectory, e); } } @@ -124,7 +124,7 @@ public static Map readFileToMap(File file) { reader.close(); return map; } catch (IOException e) { - e.printStackTrace(); + VP.LOG.error("Failed to read map from file: {}", file, e); return new HashMap<>(); } } @@ -139,7 +139,7 @@ public static void writeMapToFile(File file, Map map) { gson.toJson(map, new TypeToken>() {}.getType(), writer); writer.close(); } catch (IOException e) { - e.printStackTrace(); + VP.LOG.error("Failed to write map to file: {}", file, e); } } @@ -148,7 +148,7 @@ public static void writeNBT(File file, NBTTagCompound tag) { try (FileOutputStream stream = new FileOutputStream(newFile(file))) { CompressedStreamTools.writeCompressed(tag, stream); } catch (Exception ex) { - ex.printStackTrace(); + VP.LOG.error("Failed to write NBT to file: {}", file, ex); } return false; }); @@ -163,7 +163,7 @@ public static File newFile(File file) { } file.createNewFile(); } catch (Exception e) { - e.printStackTrace(); + VP.LOG.error("Failed to create new file: {}", file, e); } } @@ -207,7 +207,7 @@ public static Map getLegacyDimFiles(File directory) { return dimensionFiles; } catch (IOException e) { - e.printStackTrace(); + VP.LOG.error("Failed to scan legacy dim files in: {}", directory, e); return new HashMap<>(); } } @@ -229,7 +229,7 @@ private static ByteBuffer readFileToBuffer(File file) { return buffer; } catch (IOException e) { - e.printStackTrace(); + VP.LOG.error("Failed to read file to buffer: {}", file, e); return null; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/VP.java b/src/main/java/com/sinthoras/visualprospecting/VP.java index 34d3f814..83d579e8 100644 --- a/src/main/java/com/sinthoras/visualprospecting/VP.java +++ b/src/main/java/com/sinthoras/visualprospecting/VP.java @@ -26,24 +26,4 @@ public class VP { public static final int chunkDepth = 16; public static final int undergroundFluidChunkProspectingBlockRadius = undergroundFluidSizeChunkX * chunkWidth; public static int uploadSizePerPacketInBytes = 30000; // Larger than 32kB will kick the player! - - public static void debug(String message) { - VP.LOG.debug(formatMessage(message)); - } - - public static void info(String message) { - VP.LOG.info(formatMessage(message)); - } - - public static void warn(String message) { - VP.LOG.warn(formatMessage(message)); - } - - public static void error(String message) { - VP.LOG.error(formatMessage(message)); - } - - private static String formatMessage(String message) { - return "[" + Tags.MODNAME + "] " + message; - } } diff --git a/src/main/java/com/sinthoras/visualprospecting/commands/CommandHelpers.java b/src/main/java/com/sinthoras/visualprospecting/commands/CommandHelpers.java new file mode 100644 index 00000000..829551bc --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/commands/CommandHelpers.java @@ -0,0 +1,99 @@ +package com.sinthoras.visualprospecting.commands; + +import static com.gtnewhorizon.gtnhlib.util.CommandUtils.argument; + +import java.util.concurrent.CompletableFuture; + +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.EnumChatFormatting; + +import com.gtnewhorizon.gtnhlib.teams.Team; +import com.gtnewhorizon.gtnhlib.teams.TeamManager; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import com.sinthoras.visualprospecting.teams.TeamProspectionData; + +public final class CommandHelpers { + + public static final int SUCCESS = Command.SINGLE_SUCCESS; + public static final int FAILURE = 0; + + private CommandHelpers() {} + + public static RequiredArgumentBuilder playerNameArg(String name) { + return argument(name, StringArgumentType.word()).suggests(CommandHelpers::suggestOnlinePlayers); + } + + public static EntityPlayerMP requireOnlinePlayer(ICommandSender sender, String name) { + EntityPlayerMP target = MinecraftServer.getServer().getConfigurationManager().func_152612_a(name); + if (target == null) { + error(sender, "visualprospecting.command.player_offline", name); + } + return target; + } + + public static Team requireTeam(ICommandSender sender, EntityPlayerMP player) { + Team team = TeamManager.getTeamByPlayer(player.getUniqueID()); + if (team == null) { + error(sender, "visualprospecting.command.vp.team.no_team", player.getCommandSenderName()); + } + return team; + } + + public static TeamProspectionData requireTeamData(ICommandSender sender, Team team) { + TeamProspectionData data = (TeamProspectionData) team.getData(TeamProspectionData.DATA_KEY); + if (data == null) { + error(sender, "visualprospecting.command.vp.team.no_data"); + } + return data; + } + + public static MinecraftServer requireServer(ICommandSender sender) { + MinecraftServer server = MinecraftServer.getServer(); + if (server == null) { + error(sender, "visualprospecting.command.vpadmin.servercache.no_server"); + } + return server; + } + + public static int sendUsage(CommandContext ctx, String translationKey) { + return plain(ctx.getSource(), translationKey); + } + + public static int plain(ICommandSender sender, String translationKey, Object... args) { + sender.addChatMessage(new ChatComponentTranslation(translationKey, args)); + return SUCCESS; + } + + public static int success(ICommandSender sender, String transKey, Object... args) { + ChatComponentTranslation msg = new ChatComponentTranslation(transKey, args); + msg.getChatStyle().setColor(EnumChatFormatting.GREEN); + sender.addChatMessage(msg); + return SUCCESS; + } + + public static int error(ICommandSender sender, String transKey, Object... args) { + ChatComponentTranslation msg = new ChatComponentTranslation(transKey, args); + msg.getChatStyle().setColor(EnumChatFormatting.RED); + sender.addChatMessage(msg); + return FAILURE; + } + + private static CompletableFuture suggestOnlinePlayers(CommandContext ctx, + SuggestionsBuilder builder) { + String remaining = builder.getRemaining().toLowerCase(); + for (String name : MinecraftServer.getServer().getAllUsernames()) { + if (name.toLowerCase().startsWith(remaining)) { + builder.suggest(name); + } + } + return builder.buildFuture(); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/commands/ResetClientCacheCommand.java similarity index 73% rename from src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java rename to src/main/java/com/sinthoras/visualprospecting/commands/ResetClientCacheCommand.java index 8ce18847..6cc48463 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/ResetClientCacheCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/commands/ResetClientCacheCommand.java @@ -1,4 +1,4 @@ -package com.sinthoras.visualprospecting.database; +package com.sinthoras.visualprospecting.commands; import net.minecraft.client.resources.I18n; import net.minecraft.command.CommandBase; @@ -6,23 +6,25 @@ import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.IChatComponent; +import com.sinthoras.visualprospecting.database.ClientCache; + public class ResetClientCacheCommand extends CommandBase { @Override public String getCommandName() { - return "visualprospectingresetprogress"; + return "vp_client_cache_reset"; } @Override public String getCommandUsage(ICommandSender sender) { - return I18n.format("visualprospecting.resetprogress.command"); + return I18n.format("visualprospecting.command.client.resetcache.usage"); } @Override public void processCommand(ICommandSender sender, String[] parameters) { ClientCache.instance.resetPlayerProgression(); final IChatComponent confirmation = new ChatComponentTranslation( - "visualprospecting.resetprogress.confirmation"); + "visualprospecting.command.client.resetcache.confirmation"); confirmation.getChatStyle().setItalic(true); sender.addChatMessage(confirmation); } diff --git a/src/main/java/com/sinthoras/visualprospecting/commands/VPAdminCommand.java b/src/main/java/com/sinthoras/visualprospecting/commands/VPAdminCommand.java new file mode 100644 index 00000000..7a6a52ff --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/commands/VPAdminCommand.java @@ -0,0 +1,70 @@ +package com.sinthoras.visualprospecting.commands; + +import static com.gtnewhorizon.gtnhlib.util.CommandUtils.literal; +import static com.sinthoras.visualprospecting.commands.CommandHelpers.sendUsage; + +import com.gtnewhorizon.gtnhlib.brigadier.BrigadierApi; +import com.sinthoras.visualprospecting.commands.admin.VPAdminCacheCommand; +import com.sinthoras.visualprospecting.commands.admin.VPAdminDebugCommand; +import com.sinthoras.visualprospecting.commands.admin.VPAdminTeamCommand; + +/** + * {@code /vp_admin} command, available to ops and from console. + */ +public final class VPAdminCommand { + + private VPAdminCommand() {} + + // spotless:off + public static void register() { + BrigadierApi.getCommandDispatcher().register(literal("vp_admin") + // Command root + .requires(src -> src.canCommandSenderUseCommand(2, "vp_admin")) + .executes(ctx -> sendUsage(ctx, "visualprospecting.command.vpadmin.root.usage")) + + // Tree for /vp_admin team + .then(literal("team") + .executes(ctx -> sendUsage(ctx, "visualprospecting.command.vpadmin.team.usage")) + + .then(literal("info") + .executes(ctx -> sendUsage(ctx, "visualprospecting.command.vpadmin.team.info.usage")) + .then(CommandHelpers.playerNameArg(VPAdminTeamCommand.ARG_PLAYER) + .executes(ctx -> VPAdminTeamCommand.cmdInfo(ctx, false)) + .then(literal("detailed").executes(ctx -> VPAdminTeamCommand.cmdInfo(ctx, true))))) + + .then(literal("upload") + .executes(ctx -> sendUsage(ctx, "visualprospecting.command.vpadmin.team.upload.usage")) + .then(CommandHelpers.playerNameArg(VPAdminTeamCommand.ARG_PLAYER) + .executes(VPAdminTeamCommand::cmdUpload))) + + .then(literal("clear") + .executes(ctx -> sendUsage(ctx, "visualprospecting.command.vpadmin.team.clear.usage")) + .then(CommandHelpers.playerNameArg(VPAdminTeamCommand.ARG_PLAYER) + .executes(VPAdminTeamCommand::cmdClear))) + ) + + // Tree for /vp_admin servercache + .then(literal("servercache") + .requires(src -> src.canCommandSenderUseCommand(4, "vp_admin")) + .executes(ctx -> sendUsage(ctx, "visualprospecting.command.vpadmin.servercache.usage")) + + .then(literal("rebuild") + .executes(ctx -> sendUsage(ctx, "visualprospecting.command.vpadmin.servercache.rebuild.usage")) + + .then(literal("all") + .executes(VPAdminCacheCommand::cmdRebuildAll)) + .then(literal("spawn") + .executes(VPAdminCacheCommand::cmdRebuildSpawn))) + ) + + // Tree for /vp_admin debug + .then(literal("debug") + .requires(src -> src.canCommandSenderUseCommand(4, "vp_admin")) + .executes(ctx -> sendUsage(ctx, "visualprospecting.command.vpadmin.debug.usage")) + + .then(literal("vein").executes(VPAdminDebugCommand::cmdDebugOreVein)) + ) + ); + } + // spotless:on +} diff --git a/src/main/java/com/sinthoras/visualprospecting/commands/VPCommand.java b/src/main/java/com/sinthoras/visualprospecting/commands/VPCommand.java new file mode 100644 index 00000000..71138a4d --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/commands/VPCommand.java @@ -0,0 +1,28 @@ +package com.sinthoras.visualprospecting.commands; + +import static com.gtnewhorizon.gtnhlib.util.CommandUtils.literal; +import static com.sinthoras.visualprospecting.commands.CommandHelpers.sendUsage; + +import com.gtnewhorizon.gtnhlib.brigadier.BrigadierApi; +import com.sinthoras.visualprospecting.commands.common.VPTeamCommand; + +/** + * {@code /vp} command, available to all players. + */ +public final class VPCommand { + + private VPCommand() {} + + // spotless:off + public static void register() { + BrigadierApi.getCommandDispatcher().register(literal("vp") + .executes(ctx -> sendUsage(ctx, "visualprospecting.command.vp.root.usage")) + + .then(literal("team").executes(ctx -> sendUsage(ctx, "visualprospecting.command.vp.team.usage")) + + .then(literal("info").executes(ctx -> VPTeamCommand.cmdInfo(ctx, false)) + .then(literal("detailed").executes(ctx -> VPTeamCommand.cmdInfo(ctx, true))) + ))); + } + // spotless:on +} diff --git a/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminCacheCommand.java new file mode 100644 index 00000000..45d62159 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminCacheCommand.java @@ -0,0 +1,52 @@ +package com.sinthoras.visualprospecting.commands.admin; + +import static com.sinthoras.visualprospecting.commands.CommandHelpers.requireServer; + +import java.io.IOException; +import java.util.zip.DataFormatException; + +import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; + +import com.mojang.brigadier.context.CommandContext; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.commands.CommandHelpers; +import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; + +public class VPAdminCacheCommand { + + private VPAdminCacheCommand() {} + + public static int cmdRebuildAll(CommandContext ctx) { + return rebuild(ctx.getSource(), "rebuild", (world, server) -> world.cacheVeins()); + } + + public static int cmdRebuildSpawn(CommandContext ctx) { + return rebuild( + ctx.getSource(), + "rebuildspawn", + (world, server) -> world.cacheOverworldSpawnVeins(server.getEntityWorld().getSpawnPoint())); + } + + private static int rebuild(ICommandSender sender, String kind, RebuildAction action) { + MinecraftServer server = requireServer(sender); + if (server == null) return CommandHelpers.FAILURE; + + String prefix = "visualprospecting.command.vpadmin.servercache." + kind; + CommandHelpers.plain(sender, prefix + ".start"); + try { + WorldAnalysis world = new WorldAnalysis(server.getEntityWorld().getSaveHandler().getWorldDirectory()); + action.run(world, server); + } catch (IOException | DataFormatException e) { + VP.LOG.error("Could not rebuild vein cache ({})", kind, e); + return CommandHelpers.error(sender, prefix + ".failure"); + } + return CommandHelpers.success(sender, prefix + ".confirmation"); + } + + @FunctionalInterface + private interface RebuildAction { + + void run(WorldAnalysis world, MinecraftServer server) throws IOException, DataFormatException; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminDebugCommand.java b/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminDebugCommand.java new file mode 100644 index 00000000..bf569a45 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminDebugCommand.java @@ -0,0 +1,192 @@ +package com.sinthoras.visualprospecting.commands.admin; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +import com.mojang.brigadier.context.CommandContext; +import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.commands.CommandHelpers; +import com.sinthoras.visualprospecting.database.OreVeinPosition; +import com.sinthoras.visualprospecting.database.ServerCache; +import com.sinthoras.visualprospecting.database.cachebuilder.ChunkAnalysis; +import com.sinthoras.visualprospecting.database.cachebuilder.DetailedChunkAnalysis; +import com.sinthoras.visualprospecting.database.cachebuilder.DimensionAnalysis; +import com.sinthoras.visualprospecting.database.cachebuilder.PartiallyLoadedChunk; +import com.sinthoras.visualprospecting.database.veintypes.VeinType; +import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; + +import gregtech.api.interfaces.IOreMaterial; +import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; + +public class VPAdminDebugCommand { + + private static final String VEIN = "visualprospecting.command.vpadmin.debug.vein."; + private static final String ANALYZE = "visualprospecting.command.vpadmin.debug.analyze."; + + private VPAdminDebugCommand() {} + + /** + * {@code /vp_admin debug vein}: inspect the central ore chunk the sender is standing on. Prints the server cache + * record and a live output of the cache-builder analysis for that chunk. + *

    + * Limitation: Doesn't do the whole cleanUpWithNeighbors logic + */ + public static int cmdDebugOreVein(CommandContext ctx) { + ICommandSender sender = ctx.getSource(); + + if (!(sender instanceof EntityPlayerMP player)) { + return CommandHelpers.error(sender, "visualprospecting.command.console_forbidden"); + } + + final int dimensionId = player.dimension; + final int chunkX = Utils + .mapToCenterOreChunkCoord(Utils.coordBlockToChunk(MathHelper.floor_double(player.posX))); + final int chunkZ = Utils + .mapToCenterOreChunkCoord(Utils.coordBlockToChunk(MathHelper.floor_double(player.posZ))); + final String dimName = new DimensionAnalysis(dimensionId).dimensionName; + + IChatComponent header = new ChatComponentTranslation(VEIN + "header", chunkX, chunkZ, dimensionId, dimName); + header.getChatStyle().setBold(true); + sender.addChatMessage(header); + + printCacheRecord(sender, dimensionId, chunkX, chunkZ); + printDryRunAnalysis(sender, player.worldObj, dimName, dimensionId, chunkX, chunkZ); + + return CommandHelpers.SUCCESS; + } + + // Print data stored in server cache + private static void printCacheRecord(ICommandSender sender, int dimensionId, int chunkX, int chunkZ) { + final OreVeinPosition vein = ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ); + if (vein.veinType == VeinType.NO_VEIN) { + CommandHelpers.plain(sender, VEIN + "cache_none"); + return; + } + CommandHelpers.plain(sender, VEIN + "type", vein.veinType.name, vein.veinType.getVeinName()); + CommandHelpers.plain(sender, VEIN + "source", vein.getSource()); + } + + // Run the cache-builder analysis on the live chunk (output only, nothing is written to cache) + private static void printDryRunAnalysis(ICommandSender sender, World world, String dimName, int dimensionId, + int chunkX, int chunkZ) { + CommandHelpers.plain(sender, ANALYZE + "title"); + + final PartiallyLoadedChunk chunk; + try { + chunk = loadLiveChunk(world, chunkX, chunkZ); + } catch (Exception e) { + VP.LOG.error( + "/vp_admin debug vein: failed to read live chunk at {}, {} in dim {}", + chunkX, + chunkZ, + dimensionId, + e); + CommandHelpers.error(sender, ANALYZE + "error", String.valueOf(e)); + return; + } + + // Raw ore tally + final Reference2IntOpenHashMap oreCounts = new Reference2IntOpenHashMap<>(); + final int[] minY = { Integer.MAX_VALUE }; + final int[] maxY = { Integer.MIN_VALUE }; + chunk.forEachOre((x, y, z, info) -> { + oreCounts.addTo(info.material, 1); + if (y < minY[0]) minY[0] = y; + if (y > maxY[0]) maxY[0] = y; + }); + + if (oreCounts.isEmpty()) { + CommandHelpers.plain(sender, ANALYZE + "no_ores"); + return; + } + + int total = 0; + for (var entry : oreCounts.reference2IntEntrySet()) { + total += entry.getIntValue(); + } + CommandHelpers.plain(sender, ANALYZE + "stats", total, oreCounts.size(), minY[0], maxY[0]); + + final List materials = new ArrayList<>(oreCounts.keySet()); + materials.sort(Comparator.comparingInt(oreCounts::getInt).reversed()); + for (IOreMaterial ore : materials) { + CommandHelpers.plain(sender, ANALYZE + "ore_line", ore.getLocalizedName(), oreCounts.getInt(ore)); + } + + final IOreMaterial dominant = materials.get(0); + CommandHelpers.plain(sender, ANALYZE + "dominant", dominant.getLocalizedName(), oreCounts.getInt(dominant)); + + if (dimName != null && !dimName.isEmpty() && !VeinTypeCaching.hasVeinsInDimension(dimName)) { + CommandHelpers.plain(sender, ANALYZE + "no_dim_veins", dimName); + } + + printCandidateReasoning(sender, oreCounts, dimName, dominant); + printResolvedVerdicts(sender, chunk, dimName, dimensionId, chunkX, chunkZ); + } + + // Mirror the inputs of DetailedChunkAnalysis.getMatchedVein() + private static void printCandidateReasoning(ICommandSender sender, Reference2IntOpenHashMap oreCounts, + String dimName, IOreMaterial dominant) { + final List candidates = new ArrayList<>(); + for (VeinType vein : VeinTypeCaching.getVeinTypesForOre(dominant)) { + if (dimName.isEmpty() || vein.getAllowedDimensions().contains(dimName)) { + candidates.add(vein); + } + } + if (candidates.isEmpty()) { + CommandHelpers.plain(sender, ANALYZE + "candidates_none"); + return; + } + + CommandHelpers.plain(sender, ANALYZE + "candidates_header", dominant.getLocalizedName(), candidates.size()); + int fullMatches = 0; + int sporadicIgnoredMatches = 0; + for (VeinType candidate : candidates) { + final boolean full = candidate.matchesWithSpecificPrimaryOrSecondary(oreCounts.keySet(), dimName, dominant); + final boolean ignoreSporadic = candidate.matchesIgnoringSporadic(oreCounts.keySet(), dimName, dominant); + if (full) fullMatches++; + if (ignoreSporadic) sporadicIgnoredMatches++; + CommandHelpers.plain(sender, ANALYZE + "candidate_line", candidate.name, full, ignoreSporadic); + } + CommandHelpers.plain(sender, ANALYZE + "match_summary", fullMatches, sporadicIgnoredMatches); + } + + // Print Verdict + private static void printResolvedVerdicts(ICommandSender sender, PartiallyLoadedChunk chunk, String dimName, + int dimensionId, int chunkX, int chunkZ) { + final DetailedChunkAnalysis detailed = new DetailedChunkAnalysis(dimensionId, dimName, chunkX, chunkZ); + detailed.processMinecraftChunk(chunk); + detailed.resolve(new Long2IntOpenHashMap()); + final VeinType resolved = detailed.getResolvedVeinType(); + if (resolved == VeinType.NO_VEIN) { + CommandHelpers.plain(sender, ANALYZE + "resolved_none"); + } else { + CommandHelpers.plain(sender, ANALYZE + "resolved", resolved.name, resolved.getVeinName()); + } + + final ChunkAnalysis fast = new ChunkAnalysis(dimName); + fast.processMinecraftChunk(chunk); + if (fast.matchesSingleVein()) { + CommandHelpers.plain(sender, ANALYZE + "fastpath", fast.getMatchedVein().name); + } else { + CommandHelpers.plain(sender, ANALYZE + "fastpath_ambiguous"); + } + } + + private static PartiallyLoadedChunk loadLiveChunk(World world, int chunkX, int chunkZ) { + final Chunk live = world.getChunkFromChunkCoords(chunkX, chunkZ); + final PartiallyLoadedChunk chunk = new PartiallyLoadedChunk(); + chunk.loadFromLiveChunk(live); + return chunk; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminTeamCommand.java b/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminTeamCommand.java new file mode 100644 index 00000000..3e6e6142 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminTeamCommand.java @@ -0,0 +1,86 @@ +package com.sinthoras.visualprospecting.commands.admin; + +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; + +import com.gtnewhorizon.gtnhlib.teams.Team; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.commands.CommandHelpers; +import com.sinthoras.visualprospecting.commands.common.VPTeamCommand; +import com.sinthoras.visualprospecting.network.RequestTeamUploadMessage; +import com.sinthoras.visualprospecting.teams.TeamProspectionData; + +public class VPAdminTeamCommand { + + public static final String ARG_PLAYER = "player"; + + private VPAdminTeamCommand() {} + + public static int cmdInfo(CommandContext ctx, boolean detailed) { + ICommandSender sender = ctx.getSource(); + String playerName = StringArgumentType.getString(ctx, ARG_PLAYER); + + EntityPlayerMP target = CommandHelpers.requireOnlinePlayer(sender, playerName); + if (target == null) { + return CommandHelpers.FAILURE; + } else { + return VPTeamCommand.cmdInfo(ctx, detailed, target); + } + } + + public static int cmdClear(CommandContext ctx) { + ICommandSender sender = ctx.getSource(); + String playerName = StringArgumentType.getString(ctx, ARG_PLAYER); + + EntityPlayerMP target = CommandHelpers.requireOnlinePlayer(sender, playerName); + if (target == null) return CommandHelpers.FAILURE; + + Team team = CommandHelpers.requireTeam(sender, target); + if (team == null) return CommandHelpers.FAILURE; + + TeamProspectionData data = CommandHelpers.requireTeamData(sender, team); + if (data == null) return CommandHelpers.FAILURE; + + int veins = 0, fluids = 0; + for (int dim : data.knownDimensions()) { + veins += data.getDiscoveredVeinKeys(dim).size(); + fluids += data.getDiscoveredFluidKeys(dim).size(); + } + + data.clear(); + team.markDirty(); + + return CommandHelpers.success( + sender, + "visualprospecting.command.vpadmin.team.clear.success", + team.getTeamName(), + veins, + fluids); + } + + public static int cmdUpload(CommandContext ctx) { + ICommandSender sender = ctx.getSource(); + String playerName = StringArgumentType.getString(ctx, ARG_PLAYER); + + if (!Config.enableTeamSharing) { + return CommandHelpers.error(sender, "visualprospecting.command.sharing_disabled"); + } + + EntityPlayerMP target = CommandHelpers.requireOnlinePlayer(sender, playerName); + if (target == null) return CommandHelpers.FAILURE; + + Team team = CommandHelpers.requireTeam(sender, target); + if (team == null) return CommandHelpers.FAILURE; + + VP.network.sendTo(new RequestTeamUploadMessage(), target); + + return CommandHelpers.success( + sender, + "visualprospecting.command.vpadmin.team.upload.requested", + target.getCommandSenderName(), + team.getTeamName()); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/commands/common/VPTeamCommand.java b/src/main/java/com/sinthoras/visualprospecting/commands/common/VPTeamCommand.java new file mode 100644 index 00000000..41a39f32 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/commands/common/VPTeamCommand.java @@ -0,0 +1,123 @@ +package com.sinthoras.visualprospecting.commands.common; + +import java.util.Arrays; + +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +import com.gtnewhorizon.gtnhlib.teams.Team; +import com.gtnewhorizon.gtnhlib.teams.TeamManager; +import com.mojang.brigadier.context.CommandContext; +import com.sinthoras.visualprospecting.commands.CommandHelpers; +import com.sinthoras.visualprospecting.teams.TeamProspectionData; + +import it.unimi.dsi.fastutil.ints.IntSet; + +public final class VPTeamCommand { + + private VPTeamCommand() {} + + public static int cmdInfo(CommandContext ctx, boolean detailed) { + return cmdInfo(ctx, detailed, null); + } + + public static int cmdInfo(CommandContext ctx, boolean detailed, EntityPlayerMP target) { + ICommandSender sender = ctx.getSource(); + + EntityPlayerMP subject = target; + if (subject == null) { + if (!(sender instanceof EntityPlayerMP self)) { + return CommandHelpers.error(sender, "visualprospecting.command.console_needs_player"); + } + subject = self; + } + + Team team = CommandHelpers.requireTeam(sender, subject); + if (team == null) return CommandHelpers.FAILURE; + + TeamProspectionData data = CommandHelpers.requireTeamData(sender, team); + if (data == null) return CommandHelpers.FAILURE; + + printInfoReport(sender, team, data, detailed); + return CommandHelpers.SUCCESS; + } + + private static void printInfoReport(ICommandSender sender, Team team, TeamProspectionData data, boolean detailed) { + IntSet knownDimensions = data.knownDimensions(); + + long totalVeins = 0, totalFluids = 0, totalDepleted = 0; + for (int dim : knownDimensions) { + totalVeins += data.getDiscoveredVeinKeys(dim).size(); + totalFluids += data.getDiscoveredFluidKeys(dim).size(); + totalDepleted += data.getDepletedVeinKeys(dim).size(); + } + + int memberCount = team.getMembers().size(); + int onlineCount = countOnline(team); + + IChatComponent header = new ChatComponentTranslation( + "visualprospecting.command.vp.team.info.header", + team.getTeamName(), + memberCount, + onlineCount); + header.getChatStyle().setBold(true); + sender.addChatMessage(header); + + if (knownDimensions.isEmpty()) { + IChatComponent empty = new ChatComponentTranslation("visualprospecting.command.vp.team.info.empty"); + empty.getChatStyle().setColor(EnumChatFormatting.GRAY); + sender.addChatMessage(empty); + return; + } + + sender.addChatMessage( + new ChatComponentTranslation( + "visualprospecting.command.vp.team.info.summary", + knownDimensions.size(), + totalVeins, + totalDepleted, + totalFluids)); + + if (!detailed) return; + + int[] sortedDims = knownDimensions.toIntArray(); + Arrays.sort(sortedDims); + for (int dim : sortedDims) { + int v = data.getDiscoveredVeinKeys(dim).size(); + int f = data.getDiscoveredFluidKeys(dim).size(); + int d = data.getDepletedVeinKeys(dim).size(); + if (v == 0 && f == 0) continue; + sender.addChatMessage( + new ChatComponentTranslation( + "visualprospecting.command.vp.team.info.dim_line", + dimLabel(dim), + v, + d, + f)); + } + } + + private static int countOnline(Team team) { + int[] count = { 0 }; + TeamManager.forEachOnlineTeamMember(team, p -> count[0]++); + return count[0]; + } + + private static String dimLabel(int dim) { + try { + World world = DimensionManager.getWorld(dim); + if (world != null && world.provider != null) { + String name = world.provider.getDimensionName(); + if (name != null && !name.isEmpty()) { + return dim + " (" + name + ")"; + } + } + } catch (Exception ignored) {} + return Integer.toString(dim); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java deleted file mode 100644 index 9d06e023..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerCacheCommand.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.sinthoras.visualprospecting.database; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.zip.DataFormatException; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.ChatComponentTranslation; -import net.minecraft.util.IChatComponent; -import net.minecraft.util.StatCollector; - -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; - -import cpw.mods.fml.server.FMLServerHandler; - -public class RedoServerCacheCommand extends CommandBase { - - @Override - public String getCommandName() { - return "visualprospectingredoservercache"; - } - - @Override - public String getCommandUsage(ICommandSender sender) { - return StatCollector.translateToLocal("visualprospecting.redoservercache.command"); - } - - @Override - public List getCommandAliases() { - return Collections.singletonList("vp_recache"); - } - - @Override - public void processCommand(ICommandSender sender, String[] parameters) { - MinecraftServer server; - if (sender instanceof EntityPlayerMP player) { - server = player.mcServer; - } else { - server = FMLServerHandler.instance().getServer(); - } - if (server == null) { - VP.info("Server not found"); - return; - } - final IChatComponent start = new ChatComponentTranslation("visualprospecting.redoservercache.start"); - start.getChatStyle().setItalic(true); - sender.addChatMessage(start); - try { - WorldAnalysis world = new WorldAnalysis(server.getEntityWorld().getSaveHandler().getWorldDirectory()); - world.cacheVeins(); - } catch (IOException | DataFormatException e) { - VP.info("Could not load world save files to build vein cache!"); - e.printStackTrace(); - final IChatComponent failure = new ChatComponentTranslation("visualprospecting.redoservercache.failure"); - failure.getChatStyle().setItalic(true); - sender.addChatMessage(failure); - } - final IChatComponent confirmation = new ChatComponentTranslation( - "visualprospecting.redoservercache.confirmation"); - confirmation.getChatStyle().setItalic(true); - sender.addChatMessage(confirmation); - } - - @Override - public boolean canCommandSenderUseCommand(ICommandSender sender) { - // Only SP owner, or OP are allowed - if (sender instanceof EntityPlayerMP player) { - if (Objects.equals(player.mcServer.getServerOwner(), sender.getCommandSenderName())) { - return true; - } - } - return super.canCommandSenderUseCommand(sender); - } - - @Override - public int getRequiredPermissionLevel() { - return 4; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java b/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java deleted file mode 100644 index 3df89ef2..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/database/RedoServerSpawnCacheCommand.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.sinthoras.visualprospecting.database; - -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.zip.DataFormatException; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.ChatComponentTranslation; -import net.minecraft.util.IChatComponent; -import net.minecraft.util.StatCollector; - -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; - -import cpw.mods.fml.server.FMLServerHandler; - -public class RedoServerSpawnCacheCommand extends CommandBase { - - @Override - public String getCommandName() { - return "visualprospectingredoserverspawncache"; - } - - @Override - public String getCommandUsage(ICommandSender sender) { - return StatCollector.translateToLocal("visualprospecting.redoserverspawncache.command"); - } - - @Override - public List getCommandAliases() { - return Collections.singletonList("vp_recachespawn"); - } - - @Override - public void processCommand(ICommandSender sender, String[] parameters) { - - // Set the correct server - MinecraftServer server; - if (sender instanceof EntityPlayerMP) { - - EntityPlayerMP player = (EntityPlayerMP) sender; - server = player.mcServer; - } else { - - server = FMLServerHandler.instance().getServer(); - } - - if (server == null) { - VP.info("Server not found"); - return; - } - - // Fancy start message - final IChatComponent start = new ChatComponentTranslation("visualprospecting.redoserverspawncache.start"); - start.getChatStyle().setItalic(true); - sender.addChatMessage(start); - - // Attempt to analyze the world - try { - - WorldAnalysis world = new WorldAnalysis(server.getEntityWorld().getSaveHandler().getWorldDirectory()); - world.cacheOverworldSpawnVeins(server.getEntityWorld().getSpawnPoint()); - } catch (IOException | DataFormatException e) { - - VP.info("Could not load world save files to build vein cache near spawn!"); - e.printStackTrace(); - final IChatComponent failure = new ChatComponentTranslation( - "visualprospecting.redoserverspawncache.failure"); - failure.getChatStyle().setItalic(true); - sender.addChatMessage(failure); - } - final IChatComponent confirmation = new ChatComponentTranslation( - "visualprospecting.redoserverspawncache.confirmation"); - confirmation.getChatStyle().setItalic(true); - sender.addChatMessage(confirmation); - } - - @Override - public boolean canCommandSenderUseCommand(ICommandSender sender) { - - // Only SP owner, or OP are allowed - if (sender instanceof EntityPlayerMP player) { - if (Objects.equals(player.mcServer.getServerOwner(), sender.getCommandSenderName())) { - return true; - } - } - - return super.canCommandSenderUseCommand(sender); - } - - @Override - public int getRequiredPermissionLevel() { - return 4; - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java index d4c10150..4804fc99 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/PartiallyLoadedChunk.java @@ -2,12 +2,16 @@ import java.nio.ByteBuffer; import java.nio.ShortBuffer; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import net.minecraft.block.Block; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraftforge.common.util.Constants.NBT; import com.gtnewhorizon.gtnhlib.util.data.ImmutableBlockMeta; @@ -79,6 +83,32 @@ public void load(NBTTagCompound chunk, int chunkX, int chunkZ) { tiles = chunk.getCompoundTag("Level").getTagList("TileEntities", NBT.TAG_COMPOUND).tagList; } + /** + * Populates this chunk from an in-memory Chunk, to allow for real time debug command. + */ + public void loadFromLiveChunk(Chunk chunk) { + final ExtendedBlockStorage[] storage = chunk.getBlockStorageArray(); + for (int section = 0; section < SECTIONS_PER_CHUNK; section++) { + final ExtendedBlockStorage ebs = section < storage.length ? storage[section] : null; + if (ebs == null) { + this.blocks[section] = i -> 0; + this.metas[section] = i -> 0; + continue; + } + // withinSection index layout (matches forEachOre): bits 0-3 = x, 4-7 = z, 8-11 = y + this.blocks[section] = i -> Block + .getIdFromBlock(ebs.getBlockByExtId(i & 0xF, (i >> 8) & 0xF, (i >> 4) & 0xF)); + this.metas[section] = i -> ebs.getExtBlockMetadata(i & 0xF, (i >> 8) & 0xF, (i >> 4) & 0xF); + } + + this.tiles = new ArrayList<>(); + for (TileEntity tileEntity : chunk.chunkTileEntityMap.values()) { + final NBTTagCompound tag = new NBTTagCompound(); + tileEntity.writeToNBT(tag); + this.tiles.add(tag); + } + } + /** * Loads a chunk section saved in NotEnoughIDs format ("Blocks16" / "Data16"). Block IDs and metas are stored as * flat ShortBuffers - one short per block, no bit packing. diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/RegionReader.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/RegionReader.java index 7432d3ea..5f9be3a7 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/RegionReader.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/RegionReader.java @@ -15,6 +15,8 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; +import com.sinthoras.visualprospecting.VP; + public class RegionReader implements AutoCloseable { private final RandomAccessFile is; @@ -43,7 +45,7 @@ private int offset(int x, int z) { } return null; } catch (DataFormatException | IOException e) { - e.printStackTrace(); + VP.LOG.error("Failed to read chunk tiles at ({}, {})", x, z, e); return null; } } diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java index 6e9a289a..7b9abb70 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java @@ -6,8 +6,8 @@ import com.gtnewhorizons.navigator.api.NavigatorApi; import com.gtnewhorizons.navigator.api.util.Util; import com.sinthoras.visualprospecting.Utils; +import com.sinthoras.visualprospecting.commands.ResetClientCacheCommand; import com.sinthoras.visualprospecting.database.ClientCache; -import com.sinthoras.visualprospecting.database.ResetClientCacheCommand; import com.sinthoras.visualprospecting.integration.model.layers.OreVeinLayerManager; import com.sinthoras.visualprospecting.integration.model.layers.UndergroundFluidLayerManager; import com.sinthoras.visualprospecting.integration.voxelmap.VoxelMapEventHandler; diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java index 069e32a4..3023b403 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksShared.java @@ -12,8 +12,8 @@ import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Tags; import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.database.RedoServerCacheCommand; -import com.sinthoras.visualprospecting.database.RedoServerSpawnCacheCommand; +import com.sinthoras.visualprospecting.commands.VPAdminCommand; +import com.sinthoras.visualprospecting.commands.VPCommand; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.WorldIdHandler; import com.sinthoras.visualprospecting.database.cachebuilder.WorldAnalysis; @@ -27,10 +27,7 @@ import com.sinthoras.visualprospecting.network.VeinDepletionMessage; import com.sinthoras.visualprospecting.network.WorldIdNotification; import com.sinthoras.visualprospecting.task.TaskManager; -import com.sinthoras.visualprospecting.teams.TeamClearCommand; -import com.sinthoras.visualprospecting.teams.TeamInfoCommand; import com.sinthoras.visualprospecting.teams.TeamProspectionData; -import com.sinthoras.visualprospecting.teams.TeamUploadCommand; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.event.FMLInitializationEvent; @@ -129,6 +126,9 @@ public void fmlLifeCycleEvent(FMLServerAboutToStartEvent event) { File regionFolder = new File(worldDir, "region"); newWorld = !regionFolder.exists(); } + + VPCommand.register(); + VPAdminCommand.register(); } // register server commands in this event handler @@ -147,18 +147,9 @@ public void fmlLifeCycleEvent(FMLServerStartingEvent event) { WorldAnalysis worldAnalysis = new WorldAnalysis(world.getSaveHandler().getWorldDirectory()); worldAnalysis.cacheVeins(); } catch (IOException | DataFormatException e) { - VP.LOG.info("Could not load world save files to build vein cache!", e); + VP.LOG.error("Could not load world save files to build vein cache!", e); } } - - // Register the recache command - event.registerServerCommand(new RedoServerCacheCommand()); - event.registerServerCommand(new RedoServerSpawnCacheCommand()); - - // Team-sharing debug commands - event.registerServerCommand(new TeamInfoCommand()); - event.registerServerCommand(new TeamClearCommand()); - event.registerServerCommand(new TeamUploadCommand()); } public void fmlLifeCycleEvent(FMLServerStartedEvent event) {} diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamClearCommand.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamClearCommand.java deleted file mode 100644 index 0ca4c7bf..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/teams/TeamClearCommand.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.sinthoras.visualprospecting.teams; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.ChatComponentTranslation; -import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.IChatComponent; -import net.minecraft.util.StatCollector; - -import com.gtnewhorizon.gtnhlib.teams.Team; -import com.gtnewhorizon.gtnhlib.teams.TeamManager; - -import it.unimi.dsi.fastutil.ints.IntSet; - -/** - * {@code /vp_team_clear } : Delete that player team prospection record. - *

    - * Op/console only. - *

    - * Note: players local {@code ClientCache} is untouched. - */ -public class TeamClearCommand extends CommandBase { - - @Override - public String getCommandName() { - return "vp_team_clear"; - } - - @Override - public String getCommandUsage(ICommandSender sender) { - return StatCollector.translateToLocal("visualprospecting.teamclear.command"); - } - - @Override - public int getRequiredPermissionLevel() { - return 2; - } - - @Override - public boolean canCommandSenderUseCommand(ICommandSender sender) { - if (sender instanceof EntityPlayerMP player) { - if (Objects.equals(player.mcServer.getServerOwner(), sender.getCommandSenderName())) { - return true; - } - } - return super.canCommandSenderUseCommand(sender); - } - - @Override - public List addTabCompletionOptions(ICommandSender sender, String[] args) { - if (args.length == 1) { - return getListOfStringsMatchingLastWord(args, MinecraftServer.getServer().getAllUsernames()); - } - return Collections.emptyList(); - } - - @Override - public void processCommand(ICommandSender sender, String[] args) { - if (args.length != 1) { - sendMessage(sender, "visualprospecting.command.usage_error", getCommandName()); - return; - } - - EntityPlayerMP target = MinecraftServer.getServer().getConfigurationManager().func_152612_a(args[0]); - if (target == null) { - sendMessage(sender, "visualprospecting.teamcommand.player_offline", args[0]); - return; - } - - Team team = TeamManager.getTeamByPlayer(target.getUniqueID()); - if (team == null) { - sendMessage(sender, "visualprospecting.teamcommand.no_team", target.getCommandSenderName()); - return; - } - - TeamProspectionData data = (TeamProspectionData) team.getData(TeamProspectionData.DATA_KEY); - if (data == null) { - sendMessage(sender, "visualprospecting.teaminfo.no_data"); - return; - } - - IntSet dims = data.knownDimensions(); - long totalVeins = 0, totalFluids = 0; - for (int dim : dims) { - totalVeins += data.getDiscoveredVeinKeys(dim).size(); - totalFluids += data.getDiscoveredFluidKeys(dim).size(); - } - - data.clear(); - team.markDirty(); - - IChatComponent msg = new ChatComponentTranslation( - "visualprospecting.teamclear.success", - team.getTeamName(), - totalVeins, - totalFluids); - msg.getChatStyle().setColor(EnumChatFormatting.GREEN); - sender.addChatMessage(msg); - } - - private static void sendMessage(ICommandSender sender, String translationKey, Object... args) { - IChatComponent msg = new ChatComponentTranslation(translationKey, args); - msg.getChatStyle().setColor(EnumChatFormatting.RED); - sender.addChatMessage(msg); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamInfoCommand.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamInfoCommand.java deleted file mode 100644 index d7b61188..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/teams/TeamInfoCommand.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.sinthoras.visualprospecting.teams; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.ChatComponentTranslation; -import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.IChatComponent; -import net.minecraft.util.StatCollector; -import net.minecraft.world.World; -import net.minecraftforge.common.DimensionManager; - -import com.gtnewhorizon.gtnhlib.teams.Team; -import com.gtnewhorizon.gtnhlib.teams.TeamManager; - -import it.unimi.dsi.fastutil.ints.IntSet; - -/** - * {@code /vp_team_info [player] [detailed]} : inspect a player team's prospection record. - *

    - * Require op to inspect other players. - */ -public class TeamInfoCommand extends CommandBase { - - private static final String DETAILED_FLAG = "detailed"; - - @Override - public String getCommandName() { - return "vp_team_info"; - } - - @Override - public String getCommandUsage(ICommandSender sender) { - return StatCollector.translateToLocal("visualprospecting.teaminfo.command"); - } - - @Override - public int getRequiredPermissionLevel() { - return 0; - } - - @Override - public boolean canCommandSenderUseCommand(ICommandSender sender) { - return true; - } - - @Override - public List addTabCompletionOptions(ICommandSender sender, String[] args) { - if (args.length == 1) { - String[] names = MinecraftServer.getServer().getAllUsernames(); - String[] options = Arrays.copyOf(names, names.length + 1); - options[names.length] = DETAILED_FLAG; - return getListOfStringsMatchingLastWord(args, options); - } - if (args.length == 2) { - return getListOfStringsMatchingLastWord(args, DETAILED_FLAG); - } - return Collections.emptyList(); - } - - @Override - public void processCommand(ICommandSender sender, String[] args) { - boolean detailed = false; - String targetPlayerName = null; - for (String arg : args) { - if (arg.equalsIgnoreCase(DETAILED_FLAG)) { - detailed = true; - } else if (targetPlayerName == null) { - targetPlayerName = arg; - } else { - sendMessage(sender, "visualprospecting.command.usage_error", getCommandName()); - return; - } - } - - EntityPlayerMP targetPlayer = resolveTarget(sender, targetPlayerName); - if (targetPlayer == null) return; - - Team team = TeamManager.getTeamByPlayer(targetPlayer.getUniqueID()); - if (team == null) { - sendMessage(sender, "visualprospecting.teamcommand.no_team", targetPlayer.getCommandSenderName()); - return; - } - - TeamProspectionData data = (TeamProspectionData) team.getData(TeamProspectionData.DATA_KEY); - if (data == null) { - sendMessage(sender, "visualprospecting.teaminfo.no_data"); - return; - } - - printReport(sender, team, data, detailed); - } - - private EntityPlayerMP resolveTarget(ICommandSender sender, String targetName) { - if (targetName == null) { - if (sender instanceof EntityPlayerMP self) return self; - sendMessage(sender, "visualprospecting.teamcommand.console_needs_player"); - return null; - } - - // Permission check - if (!sender.canCommandSenderUseCommand(2, getCommandName())) { - sendMessage(sender, "visualprospecting.teaminfo.no_permission_other"); - return null; - } - - EntityPlayerMP target = MinecraftServer.getServer().getConfigurationManager().func_152612_a(targetName); - if (target == null) { - sendMessage(sender, "visualprospecting.teamcommand.player_offline", targetName); - return null; - } - return target; - } - - private static void printReport(ICommandSender sender, Team team, TeamProspectionData data, boolean detailed) { - IntSet dims = data.knownDimensions(); - - long totalVeins = 0, totalFluids = 0, totalDepleted = 0; - for (int dim : dims) { - totalVeins += data.getDiscoveredVeinKeys(dim).size(); - totalFluids += data.getDiscoveredFluidKeys(dim).size(); - totalDepleted += data.getDepletedVeinKeys(dim).size(); - } - - int memberCount = team.getMembers().size(); - int onlineCount = countOnline(team); - - IChatComponent header = new ChatComponentTranslation( - "visualprospecting.teaminfo.header", - team.getTeamName(), - memberCount, - onlineCount); - header.getChatStyle().setBold(true); - sender.addChatMessage(header); - - if (dims.isEmpty()) { - IChatComponent empty = new ChatComponentTranslation("visualprospecting.teaminfo.empty"); - empty.getChatStyle().setColor(EnumChatFormatting.GRAY); - sender.addChatMessage(empty); - return; - } - - sender.addChatMessage( - new ChatComponentTranslation( - "visualprospecting.teaminfo.summary", - dims.size(), - totalVeins, - totalDepleted, - totalFluids)); - - if (!detailed) return; - - int[] sortedDims = dims.toIntArray(); - Arrays.sort(sortedDims); - for (int dim : sortedDims) { - int v = data.getDiscoveredVeinKeys(dim).size(); - int f = data.getDiscoveredFluidKeys(dim).size(); - int d = data.getDepletedVeinKeys(dim).size(); - if (v == 0 && f == 0) continue; - sender.addChatMessage( - new ChatComponentTranslation("visualprospecting.teaminfo.dim_line", dimLabel(dim), v, d, f)); - } - } - - private static int countOnline(Team team) { - int[] count = { 0 }; - TeamManager.forEachOnlineTeamMember(team, p -> count[0]++); - return count[0]; - } - - private static String dimLabel(int dim) { - try { - World world = DimensionManager.getWorld(dim); - if (world != null && world.provider != null) { - String name = world.provider.getDimensionName(); - if (name != null && !name.isEmpty()) { - return dim + " (" + name + ")"; - } - } - } catch (Exception ignored) {} - return Integer.toString(dim); - } - - private static void sendMessage(ICommandSender sender, String translationKey, Object... args) { - IChatComponent msg = new ChatComponentTranslation(translationKey, args); - msg.getChatStyle().setColor(EnumChatFormatting.RED); - sender.addChatMessage(msg); - } -} diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamUploadCommand.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamUploadCommand.java deleted file mode 100644 index 5c7cbba9..00000000 --- a/src/main/java/com/sinthoras/visualprospecting/teams/TeamUploadCommand.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.sinthoras.visualprospecting.teams; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.ChatComponentTranslation; -import net.minecraft.util.EnumChatFormatting; -import net.minecraft.util.IChatComponent; -import net.minecraft.util.StatCollector; - -import com.gtnewhorizon.gtnhlib.teams.Team; -import com.gtnewhorizon.gtnhlib.teams.TeamManager; -import com.sinthoras.visualprospecting.Config; -import com.sinthoras.visualprospecting.VP; -import com.sinthoras.visualprospecting.network.RequestTeamUploadMessage; - -/** - * {@code /vp_team_upload }: ask {@code }'s client to push its {@code ClientCache} into the team's - * {@link TeamProspectionData}. - */ -public class TeamUploadCommand extends CommandBase { - - @Override - public String getCommandName() { - return "vp_team_upload"; - } - - @Override - public String getCommandUsage(ICommandSender sender) { - return StatCollector.translateToLocal("visualprospecting.teamupload.command"); - } - - @Override - public int getRequiredPermissionLevel() { - return 2; - } - - @Override - public boolean canCommandSenderUseCommand(ICommandSender sender) { - if (sender instanceof EntityPlayerMP player) { - if (Objects.equals(player.mcServer.getServerOwner(), sender.getCommandSenderName())) { - return true; - } - } - return super.canCommandSenderUseCommand(sender); - } - - @Override - public List addTabCompletionOptions(ICommandSender sender, String[] args) { - if (args.length == 1) { - return getListOfStringsMatchingLastWord(args, MinecraftServer.getServer().getAllUsernames()); - } - return Collections.emptyList(); - } - - @Override - public void processCommand(ICommandSender sender, String[] args) { - if (args.length != 1) { - sendError(sender, "visualprospecting.command.usage_error", getCommandName()); - return; - } - - if (!Config.enableTeamSharing) { - sendError(sender, "visualprospecting.teamcommand.sharing_disabled"); - return; - } - - EntityPlayerMP target = MinecraftServer.getServer().getConfigurationManager().func_152612_a(args[0]); - if (target == null) { - sendError(sender, "visualprospecting.teamcommand.player_offline", args[0]); - return; - } - - Team team = TeamManager.getTeamByPlayer(target.getUniqueID()); - if (team == null) { - sendError(sender, "visualprospecting.teamcommand.no_team", target.getCommandSenderName()); - return; - } - - VP.network.sendTo(new RequestTeamUploadMessage(), target); - - IChatComponent msg = new ChatComponentTranslation( - "visualprospecting.teamupload.requested", - target.getCommandSenderName(), - team.getTeamName()); - msg.getChatStyle().setColor(EnumChatFormatting.GREEN); - sender.addChatMessage(msg); - } - - private static void sendError(ICommandSender sender, String translationKey, Object... args) { - IChatComponent msg = new ChatComponentTranslation(translationKey, args); - msg.getChatStyle().setColor(EnumChatFormatting.RED); - sender.addChatMessage(msg); - } -} diff --git a/src/main/resources/assets/visualprospecting/lang/de_DE.lang b/src/main/resources/assets/visualprospecting/lang/de_DE.lang index 19abbcb8..f2da359b 100644 --- a/src/main/resources/assets/visualprospecting/lang/de_DE.lang +++ b/src/main/resources/assets/visualprospecting/lang/de_DE.lang @@ -4,30 +4,17 @@ visualprospecting.veins.prospected=Du hast %s neue Erzadern gefunden! visualprospecting.undergroundfluid.prospected.onlynew=Du hast %s neue Ölfelder gefunden! visualprospecting.undergroundfluid.prospected.onlyupdated=Du hast %s Ölfelder vermessen! visualprospecting.undergroundfluid.prospected.newandupdated=Du hast %s Ölfinder neu gefunden und %s vermessen! -visualprospecting.button.dirtychunk=Dirty Chunks anzeigen (Entwicklermodus, nur Einzelspieler) visualprospecting.button.orevein=GT-Erzadern anzeigen visualprospecting.button.undergroundfluid=GT-Gas/Flüssigkeitsadern anzeigen -visualprospecting.button.resetprogress=VisualProspecting zurücksetzen -visualprospecting.button.resetprogress.tooltip=Gefundene Erzadern und Flüssigkeitsadern (nur) für diesen Spieler zurücksetzen -visualprospecting.resetprogress.title=VisualProspecting-Forschritt löschen -visualprospecting.resetprogress.confirm=Ja, ich bin mir sicher! -visualprospecting.resetprogress.cancel=Abbrechen -visualprospecting.resetprogress.prompt=Spielerfortschritt bei Erz- und Flüssigkeitsadern löschen? -visualprospecting.resetprogress.command=Löscht deinen gesamten Fortschritt beim Entdecken von Erz- und Flüssigkeitsadern -visualprospecting.resetprogress.confirmation=Fortschritt gelöscht! -visualprospecting.redoservercache.command=GT-Ader-Cache auf dem Server wiederherstellen -visualprospecting.redoservercache.start=Cache-wiederherstellen auf dem Server beginnen -visualprospecting.redoservercache.failure=Konnte Weltdaten nicht laden, um Cache wiederherstellen! -visualprospecting.redoservercache.confirmation=Wiederherstellen erfolgreich! -visualprospecting.redoserverspawncache.command=GT-Erzader-Cache auf dem Server um den Spawnpunkt herum wiederherstellen -visualprospecting.redoserverspawncache.start=Wiederherstellen des GT-Erzader-Cache um den Spawnpunkt beginnen -visualprospecting.redoserverspawncache.failure=Konnte Weltdaten nicht laden, um Spawncache wiederherstellen! -visualprospecting.redoserverspawncache.confirmation=Wiederherstellen erfolgreich! +visualprospecting.command.vpadmin.servercache.rebuild.start=Cache-wiederherstellen auf dem Server beginnen +visualprospecting.command.vpadmin.servercache.rebuild.failure=Konnte Weltdaten nicht laden, um Cache wiederherstellen! +visualprospecting.command.vpadmin.servercache.rebuild.confirmation=Wiederherstellen erfolgreich! +visualprospecting.command.vpadmin.servercache.rebuildspawn.start=Wiederherstellen des GT-Erzader-Cache um den Spawnpunkt beginnen +visualprospecting.command.vpadmin.servercache.rebuildspawn.failure=Konnte Weltdaten nicht laden, um Spawncache wiederherstellen! +visualprospecting.command.vpadmin.servercache.rebuildspawn.confirmation=Wiederherstellen erfolgreich! visualprospecting.iswaypoint=Als Wegpunkt aktiv visualprospecting.depleted=ERSCHÖPFT -visualprospecting.depleted.toggle=Als erschöpft markieren mit %s visualprospecting.empty=Leer -visualprospecting.key.action.name=Aktionsknopf visualprospecting.key.toggleore.name=Erzoverlay (de)aktivieren visualprospecting.key.togglefluid.name=Flüssigkeitsoverlay (de)aktivieren visualprospecting.key.action.category=VisualProspecting @@ -49,3 +36,5 @@ item.visualprospecting.prospectorslog.reading.begin=Das ist mal ein Wälzer. Das item.visualprospecting.prospectorslog.reading.end=Goldsucher-Tagebuch von %s durchgelesen visualprospecting.node.deletehint=Mit %s als erschöpft markieren visualprospecting.tracked=Nachverfolgt: %s +visualprospecting.command.client.resetcache.usage=Löscht deinen gesamten Fortschritt beim Entdecken von Erz- und Flüssigkeitsadern +visualprospecting.command.client.resetcache.confirmation=Fortschritt gelöscht! \ No newline at end of file diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index fc67eaa0..962bd8d1 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -4,30 +4,11 @@ visualprospecting.veins.prospected=You found %s new ore veins! visualprospecting.undergroundfluid.prospected.onlynew=You found %s new oil fields! visualprospecting.undergroundfluid.prospected.onlyupdated=You updated %s oil fields! visualprospecting.undergroundfluid.prospected.newandupdated=You found %s new and updated %s oil fields! -visualprospecting.button.dirtychunk=Show Dirty Chunks (Developer, Singleplayer only) visualprospecting.button.orevein=Show GT Ore Veins visualprospecting.button.undergroundfluid=Show GT Underground Fluids -visualprospecting.button.resetprogress=Reset VisualProspecting -visualprospecting.button.resetprogress.tooltip=Reset found ore veins and underground fluids for this player only -visualprospecting.resetprogress.title=Delete VisualProspecting Progress -visualprospecting.resetprogress.confirm=Yes, i am sure! -visualprospecting.resetprogress.cancel=Cancel -visualprospecting.resetprogress.prompt=Delete player progress on ore veins and underground fluids? -visualprospecting.resetprogress.command=Deletes all your progress on ore veins and underground fluids -visualprospecting.resetprogress.confirmation=Progress deleted! -visualprospecting.redoservercache.command=Redo the GT vein cache on the server -visualprospecting.redoservercache.start=Start redoing the GT vein cache on the server -visualprospecting.redoservercache.failure=Could not load world save files to build vein cache! -visualprospecting.redoservercache.confirmation=Redo success! -visualprospecting.redoserverspawncache.command=Redo the GT vein cache near spawn on the server -visualprospecting.redoserverspawncache.start=Start redoing the GT vein cache near spawn on the server -visualprospecting.redoserverspawncache.failure=Could not load world save files to build vein cache near spawn! -visualprospecting.redoserverspawncache.confirmation=Redo success! visualprospecting.iswaypoint=Active as Waypoint visualprospecting.depleted=DEPLETED -visualprospecting.depleted.toggle=Toggle depleted with %s visualprospecting.empty=Empty -visualprospecting.key.action.name=Action button visualprospecting.key.toggleore.name=Toggle ore overlay visualprospecting.key.togglefluid.name=Toggle fluid overlay visualprospecting.key.action.category=VisualProspecting @@ -49,19 +30,53 @@ item.visualprospecting.prospectorslog.reading.begin=That's quite a lot of pages. item.visualprospecting.prospectorslog.reading.end=I finished the Prospector's Log of %s visualprospecting.node.deletehint=Mark depleted with %s visualprospecting.tracked=Tracked: %s -visualprospecting.command.usage_error=Invalid arguments for /%s. -visualprospecting.teamcommand.console_needs_player=Must specify a player when running command from console. -visualprospecting.teamcommand.player_offline=Player not found or not online: %s -visualprospecting.teamcommand.no_team=%s is not in any team. -visualprospecting.teaminfo.command=/vp_team_info [player] [detailed]: Inspect a player team's prospection record -visualprospecting.teaminfo.no_data=Team has no prospection data attached. -visualprospecting.teaminfo.no_permission_other=You don't have the permission level required to inspect another team. -visualprospecting.teaminfo.header=Team "%s" (%s members, %s online) -visualprospecting.teaminfo.empty= No discoveries recorded. -visualprospecting.teaminfo.summary= Across %s dim(s): %s veins (%s depleted), %s fluids -visualprospecting.teaminfo.dim_line= Dim %s: %s veins (%s depleted), %s fluids -visualprospecting.teamclear.command=/vp_team_clear : Delete that player team prospection record. -visualprospecting.teamclear.success=Cleared team "%s": Removed %s veins and %s fluids. -visualprospecting.teamcommand.sharing_disabled=Team sharing is disabled in the server config. -visualprospecting.teamupload.command=/vp_team_upload : Push that player's local cache into their team's record. -visualprospecting.teamupload.requested=Requested upload of %s's local cache into team "%s". +visualprospecting.command.console_needs_player=Must specify a player when running command from console. +visualprospecting.command.console_forbidden=This command cannot be run from the console. +visualprospecting.command.player_offline=Player not found or not online: %s +visualprospecting.command.sharing_disabled=Team sharing is disabled in the server config. +visualprospecting.command.client.resetcache.usage=/vp_client_cache_reset: Deletes local cache of all your ore veins and underground fluids +visualprospecting.command.client.resetcache.confirmation=Local cache deleted. It may still reconstruct partially from team cache on next logon if they are enabled. +visualprospecting.command.vp.root.usage=/vp +visualprospecting.command.vp.team.usage=/vp team info [detailed]: Inspect your own team's prospection record. +visualprospecting.command.vp.team.no_team=%s is not in any team. +visualprospecting.command.vp.team.no_data=Team has no prospection data attached. +visualprospecting.command.vp.team.info.header=Team "%s" (%s members, %s online) +visualprospecting.command.vp.team.info.empty= No discoveries recorded. +visualprospecting.command.vp.team.info.summary= Across %s dim(s): %s veins (%s depleted), %s fluids +visualprospecting.command.vp.team.info.dim_line= Dim %s: %s veins (%s depleted), %s fluids +visualprospecting.command.vpadmin.root.usage=/vp_admin : VisualProspecting admin commands. +visualprospecting.command.vpadmin.team.usage=/vp_admin team : Admin operations on a player's team prospection record. +visualprospecting.command.vpadmin.team.info.usage=/vp_admin team info [detailed]: Inspect a player's team prospection record. +visualprospecting.command.vpadmin.team.clear.usage=/vp_admin team clear : Delete the player's team prospection record. +visualprospecting.command.vpadmin.team.clear.success=Cleared team "%s": Removed %s veins and %s fluids. +visualprospecting.command.vpadmin.team.upload.usage=/vp_admin team upload : Request the player's client to push its local cache into the team's record. +visualprospecting.command.vpadmin.team.upload.requested=Requested upload of %s's local cache into team "%s". +visualprospecting.command.vpadmin.servercache.usage=/vp_admin servercache : Server vein cache operations. +visualprospecting.command.vpadmin.servercache.rebuild.usage=/vp_admin servercache rebuild : Rebuild the GT vein cache from world save files. +visualprospecting.command.vpadmin.servercache.no_server=Server instance not found. +visualprospecting.command.vpadmin.servercache.rebuild.start=Started rebuilding the GT vein cache on the server +visualprospecting.command.vpadmin.servercache.rebuild.failure=Could not load world save files to build vein cache! +visualprospecting.command.vpadmin.servercache.rebuild.confirmation=Redo success! +visualprospecting.command.vpadmin.servercache.rebuildspawn.start=Started rebuilding the GT vein cache near spawn on the server +visualprospecting.command.vpadmin.servercache.rebuildspawn.failure=Could not load world save files to build vein cache near spawn! +visualprospecting.command.vpadmin.servercache.rebuildspawn.confirmation=Redo success! +visualprospecting.command.vpadmin.debug.usage=/vp_admin debug : Inspect the server's stored prospection data. +visualprospecting.command.vpadmin.debug.vein.header=Ore chunk [%s, %s] in DIM %s (%s) +visualprospecting.command.vpadmin.debug.vein.type= [Cache] Vein: %s (%s) +visualprospecting.command.vpadmin.debug.vein.source= Source: %s +visualprospecting.command.vpadmin.debug.vein.cache_none= [Cache] No vein recorded. +visualprospecting.command.vpadmin.debug.analyze.title= [Analysis] Live ore analysis +visualprospecting.command.vpadmin.debug.analyze.error= [Analysis] Failed to read live chunk: %s +visualprospecting.command.vpadmin.debug.analyze.no_ores= [Analysis] No natural ores found in this chunk. +visualprospecting.command.vpadmin.debug.analyze.stats= Ores: %s blocks, %s materials, Y %s-%s +visualprospecting.command.vpadmin.debug.analyze.ore_line= %s x%s +visualprospecting.command.vpadmin.debug.analyze.dominant= Dominant: %s (x%s) +visualprospecting.command.vpadmin.debug.analyze.no_dim_veins= Note: dimension "%s" has no registered ore veins. +visualprospecting.command.vpadmin.debug.analyze.candidates_none= No candidate veins for the dominant ore. +visualprospecting.command.vpadmin.debug.analyze.candidates_header= Candidates for %s (%s): +visualprospecting.command.vpadmin.debug.analyze.candidate_line= %s [full=%s, ignoreSporadic=%s] +visualprospecting.command.vpadmin.debug.analyze.match_summary= Summary: %s full, %s sporadic-ignored +visualprospecting.command.vpadmin.debug.analyze.resolved= Resolved (detailed): %s (%s) +visualprospecting.command.vpadmin.debug.analyze.resolved_none= Resolved (detailed): none +visualprospecting.command.vpadmin.debug.analyze.fastpath= Fast-path (ChunkAnalysis): %s +visualprospecting.command.vpadmin.debug.analyze.fastpath_ambiguous= Fast-path (ChunkAnalysis): ambiguous, needs detailed analysis \ No newline at end of file diff --git a/src/main/resources/assets/visualprospecting/lang/zh_CN.lang b/src/main/resources/assets/visualprospecting/lang/zh_CN.lang index 1cb7cbc3..8d93f7eb 100644 --- a/src/main/resources/assets/visualprospecting/lang/zh_CN.lang +++ b/src/main/resources/assets/visualprospecting/lang/zh_CN.lang @@ -4,25 +4,13 @@ visualprospecting.veins.prospected=你找到了 %s 条新矿脉! visualprospecting.undergroundfluid.prospected.onlynew=你找到了 %s 新流体井! visualprospecting.undergroundfluid.prospected.onlyupdated=你更新了 %s 流体井! visualprospecting.undergroundfluid.prospected.newandupdated=你找到了 %s 新流体井并更新了 %s 流体井! -visualprospecting.button.dirtychunk=显示未写盘区块(仅限开发者,单机游戏) visualprospecting.button.orevein=显示GT矿脉 visualprospecting.button.undergroundfluid=显示GT地下流体 -visualprospecting.button.resetprogress=重置VisualProspecting -visualprospecting.button.resetprogress.tooltip=仅重置此玩家发现的矿脉与地下流体 -visualprospecting.resetprogress.title=删除VisualProspecting记录 -visualprospecting.resetprogress.confirm=是的,我确定! -visualprospecting.resetprogress.cancel=取消 -visualprospecting.resetprogress.prompt=删除玩家矿脉与地下流体记录? -visualprospecting.resetprogress.command=删除你的所有矿脉与地下流体记录 -visualprospecting.resetprogress.confirmation=记录已删除! -visualprospecting.redoservercache.command=在服务器上重新缓存GT矿脉 -visualprospecting.redoservercache.start=开始重新缓存GT矿脉 -visualprospecting.redoservercache.failure=无法加载世界存档以构建矿脉缓存 -visualprospecting.redoservercache.confirmation=重新缓存成功! +visualprospecting.command.vpadmin.servercache.rebuild.start=开始重新缓存GT矿脉 +visualprospecting.command.vpadmin.servercache.rebuild.failure=无法加载世界存档以构建矿脉缓存 +visualprospecting.command.vpadmin.servercache.rebuild.confirmation=重新缓存成功! visualprospecting.iswaypoint=作为导航点激活 visualprospecting.depleted=枯竭 -visualprospecting.depleted.toggle=切换为枯竭阈值: %s -visualprospecting.key.action.name=激活按钮 visualprospecting.key.action.category=VisualProspecting item.visualprospecting.prospectorslog.name=探矿记录 item.visualprospecting.prospectorslog.author=作者: %s @@ -41,4 +29,6 @@ item.visualprospecting.prospectorslog.reading.fail4=[失败]: 我有地理学博 item.visualprospecting.prospectorslog.reading.begin=有相当多页.可能得多花点时间通读一遍. item.visualprospecting.prospectorslog.reading.end=我读完了 %s 的探矿记录 visualprospecting.node.deletehint=删除 %s -visualprospecting.tracked=追踪: %s \ No newline at end of file +visualprospecting.tracked=追踪: %s +visualprospecting.command.client.resetcache.usage=删除你的所有矿脉与地下流体记录 +visualprospecting.command.client.resetcache.confirmation=记录已删除! \ No newline at end of file From 4e7f339f9a845e6943eabd240cf8eaf0298578e7 Mon Sep 17 00:00:00 2001 From: Dream Master Date: Fri, 12 Jun 2026 17:43:06 +0200 Subject: [PATCH 120/132] update+bs+deps+gradle --- dependencies.gradle | 6 +++--- gradle/gradle-daemon-jvm.properties | 20 ++++++++++---------- settings.gradle | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 9e46042a..095f9fb2 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,9 +1,9 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.1.3:dev') - api('com.github.GTNewHorizons:GTNHLib:0.11.4:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.579:dev') + api('com.github.GTNewHorizons:GTNHLib:0.11.15:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.601:dev') - compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.28-GTNH:dev') { transitive = false } + compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.29-GTNH:dev') { transitive = false } runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.16')) } diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties index 991a69c7..fa4ed510 100644 --- a/gradle/gradle-daemon-jvm.properties +++ b/gradle/gradle-daemon-jvm.properties @@ -1,12 +1,12 @@ #This file is generated by updateDaemonJvm -toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1630f7ebef05444cb27a2709ea0249b3/redirect -toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect -toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1630f7ebef05444cb27a2709ea0249b3/redirect -toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect -toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/d4fd992c9557644e637ebe98263e0ae7/redirect -toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/faa12903720d410b387cc69ccafb1a74/redirect -toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1630f7ebef05444cb27a2709ea0249b3/redirect -toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect -toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/a4c09dd2e2d7079373d30e524bbc2829/redirect -toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/8e1d9ee5d0f13e442218f6884a306da1/redirect +toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect +toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect +toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect +toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect +toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c2dd35c9d0aaf0ba6ad0791320f99dfc/redirect +toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/e5810bd7fd1f8a586644409d395a7e55/redirect +toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect +toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect +toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/7b3c4877c0749019e6805bb61e421497/redirect +toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d76df094a9cbbabd3b08251f9e61444a/redirect toolchainVersion=25 diff --git a/settings.gradle b/settings.gradle index 407aea22..7371c582 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.24' + id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.26' } From 6dd826781068d79f1e306382dc4010e761574249 Mon Sep 17 00:00:00 2001 From: Algent Date: Mon, 15 Jun 2026 21:48:33 +0200 Subject: [PATCH 121/132] Show ore vein in JM with right colors and a background matching the dimension if it exist (#93) --- .../database/DimensionNameResolver.java | 48 +++++++++++++++++++ .../cachebuilder/DimensionAnalysis.java | 39 +-------------- .../model/locations/OreVeinLocation.java | 8 ++-- .../render/DimensionStoneBackground.java | 48 +++++++++++++++++++ .../model/render/OreVeinRenderStep.java | 5 +- 5 files changed, 104 insertions(+), 44 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/database/DimensionNameResolver.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/render/DimensionStoneBackground.java diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionNameResolver.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionNameResolver.java new file mode 100644 index 00000000..f723ebf2 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionNameResolver.java @@ -0,0 +1,48 @@ +package com.sinthoras.visualprospecting.database; + +import net.minecraft.world.WorldProvider; +import net.minecraft.world.WorldServer; +import net.minecraftforge.common.DimensionManager; + +import com.sinthoras.visualprospecting.VP; + +import cpw.mods.fml.common.Optional; +import gregtech.api.enums.Mods; +import micdoodle8.mods.galacticraft.api.galaxies.CelestialBody; +import micdoodle8.mods.galacticraft.api.prefab.world.gen.WorldProviderSpace; + +/** + * Resolves a dimension name from a {@code dimensionId}, regardless of if that dimension is currently loaded or not. + */ +public final class DimensionNameResolver { + + private DimensionNameResolver() {} + + public static String resolve(int dimensionId) { + final WorldServer world = DimensionManager.getWorld(dimensionId); + WorldProvider provider = world != null ? world.provider : null; + if (provider == null) { + try { + provider = DimensionManager.createProviderFor(dimensionId); + } catch (Throwable t) { + VP.LOG.warn("Could not resolve a provider for dimensionId={}: {}", dimensionId, t); + return ""; + } + } + + final String celestialName = Mods.GalacticraftCore.isModLoaded() ? getCelestialBodyName(provider) : null; + if (celestialName != null) return celestialName; + + final String name = provider.getDimensionName(); + return name == null ? "" : name; + } + + @Optional.Method(modid = Mods.ModIDs.GALACTICRAFT_CORE) + private static String getCelestialBodyName(WorldProvider provider) { + if (provider instanceof WorldProviderSpace space) { + final CelestialBody body = space.getCelestialBody(); + return body == null ? null : body.getName(); + } + return null; + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java index 3648a27f..57ccc117 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DimensionAnalysis.java @@ -12,26 +12,20 @@ import java.util.zip.DataFormatException; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.world.WorldProvider; -import net.minecraft.world.WorldServer; -import net.minecraftforge.common.DimensionManager; import com.github.bsideup.jabel.Desugar; import com.sinthoras.visualprospecting.Config; import com.sinthoras.visualprospecting.Utils; import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.database.DimensionNameResolver; import com.sinthoras.visualprospecting.database.ServerCache; import com.sinthoras.visualprospecting.database.VeinSource; import com.sinthoras.visualprospecting.database.veintypes.VeinType; -import cpw.mods.fml.common.Optional; -import gregtech.api.enums.Mods; import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2IntMap; import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -import micdoodle8.mods.galacticraft.api.galaxies.CelestialBody; -import micdoodle8.mods.galacticraft.api.prefab.world.gen.WorldProviderSpace; public class DimensionAnalysis { @@ -43,7 +37,7 @@ public class DimensionAnalysis { public DimensionAnalysis(int dimensionId) { this.dimensionId = dimensionId; - this.dimensionName = getDimensionName(); + this.dimensionName = DimensionNameResolver.resolve(dimensionId); } private interface IChunkHandler { @@ -251,33 +245,4 @@ private void executeForEachGeneratedOreChunk(File regionFile, IChunkHandler chun AnalysisProgressTracker.notifyCorruptFile(regionFile); } } - - // Resolves the dimension name which will help filter ore veins - private String getDimensionName() { - final WorldServer world = DimensionManager.getWorld(dimensionId); - WorldProvider provider = world != null ? world.provider : null; - if (provider == null) { - try { - provider = DimensionManager.createProviderFor(dimensionId); - } catch (Throwable t) { - VP.LOG.warn("Could not resolve a provider for dimensionId={}: {}", dimensionId, t); - return ""; - } - } - - final String celestialName = Mods.GalacticraftCore.isModLoaded() ? getCelestialBodyName(provider) : null; - if (celestialName != null) return celestialName; - - final String name = provider.getDimensionName(); - return name == null ? "" : name; - } - - @Optional.Method(modid = Mods.ModIDs.GALACTICRAFT_CORE) - private static String getCelestialBodyName(WorldProvider provider) { - if (provider instanceof WorldProviderSpace space) { - final CelestialBody body = space.getCelestialBody(); - return body == null ? null : body.getName(); - } - return null; - } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java index 911fc7e3..54587f01 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/locations/OreVeinLocation.java @@ -41,10 +41,10 @@ public OreVeinLocation(OreVeinPosition oreVeinPosition) { name = EnumChatFormatting.WHITE + oreVeinPosition.veinType.getVeinName(); materialNames = oreVeinPosition.veinType.getOreMaterialNames().stream() .map(materialName -> EnumChatFormatting.GRAY + materialName).collect(Collectors.toList()); - final IOreMaterial representativeOre = oreVeinPosition.veinType.representativeOre; - final TextureSet textureSet = representativeOre.getTextureSet(); + final IOreMaterial primaryOre = oreVeinPosition.veinType.primaryOre; + final TextureSet textureSet = primaryOre.getTextureSet(); iconContainer = textureSet.mTextures[OrePrefixes.ore.getTextureIndex()]; - color = LightingHelper.getColor(representativeOre.getRGBA()); + color = LightingHelper.getColor(primaryOre.getRGBA()); } @Override @@ -126,7 +126,7 @@ public int getColor() { return color; } - public IIconContainer getIconFromRepresentativeOre() { + public IIconContainer getIconFromPrimaryOre() { return iconContainer; } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/DimensionStoneBackground.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/DimensionStoneBackground.java new file mode 100644 index 00000000..9c157621 --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/DimensionStoneBackground.java @@ -0,0 +1,48 @@ +package com.sinthoras.visualprospecting.integration.model.render; + +import java.util.List; + +import net.minecraft.init.Blocks; +import net.minecraft.util.IIcon; + +import com.sinthoras.visualprospecting.database.DimensionNameResolver; + +import gregtech.api.enums.StoneType; +import gtneioreplugin.util.DimensionHelper; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +/** + * Picks the stone-type background icon for an ore-vein marker so it matches the vein's host rock (netherrack in the + * Nether, end stone in the End, ...). + *

    + * Unmapped dimensions fall back to vanilla stone. + */ +public final class DimensionStoneBackground { + + private static final Int2ObjectOpenHashMap STONE_BY_DIM_ID = new Int2ObjectOpenHashMap<>(); + + private DimensionStoneBackground() {} + + /** Returns the stone background icon for the vein's dimension, or vanilla stone when unknown. */ + public static IIcon getBackgroundIcon(int dimensionId) { + StoneType stoneType = STONE_BY_DIM_ID.get(dimensionId); + if (stoneType == null) { + final String dimName = DimensionNameResolver.resolve(dimensionId); + stoneType = resolveStoneType(dimName); + if (!dimName.isEmpty()) { + STONE_BY_DIM_ID.put(dimensionId, stoneType); + } + } + + final IIcon icon = stoneType.getIcon(1); + return icon != null ? icon : Blocks.stone.getIcon(0, 0); + } + + private static StoneType resolveStoneType(String dimName) { + if (!DimensionHelper.INTERNAL_TO_FULL.containsKey(dimName)) { + return StoneType.Stone; + } + final List stoneTypes = DimensionHelper.getStoneTypes(dimName); + return stoneTypes.isEmpty() ? StoneType.Stone : stoneTypes.get(0); + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java index d8021dbc..556914bd 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java @@ -4,7 +4,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; -import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.util.IIcon; import net.minecraft.util.ResourceLocation; @@ -65,10 +64,10 @@ public void draw(double topX, double topY, float drawScale, double zoom) { getFontScale()); } - final IIcon blockIcon = Blocks.stone.getIcon(0, 0); + final IIcon blockIcon = DimensionStoneBackground.getBackgroundIcon(location.getDimensionId()); DrawUtils.drawQuad(blockIcon, topX, topY, width, height, 0xFFFFFF, 255); - final IIconContainer oreIconContainer = location.getIconFromRepresentativeOre(); + final IIconContainer oreIconContainer = location.getIconFromPrimaryOre(); final IIcon oreIcon = oreIconContainer.getIcon(); DrawUtils.drawQuad(oreIcon, topX, topY, width, height, location.getColor(), 255); final IIcon oreIconOverlay = oreIconContainer.getOverlayIcon(); From 031672caafba3b163184e91dc0daa8a844d81fe6 Mon Sep 17 00:00:00 2001 From: Kogepan229 <73163994+Kogepan229@users.noreply.github.com> Date: Mon, 29 Jun 2026 02:30:37 +0900 Subject: [PATCH 122/132] Adapt to GT5u change (#95) --- dependencies.gradle | 2 +- src/main/java/com/sinthoras/visualprospecting/Utils.java | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 095f9fb2..878b1cfe 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.1.3:dev') api('com.github.GTNewHorizons:GTNHLib:0.11.15:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.601:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.02:dev') compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.29-GTNH:dev') { transitive = false } diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 3f26610b..9b41f626 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -39,7 +39,9 @@ import codechicken.nei.NEIClientConfig; import codechicken.nei.SearchField; +import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Loader; +import cpw.mods.fml.relauncher.Side; import gregtech.common.GTWorldgenerator; @SuppressWarnings("ResultOfMethodCallIgnored") @@ -62,7 +64,10 @@ public static long chunkCoordsToKey(int chunkX, int chunkZ) { } public static int mapToCenterOreChunkCoord(final int chunkCoord) { - if (GTWorldgenerator.oregenPattern == GTWorldgenerator.OregenPattern.EQUAL_SPACING) { + GTWorldgenerator.OregenPattern pattern = FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER + ? GTWorldgenerator.getServerOregenPattern() + : GTWorldgenerator.getClientOregenPattern(); + if (pattern == GTWorldgenerator.OregenPattern.EQUAL_SPACING) { // new evenly spaced ore pattern return chunkCoord - Math.floorMod(chunkCoord, 3) + 1; } else { From 34c3d7cd6b05cedb38aa66fc1745989a5f8279cb Mon Sep 17 00:00:00 2001 From: Algent Date: Sun, 28 Jun 2026 19:50:35 +0200 Subject: [PATCH 123/132] Add NEI style search modes to ore overlay (#94) --- dependencies.gradle | 7 ++-- .../sinthoras/visualprospecting/Utils.java | 18 ++++++++ .../database/veintypes/VeinType.java | 42 +++++++++++++++++++ .../database/veintypes/VeinTypeCaching.java | 21 ++++------ .../model/layers/OreVeinLayerManager.java | 4 +- 5 files changed, 75 insertions(+), 17 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 878b1cfe..2b5faef8 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,9 +1,10 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.1.3:dev') - api('com.github.GTNewHorizons:GTNHLib:0.11.15:dev') + api('com.github.GTNewHorizons:GTNHLib:0.11.20:dev') api('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.02:dev') + api('com.github.GTNewHorizons:NotEnoughItems:2.8.107-GTNH:dev') - compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.29-GTNH:dev') { transitive = false } + compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.31-GTNH:dev') { transitive = false } - runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.16')) + runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.18')) } diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index 9b41f626..ff98d4fc 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -39,6 +39,7 @@ import codechicken.nei.NEIClientConfig; import codechicken.nei.SearchField; +import codechicken.nei.api.ItemFilter; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Loader; import cpw.mods.fml.relauncher.Side; @@ -263,4 +264,21 @@ public static void sendChatMessage(IChatComponent msg, boolean italic, EnumChatF return null; } } + + public static @Nullable ItemFilter getNEISearchItemFilter() { + final String searchString = NEIClientConfig.getSearchExpression(); + if (!SearchField.searchInventories() || searchString.isEmpty()) { + return null; + } + return getItemFilter(searchString); + } + + public static @Nullable ItemFilter getItemFilter(@NotNull String searchString) { + if (searchString.isEmpty()) return null; + try { + return SearchField.getFilter(searchString); + } catch (Exception e) { + return null; + } + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 6f884c51..9d250afa 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -4,14 +4,21 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.regex.Pattern; import java.util.stream.Collectors; +import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; + import com.google.common.collect.ImmutableList; import com.sinthoras.visualprospecting.Tags; +import codechicken.nei.api.ItemFilter; import galacticgreg.api.enums.DimensionDef.DimNames; +import gregtech.api.enums.OrePrefixes; import gregtech.api.interfaces.IOreMaterial; import gregtech.common.OreMixBuilder; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; @@ -37,6 +44,10 @@ public class VeinType { private final List allowedDims = new ArrayList<>(); private boolean isHighlighted = true; private final String localizedName; + private static final OrePrefixes[] SEARCH_PREFIXES = { OrePrefixes.dust, OrePrefixes.gem, OrePrefixes.ingot, + OrePrefixes.crushed, OrePrefixes.ore }; + @Nullable + private List oreSearchStacks; // Available after VisualProspecting post GT initialization public static final VeinType NO_VEIN = new VeinType(); @@ -127,6 +138,37 @@ public String getVeinName() { return localizedName; } + public boolean matchesPattern(Pattern pattern) { + final List searchableStrings = new ArrayList<>(getOreMaterialNames()); + searchableStrings.add(getVeinName()); + return searchableStrings.stream().map(EnumChatFormatting::getTextWithoutFormattingCodes) + .map(String::toLowerCase).anyMatch(searchableString -> pattern.matcher(searchableString).find()); + } + + public boolean matchesItemFilter(ItemFilter filter) { + for (ItemStack stack : getOreSearchStacks()) { + if (filter.matches(stack)) return true; + } + return false; + } + + private List getOreSearchStacks() { + if (oreSearchStacks == null) { + oreSearchStacks = new ArrayList<>(); + for (IOreMaterial ore : oresAsSet) { + if (ore == null) continue; + for (OrePrefixes prefix : SEARCH_PREFIXES) { + final ItemStack stack = ore.getPart(prefix, 1); + if (stack != null) { + oreSearchStacks.add(stack); + break; + } + } + } + } + return oreSearchStacks; + } + public List getOresAtLayer(int layerBlockY) { if (layerBlockY < 0 || layerBlockY >= veinHeight) { return Collections.emptyList(); diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java index b1df9d18..219e181f 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinTypeCaching.java @@ -6,13 +6,12 @@ import java.util.List; import java.util.regex.Pattern; -import net.minecraft.util.EnumChatFormatting; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.sinthoras.visualprospecting.Tags; +import codechicken.nei.api.ItemFilter; import gregtech.api.enums.OreMixes; import gregtech.api.interfaces.IOreMaterial; import it.unimi.dsi.fastutil.objects.Object2ObjectMap; @@ -79,20 +78,18 @@ public static List getVeinTypesForOre(IOreMaterial dominantOre) { return matchingVeinTypes == null ? Collections.emptyList() : matchingVeinTypes; } - public static void recalculateSearch(@Nullable Pattern filterPattern) { + public static void recalculateSearch(@Nullable Pattern filterPattern, @Nullable ItemFilter itemFilter) { for (VeinType veinType : veinTypes.values()) { if (veinType == VeinType.NO_VEIN) continue; - if (filterPattern != null) { - List searchableStrings = new ArrayList<>(veinType.getOreMaterialNames()); - searchableStrings.add(veinType.getVeinName()); - final boolean match = searchableStrings.stream().map(EnumChatFormatting::getTextWithoutFormattingCodes) - .map(String::toLowerCase) - .anyMatch(searchableString -> filterPattern.matcher(searchableString).find()); - - veinType.setNEISearchHighlight(match); - } else { + if (filterPattern == null && itemFilter == null) { veinType.setNEISearchHighlight(true); + continue; } + + final boolean match = (filterPattern != null && veinType.matchesPattern(filterPattern)) + || (itemFilter != null && veinType.matchesItemFilter(itemFilter)); + + veinType.setNEISearchHighlight(match); } } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java index 45336781..13cdb436 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java @@ -31,7 +31,7 @@ public OreVeinLayerManager() { @Override public void onOpenMap() { - VeinTypeCaching.recalculateSearch(Utils.getNEISearchPattern()); + VeinTypeCaching.recalculateSearch(Utils.getNEISearchPattern(), Utils.getNEISearchItemFilter()); } @Nullable @@ -68,6 +68,6 @@ protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { @Override public void onSearch(@NotNull String searchString) { - VeinTypeCaching.recalculateSearch(Utils.getSearchPattern(searchString)); + VeinTypeCaching.recalculateSearch(Utils.getSearchPattern(searchString), Utils.getItemFilter(searchString)); } } From 9b99427e0d8811322bc4cb5f9c11e0e0be176dd9 Mon Sep 17 00:00:00 2001 From: Algent Date: Sat, 4 Jul 2026 18:03:13 +0200 Subject: [PATCH 124/132] Show more clear indicator on overlay for what fluid amount mean (#96) --- .../render/UndergroundFluidRenderStep.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java index d3c2ebfb..5d77ab18 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java @@ -1,5 +1,7 @@ package com.sinthoras.visualprospecting.integration.model.render; +import java.text.MessageFormat; + import net.minecraft.client.Minecraft; import net.minecraft.client.resources.I18n; @@ -41,10 +43,11 @@ public void draw(double topX, double topY, float drawScale, double zoom) { if (!isMinimap()) { String label = I18n.format("visualprospecting.empty"); if (maxAmountInField > 0) { - label = location.getMinProduction() + "L - " - + maxAmountInField - + "L " - + location.getFluid().getLocalizedName(); + label = MessageFormat.format( + "{0}-{1} L/Op {2}", + formatAmount(location.getMinProduction()), + formatAmount(maxAmountInField), + location.getFluid().getLocalizedName()); } int textColor = 0xFFFFFFFF; @@ -101,7 +104,7 @@ private void renderChunks(double x, double y) { if (drawLabels) { DrawUtils.drawLabel( - getFluidAmountFormatted(amount), + MessageFormat.format("{0} L/Op", formatAmount(amount)), cellX + cellW / 2, cellY + cellH / 2, 0xFFFFFFFF, @@ -113,10 +116,14 @@ private void renderChunks(double x, double y) { } } - private String getFluidAmountFormatted(int amount) { - if (amount >= 1000) { - return (amount / 1000) + "kL"; + private String formatAmount(int amount) { + if (amount < 1000) { + return String.valueOf(amount); + } + final int roundedTenths = (amount + 50) / 100; + if (roundedTenths % 10 == 0) { + return (roundedTenths / 10) + "k"; } - return amount + "L"; + return (roundedTenths / 10) + "." + (roundedTenths % 10) + "k"; } } From 61e24631efdea38a3fb5efe417f51cc40fc15611 Mon Sep 17 00:00:00 2001 From: Martin Robertz Date: Sat, 4 Jul 2026 19:41:59 +0200 Subject: [PATCH 125/132] update deps --- dependencies.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 2b5faef8..d1c7aee7 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,8 +1,8 @@ dependencies { - api('com.github.GTNewHorizons:Navigator:1.1.3:dev') - api('com.github.GTNewHorizons:GTNHLib:0.11.20:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.02:dev') - api('com.github.GTNewHorizons:NotEnoughItems:2.8.107-GTNH:dev') + api('com.github.GTNewHorizons:Navigator:1.1.4:dev') + api('com.github.GTNewHorizons:GTNHLib:0.11.23:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.15:dev') + api('com.github.GTNewHorizons:NotEnoughItems:2.8.110-GTNH:dev') compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.31-GTNH:dev') { transitive = false } From 561a33f1af4ff5cb375abd035cd1515dbbc235d0 Mon Sep 17 00:00:00 2001 From: Algent Date: Thu, 9 Jul 2026 22:26:09 +0200 Subject: [PATCH 126/132] Guard against null/fake player (Fix Log spam) (#97) --- .../visualprospecting/teams/TeamProspectionDispatcher.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java index 342b1fa7..fe059260 100644 --- a/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java +++ b/src/main/java/com/sinthoras/visualprospecting/teams/TeamProspectionDispatcher.java @@ -44,6 +44,8 @@ public static void deliverProspectingResults(EntityPlayerMP player, ProspectingN public static void deliverProspectingResults(EntityPlayerMP player, ProspectingNotification notification, boolean notifySelf) { + if (player == null || player.playerNetServerHandler == null) return; + if (notifySelf) { VP.network.sendTo(notification, player); } From 74c32ffe7179ec598b7d83fd71baf8ba627f61ce Mon Sep 17 00:00:00 2001 From: Algent Date: Sun, 12 Jul 2026 13:36:41 +0200 Subject: [PATCH 127/132] Fix incorrect oregen pattern being used in some case. Attempt to autofix wrong entries in cache (#99) --- dependencies.gradle | 2 +- .../sinthoras/visualprospecting/Utils.java | 6 +- .../database/DimensionCache.java | 55 ++++++++++++++++--- .../database/WorldCache.java | 4 +- .../teams/TeamCatchupHandler.java | 9 +++ .../teams/TeamProspectionData.java | 38 +++++++++++++ 6 files changed, 98 insertions(+), 16 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index d1c7aee7..58b50f68 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,7 +1,7 @@ dependencies { api('com.github.GTNewHorizons:Navigator:1.1.4:dev') api('com.github.GTNewHorizons:GTNHLib:0.11.23:dev') - api('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.15:dev') + api('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.29:dev') api('com.github.GTNewHorizons:NotEnoughItems:2.8.110-GTNH:dev') compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.31-GTNH:dev') { transitive = false } diff --git a/src/main/java/com/sinthoras/visualprospecting/Utils.java b/src/main/java/com/sinthoras/visualprospecting/Utils.java index ff98d4fc..1e037e84 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Utils.java +++ b/src/main/java/com/sinthoras/visualprospecting/Utils.java @@ -40,9 +40,7 @@ import codechicken.nei.NEIClientConfig; import codechicken.nei.SearchField; import codechicken.nei.api.ItemFilter; -import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Loader; -import cpw.mods.fml.relauncher.Side; import gregtech.common.GTWorldgenerator; @SuppressWarnings("ResultOfMethodCallIgnored") @@ -65,9 +63,7 @@ public static long chunkCoordsToKey(int chunkX, int chunkZ) { } public static int mapToCenterOreChunkCoord(final int chunkCoord) { - GTWorldgenerator.OregenPattern pattern = FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER - ? GTWorldgenerator.getServerOregenPattern() - : GTWorldgenerator.getClientOregenPattern(); + GTWorldgenerator.OregenPattern pattern = GTWorldgenerator.getOregenPattern(); if (pattern == GTWorldgenerator.OregenPattern.EQUAL_SPACING) { // new evenly spaced ore pattern return chunkCoord - Math.floorMod(chunkCoord, 3) + 1; diff --git a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java index d8141107..e6c889e5 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/DimensionCache.java @@ -71,6 +71,7 @@ public enum UpdateResult { public final int dimensionId; private boolean isDirty = false; private boolean preventSaving = false; + private boolean requiresOreRescan = false; public DimensionCache(int dimensionId) { this.dimensionId = dimensionId; @@ -127,6 +128,9 @@ private void loadOres(NBTTagCompound ores) { oreChunks.ensureCapacity(oreChunks.size() + size); int unknownVeinTypes = 0; + int repairedCoordinates = 0; + int discardedRescans = 0; + int collapsedDuplicates = 0; for (int i = 0; i < size; i++) { int index = veinTypeIndexArray[i]; if (index < 0 || index >= palette.length) { @@ -139,15 +143,33 @@ private void loadOres(NBTTagCompound ores) { continue; } VeinSource source = VeinSource.fromByte(sourceArray[i]); - oreChunks.put( - getOreVeinKey(chunkXArray[i], chunkZArray[i]), - new OreVeinPosition( - dimensionId, - chunkXArray[i], - chunkZArray[i], - veinType, - depletedArray[i] == 1, - source)); + OreVeinPosition position = new OreVeinPosition( + dimensionId, + chunkXArray[i], + chunkZArray[i], + veinType, + depletedArray[i] == 1, + source); + if (position.chunkX != chunkXArray[i] || position.chunkZ != chunkZArray[i]) { + repairedCoordinates++; + if (source == VeinSource.RESCAN) { + discardedRescans++; + requiresOreRescan = true; + continue; + } + } + long key = getOreVeinKey(position.chunkX, position.chunkZ); + OreVeinPosition stored = oreChunks.get(key); + if (stored == null) { + oreChunks.put(key, position); + } else { + collapsedDuplicates++; + if (position.getSource().canOverwrite(stored.getSource())) { + oreChunks.put(key, position.joinDepletedState(stored)); + } else { + stored.joinDepletedState(position); + } + } } if (unknownVeinTypes > 0) { VP.LOG.warn( @@ -155,6 +177,17 @@ private void loadOres(NBTTagCompound ores) { dimensionId, unknownVeinTypes); } + if (repairedCoordinates > 0) { + markDirty(); + VP.LOG.warn( + "Dimension {}: found {} misaligned ore vein cache coordinates, repaired {}, discarded {} entries " + + "that require a rescan, and collapsed {} duplicates. The cache will be rewritten.", + dimensionId, + repairedCoordinates, + repairedCoordinates - discardedRescans, + discardedRescans, + collapsedDuplicates); + } } private void loadFluids(NBTTagCompound fluids) { @@ -337,6 +370,10 @@ boolean hasFluids() { return !undergroundFluids.isEmpty(); } + boolean requiresOreRescan() { + return requiresOreRescan; + } + void markPreventSaving() { preventSaving = true; } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java index 0f3de098..c1934208 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/WorldCache.java @@ -35,6 +35,7 @@ public boolean loadVeinCache(String worldId) { if (dimensionFiles == null || dimensionFiles.length == 0) return false; boolean loadedAny = false; + boolean requiresOreRescan = false; for (File dimensionFile : dimensionFiles) { final String fileName = dimensionFile.getName(); if (!dimensionFile.isFile() || !fileName.endsWith(".dat")) { @@ -47,10 +48,11 @@ public boolean loadVeinCache(String worldId) { final int dimensionId = dimCompound.getInteger("dim"); final DimensionCache dimension = dimensions.computeIfAbsent(dimensionId, DimensionCache::new); dimension.loadFromNbt(dimCompound); + requiresOreRescan |= dimension.requiresOreRescan(); loadedAny = true; } - return loadedAny; + return loadedAny && !requiresOreRescan; } private boolean loadLegacyVeinCache(File worldCacheDirectory) { diff --git a/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java b/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java index 7382af12..2f5033cd 100644 --- a/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java +++ b/src/main/java/com/sinthoras/visualprospecting/teams/TeamCatchupHandler.java @@ -87,6 +87,7 @@ public static void onTeamMerge(TeamMergeEvent event) { TeamProspectionData data = (TeamProspectionData) surviving.getData(TeamProspectionData.DATA_KEY); if (data == null) return; + markRepairedTeamDataDirty(surviving, data); // Update every player with new merged data, only for dimensions they visited since login TeamManager.forEachOnlineTeamMember(surviving, member -> { @@ -111,6 +112,7 @@ private static void sendDimIfNeeded(EntityPlayerMP player, int dim) { if (team == null) return; TeamProspectionData data = (TeamProspectionData) team.getData(TeamProspectionData.DATA_KEY); if (data == null) return; + markRepairedTeamDataDirty(team, data); sendDimVeins(player, data, dim); sendDimFluids(player, data, dim); @@ -187,4 +189,11 @@ private static void flushFluids(EntityPlayerMP player, List depletedVeins; // Team Data - Status private boolean expanded; + private boolean repairedVeinCoordinates; private byte[] unknownVersionBlob; private int unknownVersion; @@ -75,9 +77,43 @@ private void ensureExpanded() { } pendingBlob = null; } + repairedVeinCoordinates = normalizeVeinCoordinates(discoveredVeins) | normalizeVeinCoordinates(depletedVeins); expanded = true; } + public boolean consumeRepairedVeinCoordinates() { + ensureExpanded(); + boolean repaired = repairedVeinCoordinates; + repairedVeinCoordinates = false; + return repaired; + } + + private static boolean normalizeVeinCoordinates(Int2ObjectMap veins) { + boolean repaired = false; + for (LongSet keys : veins.values()) { + long[] oldKeys = keys.toLongArray(); + boolean changed = false; + for (long key : oldKeys) { + if (veinChunkX(key) != Utils.mapToCenterOreChunkCoord(veinChunkX(key)) + || veinChunkZ(key) != Utils.mapToCenterOreChunkCoord(veinChunkZ(key))) { + changed = true; + break; + } + } + if (!changed) continue; + + keys.clear(); + for (long key : oldKeys) { + keys.add( + packVein( + Utils.mapToCenterOreChunkCoord(veinChunkX(key)), + Utils.mapToCenterOreChunkCoord(veinChunkZ(key)))); + } + repaired = true; + } + return repaired; + } + // Pack an Ore vein position static long packVein(int chunkX, int chunkZ) { return ((long) chunkX << 32) | (chunkZ & 0xFFFFFFFFL); @@ -135,6 +171,7 @@ public void clear() { discoveredVeins = new Int2ObjectOpenHashMap<>(); discoveredFluids = new Int2ObjectOpenHashMap<>(); depletedVeins = new Int2ObjectOpenHashMap<>(); + repairedVeinCoordinates = false; expanded = true; } @@ -203,6 +240,7 @@ public void readFromNBT(NBTTagCompound tag) { discoveredVeins = null; discoveredFluids = null; depletedVeins = null; + repairedVeinCoordinates = false; if (!tag.hasKey(TAG_BLOB, Constants.NBT.TAG_STRING)) return; int version = tag.getInteger(TAG_VERSION); From 77f80340a78659d82cb436c78b2cb9cff907f2ff Mon Sep 17 00:00:00 2001 From: Algent Date: Sat, 18 Jul 2026 10:52:47 +0200 Subject: [PATCH 128/132] Fix Xaeros culling regression (#101) --- .../model/render/OreVeinRenderStep.java | 17 ++++++++++------- .../render/UndergroundFluidRenderStep.java | 8 +++++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java index 556914bd..8f88c8ea 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java @@ -43,13 +43,16 @@ public void preRender(double topX, double topY, float drawScale, double zoom) { @Override public void draw(double topX, double topY, float drawScale, double zoom) { - final Minecraft mc = Minecraft.getMinecraft(); - final double scale = isXaero && shouldScale ? getScaling(zoom) : 1.0; - final double screenW = mc.displayWidth * scale; - final double screenH = mc.displayHeight * scale; - final double topMargin = (fontHeight + 5) * getFontScale() * scale; - if (topX + width < 0 || topX > screenW || topY + height < -topMargin || topY > screenH) { - return; + // Xaero culling relies on Navigator's visible cache; add centered bounds if that cache grows costly. + if (!isXaero) { + final Minecraft mc = Minecraft.getMinecraft(); + final double scale = 1.0; + final double screenW = mc.displayWidth * scale; + final double screenH = mc.displayHeight * scale; + final double topMargin = (fontHeight + 5) * getFontScale() * scale; + if (topX + width < 0 || topX > screenW || topY + height < -topMargin || topY > screenH) { + return; + } } if (zoom >= Config.minZoomLevelForOreLabel && !location.isDepleted()) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java index 5d77ab18..963a4a2a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java @@ -25,7 +25,9 @@ public void draw(double topX, double topY, float drawScale, double zoom) { final Minecraft mc = Minecraft.getMinecraft(); final double regionW = VP.undergroundFluidSizeChunkX * VP.chunkWidth * blockSize; final double regionH = VP.undergroundFluidSizeChunkZ * VP.chunkWidth * blockSize; - if (topX + regionW < 0 || topY + regionH < 0 || topX > mc.displayWidth || topY > mc.displayHeight) { + // Xaero culling relies on Navigator's visible cache; add centered bounds if that cache grows costly. + if (!isXaero + && (topX + regionW < 0 || topY + regionH < 0 || topX > mc.displayWidth || topY > mc.displayHeight)) { return; } @@ -89,10 +91,10 @@ private void renderChunks(double x, double y) { final double cellH = getAdjustedHeight(); for (int chunkX = 0; chunkX < VP.undergroundFluidSizeChunkX; chunkX++) { final double cellX = x + chunkX * cellW; - if (cellX + cellW < 0 || cellX > screenW) continue; + if (!isXaero && (cellX + cellW < 0 || cellX > screenW)) continue; for (int chunkZ = 0; chunkZ < VP.undergroundFluidSizeChunkZ; chunkZ++) { final double cellY = y + chunkZ * cellH; - if (cellY + cellH < 0 || cellY > screenH) continue; + if (!isXaero && (cellY + cellH < 0 || cellY > screenH)) continue; int amount = chunks[chunkX][chunkZ]; if (amount <= 0) continue; int alpha = productionRange > 1 ? (int) ((amount - minProduction) / productionRange * 255) : 10; From c2779a619990bec676070040d02b7cd9765bfb78 Mon Sep 17 00:00:00 2001 From: Algent Date: Sun, 26 Jul 2026 11:24:20 +0200 Subject: [PATCH 129/132] Relax a little bit the cache fallback command (#103) --- .../commands/admin/VPAdminDebugCommand.java | 10 +++++----- .../cachebuilder/DetailedChunkAnalysis.java | 9 ++++++--- .../database/veintypes/VeinType.java | 15 +++++++-------- .../assets/visualprospecting/lang/en_US.lang | 6 +++--- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminDebugCommand.java b/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminDebugCommand.java index bf569a45..54a10499 100644 --- a/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminDebugCommand.java +++ b/src/main/java/com/sinthoras/visualprospecting/commands/admin/VPAdminDebugCommand.java @@ -150,15 +150,15 @@ private static void printCandidateReasoning(ICommandSender sender, Reference2Int CommandHelpers.plain(sender, ANALYZE + "candidates_header", dominant.getLocalizedName(), candidates.size()); int fullMatches = 0; - int sporadicIgnoredMatches = 0; + int oneMissingMatches = 0; for (VeinType candidate : candidates) { final boolean full = candidate.matchesWithSpecificPrimaryOrSecondary(oreCounts.keySet(), dimName, dominant); - final boolean ignoreSporadic = candidate.matchesIgnoringSporadic(oreCounts.keySet(), dimName, dominant); + final boolean oneMissing = candidate.matchesWithOneMissingOre(oreCounts.keySet(), dimName, dominant); if (full) fullMatches++; - if (ignoreSporadic) sporadicIgnoredMatches++; - CommandHelpers.plain(sender, ANALYZE + "candidate_line", candidate.name, full, ignoreSporadic); + if (oneMissing) oneMissingMatches++; + CommandHelpers.plain(sender, ANALYZE + "candidate_line", candidate.name, full, oneMissing); } - CommandHelpers.plain(sender, ANALYZE + "match_summary", fullMatches, sporadicIgnoredMatches); + CommandHelpers.plain(sender, ANALYZE + "match_summary", fullMatches, oneMissingMatches); } // Print Verdict diff --git a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java index 273e450c..1aa8564e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/cachebuilder/DetailedChunkAnalysis.java @@ -135,13 +135,16 @@ private VeinType getMatchedVein() { .noneMatch(blockY -> isOreVeinGeneratedAtHeight(veinType, blockY))); return matchedVeins.size() == 1 ? matchedVeins.iterator().next() : VeinType.NO_VEIN; } - return matchIgnoringSporadic(allOres.keySet(), dominantOre); + if (ServerCache.instance.getOreVein(dimensionId, chunkX, chunkZ).veinType != VeinType.NO_VEIN) { + return VeinType.NO_VEIN; + } + return matchWithOneMissingOre(allOres.keySet(), dominantOre); } - private VeinType matchIgnoringSporadic(Set foundOres, IOreMaterial dominantOre) { + private VeinType matchWithOneMissingOre(Set foundOres, IOreMaterial dominantOre) { VeinType onlyMatch = VeinType.NO_VEIN; for (VeinType veinType : VeinTypeCaching.getVeinTypesForOre(dominantOre)) { - if (veinType.matchesIgnoringSporadic(foundOres, dimName, dominantOre)) { + if (veinType.matchesWithOneMissingOre(foundOres, dimName, dominantOre)) { if (onlyMatch != VeinType.NO_VEIN) { return VeinType.NO_VEIN; } diff --git a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java index 9d250afa..51e231b6 100644 --- a/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java +++ b/src/main/java/com/sinthoras/visualprospecting/database/veintypes/VeinType.java @@ -39,7 +39,6 @@ public class VeinType { public final int minBlockY; public final int maxBlockY; private final ReferenceOpenHashSet oresAsSet = new ReferenceOpenHashSet<>(); - private final ReferenceOpenHashSet nonSporadicOres = new ReferenceOpenHashSet<>(); private final List> oresByLayer; private final List allowedDims = new ArrayList<>(); private boolean isHighlighted = true; @@ -75,9 +74,6 @@ public VeinType(OreMixBuilder oreMix) { oresAsSet.add(secondaryOre = oreMix.secondary); oresAsSet.add(inBetweenOre = oreMix.between); oresAsSet.add(sporadicOre = oreMix.sporadic); - nonSporadicOres.add(primaryOre); - nonSporadicOres.add(secondaryOre); - nonSporadicOres.add(inBetweenOre); oresByLayer = buildOresByLayer(); minBlockY = Math.max(0, oreMix.minY - 6); maxBlockY = Math.min(255, oreMix.maxY - 6); @@ -106,10 +102,13 @@ public boolean matchesWithSpecificPrimaryOrSecondary(Collection fo && foundOres.containsAll(oresAsSet); } - public boolean matchesIgnoringSporadic(Collection foundOres, String dimName, IOreMaterial specific) { - return (primaryOre == specific || secondaryOre == specific) - && (dimName.isEmpty() || allowedDims.contains(dimName)) - && foundOres.containsAll(nonSporadicOres); + public boolean matchesWithOneMissingOre(Collection foundOres, String dimName, + IOreMaterial dominantOre) { + // Only match veins with four distinct ores when exactly three were found. + if (oresAsSet.size() != 4 || foundOres.size() != 3) return false; + if (primaryOre != dominantOre && secondaryOre != dominantOre) return false; + if (!dimName.isEmpty() && !allowedDims.contains(dimName)) return false; + return oresAsSet.containsAll(foundOres); } public List getAllowedDimensions() { diff --git a/src/main/resources/assets/visualprospecting/lang/en_US.lang b/src/main/resources/assets/visualprospecting/lang/en_US.lang index 962bd8d1..59fba23f 100644 --- a/src/main/resources/assets/visualprospecting/lang/en_US.lang +++ b/src/main/resources/assets/visualprospecting/lang/en_US.lang @@ -74,9 +74,9 @@ visualprospecting.command.vpadmin.debug.analyze.dominant= Dominant: %s (x%s) visualprospecting.command.vpadmin.debug.analyze.no_dim_veins= Note: dimension "%s" has no registered ore veins. visualprospecting.command.vpadmin.debug.analyze.candidates_none= No candidate veins for the dominant ore. visualprospecting.command.vpadmin.debug.analyze.candidates_header= Candidates for %s (%s): -visualprospecting.command.vpadmin.debug.analyze.candidate_line= %s [full=%s, ignoreSporadic=%s] -visualprospecting.command.vpadmin.debug.analyze.match_summary= Summary: %s full, %s sporadic-ignored +visualprospecting.command.vpadmin.debug.analyze.candidate_line= %s [full=%s, oneMissing=%s] +visualprospecting.command.vpadmin.debug.analyze.match_summary= Summary: %s full, %s one-missing visualprospecting.command.vpadmin.debug.analyze.resolved= Resolved (detailed): %s (%s) visualprospecting.command.vpadmin.debug.analyze.resolved_none= Resolved (detailed): none visualprospecting.command.vpadmin.debug.analyze.fastpath= Fast-path (ChunkAnalysis): %s -visualprospecting.command.vpadmin.debug.analyze.fastpath_ambiguous= Fast-path (ChunkAnalysis): ambiguous, needs detailed analysis \ No newline at end of file +visualprospecting.command.vpadmin.debug.analyze.fastpath_ambiguous= Fast-path (ChunkAnalysis): ambiguous, needs detailed analysis From 8c1b87819064c8ce0b7fe36decd83770ffa50eb5 Mon Sep 17 00:00:00 2001 From: Algent Date: Wed, 29 Jul 2026 14:02:14 +0200 Subject: [PATCH 130/132] JourneyMap 6 support for ore and fluid overlays (#104) --- dependencies.gradle | 5 +- repositories.gradle | 4 + .../sinthoras/visualprospecting/Config.java | 9 + .../visualprospecting/hooks/HooksClient.java | 21 +++ .../model/layers/OreVeinLayerManager.java | 32 ++-- .../layers/UndergroundFluidLayerManager.java | 34 ++-- .../model/render/OreVeinMapMarker.java | 164 ++++++++++++++++++ .../model/render/OreVeinRenderStep.java | 14 +- .../render/UndergroundFluidImageOverlay.java | 78 +++++++++ .../render/UndergroundFluidRenderStep.java | 56 ++++-- .../textures/node_marked.png | Bin 998 -> 202 bytes 11 files changed, 377 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java create mode 100644 src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidImageOverlay.java diff --git a/dependencies.gradle b/dependencies.gradle index 58b50f68..8623f1c5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,10 +1,11 @@ dependencies { - api('com.github.GTNewHorizons:Navigator:1.1.4:dev') + api('com.github.GTNewHorizons:Navigator:1.1.8:dev') api('com.github.GTNewHorizons:GTNHLib:0.11.23:dev') api('com.github.GTNewHorizons:GT5-Unofficial:5.09.54.29:dev') api('com.github.GTNewHorizons:NotEnoughItems:2.8.110-GTNH:dev') + compileOnly('info.journeymap:journeymap-api-forge:1.7.10-2.0.0') compileOnlyApi('com.github.GTNewHorizons:Galacticraft:3.4.31-GTNH:dev') { transitive = false } - runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.18')) + runtimeOnlyNonPublishable(rfg.deobf('maven.modrinth:journeymap:5.2.20')) } diff --git a/repositories.gradle b/repositories.gradle index 9fbd7d4a..1e870960 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,2 +1,6 @@ repositories { + maven { + name = "JourneyMap" + url = "https://maven.blamejared.com" + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index c0dee5ab..513e475b 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -20,6 +20,7 @@ private static class Defaults { public static final int uploadBandwidthBytes = 2000000; public static final int maxTransferCacheSizeMB = 50; public static final boolean enableVoxelMapWaypointsByDefault = false; + public static final boolean showOreLabelsOnJourneyMap6Minimap = true; public static final int maxRegionRowFileMBForInMemoryScan = 10000; } @@ -43,6 +44,7 @@ private static class Categories { public static int uploadPacketsPerSecond = uploadBandwidthBytes / VP.uploadSizePerPacketInBytes; public static int maxTransferCacheSizeMB = Defaults.maxTransferCacheSizeMB; public static boolean enableVoxelMapWaypointsByDefault = Defaults.enableVoxelMapWaypointsByDefault; + public static boolean showOreLabelsOnJourneyMap6Minimap = Defaults.showOreLabelsOnJourneyMap6Minimap; public static int maxRegionRowFileMBForInMemoryScan = Defaults.maxRegionRowFileMBForInMemoryScan; public static void syncronizeConfiguration(File configFile) { @@ -134,6 +136,13 @@ public static void syncronizeConfiguration(File configFile) { "[CLIENT / VoxelMap] Enable waypoints added by prospecting GT ore veins or underground fluids by default"); enableVoxelMapWaypointsByDefault = enableVoxelMapWaypointsByDefaultProperty.getBoolean(); + Property showOreLabelsOnJourneyMap6MinimapProperty = configuration.get( + Categories.integration, + "showOreLabelsOnJourneyMap6Minimap", + Defaults.showOreLabelsOnJourneyMap6Minimap, + "[CLIENT / JourneyMap 6] Show ore vein labels on the minimap."); + showOreLabelsOnJourneyMap6Minimap = showOreLabelsOnJourneyMap6MinimapProperty.getBoolean(); + Property maxRegionRowFileMBForInMemoryScanProperty = configuration.get( Categories.caching, "maxRegionRowFileMBForInMemoryScan", diff --git a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java index 7b9abb70..d024f6e0 100644 --- a/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java +++ b/src/main/java/com/sinthoras/visualprospecting/hooks/HooksClient.java @@ -1,5 +1,6 @@ package com.sinthoras.visualprospecting.hooks; +import net.minecraft.client.Minecraft; import net.minecraftforge.client.ClientCommandHandler; import net.minecraftforge.common.MinecraftForge; @@ -22,6 +23,7 @@ import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.event.FMLServerStoppedEvent; import cpw.mods.fml.common.event.FMLServerStoppingEvent; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; public class HooksClient extends HooksShared { @@ -86,9 +88,28 @@ public void registerMapLayers() { NavigatorApi.registerLayerManager(OreVeinLayerManager.instance); NavigatorApi.registerLayerManager(UndergroundFluidLayerManager.instance); + MinecraftForge.EVENT_BUS.register(this); if (Util.isVoxelMapInstalled()) { MinecraftForge.EVENT_BUS.register(new VoxelMapEventHandler()); } } + + @SubscribeEvent + public void onVeinProspected(ProspectingNotificationEvent.OreVein event) { + Minecraft.getMinecraft().func_152344_a( + () -> OreVeinLayerManager.instance.invalidateLocation( + event.getPosition().dimensionId, + event.getPosition().chunkX, + event.getPosition().chunkZ)); + } + + @SubscribeEvent + public void onFluidProspected(ProspectingNotificationEvent.UndergroundFluid event) { + Minecraft.getMinecraft().func_152344_a( + () -> UndergroundFluidLayerManager.instance.invalidateLocation( + event.getPosition().dimensionId, + event.getPosition().chunkX, + event.getPosition().chunkZ)); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java index 13cdb436..762002c3 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/OreVeinLayerManager.java @@ -1,5 +1,8 @@ package com.sinthoras.visualprospecting.integration.model.layers; +import java.util.ArrayList; +import java.util.Collection; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,6 +21,7 @@ import com.sinthoras.visualprospecting.database.veintypes.VeinTypeCaching; import com.sinthoras.visualprospecting.integration.model.buttons.OreVeinButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; +import com.sinthoras.visualprospecting.integration.model.render.OreVeinMapMarker; import com.sinthoras.visualprospecting.integration.model.render.OreVeinRenderStep; public class OreVeinLayerManager extends InteractableLayerManager { @@ -38,7 +42,8 @@ public void onOpenMap() { @Override protected LayerRenderer addLayerRenderer(InteractableLayerManager manager, SupportedMods mod) { return new UniversalInteractableRenderer(manager) - .withRenderStep(location -> new OreVeinRenderStep((OreVeinLocation) location)); + .withRenderStep(location -> new OreVeinRenderStep((OreVeinLocation) location)) + .withMapMarker(location -> OreVeinMapMarker.create((OreVeinLocation) location)); } @Nullable @@ -52,18 +57,21 @@ protected WaypointManager addWaypointManager(InteractableLayerManager manager, S } @Override - protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { - int oreChunkX = Utils.mapToCenterOreChunkCoord(chunkX); - int oreChunkZ = Utils.mapToCenterOreChunkCoord(chunkZ); - if (chunkX % oreChunkX != 0 || chunkZ % oreChunkZ != 0) { - return null; - } - OreVeinPosition oreVeinPosition = ClientCache.instance.getOreVein(dim, oreChunkX, oreChunkZ); - if (oreVeinPosition.veinType != VeinType.NO_VEIN) { - return new OreVeinLocation(oreVeinPosition); + protected Collection generateVisibleLocations(int minBlockX, int minBlockZ, + int maxBlockX, int maxBlockZ, int dimension) { + Collection locations = new ArrayList<>(); + for (OreVeinPosition vein : ClientCache.instance.getAllOreVeins()) { + int blockX = vein.getBlockX(); + int blockZ = vein.getBlockZ(); + if (vein.veinType != VeinType.NO_VEIN && vein.dimensionId == dimension + && blockX >= minBlockX + && blockX <= maxBlockX + && blockZ >= minBlockZ + && blockZ <= maxBlockZ) { + locations.add(new OreVeinLocation(vein)); + } } - - return null; + return locations; } @Override diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java index 0042fde6..7669e17a 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/layers/UndergroundFluidLayerManager.java @@ -15,12 +15,13 @@ import com.gtnewhorizons.navigator.api.model.layers.LayerRenderer; import com.gtnewhorizons.navigator.api.model.layers.UniversalLayerRenderer; import com.gtnewhorizons.navigator.api.model.locations.ILocationProvider; +import com.gtnewhorizons.navigator.api.util.Util; import com.sinthoras.visualprospecting.Utils; -import com.sinthoras.visualprospecting.VP; import com.sinthoras.visualprospecting.database.ClientCache; import com.sinthoras.visualprospecting.database.UndergroundFluidPosition; import com.sinthoras.visualprospecting.integration.model.buttons.UndergroundFluidButtonManager; import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; +import com.sinthoras.visualprospecting.integration.model.render.UndergroundFluidImageOverlay; import com.sinthoras.visualprospecting.integration.model.render.UndergroundFluidRenderStep; import gregtech.api.enums.UndergroundFluidNames; @@ -40,8 +41,13 @@ public UndergroundFluidLayerManager() { @Nullable @Override protected LayerRenderer addLayerRenderer(LayerManager manager, SupportedMods mod) { - return new UniversalLayerRenderer(manager) + UniversalLayerRenderer renderer = new UniversalLayerRenderer(manager) .withRenderStep(location -> new UndergroundFluidRenderStep((UndergroundFluidLocation) location)); + if (Util.isJourneyMapV6Installed()) { + renderer.withJourneyMapV6Overlays( + location -> UndergroundFluidImageOverlay.create((UndergroundFluidLocation) location)); + } + return renderer; } @Override @@ -70,17 +76,21 @@ public void updateElement(ILocationProvider location) { } @Override - protected ILocationProvider generateLocation(int chunkX, int chunkZ, int dim) { - if (chunkX % VP.undergroundFluidSizeChunkX != 0 || chunkZ % VP.undergroundFluidSizeChunkZ != 0) { - return null; - } - - UndergroundFluidPosition undergroundFluid = ClientCache.instance.getUndergroundFluid(dim, chunkX, chunkZ); - if (undergroundFluid.isProspected()) { - return new UndergroundFluidLocation(undergroundFluid); + protected List generateVisibleLocations(int minBlockX, int minBlockZ, int maxBlockX, + int maxBlockZ, int dimension) { + List locations = new ArrayList<>(); + for (UndergroundFluidPosition fluid : ClientCache.instance.getAllUndergroundFluids()) { + int blockX = fluid.getBlockX(); + int blockZ = fluid.getBlockZ(); + if (fluid.isProspected() && fluid.dimensionId == dimension + && blockX >= minBlockX + && blockX <= maxBlockX + && blockZ >= minBlockZ + && blockZ <= maxBlockZ) { + locations.add(new UndergroundFluidLocation(fluid)); + } } - - return null; + return locations; } private void computeSearch(@Nullable Pattern filterPattern) { diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java new file mode 100644 index 00000000..0fb10d4c --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinMapMarker.java @@ -0,0 +1,164 @@ +package com.sinthoras.visualprospecting.integration.model.render; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; + +import javax.annotation.Nullable; +import javax.imageio.ImageIO; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.util.IIcon; +import net.minecraft.util.ResourceLocation; + +import com.gtnewhorizons.navigator.api.model.markers.MapMarker; +import com.sinthoras.visualprospecting.Config; +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.OreVeinLocation; + +import gregtech.api.interfaces.IIconContainer; +import gregtech.api.util.client.ResourceUtils; + +public final class OreVeinMapMarker { + + private static final ResourceLocation DEPLETED = new ResourceLocation(Tags.MODID, "textures/depleted.png"); + private static final ResourceLocation MARKED = new ResourceLocation(Tags.MODID, "textures/node_marked.png"); + private static final int ICON_SIZE = 32; + private static BufferedImage depletedImage; + private static BufferedImage markedImage; + + private OreVeinMapMarker() {} + + public static @Nullable MapMarker create(OreVeinLocation location) { + BufferedImage icon = createIcon(location); + if (icon == null) return null; + + MapMarker marker = new MapMarker(icon).setDisplaySize(ICON_SIZE, ICON_SIZE).setDisplayZoomScale(1, 2, 3, 5); + if (!location.isDepleted()) { + marker.setLabel(location.getName()).setLabelColor(location.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F) + .setLabelScale(1.2F).setLabelZoomScale(1, 2.5, Math.min(Config.minZoomLevelForOreLabel, 4), 5) + .setLabelOffsetY(28).setLabelBackgroundOpacity(0.35F) + .setLabelMinZoom(Config.minZoomLevelForOreLabel) + .setLabelOnMinimap(Config.showOreLabelsOnJourneyMap6Minimap); + } + return marker; + } + + private static @Nullable BufferedImage createIcon(OreVeinLocation location) { + BufferedImage background = spriteImage( + DimensionStoneBackground.getBackgroundIcon(location.getDimensionId()), + 0xFFFFFF); + IIconContainer ore = location.getIconFromPrimaryOre(); + BufferedImage oreImage = spriteImage(ore.getIcon(), location.getColor()); + if (background == null || oreImage == null) return null; + + BufferedImage image = new BufferedImage(ICON_SIZE, ICON_SIZE, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = image.createGraphics(); + try { + graphics.setRenderingHint( + RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); + draw(graphics, background); + draw(graphics, oreImage); + BufferedImage overlay = spriteImage(ore.getOverlayIcon(), 0xFFFFFF); + if (overlay != null) draw(graphics, overlay); + if (!location.drawSearchHighlight() || location.isDepleted()) { + graphics.setComposite(AlphaComposite.SrcOver); + graphics.setColor(new Color(0, 0, 0, 150)); + graphics.fillRect(0, 0, ICON_SIZE, ICON_SIZE); + } + if (location.isDepleted()) draw(graphics, getDepletedImage()); + if (location.isActiveAsWaypoint()) draw(graphics, getMarkedImage()); + } finally { + graphics.dispose(); + } + return image; + } + + private static void draw(Graphics2D graphics, @Nullable BufferedImage image) { + if (image != null) graphics.drawImage(image, 0, 0, ICON_SIZE, ICON_SIZE, null); + } + + private static @Nullable BufferedImage spriteImage(@Nullable IIcon icon, int tint) { + if (icon == null) return null; + BufferedImage source = loadSprite(icon); + if (source == null) source = atlasSpriteImage(icon); + if (source == null) return null; + + int red = tint >> 16 & 0xFF; + int green = tint >> 8 & 0xFF; + int blue = tint & 0xFF; + int width = source.getWidth(); + int height = source.getHeight(); + int[] pixels = source.getRGB(0, 0, width, height, null, 0, width); + for (int i = 0; i < pixels.length; i++) { + int pixel = pixels[i]; + pixels[i] = pixel & 0xFF000000 | (pixel >> 16 & 0xFF) * red / 255 << 16 + | (pixel >> 8 & 0xFF) * green / 255 << 8 + | (pixel & 0xFF) * blue / 255; + } + + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + image.setRGB(0, 0, width, height, pixels, 0, width); + return image; + } + + private static @Nullable BufferedImage loadSprite(IIcon icon) { + ResourceLocation location = ResourceUtils.getCompleteBlockTextureResourceLocation(icon.getIconName()); + try (InputStream stream = Minecraft.getMinecraft().getResourceManager().getResource(location) + .getInputStream()) { + BufferedImage image = ImageIO.read(stream); + if (image == null) return null; + int frameHeight = Math.min(image.getWidth(), image.getHeight()); + return image.getSubimage(0, 0, image.getWidth(), frameHeight); + } catch (IOException ignored) { + return null; + } + } + + private static @Nullable BufferedImage atlasSpriteImage(IIcon icon) { + if (!(icon instanceof TextureAtlasSprite sprite) || sprite.getFrameCount() == 0) return null; + + int sourceWidth = sprite.getIconWidth(); + int sourceHeight = sprite.getIconHeight(); + int[][] frame = sprite.getFrameTextureData(0); + if (frame.length == 0 || frame[0] == null || frame[0].length < sourceWidth * sourceHeight) return null; + + // The atlas location is irrelevant here; reuse MapMarker's normalized sprite region to exclude padding. + MapMarker spriteRegion = new MapMarker(TextureMap.locationBlocksTexture, sprite); + int width = spriteRegion.getTextureWidth(); + int height = spriteRegion.getTextureHeight(); + int offsetX = spriteRegion.getTextureX() - sprite.getOriginX(); + int offsetY = spriteRegion.getTextureY() - sprite.getOriginY(); + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + image.setRGB(0, 0, width, height, frame[0], offsetY * sourceWidth + offsetX, sourceWidth); + return image; + } + + private static @Nullable BufferedImage getDepletedImage() { + if (depletedImage == null) depletedImage = load(DEPLETED); + return depletedImage; + } + + private static @Nullable BufferedImage getMarkedImage() { + if (markedImage == null) markedImage = load(MARKED); + return markedImage; + } + + private static @Nullable BufferedImage load(ResourceLocation location) { + try (InputStream stream = Minecraft.getMinecraft().getResourceManager().getResource(location) + .getInputStream()) { + return ImageIO.read(stream); + } catch (IOException e) { + VP.LOG.error("Could not load map marker image " + location, e); + return null; + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java index 8f88c8ea..56b940e2 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/OreVeinRenderStep.java @@ -36,7 +36,7 @@ public OreVeinRenderStep(OreVeinLocation location) { @Override public void preRender(double topX, double topY, float drawScale, double zoom) { - double iconSize = isXaero ? 10 * zoom : 32 * drawScale; + double iconSize = isXaero ? 10 * zoom : 32 * drawScale * getZoomScale(1, 2, 3, 5); setSize(iconSize); setOffset(-iconSize / 2); } @@ -49,22 +49,23 @@ public void draw(double topX, double topY, float drawScale, double zoom) { final double scale = 1.0; final double screenW = mc.displayWidth * scale; final double screenH = mc.displayHeight * scale; - final double topMargin = (fontHeight + 5) * getFontScale() * scale; + final double topMargin = (fontHeight + 5) * getLabelScale() * scale; if (topX + width < 0 || topX > screenW || topY + height < -topMargin || topY > screenH) { return; } } if (zoom >= Config.minZoomLevelForOreLabel && !location.isDepleted()) { + final double labelScale = getLabelScale(); final int fontColor = location.drawSearchHighlight() ? 0xFFFFFF : 0x7F7F7F; DrawUtils.drawLabel( location.getName(), topX + width / 2, - topY - fontHeight - 5, + topY - (fontHeight + 5) * (isXaero ? 1 : labelScale), fontColor, 0, true, - getFontScale()); + labelScale); } final IIcon blockIcon = DimensionStoneBackground.getBackgroundIcon(location.getDimensionId()); @@ -140,4 +141,9 @@ public boolean onKeyPressed(int keyCode) { private void playClickSound() { Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(clickSound, 1.0F)); } + + private double getLabelScale() { + return isXaero ? getFontScale() + : getFontScale() * getZoomScale(1.2, 3, Math.min(Config.minZoomLevelForOreLabel, 4), 5); + } } diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidImageOverlay.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidImageOverlay.java new file mode 100644 index 00000000..3946be2a --- /dev/null +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidImageOverlay.java @@ -0,0 +1,78 @@ +package com.sinthoras.visualprospecting.integration.model.render; + +import java.awt.image.BufferedImage; +import java.util.Collection; +import java.util.Collections; + +import com.sinthoras.visualprospecting.Tags; +import com.sinthoras.visualprospecting.VP; +import com.sinthoras.visualprospecting.integration.model.locations.UndergroundFluidLocation; + +import journeymap.api.v2.client.display.ImageOverlay; +import journeymap.api.v2.client.model.MapImage; +import journeymap.api.v2.common.Context; +import journeymap.api.v2.common.util.BlockPos; + +public final class UndergroundFluidImageOverlay { + + private static final int CELL_PIXELS = 8; + + private UndergroundFluidImageOverlay() {} + + public static Collection create(UndergroundFluidLocation location) { + BufferedImage image = new BufferedImage( + VP.undergroundFluidSizeChunkX * CELL_PIXELS, + VP.undergroundFluidSizeChunkZ * CELL_PIXELS, + BufferedImage.TYPE_INT_ARGB); + if (location.isActive()) { + int min = location.getMinProduction(); + int max = location.getMaxProduction(); + float range = max - min + 1; + for (int x = 0; x < VP.undergroundFluidSizeChunkX; x++) { + for (int z = 0; z < VP.undergroundFluidSizeChunkZ; z++) { + int amount = location.getChunks()[x][z]; + if (amount <= 0) continue; + int alpha = range > 1 ? (int) ((amount - min) / range * 255) : 10; + fillCell(image, x, z, alpha << 24 | location.getColor()); + } + } + } + drawBorder( + image, + (location.getMaxProduction() > 0 ? location.getColor() : 0xFFFFFF) + | (location.isActive() && location.getMaxProduction() > 0 ? 0xFF : 74) << 24); + + int x = (int) Math.floor(location.getBlockX()); + int z = (int) Math.floor(location.getBlockZ()); + int width = VP.undergroundFluidSizeChunkX * VP.chunkWidth; + int height = VP.undergroundFluidSizeChunkZ * VP.chunkWidth; + MapImage mapImage = new MapImage(image).setBlur(false); + ImageOverlay overlay = new ImageOverlay( + Tags.MODID, + new BlockPos(x, 64, z), + new BlockPos(x + width, 64, z + height), + mapImage); + overlay.setDimension(location.getDimensionId()).setOverlayGroupName(UndergroundFluidLocation.class.getName()) + .setActiveUIs(Context.UI.Minimap); + return Collections.singletonList(overlay); + } + + private static void fillCell(BufferedImage image, int cellX, int cellZ, int argb) { + for (int x = cellX * CELL_PIXELS; x < (cellX + 1) * CELL_PIXELS; x++) { + for (int z = cellZ * CELL_PIXELS; z < (cellZ + 1) * CELL_PIXELS; z++) { + image.setRGB(x, z, argb); + } + } + } + + private static void drawBorder(BufferedImage image, int argb) { + for (int x = 0; x < image.getWidth(); x++) { + image.setRGB(x, 0, argb); + image.setRGB(x, image.getHeight() - 1, argb); + } + for (int z = 0; z < image.getHeight(); z++) { + image.setRGB(0, z, argb); + image.setRGB(image.getWidth() - 1, z, argb); + } + } +} diff --git a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java index 963a4a2a..2229037c 100644 --- a/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java +++ b/src/main/java/com/sinthoras/visualprospecting/integration/model/render/UndergroundFluidRenderStep.java @@ -20,6 +20,11 @@ public UndergroundFluidRenderStep(UndergroundFluidLocation location) { setFontScale(0.5f); } + @Override + public void preRender(double topX, double topY, float drawScale, double zoom) { + setOffset(isJourneyMap ? -blockSize / 2 : 0); + } + @Override public void draw(double topX, double topY, float drawScale, double zoom) { final Minecraft mc = Minecraft.getMinecraft(); @@ -42,14 +47,15 @@ public void draw(double topX, double topY, float drawScale, double zoom) { DrawUtils.drawHollowRect(topX, topY, getAdjustedWidth(), getAdjustedHeight(), 0xFFFFFF, 74, 2); } - if (!isMinimap()) { - String label = I18n.format("visualprospecting.empty"); + if (!isMinimap() && getZoomStep() >= Config.minZoomLevelForUndergroundFluidDetails - 3) { + String title = I18n.format("visualprospecting.empty"); + String values = null; if (maxAmountInField > 0) { - label = MessageFormat.format( - "{0}-{1} L/Op {2}", + title = location.getFluid().getLocalizedName(); + values = MessageFormat.format( + "{0}-{1} L/Op", formatAmount(location.getMinProduction()), - formatAmount(maxAmountInField), - location.getFluid().getLocalizedName()); + formatAmount(maxAmountInField)); } int textColor = 0xFFFFFFFF; @@ -57,14 +63,25 @@ public void draw(double topX, double topY, float drawScale, double zoom) { textColor = location.isActive() ? 0xFFFF00 : 0x444444; } + final double labelScale = getMainLabelScale(); DrawUtils.drawLabel( - label, + title, topX + getAdjustedWidth() / 2, topY + 1.5, textColor, 0xB4000000, true, - getFontScale()); + labelScale); + if (values != null) { + DrawUtils.drawLabel( + values, + topX + getAdjustedWidth() / 2, + topY + 1.5 + (mc.fontRenderer.FONT_HEIGHT + 2) * labelScale, + textColor, + 0xB4000000, + true, + labelScale); + } } } @@ -84,6 +101,14 @@ private void renderChunks(double x, double y) { final boolean highlightPeak = maxProduction >= 10; final Minecraft mc = Minecraft.getMinecraft(); + final double cellLabelScale = getCellLabelScale(); + final double cellLabelOffsetY = isXaero ? 0 + : (mc.fontRenderer.FONT_HEIGHT + 2) * cellLabelScale + * getZoomScale( + 1, + 0, + Config.minZoomLevelForUndergroundFluidDetails, + Config.minZoomLevelForUndergroundFluidDetails + 1); final double screenW = mc.displayWidth; final double screenH = mc.displayHeight; setSize(VP.chunkWidth); @@ -108,11 +133,11 @@ private void renderChunks(double x, double y) { DrawUtils.drawLabel( MessageFormat.format("{0} L/Op", formatAmount(amount)), cellX + cellW / 2, - cellY + cellH / 2, + cellY + cellH / 2 + cellLabelOffsetY, 0xFFFFFFFF, 0xB4000000, true, - getFontScale()); + cellLabelScale); } } } @@ -128,4 +153,15 @@ private String formatAmount(int amount) { } return (roundedTenths / 10) + "." + (roundedTenths % 10) + "k"; } + + private double getCellLabelScale() { + return isXaero ? getFontScale() * 0.7 + : getFontScale() * getZoomScale(1.2, 3, Math.min(Config.minZoomLevelForUndergroundFluidDetails, 4), 5); + } + + private double getMainLabelScale() { + return isXaero ? getFontScale() + : getFontScale() + * getZoomScale(1, 4.5, Math.min(Config.minZoomLevelForUndergroundFluidDetails - 3, 4), 5); + } } diff --git a/src/main/resources/assets/visualprospecting/textures/node_marked.png b/src/main/resources/assets/visualprospecting/textures/node_marked.png index 2f2e7cd2db1347f85a22c41bff271e827caf77d2..0eed536bb87a3e16ef88e7a2e9ad14b9e82be775 100644 GIT binary patch delta 175 zcmaFHeu{B|ay`RDPZ!6Kh{JDZI`TCr@UVQ(tQD$1+K@l-NY#PnuJFl1?MoC{`A(;8 zntrPL&g-R0-=-Vi)w_QDaYpUbZ2PPE-IKy2Pj4!y4%}sZr#^{m*Pc^sDp7no7W+Al zJ@jYwKU&b3C^2tNVv$7q$wY~^M47fk3AOgb8BkiHO`{Mf`Xk-)j=Q(mrnZgOT}>cSOjiH^ delta 977 zcmV;?11|i^0pEX>4Tx04R}tkv&MmKpe$iQ>9WW4tA*G zkfAzR5EXHhDi*;)X)CnqU~=gfG-*guTpR`0f`cE6RRs^dzd7t}p^eY9E0X~st?f%Ws@Z4huXp zY-H2(#9?Bw)Wvcav$CNQPZLKKRik_%=d!|ii?dp-v-Umt3qu8MCBt=^BS>HgNu(e` zMjaJYVIfAVMt_QlH0{Sd{KJkvMJ}0K6)&@IM1rTE|~&0<)i_H#%DM2pHG~F0MP8ya!zF0FftMG9*Xx(-ewD z;QfrgDGvL%6xAs0xAAl@%wR{5{90Fq{%3k+)cYj}ZZ~vZY_xA&OU~;OEB5(`< z000SaNLh0L04^f{04^f|c%?sf00007bV*G`2jvPG3?B-~X+FUK000?uMObu0Z*6U5 zZgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}00006VoOIv00000008+zyMF)x0lrB@K~z}7 z)tRl1!+$Ug$E~uFN_~>jYOG*vU@9x=3-mpvp-JV(S2Wm17&tuXveSW}49Z)A!g?gYG)SJ{$Uqxfuu|6!_&}o7yQ7_b|r(X1J zvIJ;`x($HrQfn)l19XeJP6*1?+TKnDo1Iy##O_4~qi$;!n4~pk{rSyuuHH00000NkvXXu0mjf*z~78 From 0221c742f545bf9778c6b78b147e7c5e71ef7a24 Mon Sep 17 00:00:00 2001 From: Algent Date: Tue, 11 Aug 2026 11:35:32 +0200 Subject: [PATCH 131/132] Improve Undergroundfluid icon (#105) --- .../textures/icons/undergroundfluid.png | Bin 1027 -> 721 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/resources/assets/visualprospecting/textures/icons/undergroundfluid.png b/src/main/resources/assets/visualprospecting/textures/icons/undergroundfluid.png index cff4db272ef693fadbbb9c52857b4407b0c5199c..b6756852b21f00937af1f4447656deb9dfad65c6 100644 GIT binary patch delta 321 zcmV-H0lxl&2+;+QBnW+JLqkw$V`H&2dI5h{0b_Fj000SaNLh0L04^f{04^f|c%?sf z0002`NkltbU6&u@!D*cD1Sur*wY#M>jSxZz zA&vo{L!wrJ2w=jCxkiBtN~Rhm3TiK-dL+ErrxpNk0x+cOfNi*X!34J9BYiLAneu<& zTP4Lf^M%0P^Gv}#;?8QdOu?_8)c4P3A3$qz-cnt6S$&Vp0t@$LXR!^MJr@}TCIGV+ zE`{#%GNWCAy-)xeIssGvtr@FAAm4okPXIumEupP*%*Hq2T#EqGD!g6O3z*Q$L2hOj zfFodgV5AXnzQDy!1e&wCOAh7ydc;xI)EATB65JCtcg!nTaLqayN T(YoK400000NkvXXu0mjf82*R- delta 629 zcmV-*0*d|71%n8XBoKvZLqkwWLqi~Na&Km7Y-O=5dI5hmPIAEj000SaNLh0L04^f{ z04^f|c%?sf00007bV*G`2jvP26FD-^-+m$h000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_C zX>@2HM@dakSAh-}00006VoOIv00000008+zyMF)x0oqAKK~!ko?bkhP6j2n$@q7S3 zft8=Z#>Riz&Q1^!K}1q)lWMVug@sKBf{0B*P$H28Qv?YrDENwnV50b1m?DaXh)Gmp z5_g-Q%~=?RS(g;Lci=v7*mLLHyFCAy`!X{ykd>8{m6esXJ7J{G=7-S27MgVgI1~V# z7_1}2{Q|&79RV7pr!Z3|^LI<;Ti8l@zBeMjT{3_DBo=a~J(QaHv)IJvvhhNnYspR{ ztYA3u4J_b5MZcc`a4Qw#v)Bn!Z!nJSzx2Ntedqga{6=X`zr=6+z-W)L&-=CpFkLeK z3P*7ezc7i}9{(}ZFZ16D#^2$1p*9?M_B57K1sKN?PF2+AF&23{Re(lkr>UrY!imV2 zaWa3^CotWm)+*$4m`DmBPT4yVjZ$q8tA+L`7E%N_7f}Y7j4kwhw7>Q^3z7qPjSE=E zGmJ%kxGn%Y*pI0=$oAq;KPxby?yeFa&-m#BS@ccWvaF(0svGbsS9R{*r5*1}xH zm^}e-GX;Ql1wadn@p~1QD`Ghoc=`HUT>qZ{oBtvPva+(Wva+(WvUa6ETmame^vfN) P00000NkvXXu0mjfYL*MN From 12482c0274f07f27c6db7f2bbb556a6b37e5619b Mon Sep 17 00:00:00 2001 From: DylanTaylor1 <89085119+DylanTaylor1@users.noreply.github.com> Date: Sun, 6 Sep 2026 21:36:01 +0200 Subject: [PATCH 132/132] Update Default Minimum Zoom Levels --- src/main/java/com/sinthoras/visualprospecting/Config.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/sinthoras/visualprospecting/Config.java b/src/main/java/com/sinthoras/visualprospecting/Config.java index 513e475b..679c0a2e 100644 --- a/src/main/java/com/sinthoras/visualprospecting/Config.java +++ b/src/main/java/com/sinthoras/visualprospecting/Config.java @@ -15,8 +15,8 @@ private static class Defaults { public static final int cacheGenerationLogUpdateMinTime = 5; public static final boolean recacheVeins = false; public static final int minDelayBetweenVeinRequests = 2000; - public static final int minZoomLevelForOreLabel = 2; - public static final int minZoomLevelForUndergroundFluidDetails = 3; + public static final int minZoomLevelForOreLabel = 1; + public static final int minZoomLevelForUndergroundFluidDetails = 2; public static final int uploadBandwidthBytes = 2000000; public static final int maxTransferCacheSizeMB = 50; public static final boolean enableVoxelMapWaypointsByDefault = false;

d6*HZS!zoZsl`mF4!ol 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℘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%0Dq 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

C>CpE|DRP-U1g1)%n*8hOC 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