Imported from rurimegu/hasugoods-mod (
AGENTS.md). Install upstream withnpx skills add rurimegu/hasugoods-mod. Copyright stays with the author.
Hasugoods Mod Development Standards (Fabric + Minecraft 1.21.1)
Core Philosophy
The goal is to maintain a professional, scalable, and modular codebase for the Hasugoods mod. AI assistants and contributors must prioritize code reuse, strict organization, and future-proofing through Data Generation.
1. Code Duplication & Generalization
- Library First: Do not write the same logic twice. If a utility (e.g., custom tooltips, NBT/Component wrappers, or math helpers) is needed in two places, move it to a reusable class in
dev.rurino.hasugoods.utilor the relevant folder. - Generic Implementations: Create base classes for recurring patterns (e.g., a
NesoBaseBlockorAbstractNesoBaseBlock) to consolidate shared logic.
2. Folder Structure & Management
Strictly adhere to the existing folder hierarchy. Create new sub-packages for distinct features to keep the root packages clean.
3. Modularity & Focused Files
- Small Files: Classes should focus on a single responsibility. If a class handles both "Block Logic" and "UI Logic," split the UI into a separate
ScreenHandlerorHelper. - Helper Classes & Methods: Extract complex logic into dedicated utility classes & methods.
- 1.21.1 Components: Favor the new Data Components system over legacy NBT for storing item data.
- NBT tags: In places where NBT tags cannot be replaced by Data Components, use
camelCasefor NBT tag keys.
4. Constant Management (No Hardcoding)
Hardcoded strings and magic numbers are prohibited.
- Global Level: Place the
MOD_IDand global configuration keys inHasugoods.java. - Class Level: Place registry keys (
RegistryKey), default values, and settings aspublic static finalfields within the class they define. - Resource Keys: Use the centralized constants when registering items, blocks, or entities to ensure consistency.
5. Data Generation (Datagen)
- Preference: All assets (Models, Blockstates) and data (Recipes, Loot Tables, Tags) must be generated via
FabricDataGenerator. - Upgrade Path: Using Datagen ensures that moving to 1.22+ will only require updating the generator logic rather than hundreds of manual JSON files.
- Workflow: Add entries to the relevant
Providerclass incom.hasugoods.datagenand run./gradlew runDatagen. - Manual JSON editing Only manually add / edit JSON files in in
src/main/resourcesif absolutely necessary, for features that are not supported by datagen yet.
6. Server & Client
- Server-side: Make sure server-side logic doesn't accidentally run on the client side with runtime or build time checks.
- Communication: Send necessary data to the client for rendering purposes, etc.
- Persistent data: Persist data wherever necessary. Do not store persistent states in member variables that will be lost when the game restarts.
- Converting between item and entity: The nesos can exist as items and entities. Make sure you persist the data during conversion. Since items use data components while entities use third party entity data components / NBT tags, you need to manually copy the data from one to the other.
7. Animation
- Client-side animation: Complex animation should be calculated on the client side, with utils in
dev.rurino.hasugoods.util.animation. Feel free to extend this library to support more complex animations. - Server-side update: Do not update the animation per tick on the server side; only send the state changes to the client, and let the client calculate the animation with
dev.rurino.hasugoods.util.animation.StateMachine. - Simple animation: Simple animation should be calculated on the client side as well, but
StateMachinemight be unnecessary.
Compliance Checklist for AI
- No Hardcoding: Did I move that string to a static constant?
- Modular: Is this file or function getting too large? Should I create a Helper class or method?
- Datagen: Did I write the script to generate the JSON instead of the JSON itself?
- DRY: Does a utility already exist in
com.hasugoods.utilfor this? - Server-side: Did I make sure server-side logic doesn't accidentally run on the client side with runtime or build time checks?
- Communication: Did I send necessary data to the client for rendering purposes, etc.?
- Persistent data: Did I persist data and write it to the game save wherever necessary? Did I persist data when converting between item and entity?
- Animation: Did I calculate the animation on the client side, and only send the state changes to the client?