diff --git a/src/generated/resources/assets/anvilcraft/blockstates/mun_rock.json b/src/generated/resources/assets/anvilcraft/blockstates/mun_rock.json new file mode 100644 index 0000000000..f58ac5fbed --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/blockstates/mun_rock.json @@ -0,0 +1,18 @@ +{ + "variants": { + "": [ + { + "model": "anvilcraft:block/mun_rock" + }, + { + "model": "anvilcraft:block/mun_rock_1" + }, + { + "model": "anvilcraft:block/mun_rock_2" + }, + { + "model": "anvilcraft:block/mun_rock_3" + } + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/blockstates/mun_soil.json b/src/generated/resources/assets/anvilcraft/blockstates/mun_soil.json new file mode 100644 index 0000000000..757d0531d2 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/blockstates/mun_soil.json @@ -0,0 +1,21 @@ +{ + "variants": { + "": [ + { + "model": "anvilcraft:block/mun_soil" + }, + { + "model": "anvilcraft:block/mun_soil_rotated", + "y": 90 + }, + { + "model": "anvilcraft:block/mun_soil_rotated", + "y": 180 + }, + { + "model": "anvilcraft:block/mun_soil_rotated", + "y": 270 + } + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/lang/en_ud.json b/src/generated/resources/assets/anvilcraft/lang/en_ud.json index 1a4398788d..3c99da4d23 100644 --- a/src/generated/resources/assets/anvilcraft/lang/en_ud.json +++ b/src/generated/resources/assets/anvilcraft/lang/en_ud.json @@ -176,6 +176,8 @@ "block.anvilcraft.mineral_fountain": "uıɐʇunoℲ ןɐɹǝuıW", "block.anvilcraft.mob_amber_block": "qoW ɥʇıʍ ɹǝqɯⱯ ɟo ʞɔoןᗺ", "block.anvilcraft.multiphase_matter_block": "ɹǝʇʇɐW ǝsɐɥdıʇןnW ɟo ʞɔoןᗺ", + "block.anvilcraft.mun_rock": "ʞɔoᴚ unW", + "block.anvilcraft.mun_soil": "ןıoS unW", "block.anvilcraft.negative_matter_block": "ɹǝʇʇɐW ǝʌıʇɐbǝN ɟo ʞɔoןᗺ", "block.anvilcraft.nesting_shulker_box": "xoᗺ ɹǝʞןnɥS buıʇsǝN", "block.anvilcraft.nether_dust": "ʇsnᗡ ɹǝɥʇǝN", diff --git a/src/generated/resources/assets/anvilcraft/lang/en_us.json b/src/generated/resources/assets/anvilcraft/lang/en_us.json index 3887127832..3950dfaf0d 100644 --- a/src/generated/resources/assets/anvilcraft/lang/en_us.json +++ b/src/generated/resources/assets/anvilcraft/lang/en_us.json @@ -176,6 +176,8 @@ "block.anvilcraft.mineral_fountain": "Mineral Fountain", "block.anvilcraft.mob_amber_block": "Block of Amber with Mob", "block.anvilcraft.multiphase_matter_block": "Block of Multiphase Matter", + "block.anvilcraft.mun_rock": "Mun Rock", + "block.anvilcraft.mun_soil": "Mun Soil", "block.anvilcraft.negative_matter_block": "Block of Negative Matter", "block.anvilcraft.nesting_shulker_box": "Nesting Shulker Box", "block.anvilcraft.nether_dust": "Nether Dust", diff --git a/src/generated/resources/assets/anvilcraft/models/block/mun_rock.json b/src/generated/resources/assets/anvilcraft/models/block/mun_rock.json new file mode 100644 index 0000000000..bfaa8552a4 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/block/mun_rock.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "anvilcraft:block/mun_rock" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/models/block/mun_rock_1.json b/src/generated/resources/assets/anvilcraft/models/block/mun_rock_1.json new file mode 100644 index 0000000000..34705fc925 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/block/mun_rock_1.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "anvilcraft:block/mun_rock_1" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/models/block/mun_rock_2.json b/src/generated/resources/assets/anvilcraft/models/block/mun_rock_2.json new file mode 100644 index 0000000000..859cc478a5 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/block/mun_rock_2.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "anvilcraft:block/mun_rock_2" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/models/block/mun_rock_3.json b/src/generated/resources/assets/anvilcraft/models/block/mun_rock_3.json new file mode 100644 index 0000000000..0c419b40fd --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/block/mun_rock_3.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "anvilcraft:block/mun_rock_3" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/models/block/mun_soil.json b/src/generated/resources/assets/anvilcraft/models/block/mun_soil.json new file mode 100644 index 0000000000..954eda3bb2 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/block/mun_soil.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "anvilcraft:block/mun_soil" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/models/block/mun_soil_rotated.json b/src/generated/resources/assets/anvilcraft/models/block/mun_soil_rotated.json new file mode 100644 index 0000000000..954eda3bb2 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/block/mun_soil_rotated.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:block/cube_all", + "textures": { + "all": "anvilcraft:block/mun_soil" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/models/item/mun_rock.json b/src/generated/resources/assets/anvilcraft/models/item/mun_rock.json new file mode 100644 index 0000000000..2b4ffd8b16 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/item/mun_rock.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft:block/mun_rock" +} \ No newline at end of file diff --git a/src/generated/resources/assets/anvilcraft/models/item/mun_soil.json b/src/generated/resources/assets/anvilcraft/models/item/mun_soil.json new file mode 100644 index 0000000000..a40f2b2cb2 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft/models/item/mun_soil.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft:block/mun_soil" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/advancement/recipes/dimension_travel/to_mun.json b/src/generated/resources/data/anvilcraft/advancement/recipes/dimension_travel/to_mun.json new file mode 100644 index 0000000000..a24c472a23 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/advancement/recipes/dimension_travel/to_mun.json @@ -0,0 +1,21 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:dimension_travel/to_mun" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:dimension_travel/to_mun" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/dimension/mun.json b/src/generated/resources/data/anvilcraft/dimension/mun.json new file mode 100644 index 0000000000..dc5640cb9a --- /dev/null +++ b/src/generated/resources/data/anvilcraft/dimension/mun.json @@ -0,0 +1,24 @@ +{ + "type": "anvilcraft:mun", + "generator": { + "type": "minecraft:noise", + "biome_source": { + "type": "minecraft:multi_noise", + "biomes": [ + { + "biome": "anvilcraft:mun", + "parameters": { + "continentalness": 0.0, + "depth": 0.0, + "erosion": 0.0, + "humidity": 0.0, + "offset": 0.0, + "temperature": 0.0, + "weirdness": 0.0 + } + } + ] + }, + "settings": "anvilcraft:mun" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/dimension_type/mun.json b/src/generated/resources/data/anvilcraft/dimension_type/mun.json new file mode 100644 index 0000000000..884c21b0fd --- /dev/null +++ b/src/generated/resources/data/anvilcraft/dimension_type/mun.json @@ -0,0 +1,20 @@ +{ + "ambient_light": 0.0, + "bed_works": false, + "coordinate_scale": 1.0, + "effects": "anvilcraft:mun", + "fixed_time": 6000, + "has_ceiling": false, + "has_raids": true, + "has_skylight": true, + "height": 384, + "infiniburn": "#anvilcraft:infiniburn_mun", + "logical_height": 384, + "min_y": -64, + "monster_spawn_block_light_limit": 0, + "monster_spawn_light_level": 0, + "natural": false, + "piglin_safe": false, + "respawn_anchor_works": true, + "ultrawarm": false +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/loot_table/blocks/mun_rock.json b/src/generated/resources/data/anvilcraft/loot_table/blocks/mun_rock.json new file mode 100644 index 0000000000..6c3b80d496 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/loot_table/blocks/mun_rock.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "anvilcraft:mun_rock" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft:blocks/mun_rock" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/loot_table/blocks/mun_soil.json b/src/generated/resources/data/anvilcraft/loot_table/blocks/mun_soil.json new file mode 100644 index 0000000000..98771e5d0b --- /dev/null +++ b/src/generated/resources/data/anvilcraft/loot_table/blocks/mun_soil.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "anvilcraft:mun_soil" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft:blocks/mun_soil" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/recipe/dimension_travel/to_mun.json b/src/generated/resources/data/anvilcraft/recipe/dimension_travel/to_mun.json new file mode 100644 index 0000000000..8c35e6eebe --- /dev/null +++ b/src/generated/resources/data/anvilcraft/recipe/dimension_travel/to_mun.json @@ -0,0 +1,11 @@ +{ + "type": "anvilcraft:dimension_travel", + "destination": "anvilcraft:mun", + "height": 349.0, + "offset": [ + 5.0, + 5.0 + ], + "origin": "minecraft:overworld", + "speed": 10.0 +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/worldgen/biome/mun.json b/src/generated/resources/data/anvilcraft/worldgen/biome/mun.json new file mode 100644 index 0000000000..f50366a1ac --- /dev/null +++ b/src/generated/resources/data/anvilcraft/worldgen/biome/mun.json @@ -0,0 +1,33 @@ +{ + "carvers": {}, + "downfall": 0.0, + "effects": { + "fog_color": 0, + "foliage_color": 16377496, + "grass_color": 16377496, + "sky_color": 2580, + "water_color": 3684408, + "water_fog_color": 2368548 + }, + "features": [ + [ + "anvilcraft:crater_mega", + "anvilcraft:crater_large", + "anvilcraft:crater_small" + ] + ], + "has_precipitation": false, + "spawn_costs": {}, + "spawners": { + "ambient": [], + "axolotls": [], + "creature": [], + "misc": [], + "monster": [], + "underground_water_creature": [], + "water_ambient": [], + "water_creature": [] + }, + "temperature": 0.2, + "temperature_modifier": "frozen" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/worldgen/configured_feature/large_crater.json b/src/generated/resources/data/anvilcraft/worldgen/configured_feature/large_crater.json new file mode 100644 index 0000000000..04255ab163 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/worldgen/configured_feature/large_crater.json @@ -0,0 +1,15 @@ +{ + "type": "anvilcraft:crater", + "config": { + "depth": { + "type": "minecraft:uniform", + "max_inclusive": 5, + "min_inclusive": 3 + }, + "radius": { + "type": "minecraft:uniform", + "max_inclusive": 15, + "min_inclusive": 12 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/worldgen/configured_feature/mega_crater.json b/src/generated/resources/data/anvilcraft/worldgen/configured_feature/mega_crater.json new file mode 100644 index 0000000000..51caca5c14 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/worldgen/configured_feature/mega_crater.json @@ -0,0 +1,15 @@ +{ + "type": "anvilcraft:crater", + "config": { + "depth": { + "type": "minecraft:uniform", + "max_inclusive": 16, + "min_inclusive": 8 + }, + "radius": { + "type": "minecraft:uniform", + "max_inclusive": 48, + "min_inclusive": 32 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/worldgen/configured_feature/small_crater.json b/src/generated/resources/data/anvilcraft/worldgen/configured_feature/small_crater.json new file mode 100644 index 0000000000..404e9d762c --- /dev/null +++ b/src/generated/resources/data/anvilcraft/worldgen/configured_feature/small_crater.json @@ -0,0 +1,15 @@ +{ + "type": "anvilcraft:crater", + "config": { + "depth": { + "type": "minecraft:uniform", + "max_inclusive": 3, + "min_inclusive": 2 + }, + "radius": { + "type": "minecraft:uniform", + "max_inclusive": 7, + "min_inclusive": 4 + } + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/worldgen/noise_settings/mun.json b/src/generated/resources/data/anvilcraft/worldgen/noise_settings/mun.json new file mode 100644 index 0000000000..80afd5525b --- /dev/null +++ b/src/generated/resources/data/anvilcraft/worldgen/noise_settings/mun.json @@ -0,0 +1,217 @@ +{ + "aquifers_enabled": true, + "default_block": { + "Name": "anvilcraft:mun_rock" + }, + "default_fluid": { + "Name": "minecraft:air" + }, + "disable_mob_generation": false, + "legacy_random_source": false, + "noise": { + "height": 384, + "min_y": -64, + "size_horizontal": 1, + "size_vertical": 2 + }, + "noise_router": { + "barrier": 0.0, + "continents": 0.0, + "depth": 0.0, + "erosion": 0.0, + "final_density": { + "type": "minecraft:squeeze", + "argument": { + "type": "minecraft:mul", + "argument1": 0.64, + "argument2": { + "type": "minecraft:interpolated", + "argument": { + "type": "minecraft:blend_density", + "argument": { + "type": "minecraft:add", + "argument1": 0.1, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 0.0, + "from_y": -64, + "to_value": 1.0, + "to_y": -40 + }, + "argument2": { + "type": "minecraft:add", + "argument1": -0.1, + "argument2": { + "type": "minecraft:add", + "argument1": -0.1, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 1.0, + "from_y": 240, + "to_value": 0.0, + "to_y": 256 + }, + "argument2": { + "type": "minecraft:add", + "argument1": 0.1, + "argument2": "minecraft:overworld/depth" + } + } + } + } + } + } + } + } + } + }, + "fluid_level_floodedness": 0.0, + "fluid_level_spread": 0.0, + "initial_density_without_jaggedness": { + "type": "minecraft:add", + "argument1": 0.1, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 0.0, + "from_y": -64, + "to_value": 1.0, + "to_y": -40 + }, + "argument2": { + "type": "minecraft:add", + "argument1": -0.1, + "argument2": { + "type": "minecraft:add", + "argument1": -0.1, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 1.0, + "from_y": 240, + "to_value": 0.0, + "to_y": 256 + }, + "argument2": { + "type": "minecraft:add", + "argument1": -0.703125, + "argument2": 0.1 + } + } + } + } + } + }, + "lava": 0.0, + "ridges": 0.0, + "temperature": 0.0, + "vegetation": 0.0, + "vein_gap": 0.0, + "vein_ridged": 0.0, + "vein_toggle": 0.0 + }, + "ore_veins_enabled": false, + "sea_level": 0, + "spawn_target": [ + { + "continentalness": [ + -0.11, + 1.0 + ], + "depth": 0.0, + "erosion": [ + -1.0, + 1.0 + ], + "humidity": [ + -1.0, + 1.0 + ], + "offset": 0.0, + "temperature": [ + -1.0, + 1.0 + ], + "weirdness": [ + -1.0, + -0.16 + ] + }, + { + "continentalness": [ + -0.11, + 1.0 + ], + "depth": 0.0, + "erosion": [ + -1.0, + 1.0 + ], + "humidity": [ + -1.0, + 1.0 + ], + "offset": 0.0, + "temperature": [ + -1.0, + 1.0 + ], + "weirdness": [ + 0.16, + 1.0 + ] + } + ], + "surface_rule": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:vertical_gradient", + "false_at_and_above": { + "above_bottom": 5 + }, + "random_name": "minecraft:bedrock_floor", + "true_at_and_below": { + "above_bottom": 0 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:bedrock" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:above_preliminary_surface" + }, + "then_run": { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": -1, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "anvilcraft:mun_soil" + } + } + } + } + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/worldgen/placed_feature/crater_large.json b/src/generated/resources/data/anvilcraft/worldgen/placed_feature/crater_large.json new file mode 100644 index 0000000000..856609d885 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/worldgen/placed_feature/crater_large.json @@ -0,0 +1,27 @@ +{ + "feature": "anvilcraft:large_crater", + "placement": [ + { + "type": "minecraft:rarity_filter", + "chance": 12 + }, + { + "type": "minecraft:in_square" + }, + { + "type": "minecraft:height_range", + "height": { + "type": "minecraft:uniform", + "max_inclusive": { + "absolute": 256 + }, + "min_inclusive": { + "above_bottom": 0 + } + } + }, + { + "type": "minecraft:biome" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/worldgen/placed_feature/crater_mega.json b/src/generated/resources/data/anvilcraft/worldgen/placed_feature/crater_mega.json new file mode 100644 index 0000000000..6dd2eb62a8 --- /dev/null +++ b/src/generated/resources/data/anvilcraft/worldgen/placed_feature/crater_mega.json @@ -0,0 +1,27 @@ +{ + "feature": "anvilcraft:mega_crater", + "placement": [ + { + "type": "minecraft:rarity_filter", + "chance": 256 + }, + { + "type": "minecraft:in_square" + }, + { + "type": "minecraft:height_range", + "height": { + "type": "minecraft:uniform", + "max_inclusive": { + "absolute": 256 + }, + "min_inclusive": { + "above_bottom": 0 + } + } + }, + { + "type": "minecraft:biome" + } + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft/worldgen/placed_feature/crater_small.json b/src/generated/resources/data/anvilcraft/worldgen/placed_feature/crater_small.json new file mode 100644 index 0000000000..5af691003b --- /dev/null +++ b/src/generated/resources/data/anvilcraft/worldgen/placed_feature/crater_small.json @@ -0,0 +1,27 @@ +{ + "feature": "anvilcraft:small_crater", + "placement": [ + { + "type": "minecraft:rarity_filter", + "chance": 4 + }, + { + "type": "minecraft:in_square" + }, + { + "type": "minecraft:height_range", + "height": { + "type": "minecraft:uniform", + "max_inclusive": { + "absolute": 256 + }, + "min_inclusive": { + "above_bottom": 0 + } + } + }, + { + "type": "minecraft:biome" + } + ] +} \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/AnvilCraft.java b/src/main/java/dev/dubhe/anvilcraft/AnvilCraft.java index ed522a8943..feca7a672c 100644 --- a/src/main/java/dev/dubhe/anvilcraft/AnvilCraft.java +++ b/src/main/java/dev/dubhe/anvilcraft/AnvilCraft.java @@ -39,6 +39,9 @@ import dev.dubhe.anvilcraft.init.ModResultModifierTypes; import dev.dubhe.anvilcraft.init.ModVillagers; import dev.dubhe.anvilcraft.init.reicpe.ModRecipeInits; +import dev.dubhe.anvilcraft.init.worldgen.ModConfiguredFeatures; +import dev.dubhe.anvilcraft.init.worldgen.ModFeatures; +import dev.dubhe.anvilcraft.init.worldgen.ModPlacedFeatures; import dev.dubhe.anvilcraft.integration.top.AnvilCraftTopPlugin; import dev.dubhe.anvilcraft.recipe.anvil.cache.RecipeCaches; import dev.dubhe.anvilcraft.util.ModInteractionMap; @@ -98,6 +101,7 @@ public AnvilCraft(IEventBus modEventBus, ModContainer modContainer) { ModMobEffects.register(modEventBus); ModInspections.initialize(); ModItemSubPredicates.initialize(modEventBus); + ModFeatures.initialize(modEventBus); ModLootContextParamSets.registerAll(); ModEnchantmentEffectComponents.register(modEventBus); diff --git a/src/main/java/dev/dubhe/anvilcraft/data/provider/ModRegistryProvider.java b/src/main/java/dev/dubhe/anvilcraft/data/provider/ModRegistryProvider.java index 82bcce6704..5d461592a1 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/provider/ModRegistryProvider.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/provider/ModRegistryProvider.java @@ -1,7 +1,13 @@ package dev.dubhe.anvilcraft.data.provider; import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.init.worldgen.ModBiomes; +import dev.dubhe.anvilcraft.init.worldgen.ModConfiguredFeatures; +import dev.dubhe.anvilcraft.init.worldgen.ModDimensionTypes; +import dev.dubhe.anvilcraft.init.worldgen.ModDimensions; +import dev.dubhe.anvilcraft.init.worldgen.ModNoiseGeneratorSettings; import dev.dubhe.anvilcraft.init.ModEnchantments; +import dev.dubhe.anvilcraft.init.worldgen.ModPlacedFeatures; import net.minecraft.core.HolderLookup; import net.minecraft.core.RegistrySetBuilder; import net.minecraft.core.registries.Registries; @@ -13,8 +19,14 @@ public class ModRegistryProvider extends DatapackBuiltinEntriesProvider { - private static final RegistrySetBuilder BUILDER = - new RegistrySetBuilder().add(Registries.ENCHANTMENT, ModEnchantments::bootstrap); + private static final RegistrySetBuilder BUILDER = new RegistrySetBuilder() + .add(Registries.ENCHANTMENT, ModEnchantments::bootstrap) + .add(Registries.DIMENSION_TYPE, ModDimensionTypes::bootstrap) + .add(Registries.CONFIGURED_FEATURE, ModConfiguredFeatures::bootstrap) + .add(Registries.PLACED_FEATURE, ModPlacedFeatures::bootstrap) + .add(Registries.BIOME, ModBiomes::bootstrap) + .add(Registries.NOISE_SETTINGS, ModNoiseGeneratorSettings::bootstrap) + .add(Registries.LEVEL_STEM, ModDimensions::bootstrap); public ModRegistryProvider(PackOutput output, CompletableFuture registries) { super(output, registries, BUILDER, Set.of(AnvilCraft.MOD_ID)); diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/DimensionTravelRecipeLoader.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/DimensionTravelRecipeLoader.java new file mode 100644 index 0000000000..e0b88bf47a --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/DimensionTravelRecipeLoader.java @@ -0,0 +1,17 @@ +package dev.dubhe.anvilcraft.data.recipe; + +import com.tterrag.registrate.providers.RegistrateRecipeProvider; +import dev.dubhe.anvilcraft.init.worldgen.ModDimensionTypes; +import dev.dubhe.anvilcraft.recipe.anvil.wrap.DimensionTravelRecipe; +import net.minecraft.world.level.Level; + +public class DimensionTravelRecipeLoader { + public static void init(RegistrateRecipeProvider provider) { + DimensionTravelRecipe.builder() + .from(Level.OVERWORLD) + .speed(10) + .height(349) + .to(ModDimensionTypes.MUN_LEVEL) + .save(provider); + } +} \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/data/recipe/RecipeHandler.java b/src/main/java/dev/dubhe/anvilcraft/data/recipe/RecipeHandler.java index 5689fdf06b..200e892e97 100644 --- a/src/main/java/dev/dubhe/anvilcraft/data/recipe/RecipeHandler.java +++ b/src/main/java/dev/dubhe/anvilcraft/data/recipe/RecipeHandler.java @@ -31,5 +31,6 @@ public static void init(RegistrateRecipeProvider provider) { ChargerChargingRecipeLoader.init(provider); AnvilCollisionCraftRecipeLoader.init(provider); MultipleToOneSmithingRecipeLoader.init(provider); + DimensionTravelRecipeLoader.init(provider); } } diff --git a/src/main/java/dev/dubhe/anvilcraft/init/ModBlockTags.java b/src/main/java/dev/dubhe/anvilcraft/init/ModBlockTags.java index 50b65c98a3..7c149c0247 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/ModBlockTags.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/ModBlockTags.java @@ -41,6 +41,7 @@ public class ModBlockTags { public static final TagKey SLIDING_RAILS = bind("sliding_rails"); public static final TagKey STICKABLE_WITH_SLIDING_RAILS = bind("stickable_with_sliding_rails"); public static final TagKey OVERHEATABLE = bind("overheatable"); + public static final TagKey INFINIBURN_MUN = bind("infiniburn_mun"); // common tags public static final TagKey ORES_TUNGSTEN = bindC("ores/tungsten"); diff --git a/src/main/java/dev/dubhe/anvilcraft/init/ModBlocks.java b/src/main/java/dev/dubhe/anvilcraft/init/ModBlocks.java index d48e6f38d0..9f55638108 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/ModBlocks.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/ModBlocks.java @@ -1,5 +1,7 @@ package dev.dubhe.anvilcraft.init; +import com.tterrag.registrate.providers.DataGenContext; +import com.tterrag.registrate.providers.RegistrateBlockstateProvider; import com.tterrag.registrate.providers.RegistrateRecipeProvider; import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.nullness.NonNullFunction; @@ -208,6 +210,8 @@ import net.neoforged.neoforge.common.Tags; import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; +import java.util.List; import java.util.function.Supplier; import static dev.dubhe.anvilcraft.AnvilCraft.REGISTRATE; @@ -4493,6 +4497,25 @@ private static BlockEntry registerCementLiquidBlock(Color color) { }) .register(); + public static final BlockEntry MUN_SOIL = REGISTRATE + .block("mun_soil", Block::new) + .initialProperties(() -> Blocks.DIRT) + .properties(properties -> properties.sound(SoundType.SAND)) + .blockstate((ctx, provider) -> + randomModelAndRotate(ctx, provider, 1, true) + ) + .simpleItem() + .register(); + + public static final BlockEntry MUN_ROCK = REGISTRATE + .block("mun_rock", Block::new) + .initialProperties(() -> Blocks.STONE) + .blockstate((ctx, provider) -> + randomModelAndRotate(ctx, provider, 4, false) + ) + .simpleItem() + .register(); + public static final BlockEntry SUGAR_BLOCK = REGISTRATE .block("sugar_block", SugarBlock::new) .initialProperties(() -> Blocks.LAPIS_BLOCK) @@ -4906,4 +4929,57 @@ public static boolean never(BlockState state, BlockGetter blockGetter, BlockPos public static boolean always(BlockState state, BlockGetter blockGetter, BlockPos pos) { return true; } + + public static void randomModelAndRotate( + DataGenContext ctx, RegistrateBlockstateProvider provider, int modelCount, boolean rotate + ) { + List list = new ArrayList<>(); + for (int i = 0; i < modelCount; i++) { + String nameSuffix = i == 0 ? "" : "_" + i; + list.add( + new ConfiguredModel( + provider.models().cubeAll( + ctx.getName() + nameSuffix, + provider.modLoc("block/" + ctx.getName() + nameSuffix) + ) + ) + ); + if (rotate) { + list.add( + new ConfiguredModel( + provider.models().cubeAll( + ctx.getName() + "_rotated" + nameSuffix, + provider.modLoc("block/" + ctx.getName() + nameSuffix) + ), + 0, + 90, + false + ) + ); + list.add( + new ConfiguredModel( + provider.models().cubeAll( + ctx.getName() + "_rotated" + nameSuffix, + provider.modLoc("block/" + ctx.getName() + nameSuffix) + ), + 0, + 180, + false + ) + ); + list.add( + new ConfiguredModel( + provider.models().cubeAll( + ctx.getName() + "_rotated" + nameSuffix, + provider.modLoc("block/" + ctx.getName() + nameSuffix) + ), + 0, + 270, + false + ) + ); + } + } + provider.simpleBlock(ctx.get(), list.toArray(new ConfiguredModel[0])); + } } \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/init/ModRecipeTypes.java b/src/main/java/dev/dubhe/anvilcraft/init/ModRecipeTypes.java index d85687bce2..609ceab5b5 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/ModRecipeTypes.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/ModRecipeTypes.java @@ -14,6 +14,7 @@ import dev.dubhe.anvilcraft.recipe.anvil.wrap.BoilingRecipe; import dev.dubhe.anvilcraft.recipe.anvil.wrap.BulgingRecipe; import dev.dubhe.anvilcraft.recipe.anvil.wrap.CookingRecipe; +import dev.dubhe.anvilcraft.recipe.anvil.wrap.DimensionTravelRecipe; import dev.dubhe.anvilcraft.recipe.anvil.wrap.ItemCompressRecipe; import dev.dubhe.anvilcraft.recipe.anvil.wrap.ItemCrushRecipe; import dev.dubhe.anvilcraft.recipe.anvil.wrap.ItemInjectRecipe; @@ -192,6 +193,16 @@ public class ModRecipeTypes { EIGHT_TO_ONE_SMITHING_SERIALIZER = RECIPE_SERIALIZERS.register("eight_to_one_smithing", EightToOneSmithingRecipe.Serializer::new); + public static final DeferredHolder, RecipeType> ANVIL_COLLISION_CRAFT = + registerType("anvil_collision"); + public static final DeferredHolder, RecipeSerializer> ANVIL_COLLISION_CRAFT_SERIALIZER = + RECIPE_SERIALIZERS.register("anvil_collision", AnvilCollisionCraftRecipe.Serializer::new); + + public static final DeferredHolder, RecipeType> DIMENSION_TRAVEL_TYPE = + registerType("dimension_travel"); + public static final DeferredHolder, RecipeSerializer> DIMENSION_TRAVEL_SERIALIZER = + RECIPE_SERIALIZERS.register("dimension_travel", DimensionTravelRecipe.Serializer::new); + private static > DeferredHolder, RecipeType> registerType(String name) { return RECIPE_TYPES.register(name, () -> new RecipeType<>() { @Override @@ -201,11 +212,6 @@ public String toString() { }); } - public static final DeferredHolder, RecipeType> ANVIL_COLLISION_CRAFT = - registerType("anvil_collision"); - public static final DeferredHolder, RecipeSerializer> ANVIL_COLLISION_CRAFT_SERIALIZER = - RECIPE_SERIALIZERS.register("anvil_collision", AnvilCollisionCraftRecipe.Serializer::new); - public static void register(IEventBus bus) { RECIPE_TYPES.register(bus); RECIPE_SERIALIZERS.register(bus); diff --git a/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipeOutcomeTypes.java b/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipeOutcomeTypes.java index fc9ea185da..7df7cc6a21 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipeOutcomeTypes.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipeOutcomeTypes.java @@ -2,6 +2,7 @@ import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.init.ModRegistries; +import dev.dubhe.anvilcraft.recipe.anvil.outcome.ChangeDimension; import dev.dubhe.anvilcraft.recipe.anvil.outcome.ChooseOneOutcome; import dev.dubhe.anvilcraft.recipe.anvil.outcome.DamageAnvil; import dev.dubhe.anvilcraft.recipe.anvil.outcome.IRecipeOutcome; @@ -33,4 +34,7 @@ public class ModRecipeOutcomeTypes { public static final DeferredHolder, ChooseOneOutcome.Type> CHOOSE_ONE = OUTCOME_TYPE .register("choose_one", ChooseOneOutcome.Type::new); + + public static final DeferredHolder, ChangeDimension.Type> CHANGE_DIMENSION = OUTCOME_TYPE + .register("change_dimension", ChangeDimension.Type::new); } diff --git a/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipePredicateTypes.java b/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipePredicateTypes.java index 7b34e7ad3b..15be04350c 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipePredicateTypes.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipePredicateTypes.java @@ -6,6 +6,7 @@ import dev.dubhe.anvilcraft.recipe.anvil.predicate.block.HasBlock; import dev.dubhe.anvilcraft.recipe.anvil.predicate.block.HasBlockIngredient; import dev.dubhe.anvilcraft.recipe.anvil.predicate.block.HasCauldron; +import dev.dubhe.anvilcraft.recipe.anvil.predicate.entity.HasEnderPearl; import dev.dubhe.anvilcraft.recipe.anvil.predicate.item.HasItem; import dev.dubhe.anvilcraft.recipe.anvil.predicate.item.HasItemIngredient; import net.neoforged.neoforge.registries.DeferredHolder; @@ -39,4 +40,9 @@ public class ModRecipePredicateTypes { "has_cauldron", HasCauldron.Type::new ); + + public static final DeferredHolder, HasEnderPearl.Type> HAS_ENDER_PEARL = PREDICATE_TYPE.register( + "has_ender_pearl", + HasEnderPearl.Type::new + ); } diff --git a/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipeTriggers.java b/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipeTriggers.java index bac744ac9f..26a225820f 100644 --- a/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipeTriggers.java +++ b/src/main/java/dev/dubhe/anvilcraft/init/reicpe/ModRecipeTriggers.java @@ -14,9 +14,12 @@ public class ModRecipeTriggers { "on_anvil_fall_on", IRecipeTrigger.Impl::new ); - public static final DeferredHolder ITEM_INTO_BLOCK = TRIGGER.register( "item_into_block", IRecipeTrigger.Impl::new ); + public static final DeferredHolder ON_ENDER_PEARL_TICK = TRIGGER.register( + "on_ender_pearl_tick", + IRecipeTrigger.Impl::new + ); } diff --git a/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModBiomes.java b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModBiomes.java new file mode 100644 index 0000000000..8c7b41a38c --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModBiomes.java @@ -0,0 +1,51 @@ +package dev.dubhe.anvilcraft.init.worldgen; + +import dev.dubhe.anvilcraft.AnvilCraft; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.data.worldgen.Carvers; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeGenerationSettings; +import net.minecraft.world.level.biome.BiomeSpecialEffects; +import net.minecraft.world.level.biome.MobSpawnSettings; +import net.minecraft.world.level.levelgen.GenerationStep; + +public class ModBiomes { + public static final ResourceKey MUN = key("mun"); + + public static void bootstrap(BootstrapContext context) { + context.register(MUN, mun(context)); + } + + private static Biome mun(BootstrapContext context) { + return new Biome.BiomeBuilder() + .hasPrecipitation(false) + .temperature(0.2f) + .downfall(0) + .generationSettings( + new BiomeGenerationSettings.Builder(context.lookup(Registries.PLACED_FEATURE), context.lookup(Registries.CONFIGURED_CARVER)) + .addFeature(GenerationStep.Decoration.RAW_GENERATION, ModPlacedFeatures.MEGA_CRATER) + .addFeature(GenerationStep.Decoration.RAW_GENERATION, ModPlacedFeatures.LARGE_CRATER) + .addFeature(GenerationStep.Decoration.RAW_GENERATION, ModPlacedFeatures.SMALL_CRATER) + .build() + ) + .mobSpawnSettings(new MobSpawnSettings.Builder().build()) + .specialEffects( + new BiomeSpecialEffects.Builder() + .fogColor(0x000000) + .skyColor(0x000A14) + .waterColor(0x383838) + .waterFogColor(0x242424) + .grassColorOverride(0xF9E698) + .foliageColorOverride(0xF9E698) + .build() + ) + .temperatureAdjustment(Biome.TemperatureModifier.FROZEN) + .build(); + } + + private static ResourceKey key(String id) { + return ResourceKey.create(Registries.BIOME, AnvilCraft.of(id)); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModConfiguredFeatures.java b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModConfiguredFeatures.java new file mode 100644 index 0000000000..3402d943ca --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModConfiguredFeatures.java @@ -0,0 +1,43 @@ +package dev.dubhe.anvilcraft.init.worldgen; + +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.worldgen.CraterConfiguration; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.util.valueproviders.UniformInt; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; + +public class ModConfiguredFeatures { + public static final ResourceKey> MEGA_CRATER = key("mega_crater"); + public static final ResourceKey> LARGE_CRATER = key("large_crater"); + public static final ResourceKey> SMALL_CRATER = key("small_crater"); + + public static void bootstrap(BootstrapContext> context) { + context.register( + MEGA_CRATER, + new ConfiguredFeature<>( + ModFeatures.CRATER.get(), + new CraterConfiguration(UniformInt.of(32, 48), UniformInt.of(8, 16)) + ) + ); + context.register( + LARGE_CRATER, + new ConfiguredFeature<>( + ModFeatures.CRATER.get(), + new CraterConfiguration(UniformInt.of(12, 15), UniformInt.of(3, 5)) + ) + ); + context.register( + SMALL_CRATER, + new ConfiguredFeature<>( + ModFeatures.CRATER.get(), + new CraterConfiguration(UniformInt.of(4, 7), UniformInt.of(2, 3)) + ) + ); + } + + private static ResourceKey> key(String name) { + return ResourceKey.create(Registries.CONFIGURED_FEATURE, AnvilCraft.of(name)); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModDimensionTypes.java b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModDimensionTypes.java new file mode 100644 index 0000000000..24add99099 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModDimensionTypes.java @@ -0,0 +1,47 @@ +package dev.dubhe.anvilcraft.init.worldgen; + +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.init.ModBlockTags; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.util.valueproviders.ConstantInt; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.dimension.DimensionType; + +import java.util.OptionalLong; + +public class ModDimensionTypes { + + public static final ResourceKey MUN = key("mun"); + public static final ResourceKey MUN_LEVEL = ResourceKey.create(Registries.DIMENSION, AnvilCraft.of("mun")); + + public static void bootstrap(BootstrapContext context) { + context.register(MUN, new DimensionType( + OptionalLong.of(6000), + true, + false, + false, + false, + 1.0, + false, + true, + -64, + 384, + 384, + ModBlockTags.INFINIBURN_MUN, + MUN_LEVEL.location(), + 0, + new DimensionType.MonsterSettings( + false, + true, + ConstantInt.ZERO, + 0 + ) + )); + } + + private static ResourceKey key(String id) { + return ResourceKey.create(Registries.DIMENSION_TYPE, AnvilCraft.of(id)); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModDimensions.java b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModDimensions.java new file mode 100644 index 0000000000..5ef6b95742 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModDimensions.java @@ -0,0 +1,38 @@ +package dev.dubhe.anvilcraft.init.worldgen; + +import com.mojang.datafixers.util.Pair; +import dev.dubhe.anvilcraft.AnvilCraft; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.biome.Climate; +import net.minecraft.world.level.biome.MultiNoiseBiomeSource; +import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; + +import java.util.List; + +public class ModDimensions { + public static final ResourceKey MUN = register("mun"); + + public static void bootstrap(BootstrapContext context) { + context.register(MUN, mun(context)); + } + + private static LevelStem mun(BootstrapContext context) { + return new LevelStem( + context.lookup(Registries.DIMENSION_TYPE).getOrThrow(ModDimensionTypes.MUN), + new NoiseBasedChunkGenerator( + MultiNoiseBiomeSource.createFromList(new Climate.ParameterList<>(List.of(Pair.of( + Climate.parameters(0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F), + context.lookup(Registries.BIOME).getOrThrow(ModBiomes.MUN) + )))), + context.lookup(Registries.NOISE_SETTINGS).getOrThrow(ModNoiseGeneratorSettings.MUN) + ) + ); + } + + private static ResourceKey register(String id) { + return ResourceKey.create(Registries.LEVEL_STEM, AnvilCraft.of(id)); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModFeatures.java b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModFeatures.java new file mode 100644 index 0000000000..aace6ce44b --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModFeatures.java @@ -0,0 +1,22 @@ +package dev.dubhe.anvilcraft.init.worldgen; + +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.worldgen.CraterConfiguration; +import dev.dubhe.anvilcraft.worldgen.CraterFeature; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +public class ModFeatures { + private static final DeferredRegister> REGISTER = DeferredRegister.create(Registries.FEATURE, AnvilCraft.MOD_ID); + + public static final DeferredHolder, CraterFeature> CRATER = REGISTER.register("crater", () -> new CraterFeature( + CraterConfiguration.CODEC + )); + + public static void initialize(IEventBus modEventBus) { + REGISTER.register(modEventBus); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModNoiseGeneratorSettings.java b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModNoiseGeneratorSettings.java new file mode 100644 index 0000000000..6cb01559c1 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModNoiseGeneratorSettings.java @@ -0,0 +1,146 @@ +package dev.dubhe.anvilcraft.init.worldgen; + +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.init.ModBlocks; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.biome.OverworldBiomeBuilder; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.DensityFunction; +import net.minecraft.world.level.levelgen.DensityFunctions; +import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; +import net.minecraft.world.level.levelgen.NoiseRouter; +import net.minecraft.world.level.levelgen.NoiseRouterData; +import net.minecraft.world.level.levelgen.NoiseSettings; +import net.minecraft.world.level.levelgen.Noises; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.VerticalAnchor; +import net.minecraft.world.level.levelgen.placement.CaveSurface; +import net.minecraft.world.level.levelgen.synth.NormalNoise; + +public class ModNoiseGeneratorSettings { + private static final ResourceKey SHIFT_X = createDensityKey("shift_x"); + private static final ResourceKey SHIFT_Z = createDensityKey("shift_z"); + private static final ResourceKey SLOPED_CHEESE = createDensityKey("overworld/sloped_cheese"); + private static final ResourceKey ENTRANCES = createDensityKey("overworld/caves/entrances"); + private static final ResourceKey NOODLE = createDensityKey("overworld/caves/noodle"); + private static final ResourceKey PILLARS = createDensityKey("overworld/caves/pillars"); + private static final ResourceKey SPAGHETTI_ROUGHNESS_FUNCTION = createDensityKey( + "overworld/caves/spaghetti_roughness_function"); + private static final ResourceKey SPAGHETTI_2D = createDensityKey("overworld/caves/spaghetti_2d"); + + private static ResourceKey createDensityKey(String location) { + return ResourceKey.create(Registries.DENSITY_FUNCTION, ResourceLocation.withDefaultNamespace(location)); + } + + public static final ResourceKey MUN = key("mun"); + + private static BootstrapContext context; + + public static void bootstrap(BootstrapContext context) { + ModNoiseGeneratorSettings.context = context; + context.register(MUN, mun()); + ModNoiseGeneratorSettings.context = null; + } + + public static NoiseGeneratorSettings mun() { + NoiseRouter noiseRouter = new NoiseRouter( + DensityFunctions.zero(), + DensityFunctions.zero(), + DensityFunctions.zero(), + DensityFunctions.zero(), + DensityFunctions.zero(), + DensityFunctions.zero(), + DensityFunctions.zero(), + DensityFunctions.zero(), + DensityFunctions.zero(), + DensityFunctions.zero(), + slide(DensityFunctions.constant(-0.703125)), + DensityFunctions.mul( + DensityFunctions.interpolated(DensityFunctions.blendDensity(slide(getFunction(NoiseRouterData.DEPTH)))), + DensityFunctions.constant(0.64) + ).squeeze(), + DensityFunctions.zero(), + DensityFunctions.zero(), + DensityFunctions.zero() + ); + return new NoiseGeneratorSettings( + NoiseSettings.create(-64, 384, 1, 2), + ModBlocks.MUN_ROCK.getDefaultState(), + Blocks.AIR.defaultBlockState(), + noiseRouter, + munRule(), + new OverworldBiomeBuilder().spawnTarget(), + 0, + false, + true, + false, + false + ); + } + + private static DensityFunction slide(DensityFunction function) { + return DensityFunctions.lerp( + DensityFunctions.yClampedGradient(-64, -64 + 24, 0.0, 1.0), 0.1, + DensityFunctions.lerp(DensityFunctions.yClampedGradient(-64 + 384 - 80, -64 + 384 - 64, 1.0, 0.0), -0.1, function) + ); + } + + private static DensityFunction underground(DensityFunction input) { + DensityFunction pillars = getFunction(PILLARS); + return DensityFunctions.max( + DensityFunctions.min( + DensityFunctions.min( + DensityFunctions.add( + DensityFunctions.mul( + DensityFunctions.constant(4.0), DensityFunctions.noise(getNoise(Noises.CAVE_LAYER), 8.0).square() + ), + DensityFunctions.add( + DensityFunctions.add( + DensityFunctions.constant(0.27), + DensityFunctions.noise(getNoise(Noises.CAVE_CHEESE), 0.6666666666666666) + ).clamp(-1.0, 1.0), + DensityFunctions.add( + DensityFunctions.constant(1.5), DensityFunctions.mul(DensityFunctions.constant(-0.64), input) + ).clamp(0.0, 0.5) + ) + ), getFunction(ENTRANCES) + ), + DensityFunctions.add(getFunction(SPAGHETTI_2D), getFunction(SPAGHETTI_ROUGHNESS_FUNCTION)) + ), DensityFunctions.rangeChoice( + pillars, -1000000.0, 0.03, DensityFunctions.constant(-1000000.0), pillars + ) + ); + } + + public static SurfaceRules.RuleSource munRule() { + return SurfaceRules.sequence( + SurfaceRules.ifTrue( + SurfaceRules.verticalGradient("bedrock_floor", VerticalAnchor.bottom(), VerticalAnchor.aboveBottom(5)), + SurfaceRules.state(Blocks.BEDROCK.defaultBlockState()) + ), + SurfaceRules.ifTrue( + SurfaceRules.abovePreliminarySurface(), + SurfaceRules.ifTrue( + SurfaceRules.stoneDepthCheck(-1, true, 0, CaveSurface.FLOOR), + SurfaceRules.state(ModBlocks.MUN_SOIL.getDefaultState()) + ) + ) + ); + } + + private static Holder getNoise(ResourceKey key) { + return ModNoiseGeneratorSettings.context.lookup(Registries.NOISE).getOrThrow(key); + } + + private static DensityFunction getFunction(ResourceKey key) { + return new DensityFunctions.HolderHolder(ModNoiseGeneratorSettings.context.lookup(Registries.DENSITY_FUNCTION).getOrThrow(key)); + } + + private static ResourceKey key(String id) { + return ResourceKey.create(Registries.NOISE_SETTINGS, AnvilCraft.of(id)); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModPlacedFeatures.java b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModPlacedFeatures.java new file mode 100644 index 0000000000..d4691513b6 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/init/worldgen/ModPlacedFeatures.java @@ -0,0 +1,51 @@ +package dev.dubhe.anvilcraft.init.worldgen; + +import dev.dubhe.anvilcraft.AnvilCraft; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstrapContext; +import net.minecraft.data.worldgen.placement.PlacementUtils; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.levelgen.placement.BiomeFilter; +import net.minecraft.world.level.levelgen.placement.InSquarePlacement; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.minecraft.world.level.levelgen.placement.RarityFilter; + +public class ModPlacedFeatures { + public static final ResourceKey MEGA_CRATER = key("crater_mega"); + public static final ResourceKey LARGE_CRATER = key("crater_large"); + public static final ResourceKey SMALL_CRATER = key("crater_small"); + + public static void bootstrap(BootstrapContext context) { + PlacementUtils.register( + context, + MEGA_CRATER, + context.lookup(Registries.CONFIGURED_FEATURE).getOrThrow(ModConfiguredFeatures.MEGA_CRATER), + RarityFilter.onAverageOnceEvery(256), + InSquarePlacement.spread(), + PlacementUtils.RANGE_BOTTOM_TO_MAX_TERRAIN_HEIGHT, + BiomeFilter.biome() + ); + PlacementUtils.register( + context, + LARGE_CRATER, + context.lookup(Registries.CONFIGURED_FEATURE).getOrThrow(ModConfiguredFeatures.LARGE_CRATER), + RarityFilter.onAverageOnceEvery(12), + InSquarePlacement.spread(), + PlacementUtils.RANGE_BOTTOM_TO_MAX_TERRAIN_HEIGHT, + BiomeFilter.biome() + ); + PlacementUtils.register( + context, + SMALL_CRATER, + context.lookup(Registries.CONFIGURED_FEATURE).getOrThrow(ModConfiguredFeatures.SMALL_CRATER), + RarityFilter.onAverageOnceEvery(4), + InSquarePlacement.spread(), + PlacementUtils.RANGE_BOTTOM_TO_MAX_TERRAIN_HEIGHT, + BiomeFilter.biome() + ); + } + + private static ResourceKey key(String name) { + return ResourceKey.create(Registries.PLACED_FEATURE, AnvilCraft.of(name)); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/mixin/ThrownEnderpearlMixin.java b/src/main/java/dev/dubhe/anvilcraft/mixin/ThrownEnderpearlMixin.java new file mode 100644 index 0000000000..1bc8b27f6e --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/mixin/ThrownEnderpearlMixin.java @@ -0,0 +1,36 @@ +package dev.dubhe.anvilcraft.mixin; + +import dev.dubhe.anvilcraft.init.reicpe.ModRecipeTriggers; +import dev.dubhe.anvilcraft.recipe.anvil.util.InWorldRecipeContext; +import dev.dubhe.anvilcraft.recipe.anvil.util.InWorldRecipeManager; +import dev.dubhe.anvilcraft.util.Util; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.ThrownEnderpearl; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ThrownEnderpearl.class) +public abstract class ThrownEnderpearlMixin extends Entity { + public ThrownEnderpearlMixin(EntityType entityType, Level level) { + super(entityType, level); + } + + @Inject(method = "tick", at = @At("RETURN")) + private void triggerRecipeAtSpeedAndHeight(CallbackInfo ci) { + if (this.isRemoved()) return; + Level level = this.level(); + if (!(level instanceof ServerLevel serverLevel)) return; + Vec3 pos = this.position(); + ThrownEnderpearl thiS = Util.cast(this); + InWorldRecipeManager manager = level.getRecipeManager().anc$getInWorldRecipeManager(); + InWorldRecipeContext context = new InWorldRecipeContext(serverLevel, pos, thiS); + manager.trigger(ModRecipeTriggers.ON_ENDER_PEARL_TICK.get(), context); + context.accept(); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/outcome/ChangeDimension.java b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/outcome/ChangeDimension.java new file mode 100644 index 0000000000..4ce257bc30 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/outcome/ChangeDimension.java @@ -0,0 +1,239 @@ +package dev.dubhe.anvilcraft.recipe.anvil.outcome; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.dubhe.anvilcraft.init.reicpe.ModRecipeOutcomeTypes; +import dev.dubhe.anvilcraft.recipe.anvil.util.InWorldRecipeContext; +import dev.dubhe.anvilcraft.util.CodecUtil; +import lombok.AccessLevel; +import lombok.Getter; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.projectile.ThrownEnderpearl; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +/** + * 维度传送配方结果 + *

+ * 该类定义了将实体传送到另一个维度的配方结果操作,通常与末影珍珠相关 + * 当配方匹配时,会将末影珍珠及其投掷者传送到指定的维度和位置 + * + * @see IRecipeOutcome 配方结果接口 + */ +@Getter(AccessLevel.PRIVATE) +public class ChangeDimension implements IRecipeOutcome { + private final ResourceKey dimensionKey; + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private final Optional centerPos; + private final Vec2 offset; + + /** + * 构造一个维度传送配方结果 + * + * @param dimensionKey 目标维度键 + * @param centerPos 传送中心位置(可选) + * @param offset 传送位置偏移量 + */ + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + public ChangeDimension(ResourceKey dimensionKey, Optional centerPos, Vec2 offset) { + this.dimensionKey = dimensionKey; + this.centerPos = centerPos; + this.offset = offset; + } + + /** + * 创建一个新的维度传送结果构建器 + * + * @return 构建器实例 + */ + public static Builder builder() { + return new Builder(); + } + + /** + * 获取配方结果类型 + * + * @return 维度传送结果类型 + */ + @Override + public Type getType() { + return ModRecipeOutcomeTypes.CHANGE_DIMENSION.get(); + } + + /** + * 执行维度传送操作 + *

+ * 检查上下文中的实体是否为末影珍珠,并将其投掷者传送到目标维度 + * + * @param context 配方上下文 + */ + @Override + public void accept(InWorldRecipeContext context) { + if (!(context.getEntity() instanceof ThrownEnderpearl pearl)) return; + Entity owner = pearl.getOwner(); + if (owner == null) return; + ServerLevel originLevel = context.getLevel(); + MinecraftServer server = originLevel.getServer(); + ServerLevel targetLevel = server.getLevel(this.dimensionKey); + if (targetLevel == null) return; + if (!owner.canChangeDimensions(originLevel, targetLevel)) return; + BlockPos targetPos = this.centerPos.map(BlockPos::new).orElseGet(targetLevel::getSharedSpawnPos); + targetPos = this.withOffset(targetLevel.random, targetPos); + owner.changeDimension(new DimensionTransition( + targetLevel, + targetPos.getBottomCenter(), + Vec3.ZERO, + 0.0F, + 0.0F, + DimensionTransition.PLAY_PORTAL_SOUND + )); + } + + /** + * 根据随机偏移量计算最终传送位置 + * + * @param random 随机数生成器 + * @param origin 原始位置 + * @return 带偏移量的目标位置 + */ + private BlockPos withOffset(RandomSource random, BlockPos origin) { + float dx = random.nextFloat() * this.offset.x; + float dz = random.nextFloat() * this.offset.y; + return origin.offset(Math.round(dx), 0, Math.round(dz)); + } + + /** + * 维度传送结果类型 + *

+ * 定义了维度传送结果的序列化和反序列化方式 + */ + public static class Type implements IRecipeOutcome.Type { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ResourceKey.codec(Registries.DIMENSION) + .fieldOf("destination") + .forGetter(ChangeDimension::getDimensionKey), + Vec3i.CODEC + .optionalFieldOf("center") + .forGetter(ChangeDimension::getCenterPos), + CodecUtil.VEC2_CODEC + .fieldOf("offset") + .forGetter(ChangeDimension::getOffset) + ).apply(instance, ChangeDimension::new)); + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ResourceKey.streamCodec(Registries.DIMENSION), + ChangeDimension::getDimensionKey, + ByteBufCodecs.optional(CodecUtil.VEC3I_STREAM_CODEC), + ChangeDimension::getCenterPos, + CodecUtil.VEC2_STREAM_CODEC, + ChangeDimension::getOffset, + ChangeDimension::new + ); + + /** + * 获取配方结果的编解码器 + * + * @return MapCodec编解码器 + */ + @Override + public @NotNull MapCodec codec() { + return CODEC; + } + + /** + * 获取配方结果的流编解码器,用于网络传输 + * + * @return StreamCodec流编解码器 + */ + @Override + public @NotNull StreamCodec streamCodec() { + return STREAM_CODEC; + } + } + + /** + * 维度传送结果构建器 + *

+ * 提供便捷的方法来构建维度传送结果,包括设置目标维度、传送位置等参数 + */ + @Getter + public static class Builder { + private ResourceKey dimensionKey; + private Vec3i centerPos; + private Vec2 offset = new Vec2(5, 5); + + /** + * 创建一个新的构建器实例 + */ + private Builder() { + } + + /** + * 设置目标维度 + * + * @param dimensionKey 目标维度键 + * @return 当前构建器实例 + */ + public Builder dimension(ResourceKey dimensionKey) { + this.dimensionKey = dimensionKey; + return this; + } + + /** + * 设置传送中心位置 + * + * @param pos 传送中心位置 + * @return 当前构建器实例 + */ + public Builder restrictNewPos(Vec3i pos) { + this.centerPos = pos; + return this; + } + + /** + * 设置传送位置偏移量 + * + * @param offset 偏移量向量 + * @return 当前构建器实例 + */ + public Builder offset(Vec2 offset) { + this.offset = offset; + return this; + } + + /** + * 设置传送位置偏移量 + * + * @param x X轴偏移量 + * @param z Z轴偏移量 + * @return 当前构建器实例 + */ + public Builder offset(float x, float z) { + this.offset = new Vec2(x, z); + return this; + } + + /** + * 构建维度传送结果实例 + * + * @return 维度传送结果实例 + */ + public ChangeDimension build() { + return new ChangeDimension(this.dimensionKey, Optional.ofNullable(this.centerPos), this.offset); + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/predicate/entity/HasEnderPearl.java b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/predicate/entity/HasEnderPearl.java new file mode 100644 index 0000000000..45ba0ec2fa --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/predicate/entity/HasEnderPearl.java @@ -0,0 +1,195 @@ +package dev.dubhe.anvilcraft.recipe.anvil.predicate.entity; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.dubhe.anvilcraft.init.reicpe.ModRecipePredicateTypes; +import dev.dubhe.anvilcraft.recipe.anvil.predicate.IRecipePredicate; +import dev.dubhe.anvilcraft.recipe.anvil.util.InWorldRecipeContext; +import lombok.Getter; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.entity.projectile.ThrownEnderpearl; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +/** + * 末影珍珠条件谓词 + *

+ * 该类用于判断当前实体是否为末影珍珠,并满足指定的条件(如所在维度、速度、高度等) + * 是维度旅行配方中的条件判断部分 + * + * @see IRecipePredicate 配方谓词接口 + */ +@Getter +public class HasEnderPearl implements IRecipePredicate { + private final ResourceKey dimensionKey; + private final double speed; + private final double height; + + /** + * 构造一个末影珍珠条件谓词 + * + * @param dimensionKey 所在维度键 + * @param speed 最小速度 + * @param height 最小高度 + */ + public HasEnderPearl(ResourceKey dimensionKey, double speed, double height) { + this.dimensionKey = dimensionKey; + this.speed = speed; + this.height = height; + } + + /** + * 创建一个新的末影珍珠条件构建器 + * + * @return 构建器实例 + */ + public static Builder builder() { + return new Builder(); + } + + /** + * 获取配方谓词类型 + * + * @return 末影珍珠条件谓词类型 + */ + @Override + public Type getType() { + return ModRecipePredicateTypes.HAS_ENDER_PEARL.get(); + } + + /** + * 测试当前配方上下文是否满足末影珍珠条件 + *

+ * 条件包括:实体是末影珍珠、所在维度匹配、速度大于设定值、高度大于设定值 + * + * @param context 配方上下文 + * @return 是否满足条件 + */ + @Override + public boolean test(InWorldRecipeContext context) { + if (!(context.getEntity() instanceof ThrownEnderpearl pearl)) return false; + if ( + !context.getLevel() + .dimension() + .location() + .equals(this.dimensionKey.location()) + ) { + return false; + } + if (Math.abs(pearl.getDeltaMovement().y) < this.speed) return false; + return pearl.position().y >= this.height; + } + + /** + * 末影珍珠条件谓词类型 + *

+ * 定义了末影珍珠条件谓词的序列化和反序列化方式 + */ + public static class Type implements IRecipePredicate.Type { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + ResourceKey.codec(Registries.DIMENSION) + .fieldOf("origin") + .forGetter(HasEnderPearl::getDimensionKey), + Codec.DOUBLE + .fieldOf("speed") + .forGetter(HasEnderPearl::getSpeed), + Codec.DOUBLE + .fieldOf("height") + .forGetter(HasEnderPearl::getHeight) + ).apply(instance, HasEnderPearl::new)); + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ResourceKey.streamCodec(Registries.DIMENSION), + HasEnderPearl::getDimensionKey, + ByteBufCodecs.DOUBLE, + HasEnderPearl::getSpeed, + ByteBufCodecs.DOUBLE, + HasEnderPearl::getHeight, + HasEnderPearl::new + ); + + /** + * 获取配方谓词的编解码器 + * + * @return MapCodec编解码器 + */ + @Override + public @NotNull MapCodec codec() { + return CODEC; + } + + /** + * 获取配方谓词的流编解码器,用于网络传输 + * + * @return StreamCodec流编解码器 + */ + @Override + public @NotNull StreamCodec streamCodec() { + return STREAM_CODEC; + } + } + + /** + * 末影珍珠条件谓词构建器 + *

+ * 提供便捷的方法来构建末影珍珠条件谓词,包括设置所在维度、速度、高度等参数 + */ + @Getter + public static class Builder { + private ResourceKey dimensionKey; + private double speed; + private double height; + + /** + * 创建一个新的构建器实例 + */ + private Builder() { + } + + /** + * 设置所在维度 + * + * @param dimensionKey 所在维度键 + * @return 当前构建器实例 + */ + public Builder dimension(ResourceKey dimensionKey) { + this.dimensionKey = dimensionKey; + return this; + } + + /** + * 设置触发条件所需的最小速度 + * + * @param speed 最小速度 + * @return 当前构建器实例 + */ + public Builder speed(double speed) { + this.speed = speed; + return this; + } + + /** + * 设置触发条件所需的最小高度 + * + * @param height 最小高度 + * @return 当前构建器实例 + */ + public Builder height(double height) { + this.height = height; + return this; + } + + /** + * 构建末影珍珠条件谓词实例 + * + * @return 末影珍珠条件谓词实例 + */ + public HasEnderPearl build() { + return new HasEnderPearl(this.dimensionKey, this.speed, this.height); + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/trigger/OnEnderPearlTick.java b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/trigger/OnEnderPearlTick.java new file mode 100644 index 0000000000..474214f234 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/trigger/OnEnderPearlTick.java @@ -0,0 +1,4 @@ +package dev.dubhe.anvilcraft.recipe.anvil.trigger; + +public class OnEnderPearlTick implements IRecipeTrigger { +} diff --git a/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/DimensionTravelRecipe.java b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/DimensionTravelRecipe.java new file mode 100644 index 0000000000..df882d1a23 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/recipe/anvil/wrap/DimensionTravelRecipe.java @@ -0,0 +1,332 @@ +package dev.dubhe.anvilcraft.recipe.anvil.wrap; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.init.ModRecipeTypes; +import dev.dubhe.anvilcraft.init.reicpe.ModRecipeTriggers; +import dev.dubhe.anvilcraft.recipe.anvil.InWorldRecipe; +import dev.dubhe.anvilcraft.recipe.anvil.builder.AbstractRecipeBuilder; +import dev.dubhe.anvilcraft.recipe.anvil.outcome.ChangeDimension; +import dev.dubhe.anvilcraft.recipe.anvil.predicate.entity.HasEnderPearl; +import lombok.AccessLevel; +import lombok.Getter; +import net.minecraft.core.Vec3i; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.data.recipes.RecipeOutput; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.crafting.RecipeSerializer; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec2; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * 维度旅行配方类 + *

+ * 该类定义了通过末影珍珠进行维度旅行的配方逻辑,包括判断末影珍珠是否满足条件以及执行维度传送操作 + *

+ * 配方由两个主要部分组成: + * 1. {@link HasEnderPearl} - 判断末影珍珠是否满足触发条件(如速度、高度、所在维度等) + * 2. {@link ChangeDimension} - 执行维度传送的具体操作 + * + * @see HasEnderPearl 末影珍珠条件判断 + * @see ChangeDimension 维度传送操作 + */ +@Getter(AccessLevel.PRIVATE) +public class DimensionTravelRecipe extends InWorldRecipe { + private final HasEnderPearl hasEnderPearl; + private final ChangeDimension changeDimension; + + /** + * 构造一个维度旅行配方 + * + * @param hasEnderPearl 末影珍珠条件谓词 + * @param changeDimension 维度传送结果 + */ + public DimensionTravelRecipe(HasEnderPearl hasEnderPearl, ChangeDimension changeDimension) { + super( + Items.ENDER_PEARL.getDefaultInstance(), + ModRecipeTriggers.ON_ENDER_PEARL_TICK.get(), + List.of(), + List.of(hasEnderPearl), + List.of(changeDimension), + DimensionTravelRecipe.getPriority(hasEnderPearl), + false + ); + this.hasEnderPearl = hasEnderPearl; + this.changeDimension = changeDimension; + } + + /** + * 创建一个新的配方构建器 + * + * @return 配方构建器实例 + */ + public static Builder builder() { + return new Builder(); + } + + /** + * 判断该配方是否为特殊配方(不在配方书中显示) + * + * @return true 表示为特殊配方 + */ + @Override + public boolean isSpecial() { + return true; + } + + /** + * 计算配方优先级,基于末影珍珠的高度和速度 + * + * @param hasEnderPearl 末影珍珠条件谓词 + * @return 计算出的优先级数值 + */ + private static int getPriority(HasEnderPearl hasEnderPearl) { + return (int) Math.round(hasEnderPearl.getHeight() * 2) + + (int) Math.floor(hasEnderPearl.getSpeed() / 3); + } + + /** + * 获取配方类型 + * + * @return 维度旅行配方类型 + */ + @Override + public @NotNull RecipeType getType() { + return ModRecipeTypes.DIMENSION_TRAVEL_TYPE.get(); + } + + /** + * 获取配方序列化器 + * + * @return 维度旅行配方序列化器 + */ + @Override + public @NotNull RecipeSerializer getSerializer() { + return ModRecipeTypes.DIMENSION_TRAVEL_SERIALIZER.get(); + } + + /** + * 维度旅行配方序列化器 + *

+ * 负责将配方对象序列化为网络传输格式或从网络传输格式反序列化为配方对象 + */ + public static class Serializer implements RecipeSerializer { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group( + HasEnderPearl.Type.CODEC.forGetter(DimensionTravelRecipe::getHasEnderPearl), + ChangeDimension.Type.CODEC.forGetter(DimensionTravelRecipe::getChangeDimension) + ).apply(instance, DimensionTravelRecipe::new)); + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + HasEnderPearl.Type.STREAM_CODEC, DimensionTravelRecipe::getHasEnderPearl, + ChangeDimension.Type.STREAM_CODEC, DimensionTravelRecipe::getChangeDimension, + DimensionTravelRecipe::new + ); + + /** + * 获取配方的编解码器 + * + * @return MapCodec编解码器 + */ + @Override + public @NotNull MapCodec codec() { + return Serializer.CODEC; + } + + /** + * 获取配方的流编解码器,用于网络传输 + * + * @return StreamCodec流编解码器 + */ + @Override + public @NotNull StreamCodec streamCodec() { + return Serializer.STREAM_CODEC; + } + } + + /** + * 维度旅行配方构建器 + *

+ * 提供便捷的方法来构建维度旅行配方,包括设置起始维度、目标维度、传送条件等参数 + */ + public static class Builder extends AbstractRecipeBuilder { + private final HasEnderPearl.Builder hasEnderPearl = HasEnderPearl.builder(); + private final ChangeDimension.Builder changeDimension = ChangeDimension.builder(); + + /** + * 从已有的末影珍珠条件构建器复制参数 + * + * @param builder 末影珍珠条件构建器 + * @return 当前构建器实例 + */ + public Builder from(HasEnderPearl.Builder builder) { + this.hasEnderPearl + .dimension(builder.getDimensionKey()) + .speed(builder.getSpeed()) + .height(builder.getHeight()); + return this; + } + + /** + * 设置起始维度 + * + * @param dimensionKey 起始维度键 + * @return 当前构建器实例 + */ + public Builder from(ResourceKey dimensionKey) { + this.hasEnderPearl.dimension(dimensionKey); + return this; + } + + /** + * 设置触发传送所需的最小速度 + * + * @param speed 最小速度 + * @return 当前构建器实例 + */ + public Builder speed(double speed) { + this.hasEnderPearl.speed(speed); + return this; + } + + /** + * 设置触发传送所需的最小高度 + * + * @param height 最小高度 + * @return 当前构建器实例 + */ + public Builder height(double height) { + this.hasEnderPearl.height(height); + return this; + } + + /** + * 从已有的维度传送结果构建器复制参数 + * + * @param builder 维度传送结果构建器 + * @return 当前构建器实例 + */ + public Builder to(ChangeDimension.Builder builder) { + this.changeDimension + .dimension(builder.getDimensionKey()) + .restrictNewPos(builder.getCenterPos()) + .offset(builder.getOffset()); + return this; + } + + /** + * 设置目标维度 + * + * @param dimensionKey 目标维度键 + * @return 当前构建器实例 + */ + public Builder to(ResourceKey dimensionKey) { + this.changeDimension.dimension(dimensionKey); + return this; + } + + /** + * 设置传送目标位置 + * + * @param newPos 目标位置 + * @return 当前构建器实例 + */ + public Builder toPos(Vec3i newPos) { + this.changeDimension.restrictNewPos(newPos); + return this; + } + + /** + * 设置传送目标位置偏移量 + * + * @param offset 偏移量向量 + * @return 当前构建器实例 + */ + public Builder toPosOffset(Vec2 offset) { + this.changeDimension.offset(offset); + return this; + } + + /** + * 设置传送目标位置偏移量 + * + * @param x X轴偏移量 + * @param z Z轴偏移量 + * @return 当前构建器实例 + */ + public Builder toPosOffset(float x, float z) { + this.changeDimension.offset(x, z); + return this; + } + + /** + * 验证构建器参数是否合法 + * + * @param pId 配方ID + * @throws IllegalArgumentException 当参数不合法时抛出异常 + */ + @Override + public void validate(@NotNull ResourceLocation pId) { + if (this.hasEnderPearl.getDimensionKey() == null) { + throw new IllegalArgumentException("The dimension key of the Ender Pearl must not be null!"); + } + if (this.hasEnderPearl.getSpeed() <= 0) { + throw new IllegalArgumentException("The dimension key of the Ender Pearl must not be lesser than 0!"); + } + if (this.changeDimension.getDimensionKey() == null) { + throw new IllegalArgumentException("The dimension key of the Destination must not be null!"); + } + } + + /** + * 构建配方实例 + * + * @return 维度旅行配方实例 + */ + @Override + public @NotNull DimensionTravelRecipe buildRecipe() { + return new DimensionTravelRecipe(this.hasEnderPearl.build(), this.changeDimension.build()); + } + + /** + * 获取配方结果物品(用于配方书显示) + * + * @return 末影珍珠物品实例 + */ + @Override + public @NotNull Item getResult() { + return Items.ENDER_PEARL; + } + + /** + * 获取配方类型名称 + * + * @return 配方类型名称 "dimension_travel" + */ + @Override + public @NotNull String getType() { + return "dimension_travel"; + } + + /** + * 保存配方到输出 + * + * @param recipeOutput 配方输出 + */ + @Override + public void save(@NotNull RecipeOutput recipeOutput) { + this.save( + recipeOutput, + AnvilCraft.of(this.changeDimension.getDimensionKey().location().getPath()) + .withPrefix("dimension_travel/to_")); + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/dubhe/anvilcraft/util/CodecUtil.java b/src/main/java/dev/dubhe/anvilcraft/util/CodecUtil.java index 89d8762660..f51f2f553a 100644 --- a/src/main/java/dev/dubhe/anvilcraft/util/CodecUtil.java +++ b/src/main/java/dev/dubhe/anvilcraft/util/CodecUtil.java @@ -16,6 +16,7 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.Vec3i; @@ -38,6 +39,7 @@ import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.minecraft.world.level.storage.loot.providers.number.NumberProvider; import net.minecraft.world.level.storage.loot.providers.number.NumberProviders; +import net.minecraft.world.phys.Vec2; import org.jetbrains.annotations.NotNull; import javax.annotation.ParametersAreNonnullByDefault; @@ -267,6 +269,25 @@ public void encode(ByteBuf buffer, Vec3i value) { } ); + public static final Codec VEC2_CODEC = Codec.FLOAT.listOf(2, 2) + .comapFlatMap( + list -> Util.fixedSize(list, 2).map(floats -> new Vec2(floats.getFirst(), floats.get(1))), + vec2 -> List.of(vec2.x, vec2.y) + ); + + public static final StreamCodec VEC2_STREAM_CODEC = new StreamCodec<>() { + @Override + public @NotNull Vec2 decode(ByteBuf buffer) { + return new Vec2(buffer.readFloat(), buffer.readFloat()); + } + + @Override + public void encode(ByteBuf buffer, Vec2 value) { + buffer.writeFloat(value.x); + buffer.writeFloat(value.y); + } + }; + public static StreamCodec composite( final StreamCodec codec1, final Function getter1, diff --git a/src/main/java/dev/dubhe/anvilcraft/worldgen/CraterConfiguration.java b/src/main/java/dev/dubhe/anvilcraft/worldgen/CraterConfiguration.java new file mode 100644 index 0000000000..a816d2775b --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/worldgen/CraterConfiguration.java @@ -0,0 +1,17 @@ +package dev.dubhe.anvilcraft.worldgen; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.util.valueproviders.IntProvider; +import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; + +public record CraterConfiguration(IntProvider radius, IntProvider depth) implements FeatureConfiguration { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + IntProvider.CODEC + .fieldOf("radius") + .forGetter(CraterConfiguration::radius), + IntProvider.CODEC + .fieldOf("depth") + .forGetter(CraterConfiguration::depth) + ).apply(instance, CraterConfiguration::new)); +} diff --git a/src/main/java/dev/dubhe/anvilcraft/worldgen/CraterFeature.java b/src/main/java/dev/dubhe/anvilcraft/worldgen/CraterFeature.java new file mode 100644 index 0000000000..3fadc9d7a1 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/worldgen/CraterFeature.java @@ -0,0 +1,56 @@ +package dev.dubhe.anvilcraft.worldgen; + +import com.mojang.serialization.Codec; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; + +public class CraterFeature extends Feature { + public CraterFeature(Codec codec) { + super(codec); + } + + @Override + public boolean place(FeaturePlaceContext context) { + WorldGenLevel level = context.level(); + BlockPos pos = level.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, context.origin()).below(); + RandomSource randomSource = context.random(); + CraterConfiguration configuration = context.config(); + int radius = configuration.radius().sample(randomSource); + int depth = configuration.depth().sample(randomSource); + if (depth > radius) return false; + int radiusCrater = (depth * depth + radius * radius) / (2 * depth); + if (radiusCrater < 15) { + digCrater(level, pos, radiusCrater, depth); + } else { + level.getLevel().getServer().execute(() -> digCrater(level.getLevel(), pos, radiusCrater, depth)); + } + + return true; + } + + private static void digCrater(LevelAccessor level, BlockPos pos, int radius, int depth) { + BlockPos canter = pos.above(radius - depth); + BlockPos.MutableBlockPos digging = pos.mutable(); + for (int i = -depth; i <= radius; i++) { + boolean bl = false; + + for (int l = -radius; l <= radius; l++) { + for (int m = -radius; m <= radius; m++) { + digging.setWithOffset(pos, l, i, m); + if (digging.distSqr(canter) < radius * radius && !level.getBlockState(digging).isAir()) { + bl = true; + level.setBlock(digging, Blocks.AIR.defaultBlockState(), 3); + } + } + } + + if (!bl && i > 0) break; + } + } +} diff --git a/src/main/resources/anvilcraft.mixins.json b/src/main/resources/anvilcraft.mixins.json index 737bd3dd13..e6e7badf5d 100644 --- a/src/main/resources/anvilcraft.mixins.json +++ b/src/main/resources/anvilcraft.mixins.json @@ -45,6 +45,7 @@ "ServerLevelMixin", "ServerPlayerMixin", "StriderMixin", + "ThrownEnderpearlMixin", "VaultBlockEntityServerMixin", "VibrationSystemUserMixin", "VillagerMixin", diff --git a/src/main/resources/assets/anvilcraft/textures/block/lunar_rock.png b/src/main/resources/assets/anvilcraft/textures/block/mun_rock.png similarity index 100% rename from src/main/resources/assets/anvilcraft/textures/block/lunar_rock.png rename to src/main/resources/assets/anvilcraft/textures/block/mun_rock.png diff --git a/src/main/resources/assets/anvilcraft/textures/block/lunar_rock_1.png b/src/main/resources/assets/anvilcraft/textures/block/mun_rock_1.png similarity index 100% rename from src/main/resources/assets/anvilcraft/textures/block/lunar_rock_1.png rename to src/main/resources/assets/anvilcraft/textures/block/mun_rock_1.png diff --git a/src/main/resources/assets/anvilcraft/textures/block/lunar_rock_2.png b/src/main/resources/assets/anvilcraft/textures/block/mun_rock_2.png similarity index 100% rename from src/main/resources/assets/anvilcraft/textures/block/lunar_rock_2.png rename to src/main/resources/assets/anvilcraft/textures/block/mun_rock_2.png diff --git a/src/main/resources/assets/anvilcraft/textures/block/lunar_rock_3.png b/src/main/resources/assets/anvilcraft/textures/block/mun_rock_3.png similarity index 100% rename from src/main/resources/assets/anvilcraft/textures/block/lunar_rock_3.png rename to src/main/resources/assets/anvilcraft/textures/block/mun_rock_3.png diff --git a/src/main/resources/assets/anvilcraft/textures/block/lunar_soil.png b/src/main/resources/assets/anvilcraft/textures/block/mun_soil.png similarity index 100% rename from src/main/resources/assets/anvilcraft/textures/block/lunar_soil.png rename to src/main/resources/assets/anvilcraft/textures/block/mun_soil.png