Skip to content

Commit 7015ff7

Browse files
committed
1.0.5
Extended and extreme mode Config files Presets
1 parent ffcf8a4 commit 7015ff7

File tree

11 files changed

+744
-177
lines changed

11 files changed

+744
-177
lines changed

README.md

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
# CR Layers Generator
22

3-
A Fabric mod for Minecraft 1.20.1 that automatically generate/remove Conquest Reforged terrain layers based on the surrounding blocks.
3+
A Fabric mod for Minecraft 1.20.1 that automatically generates/removes Conquest Reforged terrain layers based on the surrounding blocks.
44

55
## Features
66

7-
- **Automatic Layer Generation**: Generates layers that mimic natural terrain variation
7+
- **Three Generation Modes**: BASIC (linear), EXTENDED (2x distance), EXTREME (3x distance)
88
- **Smart Height Detection**: Uses neighbor block heights to determine appropriate layer counts
9-
- **Configurable Chunk Radius**: Generate layers in any chunk radius around the player
9+
- **Plant Handling**: Automatically replaces and restores vanilla plants with Conquest Reforged variants
10+
- **Configurable System**: JSON-based configuration for easy customization
11+
- **Preset System**: Quick configuration presets for different generation styles
1012
- **Conquest Reforged Integration**: Maps vanilla blocks to their Conquest Reforged layer equivalents
1113

1214
## Installation
@@ -16,59 +18,70 @@ A Fabric mod for Minecraft 1.20.1 that automatically generate/remove Conquest Re
1618
3. Install Conquest Reforged mod
1719
4. Place this mod's JAR file in your mods folder
1820

19-
## Usage
20-
21-
Use the `/generateLayers` command in-game:
21+
## Commands
2222

23+
### Layer Generation
2324
```
2425
/generateLayers [chunkRadius]
2526
```
26-
27-
- **chunk radius** (optional): The radius in chunk to generate layers (1-32). Default is 3.
28-
29-
Example:
30-
```
31-
/generateLayers 10
32-
```
33-
This will generate layers in a 10 chunk radius around your current position.
34-
35-
Use the `/removeLayers` command in-game:
27+
Generate layers in the specified chunk radius (default: 3, max: 32). Automatically handles plant replacement.
3628

3729
```
3830
/removeLayers [chunkRadius]
3931
```
32+
Remove layers in the specified chunk radius (default: 3, max: 32). Automatically restores original plants.
4033

41-
- **chunk radius** (optional): The radius in chunk to remove layers (1-32). Default is 3.
42-
43-
Example:
34+
### Configuration
4435
```
45-
/removeLayers 10
36+
/layerConfig show # Display current configuration
37+
/layerConfig mode <basic|extended|extreme> # Set generation mode
38+
/layerConfig distance <blocks> # Set max layer distance (3-25)
39+
/layerConfig edgeThreshold <blocks> # Set edge height threshold (1-5)
40+
/layerConfig smoothingCycles <cycles> # Set smoothing cycles (0-20)
41+
/layerConfig roundingMode <up|down|nearest> # Set rounding mode
42+
/layerConfig preset <basic|extended|extreme> # Apply preset configuration
43+
/layerConfig reload # Reload config from file
4644
```
47-
This will remove layers in a 10 chunk radius around your current position.
45+
46+
### Presets
47+
- **basic**: Mode: BASIC, Distance: 7, Smoothing: 6, Rounding: DOWN
48+
- **extended**: Mode: EXTENDED, Distance: 14, Smoothing: 13, Rounding: DOWN
49+
- **extreme**: Mode: EXTREME, Distance: 21, Smoothing: 20, Rounding: DOWN
4850

4951
## Configuration
5052

51-
### Block Mappings
53+
Configuration files are automatically created in `config/crlayers/` on first run.
5254

53-
The mod comes with default mappings for common terrain blocks. You can customize these mappings in `BlockMappingRegistry.java`:
55+
### Generation Modes
5456

55-
```java
56-
blockToLayerMapping.put(Blocks.GRASS_BLOCK, "conquest:grass_layer");
57-
```
57+
- **BASIC**: Linear gradients (7→6→5→4→3→2→1) with standard distance
58+
- **EXTENDED**: Gradual gradients (7,7→6,6→5,5→...) with 2x distance
59+
- **EXTREME**: Very gradual gradients (7,7,7→6,6,6→5,5,5→...) with 3x distance
5860

59-
### Supported Blocks
61+
### Configuration Files
6062

61-
Currently, layers can be generated on:
62-
- Grass Block
63-
- Dirt (all variants)
64-
- Stone (all variants)
65-
- Sand
66-
- Red Sand
67-
- Gravel
68-
- Cobblestone
69-
- And more terrain blocks...
63+
**layer_config.json**: Main generation settings
64+
- `mode`: Generation mode (BASIC, EXTENDED, EXTREME)
65+
- `max_layer_distance`: Base distance for layer spreading
66+
- `edge_height_threshold`: Minimum height difference to detect edges
67+
- `smoothing_cycles`: Number of smoothing passes
68+
- `smoothing_rounding_mode`: Rounding method (UP, DOWN, NEAREST)
7069

71-
You can add more blocks by modifying the `canGenerateLayersOn()` method in `LayerGenerator.java`.
70+
**block_mappings.json**: Vanilla to Conquest Reforged block mappings
71+
```json
72+
{
73+
"minecraft:grass_block": "conquest:grass_block_layer",
74+
"minecraft:dirt": "conquest:loamy_dirt_slab"
75+
}
76+
```
77+
78+
**plant_mappings.json**: Vanilla to Conquest Reforged plant mappings
79+
```json
80+
{
81+
"minecraft:grass": "conquest:grass",
82+
"minecraft:tall_grass": "conquest:tall_grass"
83+
}
84+
```
7285

7386
## Building from Source
7487

@@ -102,7 +115,8 @@ Contributions are welcome! Please feel free to submit issues or pull requests.
102115

103116
## Notes
104117

105-
- The mod requires OP permission level 2 to use the command
118+
- Requires OP permission level 2 to use commands
119+
- Configuration changes via commands automatically save to file
106120
- Generation happens synchronously, so very large radii may cause temporary lag
107121
- Make backups before using in important worlds
108-
- The block mapping system is designed to be easily extensible
122+
- Plant replacement and restoration is handled automatically

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx2G
33
org.gradle.parallel=true
44

55
# Mod Properties
6-
mod_version=1.0.4
6+
mod_version=1.0.5
77
maven_group=io.arona74
88
archives_base_name=crlayers
99

src/main/java/io/arona74/crlayers/BlockMappingRegistry.java

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,41 +20,30 @@ public BlockMappingRegistry() {
2020
}
2121

2222
/**
23-
* Register default block to Conquest Reforged layer mappings
24-
* NOTE: These are placeholder mappings. You'll need to replace these with actual
25-
* Conquest Reforged block IDs once you know their naming convention.
23+
* Load block to Conquest Reforged layer mappings from config file
2624
*/
2725
private void registerDefaultMappings() {
28-
// Example mappings - REPLACE THESE WITH ACTUAL CONQUEST REFORGED BLOCK IDS
29-
// Format is typically: conquest:block_name_layer or similar
30-
31-
// Grass blocks
32-
blockToLayerMapping.put(Blocks.GRASS_BLOCK, "conquest:grass_block_layer");
33-
34-
// Dirt variants
35-
blockToLayerMapping.put(Blocks.DIRT, "conquest:loamy_dirt_slab");
36-
blockToLayerMapping.put(Blocks.COARSE_DIRT, "conquest:dirt_path_layer");
37-
blockToLayerMapping.put(Blocks.PODZOL, "conquest:vibrant_autumnal_forest_floor_layer");
38-
39-
// Stone variants
40-
blockToLayerMapping.put(Blocks.STONE, "conquest:limestone_slab");
41-
blockToLayerMapping.put(Blocks.COBBLESTONE, "conquest:limestone_cobble_slab");
42-
blockToLayerMapping.put(Blocks.MOSSY_COBBLESTONE, "conquest:mossy_limestone_cobble_slab");
43-
44-
// Stone types
45-
blockToLayerMapping.put(Blocks.ANDESITE, "conquest:andesite_slab");
46-
blockToLayerMapping.put(Blocks.DIORITE, "conquest:diorite_slab");
47-
blockToLayerMapping.put(Blocks.GRANITE, "conquest:granite_slab");
48-
49-
// Sand and gravel
50-
blockToLayerMapping.put(Blocks.SAND, "conquest:sand_layer");
51-
blockToLayerMapping.put(Blocks.RED_SAND, "conquest:red_sand_layer");
52-
blockToLayerMapping.put(Blocks.GRAVEL, "conquest:gravel_layer");
53-
54-
// Other terrain
55-
blockToLayerMapping.put(Blocks.MYCELIUM, "conquest:mycelium_layer");
56-
57-
CRLayers.LOGGER.info("Registered {} block-to-layer mappings", blockToLayerMapping.size());
26+
// Load mappings from config file
27+
Map<String, String> configMappings = ConfigLoader.loadMappings("block_mappings.json");
28+
29+
// Convert string IDs to Block objects
30+
for (Map.Entry<String, String> entry : configMappings.entrySet()) {
31+
Identifier vanillaId = Identifier.tryParse(entry.getKey());
32+
if (vanillaId == null) {
33+
CRLayers.LOGGER.warn("Invalid vanilla block ID in config: {}", entry.getKey());
34+
continue;
35+
}
36+
37+
Block vanillaBlock = Registries.BLOCK.get(vanillaId);
38+
if (vanillaBlock == Blocks.AIR) {
39+
CRLayers.LOGGER.warn("Vanilla block not found: {}", entry.getKey());
40+
continue;
41+
}
42+
43+
blockToLayerMapping.put(vanillaBlock, entry.getValue());
44+
}
45+
46+
CRLayers.LOGGER.info("Registered {} block-to-layer mappings from config", blockToLayerMapping.size());
5847
}
5948

6049
/**
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package io.arona74.crlayers;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.GsonBuilder;
5+
import com.google.gson.JsonObject;
6+
import net.fabricmc.loader.api.FabricLoader;
7+
8+
import java.io.*;
9+
import java.nio.file.Files;
10+
import java.nio.file.Path;
11+
import java.util.HashMap;
12+
import java.util.Map;
13+
14+
/**
15+
* Utility class for loading mapping configurations from JSON files
16+
*/
17+
public class ConfigLoader {
18+
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
19+
private static final Path CONFIG_DIR = FabricLoader.getInstance().getConfigDir().resolve("crlayers");
20+
21+
/**
22+
* Load mappings from a JSON config file
23+
* First tries to load from the config directory, then falls back to resources
24+
* @param configFileName The name of the config file (e.g., "block_mappings.json")
25+
* @return Map of vanilla block IDs to Conquest Reforged block IDs
26+
*/
27+
public static Map<String, String> loadMappings(String configFileName) {
28+
Map<String, String> mappings = new HashMap<>();
29+
30+
// First try to load from external config directory
31+
Path externalConfigPath = CONFIG_DIR.resolve(configFileName);
32+
if (Files.exists(externalConfigPath)) {
33+
try {
34+
mappings = loadMappingsFromFile(externalConfigPath);
35+
CRLayers.LOGGER.info("Loaded mappings from external config: {}", externalConfigPath);
36+
return mappings;
37+
} catch (IOException e) {
38+
CRLayers.LOGGER.error("Failed to load external config file: {}", externalConfigPath, e);
39+
}
40+
}
41+
42+
// Fall back to resource file
43+
try {
44+
mappings = loadMappingsFromResource(configFileName);
45+
CRLayers.LOGGER.info("Loaded mappings from resource: {}", configFileName);
46+
47+
// Create external config file for user customization
48+
createExternalConfig(configFileName, mappings);
49+
} catch (IOException e) {
50+
CRLayers.LOGGER.error("Failed to load resource config file: {}", configFileName, e);
51+
}
52+
53+
return mappings;
54+
}
55+
56+
/**
57+
* Load mappings from a file path
58+
*/
59+
private static Map<String, String> loadMappingsFromFile(Path filePath) throws IOException {
60+
try (Reader reader = Files.newBufferedReader(filePath)) {
61+
return parseMappingsJson(reader);
62+
}
63+
}
64+
65+
/**
66+
* Load mappings from a resource file
67+
*/
68+
private static Map<String, String> loadMappingsFromResource(String resourceName) throws IOException {
69+
InputStream inputStream = ConfigLoader.class.getClassLoader().getResourceAsStream(resourceName);
70+
if (inputStream == null) {
71+
throw new IOException("Resource not found: " + resourceName);
72+
}
73+
74+
try (Reader reader = new InputStreamReader(inputStream)) {
75+
return parseMappingsJson(reader);
76+
}
77+
}
78+
79+
/**
80+
* Parse JSON mappings from a reader
81+
*/
82+
private static Map<String, String> parseMappingsJson(Reader reader) {
83+
Map<String, String> mappings = new HashMap<>();
84+
85+
JsonObject root = GSON.fromJson(reader, JsonObject.class);
86+
if (root.has("mappings")) {
87+
JsonObject mappingsObj = root.getAsJsonObject("mappings");
88+
for (String key : mappingsObj.keySet()) {
89+
mappings.put(key, mappingsObj.get(key).getAsString());
90+
}
91+
}
92+
93+
return mappings;
94+
}
95+
96+
/**
97+
* Create an external config file for user customization
98+
*/
99+
private static void createExternalConfig(String configFileName, Map<String, String> defaultMappings) {
100+
try {
101+
// Create config directory if it doesn't exist
102+
if (!Files.exists(CONFIG_DIR)) {
103+
Files.createDirectories(CONFIG_DIR);
104+
CRLayers.LOGGER.info("Created config directory: {}", CONFIG_DIR);
105+
}
106+
107+
Path configPath = CONFIG_DIR.resolve(configFileName);
108+
109+
// Only create if it doesn't exist
110+
if (!Files.exists(configPath)) {
111+
JsonObject root = new JsonObject();
112+
root.addProperty("_comment",
113+
"This file can be edited to customize mappings. Changes will be loaded on next startup.");
114+
115+
JsonObject mappingsObj = new JsonObject();
116+
for (Map.Entry<String, String> entry : defaultMappings.entrySet()) {
117+
mappingsObj.addProperty(entry.getKey(), entry.getValue());
118+
}
119+
root.add("mappings", mappingsObj);
120+
121+
try (Writer writer = Files.newBufferedWriter(configPath)) {
122+
GSON.toJson(root, writer);
123+
}
124+
125+
CRLayers.LOGGER.info("Created default config file: {}", configPath);
126+
}
127+
} catch (IOException e) {
128+
CRLayers.LOGGER.error("Failed to create external config file", e);
129+
}
130+
}
131+
132+
/**
133+
* Save mappings to an external config file
134+
*/
135+
public static void saveMappings(String configFileName, Map<String, String> mappings) throws IOException {
136+
if (!Files.exists(CONFIG_DIR)) {
137+
Files.createDirectories(CONFIG_DIR);
138+
}
139+
140+
Path configPath = CONFIG_DIR.resolve(configFileName);
141+
142+
JsonObject root = new JsonObject();
143+
root.addProperty("_comment",
144+
"This file can be edited to customize mappings. Changes will be loaded on next startup.");
145+
146+
JsonObject mappingsObj = new JsonObject();
147+
for (Map.Entry<String, String> entry : mappings.entrySet()) {
148+
mappingsObj.addProperty(entry.getKey(), entry.getValue());
149+
}
150+
root.add("mappings", mappingsObj);
151+
152+
try (Writer writer = Files.newBufferedWriter(configPath)) {
153+
GSON.toJson(root, writer);
154+
}
155+
156+
CRLayers.LOGGER.info("Saved mappings to config file: {}", configPath);
157+
}
158+
}

0 commit comments

Comments
 (0)