Compare commits

...

17 Commits

Author SHA1 Message Date
e7f2e0551a
Merge branch '1.21' into worldgen-placement-providers 2025-03-09 22:01:00 +07:00
755d15fc0b
Replace PCG32 with GJRAND64 2025-03-09 21:52:21 +07:00
9ffee79687
Provide "no seed" initialization for GJRAND64 2025-03-09 21:49:49 +07:00
84ca0c2a24
Use GJRAND64 for enormous placement 2025-03-09 21:47:17 +07:00
326490b73c
Merge branch '1.21' into worldgen-placement-providers 2025-03-09 21:29:52 +07:00
3a08552345
private the internal state of positional random 2025-03-09 21:29:43 +07:00
32fe6e754c
Provide GJRAND64RandomSource 2025-03-09 21:26:44 +07:00
436606abf4
Now Bread monster can spawn when thrown as item
And when killed, inert version is dropped
2025-03-09 21:11:42 +07:00
29edf383cd
Use thread local non-cryptographic random for Quantum Battery UUIDs
since they dont need to be cryptographically secure
2025-03-09 20:07:06 +07:00
9b6fa89850
Add matter value to imperfect bread so it can be replicated 2025-03-09 19:55:35 +07:00
1a30f4d203
Gold Disk, for spawning in dungeons, add Imperfect Bread to dungeons as Gold Disk 2025-03-09 19:54:03 +07:00
3f677ad353
Update bread item 2025-03-09 18:35:55 +07:00
f1c87ed5ad
Specify effect source as attacker in Wither Steel Sword 2025-03-09 16:22:11 +07:00
df7465a59f
Wither skeleton sword and helmet server config 2025-03-09 16:20:58 +07:00
6f2adfd6d3
Withered Steel Sword fixes 2025-03-09 16:17:27 +07:00
e97967903b
Update WitheredSkeletonSpawnHandler implementation 2025-03-09 16:12:24 +07:00
67ea3b977b
Further improve performance of UpgradeContainer 2025-03-09 16:00:51 +07:00
32 changed files with 354 additions and 105 deletions

View File

@ -22,7 +22,7 @@ mixin_version=0.8.5
neogradle.subsystems.parchment.minecraftVersion=1.21.1 neogradle.subsystems.parchment.minecraftVersion=1.21.1
neogradle.subsystems.parchment.mappingsVersion=2024.11.17 neogradle.subsystems.parchment.mappingsVersion=2024.11.17
kommons_version=3.3.2 kommons_version=3.5.2
caffeine_cache_version=3.1.5 caffeine_cache_version=3.1.5
jei_version=19.16.4.171 jei_version=19.16.4.171

View File

@ -34,6 +34,7 @@ import ru.dbotthepony.mc.otm.datagen.items.MatteryItemModelProvider
import ru.dbotthepony.mc.otm.datagen.lang.AddEnglishLanguage import ru.dbotthepony.mc.otm.datagen.lang.AddEnglishLanguage
import ru.dbotthepony.mc.otm.datagen.models.MatteryBlockModelProvider import ru.dbotthepony.mc.otm.datagen.models.MatteryBlockModelProvider
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource
import ru.dbotthepony.mc.otm.data.FlywheelMaterialDataProvider import ru.dbotthepony.mc.otm.data.FlywheelMaterialDataProvider
import ru.dbotthepony.mc.otm.datagen.advancements.addAdvancements import ru.dbotthepony.mc.otm.datagen.advancements.addAdvancements
import ru.dbotthepony.mc.otm.datagen.advancements.addAndroidAdvancements import ru.dbotthepony.mc.otm.datagen.advancements.addAndroidAdvancements
@ -68,6 +69,10 @@ internal fun modLootTable(string: String) = ResourceKey.create(Registries.LOOT_T
object DataGen { object DataGen {
const val MOD_ID = OverdriveThatMatters.MOD_ID const val MOD_ID = OverdriveThatMatters.MOD_ID
// for things which need to be random (e.g. UUIDs),
// so builds continue to be reproducible
val random = GJRAND64RandomSource(822393940230754753L, -2728812999467395658L)
var blockModelProvider: MatteryBlockModelProvider by WriteOnce() var blockModelProvider: MatteryBlockModelProvider by WriteOnce()
private set private set
var itemModelProvider: MatteryItemModelProvider by WriteOnce() var itemModelProvider: MatteryItemModelProvider by WriteOnce()

View File

@ -437,4 +437,6 @@ fun addMatterData(provider: MatterDataProvider) {
} }
} }
} }
provider.inherit(MItems.IMPERFECT_BREAD, Items.BREAD, 1.5)
} }

View File

@ -194,6 +194,8 @@ fun addItemModels(provider: MatteryItemModelProvider) {
provider.generated(MItems.PATTERN_DRIVE_CREATIVE) provider.generated(MItems.PATTERN_DRIVE_CREATIVE)
provider.generated(MItems.PATTERN_DRIVE_CREATIVE2) provider.generated(MItems.PATTERN_DRIVE_CREATIVE2)
provider.withExistingParent(MItems.GOLD_DISK, MItems.PATTERN_DRIVE_CREATIVE.registryName!!)
provider.generated(MItems.MATTER_DUST) provider.generated(MItems.MATTER_DUST)
provider.generated(MItems.TRITANIUM_DOOR.values) provider.generated(MItems.TRITANIUM_DOOR.values)

View File

@ -145,6 +145,8 @@ private fun sounds(provider: MatteryLanguageProvider) {
private fun misc(provider: MatteryLanguageProvider) { private fun misc(provider: MatteryLanguageProvider) {
with(provider.english) { with(provider.english) {
misc("misc.inert", "Inert")
misc("misc.yes", "Yes") misc("misc.yes", "Yes")
misc("misc.no", "No") misc("misc.no", "No")
@ -879,6 +881,9 @@ private fun items(provider: MatteryLanguageProvider) {
add(MItems.PATTERN_DRIVE_QUAD, "Quad-Level Pattern Drive") add(MItems.PATTERN_DRIVE_QUAD, "Quad-Level Pattern Drive")
add(MItems.PATTERN_DRIVE_CREATIVE, "Creative Pattern Drive") add(MItems.PATTERN_DRIVE_CREATIVE, "Creative Pattern Drive")
add(MItems.GOLD_DISK, "Gold Disk")
add(MItems.GOLD_DISK, "single_item", "Gold Disk (%s)")
add(MItems.PATTERN_DRIVE_CREATIVE2, "Omni-Present Pattern Drive") add(MItems.PATTERN_DRIVE_CREATIVE2, "Omni-Present Pattern Drive")
add(MItems.PATTERN_DRIVE_CREATIVE2, "description1", "Creative-only item") add(MItems.PATTERN_DRIVE_CREATIVE2, "description1", "Creative-only item")
add(MItems.PATTERN_DRIVE_CREATIVE2, "description2", "Holds pattern for every item that have matter value") add(MItems.PATTERN_DRIVE_CREATIVE2, "description2", "Holds pattern for every item that have matter value")

View File

@ -159,6 +159,8 @@ private fun sounds(provider: MatteryLanguageProvider) {
private fun misc(provider: MatteryLanguageProvider) { private fun misc(provider: MatteryLanguageProvider) {
with(provider.russian) { with(provider.russian) {
misc("misc.inert", "Инертен")
misc("misc.yes", "Да") misc("misc.yes", "Да")
misc("misc.no", "Нет") misc("misc.no", "Нет")
@ -872,6 +874,9 @@ private fun items(provider: MatteryLanguageProvider) {
add(MItems.PATTERN_DRIVE_QUAD, "Четырёхуровневый диск шаблонов") add(MItems.PATTERN_DRIVE_QUAD, "Четырёхуровневый диск шаблонов")
add(MItems.PATTERN_DRIVE_CREATIVE, "Творческий диск шаблонов") add(MItems.PATTERN_DRIVE_CREATIVE, "Творческий диск шаблонов")
add(MItems.GOLD_DISK, "Золотой диск")
add(MItems.GOLD_DISK, "single_item", "Золотой диск (%s)")
add(MItems.PATTERN_DRIVE_CREATIVE2, "Вездесущий диск шаблонов") add(MItems.PATTERN_DRIVE_CREATIVE2, "Вездесущий диск шаблонов")
add(MItems.PATTERN_DRIVE_CREATIVE2, "description1", "Предмет режима творчества") add(MItems.PATTERN_DRIVE_CREATIVE2, "description1", "Предмет режима творчества")
add(MItems.PATTERN_DRIVE_CREATIVE2, "description2", "Содержит в себе шаблоны всех предметов, которые имеют значение материи") add(MItems.PATTERN_DRIVE_CREATIVE2, "description2", "Содержит в себе шаблоны всех предметов, которые имеют значение материи")

View File

@ -1,7 +1,10 @@
package ru.dbotthepony.mc.otm.datagen.loot package ru.dbotthepony.mc.otm.datagen.loot
import net.minecraft.world.level.storage.loot.functions.SetComponentsFunction
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import ru.dbotthepony.mc.otm.datagen.modLootTable import ru.dbotthepony.mc.otm.datagen.modLootTable
import ru.dbotthepony.mc.otm.registry.game.MDataComponentTypes
import ru.dbotthepony.mc.otm.registry.game.MEntityTypes
import ru.dbotthepony.mc.otm.registry.game.MItems import ru.dbotthepony.mc.otm.registry.game.MItems
fun addEntityLoot(loot: LootTables) { fun addEntityLoot(loot: LootTables) {
@ -18,4 +21,12 @@ fun addEntityLoot(loot: LootTables) {
setRolls(1) setRolls(1)
} }
} }
loot.builder(LootContextParamSets.ENTITY, MEntityTypes.BREAD_MONSTER.defaultLootTable) {
lootPool {
item(MItems.IMPERFECT_BREAD) {
apply(SetComponentsFunction.setComponent(MDataComponentTypes.INERT, true))
}
}
}
} }

View File

@ -5,6 +5,7 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.util.valueproviders.UniformInt import net.minecraft.util.valueproviders.UniformInt
import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.EntityType
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.level.storage.loot.BuiltInLootTables import net.minecraft.world.level.storage.loot.BuiltInLootTables
import net.minecraft.world.level.storage.loot.LootTable import net.minecraft.world.level.storage.loot.LootTable
import net.minecraft.world.level.storage.loot.predicates.LootItemCondition import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
@ -18,9 +19,11 @@ import ru.dbotthepony.mc.otm.data.condition.HasExoPackCondition
import ru.dbotthepony.mc.otm.data.condition.ItemInInventoryCondition import ru.dbotthepony.mc.otm.data.condition.ItemInInventoryCondition
import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayerOrIndirectly import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayerOrIndirectly
import ru.dbotthepony.mc.otm.data.loot.LootPoolAppender import ru.dbotthepony.mc.otm.data.loot.LootPoolAppender
import ru.dbotthepony.mc.otm.datagen.DataGen
import ru.dbotthepony.mc.otm.datagen.modLootTable import ru.dbotthepony.mc.otm.datagen.modLootTable
import ru.dbotthepony.mc.otm.item.ProceduralBatteryItem import ru.dbotthepony.mc.otm.item.ProceduralBatteryItem
import ru.dbotthepony.mc.otm.item.exopack.ProceduralExopackSlotUpgradeItem import ru.dbotthepony.mc.otm.item.exopack.ProceduralExopackSlotUpgradeItem
import ru.dbotthepony.mc.otm.item.matter.GoldDiskItem
import ru.dbotthepony.mc.otm.registry.game.MItems import ru.dbotthepony.mc.otm.registry.game.MItems
@Suppress("FunctionName") @Suppress("FunctionName")
@ -66,6 +69,11 @@ fun addLootModifiers(it: LootModifiers) {
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(4, 10))) apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(4, 10)))
}, },
singleItem(MItems.GOLD_DISK) {
chanceCondition(0.1)
apply(GoldDiskItem.patterns(DataGen.random, MItems.IMPERFECT_BREAD))
},
singleItem(MItems.PROCEDURAL_BATTERY) { singleItem(MItems.PROCEDURAL_BATTERY) {
chanceCondition(0.15) chanceCondition(0.15)
@ -122,6 +130,11 @@ fun addLootModifiers(it: LootModifiers) {
chanceCondition(0.1) chanceCondition(0.1)
apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(27, 56), UniformInt.of(2, 6))) apply(ProceduralExopackSlotUpgradeItem.Randomizer(UniformInt.of(27, 56), UniformInt.of(2, 6)))
}, },
singleItem(MItems.GOLD_DISK) {
chanceCondition(0.15)
apply(GoldDiskItem.patterns(DataGen.random, Items.ENDER_PEARL))
},
)) ))
it.add("dungeon_pill", PlainLootAppender( it.add("dungeon_pill", PlainLootAppender(

View File

@ -34,7 +34,12 @@ fun addEquipmentTags(tagsProvider: TagsProvider) {
.add(MItems.TRITANIUM_BOOTS) .add(MItems.TRITANIUM_BOOTS)
.add(MItems.SIMPLE_TRITANIUM_BOOTS) .add(MItems.SIMPLE_TRITANIUM_BOOTS)
tagsProvider.items.Appender(ItemTags.SWORDS).add(MItems.TRITANIUM_SWORD).add(MItems.ENERGY_SWORD) tagsProvider.items.Appender(ItemTags.SWORDS)
.add(MItems.TRITANIUM_SWORD)
.add(MItems.ENERGY_SWORD)
.add(MItems.FALLING_SUN)
.add(MItems.WITHERED_STEEL_SWORD)
tagsProvider.items.Appender(ItemTags.AXES).add(MItems.TRITANIUM_AXE) tagsProvider.items.Appender(ItemTags.AXES).add(MItems.TRITANIUM_AXE)
tagsProvider.items.Appender(ItemTags.PICKAXES).add(MItems.TRITANIUM_PICKAXE) tagsProvider.items.Appender(ItemTags.PICKAXES).add(MItems.TRITANIUM_PICKAXE)
tagsProvider.items.Appender(ItemTags.SHOVELS).add(MItems.TRITANIUM_SHOVEL) tagsProvider.items.Appender(ItemTags.SHOVELS).add(MItems.TRITANIUM_SHOVEL)

View File

@ -5,11 +5,11 @@ import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import ru.dbotthepony.mc.otm.core.IMatteryLevel; import ru.dbotthepony.mc.otm.core.IMatteryLevel;
import ru.dbotthepony.mc.otm.core.util.PCG32RandomSource; import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource;
@Mixin(Level.class) @Mixin(Level.class)
public abstract class LevelMixin implements IMatteryLevel { public abstract class LevelMixin implements IMatteryLevel {
public final RandomSource otm_random = new PCG32RandomSource(); public final RandomSource otm_random = new GJRAND64RandomSource();
@Override @Override
public @NotNull RandomSource getOtmRandom() { public @NotNull RandomSource getOtmRandom() {

View File

@ -7,6 +7,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder
import net.minecraft.client.server.IntegratedServer import net.minecraft.client.server.IntegratedServer
import net.minecraft.core.HolderLookup import net.minecraft.core.HolderLookup
import net.minecraft.server.MinecraftServer import net.minecraft.server.MinecraftServer
import net.minecraft.util.RandomSource
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.neoforged.api.distmarker.Dist import net.neoforged.api.distmarker.Dist
import net.neoforged.fml.loading.FMLLoader import net.neoforged.fml.loading.FMLLoader
@ -20,6 +21,7 @@ import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.collect.WeakHashSet import ru.dbotthepony.mc.otm.core.collect.WeakHashSet
import ru.dbotthepony.mc.otm.core.util.AtomicallyInvalidatedLazy import ru.dbotthepony.mc.otm.core.util.AtomicallyInvalidatedLazy
import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource
import ru.dbotthepony.mc.otm.core.util.IConditionalTickable import ru.dbotthepony.mc.otm.core.util.IConditionalTickable
import ru.dbotthepony.mc.otm.core.util.ITickable import ru.dbotthepony.mc.otm.core.util.ITickable
import ru.dbotthepony.mc.otm.core.util.TickList import ru.dbotthepony.mc.otm.core.util.TickList
@ -28,6 +30,10 @@ import java.lang.ref.Cleaner
import java.util.* import java.util.*
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
private val threadLocalRandom = ThreadLocal.withInitial { GJRAND64RandomSource() }
internal val THREAD_LOCAL_RANDOM: RandomSource
get() = threadLocalRandom.get()
private val preServerTick = TickList() private val preServerTick = TickList()
private val postServerTick = TickList() private val postServerTick = TickList()
private val preWorldTick = WeakHashMap<Level, TickList>() private val preWorldTick = WeakHashMap<Level, TickList>()

View File

@ -1,7 +1,13 @@
package ru.dbotthepony.mc.otm.capability.matter package ru.dbotthepony.mc.otm.capability.matter
import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.Item.TooltipContext
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.kommons.math.RGBAColor
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import java.util.* import java.util.*
import java.util.function.Predicate import java.util.function.Predicate
import java.util.stream.Collectors import java.util.stream.Collectors
@ -72,3 +78,19 @@ fun IPatternStorage.getBarWidth(): Int {
fun IPatternStorage.getBarColor(): Int { fun IPatternStorage.getBarColor(): Int {
return RGBAColor.LOW_PATTERNS.linearInterpolation((storedPatterns / patternCapacity).toFloat(), RGBAColor.FULL_PATTERNS).toBGR() return RGBAColor.LOW_PATTERNS.linearInterpolation((storedPatterns / patternCapacity).toFloat(), RGBAColor.FULL_PATTERNS).toBGR()
} }
fun IPatternStorage.gatherTooltip(
context: TooltipContext,
components: MutableList<Component>,
tooltipType: TooltipFlag
) {
for (state in patterns) {
components.add(
TranslatableComponent(
"otm.item.pattern.line",
state.item.getName(ItemStack(state.item, 1)),
String.format("%.2f", state.researchPercent * 100.0)
).withStyle(ChatFormatting.AQUA)
)
}
}

View File

@ -76,4 +76,12 @@ object ServerConfig : AbstractConfig("misc") {
builder.pop() builder.pop()
} }
} }
val WITHER_SKELETON_HELMET_CHANCE: Double by builder
.comment("Chance of Wither Skeleton spawning with Netherite Helmet AND Withered Steel sword")
.defineInRange("WITHER_SKELETON_HELMET_CHANCE", 0.1, 0.0, 1.0)
val WITHER_SKELETON_SWORD_CHANCE: Double by builder
.comment("Chance of Wither Skeleton spawning with Withered Steel sword")
.defineInRange("WITHER_SKELETON_HELMET_CHANCE", 0.24, 0.0, 1.0)
} }

View File

@ -39,9 +39,9 @@ class UpgradeContainer(
} }
override val speedBonus: Double override val speedBonus: Double
get() = iterator().map { (it.getCapability(MatteryCapability.UPGRADE)?.speedBonus ?: 0.0) * it.count }.reduce(0.0) { a, b -> a + b } get() = if (isEmpty) 0.0 else iterator().map { (it.getCapability(MatteryCapability.UPGRADE)?.speedBonus ?: 0.0) * it.count }.reduce(0.0) { a, b -> a + b }
override val processingItems: Int override val processingItems: Int
get() = iterator().map { (it.getCapability(MatteryCapability.UPGRADE)?.processingItems ?: 0).coerceAtLeast(0) * it.count }.reduce(0) { a, b -> a + b } get() = if (isEmpty) 0 else iterator().map { (it.getCapability(MatteryCapability.UPGRADE)?.processingItems ?: 0).coerceAtLeast(0) * it.count }.reduce(0) { a, b -> a + b }
override val energyStorageFlat: Decimal override val energyStorageFlat: Decimal
get() = positiveDecimals(IMatteryUpgrade::energyStorageFlat, Decimal::plus) get() = positiveDecimals(IMatteryUpgrade::energyStorageFlat, Decimal::plus)
override val energyStorage: Decimal override val energyStorage: Decimal
@ -53,7 +53,7 @@ class UpgradeContainer(
override val energyConsumed: Decimal override val energyConsumed: Decimal
get() = anyDecimals(IMatteryUpgrade::energyConsumed, Decimal::plus) get() = anyDecimals(IMatteryUpgrade::energyConsumed, Decimal::plus)
override val failureMultiplier: Double override val failureMultiplier: Double
get() = iterator().map { (it.getCapability(MatteryCapability.UPGRADE)?.failureMultiplier ?: 1.0).coerceAtLeast(0.0).pow(it.count.toDouble()) }.reduce(1.0) { a, b -> a * b } get() = if (isEmpty) 1.0 else iterator().map { (it.getCapability(MatteryCapability.UPGRADE)?.failureMultiplier ?: 1.0).coerceAtLeast(0.0).pow(it.count.toDouble()) }.reduce(1.0) { a, b -> a * b }
override val energyThroughputFlat: Decimal override val energyThroughputFlat: Decimal
get() = positiveDecimals(IMatteryUpgrade::energyThroughputFlat, Decimal::plus) get() = positiveDecimals(IMatteryUpgrade::energyThroughputFlat, Decimal::plus)
override val energyThroughput: Decimal override val energyThroughput: Decimal
@ -62,24 +62,24 @@ class UpgradeContainer(
fun transform(values: EnergyBalanceValues): EnergyBalanceValues { fun transform(values: EnergyBalanceValues): EnergyBalanceValues {
return object : EnergyBalanceValues { return object : EnergyBalanceValues {
override val energyCapacity: Decimal override val energyCapacity: Decimal
get() = values.energyCapacity * (energyStorage + Decimal.ONE) + energyStorageFlat get() = if (isEmpty) values.energyCapacity else values.energyCapacity * (energyStorage + Decimal.ONE) + energyStorageFlat
override val energyThroughput: Decimal override val energyThroughput: Decimal
get() = values.energyThroughput * (this@UpgradeContainer.energyThroughput + Decimal.ONE) + energyThroughputFlat get() = if (isEmpty) values.energyThroughput else values.energyThroughput * (this@UpgradeContainer.energyThroughput + Decimal.ONE) + energyThroughputFlat
} }
} }
fun transform(values: VerboseEnergyBalanceValues): VerboseEnergyBalanceValues { fun transform(values: VerboseEnergyBalanceValues): VerboseEnergyBalanceValues {
return object : VerboseEnergyBalanceValues { return object : VerboseEnergyBalanceValues {
override val energyCapacity: Decimal override val energyCapacity: Decimal
get() = values.energyCapacity * (energyStorage + Decimal.ONE) + energyStorageFlat get() = if (isEmpty) values.energyCapacity else values.energyCapacity * (energyStorage + Decimal.ONE) + energyStorageFlat
override val maxEnergyReceive: Decimal override val maxEnergyReceive: Decimal
get() = values.maxEnergyReceive * (energyThroughput + Decimal.ONE) + energyThroughputFlat get() = if (isEmpty) values.maxEnergyReceive else values.maxEnergyReceive * (energyThroughput + Decimal.ONE) + energyThroughputFlat
override val maxEnergyExtract: Decimal override val maxEnergyExtract: Decimal
get() = values.maxEnergyExtract * (energyThroughput + Decimal.ONE) + energyThroughputFlat get() =if (isEmpty) values.maxEnergyExtract else values.maxEnergyExtract * (energyThroughput + Decimal.ONE) + energyThroughputFlat
} }
} }
fun matterCapacity(value: () -> Decimal): () -> Decimal { fun matterCapacity(value: () -> Decimal): () -> Decimal {
return { value.invoke() * (matterStorage + Decimal.ONE) + matterStorageFlat } return { if (isEmpty) value.invoke() else value.invoke() * (matterStorage + Decimal.ONE) + matterStorageFlat }
} }
} }

View File

@ -627,6 +627,10 @@ infix fun FluidStack.isNotSameAs(other: FluidStack): Boolean {
data class DoublePair(val first: Double, val second: Double) data class DoublePair(val first: Double, val second: Double)
fun RandomSource.nextUUID(): UUID {
return UUID(nextLong(), nextLong())
}
// normal distribution via Marsaglia polar method // normal distribution via Marsaglia polar method
fun RandomGenerator.nextNormalDoubles(stddev: Double, mean: Double): DoublePair { fun RandomGenerator.nextNormalDoubles(stddev: Double, mean: Double): DoublePair {
var rand1: Double var rand1: Double

View File

@ -5,7 +5,7 @@ import net.minecraft.util.RandomSource
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
import net.minecraft.world.level.levelgen.PositionalRandomFactory import net.minecraft.world.level.levelgen.PositionalRandomFactory
import net.minecraft.world.level.levelgen.RandomSupport import net.minecraft.world.level.levelgen.RandomSupport
import ru.dbotthepony.kommons.random.LCG64Random import ru.dbotthepony.kommons.random.PCG32Random
import java.lang.StringBuilder import java.lang.StringBuilder
import java.util.random.RandomGenerator import java.util.random.RandomGenerator
@ -23,7 +23,7 @@ class CMWCRandom(seed: Long = RandomSupport.generateUniqueSeed()) : RandomGenera
} }
override fun setSeed(seed: Long) { override fun setSeed(seed: Long) {
val rng = LCG64Random(seed) val rng = PCG32Random(seed)
// init state with regular LCG produced values // init state with regular LCG produced values
for (i in 1 until state.size) { for (i in 1 until state.size) {
@ -92,7 +92,7 @@ class CMWCRandom(seed: Long = RandomSupport.generateUniqueSeed()) : RandomGenera
return Positional(nextLong()) return Positional(nextLong())
} }
class Positional(val seed: Long) : PositionalRandomFactory { class Positional(private val seed: Long) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource { override fun at(x: Int, y: Int, z: Int): RandomSource {
return CMWCRandom(Mth.getSeed(x, y, z).xor(seed)) return CMWCRandom(Mth.getSeed(x, y, z).xor(seed))
} }

View File

@ -0,0 +1,57 @@
package ru.dbotthepony.mc.otm.core.util
import net.minecraft.util.Mth
import net.minecraft.util.RandomSource
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
import net.minecraft.world.level.levelgen.PositionalRandomFactory
import net.minecraft.world.level.levelgen.RandomSupport
import ru.dbotthepony.kommons.random.GJRAND64Random
import java.lang.StringBuilder
class GJRAND64RandomSource : GJRAND64Random, IRandomSourceGenerator {
private val gaussian = MarsagliaPolarGaussian(this)
constructor() : super(RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed())
constructor(seed: Long) : super(seed)
constructor(seed0: Long, seed1: Long) : super(seed0, seed1)
override fun nextInt(): Int {
return nextLong().ushr(32).toInt()
}
override fun nextGaussian(): Double {
return gaussian.nextGaussian()
}
override fun fork(): RandomSource {
return GJRAND64RandomSource(nextLong(), nextLong())
}
override fun forkPositional(): PositionalRandomFactory {
return Positional(nextLong(), nextLong())
}
override fun setSeed(seed: Long) {
reinitialize(seed)
gaussian.reset()
}
class Positional(private val seed0: Long, private val seed1: Long) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource {
val seed = Mth.getSeed(x, y, z)
return GJRAND64RandomSource(seed0.xor(seed.rotateLeft(32)), seed1.xor(seed))
}
override fun fromHashOf(name: String): RandomSource {
return GJRAND64RandomSource(name.hashCode().toLong().xor(seed0), seed1)
}
override fun fromSeed(seed: Long): RandomSource {
return GJRAND64RandomSource(seed)
}
override fun parityConfigString(builder: StringBuilder) {
throw UnsupportedOperationException()
}
}
}

View File

@ -39,7 +39,7 @@ class LCG64RandomSource(seed: Long = RandomSupport.generateUniqueSeed()) : LCG64
return Positional(nextLong()) return Positional(nextLong())
} }
class Positional(val seed: Long) : PositionalRandomFactory { class Positional(private val seed: Long) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource { override fun at(x: Int, y: Int, z: Int): RandomSource {
return LCG64RandomSource(Mth.getSeed(x, y, z).xor(seed)) return LCG64RandomSource(Mth.getSeed(x, y, z).xor(seed))
} }

View File

@ -2,11 +2,9 @@ package ru.dbotthepony.mc.otm.core.util
import net.minecraft.util.Mth import net.minecraft.util.Mth
import net.minecraft.util.RandomSource import net.minecraft.util.RandomSource
import net.minecraft.world.level.levelgen.LegacyRandomSource
import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian
import net.minecraft.world.level.levelgen.PositionalRandomFactory import net.minecraft.world.level.levelgen.PositionalRandomFactory
import net.minecraft.world.level.levelgen.RandomSupport import net.minecraft.world.level.levelgen.RandomSupport
import ru.dbotthepony.kommons.random.LCG64Random
import ru.dbotthepony.kommons.random.PCG32Random import ru.dbotthepony.kommons.random.PCG32Random
import java.lang.StringBuilder import java.lang.StringBuilder
@ -33,7 +31,7 @@ class PCG32RandomSource(seed: Long = RandomSupport.generateUniqueSeed()) : PCG32
return Positional(nextLong()) return Positional(nextLong())
} }
class Positional(val seed: Long) : PositionalRandomFactory { class Positional(private val seed: Long) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource { override fun at(x: Int, y: Int, z: Int): RandomSource {
return PCG32RandomSource(Mth.getSeed(x, y, z).xor(seed)) return PCG32RandomSource(Mth.getSeed(x, y, z).xor(seed))
} }

View File

@ -55,10 +55,10 @@ class Xoshiro256Random : Xoshiro256StarStarRandom, IRandomSourceGenerator {
} }
class Positional( class Positional(
val s0: Long, private val s0: Long,
val s1: Long, private val s1: Long,
val s2: Long, private val s2: Long,
val s3: Long, private val s3: Long,
) : PositionalRandomFactory { ) : PositionalRandomFactory {
override fun at(x: Int, y: Int, z: Int): RandomSource { override fun at(x: Int, y: Int, z: Int): RandomSource {
val rng = LCG64RandomSource(Mth.getSeed(x, y, z)) val rng = LCG64RandomSource(Mth.getSeed(x, y, z))

View File

@ -21,8 +21,11 @@ import net.minecraft.world.entity.monster.Zombie
import net.minecraft.world.entity.npc.Villager import net.minecraft.world.entity.npc.Villager
import net.minecraft.world.entity.player.Player import net.minecraft.world.entity.player.Player
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.registry.game.MEntityTypes
class BreadMonster(type: EntityType<BreadMonster>, level: Level) : Monster(type, level) { class BreadMonster(type: EntityType<BreadMonster>, level: Level) : Monster(type, level) {
constructor(level: Level) : this(MEntityTypes.BREAD_MONSTER, level)
val idleState = AnimationState() val idleState = AnimationState()
init { init {

View File

@ -6,24 +6,28 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.neoforged.bus.api.SubscribeEvent import net.neoforged.bus.api.SubscribeEvent
import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent
import ru.dbotthepony.mc.otm.config.ServerConfig
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.registry.game.MItems import ru.dbotthepony.mc.otm.registry.game.MItems
object WitheredSkeletonSpawnHandler { object WitheredSkeletonSpawnHandler {
@SubscribeEvent @SubscribeEvent
fun onEntityJoin(event: EntityJoinLevelEvent) { fun onEntityJoin(event: EntityJoinLevelEvent) {
val entity = event.entity val entity = event.entity
if (entity is WitherSkeleton){
val giveHelmet = entity.random.nextFloat() < 0.1f if (entity is WitherSkeleton) {
val giveSword = entity.random.nextFloat() < 0.24f val giveHelmet = event.level.otmRandom.nextFloat() < ServerConfig.WITHER_SKELETON_HELMET_CHANCE
val giveSword = event.level.otmRandom.nextFloat() < ServerConfig.WITHER_SKELETON_SWORD_CHANCE
if (giveHelmet) { if (giveHelmet) {
entity.setItemSlot(EquipmentSlot.HEAD, ItemStack(Items.NETHERITE_HELMET)) if (!entity.hasItemInSlot(EquipmentSlot.HEAD))
entity.setItemSlot(EquipmentSlot.MAINHAND, ItemStack(MItems.WITHERED_STEEL_SWORD)) entity.setItemSlot(EquipmentSlot.HEAD, ItemStack(Items.NETHERITE_HELMET))
} else if (giveSword) { }
entity.setItemSlot(EquipmentSlot.MAINHAND, ItemStack(MItems.WITHERED_STEEL_SWORD))
if (giveSword || giveHelmet) {
if (!entity.hasItemInSlot(EquipmentSlot.MAINHAND) || entity.getItemBySlot(EquipmentSlot.MAINHAND).item == Items.STONE_SWORD)
entity.setItemSlot(EquipmentSlot.MAINHAND, ItemStack(MItems.WITHERED_STEEL_SWORD))
} }
} }
} }

View File

@ -24,6 +24,7 @@ import net.neoforged.neoforge.event.tick.ServerTickEvent
import net.neoforged.neoforge.network.PacketDistributor import net.neoforged.neoforge.network.PacketDistributor
import net.neoforged.neoforge.network.handling.IPayloadContext import net.neoforged.neoforge.network.handling.IPayloadContext
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.THREAD_LOCAL_RANDOM
import ru.dbotthepony.mc.otm.capability.FlowDirection import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.trackedItems import ru.dbotthepony.mc.otm.capability.trackedItems
@ -42,6 +43,7 @@ import ru.dbotthepony.mc.otm.core.math.readDecimal
import ru.dbotthepony.mc.otm.core.math.set import ru.dbotthepony.mc.otm.core.math.set
import ru.dbotthepony.mc.otm.core.math.writeDecimal import ru.dbotthepony.mc.otm.core.math.writeDecimal
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.nextUUID
import ru.dbotthepony.mc.otm.core.util.formatPower import ru.dbotthepony.mc.otm.core.util.formatPower
import ru.dbotthepony.mc.otm.isClientThread import ru.dbotthepony.mc.otm.isClientThread
import ru.dbotthepony.mc.otm.isServerThread import ru.dbotthepony.mc.otm.isServerThread
@ -82,7 +84,7 @@ class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanc
} }
} }
class UnboundValues(override val uuid: UUID = UUID.randomUUID()) : IValues { class UnboundValues(override val uuid: UUID = THREAD_LOCAL_RANDOM.nextUUID()) : IValues {
override var energy: Decimal = Decimal.ZERO override var energy: Decimal = Decimal.ZERO
override var passed: Decimal = Decimal.ZERO override var passed: Decimal = Decimal.ZERO
override var received: Decimal = Decimal.ZERO override var received: Decimal = Decimal.ZERO
@ -125,7 +127,7 @@ class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanc
} }
fun values(): Values { fun values(): Values {
return values(UUID.randomUUID()) return values(THREAD_LOCAL_RANDOM.nextUUID())
} }
override fun save(nbt: CompoundTag, registry: HolderLookup.Provider): CompoundTag { override fun save(nbt: CompoundTag, registry: HolderLookup.Provider): CompoundTag {
@ -160,7 +162,7 @@ class QuantumBatteryItem(val savedataID: String, val balanceValues: EnergyBalanc
fun updateValues() { fun updateValues() {
if (!values.isServer && isServerThread()) { if (!values.isServer && isServerThread()) {
values = serverData.values(stack[MDataComponentTypes.QUANTUM_LINK_ID] ?: UUID.randomUUID().also { stack[MDataComponentTypes.QUANTUM_LINK_ID] = it }) values = serverData.values(stack[MDataComponentTypes.QUANTUM_LINK_ID] ?: THREAD_LOCAL_RANDOM.nextUUID().also { stack[MDataComponentTypes.QUANTUM_LINK_ID] = it })
} else if (isClientThread()) { } else if (isClientThread()) {
val id = stack[MDataComponentTypes.QUANTUM_LINK_ID] ?: return val id = stack[MDataComponentTypes.QUANTUM_LINK_ID] ?: return

View File

@ -1,25 +0,0 @@
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()

View File

@ -0,0 +1,52 @@
package ru.dbotthepony.mc.otm.item.consumables
import net.minecraft.ChatFormatting
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.otmRandom
import ru.dbotthepony.mc.otm.core.position
import ru.dbotthepony.mc.otm.entity.BreadMonster
import ru.dbotthepony.mc.otm.item.MatteryItem
import ru.dbotthepony.mc.otm.registry.game.MDataComponentTypes
class ImperfectBreadItem(properties: Properties) : MatteryItem(properties) {
override fun finishUsingItem(stack: ItemStack, level: Level, entity: LivingEntity): ItemStack {
if (entity is ServerPlayer) {
entity.addEffect(MobEffectInstance(MobEffects.POISON, 80, 2))
}
return super.finishUsingItem(stack, level, entity)
}
init {
tooltips.addNormal { itemStack, context, acceptor ->
if (itemStack[MDataComponentTypes.INERT] == true) {
acceptor(TranslatableComponent("otm.misc.inert").withStyle(ChatFormatting.DARK_GRAY))
}
}
}
override fun onEntityItemUpdate(stack: ItemStack, entity: ItemEntity): Boolean {
if (stack[MDataComponentTypes.INERT] == true)
return super.onEntityItemUpdate(stack, entity)
// roll multiple times so multiple bread monsters can spawn on tick
// and also chance be less biased
for (i in 0 until stack.count.coerceAtMost(16)) {
if (entity.level().otmRandom.nextFloat() < 0.001f) {
val ent = BreadMonster(entity.level())
ent.position = entity.position
entity.level().addFreshEntity(ent)
stack.shrink(1)
}
}
return super.onEntityItemUpdate(stack, entity)
}
}

View File

@ -0,0 +1,84 @@
package ru.dbotthepony.mc.otm.item.matter
import com.google.common.collect.ImmutableList
import net.minecraft.network.chat.Component
import net.minecraft.util.RandomSource
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.level.storage.loot.functions.LootItemConditionalFunction
import net.minecraft.world.level.storage.loot.functions.SetComponentsFunction
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage
import ru.dbotthepony.mc.otm.capability.matter.PatternInsertFailure
import ru.dbotthepony.mc.otm.capability.matter.PatternInsertStatus
import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.capability.matter.gatherTooltip
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.stream
import ru.dbotthepony.mc.otm.item.MatteryItem
import ru.dbotthepony.mc.otm.registry.CapabilitiesRegisterListener
import ru.dbotthepony.mc.otm.registry.game.MDataComponentTypes
import java.util.*
import java.util.stream.Stream
class GoldDiskItem(parameters: Properties) : MatteryItem(parameters), CapabilitiesRegisterListener {
override fun registerCapabilities(event: RegisterCapabilitiesEvent) {
event.registerItem(MatteryCapability.PATTERN_ITEM, { o, _ -> ItemPatternStorageCapability(o) }, this)
}
override fun getName(stack: ItemStack): Component {
val data = stack[MDataComponentTypes.PATTERNS]
if (data == null || data.size > 1) {
return super.getName(stack)
} else if (data.size == 0 || data[0].item == Items.AIR) {
return TranslatableComponent("$descriptionId.single_item", TextComponent("???"))
} else {
return TranslatableComponent("$descriptionId.single_item", data[0].item.getName(ItemStack(data[0].item)))
}
}
override fun appendHoverText(
itemStack: ItemStack,
context: TooltipContext,
components: MutableList<Component>,
tooltipType: TooltipFlag
) {
itemStack.getCapability(MatteryCapability.PATTERN_ITEM)?.gatherTooltip(context, components, tooltipType)
super.appendHoverText(itemStack, context, components, tooltipType)
}
class ItemPatternStorageCapability(val stack: ItemStack) : IPatternStorage {
override val patternCapacity: Int get() {
return stack[MDataComponentTypes.PATTERNS]?.size ?: 0
}
override val storedPatterns: Int get() {
return patternCapacity
}
override val patterns: Stream<PatternState> get() {
return stack[MDataComponentTypes.PATTERNS]?.stream() ?: Stream.empty()
}
override fun insertPattern(pattern: PatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus {
return PatternInsertFailure
}
}
companion object {
fun patterns(random: RandomSource, vararg items: Item): LootItemConditionalFunction.Builder<*> {
return SetComponentsFunction.setComponent(
MDataComponentTypes.PATTERNS,
items
.stream()
.map { PatternState(UUID(random.nextLong(), random.nextLong()), it, 1.0) }
.collect(ImmutableList.toImmutableList()))
}
}
}

View File

@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.item.matter
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity import net.minecraft.world.item.Rarity
import net.minecraft.world.item.TooltipFlag import net.minecraft.world.item.TooltipFlag
@ -15,23 +14,20 @@ import ru.dbotthepony.mc.otm.capability.matter.PatternInsertInserted
import ru.dbotthepony.mc.otm.capability.matter.PatternInsertStatus import ru.dbotthepony.mc.otm.capability.matter.PatternInsertStatus
import ru.dbotthepony.mc.otm.capability.matter.PatternInsertUpdated import ru.dbotthepony.mc.otm.capability.matter.PatternInsertUpdated
import ru.dbotthepony.mc.otm.capability.matter.PatternState import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.capability.matter.gatherTooltip
import ru.dbotthepony.mc.otm.capability.matter.getBarColor import ru.dbotthepony.mc.otm.capability.matter.getBarColor
import ru.dbotthepony.mc.otm.capability.matter.getBarWidth import ru.dbotthepony.mc.otm.capability.matter.getBarWidth
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.item.MatteryItem
import ru.dbotthepony.mc.otm.registry.CapabilitiesRegisterListener import ru.dbotthepony.mc.otm.registry.CapabilitiesRegisterListener
import ru.dbotthepony.mc.otm.registry.game.MDataComponentTypes import ru.dbotthepony.mc.otm.registry.game.MDataComponentTypes
import java.util.stream.Stream import java.util.stream.Stream
class PatternStorageItem : Item, CapabilitiesRegisterListener { class PatternStorageItem : MatteryItem, CapabilitiesRegisterListener {
private val _capacity: () -> Int private val _capacity: () -> Int
val capacity get() = _capacity.invoke() val capacity get() = _capacity.invoke()
var isCreative: Boolean var isCreative: Boolean
constructor(capacity: Int) : super(Properties().stacksTo(1)) {
_capacity = { capacity }
isCreative = false
}
constructor(capacity: () -> Int) : super(Properties().stacksTo(1)) { constructor(capacity: () -> Int) : super(Properties().stacksTo(1)) {
_capacity = capacity _capacity = capacity
isCreative = false isCreative = false
@ -47,29 +43,21 @@ class PatternStorageItem : Item, CapabilitiesRegisterListener {
} }
override fun appendHoverText( override fun appendHoverText(
p_41421_: ItemStack, itemStack: ItemStack,
p_339594_: TooltipContext, context: TooltipContext,
list: MutableList<Component>, components: MutableList<Component>,
p_41424_: TooltipFlag tooltipType: TooltipFlag
) { ) {
p_41421_.getCapability(MatteryCapability.PATTERN_ITEM)?.let { itemStack.getCapability(MatteryCapability.PATTERN_ITEM)?.let {
if (isCreative) if (isCreative)
list.add(TranslatableComponent("otm.item.pattern.infinite.stored", it.storedPatterns).withStyle(ChatFormatting.GRAY)) components.add(TranslatableComponent("otm.item.pattern.infinite.stored", it.storedPatterns).withStyle(ChatFormatting.GRAY))
else else
list.add(TranslatableComponent("otm.item.pattern.stored", it.storedPatterns, it.patternCapacity).withStyle(ChatFormatting.GRAY)) components.add(TranslatableComponent("otm.item.pattern.stored", it.storedPatterns, it.patternCapacity).withStyle(ChatFormatting.GRAY))
for (state in it.patterns) { it.gatherTooltip(context, components, tooltipType)
list.add(
TranslatableComponent(
"otm.item.pattern.line",
state.item.getName(ItemStack(state.item, 1)),
String.format("%.2f", state.researchPercent * 100.0)
).withStyle(ChatFormatting.AQUA)
)
}
} }
super.appendHoverText(p_41421_, p_339594_, list, p_41424_) super.appendHoverText(itemStack, context, components, tooltipType)
} }
override fun isBarVisible(p_150899_: ItemStack): Boolean { override fun isBarVisible(p_150899_: ItemStack): Boolean {

View File

@ -13,23 +13,19 @@ import net.minecraft.world.item.Tiers
import net.minecraft.world.item.component.ItemAttributeModifiers import net.minecraft.world.item.component.ItemAttributeModifiers
import ru.dbotthepony.mc.otm.registry.game.MItems import ru.dbotthepony.mc.otm.registry.game.MItems
class WitheredSteelSwordItem(properties: Item.Properties) : SwordItem(Tiers.IRON, properties){ class WitheredSteelSwordItem(properties: Properties) : SwordItem(Tiers.IRON, properties) {
private val attributes: ItemAttributeModifiers private val attributes: ItemAttributeModifiers
init { init {
var builder = ItemAttributeModifiers.builder() val builder = ItemAttributeModifiers.builder()
builder.add(Attributes.ATTACK_DAMAGE, AttributeModifier(BASE_ATTACK_DAMAGE_ID, 4.5, AttributeModifier.Operation.ADD_VALUE), EquipmentSlotGroup.MAINHAND) builder.add(Attributes.ATTACK_DAMAGE, AttributeModifier(BASE_ATTACK_DAMAGE_ID, 4.5, AttributeModifier.Operation.ADD_VALUE), EquipmentSlotGroup.MAINHAND)
builder.add(Attributes.ATTACK_SPEED, AttributeModifier(BASE_ATTACK_SPEED_ID, -2.4, AttributeModifier.Operation.ADD_VALUE), EquipmentSlotGroup.MAINHAND) builder.add(Attributes.ATTACK_SPEED, AttributeModifier(BASE_ATTACK_SPEED_ID, -2.4, AttributeModifier.Operation.ADD_VALUE), EquipmentSlotGroup.MAINHAND)
attributes = builder.build() attributes = builder.build()
} }
override fun getMaxDamage(stack: ItemStack): Int { override fun isEnchantable(stack: ItemStack): Boolean {
return 420 return stack.count == 1
}
override fun isEnchantable(p_41456_: ItemStack): Boolean {
return p_41456_.count == 1
} }
override fun getEnchantmentValue(stack: ItemStack): Int { override fun getEnchantmentValue(stack: ItemStack): Int {
@ -41,13 +37,12 @@ class WitheredSteelSwordItem(properties: Item.Properties) : SwordItem(Tiers.IRON
} }
override fun hurtEnemy(stack: ItemStack, target: LivingEntity, attacker: LivingEntity): Boolean { override fun hurtEnemy(stack: ItemStack, target: LivingEntity, attacker: LivingEntity): Boolean {
target.addEffect(MobEffectInstance(MobEffects.WITHER, 100, 0)) val status = super.hurtEnemy(stack, target, attacker)
return super.hurtEnemy(stack, target, attacker) if (status) target.addEffect(MobEffectInstance(MobEffects.WITHER, 100, 0), attacker)
return status
} }
override fun getDefaultAttributeModifiers(stack: ItemStack): ItemAttributeModifiers { override fun getDefaultAttributeModifiers(stack: ItemStack): ItemAttributeModifiers {
return attributes return attributes
} }
} }

View File

@ -287,6 +287,9 @@ private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) {
accept(MItems.NUTRIENT_PASTE) accept(MItems.NUTRIENT_PASTE)
accept(MItems.IMPERFECT_BREAD) accept(MItems.IMPERFECT_BREAD)
accept(ItemStack(MItems.IMPERFECT_BREAD).also {
it[MDataComponentTypes.INERT] = true
})
// exo // exo
accept(MItems.EXOPACK_PROBE) accept(MItems.EXOPACK_PROBE)

View File

@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import net.minecraft.core.UUIDUtil import net.minecraft.core.UUIDUtil
import net.minecraft.core.component.DataComponentType import net.minecraft.core.component.DataComponentType
import net.minecraft.core.component.DataComponents
import net.minecraft.core.registries.BuiltInRegistries import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.network.RegistryFriendlyByteBuf import net.minecraft.network.RegistryFriendlyByteBuf
@ -69,6 +70,8 @@ object MDataComponentTypes {
val MAX_BATTERY_OUTPUT: DataComponentType<Decimal> by registry.register("max_battery_output") { DecimalComponent() } val MAX_BATTERY_OUTPUT: DataComponentType<Decimal> by registry.register("max_battery_output") { DecimalComponent() }
val MATTER_LEVEL: DataComponentType<Decimal> by registry.register("matter_level") { DecimalComponent() } val MATTER_LEVEL: DataComponentType<Decimal> by registry.register("matter_level") { DecimalComponent() }
val INERT: DataComponentType<Boolean> by registry.register("inert") { DataComponentType.builder<Boolean>().persistent(Codec.BOOL).build() }
val EXOPACK_SLOT_COUNT: DataComponentType<Int> by registry.register("exopack_slot_count") { DataComponentType.builder<Int>().persistent(Codec.INT).networkSynchronized(StreamCodecs.INT).build() } val EXOPACK_SLOT_COUNT: DataComponentType<Int> by registry.register("exopack_slot_count") { DataComponentType.builder<Int>().persistent(Codec.INT).networkSynchronized(StreamCodecs.INT).build() }
val EXOPACK_UPGRADE_ID: DataComponentType<UUID> by registry.register("exopack_upgrade_id") { uuid() } val EXOPACK_UPGRADE_ID: DataComponentType<UUID> by registry.register("exopack_upgrade_id") { uuid() }
val QUANTUM_LINK_ID: DataComponentType<UUID> by registry.register("quantum_link_id") { uuid() } val QUANTUM_LINK_ID: DataComponentType<UUID> by registry.register("quantum_link_id") { uuid() }

View File

@ -26,18 +26,12 @@ import net.minecraft.world.item.Tiers
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.Block
import net.neoforged.bus.api.IEventBus import net.neoforged.bus.api.IEventBus
import net.neoforged.neoforge.common.DeferredSpawnEggItem
import net.neoforged.neoforge.common.SimpleTier import net.neoforged.neoforge.common.SimpleTier
import ru.dbotthepony.mc.otm.block.MatteryBlock
import ru.dbotthepony.mc.otm.block.addSimpleDescription
import ru.dbotthepony.mc.otm.block.tech.FlywheelBatteryBlock
import ru.dbotthepony.mc.otm.capability.ITieredUpgradeSet import ru.dbotthepony.mc.otm.capability.ITieredUpgradeSet
import ru.dbotthepony.mc.otm.capability.MatteryPlayer import ru.dbotthepony.mc.otm.capability.MatteryPlayer
import ru.dbotthepony.mc.otm.capability.UpgradeType import ru.dbotthepony.mc.otm.capability.UpgradeType
import ru.dbotthepony.mc.otm.config.CablesConfig import ru.dbotthepony.mc.otm.config.CablesConfig
import ru.dbotthepony.mc.otm.config.ItemsConfig import ru.dbotthepony.mc.otm.config.ItemsConfig
import ru.dbotthepony.mc.otm.core.addAll
import ru.dbotthepony.mc.otm.core.asSupplierArray
import ru.dbotthepony.mc.otm.core.collect.SupplierList import ru.dbotthepony.mc.otm.core.collect.SupplierList
import ru.dbotthepony.mc.otm.core.collect.SupplierMap import ru.dbotthepony.mc.otm.core.collect.SupplierMap
import ru.dbotthepony.mc.otm.core.math.Decimal import ru.dbotthepony.mc.otm.core.math.Decimal
@ -66,6 +60,7 @@ import ru.dbotthepony.mc.otm.item.exopack.ExopackSlotUpgradeItem
import ru.dbotthepony.mc.otm.item.exopack.ExopackUpgradeItem import ru.dbotthepony.mc.otm.item.exopack.ExopackUpgradeItem
import ru.dbotthepony.mc.otm.item.exopack.ProceduralExopackSlotUpgradeItem import ru.dbotthepony.mc.otm.item.exopack.ProceduralExopackSlotUpgradeItem
import ru.dbotthepony.mc.otm.item.matter.CreativePatternItem import ru.dbotthepony.mc.otm.item.matter.CreativePatternItem
import ru.dbotthepony.mc.otm.item.matter.GoldDiskItem
import ru.dbotthepony.mc.otm.item.matter.MatterCapacitorItem import ru.dbotthepony.mc.otm.item.matter.MatterCapacitorItem
import ru.dbotthepony.mc.otm.item.matter.MatterDustItem import ru.dbotthepony.mc.otm.item.matter.MatterDustItem
import ru.dbotthepony.mc.otm.item.matter.PatternStorageItem import ru.dbotthepony.mc.otm.item.matter.PatternStorageItem
@ -429,7 +424,7 @@ object MItems {
val PILL_HEAL: Item by registry.register(MNames.PILL_HEAL) { HealPillItem() } 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 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 IMPERFECT_BREAD: Item by registry.register(MNames.IMPERFECT_BREAD) { ImperfectBreadItem(Item.Properties().food(FoodProperties.Builder().nutrition(5).saturationModifier(0.6f).build())) }
val PILLS = SupplierList( val PILLS = SupplierList(
MItems::PILL_ANDROID, MItems::PILL_ANDROID,
@ -503,6 +498,8 @@ object MItems {
val PATTERN_DRIVE_CREATIVE: Item by registry.register(MNames.PATTERN_DRIVE_CREATIVE) { PatternStorageItem() } val PATTERN_DRIVE_CREATIVE: Item by registry.register(MNames.PATTERN_DRIVE_CREATIVE) { PatternStorageItem() }
val PATTERN_DRIVE_CREATIVE2: Item by registry.register(MNames.PATTERN_DRIVE_CREATIVE2) { CreativePatternItem() } val PATTERN_DRIVE_CREATIVE2: Item by registry.register(MNames.PATTERN_DRIVE_CREATIVE2) { CreativePatternItem() }
val GOLD_DISK: Item by registry.register("gold_disk") { GoldDiskItem(Properties().stacksTo(16).rarity(Rarity.RARE)) }
val PORTABLE_CONDENSATION_DRIVE: Item by registry.register(MNames.PORTABLE_CONDENSATION_DRIVE) { PortableCondensationDriveItem(4000) } val PORTABLE_CONDENSATION_DRIVE: Item by registry.register(MNames.PORTABLE_CONDENSATION_DRIVE) { PortableCondensationDriveItem(4000) }
val PORTABLE_DENSE_CONDENSATION_DRIVE: Item by registry.register(MNames.PORTABLE_DENSE_CONDENSATION_DRIVE) { PortableCondensationDriveItem(25000) } val PORTABLE_DENSE_CONDENSATION_DRIVE: Item by registry.register(MNames.PORTABLE_DENSE_CONDENSATION_DRIVE) { PortableCondensationDriveItem(25000) }

View File

@ -18,6 +18,7 @@ import net.minecraft.world.level.levelgen.placement.PlacementContext
import net.minecraft.world.level.levelgen.placement.PlacementModifier import net.minecraft.world.level.levelgen.placement.PlacementModifier
import net.minecraft.world.level.levelgen.placement.PlacementModifierType import net.minecraft.world.level.levelgen.placement.PlacementModifierType
import ru.dbotthepony.kommons.util.XXHash64 import ru.dbotthepony.kommons.util.XXHash64
import ru.dbotthepony.mc.otm.core.util.GJRAND64RandomSource
import ru.dbotthepony.mc.otm.core.util.PCG32RandomSource import ru.dbotthepony.mc.otm.core.util.PCG32RandomSource
import ru.dbotthepony.mc.otm.data.codec.minRange import ru.dbotthepony.mc.otm.data.codec.minRange
import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers
@ -89,7 +90,6 @@ class EnormousPlacement(
val bytes = FastByteArrayOutputStream() val bytes = FastByteArrayOutputStream()
val dataStream = DataOutputStream(bytes) val dataStream = DataOutputStream(bytes)
dataStream.writeLong(context.level.seed)
dataStream.writeLong(seedMix) dataStream.writeLong(seedMix)
dataStream.writeInt(pos.x) dataStream.writeInt(pos.x)
dataStream.writeInt(pos.z) dataStream.writeInt(pos.z)
@ -97,7 +97,7 @@ class EnormousPlacement(
val hash = XXHash64() val hash = XXHash64()
hash.update(bytes.array, 0, bytes.length) hash.update(bytes.array, 0, bytes.length)
val random = PCG32RandomSource(hash.digestAsLong()) val random = GJRAND64RandomSource(context.level.seed, hash.digestAsLong())
var stream = Stream.of(BlockPos(pos.minBlockX, 0, pos.minBlockZ)) var stream = Stream.of(BlockPos(pos.minBlockX, 0, pos.minBlockZ))
children.forEach { modifier -> stream = stream.flatMap { modifier.getPositions(context, random, it).sequential() } } children.forEach { modifier -> stream = stream.flatMap { modifier.getPositions(context, random, it).sequential() } }
return GeneratedChunk(stream) return GeneratedChunk(stream)