Initial Commit

This commit is contained in:
2026-06-28 16:07:29 +02:00
commit 8bcedc017e
12 changed files with 751 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
# MacOS DS_Store files
.DS_Store
# Gradle cache folder
.gradle
# Gradle build folder
build
# IntelliJ
out/
.idea
*.iml
# mpeltonen/sbt-idea plugin
.idea_modules/
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Common working directory
run
+164
View File
@@ -0,0 +1,164 @@
plugins {
id 'java-library'
id 'maven-publish'
id 'idea'
id 'net.neoforged.moddev' version '2.0.141'
}
version = mod_version
group = mod_group_id
repositories {
mavenLocal()
}
base {
archivesName = mod_id
}
java.toolchain.languageVersion = JavaLanguageVersion.of(25)
neoForge {
// Specify the version of NeoForge to use.
version = project.neo_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.html
implementation "me.neurodock:Core:1.6.6"
}
// 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
}
}
+38
View File
@@ -0,0 +1,38 @@
# 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=26.2.0
# 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=[26.2,27)
# The Neo version must agree with the Minecraft version to get a valid artifact
neo_version=26.2.0.7-beta
# The Neo version range can use any version of Neo as bounds
neo_version_range=[26,)
# The loader version range can only use the major version of FML as bounds
loader_version_range=[4,)
## 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=ollama
# The human-readable display name for the mod.
mod_name=Ollama
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=All Rights Reserved
# 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=me.zacharias
# The authors of the mod. This is a simple text string that is used for display purposes in the mod list.
mod_authors=Zacharias
# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.
mod_description=
+1
View File
@@ -0,0 +1 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
+11
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'
}
@@ -0,0 +1,98 @@
package me.zacharias.ollama;
import me.neurodock.ollama.OllamaFunctionArgument;
import me.neurodock.ollama.OllamaFunctionTool;
import me.neurodock.ollama.OllamaPerameter;
import me.neurodock.ollama.OllamaToolResponse;
import me.neurodock.ollama.exceptions.OllamaToolErrorException;
import net.minecraft.client.Minecraft;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import org.jetbrains.annotations.NotNull;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.List;
import java.util.stream.Stream;
public class GetCraftibles extends OllamaFunctionTool {
@Override
public @NotNull String name() {
return "getcraftibles";
}
@Override
public @NotNull OllamaPerameter parameters() {
return OllamaPerameter.builder()
.addEnumProperty("container", Container.class, "Set what container to use as the craftable", true)
.build();
}
@Override
public @NotNull OllamaToolResponse function(OllamaFunctionArgument... ollamaFunctionArguments) {
if(ollamaFunctionArguments.length != 1) {
throw new OllamaToolErrorException(name(), "Invalid number of arguments");
}
if(!ollamaFunctionArguments[0].argument().equals("container")) {
throw new OllamaToolErrorException(name(), "Invalid argument");
}
Container container = ollamaFunctionArguments[0].getValue(Container.class);
if(Minecraft.getInstance().getSingleplayerServer() == null) {
throw new OllamaToolErrorException(name(), "Not on a single player server");
}
if(Minecraft.getInstance().player == null) {
throw new OllamaToolErrorException(name(), "Cant get a player");
}
if(Minecraft.getInstance().level == null) {
throw new OllamaToolErrorException(name(), "Cant get a level");
}
Inventory inventory = Minecraft.getInstance().player.getInventory();
List<ItemStack> inputItems = Minecraft.getInstance().player.getInventory().getNonEquipmentItems();
RecipeManager recipes = Minecraft.getInstance().getSingleplayerServer().getRecipeManager();
JSONArray recipies = new JSONArray();
if(container != Container.FURNACE) {
List<RecipeHolder<CraftingRecipe>> allRecipes = recipes.getRecipes();
}
else if(container == Container.FURNACE) {
}
}
public enum Container {
INVENTORY(2,2),
CRAFTING_TABLE(3,3),
FURNACE(1,1);
private final int width, height;
Container(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
}
@@ -0,0 +1,53 @@
package me.zacharias.ollama;
import me.neurodock.ollama.OllamaFunctionArgument;
import me.neurodock.ollama.OllamaFunctionTool;
import me.neurodock.ollama.OllamaPerameter;
import me.neurodock.ollama.OllamaToolResponse;
import me.neurodock.ollama.exceptions.OllamaToolErrorException;
import net.minecraft.client.Minecraft;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;
public class GetItemTool extends OllamaFunctionTool {
@Override
public @NotNull String name() {
return "getiteminhand";
}
@Override
public @NotNull OllamaPerameter parameters() {
return OllamaPerameter.empty();
}
@Override
public @NotNull OllamaToolResponse function(OllamaFunctionArgument... ollamaFunctionArguments) {
if(Minecraft.getInstance() == null) {
throw new OllamaToolErrorException(name(), "Minecraft is not initialized");
}
if(Minecraft.getInstance().player == null) {
throw new OllamaToolErrorException(name(), "Player is not initialized");
}
if(Minecraft.getInstance().player.getInventory().getSelectedItem() == null) {
throw new OllamaToolErrorException(name(), "Selected item is null");
}
ItemStack stack = Minecraft.getInstance().player.getInventory().getSelectedItem();
JSONObject item = new JSONObject();
Identifier id = BuiltInRegistries.ITEM.getKey(stack.getItem());
item.put("item", id.toString());
item.put("count", stack.getCount());
item.put("name", stack.getDisplayName().getString());
return new OllamaToolResponse(name(), item.toString());
}
}
@@ -0,0 +1,38 @@
package me.zacharias.ollama;
import me.neurodock.ollama.OllamaFunctionArgument;
import me.neurodock.ollama.OllamaFunctionTool;
import me.neurodock.ollama.OllamaPerameter;
import me.neurodock.ollama.OllamaToolResponse;
import me.neurodock.ollama.exceptions.OllamaToolErrorException;
import net.minecraft.client.Minecraft;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;
public class GetLocation extends OllamaFunctionTool {
@Override
public @NotNull String name() {
return "getlocation";
}
@Override
public @NotNull OllamaPerameter parameters() {
return OllamaPerameter.empty();
}
@Override
public @NotNull OllamaToolResponse function(OllamaFunctionArgument... ollamaFunctionArguments) {
if(Minecraft.getInstance() == null) {
throw new OllamaToolErrorException(name(), "Minecraft is not initialized");
}
if(Minecraft.getInstance().player == null) {
throw new OllamaToolErrorException(name(), "Player is not initialized");
}
Vec3 pos = Minecraft.getInstance().player.position();
return new OllamaToolResponse(name(), new JSONObject().put("x", pos.x).put("y", pos.y).put("z", pos.z).toString());
}
}
@@ -0,0 +1,181 @@
package me.zacharias.ollama;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.logging.LogUtils;
import me.neurodock.core.Core;
import me.neurodock.core.LaunchOptions;
import me.neurodock.core.PrintAdvanceMessageHandler;
import me.neurodock.ollama.OllamaMessage;
import me.neurodock.ollama.OllamaMessageRole;
import me.neurodock.ollama.OllamaObject;
import net.minecraft.client.Minecraft;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.PlayerChatMessage;
import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.MapColor;
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.common.EventBusSubscriber;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.config.ModConfig;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.fml.loading.FMLPaths;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.event.server.ServerStartingEvent;
import net.neoforged.neoforge.registries.DeferredBlock;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister;
import org.slf4j.Logger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
// The value here should match an entry in the META-INF/neoforge.mods.toml file
@Mod(Ollama.MODID)
public class Ollama {
// Define mod id in a common place for everything to reference
public static final String MODID = "ollama";
// Directly reference a slf4j logger
private static final Logger LOGGER = LogUtils.getLogger();
private static CommandSourceStack sourceStack;
PrintAdvanceMessageHandler printAdvanceMessageHandler = new PrintAdvanceMessageHandler() {
@Override
public void printMessage(OllamaMessage ollamaMessage) {
String sender = ollamaMessage.getRole().getRole();
if(ollamaMessage.getRole() == OllamaMessageRole.ASSISTANT)
{
sender = "Merl";
}
LOGGER.info("{}: {}", sender, ollamaMessage.getContent());
if(sourceStack != null) {
sourceStack.sendSystemMessage(Component.literal(sender + "> " + ollamaMessage.getContent()));
}
}
@Override
public void printErrorMessage(OllamaMessage ollamaMessage) {
LOGGER.warn("{}: {}", ollamaMessage.getRole().getRole(), ollamaMessage.getContent());
if(sourceStack != null) {
sourceStack.sendSystemMessage(Component.literal(ollamaMessage.getRole().getRole() + "> " + ollamaMessage.getContent()));
}
}
@Override
public void printToolCalling(String s) {
//LOGGER.warn("Tool calling: {}", s);
//if(sourceStack != null) {
// sourceStack.sendSystemMessage(Component.literal("Tool calling: " + s));
// We will not send any info about tool info bc well fuck that :)
}
};
private static Core core;
// 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 Ollama(IEventBus modEventBus, ModContainer modContainer) {
// Register the commonSetup method for modloading
modEventBus.addListener(this::commonSetup);
// Register ourselves for server and other game events we are interested in.
// Note that this is necessary if and only if we want *this* class (Ollama) to respond directly to events.
// Do not add this line if there are no @SubscribeEvent-annotated functions in this class, like onServerStarting() below.
NeoForge.EVENT_BUS.register(this);
}
private void commonSetup(final FMLCommonSetupEvent event) {
// Some common setup code
LOGGER.info("HELLO FROM COMMON SETUP");
Path ollamaPath = FMLPaths.CONFIGDIR.get().resolve("ollama");
if (!Files.exists(ollamaPath)) {
try {
Files.createDirectory(ollamaPath);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Core.setDataDirectory(ollamaPath.toString(), true);
Core.setLogDirectory(ollamaPath.toString() + "/logs");
LaunchOptions.getInstance().setLoadOld(false);
initOllama();
}
private void initOllama() {
core = new Core(printAdvanceMessageHandler, "127.0.0.1");
core.setOllamaObjectNoMemory(OllamaObject.builder()
.setModel("llama3.2")
.keep_alive(10)
.addMessage(new OllamaMessage(OllamaMessageRole.SYSTEM, "You are an assistant named \"Merl\" who is tasked to help the player in Minecraft"))
.build());
core.addTool(new GetItemTool(), Core.Source.CTP);
core.addTool(new GetLocation(), Core.Source.CTP);
core.addTool(new getPlayerInventory(), Core.Source.CTP);
}
// You can use SubscribeEvent and let the Event Bus discover methods to call
@SubscribeEvent
public void onServerStarting(ServerStartingEvent event) {
// Do something when the server starts
LOGGER.info("HELLO from server starting");
}
@SubscribeEvent
public void registercommands(RegisterCommandsEvent event) {
event.getDispatcher().register(Commands.literal("chat")
.then(Commands.argument("message", StringArgumentType.greedyString())
.executes(context -> {
String message = StringArgumentType.getString(context, "message");
sourceStack = context.getSource();
core.getOllamaObject().addMessage(new OllamaMessage(OllamaMessageRole.USER, message));
core.handleResponse(core.qurryOllama());
return 1;
})
));
event.getDispatcher().register(Commands.literal("reset")
.executes(context -> {
initOllama();
return 1;
}));
}
// You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent
@EventBusSubscriber(modid = MODID, value = Dist.CLIENT)
public static class ClientModEvents {
@SubscribeEvent
public static void onClientSetup(FMLClientSetupEvent event) {
// Some client setup code
LOGGER.info("HELLO FROM CLIENT SETUP");
LOGGER.info("MINECRAFT NAME >> {}", Minecraft.getInstance().getUser().getName());
}
}
}
@@ -0,0 +1,65 @@
package me.zacharias.ollama;
import me.neurodock.ollama.OllamaFunctionArgument;
import me.neurodock.ollama.OllamaFunctionTool;
import me.neurodock.ollama.OllamaPerameter;
import me.neurodock.ollama.OllamaToolResponse;
import me.neurodock.ollama.exceptions.OllamaToolErrorException;
import net.minecraft.client.Minecraft;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.SlotAccess;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;
public class getPlayerInventory extends OllamaFunctionTool {
@Override
public @NotNull String name() {
return "getinventory";
}
@Override
public @NotNull OllamaPerameter parameters() {
return OllamaPerameter.empty();
}
@Override
public @NotNull OllamaToolResponse function(OllamaFunctionArgument... ollamaFunctionArguments) {
if(Minecraft.getInstance() == null) {
throw new OllamaToolErrorException(name(), "Minecraft is not initialized");
}
if(Minecraft.getInstance().player == null) {
throw new OllamaToolErrorException(name(), "Player is not initialized");
}
if(Minecraft.getInstance().player.getInventory() == null) {
throw new OllamaToolErrorException(name(), "Selected item is null");
}
JSONObject inventory = new JSONObject();
for(int i = 0; i < Minecraft.getInstance().player.getInventory().getContainerSize(); i++) {
JSONObject item = new JSONObject();
SlotAccess slot = Minecraft.getInstance().player.getInventory().getSlot(i);
if(slot == null) continue;
ItemStack stack = slot.get();
if(stack.getItem() == Items.AIR) continue;
Identifier id = BuiltInRegistries.ITEM.getKey(stack.getItem());
item.put("item", id.toString());
item.put("count", stack.getCount());
item.put("name", stack.getDisplayName().getString());
inventory.put(i+"", item);
}
return new OllamaToolResponse(name(), inventory.toString());
}
}
@@ -0,0 +1,2 @@
{
}
@@ -0,0 +1,79 @@
# 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="https://change.me.to.your.mods.homepage.example.invalid/" #optional
# A file name (in the root of the mod JAR) containing a logo for display
#logoFile="ollama.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 = "BOTH"
# 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,)"