chore: align ore drops and XP with vanilla 1.21 and add AGENTS.md guide
This commit is contained in:
@@ -0,0 +1,172 @@
|
|||||||
|
# Custom Ore Gem - Developer Guide for Agents
|
||||||
|
|
||||||
|
This repository is a Minecraft **NeoForge 1.21.1** mod created with **MCreator**. Agents must follow these strict guidelines to ensure build stability and code preservation.
|
||||||
|
|
||||||
|
## 1. Build & Test Commands
|
||||||
|
|
||||||
|
Use the Gradle wrapper for all operations. Ensure you are using Java 21 (NeoForge 1.21.1 requirement).
|
||||||
|
|
||||||
|
- **Build Mod:**
|
||||||
|
```bash
|
||||||
|
./gradlew build
|
||||||
|
```
|
||||||
|
- Generates the mod JAR in `build/libs/`.
|
||||||
|
- Always run this after making changes to verify compilation.
|
||||||
|
|
||||||
|
- **Run Client:**
|
||||||
|
```bash
|
||||||
|
./gradlew runClient
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Run Server:**
|
||||||
|
```bash
|
||||||
|
./gradlew runServer
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Run Data Generation:**
|
||||||
|
```bash
|
||||||
|
./gradlew runData
|
||||||
|
```
|
||||||
|
- This generates resources (blockstates, models, loot tables) into `src/generated/resources`.
|
||||||
|
|
||||||
|
- **Run All Tests:**
|
||||||
|
```bash
|
||||||
|
./gradlew test
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Run Single Test Class:**
|
||||||
|
```bash
|
||||||
|
./gradlew test --tests "net.mcreator.customoregen.OresCommandTest"
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Run Single Test Method:**
|
||||||
|
```bash
|
||||||
|
./gradlew test --tests "net.mcreator.customoregen.OresCommandTest.testCommandRegistration_ShouldRegisterOresCommand"
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Clean Project:**
|
||||||
|
```bash
|
||||||
|
./gradlew clean
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. MCreator & Code Preservation
|
||||||
|
|
||||||
|
**CRITICAL:** This project is partially generated by MCreator.
|
||||||
|
- **Generated Files:** Many files in `src/main/java` are regenerated on every build or MCreator export.
|
||||||
|
- **User Code Blocks:** You **MUST** only edit code within designated user code blocks in these files.
|
||||||
|
```java
|
||||||
|
// Start of user code block [block_name]
|
||||||
|
// ... YOUR CODE HERE ...
|
||||||
|
// End of user code block [block_name]
|
||||||
|
```
|
||||||
|
- If a file does not have these blocks, assume it is **UNSAFE** to edit unless you created it yourself.
|
||||||
|
|
||||||
|
- **Safe Files:**
|
||||||
|
- Files strictly created by you (e.g., in `src/test/java`).
|
||||||
|
- New utility classes or event handlers not managed by MCreator.
|
||||||
|
|
||||||
|
- **Do NOT** directly modify the following unless inside a user block:
|
||||||
|
- `CustomOreGenModBlocks.java`
|
||||||
|
- `CustomOreGenModItems.java`
|
||||||
|
- `CustomOreGenModTabs.java`
|
||||||
|
- Any file in `net.mcreator.customoregen.procedures` (unless explicitly safe).
|
||||||
|
|
||||||
|
## 3. Code Style & Conventions
|
||||||
|
|
||||||
|
### Formatting
|
||||||
|
- **Indentation:**
|
||||||
|
- **Source Code (`src/main`):** Use **TABS** (default MCreator style).
|
||||||
|
- **Tests (`src/test`):** Use **4 SPACES** (typical for JUnit tests).
|
||||||
|
- **Consistency:** Always check the current file's indentation before editing.
|
||||||
|
- **Encoding:** UTF-8.
|
||||||
|
|
||||||
|
### Naming
|
||||||
|
- **Classes:** PascalCase (e.g., `CustomOreGenMod`).
|
||||||
|
- **Methods:** camelCase (e.g., `queueServerWork`).
|
||||||
|
- **Constants:** UPPER_SNAKE_CASE (e.g., `MODID`, `COLD_BIOMES_TAG`).
|
||||||
|
- **Fields:** camelCase (e.g., `workQueue`, `oreGenConfig`).
|
||||||
|
- **Packages:** `net.mcreator.customoregen` (lowercase).
|
||||||
|
|
||||||
|
### Imports
|
||||||
|
- Group imports in this specific order:
|
||||||
|
1. Java/Standard Libraries (`java.*`, `javax.*`)
|
||||||
|
2. Third-party Libraries (e.g., `org.apache.logging.log4j.*`)
|
||||||
|
3. Minecraft/NeoForge (`net.minecraft.*`, `net.neoforged.*`)
|
||||||
|
4. Project Classes (`net.mcreator.customoregen.*`)
|
||||||
|
- Avoid `import *` unless there are many imports from the same package (e.g., `java.util.*` is acceptable if heavily used, but explicit imports are preferred for clarity).
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
- Use `LogManager.getLogger(Class.class)` for loggers.
|
||||||
|
- Field name: `LOGGER`.
|
||||||
|
- Log levels: Use `debug` for dev info, `info` for general status, `error` for exceptions.
|
||||||
|
|
||||||
|
## 4. Architecture & Patterns
|
||||||
|
|
||||||
|
- **Framework:** NeoForge 1.21.1 (Java 21).
|
||||||
|
- **Registries:** Use `DeferredRegister` for all registries (Blocks, Items, Tabs, SoundEvents).
|
||||||
|
- Example: `public static final DeferredRegister.Blocks REGISTRY = DeferredRegister.createBlocks(CustomOreGenMod.MODID);`
|
||||||
|
|
||||||
|
- **Event Bus:**
|
||||||
|
- The `@Mod` class registers the `IEventBus`.
|
||||||
|
- Use `@SubscribeEvent` for event handling.
|
||||||
|
- Event handlers often reside in `net.mcreator.customoregen.event` or static inner classes annotated with `@EventBusSubscriber`.
|
||||||
|
|
||||||
|
- **Configuration:**
|
||||||
|
- Located in `net.mcreator.customoregen.config.ModConfigs`.
|
||||||
|
- Uses `ModConfig.Type.COMMON` built with `ModConfigSpec`.
|
||||||
|
- Access configs via the public static fields (e.g., `ModConfigs.ORE_GEN.shardDiamondOreCount.get()`).
|
||||||
|
|
||||||
|
- **Commands:**
|
||||||
|
- Registered via `RegisterCommandsEvent`.
|
||||||
|
- Use Brigadier (`CommandDispatcher`, `CommandContext`).
|
||||||
|
- See `OresCommand.java` for the reference implementation.
|
||||||
|
|
||||||
|
## 5. Testing Guidelines
|
||||||
|
|
||||||
|
- **Framework:** JUnit 5 (Jupiter) + Mockito.
|
||||||
|
- **Location:** `src/test/java`.
|
||||||
|
- **Mocking Strategy:**
|
||||||
|
- Since a full Minecraft environment is not available in unit tests, you **MUST** mock Minecraft classes.
|
||||||
|
- Use `@ExtendWith(MockitoExtension.class)`.
|
||||||
|
- Mock critical classes: `@Mock ServerPlayer player`, `@Mock Level level`, `@Mock BlockPos pos`.
|
||||||
|
- Stub methods: `when(level.getBiome(pos)).thenReturn(biomeHolder);`.
|
||||||
|
- **Assertions:** Use `org.junit.jupiter.api.Assertions` (e.g., `assertEquals`, `assertDoesNotThrow`).
|
||||||
|
|
||||||
|
## 6. Common Tasks
|
||||||
|
|
||||||
|
- **Adding a New Ore:**
|
||||||
|
1. Create Block & Item (MCreator/Manual).
|
||||||
|
2. Add JSONs: Loot Table, Configured Feature, Placed Feature, Biome Modifier.
|
||||||
|
3. Register in `CustomOreGenModBlocks` and `CustomOreGenModItems`.
|
||||||
|
4. Update `OresCommand.java` lists (e.g., `COLD_ORES`, `HOT_ORES`) to make it discoverable.
|
||||||
|
5. Update `OreBreakEventHandler.java` if it has custom drops logic.
|
||||||
|
6. Add to `ModConfigs.java` for generation parameters (vein size, count, etc.).
|
||||||
|
|
||||||
|
- **Modifying Logic:**
|
||||||
|
- Check `procedures/` for game logic (often MCreator generated).
|
||||||
|
- Check `event/` for event-driven logic.
|
||||||
|
- Always verify if logic changes need a corresponding test update.
|
||||||
|
|
||||||
|
## 7. Safety & Verification
|
||||||
|
|
||||||
|
- **Backups:** If you are unsure about MCreator regeneration, backup the file before editing.
|
||||||
|
- **Verification:**
|
||||||
|
- Always run `./gradlew build` after changes to ensure no compilation errors.
|
||||||
|
- If you touch config files, ensure `ModConfigsTest` still passes.
|
||||||
|
- If you touch commands, ensure `OresCommandTest` still passes.
|
||||||
|
|
||||||
|
## 8. Directory Structure
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── main/
|
||||||
|
│ ├── java/net/mcreator/customoregen/
|
||||||
|
│ │ ├── block/ # Block definitions
|
||||||
|
│ │ ├── config/ # Configuration classes
|
||||||
|
│ │ ├── event/ # Event handlers
|
||||||
|
│ │ ├── init/ # Registration (Blocks, Items, Tabs)
|
||||||
|
│ │ ├── item/ # Item definitions
|
||||||
|
│ │ └── procedures/ # Game logic procedures
|
||||||
|
│ └── resources/ # Assets and data (textures, models, lang)
|
||||||
|
└── test/
|
||||||
|
└── java/net/mcreator/customoregen/ # Unit tests
|
||||||
|
```
|
||||||
@@ -57,6 +57,7 @@ net.mcreator.customoregen/
|
|||||||
├── block/ # Ore block classes (17 blocks)
|
├── block/ # Ore block classes (17 blocks)
|
||||||
├── item/ # Items (Diamond Shard, tools, armor, Paxel, OreBiomeFinder)
|
├── item/ # Items (Diamond Shard, tools, armor, Paxel, OreBiomeFinder)
|
||||||
├── config/ # NeoForge configuration system (ModConfigs.java)
|
├── config/ # NeoForge configuration system (ModConfigs.java)
|
||||||
|
├── event/ # Event handlers (OreBreakEventHandler, EnchantabilityFix)
|
||||||
├── procedures/ # Game logic (ConfigurableOreDropsProcedure, OreexperienceProcedure)
|
├── procedures/ # Game logic (ConfigurableOreDropsProcedure, OreexperienceProcedure)
|
||||||
└── init/
|
└── init/
|
||||||
├── CustomOreGenModBlocks.java # Block registry (deferred register)
|
├── CustomOreGenModBlocks.java # Block registry (deferred register)
|
||||||
@@ -76,13 +77,13 @@ The mod uses **NeoForge** biome modifiers to distribute ores based on biome temp
|
|||||||
- `tempered_biomes.json` - Temperate biomes (iron, concentrated coal)
|
- `tempered_biomes.json` - Temperate biomes (iron, concentrated coal)
|
||||||
- BOP biomes are included with `"required": false` for optional compatibility
|
- BOP biomes are included with `"required": false` for optional compatibility
|
||||||
|
|
||||||
2. **Biome Modifiers** (`src/main/resources/data/custom_ore_gen/forge/biome_modifier/`):
|
2. **Biome Modifiers** (`src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/`):
|
||||||
- Each ore has a JSON file linking it to biome tags
|
- Each ore has a JSON file linking it to biome tags
|
||||||
- Special case: `deepslatesharddiamondore_biome_modifier.json` uses `"type": "forge:any"` for all biomes
|
- Special case: `deepslatesharddiamondore_biome_modifier.json` uses `"type": "forge:any"` for all biomes
|
||||||
- **JSON Structure**:
|
- **JSON Structure**:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"type": "forge:add_features",
|
"type": "neoforge:add_features",
|
||||||
"biomes": "custom_ore_gen:cold_biomes", // or {"type": "forge:any"} for all biomes
|
"biomes": "custom_ore_gen:cold_biomes", // or {"type": "forge:any"} for all biomes
|
||||||
"features": "custom_ore_gen:deepslatesharddiamondore",
|
"features": "custom_ore_gen:deepslatesharddiamondore",
|
||||||
"step": "underground_ores"
|
"step": "underground_ores"
|
||||||
@@ -111,10 +112,11 @@ Located in `src/main/java/net/mcreator/customoregen/config/`:
|
|||||||
- Generated config file: `config/custom_ore_gen-common.toml` (created on first run)
|
- Generated config file: `config/custom_ore_gen-common.toml` (created on first run)
|
||||||
|
|
||||||
**Current Implementation Status**:
|
**Current Implementation Status**:
|
||||||
|
- **✅ Ore Drops**: Fully implemented via `OreBreakEventHandler.java` which listens to `BlockEvent.BreakEvent` and calls `ConfigurableOreDropsProcedure.execute()` for all custom ores
|
||||||
- **⚠️ Tool Stats**: Config classes exist in `ModConfigs.java`, but tools currently have hardcoded values (e.g., `SharddiamondpickaxeItem.java:18` has `return 200` for durability). Config reading not yet implemented.
|
- **⚠️ Tool Stats**: Config classes exist in `ModConfigs.java`, but tools currently have hardcoded values (e.g., `SharddiamondpickaxeItem.java:18` has `return 200` for durability). Config reading not yet implemented.
|
||||||
- **⚠️ Ore Drops**: `ConfigurableOreDropsProcedure.java` exists but requires MCreator integration to link to block loot tables
|
|
||||||
- **⚠️ Feature Toggles**: Defined in `FeatureToggleConfig` but not yet wired to block/item registration conditional logic
|
- **⚠️ Feature Toggles**: Defined in `FeatureToggleConfig` but not yet wired to block/item registration conditional logic
|
||||||
- **⚠️ Ore Generation**: Config values exist but worldgen JSON files still use hardcoded values
|
- **⚠️ Ore Generation**: Config values exist but worldgen JSON files still use hardcoded values
|
||||||
|
- **⚠️ Enchantability**: `EnchantabilityFix.java` exists but is commented out - enchantment values not yet applied to items
|
||||||
|
|
||||||
### Ore Biome Finder
|
### Ore Biome Finder
|
||||||
|
|
||||||
@@ -131,12 +133,13 @@ The `OreBiomeFinderItem` (`item/OreBiomeFinderItem.java`) and `/ores` command (`
|
|||||||
To add a new ore type (requires MCreator for full integration):
|
To add a new ore type (requires MCreator for full integration):
|
||||||
|
|
||||||
1. **Create the block** in MCreator with proper properties (sound type, harvest level, etc.)
|
1. **Create the block** in MCreator with proper properties (sound type, harvest level, etc.)
|
||||||
2. **Add loot table** at `src/main/resources/data/custom_ore_gen/loot_tables/blocks/{orename}.json`
|
2. **Add loot table** at `src/main/resources/data/custom_ore_gen/loot_table/blocks/{orename}.json` (note: `loot_table` not `loot_tables`)
|
||||||
3. **Add configured_feature** JSON in `src/main/resources/data/custom_ore_gen/worldgen/configured_feature/`
|
3. **Add configured_feature** JSON in `src/main/resources/data/custom_ore_gen/worldgen/configured_feature/`
|
||||||
4. **Add placed_feature** JSON in `src/main/resources/data/custom_ore_gen/worldgen/placed_feature/`
|
4. **Add placed_feature** JSON in `src/main/resources/data/custom_ore_gen/worldgen/placed_feature/`
|
||||||
5. **Create biome_modifier** JSON in `src/main/resources/data/custom_ore_gen/forge/biome_modifier/` linking to a biome tag (or create a new tag in `tags/worldgen/biome/`)
|
5. **Create biome_modifier** JSON in `src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/` linking to a biome tag (or create a new tag in `tags/worldgen/biome/`)
|
||||||
6. **Add BOP entries** (optional) to appropriate biome tag JSON files with `"required": false` wrapper
|
6. **Add BOP entries** (optional) to appropriate biome tag JSON files with `"required": false` wrapper
|
||||||
7. **Update `OreBiomeFinderItem.java`** to add the new ore to the appropriate category list
|
7. **Update `OreBiomeFinderItem.java`** to add the new ore to the appropriate category list
|
||||||
|
8. **Add ore type mapping** in `OreBreakEventHandler.java` if you want configurable drops via `ConfigurableOreDropsProcedure`
|
||||||
|
|
||||||
## User Code Sections
|
## User Code Sections
|
||||||
|
|
||||||
@@ -156,6 +159,36 @@ public static final Supplier<Item> ORE_BIOME_FINDER = REGISTRY.register("ore_bio
|
|||||||
|
|
||||||
**Important**: Custom items like the Ore Biome Finder, Shard Diamond armor, and Paxel are registered in this protected section and will survive MCreator rebuilds.
|
**Important**: Custom items like the Ore Biome Finder, Shard Diamond armor, and Paxel are registered in this protected section and will survive MCreator rebuilds.
|
||||||
|
|
||||||
|
## Event Handlers
|
||||||
|
|
||||||
|
The mod uses NeoForge's event system for ore processing:
|
||||||
|
|
||||||
|
### OreBreakEventHandler
|
||||||
|
- Listens to `BlockEvent.BreakEvent` with `@SubscribeEvent`
|
||||||
|
- Maps custom ore blocks to ore type strings (`shard_diamond`, `concentrated_coal`, `pure_golden`, etc.)
|
||||||
|
- Calls `ConfigurableOreDropsProcedure.execute()` with ore type when player breaks ore with correct tool
|
||||||
|
- Supports 10 ore types: shard_diamond, concentrated_coal, pure_golden, impure_iron, concentrated_diamond, lapis, redstone, emerald, copper
|
||||||
|
|
||||||
|
### EnchantabilityFix
|
||||||
|
- Uses `ModifyDefaultComponentsEvent` to set enchantability values on tools and armor
|
||||||
|
- Currently **commented out** - enchantability not yet applied
|
||||||
|
- When active, should set `DataComponents.ENCHANTABLE` with value 9 (tools) or 14 (armor)
|
||||||
|
|
||||||
|
## Loot Table Format
|
||||||
|
|
||||||
|
NeoForge 1.21 uses `loot_table` (singular) instead of `loot_tables` (plural):
|
||||||
|
- Location: `src/main/resources/data/custom_ore_gen/loot_table/blocks/{orename}.json`
|
||||||
|
- Includes Silk Touch support via `match_tool` condition
|
||||||
|
- Uses `random_sequence` for loot table randomization
|
||||||
|
- Example structure in `deepslatesharddiamondore.json` shows Silk Touch → drop block, otherwise drops handled by `OreBreakEventHandler`
|
||||||
|
|
||||||
|
## Vanilla Ore Removal
|
||||||
|
|
||||||
|
The mod removes vanilla ores via NeoForge biome modifiers (NOT KubeJS anymore):
|
||||||
|
- `src/main/resources/data/custom_ore_gen/neoforge/biome_modifier/remove_vanilla_ores.json`
|
||||||
|
- Uses `neoforge:remove_features` type to remove vanilla ore generation
|
||||||
|
- This replaces the old KubeJS automatic script system from Forge 1.20.1
|
||||||
|
|
||||||
## Biomes O' Plenty Integration
|
## Biomes O' Plenty Integration
|
||||||
|
|
||||||
The mod includes BOP biome support through biome tag entries. BOP biomes are wrapped with:
|
The mod includes BOP biome support through biome tag entries. BOP biomes are wrapped with:
|
||||||
@@ -175,6 +208,16 @@ After making changes:
|
|||||||
2. Run `./gradlew runClient` to test in-game
|
2. Run `./gradlew runClient` to test in-game
|
||||||
3. Check logs in `run/logs/` for errors
|
3. Check logs in `run/logs/` for errors
|
||||||
|
|
||||||
|
## Enchantment Tags
|
||||||
|
|
||||||
|
The mod includes enchantment tags at `src/main/resources/data/minecraft/tags/item/enchantable/`:
|
||||||
|
- **armor.json** - Marks Shard Diamond armor pieces as enchantable
|
||||||
|
- **durability.json** - Marks tools and armor for durability enchantments
|
||||||
|
- **mining.json** - Marks pickaxes, shovels, and paxel as mining tools
|
||||||
|
- **weapon.json** - Marks axes as weapons
|
||||||
|
|
||||||
|
These tags enable proper enchantment behavior for custom items in the enchanting table and anvil.
|
||||||
|
|
||||||
## Important Notes
|
## Important Notes
|
||||||
|
|
||||||
### README Disclaimer
|
### README Disclaimer
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
org.gradle.jvmargs=-Xmx4G
|
org.gradle.jvmargs=-Xmx4G
|
||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
|
org.gradle.java.home=C:\\Program Files\\Java\\jdk-24
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version=3.0
|
mod_version=3.0
|
||||||
|
|||||||
@@ -189,6 +189,7 @@ public class ModConfigs {
|
|||||||
|
|
||||||
public final ModConfigSpec.ConfigValue<Integer> concentratedCoalOreMinDrops;
|
public final ModConfigSpec.ConfigValue<Integer> concentratedCoalOreMinDrops;
|
||||||
public final ModConfigSpec.ConfigValue<Integer> concentratedCoalOreMaxDrops;
|
public final ModConfigSpec.ConfigValue<Integer> concentratedCoalOreMaxDrops;
|
||||||
|
public final ModConfigSpec.BooleanValue concentratedCoalOreEnableFortune;
|
||||||
|
|
||||||
public final ModConfigSpec.ConfigValue<Integer> pureGoldenOreMinDrops;
|
public final ModConfigSpec.ConfigValue<Integer> pureGoldenOreMinDrops;
|
||||||
public final ModConfigSpec.ConfigValue<Integer> pureGoldenOreMaxDrops;
|
public final ModConfigSpec.ConfigValue<Integer> pureGoldenOreMaxDrops;
|
||||||
@@ -204,15 +205,18 @@ public class ModConfigs {
|
|||||||
|
|
||||||
public final ModConfigSpec.ConfigValue<Integer> lapisOreMinDrops;
|
public final ModConfigSpec.ConfigValue<Integer> lapisOreMinDrops;
|
||||||
public final ModConfigSpec.ConfigValue<Integer> lapisOreMaxDrops;
|
public final ModConfigSpec.ConfigValue<Integer> lapisOreMaxDrops;
|
||||||
|
public final ModConfigSpec.BooleanValue lapisOreEnableFortune;
|
||||||
|
|
||||||
public final ModConfigSpec.ConfigValue<Integer> redstoneOreMinDrops;
|
public final ModConfigSpec.ConfigValue<Integer> redstoneOreMinDrops;
|
||||||
public final ModConfigSpec.ConfigValue<Integer> redstoneOreMaxDrops;
|
public final ModConfigSpec.ConfigValue<Integer> redstoneOreMaxDrops;
|
||||||
|
public final ModConfigSpec.BooleanValue redstoneOreEnableFortune;
|
||||||
|
|
||||||
public final ModConfigSpec.ConfigValue<Integer> emeraldOreMinDrops;
|
public final ModConfigSpec.ConfigValue<Integer> emeraldOreMinDrops;
|
||||||
public final ModConfigSpec.ConfigValue<Integer> emeraldOreMaxDrops;
|
public final ModConfigSpec.ConfigValue<Integer> emeraldOreMaxDrops;
|
||||||
|
|
||||||
public final ModConfigSpec.ConfigValue<Integer> copperOreMinDrops;
|
public final ModConfigSpec.ConfigValue<Integer> copperOreMinDrops;
|
||||||
public final ModConfigSpec.ConfigValue<Integer> copperOreMaxDrops;
|
public final ModConfigSpec.ConfigValue<Integer> copperOreMaxDrops;
|
||||||
|
public final ModConfigSpec.BooleanValue copperOreEnableFortune;
|
||||||
|
|
||||||
public final ModConfigSpec.ConfigValue<Integer> oreExperienceDrops;
|
public final ModConfigSpec.ConfigValue<Integer> oreExperienceDrops;
|
||||||
|
|
||||||
@@ -234,32 +238,35 @@ public class ModConfigs {
|
|||||||
|
|
||||||
builder.push("concentrated_diamond_ore");
|
builder.push("concentrated_diamond_ore");
|
||||||
concentratedDiamondOreMinDrops = builder
|
concentratedDiamondOreMinDrops = builder
|
||||||
.comment("Minimum diamonds dropped by Concentrated Diamond Ore (default: 1)")
|
.comment("Minimum diamonds dropped by Deepslate Diamond Ore (default: 1) - vanilla equivalent")
|
||||||
.defineInRange("minDrops", 1, 0, 64);
|
.defineInRange("minDrops", 1, 0, 64);
|
||||||
concentratedDiamondOreMaxDrops = builder
|
concentratedDiamondOreMaxDrops = builder
|
||||||
.comment("Maximum diamonds dropped by Concentrated Diamond Ore (default: 2)")
|
.comment("Maximum diamonds dropped by Deepslate Diamond Ore (default: 1) - vanilla equivalent")
|
||||||
.defineInRange("maxDrops", 2, 0, 64);
|
.defineInRange("maxDrops", 1, 0, 64);
|
||||||
concentratedDiamondOreEnableFortune = builder
|
concentratedDiamondOreEnableFortune = builder
|
||||||
.comment("Enable Fortune enchantment on Concentrated Diamond Ore (default: true)")
|
.comment("Enable Fortune enchantment on Deepslate Diamond Ore (default: true) - vanilla equivalent")
|
||||||
.define("enableFortune", true);
|
.define("enableFortune", true);
|
||||||
builder.pop();
|
builder.pop();
|
||||||
|
|
||||||
builder.push("concentrated_coal_ore");
|
builder.push("concentrated_coal_ore");
|
||||||
concentratedCoalOreMinDrops = builder
|
concentratedCoalOreMinDrops = builder
|
||||||
.comment("Minimum coal dropped by Concentrated Coal Ore (default: 2)")
|
.comment("Minimum coal dropped by Concentrated Coal Ore (default: 1) - vanilla equivalent")
|
||||||
.defineInRange("minDrops", 2, 0, 64);
|
.defineInRange("minDrops", 1, 0, 64);
|
||||||
concentratedCoalOreMaxDrops = builder
|
concentratedCoalOreMaxDrops = builder
|
||||||
.comment("Maximum coal dropped by Concentrated Coal Ore (default: 4)")
|
.comment("Maximum coal dropped by Concentrated Coal Ore (default: 1) - vanilla equivalent")
|
||||||
.defineInRange("maxDrops", 4, 0, 64);
|
.defineInRange("maxDrops", 1, 0, 64);
|
||||||
|
concentratedCoalOreEnableFortune = builder
|
||||||
|
.comment("Enable Fortune enchantment on Concentrated Coal Ore (default: true) - vanilla equivalent")
|
||||||
|
.define("enableFortune", true);
|
||||||
builder.pop();
|
builder.pop();
|
||||||
|
|
||||||
builder.push("pure_golden_ore");
|
builder.push("pure_golden_ore");
|
||||||
pureGoldenOreMinDrops = builder
|
pureGoldenOreMinDrops = builder
|
||||||
.comment("Minimum gold nuggets dropped by Pure Golden Ore (default: 2)")
|
.comment("Minimum raw gold dropped by Pure Golden Ore (default: 1) - vanilla equivalent")
|
||||||
.defineInRange("minDrops", 2, 0, 64);
|
.defineInRange("minDrops", 1, 0, 64);
|
||||||
pureGoldenOreMaxDrops = builder
|
pureGoldenOreMaxDrops = builder
|
||||||
.comment("Maximum gold nuggets dropped by Pure Golden Ore (default: 4)")
|
.comment("Maximum raw gold dropped by Pure Golden Ore (default: 1) - vanilla equivalent")
|
||||||
.defineInRange("maxDrops", 4, 0, 64);
|
.defineInRange("maxDrops", 1, 0, 64);
|
||||||
builder.pop();
|
builder.pop();
|
||||||
|
|
||||||
builder.push("ash_coal_ore");
|
builder.push("ash_coal_ore");
|
||||||
@@ -273,44 +280,53 @@ public class ModConfigs {
|
|||||||
|
|
||||||
builder.push("impure_ores");
|
builder.push("impure_ores");
|
||||||
impureIronOreMinDrops = builder
|
impureIronOreMinDrops = builder
|
||||||
.comment("Minimum impure iron dropped by Impure Iron Ore (default: 1)")
|
.comment("Minimum raw iron dropped by Iron Ore (default: 1) - vanilla equivalent")
|
||||||
.defineInRange("ironMinDrops", 1, 0, 64);
|
.defineInRange("ironMinDrops", 1, 0, 64);
|
||||||
impureIronOreMaxDrops = builder
|
impureIronOreMaxDrops = builder
|
||||||
.comment("Maximum impure iron dropped by Impure Iron Ore (default: 2)")
|
.comment("Maximum raw iron dropped by Iron Ore (default: 1) - vanilla equivalent")
|
||||||
.defineInRange("ironMaxDrops", 2, 0, 64);
|
.defineInRange("ironMaxDrops", 1, 0, 64);
|
||||||
impureGoldOreMinDrops = builder
|
impureGoldOreMinDrops = builder
|
||||||
.comment("Minimum impure gold dropped by Impure Gold Ore (default: 1)")
|
.comment("Minimum raw gold dropped by Impure Gold Ore (default: 1)")
|
||||||
.defineInRange("goldMinDrops", 1, 0, 64);
|
.defineInRange("goldMinDrops", 1, 0, 64);
|
||||||
impureGoldOreMaxDrops = builder
|
impureGoldOreMaxDrops = builder
|
||||||
.comment("Maximum impure gold dropped by Impure Gold Ore (default: 2)")
|
.comment("Maximum raw gold dropped by Impure Gold Ore (default: 1)")
|
||||||
.defineInRange("goldMaxDrops", 2, 0, 64);
|
.defineInRange("goldMaxDrops", 1, 0, 64);
|
||||||
builder.pop();
|
builder.pop();
|
||||||
|
|
||||||
builder.push("vanilla_ore_variants");
|
builder.push("vanilla_ore_variants");
|
||||||
lapisOreMinDrops = builder
|
lapisOreMinDrops = builder
|
||||||
.comment("Minimum lapis dropped (default: 4)")
|
.comment("Minimum lapis dropped (default: 4) - vanilla equivalent")
|
||||||
.defineInRange("lapisMinDrops", 4, 0, 64);
|
.defineInRange("lapisMinDrops", 4, 0, 64);
|
||||||
lapisOreMaxDrops = builder
|
lapisOreMaxDrops = builder
|
||||||
.comment("Maximum lapis dropped (default: 9)")
|
.comment("Maximum lapis dropped (default: 9) - vanilla equivalent")
|
||||||
.defineInRange("lapisMaxDrops", 9, 0, 64);
|
.defineInRange("lapisMaxDrops", 9, 0, 64);
|
||||||
|
lapisOreEnableFortune = builder
|
||||||
|
.comment("Enable Fortune enchantment on Lapis Ore (default: true) - vanilla equivalent")
|
||||||
|
.define("enableFortune", true);
|
||||||
redstoneOreMinDrops = builder
|
redstoneOreMinDrops = builder
|
||||||
.comment("Minimum redstone dropped (default: 4)")
|
.comment("Minimum redstone dropped (default: 4) - vanilla equivalent")
|
||||||
.defineInRange("redstoneMinDrops", 4, 0, 64);
|
.defineInRange("redstoneMinDrops", 4, 0, 64);
|
||||||
redstoneOreMaxDrops = builder
|
redstoneOreMaxDrops = builder
|
||||||
.comment("Maximum redstone dropped (default: 5)")
|
.comment("Maximum redstone dropped (default: 5) - vanilla equivalent")
|
||||||
.defineInRange("redstoneMaxDrops", 5, 0, 64);
|
.defineInRange("redstoneMaxDrops", 5, 0, 64);
|
||||||
|
redstoneOreEnableFortune = builder
|
||||||
|
.comment("Enable Fortune enchantment on Redstone Ore (default: true) - vanilla equivalent")
|
||||||
|
.define("enableFortune", true);
|
||||||
emeraldOreMinDrops = builder
|
emeraldOreMinDrops = builder
|
||||||
.comment("Minimum emerald dropped (default: 1)")
|
.comment("Minimum emerald dropped (default: 1) - vanilla equivalent")
|
||||||
.defineInRange("emeraldMinDrops", 1, 0, 64);
|
.defineInRange("emeraldMinDrops", 1, 0, 64);
|
||||||
emeraldOreMaxDrops = builder
|
emeraldOreMaxDrops = builder
|
||||||
.comment("Maximum emerald dropped (default: 1)")
|
.comment("Maximum emerald dropped (default: 1) - vanilla equivalent")
|
||||||
.defineInRange("emeraldMaxDrops", 1, 0, 64);
|
.defineInRange("emeraldMaxDrops", 1, 0, 64);
|
||||||
copperOreMinDrops = builder
|
copperOreMinDrops = builder
|
||||||
.comment("Minimum copper dropped (default: 2)")
|
.comment("Minimum raw copper dropped (default: 2) - vanilla equivalent")
|
||||||
.defineInRange("copperMinDrops", 2, 0, 64);
|
.defineInRange("copperMinDrops", 2, 0, 64);
|
||||||
copperOreMaxDrops = builder
|
copperOreMaxDrops = builder
|
||||||
.comment("Maximum copper dropped (default: 5)")
|
.comment("Maximum raw copper dropped (default: 5) - vanilla equivalent")
|
||||||
.defineInRange("copperMaxDrops", 5, 0, 64);
|
.defineInRange("copperMaxDrops", 5, 0, 64);
|
||||||
|
copperOreEnableFortune = builder
|
||||||
|
.comment("Enable Fortune enchantment on Copper Ore (default: true) - vanilla equivalent")
|
||||||
|
.define("enableFortune", true);
|
||||||
builder.pop();
|
builder.pop();
|
||||||
|
|
||||||
oreExperienceDrops = builder
|
oreExperienceDrops = builder
|
||||||
|
|||||||
+49
-17
@@ -80,13 +80,14 @@ public class ConfigurableOreDropsProcedure {
|
|||||||
case "concentrated_coal":
|
case "concentrated_coal":
|
||||||
minDrops = ModConfigs.DROPS.concentratedCoalOreMinDrops.get();
|
minDrops = ModConfigs.DROPS.concentratedCoalOreMinDrops.get();
|
||||||
maxDrops = ModConfigs.DROPS.concentratedCoalOreMaxDrops.get();
|
maxDrops = ModConfigs.DROPS.concentratedCoalOreMaxDrops.get();
|
||||||
|
enableFortune = ModConfigs.DROPS.concentratedCoalOreEnableFortune.get();
|
||||||
dropItem = new ItemStack(Items.COAL);
|
dropItem = new ItemStack(Items.COAL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "pure_golden":
|
case "pure_golden":
|
||||||
minDrops = ModConfigs.DROPS.pureGoldenOreMinDrops.get();
|
minDrops = ModConfigs.DROPS.pureGoldenOreMinDrops.get();
|
||||||
maxDrops = ModConfigs.DROPS.pureGoldenOreMaxDrops.get();
|
maxDrops = ModConfigs.DROPS.pureGoldenOreMaxDrops.get();
|
||||||
dropItem = new ItemStack(Items.GOLD_NUGGET);
|
dropItem = new ItemStack(Items.RAW_GOLD);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "ash_coal":
|
case "ash_coal":
|
||||||
@@ -98,7 +99,7 @@ public class ConfigurableOreDropsProcedure {
|
|||||||
case "impure_iron":
|
case "impure_iron":
|
||||||
minDrops = ModConfigs.DROPS.impureIronOreMinDrops.get();
|
minDrops = ModConfigs.DROPS.impureIronOreMinDrops.get();
|
||||||
maxDrops = ModConfigs.DROPS.impureIronOreMaxDrops.get();
|
maxDrops = ModConfigs.DROPS.impureIronOreMaxDrops.get();
|
||||||
dropItem = new ItemStack(Items.IRON_NUGGET); // Use iron nugget until IMPUREIRON item is created
|
dropItem = new ItemStack(Items.RAW_IRON);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "impure_gold":
|
case "impure_gold":
|
||||||
@@ -110,12 +111,14 @@ public class ConfigurableOreDropsProcedure {
|
|||||||
case "lapis":
|
case "lapis":
|
||||||
minDrops = ModConfigs.DROPS.lapisOreMinDrops.get();
|
minDrops = ModConfigs.DROPS.lapisOreMinDrops.get();
|
||||||
maxDrops = ModConfigs.DROPS.lapisOreMaxDrops.get();
|
maxDrops = ModConfigs.DROPS.lapisOreMaxDrops.get();
|
||||||
|
enableFortune = ModConfigs.DROPS.lapisOreEnableFortune.get();
|
||||||
dropItem = new ItemStack(Items.LAPIS_LAZULI);
|
dropItem = new ItemStack(Items.LAPIS_LAZULI);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "redstone":
|
case "redstone":
|
||||||
minDrops = ModConfigs.DROPS.redstoneOreMinDrops.get();
|
minDrops = ModConfigs.DROPS.redstoneOreMinDrops.get();
|
||||||
maxDrops = ModConfigs.DROPS.redstoneOreMaxDrops.get();
|
maxDrops = ModConfigs.DROPS.redstoneOreMaxDrops.get();
|
||||||
|
enableFortune = ModConfigs.DROPS.redstoneOreEnableFortune.get();
|
||||||
dropItem = new ItemStack(Items.REDSTONE);
|
dropItem = new ItemStack(Items.REDSTONE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -128,6 +131,7 @@ public class ConfigurableOreDropsProcedure {
|
|||||||
case "copper":
|
case "copper":
|
||||||
minDrops = ModConfigs.DROPS.copperOreMinDrops.get();
|
minDrops = ModConfigs.DROPS.copperOreMinDrops.get();
|
||||||
maxDrops = ModConfigs.DROPS.copperOreMaxDrops.get();
|
maxDrops = ModConfigs.DROPS.copperOreMaxDrops.get();
|
||||||
|
enableFortune = ModConfigs.DROPS.copperOreEnableFortune.get();
|
||||||
dropItem = new ItemStack(Items.RAW_COPPER);
|
dropItem = new ItemStack(Items.RAW_COPPER);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -136,15 +140,23 @@ public class ConfigurableOreDropsProcedure {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate drops
|
// Calculate base drops
|
||||||
int dropCount = minDrops + random.nextInt(maxDrops - minDrops + 1);
|
int dropCount = minDrops + (maxDrops > minDrops ? random.nextInt(maxDrops - minDrops + 1) : 0);
|
||||||
|
|
||||||
// Apply fortune if enabled
|
// Apply fortune if enabled
|
||||||
if (enableFortune && fortuneLevel > 0) {
|
if (enableFortune && fortuneLevel > 0) {
|
||||||
int fortuneBonus = random.nextInt(fortuneLevel + 2) - 1;
|
if (oreType.equals("lapis") || oreType.equals("copper") || oreType.equals("redstone")) {
|
||||||
if (fortuneBonus < 0)
|
// Vanilla-like multiplier for multi-drop ores (Lapis, Copper, Redstone)
|
||||||
fortuneBonus = 0;
|
// Level 3: 2/5 chance of x1, 1/5 chance of x2, 1/5 chance of x3, 1/5 chance of x4
|
||||||
dropCount += fortuneBonus;
|
int multiplier = random.nextInt(fortuneLevel + 2) - 1;
|
||||||
|
if (multiplier < 0) multiplier = 0;
|
||||||
|
dropCount *= (multiplier + 1);
|
||||||
|
} else {
|
||||||
|
// Vanilla-like bonus for discrete ores (Diamond, Coal, Emerald)
|
||||||
|
int fortuneBonus = random.nextInt(fortuneLevel + 2) - 1;
|
||||||
|
if (fortuneBonus < 0) fortuneBonus = 0;
|
||||||
|
dropCount += fortuneBonus;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop the items
|
// Drop the items
|
||||||
@@ -161,15 +173,35 @@ public class ConfigurableOreDropsProcedure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop experience if configured
|
// Drop experience based on ore type (Vanilla 1.21 values)
|
||||||
int expAmount = ModConfigs.DROPS.oreExperienceDrops.get();
|
int expAmount = 0;
|
||||||
if (expAmount > 0 && entity instanceof Player) {
|
if (entity instanceof Player) {
|
||||||
ExperienceOrb expOrb = new ExperienceOrb(
|
switch (oreType) {
|
||||||
(ServerLevel) world,
|
case "concentrated_coal":
|
||||||
x + 0.5, y + 0.5, z + 0.5,
|
expAmount = random.nextInt(3); // 0-2
|
||||||
expAmount
|
break;
|
||||||
);
|
case "shard_diamond":
|
||||||
((ServerLevel) world).addFreshEntity(expOrb);
|
case "concentrated_diamond":
|
||||||
|
case "emerald":
|
||||||
|
expAmount = 3 + random.nextInt(5); // 3-7
|
||||||
|
break;
|
||||||
|
case "lapis":
|
||||||
|
expAmount = 2 + random.nextInt(4); // 2-5
|
||||||
|
break;
|
||||||
|
case "redstone":
|
||||||
|
expAmount = 1 + random.nextInt(5); // 1-5
|
||||||
|
break;
|
||||||
|
// Iron, Gold, Copper ores don't drop XP in Vanilla 1.21 (only after smelting)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expAmount > 0 && world instanceof ServerLevel) {
|
||||||
|
ExperienceOrb expOrb = new ExperienceOrb(
|
||||||
|
(ServerLevel) world,
|
||||||
|
x + 0.5, y + 0.5, z + 0.5,
|
||||||
|
expAmount
|
||||||
|
);
|
||||||
|
((ServerLevel) world).addFreshEntity(expOrb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,9 @@ public class OreexperienceProcedure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!hasSilkTouch) {
|
if (!hasSilkTouch) {
|
||||||
if (world instanceof ServerLevel _level)
|
// XP is now handled centrally in ConfigurableOreDropsProcedure to match Vanilla 1.21 values
|
||||||
_level.addFreshEntity(new ExperienceOrb(_level, x, y, z, 2));
|
// if (world instanceof ServerLevel _level)
|
||||||
|
// _level.addFreshEntity(new ExperienceOrb(_level, x, y, z, 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user