initial commit

This commit is contained in:
LunarAkai 2025-08-30 13:58:48 +02:00
commit 4aa82637aa
10 changed files with 474 additions and 0 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
.gradle
build
.idea
run

181
build.gradle Normal file
View file

@ -0,0 +1,181 @@
plugins {
id 'java-library'
id 'maven-publish'
id 'idea'
id 'net.neoforged.moddev' version '2.0.107'
id 'org.jetbrains.kotlin.jvm' version '2.1.21'
}
version = mod_version
group = mod_group_id
repositories {
mavenLocal()
mavenCentral()
maven {
name 'Xander Maven'
url 'https://maven.isxander.dev/releases'
}
maven {
name = 'Kotlin for Forge'
url = 'https://thedarkcolour.github.io/KotlinForForge/'
}
}
base {
archivesName = mod_id
}
java.toolchain.languageVersion = JavaLanguageVersion.of(21)
neoForge {
// Specify the version of NeoForge to use.
version = project.neo_version
parchment {
mappingsVersion = project.parchment_mappings_version
minecraftVersion = project.parchment_minecraft_version
}
// This line is optional. Access Transformers are automatically detected
// accessTransformers.add('src/main/resources/META-INF/accesstransformer.cfg')
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
runs {
client {
client()
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
server {
server()
programArgument '--nogui'
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
// 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 {
type = "gameTestServer"
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
data {
clientData()
// example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it
// gameDirectory = project.file('run-data')
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
}
// applies to all the run configs above
configureEach {
// 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.
systemProperty '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
logLevel = org.slf4j.event.Level.DEBUG
}
}
mods {
// define mod <-> source bindings
// these are used to tell the game which sources are for which mod
// mostly optional in a single mod project
// but multi mod projects should define one per mod
"${mod_id}" {
sourceSet(sourceSets.main)
}
}
}
// Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' }
dependencies {
// Example mod dependency with JEI
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"
// compileOnly "mezz.jei:jei-${mc_version}-forge-api:${jei_version}"
// runtimeOnly "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 "blank:coolmod-${mc_version}:${coolmod_version}"
// Example mod dependency using a file as dependency
// implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar")
// Example project dependency using a sister or child project:
// implementation project(":myproject")
// For more info:
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.
implementation "dev.isxander:yet-another-config-lib:${project.yacl_version}"
implementation 'thedarkcolour:kotlinforforge-neoforge:5.9.0'
}
// 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.
var generateModMetadata = tasks.register("generateModMetadata", ProcessResources) {
var replaceProperties = [minecraft_version : minecraft_version,
minecraft_version_range: minecraft_version_range,
neo_version : neo_version,
neo_version_range : neo_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
expand replaceProperties
from "src/main/templates"
into "build/generated/sources/modMetadata"
}
// Include the output of "generateModMetadata" as an input directory for the build
// this works with both building through Gradle and the IDE.
sourceSets.main.resources.srcDir generateModMetadata
// To avoid having to run "generateModMetadata" manually, make it run on every project reload
neoForge.ideSyncTask generateModMetadata
// Example configuration to allow publishing using the maven-publish plugin
publishing {
publications {
register('mavenJava', MavenPublication) {
from components.java
}
}
repositories {
maven {
url "file://${project.projectDir}/repo"
}
}
}
// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior.
idea {
module {
downloadSources = true
downloadJavadoc = true
}
}

41
gradle.properties Normal file
View file

@ -0,0 +1,41 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
org.gradle.jvmargs=-Xmx2G
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
## Environment Properties
# You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge
# The Minecraft version must agree with the Neo version to get a valid artifact
minecraft_version=1.21.8
# 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.21.8,1.22)
# The Neo version must agree with the Minecraft version to get a valid artifact
neo_version=21.8.39
# The Neo version range can use any version of Neo as bounds
neo_version_range=[21,)
# The loader version range can only use the major version of FML as bounds
loader_version_range=[4,)
parchment_minecraft_version=1.21.8
parchment_mappings_version=2025.07.20
## Mod Properties
# 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=yukisstuff
# The human-readable display name for the mod.
mod_name=YukisStuff
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=GNU GPL 3.0
# The mod version. See https://semver.org/
mod_version=1.0-SNAPSHOT
# 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=de.lunarakai
# The authors of the mod. This is a simple text string that is used for display purposes in the mod list.
mod_authors=LunarAkai
# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.
mod_description=small things
yacl_version=3.7.1+1.21.6-neoforge

View file

@ -0,0 +1 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip

11
settings.gradle Normal file
View file

@ -0,0 +1,11 @@
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
maven { url = 'https://maven.neoforged.net/releases' }
}
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
}

View file

@ -0,0 +1,43 @@
package de.lunarakai.yukisstuff;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.Style;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.client.event.ClientChatReceivedEvent;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import static de.lunarakai.yukisstuff.Yukisstuff.MODID;
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
@EventBusSubscriber(modid = MODID, value = Dist.CLIENT)
public class ClientModEvents {
@SubscribeEvent
public static void onChat(ClientChatReceivedEvent event) {
net.minecraft.network.chat.Component msg = event.getMessage();
net.minecraft.network.chat.Component finalmsg = modifyMessages(msg);
event.setMessage(finalmsg);
}
private static net.minecraft.network.chat.Component modifyMessages(net.minecraft.network.chat.Component componentIn) {
MutableComponent component = net.minecraft.network.chat.Component.literal("");
MutableComponent t = net.minecraft.network.chat.Component.literal("[" + time() + "] ");
t.setStyle(Style.EMPTY.withColor(ChatFormatting.GOLD));
component.append(t);
component.append(componentIn);
componentIn = component;
return componentIn;
}
private static String time() {
LocalTime now = LocalTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
return now.format(formatter);
}
}

View file

@ -0,0 +1,41 @@
package de.lunarakai.yukisstuff;
import com.google.gson.GsonBuilder;
import dev.isxander.yacl3.config.v2.api.ConfigClassHandler;
import dev.isxander.yacl3.config.v2.api.SerialEntry;
import dev.isxander.yacl3.config.v2.api.serializer.GsonConfigSerializerBuilder;
import dev.isxander.yacl3.platform.YACLPlatform;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.config.ModConfigEvent;
import net.neoforged.neoforge.client.config.NeoForgeClientConfig;
import net.neoforged.neoforge.common.ModConfigSpec;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.common.NeoForgeMod;
import net.neoforged.neoforge.common.config.NeoForgeCommonConfig;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
// An example config class. This is not required, but it's a good idea to have one to keep your config organized.
// Demonstrates how to use Neo's config APIs
@EventBusSubscriber(modid = Yukisstuff.MODID)
public class Config {
public static ConfigClassHandler<Config> HANDLER = ConfigClassHandler.createBuilder(Config.class)
.id(ResourceLocation.fromNamespaceAndPath(Yukisstuff.MODID, "yukis_stuff"))
.serializer(config -> GsonConfigSerializerBuilder.create(config)
.setPath(YACLPlatform.getConfigDir().resolve("yukis_stuff.json5"))
.appendGsonBuilder(GsonBuilder::setPrettyPrinting) // not needed, pretty print by default
.setJson5(true)
.build())
.build();
@SerialEntry
public boolean showTimestamp = true;
}

View file

@ -0,0 +1,70 @@
package de.lunarakai.yukisstuff;
import com.mojang.logging.LogUtils;
import dev.isxander.yacl3.api.*;
import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder;
import dev.isxander.yacl3.config.v2.api.ConfigClassHandler;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.*;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.ModLoadingContext;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.config.ModConfig;
import net.neoforged.neoforge.client.event.ClientChatReceivedEvent;
import net.neoforged.neoforge.client.gui.ConfigurationScreen;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
// The value here should match an entry in the META-INF/neoforge.mods.toml file
@Mod(Yukisstuff.MODID)
public class Yukisstuff {
public static final String MODID = "yukisstuff";
private static final Logger LOGGER = LogUtils.getLogger();
// The constructor for the mod class is the first code that is run when your mod is loaded.
// FML will recognize some parameter types like IEventBus or ModContainer and pass them in automatically.
public Yukisstuff(IEventBus modEventBus, ModContainer modContainer) {
// Register our mod's ModConfigSpec so that FML can create and load the config file for us
//modContainer.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new);
Config.HANDLER.save();
Config.HANDLER.load();
boolean showTimestamp = Config.HANDLER.instance().showTimestamp;
ModLoadingContext.get().registerExtensionPoint(
IConfigScreenFactory.class,
() -> (client, parent) -> YetAnotherConfigLib.createBuilder()
.title(Component.literal("Used for narration. Could be used to render a title in the future."))
.category(ConfigCategory.createBuilder()
.name(Component.literal("Name of the category"))
.tooltip(Component.literal("This text will appear as a tooltip when you hover or focus the button with Tab. There is no need to add \n to wrap as YACL will do it for you."))
.group(OptionGroup.createBuilder()
.name(Component.literal("Name of the group"))
.description(OptionDescription.of(Component.literal("This text will appear when you hover over the name or focus on the collapse button with Tab.")))
.option(Option.<Boolean>createBuilder()
.name(Component.literal("Show Timestamp"))
.description(OptionDescription.of(Component.literal("This text will appear as a tooltip when you hover over the option.")))
.binding(true, () -> showTimestamp, newVal -> {
Config.HANDLER.instance().showTimestamp = newVal;
Config.HANDLER.save();
})
.controller(TickBoxControllerBuilder::create)
.build())
.build())
.build())
.build().generateScreen(parent));
}
}

View file

@ -0,0 +1,2 @@
{
}

View file

@ -0,0 +1,80 @@
# This is an example mods.toml file. It contains the data relating to the loading mods.
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
# The overall format is standard TOML format, v0.5.0.
# Note that there are a couple of TOML lists in this file.
# Find more information on toml format here: https://github.com/toml-lang/toml
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
modLoader = "javafml" #mandatory
# A version range to match for said mod loader - for regular FML @Mod it will be the the FML version. This is currently 47.
loaderVersion = "${loader_version_range}" #mandatory
# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
license = "${mod_license}"
# A URL to refer people to when problems occur with this mod
#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
# A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
# The modid of the mod
modId = "${mod_id}" #mandatory
# The version number of the mod
version = "${mod_version}" #mandatory
# A display name for the mod
displayName = "${mod_name}" #mandatory
# A URL to query for updates for this mod. See the JSON update specification https://docs.neoforge.net/docs/misc/updatechecker/
#updateJSONURL="https://change.me.example.invalid/updates.json" #optional
# A URL for the "homepage" for this mod, displayed in the mod UI
displayURL = "lunarakai.de" #optional
# A file name (in the root of the mod JAR) containing a logo for display
#logoFile="yukisstuff.png" #optional
# A text field displayed in the mod UI
#credits="" #optional
# A text field displayed in the mod UI
authors = "${mod_authors}" #optional
# The description text for the mod (multi line!) (#mandatory)
description = '''${mod_description}'''
# The [[mixins]] block allows you to declare your mixin config to FML so that it gets loaded.
#[[mixins]]
#config="${mod_id}.mixins.json"
# The [[accessTransformers]] block allows you to declare where your AT file is.
# If this block is omitted, a fallback attempt will be made to load an AT from META-INF/accesstransformer.cfg
#[[accessTransformers]]
#file="META-INF/accesstransformer.cfg"
# The coremods config file path is not configurable and is always loaded from META-INF/coremods.json
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
[[dependencies."${mod_id}"]] #optional
# the modid of the dependency
modId = "neoforge" #mandatory
# The type of the dependency. Can be one of "required", "optional", "incompatible" or "discouraged" (case insensitive).
# 'required' requires the mod to exist, 'optional' does not
# 'incompatible' will prevent the game from loading when the mod exists, and 'discouraged' will show a warning
type = "required" #mandatory
# Optional field describing why the dependency is required or why it is incompatible
# reason="..."
# The version range of the dependency
versionRange = "${neo_version_range}" #mandatory
# An ordering relationship for the dependency.
# BEFORE - This mod is loaded BEFORE the dependency
# AFTER - This mod is loaded AFTER the dependency
ordering = "NONE"
# Side this dependency is applied on - BOTH, CLIENT, or SERVER
side = "CLIENT"
# Here's another dependency
[[dependencies."${mod_id}"]]
modId = "minecraft"
type = "required"
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange = "${minecraft_version_range}"
ordering = "NONE"
side = "BOTH"
# Features are specific properties of the game environment, that you may want to declare you require. This example declares
# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't
# stop your mod loading on the server for example.
#[features."${mod_id}"]
#openGLVersion="[3.2,)"