mirror of
https://github.com/GTNewHorizons/StructureLib.git
synced 2026-11-09 15:04:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27bb7b2ad9 | ||
|
|
b9af0ef491 | ||
|
|
7f19399ba3 | ||
|
|
4982bb780d | ||
|
|
a069612e04 | ||
|
|
ab09b791bd | ||
|
|
b086a65828 | ||
|
|
f1f6dae00f | ||
|
|
68c5436496 | ||
|
|
c4eb372cfb | ||
|
|
2446ad2db7 | ||
|
|
906961b6c8 | ||
|
|
393045d4f2 | ||
|
|
74baa66f52 | ||
|
|
24928454fd | ||
|
|
34ceda8ccc | ||
|
|
c78c61f45e | ||
|
|
fbf8cfd82c | ||
|
|
4c42e5f2a2 |
No files matched your search
@@ -0,0 +1,9 @@
|
||||
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
|
||||
@@ -0,0 +1,45 @@
|
||||
# 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
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master, main ]
|
||||
push:
|
||||
branches: [ master, main ]
|
||||
|
||||
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 10 ./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
|
||||
@@ -0,0 +1,45 @@
|
||||
# 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:
|
||||
- '*'
|
||||
|
||||
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
|
||||
|
||||
- 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
|
||||
+27
-19
@@ -1,20 +1,28 @@
|
||||
*.class
|
||||
*.log
|
||||
*.ctxt
|
||||
.mtj.tmp/
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
hs_err_pid*
|
||||
.gradle
|
||||
**/build/
|
||||
!src/**/build/
|
||||
gradle-app.setting
|
||||
!gradle-wrapper.jar
|
||||
.gradletasknamecache
|
||||
.idea/
|
||||
run/
|
||||
.settings
|
||||
/.idea/
|
||||
/run/
|
||||
/build/
|
||||
/eclipse/
|
||||
.classpath
|
||||
.project
|
||||
/bin/
|
||||
/config/
|
||||
/crash-reports/
|
||||
/logs/
|
||||
options.txt
|
||||
/saves/
|
||||
usernamecache.json
|
||||
banned-ips.json
|
||||
banned-players.json
|
||||
eula.txt
|
||||
ops.json
|
||||
server.properties
|
||||
servers.dat
|
||||
usercache.json
|
||||
whitelist.json
|
||||
/out/
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
src/main/resources/mixins.*.json
|
||||
+493
-41
@@ -1,65 +1,517 @@
|
||||
//version: ffe7b130f98fdfa1ac7c6ba4bd34722a55ab28d4
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "https://files.minecraftforge.net/maven"
|
||||
url = "https://maven.minecraftforge.net"
|
||||
}
|
||||
maven {
|
||||
name = "sonatype"
|
||||
url = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
}
|
||||
maven {
|
||||
name = "Scala CI dependencies"
|
||||
url = "https://repo1.maven.org/maven2/"
|
||||
}
|
||||
maven {
|
||||
name = "jitpack"
|
||||
url = "https://jitpack.io"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.1'
|
||||
classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.4'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'idea'
|
||||
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")
|
||||
}
|
||||
|
||||
apply plugin: 'forge'
|
||||
|
||||
version = modVersion
|
||||
group= modGroup
|
||||
archivesBaseName = modBaseName
|
||||
def projectJavaVersion = JavaLanguageVersion.of(8)
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
minecraft {
|
||||
version = project.forgeVersion
|
||||
replaceIn "StructureLib.java"
|
||||
replace '${version}', project.version
|
||||
runDir = "run"
|
||||
}
|
||||
|
||||
processResources
|
||||
{
|
||||
inputs.property "version", project.version
|
||||
inputs.property "mcversion", project.minecraft.version
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include 'mcmod.info'
|
||||
expand 'version': project.version, 'mcversion': project.minecraft.version
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(projectJavaVersion)
|
||||
}
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
task deobfJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
classifier = 'deobf'
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives deobfJar
|
||||
archives jar
|
||||
}
|
||||
|
||||
idea {
|
||||
module {
|
||||
inheritOutputDirs = false
|
||||
outputDir = new File(compileJava.destinationDir.parentFile.parentFile, "idea")
|
||||
testOutputDir = new File(compileTestJava.destinationDir.parentFile.parentFile, "ideaTest")
|
||||
inheritOutputDirs = true
|
||||
downloadJavadoc = true
|
||||
downloadSources = true
|
||||
}
|
||||
}
|
||||
|
||||
if(JavaVersion.current() != JavaVersion.VERSION_1_8) {
|
||||
throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current())
|
||||
}
|
||||
|
||||
checkPropertyExists("modName")
|
||||
checkPropertyExists("modId")
|
||||
checkPropertyExists("modGroup")
|
||||
checkPropertyExists("autoUpdateBuildScript")
|
||||
checkPropertyExists("minecraftVersion")
|
||||
checkPropertyExists("forgeVersion")
|
||||
checkPropertyExists("replaceGradleTokenInFile")
|
||||
checkPropertyExists("gradleTokenModId")
|
||||
checkPropertyExists("gradleTokenModName")
|
||||
checkPropertyExists("gradleTokenVersion")
|
||||
checkPropertyExists("gradleTokenGroupName")
|
||||
checkPropertyExists("apiPackage")
|
||||
checkPropertyExists("accessTransformersFile")
|
||||
checkPropertyExists("usesMixins")
|
||||
checkPropertyExists("mixinPlugin")
|
||||
checkPropertyExists("mixinsPackage")
|
||||
checkPropertyExists("coreModClass")
|
||||
checkPropertyExists("containsMixinsAndOrCoreModOnly")
|
||||
checkPropertyExists("usesShadowedDependencies")
|
||||
checkPropertyExists("developmentEnvironmentUserName")
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String javaSourceDir = "src/main/java/"
|
||||
String scalaSourceDir = "src/main/scala/"
|
||||
|
||||
String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/")
|
||||
if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) {
|
||||
throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala)
|
||||
}
|
||||
|
||||
if(apiPackage) {
|
||||
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
|
||||
if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) {
|
||||
throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala)
|
||||
}
|
||||
}
|
||||
|
||||
if(accessTransformersFile) {
|
||||
String targetFile = "src/main/resources/META-INF/" + accessTransformersFile
|
||||
if(new File(targetFile).exists() == false) {
|
||||
throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile)
|
||||
}
|
||||
}
|
||||
|
||||
if(usesMixins.toBoolean()) {
|
||||
if(mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) {
|
||||
throw new GradleException("\"mixinPlugin\" requires \"mixinsPackage\" and \"mixinPlugin\" to be set!")
|
||||
}
|
||||
|
||||
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
|
||||
if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) {
|
||||
throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala)
|
||||
}
|
||||
|
||||
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((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) {
|
||||
throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava)
|
||||
}
|
||||
}
|
||||
|
||||
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((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) {
|
||||
throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava)
|
||||
}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS)
|
||||
|
||||
// Make sure GregTech build won't time out
|
||||
System.setProperty("org.gradle.internal.http.connectionTimeout", 120000 as String)
|
||||
System.setProperty("org.gradle.internal.http.socketTimeout", 120000 as String)
|
||||
}
|
||||
|
||||
// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version
|
||||
'git config core.fileMode false'.execute()
|
||||
// Pulls version from git tag
|
||||
try {
|
||||
version = minecraftVersion + "-" + gitVersion()
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!");
|
||||
}
|
||||
group = modGroup
|
||||
archivesBaseName = modId
|
||||
|
||||
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, versionDetails().lastTag
|
||||
}
|
||||
if(gradleTokenGroupName) {
|
||||
replace gradleTokenGroupName, modGroup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(file("addon.gradle").exists()) {
|
||||
apply from: "addon.gradle"
|
||||
}
|
||||
|
||||
apply from: 'repositories.gradle'
|
||||
|
||||
configurations {
|
||||
implementation.extendsFrom(shadowImplementation)
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = "Overmind forge repo mirror"
|
||||
url = "https://gregtech.overminddl1.com/"
|
||||
}
|
||||
if(usesMixins.toBoolean()) {
|
||||
maven {
|
||||
name = "sponge"
|
||||
url = "https://repo.spongepowered.org/repository/maven-public"
|
||||
}
|
||||
maven {
|
||||
url = "https://jitpack.io"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
if(usesMixins.toBoolean()) {
|
||||
annotationProcessor("org.ow2.asm:asm-debug-all:5.0.3")
|
||||
annotationProcessor("com.google.guava:guava:24.1.1-jre")
|
||||
annotationProcessor("com.google.code.gson:gson:2.8.6")
|
||||
annotationProcessor("org.spongepowered:mixin:0.8-SNAPSHOT")
|
||||
// using 0.8 to workaround a issue in 0.7 which fails mixin application
|
||||
compile("org.spongepowered:mixin:0.7.11-SNAPSHOT") {
|
||||
// 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.3.3:dev")
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
new File(projectDir.toString() + "/src/main/resources/", "mixins." + modId + ".json").text = """{
|
||||
"required": true,
|
||||
"minVersion": "0.7.11",
|
||||
"package": "${modGroup}.${mixinsPackage}",
|
||||
"plugin": "${modGroup}.${mixinPlugin}",
|
||||
"refmap": "${mixingConfigRefMap}",
|
||||
"target": "@env(DEFAULT)",
|
||||
"compatibilityLevel": "JAVA_8"
|
||||
}
|
||||
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
task relocateShadowJar(type: ConfigureShadowRelocation) {
|
||||
target = tasks.shadowJar
|
||||
prefix = modGroup + ".shadow"
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
minimize() // This will only allow shading for actually used classes
|
||||
configurations = [project.configurations.shadowImplementation]
|
||||
dependsOn(relocateShadowJar)
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
if(usesShadowedDependencies.toBoolean()) {
|
||||
dependsOn(shadowJar)
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
reobf {
|
||||
if(usesMixins.toBoolean()) {
|
||||
addExtraSrgFile mixinSrg
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
if(usesMixins.toBoolean()) {
|
||||
tasks.compileJava {
|
||||
options.compilerArgs += [
|
||||
"-AreobfSrgFile=${tasks.reobf.srg}",
|
||||
"-AoutSrgFile=${mixinSrg}",
|
||||
"-AoutRefMapFile=${refMap}",
|
||||
// Elan: from what I understand they are just some linter configs so you get some warning on how to properly code
|
||||
"-XDenableSunApiLintControl",
|
||||
"-XDignore.symbol.file"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runClient {
|
||||
def arguments = []
|
||||
|
||||
if(usesMixins.toBoolean()) {
|
||||
arguments += [
|
||||
"--mods=../build/libs/$modId-${version}.jar",
|
||||
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
|
||||
]
|
||||
}
|
||||
|
||||
if(developmentEnvironmentUserName) {
|
||||
arguments += [
|
||||
"--username",
|
||||
developmentEnvironmentUserName
|
||||
]
|
||||
}
|
||||
|
||||
args(arguments)
|
||||
}
|
||||
|
||||
runServer {
|
||||
def arguments = []
|
||||
|
||||
if (usesMixins.toBoolean()) {
|
||||
arguments += [
|
||||
"--mods=../build/libs/$modId-${version}.jar",
|
||||
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
|
||||
]
|
||||
}
|
||||
|
||||
args(arguments)
|
||||
}
|
||||
|
||||
tasks.withType(JavaExec).configureEach {
|
||||
javaLauncher.set(
|
||||
javaToolchains.launcherFor {
|
||||
languageVersion = projectJavaVersion
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
processResources
|
||||
{
|
||||
// this will ensure that this task is redone when the versions change.
|
||||
inputs.property "version", project.version
|
||||
inputs.property "mcversion", project.minecraft.version
|
||||
|
||||
// replace stuff in mcmod.info, nothing else
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include 'mcmod.info'
|
||||
|
||||
// replace version and mcversion
|
||||
expand "minecraftVersion": project.minecraft.version,
|
||||
"modVersion": versionDetails().lastTag,
|
||||
"modId": modId,
|
||||
"modName": modName
|
||||
}
|
||||
|
||||
if(usesMixins.toBoolean()) {
|
||||
from refMap
|
||||
}
|
||||
|
||||
// copy everything else, thats not the mcmod.info
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude 'mcmod.info'
|
||||
}
|
||||
}
|
||||
|
||||
def getManifestAttributes() {
|
||||
def manifestAttributes = [:]
|
||||
if(containsMixinsAndOrCoreModOnly.toBoolean() == false && (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() == false
|
||||
]
|
||||
}
|
||||
return manifestAttributes
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
from (sourceSets.main.allJava)
|
||||
from (file("$projectDir/LICENSE"))
|
||||
getArchiveClassifier().set('sources')
|
||||
}
|
||||
|
||||
task shadowDevJar(type: ShadowJar) {
|
||||
from sourceSets.main.output
|
||||
getArchiveClassifier().set("dev")
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
minimize() // This will only allow shading for actually used classes
|
||||
configurations = [project.configurations.shadowImplementation]
|
||||
}
|
||||
|
||||
task relocateShadowDevJar(type: ConfigureShadowRelocation) {
|
||||
target = tasks.shadowDevJar
|
||||
prefix = modGroup + ".shadow"
|
||||
}
|
||||
|
||||
task circularResolverJar(type: Jar) {
|
||||
dependsOn(relocateShadowDevJar)
|
||||
dependsOn(shadowDevJar)
|
||||
enabled = false
|
||||
}
|
||||
|
||||
task devJar(type: Jar) {
|
||||
from sourceSets.main.output
|
||||
getArchiveClassifier().set("dev")
|
||||
|
||||
manifest {
|
||||
attributes(getManifestAttributes())
|
||||
}
|
||||
|
||||
if(usesShadowedDependencies.toBoolean()) {
|
||||
dependsOn(circularResolverJar)
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
task apiJar(type: Jar) {
|
||||
from (sourceSets.main.allJava) {
|
||||
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**'
|
||||
}
|
||||
|
||||
from (sourceSets.main.output) {
|
||||
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**'
|
||||
}
|
||||
|
||||
from (sourceSets.main.resources.srcDirs) {
|
||||
include("LICENSE")
|
||||
}
|
||||
|
||||
getArchiveClassifier().set('api')
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives sourcesJar
|
||||
archives devJar
|
||||
if(apiPackage) {
|
||||
archives apiJar
|
||||
}
|
||||
}
|
||||
|
||||
// Updating
|
||||
task updateBuildScript {
|
||||
doLast {
|
||||
if (updateBuildScript()) return
|
||||
|
||||
print("Build script already up-to-date!")
|
||||
}
|
||||
}
|
||||
|
||||
if (isNewBuildScriptVersionAvailable()) {
|
||||
if (autoUpdateBuildScript.toBoolean()) {
|
||||
updateBuildScript()
|
||||
} else {
|
||||
println("Build script update available! Run 'gradle updateBuildScript'")
|
||||
}
|
||||
}
|
||||
|
||||
static URL availableBuildScriptUrl() {
|
||||
new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle")
|
||||
}
|
||||
|
||||
static boolean updateBuildScript() {
|
||||
if (isNewBuildScriptVersionAvailable()) {
|
||||
def buildscriptFile = new File("build.gradle")
|
||||
availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } }
|
||||
print("Build script updated. Please REIMPORT the project or RESTART your IDE!")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static boolean isNewBuildScriptVersionAvailable() {
|
||||
Map parameters = ["connectTimeout": 2000, "readTimeout": 2000]
|
||||
|
||||
String currentBuildScript = new File("build.gradle").getText()
|
||||
String currentBuildScriptHash = getVersionHash(currentBuildScript)
|
||||
String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText()
|
||||
String availableBuildScriptHash = getVersionHash(availableBuildScript)
|
||||
|
||||
boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash
|
||||
return !isUpToDate
|
||||
}
|
||||
|
||||
static String getVersionHash(String buildScriptContent) {
|
||||
String versionLine = buildScriptContent.find("^//version: [a-z0-9]*")
|
||||
if(versionLine != null) {
|
||||
return versionLine.split(": ").last()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
configure(updateBuildScript) {
|
||||
group = 'forgegradle'
|
||||
description = 'Updates the build script to the latest version'
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
+59
-4
@@ -1,5 +1,60 @@
|
||||
modGroup = com.gtnewhorizon
|
||||
modVersion = 1.0.1
|
||||
modBaseName = StructureLib
|
||||
modName = StructureLib
|
||||
|
||||
forgeVersion = 1.7.10-10.13.4.1614-1.7.10
|
||||
# This is a case-sensitive string to identify your mod. Convention is to use lower case.
|
||||
modId = structurelib
|
||||
|
||||
modGroup = com.gtnewhorizon.structurelib
|
||||
|
||||
# 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/
|
||||
|
||||
# Will update your build.gradle automatically whenever an update is available
|
||||
autoUpdateBuildScript = false
|
||||
|
||||
minecraftVersion = 1.7.10
|
||||
forgeVersion = 10.13.4.1614
|
||||
|
||||
# Select a username for testing your mod with breakpoints. You may leave this empty for a random user name 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:
|
||||
# public static final String VERSION = "GRADLETOKEN_VERSION";
|
||||
# The string's content will be replaced with your mods 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 = StructureLib.java
|
||||
gradleTokenModId =
|
||||
gradleTokenModName =
|
||||
gradleTokenVersion = GRADLETOKEN_VERSION
|
||||
gradleTokenGroupName =
|
||||
|
||||
# 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
|
||||
apiPackage =
|
||||
|
||||
# Specify the configuration file for Forge's access transformers here. I must be placed into /src/main/resources/META-INF/
|
||||
# Example value: mymodid_at.cfg
|
||||
accessTransformersFile =
|
||||
|
||||
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
|
||||
usesMixins = false
|
||||
# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise.
|
||||
mixinPlugin =
|
||||
# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
|
||||
mixinsPackage =
|
||||
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
|
||||
# This parameter is for legacy compatability only
|
||||
# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin
|
||||
coreModClass =
|
||||
# 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
|
||||
|
||||
# If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your
|
||||
# responsibility check the licence and request permission for distribution, if required.
|
||||
usesShadowedDependencies = false
|
||||
Vendored
BIN
Binary file not shown.
+1
-2
@@ -1,6 +1,5 @@
|
||||
#Sat Jan 04 01:52:14 CET 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip
|
||||
@@ -1,4 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
@@ -6,47 +22,6 @@
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
@@ -61,9 +36,49 @@ while [ -h "$PRG" ] ; do
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 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
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
@@ -90,7 +105,7 @@ location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
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
|
||||
@@ -110,10 +125,11 @@ if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
# 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`
|
||||
@@ -154,11 +170,19 @@ if $cygwin ; then
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
# 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"
|
||||
|
||||
# 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
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
Vendored
+20
-10
@@ -1,3 +1,19 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@@ -8,14 +24,14 @@
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@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=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
@@ -46,10 +62,9 @@ echo location of your Java installation.
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
@@ -60,11 +75,6 @@ set _SKIP=2
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
before_install:
|
||||
- ./gradlew setupCIWorkspace
|
||||
@@ -0,0 +1,5 @@
|
||||
// Add any additional repositiroes for your dependencies here
|
||||
|
||||
repositories {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import cpw.mods.fml.client.event.ConfigChangedEvent;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.common.config.ConfigCategory;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
import net.minecraftforge.common.config.Property;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
public enum ConfigurationHandler {
|
||||
INSTANCE;
|
||||
|
||||
private Configuration config;
|
||||
private int maxCoexistingHologram;
|
||||
private boolean removeCollidingHologram;
|
||||
|
||||
ConfigurationHandler() {
|
||||
FMLCommonHandler.instance().bus().register(this);
|
||||
}
|
||||
|
||||
void init(File f) {
|
||||
config = new Configuration(f, ConfigurationVersion.latest().getVersionMarker());
|
||||
ConfigurationVersion.migrateToLatest(config);
|
||||
loadConfig();
|
||||
setLanguageKeys();
|
||||
}
|
||||
|
||||
private void setLanguageKeys() {
|
||||
for (String categoryName : config.getCategoryNames()) {
|
||||
ConfigCategory category = config.getCategory(categoryName);
|
||||
category.setLanguageKey("structurelib.config." + categoryName);
|
||||
for (Map.Entry<String, Property> entry : category.entrySet()) {
|
||||
entry.getValue().setLanguageKey(String.format("%s.%s", category.getLanguagekey(), entry.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadConfig() {
|
||||
maxCoexistingHologram = config.getInt("maxCoexisting", "client.hologram", 1, 1, 100, "An attempt will be made to prune old holograms when a new hologram is about to be projected");
|
||||
removeCollidingHologram = config.getBoolean("removeColliding", "client.hologram", true, "An attempt will be made to remove an existing hologram if it collides with a new hologram.");
|
||||
|
||||
if (config.hasChanged()) {
|
||||
config.save();
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onConfigChange(ConfigChangedEvent.PostConfigChangedEvent e) {
|
||||
if (e.modID.equals(StructureLibAPI.MOD_ID)) {
|
||||
loadConfig();
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxCoexistingHologram() {
|
||||
return maxCoexistingHologram;
|
||||
}
|
||||
|
||||
public boolean isRemoveCollidingHologram() {
|
||||
return removeCollidingHologram;
|
||||
}
|
||||
|
||||
Configuration getConfig() {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
enum ConfigurationVersion {
|
||||
V1 {
|
||||
@Override
|
||||
protected void step(Configuration c) {
|
||||
}
|
||||
};
|
||||
|
||||
private static final ConfigurationVersion[] VALUES = values();
|
||||
|
||||
private final String versionMarker;
|
||||
|
||||
ConfigurationVersion() {
|
||||
this.versionMarker = name();
|
||||
}
|
||||
|
||||
public static void migrateToLatest(Configuration c) {
|
||||
for (int i = identify(c).ordinal() + 1; i < VALUES.length; i++) {
|
||||
VALUES[i].step(c);
|
||||
}
|
||||
}
|
||||
|
||||
public static ConfigurationVersion latest() {
|
||||
return VALUES[VALUES.length - 1];
|
||||
}
|
||||
|
||||
public static ConfigurationVersion identify(Configuration c) {
|
||||
return Arrays.stream(VALUES).filter(v -> Objects.equals(c.getLoadedConfigVersion(), v.getVersionMarker())).findFirst().orElse(V1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getVersionMarker() {
|
||||
return versionMarker;
|
||||
}
|
||||
|
||||
protected abstract void step(Configuration c);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import cpw.mods.fml.client.IModGuiFactory;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class GuiFactory implements IModGuiFactory {
|
||||
@Override
|
||||
public void initialize(Minecraft minecraftInstance) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends GuiScreen> mainConfigGuiClass() {
|
||||
return GuiModConfig.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RuntimeOptionCategoryElement> runtimeGuiCategories() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import cpw.mods.fml.client.config.GuiConfig;
|
||||
import cpw.mods.fml.client.config.IConfigElement;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraftforge.common.config.ConfigElement;
|
||||
import net.minecraftforge.common.config.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class GuiModConfig extends GuiConfig {
|
||||
public GuiModConfig(GuiScreen guiScreen) {
|
||||
super(guiScreen, getConfigElements(), StructureLibAPI.MOD_ID, false, false, GuiConfig.getAbridgedConfigPath(ConfigurationHandler.INSTANCE.getConfig().toString()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static List<IConfigElement> getConfigElements() {
|
||||
final Configuration config = ConfigurationHandler.INSTANCE.getConfig();
|
||||
return config.getCategoryNames().stream()
|
||||
.filter(name -> name.indexOf('.') == -1)
|
||||
.map(name -> new ConfigElement(config.getCategory(name)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.AlignmentMessage;
|
||||
import com.gtnewhorizon.structurelib.net.AlignmentMessage;
|
||||
import com.gtnewhorizon.structurelib.block.BlockHint;
|
||||
import com.gtnewhorizon.structurelib.item.ItemBlockHint;
|
||||
import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger;
|
||||
import com.gtnewhorizon.structurelib.item.ItemFrontRotationTool;
|
||||
import com.gtnewhorizon.structurelib.proxy.CommonProxy;
|
||||
import com.gtnewhorizon.structurelib.util.XSTR;
|
||||
@@ -25,15 +26,14 @@ import org.apache.logging.log4j.Logger;
|
||||
/**
|
||||
* This class does not contain a stable API. Refrain from using this class.
|
||||
*/
|
||||
@Mod(modid = StructureLib.MOD_ID, name = "StructureLib", version = "${version}", acceptableRemoteVersions = "*")
|
||||
@Mod(modid = StructureLibAPI.MOD_ID, name = "StructureLib", version = "GRADLETOKEN_VERSION", acceptableRemoteVersions = "*", guiFactory = "com.gtnewhorizon.structurelib.GuiFactory")
|
||||
public class StructureLib {
|
||||
public static boolean DEBUG_MODE = true;
|
||||
public static boolean DEBUG_MODE = Boolean.getBoolean("structurelib.debug");
|
||||
public static Logger LOGGER = LogManager.getLogger("StructureLib");
|
||||
public static final String MOD_ID = "structurelib";
|
||||
|
||||
@SidedProxy(serverSide = "com.gtnewhorizon.structurelib.proxy.CommonProxy", clientSide = "com.gtnewhorizon.structurelib.proxy.ClientProxy")
|
||||
static CommonProxy proxy;
|
||||
static SimpleNetworkWrapper net = NetworkRegistry.INSTANCE.newSimpleChannel(MOD_ID);
|
||||
static SimpleNetworkWrapper net = NetworkRegistry.INSTANCE.newSimpleChannel(StructureLibAPI.MOD_ID);
|
||||
|
||||
static {
|
||||
net.registerMessage(AlignmentMessage.ServerHandler.class, AlignmentMessage.AlignmentQuery.class, 0, Side.SERVER);
|
||||
@@ -45,6 +45,7 @@ public class StructureLib {
|
||||
static Block blockHint;
|
||||
static Item itemBlockHint;
|
||||
static Item itemFrontRotationTool;
|
||||
static Item itemConstructableTrigger;
|
||||
public static final CreativeTabs creativeTab = new CreativeTabs("structurelib") {
|
||||
@Override
|
||||
@SideOnly(Side.CLIENT)
|
||||
@@ -55,9 +56,12 @@ public class StructureLib {
|
||||
|
||||
@Mod.EventHandler
|
||||
public void preInit(FMLPreInitializationEvent e) {
|
||||
ConfigurationHandler.INSTANCE.init(e.getSuggestedConfigurationFile());
|
||||
GameRegistry.registerBlock(blockHint = new BlockHint(), ItemBlockHint.class, "blockhint");
|
||||
itemBlockHint = ItemBlock.getItemFromBlock(StructureLibAPI.getBlockHint());
|
||||
GameRegistry.registerItem(itemFrontRotationTool = new ItemFrontRotationTool(), itemFrontRotationTool.getUnlocalizedName());
|
||||
GameRegistry.registerItem(itemConstructableTrigger = new ItemConstructableTrigger(), itemConstructableTrigger.getUnlocalizedName());
|
||||
proxy.preInit(e);
|
||||
}
|
||||
|
||||
public static void addClientSideChatMessages(String... messages) {
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
package com.gtnewhorizon.structurelib;
|
||||
|
||||
import com.gtnewhorizon.structurelib.alignment.AlignmentMessage;
|
||||
import com.gtnewhorizon.structurelib.net.AlignmentMessage;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||
import net.minecraft.block.Block;
|
||||
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.util.IIcon;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.proxy;
|
||||
|
||||
/**
|
||||
* A stable interface into the structure lib's internals. Backwards compatibility is maintained to the maximum extend possible.
|
||||
*/
|
||||
public class StructureLibAPI {
|
||||
public static final String MOD_ID = "structurelib";
|
||||
public static final int HINT_BLOCK_META_GENERIC_0 = 0;
|
||||
public static final int HINT_BLOCK_META_GENERIC_1 = 1;
|
||||
public static final int HINT_BLOCK_META_GENERIC_2 = 2;
|
||||
@@ -28,6 +35,25 @@ public class StructureLibAPI {
|
||||
public static final int HINT_BLOCK_META_AIR = 13;
|
||||
public static final int HINT_BLOCK_META_NOT_AIR = 14;
|
||||
public static final int HINT_BLOCK_META_ERROR = 15;
|
||||
|
||||
/**
|
||||
* Start a batch of hinting. All hints particles generated during one batch will be considered to belong to one hologram.
|
||||
*
|
||||
* You don't need to call this unless your constructable tool didn't call {@link com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility#handle(ItemStack, EntityPlayer, World, int, int, int, int)}
|
||||
*/
|
||||
public static void startHinting(World w) {
|
||||
proxy.startHinting(w);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start current batch of hinting. All hints particles generated during one batch will be considered to belong to one hologram.
|
||||
*
|
||||
* You don't need to call this unless your constructable tool didn't call {@link com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility#handle(ItemStack, EntityPlayer, World, int, int, int, int)}
|
||||
*/
|
||||
public static void endHinting(World w) {
|
||||
proxy.endHinting(w);
|
||||
}
|
||||
|
||||
public static void hintParticleTinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {
|
||||
proxy.hintParticleTinted(w, x, y, z, icons, RGBa);
|
||||
}
|
||||
@@ -44,22 +70,45 @@ public class StructureLibAPI {
|
||||
proxy.hintParticle(w, x, y, z, block, meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the ExtendedFacing of this tile entity.
|
||||
* The ExtendedFacing will later be set onto given tile entity via {@link com.gtnewhorizon.structurelib.alignment.IAlignment#setExtendedFacing(ExtendedFacing)}
|
||||
* upon arrival of server reply.
|
||||
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
|
||||
*/
|
||||
public static void queryAlignment(IAlignmentProvider provider) {
|
||||
StructureLib.net.sendToServer(new AlignmentMessage.AlignmentQuery(provider));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the ExtendedFacing of this Tile Entity to all players. Can be called on server side only.
|
||||
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
|
||||
*/
|
||||
public static void sendAlignment(IAlignmentProvider provider) {
|
||||
StructureLib.net.sendToAll(new AlignmentMessage.AlignmentData(provider));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the ExtendedFacing of this Tile Entity to given player. Can be called on server side only.
|
||||
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
|
||||
*/
|
||||
public static void sendAlignment(IAlignmentProvider provider, EntityPlayerMP player) {
|
||||
StructureLib.net.sendTo(new AlignmentMessage.AlignmentData(provider), player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the ExtendedFacing of this Tile Entity to all players around target point. Can be called on server side only.
|
||||
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
|
||||
*/
|
||||
public static void sendAlignment(IAlignmentProvider provider, NetworkRegistry.TargetPoint targetPoint) {
|
||||
StructureLib.net.sendToAllAround(new AlignmentMessage.AlignmentData(provider), targetPoint);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send the ExtendedFacing of this Tile Entity to all players in that dimension. Can be called on server side only.
|
||||
* @throws IllegalArgumentException if is not tile entity or provided a null alignment
|
||||
*/
|
||||
public static void sendAlignment(IAlignmentProvider provider, World dimension) {
|
||||
StructureLib.net.sendToDimension(new AlignmentMessage.AlignmentData(provider), dimension.provider.dimensionId);
|
||||
}
|
||||
@@ -71,4 +120,12 @@ public class StructureLibAPI {
|
||||
public static Item getItemBlockHint() {
|
||||
return StructureLib.itemBlockHint;
|
||||
}
|
||||
|
||||
public static boolean isDebugEnabled() {
|
||||
return StructureLib.DEBUG_MODE;
|
||||
}
|
||||
|
||||
public static void setDebugEnabled(boolean enabled) {
|
||||
StructureLib.DEBUG_MODE = enabled;
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public interface IAlignment extends IAlignmentLimits,IAlignmentProvider {
|
||||
default boolean toolSetDirection(ForgeDirection direction){
|
||||
if(direction==null || direction==ForgeDirection.UNKNOWN){
|
||||
for (int i = 0,j=getDirection().ordinal()+1, valuesLength = Direction.VALUES.length; i < valuesLength; i++) {
|
||||
if(toolSetDirection(Direction.VALUES[j%valuesLength].getForgeDirection())){
|
||||
if (toolSetDirection(Direction.VALUES[(j + i) % valuesLength].getForgeDirection())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -90,8 +90,8 @@ public interface IAlignment extends IAlignmentLimits,IAlignmentProvider {
|
||||
int flips = Flip.VALUES.length;
|
||||
int rotations = Rotation.VALUES.length;
|
||||
for (int ii = 0,jj=getFlip().ordinal(); ii < flips; ii++) {
|
||||
for (int i = 0,j=getRotation().ordinal()+1; i < rotations; i++) {
|
||||
if(checkedSetExtendedFacing(ExtendedFacing.of(getDirection(),Rotation.VALUES[j%rotations],Flip.VALUES[jj%flips]))){
|
||||
for (int i = 1, j = getRotation().ordinal(); i < rotations; i++) {
|
||||
if (checkedSetExtendedFacing(ExtendedFacing.of(getDirection(), Rotation.VALUES[(j + i) % rotations], Flip.VALUES[(jj + ii) % flips]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -112,8 +112,8 @@ public interface IAlignment extends IAlignmentLimits,IAlignmentProvider {
|
||||
|
||||
default boolean toolSetFlip(Flip flip){
|
||||
if(flip==null){
|
||||
for (int i = 0,j=getFlip().ordinal()+1, valuesLength = Flip.VALUES.length; i < valuesLength; i++) {
|
||||
if(toolSetFlip(Flip.VALUES[j%valuesLength])){
|
||||
for (int i = 1, j = getFlip().ordinal(), valuesLength = Flip.VALUES.length; i < valuesLength; i++) {
|
||||
if (checkedSetFlip(Flip.VALUES[(j + i) % valuesLength])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ public interface IAlignment extends IAlignmentLimits,IAlignmentProvider {
|
||||
default boolean toolSetExtendedFacing(ExtendedFacing extendedFacing){
|
||||
if(extendedFacing==null){
|
||||
for (int i = 0,j=getExtendedFacing().ordinal()+1, valuesLength = ExtendedFacing.VALUES.length; i < valuesLength; i++) {
|
||||
if(toolSetExtendedFacing(ExtendedFacing.VALUES[j%valuesLength])){
|
||||
if (checkedSetExtendedFacing(ExtendedFacing.VALUES[(j + i)%valuesLength])){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizon.structurelib.alignment.constructable;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignment;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
@@ -17,6 +18,13 @@ public class ConstructableUtility {
|
||||
}
|
||||
|
||||
public static boolean handle(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ, int aSide) {
|
||||
StructureLibAPI.startHinting(aWorld);
|
||||
boolean ret = handle0(aStack, aPlayer, aWorld, aX, aY, aZ, aSide);
|
||||
StructureLibAPI.endHinting(aWorld);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static boolean handle0(ItemStack aStack, EntityPlayer aPlayer, World aWorld, int aX, int aY, int aZ, int aSide) {
|
||||
TileEntity tTileEntity = aWorld.getTileEntity(aX, aY, aZ);
|
||||
if (tTileEntity == null || aPlayer instanceof FakePlayer) {
|
||||
return aPlayer instanceof EntityPlayerMP;
|
||||
|
||||
+4
@@ -14,6 +14,10 @@ import java.util.HashMap;
|
||||
public interface IMultiblockInfoContainer<T> {
|
||||
HashMap<String, IMultiblockInfoContainer<?>> MULTIBLOCK_MAP = new HashMap<>();
|
||||
|
||||
/**
|
||||
* There is no specific loading phase restriction, but you should generally not call it before the tile entity is
|
||||
* properly registered.
|
||||
*/
|
||||
static <T extends TileEntity> void registerTileClass(Class<T> clazz, IMultiblockInfoContainer<?> info) {
|
||||
MULTIBLOCK_MAP.put(clazz.getCanonicalName(), info);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* All public stuff in this package and its subpackages are considered part of the public API.
|
||||
* Backwards compatibility is maintained to the maximum extend possible.
|
||||
*/
|
||||
package com.gtnewhorizon.structurelib.alignment;
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizon.structurelib.block;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.StructureLibAPI;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.block.Block;
|
||||
@@ -26,22 +27,22 @@ public class BlockHint extends Block {
|
||||
@Override
|
||||
public void registerBlockIcons(IIconRegister aIconRegister) {
|
||||
//super.registerBlockIcons(aIconRegister);
|
||||
hint[0] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_0");
|
||||
hint[1] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_1");
|
||||
hint[2] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_2");
|
||||
hint[3] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_3");
|
||||
hint[4] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_4");
|
||||
hint[5] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_5");
|
||||
hint[6] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_6");
|
||||
hint[7] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_7");
|
||||
hint[8] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_8");
|
||||
hint[9] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_9");
|
||||
hint[10] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_10");
|
||||
hint[11] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_11");
|
||||
hint[12] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_DEFAULT");
|
||||
hint[13] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_AIR");
|
||||
hint[14] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_NOAIR");
|
||||
hint[15] = aIconRegister.registerIcon(StructureLib.MOD_ID + ":iconsets/HINT_ERROR");
|
||||
hint[0] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_0");
|
||||
hint[1] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_1");
|
||||
hint[2] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_2");
|
||||
hint[3] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_3");
|
||||
hint[4] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_4");
|
||||
hint[5] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_5");
|
||||
hint[6] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_6");
|
||||
hint[7] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_7");
|
||||
hint[8] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_8");
|
||||
hint[9] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_9");
|
||||
hint[10] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_10");
|
||||
hint[11] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_11");
|
||||
hint[12] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_DEFAULT");
|
||||
hint[13] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_AIR");
|
||||
hint[14] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_NOAIR");
|
||||
hint[15] = aIconRegister.registerIcon(StructureLibAPI.MOD_ID + ":iconsets/HINT_ERROR");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+12
-5
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizon.structurelib.entity.fx;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.proxy.ClientProxy;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.block.Block;
|
||||
@@ -12,11 +13,11 @@ import net.minecraft.world.World;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class BlockHint extends EntityFX {
|
||||
public class EntityFXBlockHint extends EntityFX {
|
||||
private IIcon[] icons;
|
||||
private short[] mRGBa = {255,255,255,0};
|
||||
|
||||
public BlockHint(World world){
|
||||
public EntityFXBlockHint(World world){
|
||||
this(world,0,0,0, Blocks.stone,0);
|
||||
}
|
||||
|
||||
@@ -28,7 +29,7 @@ public class BlockHint extends EntityFX {
|
||||
* @param z
|
||||
* @param icons DOWN, UP, NORTH, SOUTH, WEST, EAST
|
||||
*/
|
||||
public BlockHint(World world, int x, int y, int z, IIcon[] icons) {
|
||||
public EntityFXBlockHint(World world, int x, int y, int z, IIcon[] icons) {
|
||||
super(world, x + .25, y + .5, z + .25);
|
||||
particleGravity = 0;
|
||||
prevPosX = posX;
|
||||
@@ -39,7 +40,7 @@ public class BlockHint extends EntityFX {
|
||||
this.icons=icons;
|
||||
}
|
||||
|
||||
public BlockHint(World world, int x, int y, int z, Block block, int meta) {
|
||||
public EntityFXBlockHint(World world, int x, int y, int z, Block block, int meta) {
|
||||
super(world, x+.25, y+.5, z+.25);
|
||||
particleGravity = 0;
|
||||
prevPosX = posX;
|
||||
@@ -53,7 +54,7 @@ public class BlockHint extends EntityFX {
|
||||
}
|
||||
}
|
||||
|
||||
public BlockHint withColorTint(short[] coloure){
|
||||
public EntityFXBlockHint withColorTint(short[] coloure){
|
||||
this.mRGBa =coloure;
|
||||
return this;
|
||||
}
|
||||
@@ -130,4 +131,10 @@ public class BlockHint extends EntityFX {
|
||||
public boolean shouldRenderInPass(int pass) {
|
||||
return pass==2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDead() {
|
||||
super.setDead();
|
||||
ClientProxy.onHintDead(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.gtnewhorizon.structurelib.item;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.constructable.ConstructableUtility;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.StructureLibAPI.MOD_ID;
|
||||
import static net.minecraft.util.EnumChatFormatting.BLUE;
|
||||
import static net.minecraft.util.StatCollector.translateToLocal;
|
||||
|
||||
public class ItemConstructableTrigger extends Item {
|
||||
public ItemConstructableTrigger() {
|
||||
setUnlocalizedName("structurelib.constructableTrigger");
|
||||
setTextureName(MOD_ID + ":itemConstructableTrigger");
|
||||
setCreativeTab(StructureLib.creativeTab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemUseFirst(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ) {
|
||||
return ConstructableUtility.handle(stack, player, world, x, y, z, side);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void addInformation(ItemStack aStack, EntityPlayer ep, List aList, boolean boo) {
|
||||
aList.add(translateToLocal("item.structurelib.constructableTrigger.desc.0"));//Triggers Constructable Interface
|
||||
aList.add(BLUE + translateToLocal("item.structurelib.constructableTrigger.desc.1"));//Shows multiblock construction details,
|
||||
aList.add(BLUE + translateToLocal("item.structurelib.constructableTrigger.desc.2"));//just Use on a multiblock controller.
|
||||
aList.add(BLUE + translateToLocal("item.structurelib.constructableTrigger.desc.3"));//(Sneak Use in creative to build)
|
||||
aList.add(BLUE + translateToLocal("item.structurelib.constructableTrigger.desc.4"));//Quantity affects tier/mode/type
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import net.minecraft.world.World;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.MOD_ID;
|
||||
import static com.gtnewhorizon.structurelib.StructureLibAPI.MOD_ID;
|
||||
import static net.minecraft.util.StatCollector.translateToLocal;
|
||||
|
||||
public class ItemFrontRotationTool extends Item {
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
package com.gtnewhorizon.structurelib.alignment;
|
||||
package com.gtnewhorizon.structurelib.net;
|
||||
|
||||
import com.gtnewhorizon.structurelib.StructureLib;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignment;
|
||||
import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider;
|
||||
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import cpw.mods.fml.common.network.ByteBufUtils;
|
||||
import cpw.mods.fml.common.network.simpleimpl.IMessage;
|
||||
@@ -1,7 +1,12 @@
|
||||
package com.gtnewhorizon.structurelib.proxy;
|
||||
|
||||
import com.gtnewhorizon.structurelib.entity.fx.BlockHint;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.gtnewhorizon.structurelib.ConfigurationHandler;
|
||||
import com.gtnewhorizon.structurelib.entity.fx.EntityFXBlockHint;
|
||||
import com.gtnewhorizon.structurelib.entity.fx.WeightlessParticleFX;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiNewChat;
|
||||
@@ -10,57 +15,173 @@ import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.gtnewhorizon.structurelib.StructureLib.RANDOM;
|
||||
|
||||
public class ClientProxy extends CommonProxy {
|
||||
@Override
|
||||
public void hintParticleTinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {
|
||||
Minecraft.getMinecraft().effectRenderer.addEffect(new BlockHint(w, x, y, z, icons).withColorTint(RGBa));
|
||||
@Override
|
||||
public void hintParticleTinted(World w, int x, int y, int z, IIcon[] icons, short[] RGBa) {
|
||||
EntityFXBlockHint hint = new EntityFXBlockHint(w, x, y, z, icons).withColorTint(RGBa);
|
||||
Minecraft.getMinecraft().effectRenderer.addEffect(hint);
|
||||
ensureHinting();
|
||||
if (ConfigurationHandler.INSTANCE.isRemoveCollidingHologram()) {
|
||||
HintParticleInfo info = new HintParticleInfo(x, y, z, currentHints);
|
||||
EntityFXBlockHint dupe = allHints.inverse().get(info);
|
||||
if (dupe != null) {
|
||||
List<EntityFXBlockHint> owner = allHints.get(dupe).owner;
|
||||
// in case someone forget to call endHinting
|
||||
if (owner != currentHints) {
|
||||
hintOwners.remove(owner);
|
||||
owner.forEach(EntityFXBlockHint::setDead);
|
||||
owner.clear();
|
||||
}
|
||||
}
|
||||
allHints.forcePut(hint, info);
|
||||
}
|
||||
currentHints.add(hint);
|
||||
|
||||
EntityFX particle = new WeightlessParticleFX(w, x + RANDOM.nextFloat() * 0.5F, y + RANDOM.nextFloat() * 0.5F, z + RANDOM.nextFloat() * 0.5F, 0, 0, 0);
|
||||
particle.setRBGColorF(0, 0.6F * RANDOM.nextFloat(), 0.8f);
|
||||
Minecraft.getMinecraft().effectRenderer.addEffect(particle);
|
||||
}
|
||||
EntityFX particle = new WeightlessParticleFX(w, x + RANDOM.nextFloat() * 0.5F, y + RANDOM.nextFloat() * 0.5F, z + RANDOM.nextFloat() * 0.5F, 0, 0, 0);
|
||||
particle.setRBGColorF(0, 0.6F * RANDOM.nextFloat(), 0.8f);
|
||||
Minecraft.getMinecraft().effectRenderer.addEffect(particle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hintParticleTinted(World w, int x, int y, int z, Block block, int meta, short[] RGBa) {
|
||||
hintParticleTinted(w, x, y, z, createIIconFromBlock(block, meta), RGBa);
|
||||
}
|
||||
@Override
|
||||
public void hintParticleTinted(World w, int x, int y, int z, Block block, int meta, short[] RGBa) {
|
||||
hintParticleTinted(w, x, y, z, createIIconFromBlock(block, meta), RGBa);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hintParticle(World w, int x, int y, int z, IIcon[] icons) {
|
||||
hintParticleTinted(w, x, y, z, icons, new short[]{255, 255, 255, 0});
|
||||
}
|
||||
@Override
|
||||
public void hintParticle(World w, int x, int y, int z, IIcon[] icons) {
|
||||
hintParticleTinted(w, x, y, z, icons, new short[]{255, 255, 255, 0});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hintParticle(World w, int x, int y, int z, Block block, int meta) {
|
||||
hintParticleTinted(w, x, y, z, createIIconFromBlock(block, meta), new short[]{255, 255, 255, 0});
|
||||
}
|
||||
@Override
|
||||
public void hintParticle(World w, int x, int y, int z, Block block, int meta) {
|
||||
hintParticleTinted(w, x, y, z, createIIconFromBlock(block, meta), new short[]{255, 255, 255, 0});
|
||||
}
|
||||
|
||||
private static IIcon[] createIIconFromBlock(Block block, int meta) {
|
||||
IIcon[] ret = new IIcon[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
block.getIcon(i, meta);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private static IIcon[] createIIconFromBlock(Block block, int meta) {
|
||||
IIcon[] ret = new IIcon[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
ret[i] = block.getIcon(i, meta);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addClientSideChatMessages(String... messages) {
|
||||
GuiNewChat chat = Minecraft.getMinecraft().ingameGUI.getChatGUI();
|
||||
for (String s : messages) {
|
||||
chat.printChatMessage(new ChatComponentText(s));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void addClientSideChatMessages(String... messages) {
|
||||
GuiNewChat chat = Minecraft.getMinecraft().ingameGUI.getChatGUI();
|
||||
for (String s : messages) {
|
||||
chat.printChatMessage(new ChatComponentText(s));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityPlayer getCurrentPlayer() {
|
||||
return Minecraft.getMinecraft().thePlayer;
|
||||
}
|
||||
@Override
|
||||
public EntityPlayer getCurrentPlayer() {
|
||||
return Minecraft.getMinecraft().thePlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCurrentPlayer(EntityPlayer player) {
|
||||
return player == Minecraft.getMinecraft().thePlayer;
|
||||
}
|
||||
@Override
|
||||
public boolean isCurrentPlayer(EntityPlayer player) {
|
||||
return player == Minecraft.getMinecraft().thePlayer;
|
||||
}
|
||||
|
||||
private static final BiMap<EntityFXBlockHint, HintParticleInfo> allHints = HashBiMap.create();
|
||||
private static final List<List<EntityFXBlockHint>> hintOwners = new ArrayList<>();
|
||||
private static List<EntityFXBlockHint> currentHints;
|
||||
|
||||
public static void onHintDead(EntityFXBlockHint fx) {
|
||||
if (ConfigurationHandler.INSTANCE.isRemoveCollidingHologram())
|
||||
allHints.remove(fx);
|
||||
for (Iterator<List<EntityFXBlockHint>> iterator = hintOwners.iterator(); iterator.hasNext(); ) {
|
||||
List<EntityFXBlockHint> list = iterator.next();
|
||||
if (list.remove(fx)) {
|
||||
if (list.isEmpty())
|
||||
iterator.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startHinting(World w) {
|
||||
if (!w.isRemote)
|
||||
return;
|
||||
if (currentHints != null)
|
||||
hintOwners.add(currentHints);
|
||||
currentHints = new LinkedList<>();
|
||||
}
|
||||
|
||||
private void ensureHinting() {
|
||||
if (currentHints == null)
|
||||
currentHints = new LinkedList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endHinting(World w) {
|
||||
if (!w.isRemote)
|
||||
return;
|
||||
while (!hintOwners.isEmpty() && hintOwners.size() >= ConfigurationHandler.INSTANCE.getMaxCoexistingHologram()) {
|
||||
List<EntityFXBlockHint> list = hintOwners.remove(0);
|
||||
list.forEach(EntityFXBlockHint::setDead);
|
||||
list.clear();
|
||||
}
|
||||
if (!currentHints.isEmpty())
|
||||
hintOwners.add(currentHints);
|
||||
currentHints = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preInit(FMLPreInitializationEvent e) {
|
||||
MinecraftForge.EVENT_BUS.register(new ForgeEventHandler());
|
||||
}
|
||||
|
||||
private static class HintParticleInfo {
|
||||
private final int x, y, z;
|
||||
private final List<EntityFXBlockHint> owner;
|
||||
|
||||
public HintParticleInfo(int x, int y, int z, List<EntityFXBlockHint> owner) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
HintParticleInfo that = (HintParticleInfo) o;
|
||||
|
||||
if (x != that.x) return false;
|
||||
if (y != that.y) return false;
|
||||
return z == that.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = x;
|
||||
result = 31 * result + y;
|
||||
result = 31 * result + z;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ForgeEventHandler {
|
||||
@SubscribeEvent
|
||||
public void onWorldLoad(WorldEvent.Load e) {
|
||||
if (e.world.isRemote) {
|
||||
allHints.clear();
|
||||
hintOwners.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizon.structurelib.proxy;
|
||||
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.IIcon;
|
||||
@@ -18,4 +19,8 @@ public class CommonProxy {
|
||||
}
|
||||
public void addClientSideChatMessages(String... messages){
|
||||
}
|
||||
public void startHinting(World w) {}
|
||||
public void endHinting(World w) {}
|
||||
|
||||
public void preInit(FMLPreInitializationEvent e) {}
|
||||
}
|
||||
@@ -13,8 +13,11 @@ public interface IStructureDefinition<T> {
|
||||
/**
|
||||
* Used internally
|
||||
*
|
||||
* Might, but is not required, to throw {@link java.util.NoSuchElementException} if the given structure piece is not found.
|
||||
*
|
||||
* @param name same name as for other methods here
|
||||
* @return the array of elements to process
|
||||
* @throws java.util.NoSuchElementException if the given structure piece is not found and the moon phase perfectly matches
|
||||
*/
|
||||
IStructureElement<T>[] getStructureFor(String name);
|
||||
|
||||
@@ -165,4 +168,8 @@ public interface IStructureDefinition<T> {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static <T> StructureDefinition.Builder<T> builder() {
|
||||
return StructureDefinition.builder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
|
||||
/**
|
||||
* a function to extract tier info from a block.
|
||||
* @param <TIER>
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ITierConverter<TIER> {
|
||||
TIER convert(Block block, int meta);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
/**
|
||||
* Implement this and use {@link StructureUtility#withContext(IStructureElement)} in case you need to record some
|
||||
* temporary states that don't need to live in your main context, which would usually live for the whole lifetime of the
|
||||
* structure than just during structure check. Usually just save some few bytes, but becomes non trivial if you need to
|
||||
* record too much stuff.
|
||||
*
|
||||
* You will have to reset the context yourself though. The API can't guess when the old context becomes invalid.
|
||||
* @param <CTX> the temporary state context
|
||||
*/
|
||||
public interface IWithExtendedContext<CTX> {
|
||||
CTX getCurrentContext();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
class LazyStructureElement<T> implements IStructureElementDeferred<T> {
|
||||
private Function<T, IStructureElement<T>> to;
|
||||
private IStructureElement<T> elem;
|
||||
|
||||
public LazyStructureElement(Function<T, IStructureElement<T>> to) {
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
private IStructureElement<T> get(T t) {
|
||||
if (to != null) {
|
||||
elem = to.apply(t);
|
||||
to = null;
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(T t, World world, int x, int y, int z) {
|
||||
return get(t).check(t, world, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
return get(t).placeBlock(t, world, x, y, z, trigger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
return get(t).spawnHint(t, world, x, y, z, trigger);
|
||||
}
|
||||
}
|
||||
@@ -193,6 +193,9 @@ public class StructureDefinition<T> implements IStructureDefinition<T> {
|
||||
|
||||
@Override
|
||||
public IStructureElement<T>[] getStructureFor(String name) {
|
||||
return structures.get(name);
|
||||
IStructureElement<T>[] elements = structures.get(name);
|
||||
if (elements == null)
|
||||
throw new NoSuchElementException(name);
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
@@ -5,17 +5,34 @@ import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
|
||||
import com.gtnewhorizon.structurelib.structure.adders.IBlockAdder;
|
||||
import com.gtnewhorizon.structurelib.structure.adders.ITileAdder;
|
||||
import com.gtnewhorizon.structurelib.util.Vec3Impl;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.world.World;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.*;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static java.lang.Integer.MIN_VALUE;
|
||||
@@ -175,6 +192,173 @@ public class StructureUtility {
|
||||
|
||||
//region block
|
||||
|
||||
/**
|
||||
* A more primitive variant of {@link #ofBlocksTiered(ITierConverter, List, Object, BiConsumer, Function)}
|
||||
* Main difference is this one is check only.
|
||||
* @see #ofBlocksTiered(ITierConverter, Object, BiConsumer, Function)
|
||||
*/
|
||||
public static <T, TIER> IStructureElementCheckOnly<T> ofBlocksTiered(ITierConverter<TIER> tierExtractor, @Nullable TIER notSet, BiConsumer<T, TIER> setter, Function<T, TIER> getter) {
|
||||
if (tierExtractor == null) throw new IllegalArgumentException();
|
||||
if (setter == null) throw new IllegalArgumentException();
|
||||
if (getter == null) throw new IllegalArgumentException();
|
||||
|
||||
return (t, world, x, y, z) -> {
|
||||
Block block = world.getBlock(x, y, z);
|
||||
int meta = world.getBlockMetadata(x, y, z);
|
||||
TIER tier = tierExtractor.convert(block, meta);
|
||||
TIER current = getter.apply(t);
|
||||
if (Objects.equals(notSet, current)) {
|
||||
setter.accept(t, tier);
|
||||
return true;
|
||||
}
|
||||
return Objects.equals(current, tier);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Element representing a component with different tiers. Player can use more blueprint to get hints denoting more
|
||||
* advanced components.
|
||||
*
|
||||
* There is yet no TileEntity counter part of this utility. Feel free to submit a PR to add it.
|
||||
* @param allKnownTiers All known tiers as of calling. Can be empty or null. No hint will be spawned if empty or null. Cannot have null elements.
|
||||
* First element denotes the most primitive tier. Last element denotes the most advanced tier.
|
||||
* If not all tiers are available at definition construction time, use {@link #lazy(Supplier)} or its overloads to delay a little bit.
|
||||
* @param notSet The value returned from {@code getter} when there were no tier info found in T yet. Can be null.
|
||||
* @param getter a function to retrieve the current tier from T
|
||||
* @param setter a function to set the current tier into T
|
||||
* @param tierExtractor a function to extract tier info from a block.
|
||||
*/
|
||||
public static <T, TIER> IStructureElement<T> ofBlocksTiered(ITierConverter<TIER> tierExtractor, @Nullable List<Pair<Block, Integer>> allKnownTiers, @Nullable TIER notSet, BiConsumer<T, TIER> setter, Function<T, TIER> getter) {
|
||||
List<Pair<Block, Integer>> hints = allKnownTiers == null ? Collections.emptyList() : allKnownTiers;
|
||||
if (hints.stream().anyMatch(Objects::isNull)) throw new IllegalArgumentException();
|
||||
IStructureElementCheckOnly<T> check = ofBlocksTiered(tierExtractor, notSet, setter, getter);
|
||||
return new IStructureElement<T>() {
|
||||
@Override
|
||||
public boolean check(T t, World world, int x, int y, int z) {
|
||||
return check.check(t, world, x, y, z);
|
||||
}
|
||||
|
||||
private Pair<Block, Integer> getHint(ItemStack trigger) {
|
||||
return hints.get(Math.min(Math.max(trigger.stackSize, 1), hints.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
Pair<Block, Integer> hint = getHint(trigger);
|
||||
if (hint == null)
|
||||
return false;
|
||||
StructureLibAPI.hintParticle(world, x, y, z, hint.getKey(), hint.getValue());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
Pair<Block, Integer> hint = getHint(trigger);
|
||||
if (hint == null)
|
||||
return false;
|
||||
if (hint.getKey() instanceof ICustomBlockSetting) {
|
||||
ICustomBlockSetting block = (ICustomBlockSetting) hint.getKey();
|
||||
block.setBlock(world, x, y, z, hint.getValue());
|
||||
} else {
|
||||
world.setBlock(x, y, z, hint.getKey(), hint.getValue(), 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Denote a block using unlocalized names. This can be useful to get around mod loading order issues.
|
||||
* <p>
|
||||
* While no immediate error will be thrown, client code should ensure said mod is loaded and
|
||||
* said mod is present, otherwise bad things will happen later!
|
||||
*/
|
||||
public static <T> IStructureElement<T> ofBlockUnlocalizedName(String modid, String unlocalizedName, int meta) {
|
||||
if (StringUtils.isBlank(unlocalizedName)) throw new IllegalArgumentException();
|
||||
if (meta < 0) throw new IllegalArgumentException();
|
||||
if (meta > 15) throw new IllegalArgumentException();
|
||||
if (StringUtils.isBlank(modid)) throw new IllegalArgumentException();
|
||||
return new IStructureElement<T>() {
|
||||
private Block block;
|
||||
|
||||
private Block getBlock() {
|
||||
if (block == null)
|
||||
block = GameRegistry.findBlock(modid, unlocalizedName);
|
||||
return block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(T t, World world, int x, int y, int z) {
|
||||
return world.getBlock(x, y, z) == getBlock() && world.getBlockMetadata(x, y, z) == meta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
StructureLibAPI.hintParticle(world, x, y, z, getBlock(), meta);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
world.setBlock(x, y, z, getBlock(), meta, 2);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Similiar to the other overload, but allows client code to specify a fallback in case said block was not found later
|
||||
* when the element got called.
|
||||
*
|
||||
* This is slightly different to using the other overload and another element in a {@link #ofChain(IStructureElement[])},
|
||||
* as that combination would cause crash, where this won't.
|
||||
*/
|
||||
public static <T> IStructureElement<T> ofBlockUnlocalizedName(String modid, String unlocalizedName, int meta, IStructureElement<T> fallback) {
|
||||
if (StringUtils.isBlank(unlocalizedName)) throw new IllegalArgumentException();
|
||||
if (meta < 0) throw new IllegalArgumentException();
|
||||
if (meta > 15) throw new IllegalArgumentException();
|
||||
if (StringUtils.isBlank(modid)) throw new IllegalArgumentException();
|
||||
if (fallback == null) throw new IllegalArgumentException();
|
||||
return new IStructureElement<T>() {
|
||||
private Block block;
|
||||
private boolean initialized;
|
||||
|
||||
private boolean init() {
|
||||
if (!initialized) {
|
||||
block = GameRegistry.findBlock(modid, unlocalizedName);
|
||||
initialized = true;
|
||||
}
|
||||
return block != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean check(T t, World world, int x, int y, int z) {
|
||||
if (init())
|
||||
return world.getBlock(x, y, z) != block && world.getBlockMetadata(x, y, z) == meta;
|
||||
else
|
||||
return fallback.check(t, world, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
if (init()) {
|
||||
StructureLibAPI.hintParticle(world, x, y, z, block, meta);
|
||||
return true;
|
||||
} else
|
||||
return fallback.spawnHint(t, world, x, y, z, trigger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
if (init()) {
|
||||
world.setBlock(x, y, z, block, meta, 2);
|
||||
return true;
|
||||
} else
|
||||
return fallback.placeBlock(t, world, x, y, z, trigger);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not allow Block duplicates (with different meta)
|
||||
*/
|
||||
@@ -558,6 +742,26 @@ public class StructureUtility {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static <T, E> IStructureElementNoPlacement<T> ofSpecificTileAdder(BiPredicate<T, E> iTileAdder, Class<E> tileClass, Block hintBlock, int hintMeta) {
|
||||
if (iTileAdder == null || hintBlock == null || tileClass == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return new IStructureElementNoPlacement<T>() {
|
||||
@Override
|
||||
public boolean check(T t, World world, int x, int y, int z) {
|
||||
TileEntity tileEntity = world.getTileEntity(x, y, z);
|
||||
// This used to check if it's a GT tile. Since this is now an standalone mod we no longer do this
|
||||
return tileClass.isInstance(tileEntity) && iTileAdder.test(t, tileClass.cast(tileEntity));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
StructureLibAPI.hintParticle(world, x, y, z, hintBlock, hintMeta);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
// No more hatch adder. Implement it via tile adder. We could of course add a wrapper around it in gregtech, but not any more in this standalone mod.
|
||||
|
||||
//endregion
|
||||
@@ -640,8 +844,51 @@ public class StructureUtility {
|
||||
return ofChain(elementChain.toArray(new IStructureElement[0]));
|
||||
}
|
||||
|
||||
// region context
|
||||
public static <CTX, T extends IWithExtendedContext<CTX>, E extends IStructureElement<CTX>> IStructureElement<T> withContext(E elem) {
|
||||
return new IStructureElement<T>() {
|
||||
@Override
|
||||
public boolean check(T t, World world, int x, int y, int z) {
|
||||
return elem.check(t.getCurrentContext(), world, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
return elem.spawnHint(t.getCurrentContext(), world, x, y, z, trigger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
|
||||
return elem.placeBlock(t.getCurrentContext(), world, x, y, z, trigger);
|
||||
}
|
||||
};
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region defer
|
||||
|
||||
/**
|
||||
* Similar to defer, but caches the first returned element returned and won't call it again.
|
||||
* Initialization is not thread safe.
|
||||
*/
|
||||
public static <T> IStructureElementDeferred<T> lazy(Supplier<IStructureElement<T>> to) {
|
||||
if (to == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return new LazyStructureElement<>(t -> to.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to defer, but caches the first returned element returned and won't call it again.
|
||||
* Initialization is not thread safe.
|
||||
*/
|
||||
public static <T> IStructureElementDeferred<T> lazy(Function<T, IStructureElement<T>> to) {
|
||||
if (to == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return new LazyStructureElement<>(to);
|
||||
}
|
||||
|
||||
public static <T> IStructureElementDeferred<T> defer(Supplier<IStructureElement<T>> to) {
|
||||
if (to == null) {
|
||||
throw new IllegalArgumentException();
|
||||
@@ -1269,4 +1516,5 @@ public class StructureUtility {
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* All public stuff in this package and its subpackages are considered part of the public API.
|
||||
* Backwards compatibility is maintained to the maximum extend possible.
|
||||
*/
|
||||
package com.gtnewhorizon.structurelib.structure;
|
||||
@@ -15,11 +15,18 @@ tile.structurelib.blockhint.13.name=Hint air
|
||||
tile.structurelib.blockhint.14.name=Hint no air
|
||||
tile.structurelib.blockhint.15.name=Hint error
|
||||
|
||||
item.structurelib.frontRotationTool.name=Front Rotation Tool
|
||||
item.structurelib.frontRotationTool.name=Front Rotation Tool (Standalone)
|
||||
item.structurelib.frontRotationTool.desc.0=Triggers Front Rotation Interface
|
||||
item.structurelib.frontRotationTool.desc.1=Rotates only the front panel,
|
||||
item.structurelib.frontRotationTool.desc.2=which allows structure rotation.
|
||||
|
||||
item.structurelib.constructableTrigger.name=Multiblock Structure Hologram Projector
|
||||
item.structurelib.constructableTrigger.desc.0=Triggers Constructable Interface
|
||||
item.structurelib.constructableTrigger.desc.1=Shows multiblock construction details,
|
||||
item.structurelib.constructableTrigger.desc.2=just Use on a multiblock controller.
|
||||
item.structurelib.constructableTrigger.desc.3=(Sneak Use in creative to build)
|
||||
item.structurelib.constructableTrigger.desc.4=Quantity affects tier/mode/type
|
||||
|
||||
structurelib.blockhint.desc.0=Helps while building
|
||||
structurelib.blockhint.0.name=Hint 1 dot
|
||||
structurelib.blockhint.1.name=Hint 2 dot
|
||||
@@ -42,4 +49,13 @@ structurelib.blockhint.14.name=Hint no air
|
||||
structurelib.blockhint.desc.4=Make sure it does not contain Air material.
|
||||
structurelib.blockhint.15.name=Hint error
|
||||
structurelib.blockhint.desc.5=ERROR, what did u expect?
|
||||
itemGroup.structurelib=StructureLib
|
||||
itemGroup.structurelib=StructureLib
|
||||
|
||||
structurelib.config.client=Client Side Configurations
|
||||
structurelib.config.client.tooltip=Configurations that only changes how the game looks like, but not how it functions.
|
||||
structurelib.config.client.hologram=Hologram Configurations
|
||||
structurelib.config.client.hologram.tooltip=Configurations that changes how the hologram got projected into the world by default.
|
||||
structurelib.config.client.hologram.maxCoexisting=Max Coexisting Holograms
|
||||
structurelib.config.client.hologram.maxCoexisting.tooltip=Number of holograms that can coexist. Usually all hints generated by one right click belongs to one hologram. An attempt will be made to prune old holograms when a new hologram is about to be projected and this limit would be exceeded.
|
||||
structurelib.config.client.hologram.removeColliding=Remove Colliding Holograms
|
||||
structurelib.config.client.hologram.removeColliding.tooltip=Whether an attempt will be made to remove any existing hologram that collides with a new hologram.
|
||||
@@ -0,0 +1,61 @@
|
||||
tile.structurelib.blockhint.0.name=提示方块:1号
|
||||
tile.structurelib.blockhint.1.name=提示方块:2号
|
||||
tile.structurelib.blockhint.2.name=提示方块:3号
|
||||
tile.structurelib.blockhint.3.name=提示方块:4号
|
||||
tile.structurelib.blockhint.4.name=提示方块:5号
|
||||
tile.structurelib.blockhint.5.name=提示方块:6号
|
||||
tile.structurelib.blockhint.6.name=提示方块:7号
|
||||
tile.structurelib.blockhint.7.name=提示方块:8号
|
||||
tile.structurelib.blockhint.8.name=提示方块:9号
|
||||
tile.structurelib.blockhint.9.name=提示方块:10号
|
||||
tile.structurelib.blockhint.10.name=提示方块:11号
|
||||
tile.structurelib.blockhint.11.name=提示方块:12号
|
||||
tile.structurelib.blockhint.12.name=提示方块:一般
|
||||
tile.structurelib.blockhint.13.name=提示方块:空气
|
||||
tile.structurelib.blockhint.14.name=提示方块:非空气
|
||||
tile.structurelib.blockhint.15.name=提示方块:错误
|
||||
|
||||
item.structurelib.frontRotationTool.name=正面旋转扳手 (StructureLib)
|
||||
item.structurelib.frontRotationTool.desc.0=可以旋转/翻转多方块主机
|
||||
item.structurelib.frontRotationTool.desc.1=多方块机器结构也需要跟随
|
||||
item.structurelib.frontRotationTool.desc.2=多方块主机一起旋转/翻转。
|
||||
|
||||
item.structurelib.constructableTrigger.name=多方块结构全息投影仪
|
||||
item.structurelib.constructableTrigger.desc.0=可以显示多方块机器的结构
|
||||
item.structurelib.constructableTrigger.desc.1=只能在多方块主机上使用,将会显示机器
|
||||
item.structurelib.constructableTrigger.desc.2=结构的细节。 (译者注:请搭高使用)
|
||||
item.structurelib.constructableTrigger.desc.3= (创造模式下潜行右键可以直接完成搭建)
|
||||
item.structurelib.constructableTrigger.desc.4=此物品堆叠数量会影响显示的机器等级/模式/类型
|
||||
|
||||
structurelib.blockhint.desc.0=帮助你搭建机器
|
||||
structurelib.blockhint.0.name=提示方块:1号
|
||||
structurelib.blockhint.1.name=提示方块:2号
|
||||
structurelib.blockhint.2.name=提示方块:3号
|
||||
structurelib.blockhint.3.name=提示方块:4号
|
||||
structurelib.blockhint.4.name=提示方块:5号
|
||||
structurelib.blockhint.5.name=提示方块:6号
|
||||
structurelib.blockhint.6.name=提示方块:7号
|
||||
structurelib.blockhint.7.name=提示方块:8号
|
||||
structurelib.blockhint.8.name=提示方块:9号
|
||||
structurelib.blockhint.9.name=提示方块:10号
|
||||
structurelib.blockhint.10.name=提示方块:11号
|
||||
structurelib.blockhint.11.name=提示方块:12号
|
||||
structurelib.blockhint.desc.1=特定方块们的占位符。
|
||||
structurelib.blockhint.12.name=提示方块:一般
|
||||
structurelib.blockhint.desc.2=一般通用占位符。
|
||||
structurelib.blockhint.13.name=提示方块:空气
|
||||
structurelib.blockhint.desc.3=确保这里是空气方块。
|
||||
structurelib.blockhint.14.name=提示方块:非空气
|
||||
structurelib.blockhint.desc.4=确保这里不是空气方块。
|
||||
structurelib.blockhint.15.name=提示方块:错误
|
||||
structurelib.blockhint.desc.5=ERROR,你想要做什么?
|
||||
itemGroup.structurelib=StructureLib
|
||||
|
||||
structurelib.config.client=客户端-配置
|
||||
structurelib.config.client.tooltip=修改此配置只会改变游戏中的显示效果,而不会改变实际工作模式。
|
||||
structurelib.config.client.hologram=全息投影仪-配置
|
||||
structurelib.config.client.hologram.tooltip=这将决定默认情况下,机器结构细节将如何被投影到世界中。
|
||||
structurelib.config.client.hologram.maxCoexisting=最多可以同时存在的全息投影数量
|
||||
structurelib.config.client.hologram.maxCoexisting.tooltip=这决定最多可以同时存在多少台机器的全息投影。一般一次使用全息投影仪右键生成的所有机器结构细节被视为一个全息投影。当同时存在多个全息投影,并超过此数量时,再次使用全息投影仪会移除旧有的全息投影。
|
||||
structurelib.config.client.hologram.removeColliding=移除冲突的全息投影
|
||||
structurelib.config.client.hologram.removeColliding.tooltip=当新的全息投影与已存在的全息投影冲突时,开启此选项时会移除已存在的全息投影。
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 667 B |
@@ -1,10 +1,10 @@
|
||||
[
|
||||
{
|
||||
"modid": "structurelib",
|
||||
"name": "StructureLib",
|
||||
"modid": "${modId}",
|
||||
"name": "${modName}",
|
||||
"description": "Multiblocks with ease",
|
||||
"version": "${version}",
|
||||
"mcversion": "${mcversion}",
|
||||
"version": "${modVersion}",
|
||||
"mcversion": "${minecraftVersion}",
|
||||
"url": "",
|
||||
"updateUrl": "",
|
||||
"authorList": ["glee8e"],
|
||||
|
||||
Reference in new issue
Block a user