Balm Mod

Development Learn more about Balm Mod.

Getting Started with Balm as a Mod Developer

Cartoon rhythm game scene in a purple room

Getting started with Balm as a mod developer is best approached as a small, reproducible experiment in the target Minecraft and loader environments. Choose the supported project setup described by the official documentation, establish a clean build, add one testable behaviour, and verify the produced artifacts outside the development run. This guide focuses on planning and validation rather than copying version-specific dependency declarations that may not fit your project. The aim is a foundation you understand well enough to extend, debug, and release responsibly.

Define a narrow first development goal

Write down one behaviour you want to implement and how you will recognise that it works. Avoid beginning with an entire mod migration or a large collection of unrelated features. A small goal makes the development loop easier to inspect and lets you distinguish setup failures from mistakes in your own code. Choose a behaviour you can exercise quickly in a disposable test world. The first milestone should establish a repeatable process, not an impressive feature count.

Identify target game and loader environments

List the Minecraft version and intended loaders before selecting a template or documentation branch. Multi-loader support is a set of environments to verify, not a label that removes the need for individual checks. If you plan to support several combinations, record them explicitly. Start with a manageable scope and expand only when the workflow is understood. A clear target list prevents dependency declarations from one game version being copied into another project without their surrounding assumptions.

Separate player installation from development dependencies

A playable mod JAR and a development project solve different tasks. A player's mods folder does not establish a source workspace, build tool configuration, mappings, or test environment. Likewise, a successful development setup does not prove a produced file works in a clean player installation. Our Balm JAR and source ZIP guide explains the deliverable distinction. Keep these workflows separate from the beginning so later tests can verify each stage clearly.

Read the official project setup before copying code

Use the documentation, examples, and template resources identified by the project for your target environment. Inspect their stated prerequisites and build instructions. An example found in a search result may target another game version or an earlier API. Do not combine snippets solely because each one mentions Balm. Establish which revision and environment the example belongs to, then follow one coherent starting point until you have a working baseline you can understand and reproduce.

Check version-specific instructions carefully

Dependency coordinates, plugin versions, runtime requirements, and project layouts can change between targets. Read the instructions associated with the chosen setup rather than assuming a tutorial's values remain current. Record the relevant versions in the project. This guide intentionally avoids prescribing a universal build snippet because the correct declaration depends on the target environment and project guidance. A valid development configuration is one whose components fit together, not a collection of individually familiar lines copied from unrelated examples.

Inspect examples as working relationships

When reading example code, identify which files are shared, which belong to a loader-specific part, and how the build connects them. Understand the purpose of a declaration before editing it. A small successful example can teach more than a large unexplained copy. Keep notes about why a component exists and which target uses it. This helps you maintain the setup later, when a build error requires reasoning about relationships rather than searching for another snippet to paste.

Create an isolated development workspace

Keep the experiment separate from your main mod project and personal gameplay instance. Use version control or another clear revision record so changes can be compared and reversed. Preserve the starting template's provenance and applicable licence information. Set up the documented toolchain and run the initial build before adding your own behaviour. A clean baseline confirms that the environment can build the starting project and gives subsequent errors a more specific comparison point.

Verify the baseline before extending it

Run the documented build and development launch tasks for the initial target. Record the commands and outcomes. If the untouched starting project fails, resolve that setup issue before adding feature code. Otherwise, you risk debugging your implementation and the environment at the same time. A baseline need not contain your desired feature, but it should establish a working build and launch process whose expected behaviour you can recognise and repeat.

Keep generated output separate from source changes

Understand which directories contain source material, generated files, caches, and produced artifacts. Do not edit generated output as a substitute for correcting source or configuration. Keep the workspace organised enough that a clean build can recreate the output. If a manual adjustment is genuinely part of the documented process, record it. A development setup that works only because of an untracked local edit is difficult to reproduce and can fail unexpectedly on another machine or after cleanup.

Understand the role of shared library code

A supporting library gives a project reusable functionality through defined interfaces. Wikipedia's software library overview provides general background. In your experiment, focus on which behaviour the selected Balm API is intended to provide and what assumptions its documentation makes. Do not treat a shared interface as proof that every surrounding detail behaves identically in every environment. Read the contract, use the documented approach, and verify the actual behaviour on each target you intend to support.

Distinguish API usage from project architecture

Calling a library function is one part of development. Structuring source sets, selecting dependency versions, producing loader-specific artifacts, and declaring runtime requirements are related but separate concerns. Keep each understandable. A feature may compile while the packaging or declaration remains incorrect. Conversely, a packaging issue may prevent a correct implementation from reaching runtime. Distinguishing these stages gives build and launch failures a clearer place in the investigation and prevents every error from being labelled an API problem.

Avoid inventing compatibility from a successful compile

Compilation establishes that a particular source configuration passed that stage with its selected dependencies. It does not establish successful runtime behaviour in every environment. Some problems appear only during startup, world loading, interaction, or server deployment. Treat compilation as one checkpoint in the development process. Define the later checks before making support claims so that a project described as multi-loader has evidence for the specific target combinations you actually intend to publish.

Implement one testable behaviour

Add the smallest change that demonstrates your first goal using the documented API for your target. Keep unrelated refactoring and feature additions out of the same experiment. Write down how to trigger the behaviour and what result you expect. If the result differs, compare with the last working revision. A focused change provides a manageable debugging surface and helps you learn the relationship between the library call, project setup, and observed game behaviour without hiding it inside a large migration.

Keep shared and loader-specific decisions explicit

Follow the selected project's structure and identify any behaviour that needs environment-specific handling. Do not force every implementation detail into shared code simply to preserve the appearance of uniformity. Conversely, do not duplicate code without understanding whether the library already provides an appropriate abstraction. The useful outcome is maintainable behaviour with clear responsibilities. Let the documented API and observed requirements guide the division, and record the decisions that future maintenance will need to revisit.

Use diagnostic output with a purpose

Add only the diagnostics needed to identify whether the intended action occurred and where a failure begins. Avoid flooding logs with unrelated output that obscures the important event. Keep temporary investigation aids distinguishable from release behaviour. When a test fails, preserve the relevant report and revision so you can compare it with the baseline. Diagnostic information is most valuable when it answers a specific question about the code path or environment being tested.

Test each intended loader environment

Run the feature in the development environment for each target in your support list. Record game and loader versions, the source revision, and the outcome of the same behavioural test. If a target has not been checked, mark it untested instead of inferring support from another target's success. The test should exercise the intended interaction, not only the main menu. Consistent steps across targets make differences easier to identify and keep support claims tied to observations.

Add server testing where the feature requires it

If the feature's documented role involves a dedicated server or shared client-server behaviour, include those environments in the plan. A local development run may not establish dedicated-server compatibility or correct interaction between independently configured clients and servers. Use a controlled test pair and record both sides. Keep private addresses and credentials out of published reports. The test scope should follow what the feature actually does rather than a blanket assumption that every mod behaves the same way in all deployments.

Save reproducible failure cases

When a target fails, record the smallest setup and steps that reproduce the issue. Distinguish a source implementation problem from an unmet dependency or environment requirement. Our Balm bug reporting guide explains how to organise that evidence if you need help. Do not present a library defect as confirmed merely because a stack trace mentions it. A precise reproduction and environment record provide a stronger basis for investigation than an unsupported root-cause claim.

Build and inspect the release artifacts

Use the documented build workflow to produce the artifacts intended for distribution. Identify which output corresponds to each target and which files are development, source, or auxiliary artifacts. Do not choose the first JAR in a build directory without understanding its role. Preserve original output identities while testing. A project can produce several archives for different purposes, and confusing them can make a valid implementation appear broken in a player's clean instance.

Test outside the development run

Install the intended runtime artifact into a clean compatible instance with the documented dependencies. Verify startup and repeat the feature test. This checks packaging and runtime declarations as well as implementation. A development environment can supply components implicitly that a player does not receive. If the clean test requires an undocumented manual repair, fix the project or release instructions and repeat it. Do not treat your knowledge of the repair as a substitute for a reproducible deliverable.

Check dependency declarations and user instructions

State the supported game and loader versions and required libraries clearly in the release metadata and documentation appropriate to the platform. Avoid instructions that simply tell players to obtain the latest everything. The published requirement should describe a compatible environment that corresponds to what you tested. Keep examples accurate and distinguish optional integrations from mandatory components. Clear declarations reduce preventable installation errors and give support discussions a shared reference when a user reports a mismatch.

Review provenance, licences, and release claims

Before sharing a project, review the licences of the template, library, copied examples, and any assets. Do not assume that permission for source code automatically extends unchanged to icons or compiled files. Preserve required notices and describe your own project without implying endorsement by the library's author. Document known limitations and untested environments. A professional release communicates what the artifact is, which setup it supports, and what was verified, without promising universal compatibility you have not established.

Example: moving from a small experiment to a release

Imagine implementing one interaction in a fresh template. The untouched project builds, your change works in the first development target, and you repeat the same test in the other intended environments. You then build the runtime artifacts, install each in a clean instance with declared dependencies, and verify the interaction again. Any packaging failure is corrected before publication. The final notes identify the source revision, target environments, artifacts, requirements, and behavioural checks that justify the release.

That sequence creates a maintainable foundation. You can now add another feature against a known baseline rather than extending an unexplained setup whose first success depended on local caches or hidden files. Keep the tests proportional to the behaviour and revisit the compatibility record when target versions change. The central habit is to connect each development claim to a reproducible result: a build, a launch, a specific interaction, and a clean installation of the actual artifact you intend people to use.

Keep the next development step as reproducible as the first

Before adding another feature, preserve the successful revision and the commands used to build and verify it. Describe the behaviour already covered and any environment not yet checked. Then define the next small change and its expected observation. This keeps growth incremental without pretending that a successful first experiment establishes every future compatibility claim. When a later change fails, you have an understandable baseline and a narrow difference to investigate instead of a large project whose working assumptions were never recorded.

Review the clean-install test whenever packaging, dependency declarations, or supported targets change. Those changes can affect players even when the feature implementation remains the same. Keep development-run success and published-artifact success as separate checkpoints. A reproducible project should let another developer obtain the intended source revision, follow the documented setup, produce the expected runtime artifact, and repeat the relevant behavioural test. That practical standard supports collaboration and release maintenance without requiring inflated claims about universal support or an unnecessarily complicated process for a small, well-defined feature.