From cdfa361718b7ac76b9a7e116deed8aa3b2c5572b Mon Sep 17 00:00:00 2001 From: Augusto Resende Date: Mon, 13 Jul 2020 14:05:23 -0300 Subject: [PATCH] Forge & Fabric! --- build.gradle | 406 +++++++++++------- changelog.txt | 1 + .../com/vanilla/experience/CommonUtils.java | 6 + .../com/vanilla/experience/HelloMessage.java | 12 + .../recipes/chainmail_boots.json | 0 .../recipes/chainmail_chestplate.json | 0 .../recipes/chainmail_helmet.json | 0 .../recipes/chainmail_leggings.json | 0 .../vanillaexperience/recipes/coal_ore.json | 0 .../vanillaexperience/recipes/cobweb.json | 0 .../recipes/diamond_horse_armor.json | 0 .../recipes/diamond_ore.json | 0 .../vanillaexperience/recipes/elytra.json | 0 .../recipes/emerald_ore.json | 0 .../recipes/enchanted_golden_apple.json | 0 .../recipes/ender_pearl.json | 0 .../vanillaexperience/recipes/gold_ore.json | 0 .../recipes/golden_horse_armor.json | 6 +- .../data/vanillaexperience/recipes/grass.json | 0 .../recipes/iron_horse_armor.json | 0 .../vanillaexperience/recipes/iron_ore.json | 0 .../vanillaexperience/recipes/lapis_ore.json | 0 .../recipes/leather_horse_armor.json | 0 .../vanillaexperience/recipes/name_tag.json | 2 +- .../recipes/redstone_ore.json | 0 .../vanillaexperience/recipes/saddle.json | 0 .../src}/main/resources/pack.mcmeta | 2 +- {src => common/src}/main/resources/vex.png | Bin fabric/.gitignore | 21 + fabric/build.gradle | 74 ++++ fabric/gradle.properties | 13 + fabric/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55616 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + fabric/gradlew | 172 ++++++++ fabric/gradlew.bat | 84 ++++ .../.test => fabric/logs/debug.log | 0 fabric/logs/latest.log | 0 fabric/settings.gradle | 10 + .../experience/fabric/VanillaExperience.java | 20 + .../mixin/SweetBerryBushBlockMixin.java | 28 ++ .../enhancedbonemeal/EnhancedBoneMeal.java | 67 +++ .../EnhancedBoneMealDispenserBehaviour.java | 67 +++ .../fabric/enhancedseeds/EnhancedSeeds.java | 73 ++++ .../EnhancedSeedsDispenserBehaviour.java | 58 +++ .../mixin/LivingEntityMixin.java | 61 +++ .../experience/fabric/utils/MixinLoader.java | 24 ++ .../experience/fabric/utils/VexUtils.java | 14 + .../mixin/EntityTypeMixin.java | 17 + .../mixin/ZeroTickAbstractPlantStemBlock.java | 27 ++ .../mixin/ZeroTickBambooBlock.java | 31 ++ .../mixin/ZeroTickCactusBlock.java | 26 ++ .../mixin/ZeroTickChorusFlowerBlock.java | 26 ++ .../mixin/ZeroTickSugarCaneBlock.java | 26 ++ fabric/src/main/resources/fabric.mod.json | 37 ++ .../mixin/fabric/enhancedtotem.mixins.json | 13 + .../fabric/witherrosesunpatch.mixins.json | 13 + .../mixin/fabric/zerotickunpatch.mixins.json | 16 + forge/.gitignore | 21 + forge/build.gradle | 102 +++++ forge/gradle.properties | 9 + forge/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 56177 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 + forge/gradlew | 172 ++++++++ forge/gradlew.bat | 84 ++++ forge/logs/debug.log | 0 forge/logs/latest.log | 0 .../experience/forge/VanillaExperience.java | 35 ++ .../enhancedberries/EnhancedBerries.java | 2 +- .../enhancedbonemeal/EnhancedBoneMeal.java | 9 +- .../EnhancedBoneMealDispenserBehaviour.java | 11 +- .../forge}/enhancedseeds/EnhancedSeeds.java | 10 +- .../EnhancedSeedsDispenserBehaviour.java | 11 +- .../forge}/enhancedtotem/EnhancedTotem.java | 12 +- .../experience/forge/utils/MixinLoader.java | 23 + .../forge/utils/OverrideLoader.java | 66 +++ .../experience/forge/utils/VexUtils.java | 23 + .../mixin/EntityTypeMixin.java | 16 + .../override/WitherRose.java | 10 +- .../mixin/ZeroTickAbstractTopPlantBlock.java | 27 ++ .../mixin/ZeroTickBambooBlock.java | 31 ++ .../mixin/ZeroTickCactusBlock.java | 26 ++ .../mixin/ZeroTickChorusFlowerBlock.java | 26 ++ .../mixin/ZeroTickSugarCaneBlock.java | 26 ++ .../override}/ZeroTickBambooBlock.java | 5 +- .../override}/ZeroTickCactusBlock.java | 5 +- .../override}/ZeroTickChorusFlowerBlock.java | 3 +- .../override}/ZeroTickKelpTopBlock.java | 5 +- .../override}/ZeroTickSugarCaneBlock.java | 5 +- .../ZeroTickTwistingVinesTopBlock.java | 7 +- .../ZeroTickWeepingVinesTopBlock.java | 7 +- forge/src/main/resources/META-INF/MANIFEST.MF | 8 + .../src}/main/resources/META-INF/mods.toml | 23 +- .../forge/witherrosesunpatch.mixins.json | 12 + .../mixin/forge/zerotickunpatch.mixins.json | 16 + gradle.properties | 7 +- .../vanilla/experience/VanillaExperience.java | 126 ------ src/main/resources/META-INF/MANIFEST.MF | 8 - 97 files changed, 2107 insertions(+), 347 deletions(-) create mode 100644 changelog.txt create mode 100644 common/src/main/java/com/vanilla/experience/CommonUtils.java create mode 100644 common/src/main/java/com/vanilla/experience/HelloMessage.java rename {src => common/src}/main/resources/data/vanillaexperience/recipes/chainmail_boots.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/chainmail_chestplate.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/chainmail_helmet.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/chainmail_leggings.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/coal_ore.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/cobweb.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/diamond_horse_armor.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/diamond_ore.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/elytra.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/emerald_ore.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/enchanted_golden_apple.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/ender_pearl.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/gold_ore.json (100%) rename src/main/resources/data/vanillaexperience/recipes/gold_horse_armor.json => common/src/main/resources/data/vanillaexperience/recipes/golden_horse_armor.json (66%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/grass.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/iron_horse_armor.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/iron_ore.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/lapis_ore.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/leather_horse_armor.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/name_tag.json (90%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/redstone_ore.json (100%) rename {src => common/src}/main/resources/data/vanillaexperience/recipes/saddle.json (100%) rename {src => common/src}/main/resources/pack.mcmeta (78%) rename {src => common/src}/main/resources/vex.png (100%) create mode 100644 fabric/.gitignore create mode 100644 fabric/build.gradle create mode 100644 fabric/gradle.properties create mode 100644 fabric/gradle/wrapper/gradle-wrapper.jar create mode 100644 fabric/gradle/wrapper/gradle-wrapper.properties create mode 100644 fabric/gradlew create mode 100644 fabric/gradlew.bat rename src/main/resources/data/vanillaexperience/.test => fabric/logs/debug.log (100%) create mode 100644 fabric/logs/latest.log create mode 100644 fabric/settings.gradle create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/VanillaExperience.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/enhancedberries/mixin/SweetBerryBushBlockMixin.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/enhancedbonemeal/EnhancedBoneMeal.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/enhancedseeds/EnhancedSeeds.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/enhancedseeds/EnhancedSeedsDispenserBehaviour.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/enhancedtotem/mixin/LivingEntityMixin.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/utils/MixinLoader.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/utils/VexUtils.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/witherrosesunpatch/mixin/EntityTypeMixin.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickAbstractPlantStemBlock.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickBambooBlock.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickCactusBlock.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickChorusFlowerBlock.java create mode 100644 fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickSugarCaneBlock.java create mode 100644 fabric/src/main/resources/fabric.mod.json create mode 100644 fabric/src/main/resources/mixin/fabric/enhancedtotem.mixins.json create mode 100644 fabric/src/main/resources/mixin/fabric/witherrosesunpatch.mixins.json create mode 100644 fabric/src/main/resources/mixin/fabric/zerotickunpatch.mixins.json create mode 100644 forge/.gitignore create mode 100644 forge/build.gradle create mode 100644 forge/gradle.properties create mode 100644 forge/gradle/wrapper/gradle-wrapper.jar create mode 100644 forge/gradle/wrapper/gradle-wrapper.properties create mode 100644 forge/gradlew create mode 100644 forge/gradlew.bat create mode 100644 forge/logs/debug.log create mode 100644 forge/logs/latest.log create mode 100644 forge/src/main/java/com/vanilla/experience/forge/VanillaExperience.java rename {src/main/java/com/vanilla/experience => forge/src/main/java/com/vanilla/experience/forge}/enhancedberries/EnhancedBerries.java (91%) rename {src/main/java/com/vanilla/experience => forge/src/main/java/com/vanilla/experience/forge}/enhancedbonemeal/EnhancedBoneMeal.java (90%) rename {src/main/java/com/vanilla/experience => forge/src/main/java/com/vanilla/experience/forge}/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java (90%) rename {src/main/java/com/vanilla/experience => forge/src/main/java/com/vanilla/experience/forge}/enhancedseeds/EnhancedSeeds.java (87%) rename {src/main/java/com/vanilla/experience => forge/src/main/java/com/vanilla/experience/forge}/enhancedseeds/EnhancedSeedsDispenserBehaviour.java (87%) rename {src/main/java/com/vanilla/experience => forge/src/main/java/com/vanilla/experience/forge}/enhancedtotem/EnhancedTotem.java (86%) create mode 100644 forge/src/main/java/com/vanilla/experience/forge/utils/MixinLoader.java create mode 100644 forge/src/main/java/com/vanilla/experience/forge/utils/OverrideLoader.java create mode 100644 forge/src/main/java/com/vanilla/experience/forge/utils/VexUtils.java create mode 100644 forge/src/main/java/com/vanilla/experience/forge/witherrosesunpatch/mixin/EntityTypeMixin.java rename src/main/java/com/vanilla/experience/enhancedwitherroses/EnhancedWitherRoses.java => forge/src/main/java/com/vanilla/experience/forge/witherrosesunpatch/override/WitherRose.java (59%) create mode 100644 forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickAbstractTopPlantBlock.java create mode 100644 forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickBambooBlock.java create mode 100644 forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickCactusBlock.java create mode 100644 forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickChorusFlowerBlock.java create mode 100644 forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickSugarCaneBlock.java rename {src/main/java/com/vanilla/experience/zerotickunpatch => forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override}/ZeroTickBambooBlock.java (80%) rename {src/main/java/com/vanilla/experience/zerotickunpatch => forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override}/ZeroTickCactusBlock.java (80%) rename {src/main/java/com/vanilla/experience/zerotickunpatch => forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override}/ZeroTickChorusFlowerBlock.java (89%) rename {src/main/java/com/vanilla/experience/zerotickunpatch => forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override}/ZeroTickKelpTopBlock.java (79%) rename {src/main/java/com/vanilla/experience/zerotickunpatch => forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override}/ZeroTickSugarCaneBlock.java (79%) rename {src/main/java/com/vanilla/experience/zerotickunpatch => forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override}/ZeroTickTwistingVinesTopBlock.java (79%) rename {src/main/java/com/vanilla/experience/zerotickunpatch => forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override}/ZeroTickWeepingVinesTopBlock.java (79%) create mode 100644 forge/src/main/resources/META-INF/MANIFEST.MF rename {src => forge/src}/main/resources/META-INF/mods.toml (56%) create mode 100644 forge/src/main/resources/mixin/forge/witherrosesunpatch.mixins.json create mode 100644 forge/src/main/resources/mixin/forge/zerotickunpatch.mixins.json delete mode 100644 src/main/java/com/vanilla/experience/VanillaExperience.java delete mode 100644 src/main/resources/META-INF/MANIFEST.MF diff --git a/build.gradle b/build.gradle index 04583d9..aa4fbe7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,147 +1,259 @@ -buildscript { - repositories { - maven { url = 'https://files.minecraftforge.net/maven' } - jcenter() - mavenCentral() - } - dependencies { - classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true - } -} -apply plugin: 'net.minecraftforge.gradle' -// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. -apply plugin: 'eclipse' -apply plugin: 'maven-publish' - -version = '0.1.0' -group = 'com.vanilla.experience' -archivesBaseName = 'vanillaexperience' - -sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. - -println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) -minecraft { - // The mappings can be changed at any time, and must be in the following format. - // snapshot_YYYYMMDD Snapshot are built nightly. - // stable_# Stables are built at the discretion of the MCP team. - // Use non-default mappings at your own risk. they may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: 'snapshot', version: '20200707-1.16.1' - // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. - - // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') - - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - client { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' - - // Recommended logging level for the console - property 'forge.logging.console.level', 'debug' - - mods { - examplemod { - source sourceSets.main - } - } - } - - server { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' - - // Recommended logging level for the console - property 'forge.logging.console.level', 'debug' - - mods { - examplemod { - source sourceSets.main - } - } - } - - data { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' - - // Recommended logging level for the console - property 'forge.logging.console.level', 'debug' - - args '--mod', 'examplemod', '--all', '--output', file('src/generated/resources/') - - mods { - examplemod { - source sourceSets.main - } - } - } - } -} - -dependencies { - // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed - // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. - // The userdev artifact is a special name and will get all sorts of transformations applied to it. - minecraft 'net.minecraftforge:forge:1.16.1-32.0.59' - - // You may put jars on which you depend on in ./libs or you may define them like so.. - // compile "some.group:artifact:version:classifier" - // compile "some.group:artifact:version" - - // Real examples - // compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env - // compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env - - // The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. - // provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' - - // These dependencies get remapped to your current MCP mappings - // deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev' - - // For more info... - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html - -} - -// Example for how to get properties into the manifest for reading by the runtime.. -jar { - manifest { - attributes([ - "Specification-Title": "vanillaexperience", - "Specification-Vendor": "vanillaexperience", - "Specification-Version": "1", // We are version 1 of ourselves - "Implementation-Title": project.name, - "Implementation-Version": "${version}", - "Implementation-Vendor" :"vanillaexperience", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } -} - -// Example configuration to allow publishing using the maven-publish task -// This is the preferred method to reobfuscate your jar file -jar.finalizedBy('reobfJar') -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing -//publish.dependsOn('reobfJar') - -publishing { - publications { - mavenJava(MavenPublication) { - artifact jar - } - } - repositories { - maven { - url "file:///${project.projectDir}/mcmodsrepo" - } - } -} \ No newline at end of file +import java.util.jar.Manifest +import java.nio.file.* +import java.nio.file.attribute.BasicFileAttributes +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream + +import org.apache.tools.ant.taskdefs.condition.Os + +buildscript { + repositories { + maven { + name = "Modmuss50" + url = "http://maven.modmuss50.me/" + } + jcenter() + } +} +plugins { + id 'java' + id "com.matthewprenger.cursegradle" version "1.4.0" +} + +version = "${mod_version}" +group = "com.vanilla.experience" +archivesBaseName = "${mod_id}-${mc_version}" + +curseforge { + apiKey = project.hasProperty("curseForgeApiKey") ? project.curseForgeApiKey : "c1dbff3f-4cfc-4eee-81bf-7406d1e3c5d1" + project { + + id = "${curseforge_id}" + changelog = file('changelog.txt') + + //release/beta/alpha + releaseType = 'release' + addGameVersion '1.16.1' + addGameVersion 'Java 8' + addGameVersion 'Forge' + addGameVersion 'Fabric' + mainArtifact(new File(new File(buildDir, "libs"), "$archivesBaseName-${version}.jar")) { + displayName = "$archivesBaseName-$version" + relations { + requiredDependency 'mixinbootstrap' + requiredDependency 'fabric-api' + } + } + /* addArtifact(new File(new File(buildDir, "libs"), "$archivesBaseName-$version-forge-deobf.jar")) { + displayName = "$archivesBaseName-$version-forge-deobf" + changelog = "*This is a file for mod developers. If you don't know what to do with it, don't use it!*" + } + addArtifact(new File(new File(buildDir, "libs"), "$archivesBaseName-$version-fabric-dev.jar")) { + displayName = "$archivesBaseName-$version-fabric-dev" + changelog = "*This is a file for mod developers. If you don't know what to do with it, don't use it!*" + } + addArtifact(new File(new File(buildDir, "libs"), "$archivesBaseName-$version-fabric-sources.jar")) { + displayName = "$archivesBaseName-$version-fabric-sources" + changelog = "*This is a file for mod developers. If you don't know what to do with it, don't use it!*" + } + addArtifact(new File(new File(buildDir, "libs"), "$archivesBaseName-$version-fabric-sources-dev.jar")) { + displayName = "$archivesBaseName-$version-fabric-sources-dev" + changelog = "*This is a file for mod developers. If you don't know what to do with it, don't use it!*" + } */ + } + options { + javaIntegration = false + forgeGradleIntegration = false + } +} + +task cfpublish(dependsOn: ['build', 'curseforge']) + +static boolean isWindows() { + return Os.isFamily(Os.FAMILY_WINDOWS); +} + +String appendPrefix(String dir) { + if(isWindows()) + dir = buildscript.sourceFile.getParentFile().getPath().toString()+"\\"+dir + return dir +} + +void copyFiles(String dir) { + println("Copying $dir files...") + File outDir = new File("$buildDir/libs/$dir") + //Dev files are not merged, to help avoid developer confusion and/or accidentally importing the wrong loaders' files when developing for one loader or the other. + //So in the case of dev files, move them to the final output folder + File devOutDir = new File("$buildDir/libs") + if(!outDir.exists()) + outDir.mkdirs() + String inDirPath = appendPrefix(dir) + File inDir = new File("$inDirPath/build/libs") + inDir.listFiles().each { file -> + File outFile = null; + //Main file from either one + if(file.getName() == "$archivesBaseName-${version}.jar") + outFile = new File(outDir, file.getName()) + //Developer file - include which loader it is for in the output filename + else + outFile = new File(devOutDir, file.getName().replaceAll("$archivesBaseName-$version", "$archivesBaseName-$version-$dir")) + if(outFile.exists()) + outFile.delete() + Files.copy(file.toPath(), outFile.toPath()) + } +} + +void deleteDir(File file) { + File[] contents = file.listFiles(); + if (contents != null) + for (File f: contents) + if (!Files.isSymbolicLink(f.toPath())) + deleteDir(f) + file.delete() +} + +task createFinalJar(type: Zip) { + from "$buildDir/rebuild" + include '**/' + archiveName "$archivesBaseName-${version}.jar" + destinationDir(file("$buildDir/libs/")) +} + +/* +task createFinalJar { + + inputs.files(fileTree("$buildDir/rebuild")) + outputs.file("$buildDir/libs/$archivesBaseName-${version}.jar") + doLast { + println("Creating the final jar...") + File f = new File("$buildDir/libs/$archivesBaseName-${version}.jar") + + final Path sourceDir = Paths.get("$buildDir/rebuild"); + try { + final ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(f)) + Files.walkFileTree(sourceDir, new SimpleFileVisitor() { + @Override + FileVisitResult visitFile(Path file, BasicFileAttributes attributes) { + try { + Path targetFile = sourceDir.relativize(file) + outputStream.putNextEntry(new ZipEntry(targetFile.toString())) + byte[] bytes = Files.readAllBytes(file) + outputStream.write(bytes, 0, bytes.length) + outputStream.closeEntry() + } catch (IOException e) { + e.printStackTrace() + } + return FileVisitResult.CONTINUE + } + }) + outputStream.close() + } catch (IOException e) { + e.printStackTrace() + } + } +}*/ + +task extractMainJars { + inputs.files(fileTree("$buildDir/libs")) + outputs.files(fileTree("$buildDir/rebuild")) + outputs.files(fileTree("$buildDir/tmp/expandedArchives")) + finalizedBy createFinalJar + doLast { + FileTree fabricTree = zipTree(new File("$buildDir/libs/fabric/$archivesBaseName-${version}.jar")) + FileTree forgeTree = zipTree(new File("$buildDir/libs/forge/$archivesBaseName-${version}.jar")) + File rebuildDir = new File("$buildDir/rebuild") + if (rebuildDir.exists()) { + println("Clearing old data...") + deleteDir(rebuildDir) + } + rebuildDir.mkdirs() + println("Extracting jars to merge...") + Manifest manifest = null + String regexSafeBuildDir = buildDir.toString().replaceAll('\\\\', '\\\\\\\\') + fabricTree.getFiles().each { file -> + String rebuildPath = isWindows() ? file.getPath().replaceAll("$regexSafeBuildDir\\\\tmp\\\\expandedArchives\\\\$archivesBaseName-${version}\\.jar_[0-9a-z]+\\\\", '') : file.getPath().replaceAll("$regexSafeBuildDir/tmp/expandedArchives/$archivesBaseName-${version}.jar_[0-z]+/", '') + //Make sure to properly merge the manifests of the jars + if (rebuildPath == "META-INF/MANIFEST.MF" || rebuildPath == "META-INF\\MANIFEST.MF") { + FileInputStream inputStream = new FileInputStream(file) + manifest = new Manifest(inputStream) + inputStream.close() + } else { + File outFile = new File("$buildDir/rebuild/" + rebuildPath) + outFile.getParentFile().mkdirs() + //println("Extracting file to "+outFile.getPath()) + Files.copy(file.toPath(), outFile.toPath()) + } + } + forgeTree.getFiles().each { file -> + String rebuildPath = isWindows() ? file.getPath().replaceAll("$regexSafeBuildDir\\\\tmp\\\\expandedArchives\\\\$archivesBaseName-${version}\\.jar_[0-9a-z]+\\\\", '') : file.getPath().replaceAll("$regexSafeBuildDir/tmp/expandedArchives/$archivesBaseName-${version}.jar_[0-z]+/", '') + //Make sure to properly merge the manifests of the jars + if (rebuildPath == "META-INF/MANIFEST.MF" || rebuildPath == "META-INF\\MANIFEST.MF") { + FileInputStream inputStream = new FileInputStream(file) + if (manifest == null) + manifest = new Manifest(inputStream) + else + manifest.read(inputStream) + inputStream.close() + } else { + File outFile = new File("$buildDir/rebuild/" + rebuildPath) + outFile.getParentFile().mkdirs() + //println("Extracting file to "+outFile.getPath()) + if (!outFile.exists()) + Files.copy(file.toPath(), outFile.toPath()) + else if (outFile.getPath().contains("assets")) + println("Skipping duplicate asset: " + outFile.toPath()) + else + System.err.println("Warning: Skipping duplicate file: " + outFile.toPath()) + } + } + if (manifest != null) { + println("Creating manifest...") + File outFile = new File("$buildDir/rebuild/META-INF/MANIFEST.MF") + outFile.getParentFile().mkdirs() + FileOutputStream outputStream = new FileOutputStream(outFile) + manifest.write(outputStream) + outputStream.close() + } + + //Do this because otherwise we end up with a lot of temporary files that never get cleared + deleteDir(new File("$buildDir/tmp/expandedArchives")) + } +} + +task copyFiles { + inputs.files(fileTree("forge/build/libs")) + inputs.files(fileTree("fabric/build/libs")) + outputs.files(fileTree("$buildDir/libs/forge")) + outputs.files(fileTree("$buildDir/libs/fabric")) + finalizedBy extractMainJars + doLast { + copyFiles("forge") + copyFiles("fabric") + } +} + +task execBuilds { + inputs.files(fileTree('fabric')) + inputs.files(fileTree('forge')) + outputs.files(fileTree("forge/build/libs")) + outputs.files(fileTree("fabric/build/libs")) + finalizedBy copyFiles + doLast { + def gradleFile = isWindows() ? "./gradlew.bat" : "./gradlew" + def sout = System.out, serr = System.err + def procFabric = "$gradleFile build -Pversion=$version -Pgroup=$group -PoutputJarBaseName=$archivesBaseName".execute(null, new File("fabric")) + procFabric.consumeProcessOutput(sout, serr) + //TODO Test if concurrent even does it any differently + if (!project.hasProperty("concurrent") || !project.concurrent) + procFabric.waitForOrKill(1800000) + def procForge = "$gradleFile build -Pversion=$version -Pgroup=$group -PoutputJarBaseName=$archivesBaseName".execute(null, new File("forge")) + procForge.consumeProcessOutput(sout, serr) + if (project.hasProperty("concurrent") && project.concurrent) + procFabric.waitForOrKill(1800000) + procForge.waitForOrKill(1800000) + } +} + +build { + finalizedBy execBuilds +} diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 0000000..fa380a6 --- /dev/null +++ b/changelog.txt @@ -0,0 +1 @@ +This version now supports Fabric AND Forge with SAME JAR. Enjoy. \ No newline at end of file diff --git a/common/src/main/java/com/vanilla/experience/CommonUtils.java b/common/src/main/java/com/vanilla/experience/CommonUtils.java new file mode 100644 index 0000000..5c477f6 --- /dev/null +++ b/common/src/main/java/com/vanilla/experience/CommonUtils.java @@ -0,0 +1,6 @@ +package com.vanilla.experience; + +public class CommonUtils { + public static int zeroTickVersionPatch = 2524; + public static int witherRosesVersionPatch = 2554; +} \ No newline at end of file diff --git a/common/src/main/java/com/vanilla/experience/HelloMessage.java b/common/src/main/java/com/vanilla/experience/HelloMessage.java new file mode 100644 index 0000000..5626dd8 --- /dev/null +++ b/common/src/main/java/com/vanilla/experience/HelloMessage.java @@ -0,0 +1,12 @@ +package com.vanilla.experience; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class HelloMessage { + private static final Logger LOGGER = LogManager.getLogger(); + + public HelloMessage(){ + LOGGER.info("[VEX] Starting Vanilla Experience, thanks for downloading!"); + } +} diff --git a/src/main/resources/data/vanillaexperience/recipes/chainmail_boots.json b/common/src/main/resources/data/vanillaexperience/recipes/chainmail_boots.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/chainmail_boots.json rename to common/src/main/resources/data/vanillaexperience/recipes/chainmail_boots.json diff --git a/src/main/resources/data/vanillaexperience/recipes/chainmail_chestplate.json b/common/src/main/resources/data/vanillaexperience/recipes/chainmail_chestplate.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/chainmail_chestplate.json rename to common/src/main/resources/data/vanillaexperience/recipes/chainmail_chestplate.json diff --git a/src/main/resources/data/vanillaexperience/recipes/chainmail_helmet.json b/common/src/main/resources/data/vanillaexperience/recipes/chainmail_helmet.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/chainmail_helmet.json rename to common/src/main/resources/data/vanillaexperience/recipes/chainmail_helmet.json diff --git a/src/main/resources/data/vanillaexperience/recipes/chainmail_leggings.json b/common/src/main/resources/data/vanillaexperience/recipes/chainmail_leggings.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/chainmail_leggings.json rename to common/src/main/resources/data/vanillaexperience/recipes/chainmail_leggings.json diff --git a/src/main/resources/data/vanillaexperience/recipes/coal_ore.json b/common/src/main/resources/data/vanillaexperience/recipes/coal_ore.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/coal_ore.json rename to common/src/main/resources/data/vanillaexperience/recipes/coal_ore.json diff --git a/src/main/resources/data/vanillaexperience/recipes/cobweb.json b/common/src/main/resources/data/vanillaexperience/recipes/cobweb.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/cobweb.json rename to common/src/main/resources/data/vanillaexperience/recipes/cobweb.json diff --git a/src/main/resources/data/vanillaexperience/recipes/diamond_horse_armor.json b/common/src/main/resources/data/vanillaexperience/recipes/diamond_horse_armor.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/diamond_horse_armor.json rename to common/src/main/resources/data/vanillaexperience/recipes/diamond_horse_armor.json diff --git a/src/main/resources/data/vanillaexperience/recipes/diamond_ore.json b/common/src/main/resources/data/vanillaexperience/recipes/diamond_ore.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/diamond_ore.json rename to common/src/main/resources/data/vanillaexperience/recipes/diamond_ore.json diff --git a/src/main/resources/data/vanillaexperience/recipes/elytra.json b/common/src/main/resources/data/vanillaexperience/recipes/elytra.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/elytra.json rename to common/src/main/resources/data/vanillaexperience/recipes/elytra.json diff --git a/src/main/resources/data/vanillaexperience/recipes/emerald_ore.json b/common/src/main/resources/data/vanillaexperience/recipes/emerald_ore.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/emerald_ore.json rename to common/src/main/resources/data/vanillaexperience/recipes/emerald_ore.json diff --git a/src/main/resources/data/vanillaexperience/recipes/enchanted_golden_apple.json b/common/src/main/resources/data/vanillaexperience/recipes/enchanted_golden_apple.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/enchanted_golden_apple.json rename to common/src/main/resources/data/vanillaexperience/recipes/enchanted_golden_apple.json diff --git a/src/main/resources/data/vanillaexperience/recipes/ender_pearl.json b/common/src/main/resources/data/vanillaexperience/recipes/ender_pearl.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/ender_pearl.json rename to common/src/main/resources/data/vanillaexperience/recipes/ender_pearl.json diff --git a/src/main/resources/data/vanillaexperience/recipes/gold_ore.json b/common/src/main/resources/data/vanillaexperience/recipes/gold_ore.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/gold_ore.json rename to common/src/main/resources/data/vanillaexperience/recipes/gold_ore.json diff --git a/src/main/resources/data/vanillaexperience/recipes/gold_horse_armor.json b/common/src/main/resources/data/vanillaexperience/recipes/golden_horse_armor.json similarity index 66% rename from src/main/resources/data/vanillaexperience/recipes/gold_horse_armor.json rename to common/src/main/resources/data/vanillaexperience/recipes/golden_horse_armor.json index 06c47d6..73f9d7a 100644 --- a/src/main/resources/data/vanillaexperience/recipes/gold_horse_armor.json +++ b/common/src/main/resources/data/vanillaexperience/recipes/golden_horse_armor.json @@ -10,7 +10,7 @@ { "h": { - "item": "minecraft:gold_helmet" + "item": "minecraft:golden_helmet" }, "g": { @@ -22,12 +22,12 @@ }, "b": { - "item": "minecraft:gold_boots" + "item": "minecraft:golden_boots" } }, "result": { - "item": "minecraft:gold_horse_armor", + "item": "minecraft:golden_horse_armor", "count": 1 } } \ No newline at end of file diff --git a/src/main/resources/data/vanillaexperience/recipes/grass.json b/common/src/main/resources/data/vanillaexperience/recipes/grass.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/grass.json rename to common/src/main/resources/data/vanillaexperience/recipes/grass.json diff --git a/src/main/resources/data/vanillaexperience/recipes/iron_horse_armor.json b/common/src/main/resources/data/vanillaexperience/recipes/iron_horse_armor.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/iron_horse_armor.json rename to common/src/main/resources/data/vanillaexperience/recipes/iron_horse_armor.json diff --git a/src/main/resources/data/vanillaexperience/recipes/iron_ore.json b/common/src/main/resources/data/vanillaexperience/recipes/iron_ore.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/iron_ore.json rename to common/src/main/resources/data/vanillaexperience/recipes/iron_ore.json diff --git a/src/main/resources/data/vanillaexperience/recipes/lapis_ore.json b/common/src/main/resources/data/vanillaexperience/recipes/lapis_ore.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/lapis_ore.json rename to common/src/main/resources/data/vanillaexperience/recipes/lapis_ore.json diff --git a/src/main/resources/data/vanillaexperience/recipes/leather_horse_armor.json b/common/src/main/resources/data/vanillaexperience/recipes/leather_horse_armor.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/leather_horse_armor.json rename to common/src/main/resources/data/vanillaexperience/recipes/leather_horse_armor.json diff --git a/src/main/resources/data/vanillaexperience/recipes/name_tag.json b/common/src/main/resources/data/vanillaexperience/recipes/name_tag.json similarity index 90% rename from src/main/resources/data/vanillaexperience/recipes/name_tag.json rename to common/src/main/resources/data/vanillaexperience/recipes/name_tag.json index 6498ac6..b235c62 100644 --- a/src/main/resources/data/vanillaexperience/recipes/name_tag.json +++ b/common/src/main/resources/data/vanillaexperience/recipes/name_tag.json @@ -16,7 +16,7 @@ { "item": "minecraft:paper" }, - "p": + "d": { "item": "minecraft:diamond_block" } diff --git a/src/main/resources/data/vanillaexperience/recipes/redstone_ore.json b/common/src/main/resources/data/vanillaexperience/recipes/redstone_ore.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/redstone_ore.json rename to common/src/main/resources/data/vanillaexperience/recipes/redstone_ore.json diff --git a/src/main/resources/data/vanillaexperience/recipes/saddle.json b/common/src/main/resources/data/vanillaexperience/recipes/saddle.json similarity index 100% rename from src/main/resources/data/vanillaexperience/recipes/saddle.json rename to common/src/main/resources/data/vanillaexperience/recipes/saddle.json diff --git a/src/main/resources/pack.mcmeta b/common/src/main/resources/pack.mcmeta similarity index 78% rename from src/main/resources/pack.mcmeta rename to common/src/main/resources/pack.mcmeta index 700e07e..b34e030 100644 --- a/src/main/resources/pack.mcmeta +++ b/common/src/main/resources/pack.mcmeta @@ -1,6 +1,6 @@ { "pack": { - "description": "examplemod resources", + "description": "VanillaExperience resources", "pack_format": 5, "_comment": "A pack_format of 5 requires json lang files and some texture changes from 1.15. Note: we require v5 pack meta for all mods." } diff --git a/src/main/resources/vex.png b/common/src/main/resources/vex.png similarity index 100% rename from src/main/resources/vex.png rename to common/src/main/resources/vex.png diff --git a/fabric/.gitignore b/fabric/.gitignore new file mode 100644 index 0000000..8673c0d --- /dev/null +++ b/fabric/.gitignore @@ -0,0 +1,21 @@ +# gradle +.gradle/ +build/ +out/ +classes/ + +# idea +.idea/ +*.iml +*.ipr +*.iws + +# vscode +.settings/ +.vscode/ +bin/ +.classpath +.project + +# fabric +run/ diff --git a/fabric/build.gradle b/fabric/build.gradle new file mode 100644 index 0000000..6e63dfa --- /dev/null +++ b/fabric/build.gradle @@ -0,0 +1,74 @@ +plugins { + id 'fabric-loom' version '0.4-SNAPSHOT' +} + +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 + +sourceSets { + main { + java { + srcDir 'src/main/java' + srcDir '../common/src/main/java' + } + resources { + srcDir 'src/main/resources' + srcDir '../common/src/main/resources' + } + } +} + +archivesBaseName = project.hasProperty("outputJarBaseName") ? project.outputJarBaseName : "fabric" + +minecraft { +} + +repositories { + maven { url 'https://jitpack.io' } +} + +dependencies { + //to change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modCompile "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modCompile "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + + modCompile "com.github.Chocohead:Fabric-ASM:${project.fabric_asm_version}" + include "com.github.Chocohead:Fabric-ASM:${project.fabric_asm_version}" + +} + +processResources { + inputs.property "version", project.version + + from(sourceSets.main.resources.srcDirs) { + include "fabric.mod.json" + expand "version": project.version + } + + from(sourceSets.main.resources.srcDirs) { + exclude "fabric.mod.json" + } +} + +// ensure that the encoding is set to UTF-8, no matter what the system default is +// this fixes some edge cases with special characters not displaying correctly +// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} + +// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task +// if it is present. +// If you remove this task, sources will not be generated. +task sourcesJar(type: Jar, dependsOn: classes) { + classifier = "sources" + from sourceSets.main.allSource +} + +jar { + from "../LICENSE" +} diff --git a/fabric/gradle.properties b/fabric/gradle.properties new file mode 100644 index 0000000..6cca140 --- /dev/null +++ b/fabric/gradle.properties @@ -0,0 +1,13 @@ +# Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G + +# Fabric Properties + # check these on https://fabricmc.net/use + minecraft_version=1.16.1 + yarn_mappings=1.16.1+build.21 + loader_version=0.8.8+build.203 + +# Dependencies + # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api + fabric_version=0.14.1+build.372-1.16 + fabric_asm_version=v2.0 \ No newline at end of file diff --git a/fabric/gradle/wrapper/gradle-wrapper.jar b/fabric/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..5c2d1cf016b3885f6930543d57b744ea8c220a1a GIT binary patch literal 55616 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 \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# 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 + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, 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" "$@" diff --git a/fabric/gradlew.bat b/fabric/gradlew.bat new file mode 100644 index 0000000..e95643d --- /dev/null +++ b/fabric/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +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= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/main/resources/data/vanillaexperience/.test b/fabric/logs/debug.log similarity index 100% rename from src/main/resources/data/vanillaexperience/.test rename to fabric/logs/debug.log diff --git a/fabric/logs/latest.log b/fabric/logs/latest.log new file mode 100644 index 0000000..e69de29 diff --git a/fabric/settings.gradle b/fabric/settings.gradle new file mode 100644 index 0000000..5b60df3 --- /dev/null +++ b/fabric/settings.gradle @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + jcenter() + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + gradlePluginPortal() + } +} diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/VanillaExperience.java b/fabric/src/main/java/com/vanilla/experience/fabric/VanillaExperience.java new file mode 100644 index 0000000..259911f --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/VanillaExperience.java @@ -0,0 +1,20 @@ +package com.vanilla.experience.fabric; + +import com.vanilla.experience.fabric.enhancedbonemeal.EnhancedBoneMeal; +import com.vanilla.experience.fabric.enhancedbonemeal.EnhancedBoneMealDispenserBehaviour; +import com.vanilla.experience.fabric.enhancedseeds.EnhancedSeeds; +import com.vanilla.experience.fabric.enhancedseeds.EnhancedSeedsDispenserBehaviour; +import com.vanilla.experience.HelloMessage; +import net.fabricmc.api.ModInitializer; + +public class VanillaExperience implements ModInitializer { + + @Override + public void onInitialize() { + new HelloMessage(); + new EnhancedBoneMeal(); + new EnhancedSeeds(); + new EnhancedBoneMealDispenserBehaviour(); + new EnhancedSeedsDispenserBehaviour(); + } +} diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/enhancedberries/mixin/SweetBerryBushBlockMixin.java b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedberries/mixin/SweetBerryBushBlockMixin.java new file mode 100644 index 0000000..16bea3c --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedberries/mixin/SweetBerryBushBlockMixin.java @@ -0,0 +1,28 @@ +package com.vanilla.experience.fabric.enhancedberries.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.PlantBlock; +import net.minecraft.block.SweetBerryBushBlock; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(SweetBerryBushBlock.class) +public abstract class SweetBerryBushBlockMixin extends PlantBlock { + protected SweetBerryBushBlockMixin(Settings settings) { super(settings); } + + @Inject(method = "onEntityCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;damage(Lnet/minecraft/entity/damage/DamageSource;F)Z"), cancellable = true) + private void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity, CallbackInfo ci) { + if (entity instanceof PlayerEntity) { + PlayerEntity player = (PlayerEntity) entity; + if(!player.getEquippedStack(EquipmentSlot.FEET).isEmpty() && !player.getEquippedStack(EquipmentSlot.LEGS).isEmpty()) ci.cancel(); + } + if (entity.isSneaking()) ci.cancel(); + } +} \ No newline at end of file diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/enhancedbonemeal/EnhancedBoneMeal.java b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedbonemeal/EnhancedBoneMeal.java new file mode 100644 index 0000000..bc49dc2 --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedbonemeal/EnhancedBoneMeal.java @@ -0,0 +1,67 @@ +package com.vanilla.experience.fabric.enhancedbonemeal; + +import net.fabricmc.fabric.api.event.player.UseBlockCallback; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class EnhancedBoneMeal implements UseBlockCallback { + + public EnhancedBoneMeal(){ + UseBlockCallback.EVENT.register(this); + } + + @Override + public ActionResult interact(PlayerEntity player, World world, Hand hand, BlockHitResult block) { + ItemStack stack = player.getStackInHand(hand); + + if(stack.getItem().equals(Items.BONE_MEAL)){ + BlockPos blockPos = block.getBlockPos(); + BlockState blockState = world.getBlockState(blockPos); + Block currentBlock = blockState.getBlock(); + + if(currentBlock.equals(Blocks.CACTUS) || currentBlock.equals((Blocks.SUGAR_CANE))) { + for(int y = blockPos.getY(); y <= 256; y++) { + BlockPos upperPos = new BlockPos(blockPos.getX(), y, blockPos.getZ()); + Block upperBlock = world.getBlockState(upperPos).getBlock(); + if(upperBlock.equals(Blocks.AIR)) { + world.setBlockState(upperPos, currentBlock.getDefaultState()); + if (!world.isClient) { + world.syncWorldEvent(2005, upperPos, 0); + world.syncWorldEvent(2005, upperPos.up(), 0); + } + if(!player.isCreative()) + stack.decrement(1); + return ActionResult.SUCCESS; + } + } + } + if(currentBlock.equals(Blocks.VINE)) { + for(int y = blockPos.getY(); y > 0; y--) { + BlockPos downPos = new BlockPos(blockPos.getX(), y, blockPos.getZ()); + Block downBlock = world.getBlockState(downPos).getBlock(); + if(downBlock.equals(Blocks.AIR)) { + world.setBlockState(downPos, currentBlock.getDefaultState()); + if (!world.isClient) { + world.syncWorldEvent(2005, downPos, 0); + world.syncWorldEvent(2005, downPos.down(), 0); + } + if(!player.isCreative()) + stack.decrement(1); + return ActionResult.SUCCESS; + } + } + } + + } + return ActionResult.PASS; + } +} diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java new file mode 100644 index 0000000..2672e42 --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java @@ -0,0 +1,67 @@ +package com.vanilla.experience.fabric.enhancedbonemeal; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.DispenserBlock; +import net.minecraft.block.dispenser.FallibleItemDispenserBehavior; +import net.minecraft.item.BoneMealItem; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPointer; +import net.minecraft.util.math.BlockPos; + +public class EnhancedBoneMealDispenserBehaviour extends FallibleItemDispenserBehavior { + + public EnhancedBoneMealDispenserBehaviour() { + DispenserBlock.registerBehavior(Items.BONE_MEAL, this); + } + + protected ItemStack dispenseSilently(BlockPointer block, ItemStack stack) { + this.setSuccess(true); + ServerWorld world = (ServerWorld) block.getWorld(); + BlockPos blockPos = block.getBlockPos().offset(block.getBlockState().get(DispenserBlock.FACING)); + if (BoneMealItem.useOnFertilizable(stack, world, blockPos) || BoneMealItem.useOnGround(stack, world, blockPos, null)) { + if (!world.isClient) { + world.syncWorldEvent(2005, blockPos, 0); + } + } else { + BlockState blockState = world.getBlockState(blockPos); + Block currentBlock = blockState.getBlock(); + + if(currentBlock.equals(Blocks.SUGAR_CANE) || currentBlock.equals(Blocks.CACTUS)) { + for(int y = blockPos.getY(); y <= 256; y++) { + BlockPos upperPos = new BlockPos(blockPos.getX(), y, blockPos.getZ()); + Block upperBlock = world.getBlockState(upperPos).getBlock(); + if(upperBlock.equals(Blocks.AIR)) { + world.setBlockState(upperPos, blockState.getBlock().getDefaultState()); + if (!world.isClient) { + world.syncWorldEvent(2005, upperPos, 0); + world.syncWorldEvent(2005, upperPos.up(), 0); + } + stack.decrement(1); + break; + } + } + } else if(blockState.getBlock().equals(Blocks.VINE)) { + for(int y = blockPos.getY(); y > 0; y--) { + BlockPos downPos = new BlockPos(blockPos.getX(), y, blockPos.getZ()); + Block downBlock = world.getBlockState(downPos).getBlock(); + if (downBlock.equals(Blocks.AIR)) { + world.setBlockState(downPos, blockState.getBlock().getDefaultState()); + if (!world.isClient) { + world.syncWorldEvent(2005, downPos, 0); + world.syncWorldEvent(2005, downPos.down(), 0); + } + stack.decrement(1); + break; + } + } + } else { + this.setSuccess(false); + } + } + return stack; + } +} \ No newline at end of file diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/enhancedseeds/EnhancedSeeds.java b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedseeds/EnhancedSeeds.java new file mode 100644 index 0000000..a815e76 --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedseeds/EnhancedSeeds.java @@ -0,0 +1,73 @@ +package com.vanilla.experience.fabric.enhancedseeds; + +import net.fabricmc.fabric.api.event.player.UseBlockCallback; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.TallPlantBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class EnhancedSeeds implements UseBlockCallback { + + public EnhancedSeeds(){ + UseBlockCallback.EVENT.register(this); + } + + @Override + public ActionResult interact(PlayerEntity player, World world, Hand hand, BlockHitResult block) { + ItemStack stack = player.getStackInHand(hand); + + if(stack.getItem().equals(Items.WHEAT_SEEDS)){ + BlockPos blockPos = block.getBlockPos(); + BlockState blockState = world.getBlockState(blockPos); + Block currentBlock = blockState.getBlock(); + + if(currentBlock.equals(Blocks.DIRT)) { + world.setBlockState(blockPos, Blocks.GRASS_BLOCK.getDefaultState()); + if(!player.isCreative()) + stack.decrement(1); + return ActionResult.SUCCESS; + } else if(currentBlock.equals(Blocks.GRASS_BLOCK)) { + BlockPos upperPos = blockPos.up(); + Block upperBlock = world.getBlockState(upperPos).getBlock(); + if(upperBlock.equals(Blocks.AIR)) { + world.setBlockState(upperPos, Blocks.GRASS.getDefaultState()); + if(!player.isCreative()) + stack.decrement(1); + return ActionResult.SUCCESS; + } else if(upperBlock.equals(Blocks.GRASS)) { + if(upgrade(world, upperPos)) { + if(!player.isCreative()) + stack.decrement(1); + return ActionResult.SUCCESS; + } + } + } else if(currentBlock.equals(Blocks.GRASS)) { + if(upgrade(world, blockPos)) { + if(!player.isCreative()) + stack.decrement(1); + return ActionResult.SUCCESS; + } + } + + } + return ActionResult.PASS; + } + + public boolean upgrade(World world, BlockPos pos) { + TallPlantBlock blockDoublePlant = (TallPlantBlock) Blocks.TALL_GRASS; + + if(world.isAir(pos.up())) { + blockDoublePlant.placeAt(world, pos, 2); + return true; + } + return false; + } +} diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/enhancedseeds/EnhancedSeedsDispenserBehaviour.java b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedseeds/EnhancedSeedsDispenserBehaviour.java new file mode 100644 index 0000000..825d937 --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedseeds/EnhancedSeedsDispenserBehaviour.java @@ -0,0 +1,58 @@ +package com.vanilla.experience.fabric.enhancedseeds; + +import net.minecraft.block.*; +import net.minecraft.block.dispenser.FallibleItemDispenserBehavior; +import net.minecraft.item.BoneMealItem; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.math.BlockPointer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class EnhancedSeedsDispenserBehaviour extends FallibleItemDispenserBehavior { + + public EnhancedSeedsDispenserBehaviour() { + DispenserBlock.registerBehavior(Items.WHEAT_SEEDS, this); + } + + protected ItemStack dispenseSilently(BlockPointer block, ItemStack stack) { + this.setSuccess(true); + ServerWorld world = (ServerWorld) block.getWorld(); + BlockPos blockPos = block.getBlockPos().offset(block.getBlockState().get(DispenserBlock.FACING)); + BlockState blockState = world.getBlockState(blockPos); + Block currentBlock = blockState.getBlock(); + + if(currentBlock.equals(Blocks.DIRT)) { + world.setBlockState(blockPos, Blocks.GRASS_BLOCK.getDefaultState()); + stack.decrement(1); + } else if(currentBlock.equals(Blocks.GRASS_BLOCK)) { + BlockPos upperPos = blockPos.up(); + Block upperBlock = world.getBlockState(upperPos).getBlock(); + if(upperBlock.equals(Blocks.AIR)) { + world.setBlockState(upperPos, Blocks.GRASS.getDefaultState()); + stack.decrement(1); + } else if(upperBlock.equals(Blocks.GRASS)) { + if(upgrade(world, upperPos)) + stack.decrement(1); + } + } else if(currentBlock.equals(Blocks.GRASS)) { + if(upgrade(world, blockPos)) + stack.decrement(1); + } else { + this.setSuccess(false); + } + + return stack; + } + + public boolean upgrade(World world, BlockPos pos) { + TallPlantBlock blockDoublePlant = (TallPlantBlock) Blocks.TALL_GRASS; + + if(world.isAir(pos.up())) { + blockDoublePlant.placeAt(world, pos, 2); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/enhancedtotem/mixin/LivingEntityMixin.java b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedtotem/mixin/LivingEntityMixin.java new file mode 100644 index 0000000..47c0413 --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/enhancedtotem/mixin/LivingEntityMixin.java @@ -0,0 +1,61 @@ +package com.vanilla.experience.fabric.enhancedtotem.mixin; + +import net.minecraft.advancement.criterion.Criteria; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.entity.effect.StatusEffects; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.stat.Stats; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(LivingEntity.class) +public abstract class LivingEntityMixin { + + @Inject(method = "tryUseTotem", at = @At("HEAD")) + private void tryUseTotem(DamageSource source, CallbackInfoReturnable info) { + LivingEntity livingEntity = ((LivingEntity)(Object)this); + + if(livingEntity instanceof PlayerEntity) { + PlayerEntity player = (PlayerEntity) livingEntity; + + ItemStack itemStack = null; + + PlayerInventory inventory = player.inventory; + + for(int i = 0; i < inventory.size(); i++) { + ItemStack stack = inventory.getStack(i); + if (stack.getItem().equals(Items.TOTEM_OF_UNDYING)) { + itemStack = stack; + break; + } + } + + if(itemStack != null) { + if (player instanceof ServerPlayerEntity) { + ServerPlayerEntity serverPlayerEntity = (ServerPlayerEntity)player; + serverPlayerEntity.incrementStat(Stats.USED.getOrCreateStat(Items.TOTEM_OF_UNDYING)); + Criteria.USED_TOTEM.trigger(serverPlayerEntity, itemStack); + } + + itemStack.decrement(1); + + player.setHealth(1.0F); + player.clearStatusEffects(); + player.addStatusEffect(new StatusEffectInstance(StatusEffects.REGENERATION, 900, 1)); + player.addStatusEffect(new StatusEffectInstance(StatusEffects.ABSORPTION, 100, 1)); + player.addStatusEffect(new StatusEffectInstance(StatusEffects.FIRE_RESISTANCE, 800, 2)); // 1.16.2 + player.world.sendEntityStatus(player, (byte)35); + + info.setReturnValue(true); + } + } + } +} \ No newline at end of file diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/utils/MixinLoader.java b/fabric/src/main/java/com/vanilla/experience/fabric/utils/MixinLoader.java new file mode 100644 index 0000000..68b54cc --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/utils/MixinLoader.java @@ -0,0 +1,24 @@ +package com.vanilla.experience.fabric.utils; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.spongepowered.asm.mixin.Mixins; + +public class MixinLoader implements Runnable { + private static final Logger LOGGER = LogManager.getLogger(); + + @Override + public void run() { + LOGGER.info("[VEX] Patching EnhancedTotem with Fabric Mixin."); + Mixins.addConfiguration("mixin/fabric/enhancedtotem.mixins.json"); + + if (VexUtils.isZeroTickPatched()) { + LOGGER.info("[VEX] Unpatching ZeroTick with Fabric Mixin."); + Mixins.addConfiguration("mixin/fabric/zerotickunpatch.mixins.json"); + } + if (VexUtils.isWitherRosesSpawnPatched()) { + LOGGER.info("[VEX] Unpatching Wither Rose spawning with Fabric Mixin."); + Mixins.addConfiguration("mixin/fabric/witherrosesunpatch.mixins.json"); + } + } +} diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/utils/VexUtils.java b/fabric/src/main/java/com/vanilla/experience/fabric/utils/VexUtils.java new file mode 100644 index 0000000..1234bd5 --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/utils/VexUtils.java @@ -0,0 +1,14 @@ +package com.vanilla.experience.fabric.utils; + +import net.minecraft.SharedConstants; +import com.vanilla.experience.CommonUtils; + +public class VexUtils { + public static boolean isZeroTickPatched() { + return SharedConstants.getGameVersion().getWorldVersion() >= CommonUtils.zeroTickVersionPatch; + } + + public static boolean isWitherRosesSpawnPatched() { + return SharedConstants.getGameVersion().getWorldVersion() >= CommonUtils.witherRosesVersionPatch; + } +} diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/witherrosesunpatch/mixin/EntityTypeMixin.java b/fabric/src/main/java/com/vanilla/experience/fabric/witherrosesunpatch/mixin/EntityTypeMixin.java new file mode 100644 index 0000000..3eb7508 --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/witherrosesunpatch/mixin/EntityTypeMixin.java @@ -0,0 +1,17 @@ +package com.vanilla.experience.fabric.witherrosesunpatch.mixin; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.entity.EntityType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(EntityType.class) +public class EntityTypeMixin { + + @Redirect(method = "method_29496", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;isOf(Lnet/minecraft/block/Block;)Z", ordinal = 2)) + private boolean restoreWitherRoseSpawning(BlockState blockState, Block block) { + return false; // return false to method that checks if is inside a Whiter Rose + } +} \ No newline at end of file diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickAbstractPlantStemBlock.java b/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickAbstractPlantStemBlock.java new file mode 100644 index 0000000..b33586c --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickAbstractPlantStemBlock.java @@ -0,0 +1,27 @@ +package com.vanilla.experience.fabric.zerotickunpatch.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.AbstractPlantStemBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.server.world.ServerWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +// this abstracts Kelp, TwistingVines and WeepingVines +@Mixin(AbstractPlantStemBlock.class) +public class ZeroTickAbstractPlantStemBlock { + @Shadow + public void randomTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random) {} + + @Inject(at = @At("TAIL"), method = "scheduledTick") + public void scheduledTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random, CallbackInfo info) { + if(!world.isAir(pos.down())) { + this.randomTick(state, world, pos, random); + } + } +} \ No newline at end of file diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickBambooBlock.java b/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickBambooBlock.java new file mode 100644 index 0000000..a18a4d8 --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickBambooBlock.java @@ -0,0 +1,31 @@ +package com.vanilla.experience.fabric.zerotickunpatch.mixin; + +import net.minecraft.block.BambooBlock; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.server.world.ServerWorld; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +@Mixin(BambooBlock.class) +public class ZeroTickBambooBlock { + private static final Logger LOGGER = LogManager.getLogger(); + + @Shadow + public void randomTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random) {} + + @Inject(at = @At("TAIL"), method = "scheduledTick") + public void scheduledTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random, CallbackInfo info) { + if(!world.isAir(pos.down())) { + this.randomTick(state, world, pos, random); + } + } + +} \ No newline at end of file diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickCactusBlock.java b/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickCactusBlock.java new file mode 100644 index 0000000..176fd53 --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickCactusBlock.java @@ -0,0 +1,26 @@ +package com.vanilla.experience.fabric.zerotickunpatch.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.CactusBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.server.world.ServerWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +@Mixin(CactusBlock.class) +public class ZeroTickCactusBlock { + @Shadow + public void randomTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random) {} + + @Inject(at = @At("TAIL"), method = "scheduledTick") + public void scheduledTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random, CallbackInfo info) { + if(!world.isAir(pos.down())) { + this.randomTick(state, world, pos, random); + } + } +} \ No newline at end of file diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickChorusFlowerBlock.java b/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickChorusFlowerBlock.java new file mode 100644 index 0000000..8217806 --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickChorusFlowerBlock.java @@ -0,0 +1,26 @@ +package com.vanilla.experience.fabric.zerotickunpatch.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.ChorusFlowerBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.server.world.ServerWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +@Mixin(ChorusFlowerBlock.class) +public class ZeroTickChorusFlowerBlock { + @Shadow + public void randomTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random) {} + + @Inject(at = @At("TAIL"), method = "scheduledTick") + public void scheduledTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random, CallbackInfo info) { + if(!world.isAir(pos.down())) { + this.randomTick(state, world, pos, random); + } + } +} \ No newline at end of file diff --git a/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickSugarCaneBlock.java b/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickSugarCaneBlock.java new file mode 100644 index 0000000..437669d --- /dev/null +++ b/fabric/src/main/java/com/vanilla/experience/fabric/zerotickunpatch/mixin/ZeroTickSugarCaneBlock.java @@ -0,0 +1,26 @@ +package com.vanilla.experience.fabric.zerotickunpatch.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.SugarCaneBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.server.world.ServerWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +@Mixin(SugarCaneBlock.class) +public class ZeroTickSugarCaneBlock { + @Shadow + public void randomTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random) {} + + @Inject(at = @At("TAIL"), method = "scheduledTick") + public void tick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random, CallbackInfo info) { + if(!world.isAir(pos.down())) { + this.randomTick(state, world, pos, random); + } + } +} \ No newline at end of file diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..ba9e810 --- /dev/null +++ b/fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,37 @@ +{ + "schemaVersion": 1, + "id": "vanillaexperience", + "version": "${version}", + + "name": "Vanilla Experience", + "description": "Thanks for downloading Vanilla Experience for Fabric!", + "authors": [ + "AugustoResende" + ], + "contact": { + "homepage": "https://mods.augustoresende.com/vanillaexperience/", + "sources": "https://mods.augustoresende.com/vanillaexperience/source", + "issues": "https://mods.augustoresende.com/vanillaexperience/issues" + }, + + "license": "WTFPL", + "icon": "vex.png", + + "environment": "*", + "entrypoints": { + "mm:early_risers": [ + "com.vanilla.experience.fabric.utils.MixinLoader" + ], + "main": [ + "com.vanilla.experience.fabric.VanillaExperience" + ] + }, + "mixins": [], + + "depends": { + "fabricloader": ">=0.7.2", + "fabric": "*", + "minecraft": "1.16.x", + "mm": ">=2.0" + } +} diff --git a/fabric/src/main/resources/mixin/fabric/enhancedtotem.mixins.json b/fabric/src/main/resources/mixin/fabric/enhancedtotem.mixins.json new file mode 100644 index 0000000..5a7d85e --- /dev/null +++ b/fabric/src/main/resources/mixin/fabric/enhancedtotem.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "package": "com.vanilla.experience.fabric.enhancedtotem.mixin", + "compatibilityLevel": "JAVA_8", + "refmap": "vanillaexperience-1.16.1-refmap.json", + "mixins": [ + "LivingEntityMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "minVersion": "0.8" +} \ No newline at end of file diff --git a/fabric/src/main/resources/mixin/fabric/witherrosesunpatch.mixins.json b/fabric/src/main/resources/mixin/fabric/witherrosesunpatch.mixins.json new file mode 100644 index 0000000..f294114 --- /dev/null +++ b/fabric/src/main/resources/mixin/fabric/witherrosesunpatch.mixins.json @@ -0,0 +1,13 @@ +{ + "required": true, + "package": "com.vanilla.experience.fabric.witherrosesunpatch.mixin", + "compatibilityLevel": "JAVA_8", + "refmap": "vanillaexperience-1.16.1-refmap.json", + "mixins": [ + "EntityTypeMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "minVersion": "0.8" +} \ No newline at end of file diff --git a/fabric/src/main/resources/mixin/fabric/zerotickunpatch.mixins.json b/fabric/src/main/resources/mixin/fabric/zerotickunpatch.mixins.json new file mode 100644 index 0000000..fcebf80 --- /dev/null +++ b/fabric/src/main/resources/mixin/fabric/zerotickunpatch.mixins.json @@ -0,0 +1,16 @@ +{ + "required": true, + "package": "com.vanilla.experience.fabric.zerotickunpatch.mixin", + "compatibilityLevel": "JAVA_8", + "refmap": "vanillaexperience-1.16.1-refmap.json", + "mixins": [ + "ZeroTickAbstractPlantStemBlock", + "ZeroTickBambooBlock", + "ZeroTickCactusBlock", + "ZeroTickChorusFlowerBlock", + "ZeroTickSugarCaneBlock" + ], + "injectors": { + "defaultRequire": 1 + } +} diff --git a/forge/.gitignore b/forge/.gitignore new file mode 100644 index 0000000..8673c0d --- /dev/null +++ b/forge/.gitignore @@ -0,0 +1,21 @@ +# gradle +.gradle/ +build/ +out/ +classes/ + +# idea +.idea/ +*.iml +*.ipr +*.iws + +# vscode +.settings/ +.vscode/ +bin/ +.classpath +.project + +# fabric +run/ diff --git a/forge/build.gradle b/forge/build.gradle new file mode 100644 index 0000000..d2c8a98 --- /dev/null +++ b/forge/build.gradle @@ -0,0 +1,102 @@ +buildscript { + repositories { + maven { url = 'https://files.minecraftforge.net/maven' } + jcenter() + mavenCentral() + maven { url = 'https://dist.creeper.host/Sponge/maven' } + } + dependencies { + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true + classpath group: 'org.spongepowered', name:'mixingradle', version: '0.7-SNAPSHOT' + } +} +apply plugin: 'net.minecraftforge.gradle' +apply plugin: 'org.spongepowered.mixin' + +sourceSets { + main { + java { + srcDir 'src/main/java' + srcDir '../common/src/main/java' + } + resources { + srcDir 'src/main/resources' + srcDir '../common/src/main/resources' + } + } +} + +archivesBaseName = project.hasProperty("outputJarBaseName") ? project.outputJarBaseName : "${mod_id}-${mod_version}-${mc_version}" + +minecraft { + + mappings channel: 'snapshot', version: "${forge_mappings}" + + runs { + client { + property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + property 'forge.logging.console.level', 'debug' + + workingDirectory project.file('run').canonicalPath + + mods { + vanillaexperience { + source sourceSets.main + } + } + } + + server { + property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + property 'forge.logging.console.level', 'debug' + + workingDirectory project.file('run').canonicalPath + + mods { + vanillaexperience { + source sourceSets.main + } + } + } + } +} + +repositories { + maven { url = 'https://files.minecraftforge.net/maven' } + jcenter() + mavenCentral() + maven { url='https://dist.creeper.host/Sponge/maven' } + flatDir { + dirs 'libs' + } +} + +dependencies { + minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}" + + compile 'org.spongepowered:mixin:0.8.1-SNAPSHOT' +} + +jar { + inputs.property "version", project.version + + manifest { + attributes([ + "Specification-Title": "${mod_id}", + "Specification-Vendor": "${mod_id}", + "Specification-Version": "${project.version}", + "Implementation-Title": "${mod_id}", + "Implementation-Version": "${project.version}", + "Implementation-Vendor": "${mod_id}", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), + "MixinConnector": "com.vanilla.experience.forge.utils.MixinLoader" + ]) + } +} + +jar.finalizedBy('reobfJar') + +task deobfJar(type: Jar) { + from sourceSets.main.output + classifier = 'deobf' +} diff --git a/forge/gradle.properties b/forge/gradle.properties new file mode 100644 index 0000000..d6c0096 --- /dev/null +++ b/forge/gradle.properties @@ -0,0 +1,9 @@ +org.gradle.jvmargs=-Xmx4G +org.gradle.daemon=false + +mod_version=0.1.6 +mod_id=vanillaexperience +mc_version=1.16.1 +forge_version=32.0.59 +forge_mappings=20200707-1.16.1 +curseforge_id=393896 \ No newline at end of file diff --git a/forge/gradle/wrapper/gradle-wrapper.jar b/forge/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..94336fcae912db8a11d55634156fa011f4686124 GIT binary patch literal 56177 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 i;x|p)^~-yfPOPa3(|vBayXKz \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# 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 + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, 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" "$@" diff --git a/forge/gradlew.bat b/forge/gradlew.bat new file mode 100644 index 0000000..e95643d --- /dev/null +++ b/forge/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +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= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/forge/logs/debug.log b/forge/logs/debug.log new file mode 100644 index 0000000..e69de29 diff --git a/forge/logs/latest.log b/forge/logs/latest.log new file mode 100644 index 0000000..e69de29 diff --git a/forge/src/main/java/com/vanilla/experience/forge/VanillaExperience.java b/forge/src/main/java/com/vanilla/experience/forge/VanillaExperience.java new file mode 100644 index 0000000..2260905 --- /dev/null +++ b/forge/src/main/java/com/vanilla/experience/forge/VanillaExperience.java @@ -0,0 +1,35 @@ +package com.vanilla.experience.forge; + +import com.vanilla.experience.forge.enhancedberries.*; +import com.vanilla.experience.forge.enhancedbonemeal.*; +import com.vanilla.experience.forge.enhancedseeds.*; +import com.vanilla.experience.forge.enhancedtotem.*; +import com.vanilla.experience.forge.utils.OverrideLoader; +import com.vanilla.experience.forge.utils.VexUtils; +import com.vanilla.experience.HelloMessage; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Mod("vanillaexperience") +public class VanillaExperience { + private static final Logger LOGGER = LogManager.getLogger(); + + public VanillaExperience() { + new HelloMessage(); + + new OverrideLoader(VexUtils.mixinExists()); + + new EnhancedBoneMealDispenserBehaviour(); + new EnhancedSeedsDispenserBehaviour(); + + FMLJavaModLoadingContext.get().getModEventBus().addListener((FMLLoadCompleteEvent e) -> { + new EnhancedBoneMeal(); + new EnhancedSeeds(); + new EnhancedBerries(); + new EnhancedTotem(); + }); + } +} \ No newline at end of file diff --git a/src/main/java/com/vanilla/experience/enhancedberries/EnhancedBerries.java b/forge/src/main/java/com/vanilla/experience/forge/enhancedberries/EnhancedBerries.java similarity index 91% rename from src/main/java/com/vanilla/experience/enhancedberries/EnhancedBerries.java rename to forge/src/main/java/com/vanilla/experience/forge/enhancedberries/EnhancedBerries.java index 63f2060..ef1b097 100644 --- a/src/main/java/com/vanilla/experience/enhancedberries/EnhancedBerries.java +++ b/forge/src/main/java/com/vanilla/experience/forge/enhancedberries/EnhancedBerries.java @@ -1,4 +1,4 @@ -package com.vanilla.experience.enhancedberries; +package com.vanilla.experience.forge.enhancedberries; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.EquipmentSlotType; diff --git a/src/main/java/com/vanilla/experience/enhancedbonemeal/EnhancedBoneMeal.java b/forge/src/main/java/com/vanilla/experience/forge/enhancedbonemeal/EnhancedBoneMeal.java similarity index 90% rename from src/main/java/com/vanilla/experience/enhancedbonemeal/EnhancedBoneMeal.java rename to forge/src/main/java/com/vanilla/experience/forge/enhancedbonemeal/EnhancedBoneMeal.java index 684314b..b903b6e 100644 --- a/src/main/java/com/vanilla/experience/enhancedbonemeal/EnhancedBoneMeal.java +++ b/forge/src/main/java/com/vanilla/experience/forge/enhancedbonemeal/EnhancedBoneMeal.java @@ -1,18 +1,23 @@ -package com.vanilla.experience.enhancedbonemeal; +package com.vanilla.experience.forge.enhancedbonemeal; import net.minecraft.block.*; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.BonemealEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @EventBusSubscriber public class EnhancedBoneMeal { + + public EnhancedBoneMeal(){ + MinecraftForge.EVENT_BUS.register(this); + } + @SubscribeEvent public void onBoneMeal(BonemealEvent e) { diff --git a/src/main/java/com/vanilla/experience/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java b/forge/src/main/java/com/vanilla/experience/forge/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java similarity index 90% rename from src/main/java/com/vanilla/experience/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java rename to forge/src/main/java/com/vanilla/experience/forge/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java index 05d2a0a..0dab483 100644 --- a/src/main/java/com/vanilla/experience/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java +++ b/forge/src/main/java/com/vanilla/experience/forge/enhancedbonemeal/EnhancedBoneMealDispenserBehaviour.java @@ -1,4 +1,4 @@ -package com.vanilla.experience.enhancedbonemeal; +package com.vanilla.experience.forge.enhancedbonemeal; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -8,12 +8,17 @@ import net.minecraft.dispenser.IBlockSource; import net.minecraft.item.BoneMealItem; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class EnhancedBoneMealDispenserBehaviour extends DefaultDispenseItemBehavior -{ +public class EnhancedBoneMealDispenserBehaviour extends DefaultDispenseItemBehavior { + + public EnhancedBoneMealDispenserBehaviour(){ + DispenserBlock.registerDispenseBehavior(Items.BONE_MEAL, this); + } + @Override public ItemStack dispenseStack(IBlockSource source, ItemStack stack) { World world = source.getWorld(); diff --git a/src/main/java/com/vanilla/experience/enhancedseeds/EnhancedSeeds.java b/forge/src/main/java/com/vanilla/experience/forge/enhancedseeds/EnhancedSeeds.java similarity index 87% rename from src/main/java/com/vanilla/experience/enhancedseeds/EnhancedSeeds.java rename to forge/src/main/java/com/vanilla/experience/forge/enhancedseeds/EnhancedSeeds.java index 9d7315c..98f6aac 100644 --- a/src/main/java/com/vanilla/experience/enhancedseeds/EnhancedSeeds.java +++ b/forge/src/main/java/com/vanilla/experience/forge/enhancedseeds/EnhancedSeeds.java @@ -1,4 +1,4 @@ -package com.vanilla.experience.enhancedseeds; +package com.vanilla.experience.forge.enhancedseeds; import net.minecraft.block.Block; import net.minecraft.block.Blocks; @@ -8,12 +8,18 @@ import net.minecraft.item.Items; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @EventBusSubscriber public class EnhancedSeeds { + + public EnhancedSeeds(){ + MinecraftForge.EVENT_BUS.register(this); + } + @SubscribeEvent public void onDirtGrassClick(RightClickBlock e) { World world = e.getWorld(); @@ -35,7 +41,7 @@ public void onDirtGrassClick(RightClickBlock e) { if(!player.isCreative()) hand.shrink(1); } else if(upperBlock.equals(Blocks.GRASS)) { - if(upgrade(world, blockPos) && !player.isCreative()) + if(upgrade(world, blockPos.up()) && !player.isCreative()) hand.shrink(1); } } else if(currentBlock.equals(Blocks.GRASS)) { diff --git a/src/main/java/com/vanilla/experience/enhancedseeds/EnhancedSeedsDispenserBehaviour.java b/forge/src/main/java/com/vanilla/experience/forge/enhancedseeds/EnhancedSeedsDispenserBehaviour.java similarity index 87% rename from src/main/java/com/vanilla/experience/enhancedseeds/EnhancedSeedsDispenserBehaviour.java rename to forge/src/main/java/com/vanilla/experience/forge/enhancedseeds/EnhancedSeedsDispenserBehaviour.java index 486ae5e..b023ae9 100644 --- a/src/main/java/com/vanilla/experience/enhancedseeds/EnhancedSeedsDispenserBehaviour.java +++ b/forge/src/main/java/com/vanilla/experience/forge/enhancedseeds/EnhancedSeedsDispenserBehaviour.java @@ -1,15 +1,20 @@ -package com.vanilla.experience.enhancedseeds; +package com.vanilla.experience.forge.enhancedseeds; import net.minecraft.block.*; import net.minecraft.dispenser.DefaultDispenseItemBehavior; import net.minecraft.dispenser.IBlockSource; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class EnhancedSeedsDispenserBehaviour extends DefaultDispenseItemBehavior -{ +public class EnhancedSeedsDispenserBehaviour extends DefaultDispenseItemBehavior { + + public EnhancedSeedsDispenserBehaviour(){ + DispenserBlock.registerDispenseBehavior(Items.WHEAT_SEEDS, this); + } + @Override public ItemStack dispenseStack(IBlockSource source, ItemStack stack) { Direction facing = source.getBlockState().get(DispenserBlock.FACING); diff --git a/src/main/java/com/vanilla/experience/enhancedtotem/EnhancedTotem.java b/forge/src/main/java/com/vanilla/experience/forge/enhancedtotem/EnhancedTotem.java similarity index 86% rename from src/main/java/com/vanilla/experience/enhancedtotem/EnhancedTotem.java rename to forge/src/main/java/com/vanilla/experience/forge/enhancedtotem/EnhancedTotem.java index a748efe..140c279 100644 --- a/src/main/java/com/vanilla/experience/enhancedtotem/EnhancedTotem.java +++ b/forge/src/main/java/com/vanilla/experience/forge/enhancedtotem/EnhancedTotem.java @@ -1,7 +1,6 @@ -package com.vanilla.experience.enhancedtotem; +package com.vanilla.experience.forge.enhancedtotem; import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.client.particle.TotemOfUndyingParticle; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; @@ -12,6 +11,7 @@ import net.minecraft.potion.Effects; import net.minecraft.stats.Stats; import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.living.LivingDeathEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -19,6 +19,10 @@ @EventBusSubscriber public class EnhancedTotem { + public EnhancedTotem(){ + MinecraftForge.EVENT_BUS.register(this); + } + @SubscribeEvent public void onPlayerDeath(LivingDeathEvent e){ Entity entity = e.getEntity(); @@ -38,7 +42,7 @@ public void onPlayerDeath(LivingDeathEvent e){ if(inventory == null); - for (int i = 0; i < inventory.getSizeInventory(); i++) { + for(int i = 0; i < inventory.getSizeInventory(); i++) { ItemStack stack = inventory.getStackInSlot(i); if (stack.getItem().equals(Items.TOTEM_OF_UNDYING)) { itemStack = stack; @@ -48,7 +52,7 @@ public void onPlayerDeath(LivingDeathEvent e){ if(itemStack == null) return; e.setCanceled(true); - if (player instanceof ServerPlayerEntity) { + if(player instanceof ServerPlayerEntity) { ServerPlayerEntity entityPlayer = (ServerPlayerEntity) player; entityPlayer.addStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); CriteriaTriggers.USED_TOTEM.trigger(entityPlayer, itemStack); diff --git a/forge/src/main/java/com/vanilla/experience/forge/utils/MixinLoader.java b/forge/src/main/java/com/vanilla/experience/forge/utils/MixinLoader.java new file mode 100644 index 0000000..cac1aea --- /dev/null +++ b/forge/src/main/java/com/vanilla/experience/forge/utils/MixinLoader.java @@ -0,0 +1,23 @@ +package com.vanilla.experience.forge.utils; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.spongepowered.asm.mixin.Mixins; +import org.spongepowered.asm.mixin.connect.IMixinConnector; + +public class MixinLoader implements IMixinConnector { + + private static final Logger LOGGER = LogManager.getLogger(); + + @Override + public void connect() { + if(VexUtils.isZeroTickPatched()) { + LOGGER.info("[VEX] Unpatching ZeroTick with MixinBootstrap."); + Mixins.addConfiguration("mixin/forge/zerotickunpatch.mixins.json"); + } + if(VexUtils.isWitherRosesSpawnPatched()) { + LOGGER.info("[VEX] Unpatching Wither Rose spawning with MixinBootstrap."); + Mixins.addConfiguration("mixin/forge/witherrosesunpatch.mixins.json"); + } + } +} \ No newline at end of file diff --git a/forge/src/main/java/com/vanilla/experience/forge/utils/OverrideLoader.java b/forge/src/main/java/com/vanilla/experience/forge/utils/OverrideLoader.java new file mode 100644 index 0000000..67d307a --- /dev/null +++ b/forge/src/main/java/com/vanilla/experience/forge/utils/OverrideLoader.java @@ -0,0 +1,66 @@ +package com.vanilla.experience.forge.utils; + +import com.vanilla.experience.forge.witherrosesunpatch.override.WitherRose; +import com.vanilla.experience.forge.zerotickunpatch.override.*; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; +import net.minecraft.item.Items; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@EventBusSubscriber(bus=EventBusSubscriber.Bus.MOD) +public class OverrideLoader { + private static final Logger LOGGER = LogManager.getLogger(); + + public OverrideLoader(boolean mixinExists){ + if(!mixinExists) MinecraftForge.EVENT_BUS.register(this); + } + + @SubscribeEvent + public static void onBlocksRegistry(final RegistryEvent.Register blockRegistryEvent) { + if(VexUtils.isZeroTickPatched()) { + LOGGER.info("[VEX] Unpatching ZeroTick, ignore the 'Potentially Dangerous' messages."); + LOGGER.info("[VEX] If you want to disable the block overrides, please install MixinBootstrap or use Fabric version."); + blockRegistryEvent.getRegistry().register(new ZeroTickBambooBlock(Block.Properties.from(Blocks.BAMBOO)).setRegistryName("minecraft", "bamboo")); + blockRegistryEvent.getRegistry().register(new ZeroTickCactusBlock(Block.Properties.from(Blocks.CACTUS)).setRegistryName("minecraft", "cactus")); + blockRegistryEvent.getRegistry().register(new ZeroTickSugarCaneBlock(Block.Properties.from(Blocks.SUGAR_CANE)).setRegistryName("minecraft", "sugar_cane")); + blockRegistryEvent.getRegistry().register(new ZeroTickKelpTopBlock(Block.Properties.from(Blocks.KELP)).setRegistryName("minecraft", "kelp")); + blockRegistryEvent.getRegistry().register(new ZeroTickWeepingVinesTopBlock(Block.Properties.from(Blocks.WEEPING_VINES)).setRegistryName("minecraft", "weeping_vines")); + blockRegistryEvent.getRegistry().register(new ZeroTickTwistingVinesTopBlock(Block.Properties.from(Blocks.TWISTING_VINES)).setRegistryName("minecraft", "twisting_vines")); + blockRegistryEvent.getRegistry().register(new ZeroTickChorusFlowerBlock(Block.Properties.from(Blocks.CHORUS_FLOWER)).setRegistryName("minecraft", "chorus_flower")); + } + + if(VexUtils.isWitherRosesSpawnPatched()) { + LOGGER.info("[VEX] Unpatching Wither Rose spawning, ignore the 'Potentially Dangerous' messages."); + LOGGER.info("[VEX] If you want to disable the block overrides, please install MixinBootstrap or use Fabric version."); + blockRegistryEvent.getRegistry().register(new WitherRose(Block.Properties.from(Blocks.WITHER_ROSE)).setRegistryName("minecraft", "wither_rose")); + } + } + + @SubscribeEvent + public static void onItemsRegistry(final RegistryEvent.Register itemRegistryEvent) { + if(VexUtils.isZeroTickPatched()) { + LOGGER.info("[VEX] Restoring ZeroTick Block Items"); + LOGGER.info("[VEX] If you want to disable the block overrides, please install MixinBootstrap or use Fabric version."); + itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.BAMBOO, new Item.Properties().group(Items.BAMBOO.getGroup())).setRegistryName("minecraft", "bamboo")); + itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.CACTUS, new Item.Properties().group(Items.CACTUS.getGroup())).setRegistryName("minecraft", "cactus")); + itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.SUGAR_CANE, new Item.Properties().group(Items.SUGAR_CANE.getGroup())).setRegistryName("minecraft", "sugar_cane")); + itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.KELP, new Item.Properties().group(Items.KELP.getGroup())).setRegistryName("minecraft", "kelp")); + itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.WEEPING_VINES, new Item.Properties().group(Items.WEEPING_VINES.getGroup())).setRegistryName("minecraft", "weeping_vines")); + itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.TWISTING_VINES, new Item.Properties().group(Items.TWISTING_VINES.getGroup())).setRegistryName("minecraft", "twisting_vines")); + itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.CHORUS_FLOWER, new Item.Properties().group(Items.CHORUS_FLOWER.getGroup())).setRegistryName("minecraft", "chorus_flower")); + } + + if(VexUtils.isWitherRosesSpawnPatched()) { + LOGGER.info("[VEX] Restoring Wither Rose Block Item"); + LOGGER.info("[VEX] If you want to disable the block overrides, please install MixinBootstrap or use Fabric version."); + itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.WITHER_ROSE, new Item.Properties().group(Items.CHORUS_FLOWER.getGroup())).setRegistryName("minecraft", "wither_rose")); + } + } +} diff --git a/forge/src/main/java/com/vanilla/experience/forge/utils/VexUtils.java b/forge/src/main/java/com/vanilla/experience/forge/utils/VexUtils.java new file mode 100644 index 0000000..9677736 --- /dev/null +++ b/forge/src/main/java/com/vanilla/experience/forge/utils/VexUtils.java @@ -0,0 +1,23 @@ +package com.vanilla.experience.forge.utils; + +import com.vanilla.experience.CommonUtils; +import net.minecraft.util.SharedConstants; + +public class VexUtils { + public static boolean mixinExists() { + try { + Class.forName("org.spongepowered.asm.launch.MixinBootstrap"); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } + + public static boolean isZeroTickPatched() { + return SharedConstants.getVersion().getWorldVersion() >= CommonUtils.zeroTickVersionPatch; + } + + public static boolean isWitherRosesSpawnPatched() { + return SharedConstants.getVersion().getWorldVersion() >= CommonUtils.witherRosesVersionPatch; + } +} diff --git a/forge/src/main/java/com/vanilla/experience/forge/witherrosesunpatch/mixin/EntityTypeMixin.java b/forge/src/main/java/com/vanilla/experience/forge/witherrosesunpatch/mixin/EntityTypeMixin.java new file mode 100644 index 0000000..01304d8 --- /dev/null +++ b/forge/src/main/java/com/vanilla/experience/forge/witherrosesunpatch/mixin/EntityTypeMixin.java @@ -0,0 +1,16 @@ +package com.vanilla.experience.forge.witherrosesunpatch.mixin; + +import net.minecraft.block.*; +import net.minecraft.entity.EntityType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(EntityType.class) +public class EntityTypeMixin { + + @Redirect(method = "func_233597_a_(Lnet/minecraft/block/BlockState;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;isIn(Lnet/minecraft/block/Block;)Z", ordinal = 2)) + private boolean restoreWitherRoseSpawning(BlockState blockState, Block block) { + return false; // return false to method that checks if is inside a Whiter Rose + } +} \ No newline at end of file diff --git a/src/main/java/com/vanilla/experience/enhancedwitherroses/EnhancedWitherRoses.java b/forge/src/main/java/com/vanilla/experience/forge/witherrosesunpatch/override/WitherRose.java similarity index 59% rename from src/main/java/com/vanilla/experience/enhancedwitherroses/EnhancedWitherRoses.java rename to forge/src/main/java/com/vanilla/experience/forge/witherrosesunpatch/override/WitherRose.java index 4221c69..3fceeae 100644 --- a/src/main/java/com/vanilla/experience/enhancedwitherroses/EnhancedWitherRoses.java +++ b/forge/src/main/java/com/vanilla/experience/forge/witherrosesunpatch/override/WitherRose.java @@ -1,20 +1,16 @@ -package com.vanilla.experience.enhancedwitherroses; +package com.vanilla.experience.forge.witherrosesunpatch.override; import net.minecraft.block.BlockState; -import net.minecraft.block.FlowerBlock; import net.minecraft.block.WitherRoseBlock; import net.minecraft.entity.EntitySpawnPlacementRegistry; import net.minecraft.entity.EntityType; import net.minecraft.potion.Effects; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockReader; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -public class EnhancedWitherRoses extends WitherRoseBlock { - private static final Logger LOGGER = LogManager.getLogger(); +public class WitherRose extends WitherRoseBlock { - public EnhancedWitherRoses(Properties properties) { + public WitherRose(Properties properties) { super(Effects.WITHER, properties); } diff --git a/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickAbstractTopPlantBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickAbstractTopPlantBlock.java new file mode 100644 index 0000000..7fa7d82 --- /dev/null +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickAbstractTopPlantBlock.java @@ -0,0 +1,27 @@ +package com.vanilla.experience.forge.zerotickunpatch.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.AbstractTopPlantBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +// this abstracts Kelp, TwistingVines and WeepingVines +@Mixin(AbstractTopPlantBlock.class) +public class ZeroTickAbstractTopPlantBlock { + @Shadow + public void randomTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random) {} + + @Inject(at = @At("TAIL"), method = "tick") + public void tick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random, CallbackInfo info) { + if(!world.isAirBlock(pos.down())) { + this.randomTick(state, world, pos, random); + } + } +} \ No newline at end of file diff --git a/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickBambooBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickBambooBlock.java new file mode 100644 index 0000000..d750848 --- /dev/null +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickBambooBlock.java @@ -0,0 +1,31 @@ +package com.vanilla.experience.forge.zerotickunpatch.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.BambooBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.server.ServerWorld; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +@Mixin(BambooBlock.class) +public class ZeroTickBambooBlock { + private static final Logger LOGGER = LogManager.getLogger(); + + @Shadow + public void randomTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random) {} + + @Inject(at = @At("TAIL"), method = "tick") + public void tick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random, CallbackInfo info) { + if(!world.isAirBlock(pos.down())) { + this.randomTick(state, world, pos, random); + } + } + +} \ No newline at end of file diff --git a/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickCactusBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickCactusBlock.java new file mode 100644 index 0000000..1325775 --- /dev/null +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickCactusBlock.java @@ -0,0 +1,26 @@ +package com.vanilla.experience.forge.zerotickunpatch.mixin; + +import net.minecraft.block.CactusBlock; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +@Mixin(CactusBlock.class) +public class ZeroTickCactusBlock { + @Shadow + public void randomTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random) {} + + @Inject(at = @At("TAIL"), method = "tick") + public void tick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random, CallbackInfo info) { + if(!world.isAirBlock(pos.down())) { + this.randomTick(state, world, pos, random); + } + } +} \ No newline at end of file diff --git a/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickChorusFlowerBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickChorusFlowerBlock.java new file mode 100644 index 0000000..0e010e7 --- /dev/null +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickChorusFlowerBlock.java @@ -0,0 +1,26 @@ +package com.vanilla.experience.forge.zerotickunpatch.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.ChorusFlowerBlock; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +@Mixin(ChorusFlowerBlock.class) +public class ZeroTickChorusFlowerBlock { + @Shadow + public void randomTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random) {} + + @Inject(at = @At("TAIL"), method = "tick") + public void tick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random, CallbackInfo info) { + if(!world.isAirBlock(pos.down())) { + this.randomTick(state, world, pos, random); + } + } +} \ No newline at end of file diff --git a/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickSugarCaneBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickSugarCaneBlock.java new file mode 100644 index 0000000..15cf529 --- /dev/null +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/mixin/ZeroTickSugarCaneBlock.java @@ -0,0 +1,26 @@ +package com.vanilla.experience.forge.zerotickunpatch.mixin; + +import net.minecraft.block.BlockState; +import net.minecraft.block.SugarCaneBlock; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +@Mixin(SugarCaneBlock.class) +public class ZeroTickSugarCaneBlock { + @Shadow + public void randomTick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random) {} + + @Inject(at = @At("TAIL"), method = "tick") + public void tick(final BlockState state, final ServerWorld world, final BlockPos pos, final Random random, CallbackInfo info) { + if(!world.isAirBlock(pos.down())) { + this.randomTick(state, world, pos, random); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickBambooBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickBambooBlock.java similarity index 80% rename from src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickBambooBlock.java rename to forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickBambooBlock.java index e6de112..9281f2b 100644 --- a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickBambooBlock.java +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickBambooBlock.java @@ -1,4 +1,4 @@ -package com.vanilla.experience.zerotickunpatch; +package com.vanilla.experience.forge.zerotickunpatch.override; import net.minecraft.block.BambooBlock; import net.minecraft.block.BlockState; @@ -7,8 +7,7 @@ import java.util.Random; -public class ZeroTickBambooBlock extends BambooBlock -{ +public class ZeroTickBambooBlock extends BambooBlock { public ZeroTickBambooBlock(Properties properties) { super(properties); } diff --git a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickCactusBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickCactusBlock.java similarity index 80% rename from src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickCactusBlock.java rename to forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickCactusBlock.java index 0657636..62b6cd2 100644 --- a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickCactusBlock.java +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickCactusBlock.java @@ -1,4 +1,4 @@ -package com.vanilla.experience.zerotickunpatch; +package com.vanilla.experience.forge.zerotickunpatch.override; import net.minecraft.block.CactusBlock; import net.minecraft.block.BlockState; @@ -7,8 +7,7 @@ import java.util.Random; -public class ZeroTickCactusBlock extends CactusBlock -{ +public class ZeroTickCactusBlock extends CactusBlock { public ZeroTickCactusBlock(Properties properties) { super(properties); } diff --git a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickChorusFlowerBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickChorusFlowerBlock.java similarity index 89% rename from src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickChorusFlowerBlock.java rename to forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickChorusFlowerBlock.java index 8cde80d..ac48378 100644 --- a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickChorusFlowerBlock.java +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickChorusFlowerBlock.java @@ -1,4 +1,4 @@ -package com.vanilla.experience.zerotickunpatch; +package com.vanilla.experience.forge.zerotickunpatch.override; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -9,7 +9,6 @@ import java.util.Random; - public class ZeroTickChorusFlowerBlock extends ChorusFlowerBlock { public ZeroTickChorusFlowerBlock(Properties builder) { diff --git a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickKelpTopBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickKelpTopBlock.java similarity index 79% rename from src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickKelpTopBlock.java rename to forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickKelpTopBlock.java index 32970c5..43e17a4 100644 --- a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickKelpTopBlock.java +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickKelpTopBlock.java @@ -1,4 +1,4 @@ -package com.vanilla.experience.zerotickunpatch; +package com.vanilla.experience.forge.zerotickunpatch.override; import net.minecraft.block.KelpTopBlock; import net.minecraft.block.BlockState; @@ -7,8 +7,7 @@ import java.util.Random; -public class ZeroTickKelpTopBlock extends KelpTopBlock -{ +public class ZeroTickKelpTopBlock extends KelpTopBlock { public ZeroTickKelpTopBlock(Properties properties) { super(properties); } diff --git a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickSugarCaneBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickSugarCaneBlock.java similarity index 79% rename from src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickSugarCaneBlock.java rename to forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickSugarCaneBlock.java index aa2c682..433e98d 100644 --- a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickSugarCaneBlock.java +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickSugarCaneBlock.java @@ -1,4 +1,4 @@ -package com.vanilla.experience.zerotickunpatch; +package com.vanilla.experience.forge.zerotickunpatch.override; import net.minecraft.block.BlockState; import net.minecraft.block.SugarCaneBlock; @@ -7,8 +7,7 @@ import java.util.Random; -public class ZeroTickSugarCaneBlock extends SugarCaneBlock -{ +public class ZeroTickSugarCaneBlock extends SugarCaneBlock { public ZeroTickSugarCaneBlock(Properties properties) { super(properties); } diff --git a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickTwistingVinesTopBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickTwistingVinesTopBlock.java similarity index 79% rename from src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickTwistingVinesTopBlock.java rename to forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickTwistingVinesTopBlock.java index b17b4ca..75a4cfc 100644 --- a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickTwistingVinesTopBlock.java +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickTwistingVinesTopBlock.java @@ -1,16 +1,13 @@ -package com.vanilla.experience.zerotickunpatch; +package com.vanilla.experience.forge.zerotickunpatch.override; import net.minecraft.block.BlockState; import net.minecraft.block.TwistingVinesTopBlock; import net.minecraft.util.math.BlockPos; import net.minecraft.world.server.ServerWorld; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import java.util.Random; -public class ZeroTickTwistingVinesTopBlock extends TwistingVinesTopBlock -{ +public class ZeroTickTwistingVinesTopBlock extends TwistingVinesTopBlock { public ZeroTickTwistingVinesTopBlock(Properties properties) { super(properties); } diff --git a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickWeepingVinesTopBlock.java b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickWeepingVinesTopBlock.java similarity index 79% rename from src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickWeepingVinesTopBlock.java rename to forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickWeepingVinesTopBlock.java index dad7bcb..413de44 100644 --- a/src/main/java/com/vanilla/experience/zerotickunpatch/ZeroTickWeepingVinesTopBlock.java +++ b/forge/src/main/java/com/vanilla/experience/forge/zerotickunpatch/override/ZeroTickWeepingVinesTopBlock.java @@ -1,16 +1,13 @@ -package com.vanilla.experience.zerotickunpatch; +package com.vanilla.experience.forge.zerotickunpatch.override; import net.minecraft.block.WeepingVinesTopBlock; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.server.ServerWorld; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import java.util.Random; -public class ZeroTickWeepingVinesTopBlock extends WeepingVinesTopBlock -{ +public class ZeroTickWeepingVinesTopBlock extends WeepingVinesTopBlock { public ZeroTickWeepingVinesTopBlock(Properties properties) { super(properties); } diff --git a/forge/src/main/resources/META-INF/MANIFEST.MF b/forge/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..70fce8a --- /dev/null +++ b/forge/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,8 @@ +Specification-Vendor: vanillaexperience +Specification-Title: vanillaexperience +Specification-Version: 1 +Implementation-Title: vanillaexperience +Implementation-Version: 1.0 +Implementation-Vendor: vanillaexperience +MixinConnector: com.vanilla.experience.forge.utils.MixinLoader + diff --git a/src/main/resources/META-INF/mods.toml b/forge/src/main/resources/META-INF/mods.toml similarity index 56% rename from src/main/resources/META-INF/mods.toml rename to forge/src/main/resources/META-INF/mods.toml index 3df497c..3419921 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/forge/src/main/resources/META-INF/mods.toml @@ -1,14 +1,12 @@ -modLoader="javafml" #mandatory - -loaderVersion="[32,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +modLoader="javafml" +loaderVersion="[32,)" issueTrackerURL="https://mods.augustoresende.com/vanillaexperience/issues" - [[mods]] modId="vanillaexperience" -version="0.0.1" +version="${file.jarVersion}" displayName="Vanilla Experience" @@ -17,19 +15,16 @@ updateJSONURL="https://mods.augustoresende.com/vanillaexperience/updates.json" displayURL="https://mods.augustoresende.com/vanillaexperience/" logoFile="vex.png" -credits="Vanilla Experience Mod!" +credits="AugustoResende" -authors="AugustoResende" #optional +authors="AugustoResende" -description=''' -Thanks for downloading! - -''' +description='''Thanks for downloading Vanilla Experience for Forge!''' [[dependencies.forge]] - modId="forge" #mandatory - mandatory=true #mandatory - versionRange="[32,)" #mandatory + modId="forge" + mandatory=true + versionRange="[32,)" ordering="NONE" side="BOTH" diff --git a/forge/src/main/resources/mixin/forge/witherrosesunpatch.mixins.json b/forge/src/main/resources/mixin/forge/witherrosesunpatch.mixins.json new file mode 100644 index 0000000..4ea9d28 --- /dev/null +++ b/forge/src/main/resources/mixin/forge/witherrosesunpatch.mixins.json @@ -0,0 +1,12 @@ +{ + "required": true, + "package": "com.vanilla.experience.forge.witherrosesunpatch.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "EntityTypeMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "minVersion": "0.8" +} \ No newline at end of file diff --git a/forge/src/main/resources/mixin/forge/zerotickunpatch.mixins.json b/forge/src/main/resources/mixin/forge/zerotickunpatch.mixins.json new file mode 100644 index 0000000..55a3a1e --- /dev/null +++ b/forge/src/main/resources/mixin/forge/zerotickunpatch.mixins.json @@ -0,0 +1,16 @@ +{ + "required": true, + "package": "com.vanilla.experience.forge.zerotickunpatch.mixin", + "compatibilityLevel": "JAVA_8", + "mixins": [ + "ZeroTickAbstractTopPlantBlock", + "ZeroTickBambooBlock", + "ZeroTickCactusBlock", + "ZeroTickChorusFlowerBlock", + "ZeroTickSugarCaneBlock" + ], + "injectors": { + "defaultRequire": 1 + }, + "minVersion": "0.8" +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 5927faf..bab2658 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,9 @@ # Sets default memory used for gradle commands. Can be overridden by user or command line properties. # This is required to provide enough memory for the Minecraft decompilation process. org.gradle.jvmargs=-Xmx4G -org.gradle.daemon=false \ No newline at end of file +org.gradle.daemon=false +mod_version=0.1.6 +mod_id=vanillaexperience +mc_version=1.16.1 +forge_version=32.0.59 +curseforge_id=393896 \ No newline at end of file diff --git a/src/main/java/com/vanilla/experience/VanillaExperience.java b/src/main/java/com/vanilla/experience/VanillaExperience.java deleted file mode 100644 index 1f75e02..0000000 --- a/src/main/java/com/vanilla/experience/VanillaExperience.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.vanilla.experience; - -import com.vanilla.experience.enhancedberries.*; -import com.vanilla.experience.enhancedbonemeal.*; -import com.vanilla.experience.enhancedseeds.*; -import com.vanilla.experience.enhancedtotem.*; -import com.vanilla.experience.enhancedwitherroses.*; -import com.vanilla.experience.zerotickunpatch.*; -import net.minecraft.block.*; -import net.minecraft.item.*; -import net.minecraft.util.SharedConstants; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.RegistryEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent; -import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent; -import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent; -import net.minecraftforge.fml.event.server.FMLServerStartingEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -// The value here should match an entry in the META-INF/mods.toml file -@Mod("vanillaexperience") -public class VanillaExperience -{ - // Directly reference a log4j logger. - private static final Logger LOGGER = LogManager.getLogger(); - - public VanillaExperience() { - /* // Register the setup method for modloading - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup); - // Register the enqueueIMC method for modloading - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::enqueueIMC); - // Register the processIMC method for modloading - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::processIMC); - // Register the doClientStuff method for modloading - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::doClientStuff); */ - - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::loadCompleted); - - MinecraftForge.EVENT_BUS.register(this); - - DispenserBlock.registerDispenseBehavior(Items.BONE_MEAL, new EnhancedBoneMealDispenserBehaviour()); - DispenserBlock.registerDispenseBehavior(Items.WHEAT_SEEDS, new EnhancedSeedsDispenserBehaviour()); - } - - private void loadCompleted(FMLLoadCompleteEvent e){ - MinecraftForge.EVENT_BUS.register(new EnhancedBoneMeal()); - MinecraftForge.EVENT_BUS.register(new EnhancedBerries()); - MinecraftForge.EVENT_BUS.register(new EnhancedSeeds()); - MinecraftForge.EVENT_BUS.register(new EnhancedTotem()); - } - - @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD) - public static class RegistryEvents { - @SubscribeEvent - public static void onBlocksRegistry(final RegistryEvent.Register blockRegistryEvent) { - if(SharedConstants.getVersion().getWorldVersion() >= 2524){ - LOGGER.info("Unpatching ZeroTick, ignore the 'Potentially Dangerous' messages."); - blockRegistryEvent.getRegistry().register(new ZeroTickBambooBlock(Block.Properties.from(Blocks.BAMBOO)).setRegistryName("minecraft", "bamboo")); - blockRegistryEvent.getRegistry().register(new ZeroTickCactusBlock(Block.Properties.from(Blocks.CACTUS)).setRegistryName("minecraft", "cactus")); - blockRegistryEvent.getRegistry().register(new ZeroTickSugarCaneBlock(Block.Properties.from(Blocks.SUGAR_CANE)).setRegistryName("minecraft", "sugar_cane")); - blockRegistryEvent.getRegistry().register(new ZeroTickKelpTopBlock(Block.Properties.from(Blocks.KELP)).setRegistryName("minecraft", "kelp")); - blockRegistryEvent.getRegistry().register(new ZeroTickWeepingVinesTopBlock(Block.Properties.from(Blocks.WEEPING_VINES)).setRegistryName("minecraft", "weeping_vines")); - blockRegistryEvent.getRegistry().register(new ZeroTickTwistingVinesTopBlock(Block.Properties.from(Blocks.TWISTING_VINES)).setRegistryName("minecraft", "twisting_vines")); - blockRegistryEvent.getRegistry().register(new ZeroTickChorusFlowerBlock(Block.Properties.from(Blocks.CHORUS_FLOWER)).setRegistryName("minecraft", "chorus_flower")); - LOGGER.info("Unpatching Wither Rose spawning."); - blockRegistryEvent.getRegistry().register(new EnhancedWitherRoses(Block.Properties.from(Blocks.WITHER_ROSE)).setRegistryName("minecraft", "wither_rose")); - } - } - - @SubscribeEvent - public static void onItemsRegistry(final RegistryEvent.Register itemRegistryEvent) { - if (SharedConstants.getVersion().getWorldVersion() >= 2524) { - itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.BAMBOO, new Item.Properties().group(Items.BAMBOO.getGroup())).setRegistryName("minecraft", "bamboo")); - itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.CACTUS, new Item.Properties().group(Items.CACTUS.getGroup())).setRegistryName("minecraft", "cactus")); - itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.SUGAR_CANE, new Item.Properties().group(Items.SUGAR_CANE.getGroup())).setRegistryName("minecraft", "sugar_cane")); - itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.KELP, new Item.Properties().group(Items.KELP.getGroup())).setRegistryName("minecraft", "kelp")); - itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.WEEPING_VINES, new Item.Properties().group(Items.WEEPING_VINES.getGroup())).setRegistryName("minecraft", "weeping_vines")); - itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.TWISTING_VINES, new Item.Properties().group(Items.TWISTING_VINES.getGroup())).setRegistryName("minecraft", "twisting_vines")); - itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.CHORUS_FLOWER, new Item.Properties().group(Items.CHORUS_FLOWER.getGroup())).setRegistryName("minecraft", "chorus_flower")); - itemRegistryEvent.getRegistry().register(new BlockItem(Blocks.WITHER_ROSE, new Item.Properties().group(Items.CHORUS_FLOWER.getGroup())).setRegistryName("minecraft", "wither_rose")); - } - } - } - - /* private void setup(final FMLCommonSetupEvent event) - { - // some preinit code - //LOGGER.info("HELLO FROM PREINIT"); - //LOGGER.info("DIRT BLOCK >> {}", Blocks.DIRT.getRegistryName()); - } - - private void doClientStuff(final FMLClientSetupEvent event) { - // do something that can only be done on the client - //LOGGER.info("Got game settings {}", event.getMinecraftSupplier().get().gameSettings); - } - - private void enqueueIMC(final InterModEnqueueEvent event) - { - // some example code to dispatch IMC to another mod - //InterModComms.sendTo("examplemod", "helloworld", () -> { LOGGER.info("Hello world from the MDK"); return "Hello world";}); - } - - private void processIMC(final InterModProcessEvent event) - { - // some example code to receive and process InterModComms from other mods - //LOGGER.info("Got IMC {}", event.getIMCStream(). - // map(m->m.getMessageSupplier().get()). - // collect(Collectors.toList())); - } - // You can use SubscribeEvent and let the Event Bus discover methods to call - @SubscribeEvent - public void onServerStarting(FMLServerStartingEvent event) { - // do something when the server starts - //LOGGER.info("HELLO from server starting"); - } */ - - // You can use EventBusSubscriber to automatically subscribe events on the contained class (this is subscribing to the MOD - // Event bus for receiving Registry Events) -} - diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF deleted file mode 100644 index b21f14e..0000000 --- a/src/main/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1,8 +0,0 @@ -Manifest-Version: 1.0 -Implementation-Title: VanillaExperience -Implementation-Version: 1.0 -Specification-Vendor: test -Specification-Title: vanillaexperience -Specification-Version: 1 -Implementation-Vendor: test -