commit b936dd5c368f5be8910c3c3e4c89d639d294d9c5 Author: Jenny Date: Wed May 7 20:49:47 2025 +0200 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5f737e --- /dev/null +++ b/.gitignore @@ -0,0 +1,119 @@ +# User-specific stuff +.idea/ + +*.iml +*.ipr +*.iws + +# IntelliJ +out/ +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Cache of project +.gradletasknamecache + +**/build/ + +# Common working directory +run/ +runs/ + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..ea59ea0 --- /dev/null +++ b/build.gradle @@ -0,0 +1,188 @@ +plugins { + id 'eclipse' + id 'idea' + id 'net.minecraftforge.gradle' version '[6.0.16,6.2)' + id 'org.parchmentmc.librarian.forgegradle' version '1.+' +} + + +group = mod_group_id +version = mod_version + +base { + archivesName = mod_id +} + +java { + toolchain.languageVersion = JavaLanguageVersion.of(17) +} + +minecraft { + // The mappings can be changed at any time and must be in the following format. + // Channel: Version: + // official MCVersion Official field/method names from Mojang mapping files + // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official + // + // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge + // Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started + // + // 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: mapping_channel, version: mapping_version + + // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. + // In most cases, it is not necessary to enable. + // enableEclipsePrepareRuns = true + // enableIdeaPrepareRuns = true + + // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. + // It is REQUIRED to be set to true for this template to function. + // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html + copyIdeResources = true + + // When true, this property will add the folder name of all declared run configurations to generated IDE run configurations. + // The folder name can be set on a run configuration using the "folderName" property. + // By default, the folder name of a run configuration is the name of the Gradle project containing it. + // generateRunFolders = true + + // This property enables access transformers for use in development. + // They will be applied to the Minecraft artifact. + // The access transformer file can be anywhere in the project. + // However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge. + // This default location is a best practice to automatically put the file in the right place in the final jar. + // See https://docs.minecraftforge.net/en/latest/advanced/accesstransformers/ for more information. + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + // applies to all the run configs below + configureEach { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + "${mod_id}" { + source sourceSets.main + } + } + } + + client { + // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. + property 'forge.enabledGameTestNamespaces', mod_id + } + + server { + property 'forge.enabledGameTestNamespaces', mod_id + args '--nogui' + } + + // This run config launches GameTestServer and runs all registered gametests, then exits. + // By default, the server will crash when no gametests are provided. + // The gametest system is also enabled by default for other run configs under the /test command. + gameTestServer { + property 'forge.enabledGameTestNamespaces', mod_id + } + + data { + // example of overriding the workingDirectory set in configureEach above + workingDirectory project.file('run-data') + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + +repositories { + // Put repositories for dependencies here + // ForgeGradle automatically adds the Forge maven and Maven Central for you + + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver + // flatDir { + // dir 'libs' + // } +} + +dependencies { + // Specify the version of Minecraft to use. + // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact. + // The "userdev" classifier will be requested and setup by ForgeGradle. + // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], + // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. + minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" + + // Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings + // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}") + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}") + // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}") + + // Example mod dependency using a mod jar from ./libs with a flat dir repository + // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar + // The group id is ignored when searching -- in this case, it is "blank" + // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + + // For more info: + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html + +} + +// This block of code expands all declared replace properties in the specified resource targets. +// A missing property will result in an error. Properties are expanded using ${} Groovy notation. +// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. +// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html +tasks.named('processResources', ProcessResources).configure { + var replaceProperties = [minecraft_version : minecraft_version, minecraft_version_range: minecraft_version_range, + forge_version : forge_version, forge_version_range: forge_version_range, + loader_version_range: loader_version_range, + mod_id : mod_id, mod_name: mod_name, mod_license: mod_license, mod_version: mod_version, + mod_authors : mod_authors, mod_description: mod_description,] + + inputs.properties replaceProperties + + filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { + expand replaceProperties + [project: project] + } +} + +// Example for how to get properties into the manifest for reading at runtime. +tasks.named('jar', Jar).configure { + manifest { + attributes(["Specification-Title" : mod_id, + "Specification-Vendor" : mod_authors, + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : mod_authors, + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")]) + } + + // This is the preferred method to reobfuscate your jar file + finalizedBy 'reobfJar' +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..6e27c96 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,49 @@ +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false +# The Minecraft version must agree with the Forge version to get a valid artifact +minecraft_version=1.20.1 +# The Minecraft version range can use any release version of Minecraft as bounds. +# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly +# as they do not follow standard versioning conventions. +minecraft_version_range=[1.20.1] +# The Forge version must agree with the Minecraft version to get a valid artifact +forge_version=47.4.0 +# The Forge version range can use any version of Forge as bounds or match the loader version range +forge_version_range=[47,) +# The loader version range can only use the major version of Forge/FML as bounds +loader_version_range=[47,) +# The mapping channel to use for mappings. +# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. +# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. +# +# | Channel | Version | | +# |-----------|----------------------|--------------------------------------------------------------------------------| +# | official | MCVersion | Official field/method names from Mojang mapping files | +# | parchment | YYYY.MM.DD-MCVersion | Open community-sourced parameter names and javadocs layered on top of official | +# +# You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. +# See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md +# +# Parchment is an unofficial project maintained by ParchmentMC, separate from Minecraft Forge. +# Additional setup is needed to use their mappings, see https://parchmentmc.org/docs/getting-started +mapping_channel=parchment +# The mapping version to query from the mapping channel. +# This must match the format required by the mapping channel. +mapping_version=2023.09.03-1.20.1 +# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} +# Must match the String constant located in the main mod class annotated with @Mod. +mod_id=jennyutil +# The human-readable display name for the mod. +mod_name=JennyUtil +# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. +mod_license=CC-BY-NC-4.0 +# The mod version. See https://semver.org/ +mod_version=0.0.1 +# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. +# This should match the base package used for the mod sources. +# See https://maven.apache.org/guides/mini/guide-naming-conventions.html +mod_group_id=com.smthng +# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. +mod_authors=xJenny69 +# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. +mod_description=This is a library for often needed code in my mods diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..51f2657 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,16 @@ +pluginManagement { + repositories { + gradlePluginPortal() + maven { + name = 'MinecraftForge' + url = 'https://maven.minecraftforge.net/' + } + maven { url = 'https://maven.parchmentmc.org' } + } +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' +} + +rootProject.name = 'jennyutil' diff --git a/src/main/java/com/smthng/jennyutil/Jennyutil.java b/src/main/java/com/smthng/jennyutil/Jennyutil.java new file mode 100644 index 0000000..ba25277 --- /dev/null +++ b/src/main/java/com/smthng/jennyutil/Jennyutil.java @@ -0,0 +1,12 @@ +package com.smthng.jennyutil; + +import com.mojang.logging.LogUtils; +import org.slf4j.Logger; + +public class Jennyutil { + public static final Logger LOGGER = LogUtils.getLogger(); + + public static boolean test() { + return true; + } +} diff --git a/src/main/java/com/smthng/jennyutil/datagen/ModItemModelProvider.java b/src/main/java/com/smthng/jennyutil/datagen/ModItemModelProvider.java new file mode 100644 index 0000000..f087bd5 --- /dev/null +++ b/src/main/java/com/smthng/jennyutil/datagen/ModItemModelProvider.java @@ -0,0 +1,32 @@ +package com.smthng.jennyutil.datagen; + +import net.minecraft.data.PackOutput; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.entity.SpawnerBlockEntity; +import net.minecraftforge.client.model.generators.ItemModelBuilder; +import net.minecraftforge.client.model.generators.ItemModelProvider; +import net.minecraftforge.common.data.ExistingFileHelper; +import net.minecraftforge.registries.RegistryObject; +import org.jetbrains.annotations.NotNull; + +public abstract class ModItemModelProvider extends ItemModelProvider { + private String MODID; + + public ModItemModelProvider(String modID, PackOutput output, ExistingFileHelper existingFileHelper) { + super(output, modID, existingFileHelper); + MODID = modID; + } + + private ItemModelBuilder simpleItem(@NotNull RegistryObject item) { + return withExistingParent(item.getId().getPath(), + ResourceLocation.parse("item/generated")).texture("layer0", + ResourceLocation.fromNamespaceAndPath(MODID, "item/" + item.getId().getPath())); + } + + private ItemModelBuilder handheldItem(RegistryObject item) { + return withExistingParent(item.getId().getPath(), + ResourceLocation.parse("item/handheld")).texture("layer0", + ResourceLocation.fromNamespaceAndPath(MODID,"item/" + item.getId().getPath())); + } +} diff --git a/src/main/java/com/smthng/jennyutil/items/BlockItemTooltip.java b/src/main/java/com/smthng/jennyutil/items/BlockItemTooltip.java new file mode 100644 index 0000000..f639f47 --- /dev/null +++ b/src/main/java/com/smthng/jennyutil/items/BlockItemTooltip.java @@ -0,0 +1,34 @@ +package com.smthng.jennyutil.items; + +import com.smthng.jennyutil.Jennyutil; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraftforge.registries.ForgeRegistries; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class BlockItemTooltip extends BlockItem { + public BlockItemTooltip(Block pBlock, Properties pProperties) { + super(pBlock, pProperties); + } + + @Override + public void appendHoverText(@NotNull ItemStack pStack, @Nullable Level pLevel, @NotNull List pTooltipComponents, @NotNull TooltipFlag pIsAdvanced) { + String key = String.format("tooltip.%s", ForgeRegistries.ITEMS.getKey(this).toString().replaceFirst(":", ".")); + MutableComponent toolTip = Component.translatable(key); + if (!toolTip.getString().equals(key)) { + pTooltipComponents.add(toolTip.withStyle(ChatFormatting.DARK_BLUE)); + super.appendHoverText(pStack, pLevel, pTooltipComponents, pIsAdvanced); + } else { + Jennyutil.LOGGER.debug(String.format("BlockItemTooltip missing tooltip \"%s\"", key)); + } + } +} diff --git a/src/main/java/com/smthng/jennyutil/items/ToolMode.java b/src/main/java/com/smthng/jennyutil/items/ToolMode.java new file mode 100644 index 0000000..3028aee --- /dev/null +++ b/src/main/java/com/smthng/jennyutil/items/ToolMode.java @@ -0,0 +1,41 @@ +package com.smthng.jennyutil.items; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; + + +public class ToolMode { + private final int maxVal, defVal; + private final String tagName; + + /** + * + * @param maxVal maximum mode value (inclusive) + * @param defaultVal value to return if no value is found, will be the first value returned + */ + public ToolMode(int maxVal, int defaultVal) { + this.maxVal = maxVal; + this.defVal = defaultVal; + this.tagName = "tool_mode"; + } + + public int getMode(ItemStack itemStack) { + CompoundTag compoundTag = itemStack.getOrCreateTag(); + if (compoundTag.contains(tagName)) { + return compoundTag.getInt(tagName); + } else { + setMode(itemStack, defVal); + return defVal; + } + } + + public void setMode(ItemStack itemStack, int mode) { + CompoundTag compoundTag = itemStack.getOrCreateTag(); + compoundTag.putInt(tagName, mode); + itemStack.setTag(compoundTag); + } + + public void cycleMode(ItemStack itemStack) { + setMode(itemStack, (getMode(itemStack) + 1) % (maxVal + 1)); + } +}