Compare commits
15 Commits
f655405d4b
...
f6abe0f038
Author | SHA1 | Date | |
---|---|---|---|
f6abe0f038 | |||
97d30d3a19 | |||
cc9ebef018 | |||
f9c8130e26 | |||
c0812687cb | |||
cd38e1a154 | |||
a903b9cff8 | |||
42b86778cb | |||
36a16ac9d2 | |||
e6bab75bc7 | |||
80128a01e5 | |||
e1decb67ec | |||
9d12044db4 | |||
271f594389 | |||
9ce2fbf497 |
@ -13,6 +13,7 @@ val mod_id: String by project
|
||||
val handle_deps: String by project
|
||||
val use_commit_hash_in_version: String by project
|
||||
val handleDeps = handle_deps.toBoolean()
|
||||
val caffeine_cache_version: String by project
|
||||
|
||||
plugins {
|
||||
java
|
||||
@ -142,14 +143,11 @@ dependencies {
|
||||
|
||||
implementation("thedarkcolour:kotlinforforge-neoforge:$kotlin_for_forge_version")
|
||||
|
||||
jarJar("ru.dbotthepony.kommons:kommons:[$kommons_version,)") { setTransitive(false) }
|
||||
implementation("ru.dbotthepony.kommons:kommons:[$kommons_version,)") { setTransitive(false) }
|
||||
jarJar(implementation("com.github.ben-manes.caffeine:caffeine:[$caffeine_cache_version,)")!!)
|
||||
|
||||
jarJar("ru.dbotthepony.kommons:kommons-gson:[$kommons_version,)") { setTransitive(false) }
|
||||
implementation("ru.dbotthepony.kommons:kommons-gson:[$kommons_version,)") { setTransitive(false) }
|
||||
|
||||
jarJar("ru.dbotthepony.kommons:kommons-guava:[$kommons_version,)") { setTransitive(false) }
|
||||
implementation("ru.dbotthepony.kommons:kommons-guava:[$kommons_version,)") { setTransitive(false) }
|
||||
jarJar(implementation("ru.dbotthepony.kommons:kommons:[$kommons_version,)") { setTransitive(false) })
|
||||
jarJar(implementation("ru.dbotthepony.kommons:kommons-gson:[$kommons_version,)") { setTransitive(false) })
|
||||
jarJar(implementation("ru.dbotthepony.kommons:kommons-guava:[$kommons_version,)") { setTransitive(false) })
|
||||
|
||||
compileOnly("yalter.mousetweaks:MouseTweaks:2.23:api")
|
||||
annotationProcessor("org.spongepowered:mixin:${mixin_version}:processor")
|
||||
@ -228,6 +226,10 @@ minecraft {
|
||||
|
||||
// Log4j console level
|
||||
systemProperty("forge.logging.console.level", "debug")
|
||||
|
||||
dependencies {
|
||||
runtime("com.github.ben-manes.caffeine:caffeine:[$caffeine_cache_version,)")
|
||||
}
|
||||
}
|
||||
|
||||
getByName("client") {
|
||||
|
@ -23,6 +23,7 @@ neogradle.subsystems.parchment.minecraftVersion=1.21.1
|
||||
neogradle.subsystems.parchment.mappingsVersion=2024.11.17
|
||||
|
||||
kommons_version=3.1.3
|
||||
caffeine_cache_version=3.1.5
|
||||
|
||||
jei_version=19.16.4.171
|
||||
jupiter_version=5.9.2
|
||||
|
@ -9,6 +9,8 @@ import net.minecraft.tags.BlockTags
|
||||
import net.minecraft.util.valueproviders.ClampedNormalFloat
|
||||
import net.minecraft.util.valueproviders.ClampedNormalInt
|
||||
import net.minecraft.util.valueproviders.ConstantFloat
|
||||
import net.minecraft.util.valueproviders.IntProvider
|
||||
import net.minecraft.util.valueproviders.UniformFloat
|
||||
import net.minecraft.util.valueproviders.UniformInt
|
||||
import net.minecraft.world.level.levelgen.GenerationStep
|
||||
import net.minecraft.world.level.levelgen.VerticalAnchor
|
||||
@ -21,18 +23,26 @@ import net.minecraft.world.level.levelgen.placement.HeightRangePlacement
|
||||
import net.minecraft.world.level.levelgen.placement.InSquarePlacement
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature
|
||||
import net.minecraft.world.level.levelgen.placement.RarityFilter
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.AlwaysTrueTest
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.BlockStateMatchTest
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.TagMatchTest
|
||||
import net.neoforged.neoforge.common.world.BiomeModifier
|
||||
import net.neoforged.neoforge.registries.NeoForgeRegistries
|
||||
import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.data.world.EllipsoidPlacement
|
||||
import ru.dbotthepony.mc.otm.data.world.StandardDeviationHeightProvider
|
||||
import ru.dbotthepony.mc.otm.data.world.BooleanProvider
|
||||
import ru.dbotthepony.mc.otm.data.world.OneOfFloatProvider
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.StandardDeviationHeightProvider
|
||||
import ru.dbotthepony.mc.otm.registry.game.MBlocks
|
||||
import ru.dbotthepony.mc.otm.registry.data.MWorldGenFeatures
|
||||
import ru.dbotthepony.mc.otm.worldgen.feature.BlackHolePlacerFeature
|
||||
import ru.dbotthepony.mc.otm.worldgen.feature.DebugPlacerFeature
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.AbstractEnormousPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.EnormousEllipsoidPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
||||
|
||||
private object ConfiguredFeatures {
|
||||
val TRITANIUM_ORE = key("tritanium_ore")
|
||||
val TRITANIUM_ORE_SMALL = key("tritanium_ore_small")
|
||||
val DILITHIUM = key("dilithium")
|
||||
val BLACK_HOLE = key("black_hole")
|
||||
|
||||
@ -52,6 +62,8 @@ fun registerConfiguredFeatures(context: BootstrapContext<ConfiguredFeature<*, *>
|
||||
)
|
||||
|
||||
context.register(ConfiguredFeatures.TRITANIUM_ORE, ConfiguredFeature(Feature.ORE, OreConfiguration(target, 9)))
|
||||
//context.register(ConfiguredFeatures.TRITANIUM_ORE_SMALL, ConfiguredFeature(Feature.ORE, OreConfiguration(target, 3)))
|
||||
context.register(ConfiguredFeatures.TRITANIUM_ORE_SMALL, ConfiguredFeature(MWorldGenFeatures.DEBUG_PLACEMENT, DebugPlacerFeature.Config(MBlocks.TRITANIUM_ORE.defaultBlockState())))
|
||||
}
|
||||
|
||||
run {
|
||||
@ -71,7 +83,7 @@ fun registerConfiguredFeatures(context: BootstrapContext<ConfiguredFeature<*, *>
|
||||
private object PlacedFeatures {
|
||||
val NORMAL_TRITANIUM = key("normal_tritanium")
|
||||
val DEEP_TRITANIUM = key("deep_tritanium")
|
||||
val CLOUD_TITANIUM = key("cloud_tritanium")
|
||||
val WORM_TRITANIUM = key("worm_tritanium")
|
||||
val DILITHIUM = key("dilithium")
|
||||
val BLACK_HOLE = key("black_hole")
|
||||
|
||||
@ -104,20 +116,23 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
|
||||
)
|
||||
))
|
||||
|
||||
context.register(PlacedFeatures.CLOUD_TITANIUM, PlacedFeature(
|
||||
ore,
|
||||
context.register(PlacedFeatures.WORM_TRITANIUM, PlacedFeature(
|
||||
configured.getOrThrow(ConfiguredFeatures.TRITANIUM_ORE_SMALL),
|
||||
listOf(
|
||||
RarityFilter.onAverageOnceEvery(16),
|
||||
InSquarePlacement.spread(),
|
||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(10), 15.0)),
|
||||
EllipsoidPlacement(
|
||||
x = ClampedNormalInt.of(0f, 6f, Int.MIN_VALUE, Int.MAX_VALUE),
|
||||
y = ClampedNormalInt.of(0f, 12f, Int.MIN_VALUE, Int.MAX_VALUE),
|
||||
z = ClampedNormalInt.of(0f, 6f, Int.MIN_VALUE, Int.MAX_VALUE),
|
||||
count = ClampedNormalInt.of(60f, 60f, 40, 160),
|
||||
xLength = ClampedNormalFloat.of(11f, 4f, 6f, 14f),
|
||||
yLength = ClampedNormalFloat.of(11f, 4f, 6f, 14f),
|
||||
zLength = ClampedNormalFloat.of(11f, 4f, 6f, 14f),
|
||||
WormPlacement(
|
||||
parameters = AbstractEnormousPlacement.Parameters(
|
||||
chunkScanRange = 12,
|
||||
seedMix = 9284343575495L,
|
||||
placementModifiers = listOf(
|
||||
RarityFilter.onAverageOnceEvery(10),
|
||||
InSquarePlacement.spread(),
|
||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(120), 15.0)),
|
||||
)
|
||||
),
|
||||
wormLength = UniformInt.of(40, 200),
|
||||
wormTurnChance = BooleanProvider.onceEvery(4),
|
||||
wormTurnXY = WormPlacement.normalDistributedTurnRate(60f),
|
||||
wormTurnXZ = WormPlacement.normalDistributedTurnRate(60f),
|
||||
)
|
||||
)
|
||||
))
|
||||
@ -126,22 +141,31 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
|
||||
run {
|
||||
val ore = configured.getOrThrow(ConfiguredFeatures.DILITHIUM)
|
||||
|
||||
val ringularity = OneOfFloatProvider.of(
|
||||
ClampedNormalFloat.of(0.4f, 0.2f, -2f, 2f),
|
||||
ClampedNormalFloat.of(-0.4f, 0.2f, -2f, 2f),
|
||||
)
|
||||
|
||||
context.register(PlacedFeatures.DILITHIUM, PlacedFeature(
|
||||
ore,
|
||||
listOf(
|
||||
RarityFilter.onAverageOnceEvery(12),
|
||||
InSquarePlacement.spread(),
|
||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(0), 15.0)),
|
||||
EllipsoidPlacement(
|
||||
x = ClampedNormalInt.of(0f, 8f, Int.MIN_VALUE, Int.MAX_VALUE),
|
||||
y = ClampedNormalInt.of(0f, 20f, Int.MIN_VALUE, Int.MAX_VALUE),
|
||||
z = ClampedNormalInt.of(0f, 8f, Int.MIN_VALUE, Int.MAX_VALUE),
|
||||
count = ClampedNormalInt.of(200f, 200f, 200, 600),
|
||||
xLength = ClampedNormalFloat.of(11f, 4f, 8f, 14f),
|
||||
// allow crystals to generate as far as standard deviation allows
|
||||
// to increase chance for player to discover crystal vein
|
||||
yLength = ConstantFloat.of(60f),
|
||||
zLength = ClampedNormalFloat.of(11f, 4f, 8f, 14f),
|
||||
EnormousEllipsoidPlacement(
|
||||
parameters = AbstractEnormousPlacement.Parameters(
|
||||
chunkScanRange = 5,
|
||||
seedMix = 237483209523709234L,
|
||||
placementModifiers = listOf(
|
||||
RarityFilter.onAverageOnceEvery(120),
|
||||
InSquarePlacement.spread(),
|
||||
HeightRangePlacement.of(StandardDeviationHeightProvider(VerticalAnchor.absolute(0), 15.0)),
|
||||
),
|
||||
),
|
||||
x = ringularity,
|
||||
y = ringularity,
|
||||
z = ringularity,
|
||||
count = UniformInt.of(8000, 28000),
|
||||
xLength = UniformFloat.of(30f, 70f),
|
||||
yLength = UniformFloat.of(40f, 90f),
|
||||
zLength = UniformFloat.of(30f, 70f),
|
||||
)
|
||||
)
|
||||
))
|
||||
@ -179,7 +203,7 @@ fun registerBiomeModifiers(context: BootstrapContext<BiomeModifier>) {
|
||||
HolderSet.direct(
|
||||
placed.getOrThrow(PlacedFeatures.NORMAL_TRITANIUM),
|
||||
placed.getOrThrow(PlacedFeatures.DEEP_TRITANIUM),
|
||||
placed.getOrThrow(PlacedFeatures.CLOUD_TITANIUM),
|
||||
placed.getOrThrow(PlacedFeatures.WORM_TRITANIUM),
|
||||
placed.getOrThrow(PlacedFeatures.DILITHIUM),
|
||||
),
|
||||
GenerationStep.Decoration.UNDERGROUND_ORES
|
||||
|
@ -11,6 +11,8 @@ fun addBlockModels(provider: MatteryBlockModelProvider) {
|
||||
resourceCubeAll(MBlocks.DEEPSLATE_TRITANIUM_ORE)
|
||||
resourceCubeAll(MBlocks.TRITANIUM_INGOT_BLOCK)
|
||||
|
||||
resourceCubeAll(MBlocks.WITHERED_STEEL_BLOCK)
|
||||
|
||||
resourceCubeAll(MBlocks.DILITHIUM_ORE)
|
||||
resourceCubeAll(MBlocks.DEEPSLATE_DILITHIUM_ORE)
|
||||
resourceCubeAll(MBlocks.DILITHIUM_CRYSTAL_BLOCK)
|
||||
|
@ -32,6 +32,20 @@ fun addBlockStates(provider: MatteryBlockStateProvider) {
|
||||
provider.ore(MBlocks.TRITANIUM_RAW_BLOCK)
|
||||
provider.block(MBlocks.TRITANIUM_INGOT_BLOCK)
|
||||
|
||||
provider.block(MBlocks.WITHERED_STEEL_BLOCK)
|
||||
provider.exec {
|
||||
provider.getVariantBuilder(MBlocks.ROFLITE_ALLOY_BLOCK).forAllStates {
|
||||
val side1 = modLocation("block/resource/roflite_alloy_1")
|
||||
val side2 = modLocation("block/resource/roflite_alloy_2")
|
||||
val top = modLocation("block/resource/roflite_alloy_top")
|
||||
|
||||
val a = provider.models().cube(MBlocks.ROFLITE_ALLOY_BLOCK.registryName!!.path, top, top, side1, side1, side2, side2).texture("particle", side1)
|
||||
val b = provider.models().cube("${MBlocks.ROFLITE_ALLOY_BLOCK.registryName!!.path}_b", top, top, side2, side2, side1, side1).texture("particle", side2)
|
||||
|
||||
return@forAllStates arrayOf(ConfiguredModel.builder().modelFile(a).buildLast(), ConfiguredModel.builder().modelFile(b).buildLast())
|
||||
}
|
||||
}
|
||||
|
||||
provider.ore(MBlocks.DILITHIUM_ORE)
|
||||
provider.ore(MBlocks.DEEPSLATE_DILITHIUM_ORE)
|
||||
provider.block(MBlocks.DILITHIUM_CRYSTAL_BLOCK)
|
||||
|
@ -35,6 +35,9 @@ fun addItemModels(provider: MatteryItemModelProvider) {
|
||||
provider.block(MItems.TRITANIUM_RAW_BLOCK)
|
||||
provider.block(MItems.TRITANIUM_INGOT_BLOCK)
|
||||
|
||||
provider.block(MItems.WITHERED_STEEL_BLOCK)
|
||||
provider.block(MItems.ROFLITE_ALLOY_BLOCK)
|
||||
|
||||
provider.block(MItems.DILITHIUM_ORE)
|
||||
provider.block(MItems.DEEPSLATE_DILITHIUM_ORE)
|
||||
provider.block(MItems.DILITHIUM_CRYSTAL_BLOCK)
|
||||
@ -68,6 +71,7 @@ fun addItemModels(provider: MatteryItemModelProvider) {
|
||||
provider.generated(MItems.PILL_HEAL)
|
||||
provider.generated(MItems.PILL_NOT_NORMAL)
|
||||
provider.generated(MItems.NUTRIENT_PASTE)
|
||||
provider.generated(MItems.IMPERFECT_BREAD)
|
||||
provider.generated(MItems.REDSTONE_INTERACTOR)
|
||||
|
||||
provider.generated(MItems.ESSENCE_DRIVE)
|
||||
@ -100,6 +104,7 @@ fun addItemModels(provider: MatteryItemModelProvider) {
|
||||
|
||||
provider.resource(MItems.DILITHIUM_CRYSTAL)
|
||||
provider.resource(MItems.WITHERED_STEEL)
|
||||
provider.resource(MItems.ROFLITE_ALLOY_INGOT)
|
||||
|
||||
provider.generated(MItems.EXOPACK_PROBE)
|
||||
|
||||
|
@ -612,6 +612,8 @@ private fun blocks(provider: MatteryLanguageProvider) {
|
||||
add(MBlocks.HOLO_SIGN, "desc", "Multi-line, colored and glowing, text sign")
|
||||
|
||||
add(MBlocks.TRITANIUM_INGOT_BLOCK, "Tritanium Plating Block")
|
||||
add(MBlocks.WITHERED_STEEL_BLOCK, "Withered Steel Block")
|
||||
add(MBlocks.ROFLITE_ALLOY_BLOCK, "Roflite Alloy Block")
|
||||
|
||||
addBlock(MBlocks.ENERGY_COUNTER.values, "Energy Counter")
|
||||
addBlock(MBlocks.ENERGY_COUNTER.values, "desc", "Restricts energy flow direction;")
|
||||
@ -741,6 +743,7 @@ private fun items(provider: MatteryLanguageProvider) {
|
||||
add(MItems.ESSENCE_SERVO, "desc2", "Can be used as a tool to pump essence manually")
|
||||
|
||||
add(MItems.NUTRIENT_PASTE, "Nutrient Paste")
|
||||
add(MItems.IMPERFECT_BREAD, "Imperfect Bread")
|
||||
|
||||
add(MItems.FLUID_CAPSULE, "Fluid Capsule")
|
||||
add(MItems.FLUID_CAPSULE, "named", "Fluid Capsule (%s)")
|
||||
@ -788,6 +791,7 @@ private fun items(provider: MatteryLanguageProvider) {
|
||||
add(MItems.TRITANIUM_INGOT, "Tritanium Ingot")
|
||||
add(MItems.DILITHIUM_CRYSTAL, "Dilithium Crystal")
|
||||
add(MItems.WITHERED_STEEL, "Withered Steel Ingot")
|
||||
add(MItems.ROFLITE_ALLOY_INGOT, "Roflite Alloy Ingot")
|
||||
add(MItems.TRITANIUM_NUGGET, "Tritanium Nugget")
|
||||
add(MItems.MATTER_IO_PORT, "Matter IO Port")
|
||||
add(MItems.MATTER_TRANSFORM_MATRIX, "Matter Transformation Matrix")
|
||||
|
@ -616,6 +616,8 @@ private fun blocks(provider: MatteryLanguageProvider) {
|
||||
add(MBlocks.HOLO_SIGN, "desc", "Многострочная, крашеная и светящееся, табличка")
|
||||
|
||||
add(MBlocks.TRITANIUM_INGOT_BLOCK, "Блок слитков тритана")
|
||||
add(MBlocks.WITHERED_STEEL_BLOCK, "Блок иссушенной стали")
|
||||
add(MBlocks.ROFLITE_ALLOY_BLOCK, "Блок рофлитового сплава")
|
||||
|
||||
addBlock(MBlocks.ENERGY_COUNTER.values, "Счётчик энергии")
|
||||
addBlock(MBlocks.ENERGY_COUNTER.values, "desc", "Ограничивает направление передачи энергии;")
|
||||
@ -734,6 +736,7 @@ private fun items(provider: MatteryLanguageProvider) {
|
||||
add(MItems.ESSENCE_SERVO, "desc2", "Может использоваться как инструмент для ручной перекачки эссенции")
|
||||
|
||||
add(MItems.NUTRIENT_PASTE, "Питательная паста")
|
||||
add(MItems.IMPERFECT_BREAD, "Несовершенный хлеб")
|
||||
|
||||
add(MItems.FLUID_CAPSULE, "Жидкостная капсула")
|
||||
add(MItems.FLUID_CAPSULE, "named", "Жидкостная капсула (%s)")
|
||||
@ -781,6 +784,7 @@ private fun items(provider: MatteryLanguageProvider) {
|
||||
add(MItems.TRITANIUM_INGOT, "Тритановый слиток")
|
||||
add(MItems.DILITHIUM_CRYSTAL, "Дилитевый кристалл")
|
||||
add(MItems.WITHERED_STEEL, "Слиток иссушенной стали")
|
||||
add(MItems.ROFLITE_ALLOY_INGOT, "Слиток рофлитового сплава")
|
||||
add(MItems.TRITANIUM_NUGGET, "Тритановый самородок")
|
||||
add(MItems.MATTER_IO_PORT, "Порт ввода/вывода материи")
|
||||
add(MItems.MATTER_TRANSFORM_MATRIX, "Матрица преобразования материи")
|
||||
|
@ -50,6 +50,8 @@ fun addDecorativeLoot(lootTables: LootTables) {
|
||||
lootTables.dropsSelf(MBlocks.TRITANIUM_INGOT_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
|
||||
lootTables.dropsSelf(MBlocks.TRITANIUM_BARS) { condition(ExplosionCondition.survivesExplosion()) }
|
||||
|
||||
lootTables.dropsSelf(MBlocks.WITHERED_STEEL_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
|
||||
|
||||
lootTables.dropsSelf(MBlocks.TRITANIUM_HULL) { condition(ExplosionCondition.survivesExplosion()) }
|
||||
|
||||
lootTables.dropsSelf(MBlocks.GENERATOR_BLOCK) { condition(ExplosionCondition.survivesExplosion()) }
|
||||
|
@ -93,4 +93,24 @@ fun addShapelessRecipes(consumer: RecipeOutput) {
|
||||
hammerRecipe(MItems.TRITANIUM_PLATE, MItemTags.TRITANIUM_INGOTS, consumer)
|
||||
hammerRecipe(MItems.IRON_PLATE, Tags.Items.INGOTS_IRON, consumer)
|
||||
hammerRecipe(MItems.GOLD_PLATE, Tags.Items.INGOTS_GOLD, consumer)
|
||||
|
||||
ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, MItems.WITHERED_STEEL_BLOCK, 1)
|
||||
.requires(Ingredient.of(MItems.WITHERED_STEEL), 9)
|
||||
.unlockedBy(MItems.WITHERED_STEEL)
|
||||
.save(consumer)
|
||||
|
||||
ShapelessRecipeBuilder(RecipeCategory.MISC, MItems.WITHERED_STEEL, 9)
|
||||
.requires(Ingredient.of(MItems.WITHERED_STEEL_BLOCK))
|
||||
.unlockedBy(MItems.WITHERED_STEEL_BLOCK)
|
||||
.save(consumer)
|
||||
|
||||
ShapelessRecipeBuilder(RecipeCategory.BUILDING_BLOCKS, MItems.ROFLITE_ALLOY_BLOCK, 1)
|
||||
.requires(Ingredient.of(MItems.ROFLITE_ALLOY_INGOT), 9)
|
||||
.unlockedBy(MItems.ROFLITE_ALLOY_INGOT)
|
||||
.save(consumer)
|
||||
|
||||
ShapelessRecipeBuilder(RecipeCategory.MISC, MItems.ROFLITE_ALLOY_INGOT, 9)
|
||||
.requires(Ingredient.of(MItems.ROFLITE_ALLOY_BLOCK))
|
||||
.unlockedBy(MItems.ROFLITE_ALLOY_BLOCK)
|
||||
.save(consumer)
|
||||
}
|
||||
|
@ -11,7 +11,11 @@ import ru.dbotthepony.mc.otm.registry.game.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
|
||||
fun addConstructionTags(tagsProvider: TagsProvider) {
|
||||
tagsProvider.blocks.Appender(BlockTags.BEACON_BASE_BLOCKS).add(MBlocks.TRITANIUM_INGOT_BLOCK)
|
||||
tagsProvider.blocks.Appender(BlockTags.BEACON_BASE_BLOCKS)
|
||||
.add(MBlocks.TRITANIUM_INGOT_BLOCK)
|
||||
.add(MBlocks.DILITHIUM_CRYSTAL_BLOCK)
|
||||
.add(MBlocks.WITHERED_STEEL_BLOCK)
|
||||
.add(MBlocks.ROFLITE_ALLOY_BLOCK)
|
||||
|
||||
tagsProvider.blocks.Appender(MBlockTags.MULTIBLOCK_STRUCTURE)
|
||||
.add(MBlockTags.MULTIBLOCK_HARD_STRUCTURE, MBlockTags.MULTIBLOCK_SOFT_STRUCTURE)
|
||||
|
@ -51,6 +51,8 @@ fun addMineableTags(tagsProvider: TagsProvider) {
|
||||
*MBlocks.ENERGY_SERVO.values.toTypedArray(),
|
||||
|
||||
MBlocks.TRITANIUM_INGOT_BLOCK,
|
||||
MBlocks.WITHERED_STEEL_BLOCK,
|
||||
|
||||
MBlocks.METAL_JUNK,
|
||||
MBlocks.METAL_MESH,
|
||||
MBlocks.TRITANIUM_BARS,
|
||||
@ -96,6 +98,7 @@ fun addMineableTags(tagsProvider: TagsProvider) {
|
||||
MBlocks.DILITHIUM_ORE,
|
||||
MBlocks.DEEPSLATE_DILITHIUM_ORE,
|
||||
MBlocks.DILITHIUM_CRYSTAL_BLOCK,
|
||||
MBlocks.ROFLITE_ALLOY_BLOCK,
|
||||
|
||||
MBlocks.GRAVITATION_STABILIZER,
|
||||
MBlocks.GRAVITATION_STABILIZER_LENS,
|
||||
|
@ -21,6 +21,8 @@ fun addResourceTags(tagsProvider: TagsProvider) {
|
||||
|
||||
tagsProvider.dusts.add("tritanium", MItems.TRITANIUM_DUST)
|
||||
tagsProvider.ingots.add("tritanium", MItems.TRITANIUM_INGOT)
|
||||
tagsProvider.ingots.add("withered_steel", MItems.WITHERED_STEEL)
|
||||
tagsProvider.ingots.add("roflite_alloy", MItems.ROFLITE_ALLOY_INGOT)
|
||||
|
||||
tagsProvider.wires.add("copper", MItems.COPPER_WIRING)
|
||||
tagsProvider.wires.add("gold", MItems.GOLD_WIRING)
|
||||
@ -32,6 +34,10 @@ fun addResourceTags(tagsProvider: TagsProvider) {
|
||||
|
||||
tagsProvider.storageBlocksAsItem.add("tritanium", MItems.TRITANIUM_INGOT_BLOCK)
|
||||
tagsProvider.storageBlocksAsBlock.add("tritanium", MBlocks.TRITANIUM_INGOT_BLOCK)
|
||||
tagsProvider.storageBlocksAsItem.add("withered_steel", MItems.WITHERED_STEEL_BLOCK)
|
||||
tagsProvider.storageBlocksAsBlock.add("withered_steel", MBlocks.WITHERED_STEEL_BLOCK)
|
||||
tagsProvider.storageBlocksAsItem.add("roflite_alloy", MItems.ROFLITE_ALLOY_BLOCK)
|
||||
tagsProvider.storageBlocksAsBlock.add("roflite_alloy", MBlocks.ROFLITE_ALLOY_BLOCK)
|
||||
|
||||
tagsProvider.singleDropOre(
|
||||
MBlocks.TRITANIUM_ORE,
|
||||
|
@ -20,6 +20,8 @@ fun addTags(tagsProvider: TagsProvider) {
|
||||
tagsProvider.items.Appender(ItemTags.BEACON_PAYMENT_ITEMS)
|
||||
.add(MItems.TRITANIUM_INGOT)
|
||||
.add(MItems.DILITHIUM_CRYSTAL)
|
||||
.add(MItems.WITHERED_STEEL)
|
||||
.add(MItems.ROFLITE_ALLOY_INGOT)
|
||||
|
||||
tagsProvider.items.Appender(ItemTags.MEAT).add(MItems.NUTRIENT_PASTE)
|
||||
|
||||
|
@ -86,6 +86,7 @@ import ru.dbotthepony.mc.otm.registry.data.MHeightProviders
|
||||
import ru.dbotthepony.mc.otm.registry.data.MItemFunctionTypes
|
||||
import ru.dbotthepony.mc.otm.registry.data.MLootItemConditions
|
||||
import ru.dbotthepony.mc.otm.registry.data.MLootNumberProviders
|
||||
import ru.dbotthepony.mc.otm.registry.data.MNumberProviders
|
||||
import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers
|
||||
import ru.dbotthepony.mc.otm.registry.data.MWorldGenFeatures
|
||||
import ru.dbotthepony.mc.otm.server.MCommands
|
||||
@ -124,6 +125,7 @@ object OverdriveThatMatters {
|
||||
CommandArgumentTypes.register(MOD_BUS)
|
||||
MHeightProviders.register(MOD_BUS)
|
||||
MPlacementModifiers.register(MOD_BUS)
|
||||
MNumberProviders.register(MOD_BUS)
|
||||
MLootNumberProviders.register(MOD_BUS)
|
||||
|
||||
StorageStack.register(MOD_BUS)
|
||||
|
@ -678,3 +678,15 @@ fun RandomSource.nextNormalDoubles(stddev: Double, mean: Double): DoublePair {
|
||||
fun RandomSource.nextNormalDouble(stddev: Double, mean: Double): Double {
|
||||
return nextGaussian() * stddev + mean
|
||||
}
|
||||
|
||||
fun RandomSource.nextFloat(min: Float, max: Float): Float {
|
||||
require(max >= min) { "Min is bigger than max: $min vs $max" }
|
||||
if (min == max) return min
|
||||
return min + nextFloat() * (max - min)
|
||||
}
|
||||
|
||||
fun RandomSource.nextDouble(min: Double, max: Double): Double {
|
||||
require(max >= min) { "Min is bigger than max: $min vs $max" }
|
||||
if (min == max) return min
|
||||
return min + nextDouble() * (max - min)
|
||||
}
|
||||
|
@ -436,7 +436,9 @@ operator fun Direction.times(int: Int): Vec3i = this.normal.multiply(int)
|
||||
operator fun Vec3i.times(double: Double): Vector = Vector(x * double, y * double, z * double)
|
||||
|
||||
fun Vec3.toIntVector() = Vec3i(x.toInt(), y.toInt(), z.toInt())
|
||||
fun Vec3.toBlockPos() = BlockPos(x.toInt(), y.toInt(), z.toInt())
|
||||
fun Vec3.roundToIntVector() = Vec3i(x.roundToInt(), y.roundToInt(), z.roundToInt())
|
||||
fun Vec3.roundToBlockPos() = BlockPos(x.roundToInt(), y.roundToInt(), z.roundToInt())
|
||||
|
||||
fun BlockPos.asVector(): Vector {
|
||||
return Vector(x + 0.5, y + 0.5, z + 0.5)
|
||||
|
@ -53,3 +53,5 @@ fun <S : Comparable<S>> Codec<S>.maxRange(max: S, exclusive: Boolean = false) =
|
||||
ComparableCodec(this, max = max, maxExclusive = exclusive)
|
||||
fun <S : Comparable<S>> Codec<S>.inRange(min: S, minExclusive: Boolean = false, max: S, maxExclusive: Boolean = false) =
|
||||
ComparableCodec(this, min, max, minExclusive, maxExclusive)
|
||||
fun <S : Comparable<S>> Codec<S>.inRange(min: S, max: S) =
|
||||
ComparableCodec(this, min, max, false, false)
|
||||
|
@ -0,0 +1,33 @@
|
||||
package ru.dbotthepony.mc.otm.data.world
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.valueproviders.FloatProvider
|
||||
import net.minecraft.util.valueproviders.UniformFloat
|
||||
|
||||
class BooleanProvider(val sampler: FloatProvider, val threshold: Float, val lessThan: Boolean = true) {
|
||||
fun sample(random: RandomSource): Boolean {
|
||||
val sampled = sampler.sample(random)
|
||||
|
||||
if (lessThan) {
|
||||
return sampled < threshold
|
||||
} else {
|
||||
return sampled >= threshold
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun onceEvery(samples: Int): BooleanProvider {
|
||||
return BooleanProvider(UniformFloat.of(0f, samples.toFloat()), 1f, lessThan = true)
|
||||
}
|
||||
|
||||
val CODEC: Codec<BooleanProvider> = RecordCodecBuilder.create {
|
||||
it.group(
|
||||
FloatProvider.CODEC.fieldOf("sampler").forGetter(BooleanProvider::sampler),
|
||||
Codec.FLOAT.fieldOf("threshold").forGetter(BooleanProvider::threshold),
|
||||
Codec.BOOL.optionalFieldOf("less_than", true).forGetter(BooleanProvider::lessThan)
|
||||
).apply(it, ::BooleanProvider)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package ru.dbotthepony.mc.otm.data.world
|
||||
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.valueproviders.FloatProvider
|
||||
import net.minecraft.util.valueproviders.FloatProviderType
|
||||
import ru.dbotthepony.mc.otm.registry.data.MNumberProviders
|
||||
|
||||
class OneOfFloatProvider(private val provider: OneOfProvider<FloatProvider>) : FloatProvider() {
|
||||
override fun sample(random: RandomSource): Float {
|
||||
return provider.select(random).sample(random)
|
||||
}
|
||||
|
||||
override fun getMinValue(): Float {
|
||||
return provider.children.minOf { it.minValue }
|
||||
}
|
||||
|
||||
override fun getMaxValue(): Float {
|
||||
return provider.children.minOf { it.maxValue }
|
||||
}
|
||||
|
||||
override fun getType(): FloatProviderType<*> {
|
||||
return MNumberProviders.ONE_OF_FLOAT
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun of(vararg providers: FloatProvider): OneOfFloatProvider {
|
||||
return OneOfFloatProvider(OneOfProvider.of(*providers))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun of(providers: Collection<FloatProvider>): OneOfFloatProvider {
|
||||
return OneOfFloatProvider(OneOfProvider.of(providers))
|
||||
}
|
||||
|
||||
val CODEC = OneOfProvider.createCodec(FloatProvider.CODEC, ::OneOfFloatProvider, OneOfFloatProvider::provider)
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package ru.dbotthepony.mc.otm.data.world
|
||||
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.valueproviders.IntProvider
|
||||
import net.minecraft.util.valueproviders.IntProviderType
|
||||
import ru.dbotthepony.mc.otm.registry.data.MNumberProviders
|
||||
|
||||
class OneOfIntProvider(private val provider: OneOfProvider<IntProvider>) : IntProvider() {
|
||||
override fun sample(random: RandomSource): Int {
|
||||
return provider.select(random).sample(random)
|
||||
}
|
||||
|
||||
override fun getMinValue(): Int {
|
||||
return provider.children.minOf { it.minValue }
|
||||
}
|
||||
|
||||
override fun getMaxValue(): Int {
|
||||
return provider.children.minOf { it.maxValue }
|
||||
}
|
||||
|
||||
override fun getType(): IntProviderType<*> {
|
||||
return MNumberProviders.ONE_OF_INT
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun of(vararg providers: IntProvider): OneOfIntProvider {
|
||||
return OneOfIntProvider(OneOfProvider.of(*providers))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun of(providers: Collection<IntProvider>): OneOfIntProvider {
|
||||
return OneOfIntProvider(OneOfProvider.of(providers))
|
||||
}
|
||||
|
||||
val CODEC = OneOfProvider.createCodec(IntProvider.CODEC, ::OneOfIntProvider, OneOfIntProvider::provider)
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package ru.dbotthepony.mc.otm.data.world
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.DataResult
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.valueproviders.IntProvider
|
||||
import ru.dbotthepony.mc.otm.core.random
|
||||
import java.util.Optional
|
||||
|
||||
class OneOfProvider<T> private constructor(val children: List<T>, val selector: Optional<IntProvider> = Optional.empty()) {
|
||||
fun select(random: RandomSource): T {
|
||||
if (selector.isEmpty) {
|
||||
return children.random(random)
|
||||
}
|
||||
|
||||
val index = selector.get().sample(random)
|
||||
|
||||
if (index !in children.indices) {
|
||||
throw RuntimeException("Provided selector ($selector) provided index out of bounds: $index (bounds: ${children.indices})")
|
||||
}
|
||||
|
||||
return children[index]
|
||||
}
|
||||
|
||||
class Builder<T> {
|
||||
private var selector: IntProvider? = null
|
||||
private val inputs = ArrayList<T>()
|
||||
|
||||
fun indexSelector(selector: IntProvider): Builder<T> {
|
||||
this.selector = selector
|
||||
return this
|
||||
}
|
||||
|
||||
fun add(vararg provider: T): Builder<T> {
|
||||
inputs.addAll(provider)
|
||||
return this
|
||||
}
|
||||
|
||||
fun copy(): Builder<T> {
|
||||
val new = Builder<T>()
|
||||
new.selector = selector
|
||||
new.inputs.addAll(inputs)
|
||||
return new
|
||||
}
|
||||
|
||||
fun build(): OneOfProvider<T> {
|
||||
return OneOfProvider(ImmutableList.copyOf(inputs), Optional.ofNullable(selector))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun <T> of(vararg providers: T): OneOfProvider<T> {
|
||||
return OneOfProvider(ImmutableList.copyOf(providers))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun <T> of(providers: Collection<T>): OneOfProvider<T> {
|
||||
return OneOfProvider(ImmutableList.copyOf(providers))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun <T> createCodec(childrenCodec: Codec<T>): MapCodec<OneOfProvider<T>> {
|
||||
return RecordCodecBuilder.mapCodec {
|
||||
it.group(
|
||||
Codec.list(childrenCodec, 1, Int.MAX_VALUE).fieldOf("children").forGetter<OneOfProvider<T>> { it.children },
|
||||
IntProvider.POSITIVE_CODEC.optionalFieldOf("selector").forGetter<OneOfProvider<T>> { it.selector },
|
||||
).apply(it, ::OneOfProvider)
|
||||
}.validate {
|
||||
if (it.selector.isEmpty || it.selector.get().minValue in it.children.indices && it.selector.get().maxValue in it.children.indices) {
|
||||
return@validate DataResult.success(it)
|
||||
} else {
|
||||
return@validate DataResult.error { "Provided number sampler ${it.selector.get()} can produce values outside of children list index range (list size: ${it.children.size})" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <S, T> createCodec(childrenCodec: Codec<T>, to: (OneOfProvider<T>) -> S, from: (S) -> OneOfProvider<T>): MapCodec<S> {
|
||||
return createCodec(childrenCodec).xmap(to, from)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package ru.dbotthepony.mc.otm.item.consumables
|
||||
|
||||
import net.minecraft.world.effect.MobEffectInstance
|
||||
import net.minecraft.world.effect.MobEffects
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.food.FoodProperties
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class ImperfectBread(properties: Item.Properties) : Item(properties) {
|
||||
override fun finishUsingItem(stack: ItemStack, level: Level, entity: LivingEntity): ItemStack {
|
||||
if (entity is Player) {
|
||||
entity.addEffect(MobEffectInstance(MobEffects.POISON, 80, 0))
|
||||
}
|
||||
return super.finishUsingItem(stack, level, entity)
|
||||
}
|
||||
}
|
||||
|
||||
val IMPERFECT_BREAD_FOOD: FoodProperties = FoodProperties.Builder()
|
||||
.nutrition(5)
|
||||
.saturationModifier(0.6f)
|
||||
.build()
|
||||
|
@ -93,10 +93,12 @@ object MNames {
|
||||
|
||||
// building blocks
|
||||
const val TRITANIUM_BLOCK = "tritanium_block"
|
||||
const val TRITANIUM_BLOCK_YELLOW_CLASSIC = "tritanium_block_yellow_classic"
|
||||
const val TRITANIUM_STAIRS = "tritanium_stairs"
|
||||
const val TRITANIUM_SLAB = "tritanium_slab"
|
||||
const val TRITANIUM_WALL = "tritanium_wall"
|
||||
const val TRITANIUM_STRIPED_BLOCK = "tritanium_striped_block"
|
||||
const val TRITANIUM_CLASSIC_STRIPED_BLOCK = "tritanium_classic_striped_block"
|
||||
const val TRITANIUM_STRIPED_STAIRS = "tritanium_striped_stairs"
|
||||
const val TRITANIUM_STRIPED_SLAB = "tritanium_striped_slab"
|
||||
const val TRITANIUM_STRIPED_WALL = "tritanium_striped_wall"
|
||||
@ -128,6 +130,8 @@ object MNames {
|
||||
const val PILL_HEAL = "pill_heal"
|
||||
const val PILL_NOT_NORMAL = "pill_not_normal"
|
||||
|
||||
const val IMPERFECT_BREAD = "imperfect_bread"
|
||||
|
||||
const val BATTERY_CRUDE = "battery_crude"
|
||||
const val BATTERY_BASIC = "battery_basic"
|
||||
const val BATTERY_NORMAL = "battery_normal"
|
||||
@ -205,8 +209,12 @@ object MNames {
|
||||
const val TRITANIUM_INGOT = "tritanium_ingot"
|
||||
const val TRITANIUM_INGOT_BLOCK = "tritanium_ingot_block"
|
||||
|
||||
const val WITHERED_STEEL_BLOCK = "withered_steel_block"
|
||||
const val WITHERED_STEEL = "withered_steel"
|
||||
|
||||
const val ROFLITE_ALLOY_INGOT = "roflite_alloy_ingot"
|
||||
const val ROFLITE_ALLOY_BLOCK = "roflite_alloy_block"
|
||||
|
||||
const val MATTER_IO_PORT = "matter_io_port"
|
||||
|
||||
const val CARBON_MESH = "carbon_mesh"
|
||||
|
@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.registry.data
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.world.level.levelgen.heightproviders.HeightProviderType
|
||||
import net.neoforged.bus.api.IEventBus
|
||||
import ru.dbotthepony.mc.otm.data.world.StandardDeviationHeightProvider
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.StandardDeviationHeightProvider
|
||||
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
|
||||
|
||||
object MHeightProviders {
|
||||
|
@ -0,0 +1,22 @@
|
||||
package ru.dbotthepony.mc.otm.registry.data
|
||||
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.util.valueproviders.FloatProviderType
|
||||
import net.minecraft.util.valueproviders.IntProviderType
|
||||
import net.neoforged.bus.api.IEventBus
|
||||
import ru.dbotthepony.mc.otm.data.world.OneOfFloatProvider
|
||||
import ru.dbotthepony.mc.otm.data.world.OneOfIntProvider
|
||||
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
|
||||
|
||||
object MNumberProviders {
|
||||
private val floats = MDeferredRegister(BuiltInRegistries.FLOAT_PROVIDER_TYPE)
|
||||
private val ints = MDeferredRegister(BuiltInRegistries.INT_PROVIDER_TYPE)
|
||||
|
||||
fun register(bus: IEventBus) {
|
||||
floats.register(bus)
|
||||
ints.register(bus)
|
||||
}
|
||||
|
||||
val ONE_OF_FLOAT by floats.register("one_of_float") { FloatProviderType { OneOfFloatProvider.CODEC } }
|
||||
val ONE_OF_INT by ints.register("one_of_int") { IntProviderType { OneOfIntProvider.CODEC } }
|
||||
}
|
@ -3,8 +3,10 @@ package ru.dbotthepony.mc.otm.registry.data
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
||||
import net.neoforged.bus.api.IEventBus
|
||||
import ru.dbotthepony.mc.otm.data.world.EllipsoidPlacement
|
||||
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.EllipsoidPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.EnormousEllipsoidPlacement
|
||||
import ru.dbotthepony.mc.otm.worldgen.placement.WormPlacement
|
||||
|
||||
object MPlacementModifiers {
|
||||
private val registry = MDeferredRegister(BuiltInRegistries.PLACEMENT_MODIFIER_TYPE)
|
||||
@ -14,4 +16,6 @@ object MPlacementModifiers {
|
||||
}
|
||||
|
||||
val ELLIPSOID_PLACEMENT by registry.register("ellipsoid") { PlacementModifierType { EllipsoidPlacement.CODEC } }
|
||||
val ENORMOUS_ELLIPSOID_PLACEMENT by registry.register("enormous_ellipsoid") { PlacementModifierType { EnormousEllipsoidPlacement.CODEC } }
|
||||
val WORM_PLACEMENT by registry.register("worm") { PlacementModifierType { WormPlacement.CODEC } }
|
||||
}
|
||||
|
@ -2,8 +2,10 @@ package ru.dbotthepony.mc.otm.registry.data
|
||||
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.neoforged.bus.api.IEventBus
|
||||
import ru.dbotthepony.kommons.util.getValue
|
||||
import ru.dbotthepony.mc.otm.registry.MDeferredRegister
|
||||
import ru.dbotthepony.mc.otm.worldgen.feature.BlackHolePlacerFeature
|
||||
import ru.dbotthepony.mc.otm.worldgen.feature.DebugPlacerFeature
|
||||
|
||||
object MWorldGenFeatures {
|
||||
private val registry = MDeferredRegister(BuiltInRegistries.FEATURE)
|
||||
@ -13,4 +15,5 @@ object MWorldGenFeatures {
|
||||
}
|
||||
|
||||
val BLACK_HOLE_PLACER by registry.register("black_hole_placer") { BlackHolePlacerFeature }
|
||||
val DEBUG_PLACEMENT by registry.register("debug") { DebugPlacerFeature }
|
||||
}
|
||||
|
@ -252,6 +252,14 @@ object MBlocks {
|
||||
Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BLUE).sound(SoundType.METAL).explosionResistance(400f).destroyTime(3f).requiresCorrectToolForDrops())
|
||||
}
|
||||
|
||||
val WITHERED_STEEL_BLOCK: Block by registry.register(MNames.WITHERED_STEEL_BLOCK) {
|
||||
Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_GREEN).sound(SoundType.NETHERITE_BLOCK).explosionResistance(400f).destroyTime(3f).requiresCorrectToolForDrops())
|
||||
}
|
||||
|
||||
val ROFLITE_ALLOY_BLOCK: Block by registry.register(MNames.ROFLITE_ALLOY_BLOCK) {
|
||||
Block(BlockBehaviour.Properties.of().mapColor(MapColor.COLOR_BROWN).sound(SoundType.NETHERITE_BLOCK).explosionResistance(400f).destroyTime(3f).requiresCorrectToolForDrops())
|
||||
}
|
||||
|
||||
val METAL_JUNK: MatteryBlock by registry.register(MNames.METAL_JUNK) {
|
||||
MatteryBlock(BlockBehaviour.Properties.of().sound(SoundType.NETHERITE_BLOCK).mapColor(MapColor.COLOR_GRAY).explosionResistance(45f).destroyTime(3f).requiresCorrectToolForDrops())
|
||||
.addSimpleDescription()
|
||||
|
@ -237,6 +237,10 @@ private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) {
|
||||
accept(MItems.DILITHIUM_CRYSTAL_BLOCK)
|
||||
|
||||
accept(MItems.WITHERED_STEEL)
|
||||
accept(MItems.WITHERED_STEEL_BLOCK)
|
||||
|
||||
accept(MItems.ROFLITE_ALLOY_INGOT)
|
||||
accept(MItems.ROFLITE_ALLOY_BLOCK)
|
||||
|
||||
accept(MItems.TRITANIUM_TOOLS)
|
||||
accept(MItems.TRITANIUM_SHIELD)
|
||||
@ -281,6 +285,7 @@ private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) {
|
||||
base(MItems.CARGO_CRATE_MINECARTS)
|
||||
|
||||
accept(MItems.NUTRIENT_PASTE)
|
||||
accept(MItems.IMPERFECT_BREAD)
|
||||
|
||||
// exo
|
||||
accept(MItems.EXOPACK_PROBE)
|
||||
|
@ -43,16 +43,12 @@ import ru.dbotthepony.mc.otm.core.math.Decimal
|
||||
import ru.dbotthepony.mc.otm.item.BatteryItem
|
||||
import ru.dbotthepony.mc.otm.item.ChestUpgraderItem
|
||||
import ru.dbotthepony.mc.otm.item.CrudeBatteryItem
|
||||
import ru.dbotthepony.mc.otm.item.consumables.EssenceCapsuleItem
|
||||
import ru.dbotthepony.mc.otm.item.EssenceServoItem
|
||||
import ru.dbotthepony.mc.otm.item.FluidCapsuleItem
|
||||
import ru.dbotthepony.mc.otm.item.block.FluidTankItem
|
||||
import ru.dbotthepony.mc.otm.item.GravitationalDisruptorItem
|
||||
import ru.dbotthepony.mc.otm.item.consumables.HealPillItem
|
||||
import ru.dbotthepony.mc.otm.item.MatteryItem
|
||||
import ru.dbotthepony.mc.otm.item.MinecartCargoCrateItem
|
||||
import ru.dbotthepony.mc.otm.item.consumables.PillItem
|
||||
import ru.dbotthepony.mc.otm.item.consumables.PillType
|
||||
import ru.dbotthepony.mc.otm.item.PortableCondensationDriveItem
|
||||
import ru.dbotthepony.mc.otm.item.ProceduralBatteryItem
|
||||
import ru.dbotthepony.mc.otm.item.QuantumBatteryItem
|
||||
@ -62,7 +58,7 @@ import ru.dbotthepony.mc.otm.item.addSimpleDescription
|
||||
import ru.dbotthepony.mc.otm.item.armor.PortableGravitationStabilizerItem
|
||||
import ru.dbotthepony.mc.otm.item.armor.TritaniumArmorItem
|
||||
import ru.dbotthepony.mc.otm.item.block.EnergyCableItem
|
||||
import ru.dbotthepony.mc.otm.item.consumables.NotNormalPill
|
||||
import ru.dbotthepony.mc.otm.item.consumables.*
|
||||
import ru.dbotthepony.mc.otm.item.exopack.ExopackProbeItem
|
||||
import ru.dbotthepony.mc.otm.item.exopack.ExopackSlotUpgradeItem
|
||||
import ru.dbotthepony.mc.otm.item.exopack.ExopackUpgradeItem
|
||||
@ -301,6 +297,9 @@ object MItems {
|
||||
val TRITANIUM_NUGGET: Item by registry.register(MNames.TRITANIUM_NUGGET) { Item(DEFAULT_PROPERTIES) }
|
||||
val TRITANIUM_INGOT: Item by registry.register(MNames.TRITANIUM_INGOT) { Item(DEFAULT_PROPERTIES) }
|
||||
val TRITANIUM_INGOT_BLOCK: BlockItem by registry.register(MNames.TRITANIUM_INGOT_BLOCK) { BlockItem(MBlocks.TRITANIUM_INGOT_BLOCK, DEFAULT_PROPERTIES) }
|
||||
|
||||
val WITHERED_STEEL_BLOCK: BlockItem by registry.register(MNames.WITHERED_STEEL_BLOCK) { BlockItem(MBlocks.WITHERED_STEEL_BLOCK, DEFAULT_PROPERTIES) }
|
||||
|
||||
val TRITANIUM_BARS: BlockItem by registry.register(MNames.TRITANIUM_BARS) { BlockItem(MBlocks.TRITANIUM_BARS, DEFAULT_PROPERTIES) }
|
||||
val METAL_RAILING: BlockItem by registry.register(MNames.METAL_RAILING) { BlockItem(MBlocks.METAL_RAILING, DEFAULT_PROPERTIES) }
|
||||
|
||||
@ -426,6 +425,8 @@ object MItems {
|
||||
val PILL_HEAL: Item by registry.register(MNames.PILL_HEAL) { HealPillItem() }
|
||||
val PILL_NOT_NORMAL: Item by registry.register(MNames.PILL_NOT_NORMAL) { NotNormalPill() }
|
||||
|
||||
val IMPERFECT_BREAD: Item by registry.register(MNames.IMPERFECT_BREAD) { ImperfectBread(Item.Properties().food(IMPERFECT_BREAD_FOOD)) }
|
||||
|
||||
val PILLS = SupplierList(
|
||||
MItems::PILL_ANDROID,
|
||||
MItems::PILL_HUMANE,
|
||||
@ -665,6 +666,9 @@ object MItems {
|
||||
|
||||
val BREAD_MONSTER_SPAWN_EGG: Item by registry.register(MNames.BREAD_MONSTER_SPAWN_EGG){ SpawnEggItem(MEntityTypes.BREAD_MONSTER, 0xFFFFFF, 0xFFFFFF, Item.Properties())}
|
||||
|
||||
val ROFLITE_ALLOY_INGOT: Item by registry.register(MNames.ROFLITE_ALLOY_INGOT) { Item(DEFAULT_PROPERTIES) }
|
||||
val ROFLITE_ALLOY_BLOCK: BlockItem by registry.register(MNames.ROFLITE_ALLOY_BLOCK) { BlockItem(MBlocks.ROFLITE_ALLOY_BLOCK, DEFAULT_PROPERTIES) }
|
||||
|
||||
init {
|
||||
MRegistry.registerItems(registry)
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package ru.dbotthepony.mc.otm.worldgen.feature
|
||||
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.levelgen.feature.Feature
|
||||
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration
|
||||
import ru.dbotthepony.mc.otm.registry.game.MBlocks
|
||||
|
||||
object DebugPlacerFeature : Feature<DebugPlacerFeature.Config>(BlockState.CODEC.xmap(::Config, Config::blockState)) {
|
||||
data class Config(val blockState: BlockState) : FeatureConfiguration
|
||||
|
||||
override fun place(context: FeaturePlaceContext<Config>): Boolean {
|
||||
return context.level().setBlock(context.origin(), context.config().blockState, Block.UPDATE_CLIENTS)
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
package ru.dbotthepony.mc.otm.worldgen.placement
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import com.github.benmanes.caffeine.cache.Scheduler
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import it.unimi.dsi.fastutil.HashCommon
|
||||
import net.minecraft.Util
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.SectionPos
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.level.ChunkPos
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementContext
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifier
|
||||
import ru.dbotthepony.mc.otm.data.codec.inRange
|
||||
import ru.dbotthepony.mc.otm.data.codec.minRange
|
||||
import java.time.Duration
|
||||
import java.util.stream.Stream
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
* Enormous placement base, which allows it to span over several chunks without issues.
|
||||
*
|
||||
* MUST come as first placement modifier, other placement modifiers (such as rarity and
|
||||
* shuffle of center point within chunks) must be provided inside [Parameters.placementModifiers] list, in same order as if they were
|
||||
* *before* this placement
|
||||
*/
|
||||
abstract class AbstractEnormousPlacement(val parameters: Parameters) : PlacementModifier() {
|
||||
data class Parameters(
|
||||
/**
|
||||
* How many chunks away to look for actual placements
|
||||
*
|
||||
* Too small value will cause placement cutoffs
|
||||
*/
|
||||
val chunkScanRange: Int,
|
||||
val seedMix: Long,
|
||||
|
||||
/**
|
||||
* Baseline placement modifiers, dictating how to appear in chunk
|
||||
*/
|
||||
val placementModifiers: List<PlacementModifier>,
|
||||
)
|
||||
|
||||
private class GeneratedChunk(positions: Stream<BlockPos>) {
|
||||
// TODO: memory inefficient
|
||||
private val positions = ArrayList<BlockPos>()
|
||||
|
||||
init {
|
||||
positions.forEach { this.positions.add(it) }
|
||||
}
|
||||
|
||||
// TODO: this is primitive implementation, need to implement better one
|
||||
fun getPositions(pos: ChunkPos): Stream<BlockPos> {
|
||||
return positions.stream().filter {
|
||||
SectionPos.blockToSectionCoord(it.x) == pos.x &&
|
||||
SectionPos.blockToSectionCoord(it.z) == pos.z
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun getPositions(center: BlockPos, random: RandomSource): Stream<BlockPos>
|
||||
|
||||
private val chunkCache = Caffeine.newBuilder()
|
||||
.scheduler(Scheduler.systemScheduler())
|
||||
.executor(Util.backgroundExecutor())
|
||||
.maximumSize(16384L)
|
||||
.expireAfterWrite(Duration.ofMinutes(5))
|
||||
.softValues()
|
||||
.build<ChunkPos, GeneratedChunk>()
|
||||
|
||||
private fun computeChunk(context: PlacementContext, pos: ChunkPos): GeneratedChunk {
|
||||
// TODO: Maybe switch to something else other than original LCG PRNG? Original form of LCG is kinda bad for this kind of workload
|
||||
val random = RandomSource.create(context.level.seed + HashCommon.murmurHash3(pos.x + pos.z * 31) + parameters.seedMix)
|
||||
var stream = Stream.of(BlockPos(pos.minBlockX, 0, pos.minBlockZ))
|
||||
parameters.placementModifiers.forEach { modifier -> stream = stream.flatMap { modifier.getPositions(context, random, it).sequential() } }
|
||||
return GeneratedChunk(stream.flatMap { getPositions(it, random) })
|
||||
}
|
||||
|
||||
final override fun getPositions(context: PlacementContext, random: RandomSource, pos: BlockPos): Stream<BlockPos> {
|
||||
val cPos = ChunkPos(pos)
|
||||
val instances = ArrayList<GeneratedChunk>()
|
||||
|
||||
for (x in -parameters.chunkScanRange .. parameters.chunkScanRange) {
|
||||
for (z in -parameters.chunkScanRange .. parameters.chunkScanRange) {
|
||||
// floor, so chunk scan range of 1 will give square instead of diamond
|
||||
val radius = sqrt(x.toDouble() * x + z.toDouble() * z).toInt()
|
||||
|
||||
if (radius <= parameters.chunkScanRange) {
|
||||
val thisPos = ChunkPos(cPos.x + x, cPos.z + z)
|
||||
|
||||
instances.add(chunkCache.get(thisPos) { computeChunk(context, thisPos) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return instances.stream().flatMap { it.getPositions(cPos) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
val PARAMETERS_CODEC: MapCodec<Parameters> = RecordCodecBuilder.mapCodec {
|
||||
it.group(
|
||||
Codec.INT.minRange(0).fieldOf("chunk_scan_range").forGetter(Parameters::chunkScanRange),
|
||||
Codec.LONG.fieldOf("seed_mix").forGetter(Parameters::seedMix),
|
||||
CODEC.listOf().fieldOf("placement").forGetter(Parameters::placementModifiers),
|
||||
).apply(it, ::Parameters)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package ru.dbotthepony.mc.otm.data.world
|
||||
package ru.dbotthepony.mc.otm.worldgen.placement
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
@ -19,16 +19,20 @@ import java.util.stream.Stream
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
// aka "cloud placement"
|
||||
/**
|
||||
* Regular ellipsoid ("cloud") placement, suitable to be used as non-primary placement modifier
|
||||
*
|
||||
* This placement modifier is designed to be terminal; other placement modifiers after this MUST NOT be placed
|
||||
*/
|
||||
data class EllipsoidPlacement(
|
||||
val x: IntProvider,
|
||||
val z: IntProvider,
|
||||
val y: IntProvider,
|
||||
val count: IntProvider,
|
||||
val xLength: FloatProvider,
|
||||
val zLength: FloatProvider,
|
||||
val yLength: FloatProvider,
|
||||
) : PlacementModifier() {
|
||||
override val x: FloatProvider,
|
||||
override val z: FloatProvider,
|
||||
override val y: FloatProvider,
|
||||
override val count: IntProvider,
|
||||
override val xLength: FloatProvider,
|
||||
override val zLength: FloatProvider,
|
||||
override val yLength: FloatProvider,
|
||||
) : PlacementModifier(), IEllipsoidPlacement {
|
||||
init {
|
||||
require(xLength.minValue >= 1f) { "Bad ellipsoid x minimal size: $xLength" }
|
||||
require(zLength.minValue >= 1f) { "Bad ellipsoid z minimal size: $zLength" }
|
||||
@ -40,34 +44,7 @@ data class EllipsoidPlacement(
|
||||
random: RandomSource,
|
||||
position: BlockPos
|
||||
): Stream<BlockPos> {
|
||||
var count = count.sample(random)
|
||||
|
||||
if (count <= 0) {
|
||||
return Stream.empty()
|
||||
}
|
||||
|
||||
val xLength = xLength.sample(random)
|
||||
val zLength = zLength.sample(random)
|
||||
val yLength = yLength.sample(random)
|
||||
|
||||
val xPow = xLength * xLength
|
||||
val zPow = zLength * zLength
|
||||
val yPow = yLength * yLength
|
||||
|
||||
count = minOf(count, (xLength * zLength * yLength * PI * (4.0 / 3.0)).roundToInt())
|
||||
count = 600
|
||||
|
||||
return Stream.generate { position + BlockPos(this.x.sample(random), this.y.sample(random), this.z.sample(random)) }
|
||||
.limit(count * 10L) // failsafe
|
||||
.filter {
|
||||
val (ellipsoidX, ellipsoidY, ellipsoidZ) = it - position
|
||||
|
||||
(ellipsoidX * ellipsoidX) / xPow +
|
||||
(ellipsoidY * ellipsoidY) / yPow +
|
||||
(ellipsoidZ * ellipsoidZ) / zPow <= 1.0f
|
||||
}
|
||||
.distinct()
|
||||
.limit(count.toLong())
|
||||
return getEllipsoidPositions(random, position)
|
||||
}
|
||||
|
||||
override fun type(): PlacementModifierType<*> {
|
||||
@ -78,9 +55,9 @@ data class EllipsoidPlacement(
|
||||
val CODEC: MapCodec<EllipsoidPlacement> by lazy {
|
||||
RecordCodecBuilder.mapCodec {
|
||||
it.group(
|
||||
IntProvider.CODEC.fieldOf("x").forGetter(EllipsoidPlacement::x),
|
||||
IntProvider.CODEC.fieldOf("y").forGetter(EllipsoidPlacement::y),
|
||||
IntProvider.CODEC.fieldOf("z").forGetter(EllipsoidPlacement::z),
|
||||
FloatProvider.CODEC.fieldOf("x").forGetter(EllipsoidPlacement::x),
|
||||
FloatProvider.CODEC.fieldOf("y").forGetter(EllipsoidPlacement::y),
|
||||
FloatProvider.CODEC.fieldOf("z").forGetter(EllipsoidPlacement::z),
|
||||
IntProvider.CODEC.fieldOf("count").forGetter(EllipsoidPlacement::count),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("x_size").forGetter(EllipsoidPlacement::xLength),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("z_size").forGetter(EllipsoidPlacement::zLength),
|
@ -0,0 +1,60 @@
|
||||
package ru.dbotthepony.mc.otm.worldgen.placement
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.valueproviders.FloatProvider
|
||||
import net.minecraft.util.valueproviders.IntProvider
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
||||
import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers
|
||||
import java.util.stream.Stream
|
||||
|
||||
/**
|
||||
* Enormous ellipsoid ("cloud") placement, suitable to be used as ONLY primary placement modifier
|
||||
*
|
||||
* This placement modifier is designed to be terminal; other placement modifiers after this MUST NOT be placed
|
||||
*
|
||||
* @see AbstractEnormousPlacement
|
||||
*/
|
||||
class EnormousEllipsoidPlacement(
|
||||
parameters: Parameters,
|
||||
override val x: FloatProvider,
|
||||
override val z: FloatProvider,
|
||||
override val y: FloatProvider,
|
||||
override val count: IntProvider,
|
||||
override val xLength: FloatProvider,
|
||||
override val zLength: FloatProvider,
|
||||
override val yLength: FloatProvider,
|
||||
) : AbstractEnormousPlacement(parameters), IEllipsoidPlacement {
|
||||
init {
|
||||
require(xLength.minValue >= 1f) { "Bad ellipsoid x minimal size: $xLength" }
|
||||
require(zLength.minValue >= 1f) { "Bad ellipsoid z minimal size: $zLength" }
|
||||
require(yLength.minValue >= 1f) { "Bad ellipsoid y minimal size: $yLength" }
|
||||
}
|
||||
|
||||
override fun type(): PlacementModifierType<*> {
|
||||
return MPlacementModifiers.ENORMOUS_ELLIPSOID_PLACEMENT
|
||||
}
|
||||
|
||||
override fun getPositions(center: BlockPos, random: RandomSource): Stream<BlockPos> {
|
||||
return getEllipsoidPositions(random, center)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC: MapCodec<EnormousEllipsoidPlacement> by lazy {
|
||||
RecordCodecBuilder.mapCodec {
|
||||
it.group(
|
||||
PARAMETERS_CODEC.forGetter(EnormousEllipsoidPlacement::parameters),
|
||||
FloatProvider.CODEC.fieldOf("x").forGetter(EnormousEllipsoidPlacement::x),
|
||||
FloatProvider.CODEC.fieldOf("y").forGetter(EnormousEllipsoidPlacement::y),
|
||||
FloatProvider.CODEC.fieldOf("z").forGetter(EnormousEllipsoidPlacement::z),
|
||||
IntProvider.CODEC.fieldOf("count").forGetter(EnormousEllipsoidPlacement::count),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("x_size").forGetter(EnormousEllipsoidPlacement::xLength),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("z_size").forGetter(EnormousEllipsoidPlacement::zLength),
|
||||
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("y_size").forGetter(EnormousEllipsoidPlacement::yLength),
|
||||
).apply(it, ::EnormousEllipsoidPlacement)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package ru.dbotthepony.mc.otm.worldgen.placement
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.valueproviders.FloatProvider
|
||||
import net.minecraft.util.valueproviders.IntProvider
|
||||
import ru.dbotthepony.mc.otm.core.math.component1
|
||||
import ru.dbotthepony.mc.otm.core.math.component2
|
||||
import ru.dbotthepony.mc.otm.core.math.component3
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import java.util.stream.Stream
|
||||
|
||||
interface IEllipsoidPlacement {
|
||||
/**
|
||||
* X position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||
*/
|
||||
val x: FloatProvider
|
||||
|
||||
/**
|
||||
* Z position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||
*/
|
||||
val z: FloatProvider
|
||||
|
||||
/**
|
||||
* Y position within ellipsoid sampler, expected to be in range -1 .. 1
|
||||
*/
|
||||
val y: FloatProvider
|
||||
|
||||
/**
|
||||
* Total amount of block positions to generate
|
||||
*/
|
||||
val count: IntProvider
|
||||
|
||||
/**
|
||||
* Ellipsoid size sampler on X axis
|
||||
*/
|
||||
val xLength: FloatProvider
|
||||
|
||||
/**
|
||||
* Ellipsoid size sampler on Z axis
|
||||
*/
|
||||
val zLength: FloatProvider
|
||||
|
||||
/**
|
||||
* Ellipsoid size sampler on Y axis
|
||||
*/
|
||||
val yLength: FloatProvider
|
||||
|
||||
fun getEllipsoidPositions(random: RandomSource, position: BlockPos): Stream<BlockPos> {
|
||||
val count = count.sample(random)
|
||||
|
||||
if (count <= 0)
|
||||
return Stream.empty()
|
||||
|
||||
val xLength = xLength.sample(random)
|
||||
val zLength = zLength.sample(random)
|
||||
val yLength = yLength.sample(random)
|
||||
|
||||
val xPow = xLength * xLength
|
||||
val zPow = zLength * zLength
|
||||
val yPow = yLength * yLength
|
||||
|
||||
return Stream.generate {
|
||||
val x = this.x.sample(random) * xLength
|
||||
val y = this.y.sample(random) * yLength
|
||||
val z = this.z.sample(random) * zLength
|
||||
BlockPos(x.toInt(), y.toInt(), z.toInt())
|
||||
}
|
||||
.limit(count.toLong() * 10)
|
||||
.filter {
|
||||
val (ellipsoidX, ellipsoidY, ellipsoidZ) = it
|
||||
|
||||
(ellipsoidX * ellipsoidX) / xPow +
|
||||
(ellipsoidY * ellipsoidY) / yPow +
|
||||
(ellipsoidZ * ellipsoidZ) / zPow <= 1.0f
|
||||
}
|
||||
.distinct()
|
||||
.limit(count.toLong())
|
||||
.map { it + position }
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package ru.dbotthepony.mc.otm.data.world
|
||||
package ru.dbotthepony.mc.otm.worldgen.placement
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
@ -0,0 +1,125 @@
|
||||
package ru.dbotthepony.mc.otm.worldgen.placement
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.valueproviders.ClampedNormalFloat
|
||||
import net.minecraft.util.valueproviders.ConstantFloat
|
||||
import net.minecraft.util.valueproviders.FloatProvider
|
||||
import net.minecraft.util.valueproviders.IntProvider
|
||||
import net.minecraft.util.valueproviders.UniformFloat
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
||||
import ru.dbotthepony.mc.otm.core.math.Vector
|
||||
import ru.dbotthepony.mc.otm.core.math.plus
|
||||
import ru.dbotthepony.mc.otm.core.math.toBlockPos
|
||||
import ru.dbotthepony.mc.otm.core.nextDouble
|
||||
import ru.dbotthepony.mc.otm.data.world.BooleanProvider
|
||||
import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers
|
||||
import java.util.stream.Stream
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class WormPlacement(
|
||||
parameters: Parameters,
|
||||
val wormLength: IntProvider,
|
||||
val wormTurnChance: BooleanProvider,
|
||||
val wormTurnXZ: FloatProvider,
|
||||
val wormTurnXY: FloatProvider,
|
||||
) : AbstractEnormousPlacement(parameters) {
|
||||
override fun getPositions(center: BlockPos, random: RandomSource): Stream<BlockPos> {
|
||||
var position = Vector.ZERO
|
||||
val maxDistance = wormLength.sample(random)
|
||||
// determine initial worm facing angle
|
||||
var xzRotation = random.nextDouble(-PI / 2.0, PI / 2.0)
|
||||
var xyRotation = random.nextDouble(-PI / 16.0, PI / 16.0)
|
||||
|
||||
var xzSin = sin(xzRotation)
|
||||
var xzCos = cos(xzRotation)
|
||||
var xySin = sin(xyRotation)
|
||||
|
||||
val positions = ArrayList<BlockPos>()
|
||||
var prevPos = position.toBlockPos()
|
||||
positions.add(prevPos)
|
||||
|
||||
for (traveledDistance in 0 .. maxDistance) {
|
||||
// wormy turn
|
||||
if (wormTurnChance.sample(random)) {
|
||||
// wormy angle
|
||||
// TODO: smooth turning, instead of snapping to new angle make it gradually face new angle
|
||||
xzRotation += wormTurnXZ.sample(random)
|
||||
xyRotation += wormTurnXY.sample(random)
|
||||
|
||||
xzSin = sin(xzRotation)
|
||||
xzCos = cos(xzRotation)
|
||||
xySin = sin(xyRotation)
|
||||
}
|
||||
|
||||
// advance worm
|
||||
position += Vector(xzCos, xySin, xzSin)
|
||||
val calc = position.toBlockPos()
|
||||
|
||||
if (calc != prevPos) {
|
||||
// if worm made a wurm, add new position to set
|
||||
prevPos = calc
|
||||
positions.add(calc)
|
||||
}
|
||||
}
|
||||
|
||||
return positions.stream().map { it + center }
|
||||
}
|
||||
|
||||
override fun type(): PlacementModifierType<*> {
|
||||
return MPlacementModifiers.WORM_PLACEMENT
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun increment(value: Float): Float {
|
||||
var i = 1f
|
||||
|
||||
while (true) {
|
||||
val enlarge = Float.MIN_VALUE * i
|
||||
val sum = value + enlarge
|
||||
|
||||
if (sum != value) {
|
||||
return sum
|
||||
} else {
|
||||
i += 1f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun uniformTurnRate(degrees: Float): FloatProvider {
|
||||
return uniformTurnRateRadians(degrees * DEGREES_TO_RADIANS)
|
||||
}
|
||||
|
||||
fun uniformTurnRateRadians(rad: Float): FloatProvider {
|
||||
require(rad >= 0f) { "Provided value must be non-negative, $rad given" }
|
||||
if (rad == 0f) return ConstantFloat.ZERO
|
||||
return UniformFloat.of(-rad, increment(rad))
|
||||
}
|
||||
|
||||
fun normalDistributedTurnRate(deviation: Float): FloatProvider {
|
||||
return normalDistributedTurnRateRadians(deviation * DEGREES_TO_RADIANS)
|
||||
}
|
||||
|
||||
fun normalDistributedTurnRateRadians(deviation: Float): FloatProvider {
|
||||
require(deviation >= 0f) { "Provided value must be non-negative, $deviation given" }
|
||||
if (deviation == 0f) return ConstantFloat.ZERO
|
||||
return ClampedNormalFloat.of(0f, deviation, -PI.toFloat() * 2f, PI.toFloat() * 2f)
|
||||
}
|
||||
|
||||
private const val DEGREES_TO_RADIANS = PI.toFloat() / 180f
|
||||
|
||||
val CODEC: MapCodec<WormPlacement> = RecordCodecBuilder.mapCodec {
|
||||
it.group(
|
||||
PARAMETERS_CODEC.forGetter(WormPlacement::parameters),
|
||||
IntProvider.CODEC.fieldOf("length").forGetter(WormPlacement::wormLength),
|
||||
BooleanProvider.CODEC.fieldOf("turn_chance").forGetter(WormPlacement::wormTurnChance),
|
||||
FloatProvider.CODEC.fieldOf("turn_xz").forGetter(WormPlacement::wormTurnXZ),
|
||||
FloatProvider.CODEC.fieldOf("turn_xy").forGetter(WormPlacement::wormTurnXY),
|
||||
).apply(it, ::WormPlacement)
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 489 B |
Loading…
Reference in New Issue
Block a user