Android config values, move immune effect list to tags
Clear immune effects before ticking player
This commit is contained in:
parent
57d7c7f908
commit
ca70916331
@ -1,5 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.datagen.tags
|
||||
|
||||
import net.minecraft.world.effect.MobEffects
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.Tiers
|
||||
import ru.dbotthepony.mc.otm.registry.MBlocks
|
||||
@ -97,4 +98,20 @@ fun addTags(tagsProvider: TagsProvider) {
|
||||
tagsProvider.witherImmune.add(
|
||||
MBlocks.BLACK_HOLE,
|
||||
)
|
||||
|
||||
tagsProvider.androidImmuneEffects.add(
|
||||
MobEffects.CONDUIT_POWER,
|
||||
MobEffects.HEAL,
|
||||
// maybe it makes things go haywire idk
|
||||
// MobEffects.HARM,
|
||||
MobEffects.REGENERATION,
|
||||
MobEffects.WATER_BREATHING,
|
||||
MobEffects.POISON,
|
||||
// even skeletons can be withered
|
||||
// MobEffects.WITHER,
|
||||
MobEffects.HEALTH_BOOST,
|
||||
MobEffects.ABSORPTION,
|
||||
MobEffects.SATURATION,
|
||||
MobEffects.DOLPHINS_GRACE,
|
||||
)
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import net.minecraft.world.item.Tiers
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.gameevent.GameEvent
|
||||
import net.minecraftforge.data.event.GatherDataEvent
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.datagen.DataGen
|
||||
import net.minecraft.data.tags.TagsProvider as MinecraftTagsProvider
|
||||
|
||||
@ -57,6 +58,10 @@ class TagsProvider(
|
||||
private val event: GatherDataEvent
|
||||
) {
|
||||
inner class Delegate<T>(registry: Registry<T>) : MinecraftTagsProvider<T>(event.generator, registry, DataGen.MOD_ID, event.existingFileHelper) {
|
||||
init {
|
||||
event.generator.addProvider(true, this)
|
||||
}
|
||||
|
||||
private val tags = HashMap<TagKey<T>, ObjectArraySet<T>>()
|
||||
|
||||
override fun addTags() {
|
||||
@ -165,6 +170,9 @@ class TagsProvider(
|
||||
|
||||
val blocks = Delegate(Registry.BLOCK)
|
||||
val items = Delegate(Registry.ITEM)
|
||||
val mobEffects = Delegate(Registry.MOB_EFFECT)
|
||||
|
||||
val androidImmuneEffects = mobEffects.appender(MatteryPlayerCapability.ANDROID_IMMUNE_EFFECTS)
|
||||
|
||||
val requiresShovel = blocks.appender(BlockTags.MINEABLE_WITH_SHOVEL)
|
||||
val requiresAxe = blocks.appender(BlockTags.MINEABLE_WITH_AXE)
|
||||
@ -216,11 +224,6 @@ class TagsProvider(
|
||||
val gameEvents = Delegate(Registry.GAME_EVENT)
|
||||
val vibrations = gameEvents.appender(GameEventTags.VIBRATIONS)
|
||||
|
||||
init {
|
||||
event.generator.addProvider(true, blocks)
|
||||
event.generator.addProvider(true, items)
|
||||
}
|
||||
|
||||
fun requiresPickaxe(block: Block, tier: Tier? = null): TagsProvider {
|
||||
requiresPickaxe.add(block)
|
||||
|
||||
|
@ -122,8 +122,6 @@ public final class OverdriveThatMatters {
|
||||
EVENT_BUS.addListener(EventPriority.NORMAL, QuantumBatteryItem.Companion::clientDisconnect);
|
||||
EVENT_BUS.addListener(EventPriority.LOWEST, PortableCondensationDriveItem.Companion::onPickupEvent);
|
||||
|
||||
MatteryPlayerCapability.Companion.registerEffects(event);
|
||||
|
||||
MatteryPlayerNetworkChannel.INSTANCE.register();
|
||||
MenuNetworkChannel.INSTANCE.register();
|
||||
WeaponNetworkChannel.INSTANCE.register();
|
||||
|
171
src/main/kotlin/ru/dbotthepony/mc/otm/ObservedConfigList.kt
Normal file
171
src/main/kotlin/ru/dbotthepony/mc/otm/ObservedConfigList.kt
Normal file
@ -0,0 +1,171 @@
|
||||
package ru.dbotthepony.mc.otm
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraftforge.common.ForgeConfigSpec
|
||||
import net.minecraftforge.registries.IForgeRegistry
|
||||
import java.util.LinkedList
|
||||
|
||||
abstract class ObservedConfigList<V : Any>(val parent: ForgeConfigSpec.ConfigValue<MutableList<String>>, private val allowNulls: Boolean = false) : AbstractMutableList<V>(), RandomAccess {
|
||||
private val rawValue: MutableList<String> by parent
|
||||
private val observedValue = LinkedList<String>()
|
||||
private val parsedView: ArrayList<V> = ArrayList()
|
||||
|
||||
protected abstract fun toString(value: V): Pair<String, V>?
|
||||
protected abstract fun fromString(value: String): V?
|
||||
|
||||
private fun load() {
|
||||
parsedView.clear()
|
||||
observedValue.clear()
|
||||
val removeIndexes = IntArrayList()
|
||||
|
||||
for ((i, value) in rawValue.withIndex()) {
|
||||
val parsedValue = fromString(value)
|
||||
|
||||
if (parsedValue != null || allowNulls) {
|
||||
observedValue.add(value)
|
||||
}
|
||||
|
||||
if (parsedValue != null) {
|
||||
parsedView.add(parsedValue)
|
||||
} else if (!allowNulls) {
|
||||
removeIndexes.add(i)
|
||||
}
|
||||
}
|
||||
|
||||
for (i in removeIndexes.size - 1 downTo 0) {
|
||||
rawValue.removeAt(removeIndexes.getInt(i))
|
||||
}
|
||||
|
||||
if (removeIndexes.isNotEmpty()) {
|
||||
parent.save()
|
||||
}
|
||||
}
|
||||
|
||||
private fun observe() {
|
||||
val observedValue = observedValue
|
||||
val rawValue = rawValue
|
||||
|
||||
if (observedValue.size != rawValue.size) {
|
||||
load()
|
||||
} else {
|
||||
val iter1 = rawValue.iterator()
|
||||
val iter2 = observedValue.iterator()
|
||||
|
||||
while (iter1.hasNext() && iter2.hasNext()) {
|
||||
if (iter1.next() != iter2.next()) {
|
||||
load()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (iter1.hasNext() || iter2.hasNext()) {
|
||||
load()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final override fun add(index: Int, element: V) {
|
||||
observe()
|
||||
|
||||
val (serialized, newObject) = toString(element) ?: return
|
||||
|
||||
rawValue.add(index, serialized)
|
||||
parsedView.add(index, newObject)
|
||||
observedValue.add(index, serialized)
|
||||
|
||||
parent.save()
|
||||
}
|
||||
|
||||
final override fun removeAt(index: Int): V {
|
||||
observe()
|
||||
|
||||
val old = parsedView[index]
|
||||
val (serialized, _) = toString(old) ?: throw RuntimeException("Serializer did not accept element already present in list")
|
||||
val oldStr = rawValue.getOrNull(index)
|
||||
|
||||
if (oldStr == serialized) {
|
||||
rawValue.removeAt(index)
|
||||
observedValue.removeAt(index)
|
||||
} else {
|
||||
val serializedIndex = rawValue.indexOf(serialized)
|
||||
|
||||
if (serializedIndex == -1) {
|
||||
throw NoSuchElementException("Element $old is present in parsed list at index $index with serialized form of '$serialized', but it is not found in Forge's config list")
|
||||
}
|
||||
|
||||
rawValue.removeAt(serializedIndex)
|
||||
observedValue.removeAt(serializedIndex)
|
||||
}
|
||||
|
||||
parsedView.removeAt(index)
|
||||
|
||||
parent.save()
|
||||
|
||||
return old
|
||||
}
|
||||
|
||||
final override fun set(index: Int, element: V): V {
|
||||
observe()
|
||||
|
||||
val old = parsedView[index]
|
||||
|
||||
val (serializedNew, newElement) = toString(element) ?: return old
|
||||
|
||||
if (old === newElement) {
|
||||
return old
|
||||
}
|
||||
|
||||
val (serialized, _) = toString(old) ?: throw RuntimeException("Serializer did not accept element already present in list")
|
||||
|
||||
check(rawValue[index] == serialized) { "Old value serialized representation $serialized does not match already stored representation ${rawValue[index]} at index $index" }
|
||||
|
||||
parsedView[index] = newElement
|
||||
observedValue[index] = serializedNew
|
||||
rawValue[index] = serializedNew
|
||||
|
||||
parent.save()
|
||||
|
||||
return old
|
||||
}
|
||||
|
||||
final override val size: Int get() {
|
||||
observe()
|
||||
return parsedView.size
|
||||
}
|
||||
|
||||
override fun get(index: Int): V {
|
||||
observe()
|
||||
return parsedView[index]
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : Any> ForgeConfigSpec.Builder.defineObjectList(
|
||||
name: String,
|
||||
defaultValues: () -> List<T>,
|
||||
write: (value: T) -> Pair<String, T>?,
|
||||
read: (value: String) -> T?
|
||||
): ObservedConfigList<T> {
|
||||
val parent = defineListAllowEmpty(name.split('.'), { defaultValues.invoke().mapNotNull { write.invoke(it)?.first }.toMutableList()}, { it is String }) as ForgeConfigSpec.ConfigValue<MutableList<String>>
|
||||
|
||||
return object : ObservedConfigList<T>(parent) {
|
||||
override fun toString(value: T): Pair<String, T>? {
|
||||
return write.invoke(value)
|
||||
}
|
||||
|
||||
override fun fromString(value: String): T? {
|
||||
return read.invoke(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Obviously better use tags")
|
||||
fun <T : Any> ForgeConfigSpec.Builder.defineForgeObjectList(
|
||||
name: String,
|
||||
defaultValues: () -> List<T>,
|
||||
registry: IForgeRegistry<T>
|
||||
): ObservedConfigList<T> {
|
||||
return defineObjectList(name, defaultValues,
|
||||
write = { (registry.getKey(it)?.toString() ?: return@defineObjectList null) to it },
|
||||
read = { registry.getValue(ResourceLocation(it)) })
|
||||
}
|
@ -12,20 +12,20 @@ abstract class ObservedConfigValue<V : Any>(val parent: ConfigValue<String>) : R
|
||||
private var observedValue: String? = null
|
||||
private var cachedValue: V? = null
|
||||
|
||||
protected abstract fun fromValue(value: String): V?
|
||||
protected abstract fun fromString(value: String): V?
|
||||
|
||||
/**
|
||||
* value [V] -> newRawValue [String], newValue [V]
|
||||
*/
|
||||
protected abstract fun toValue(value: V): Pair<String, V>
|
||||
protected abstract fun toString(value: V): Pair<String, V>
|
||||
|
||||
override fun get(): V {
|
||||
if (cachedValue == null || rawValue != observedValue) {
|
||||
var deserialized = fromValue(rawValue)
|
||||
var deserialized = fromString(rawValue)
|
||||
|
||||
if (deserialized == null) {
|
||||
val default = parent.default
|
||||
deserialized = fromValue(default)
|
||||
deserialized = fromString(default)
|
||||
|
||||
if (deserialized == null) {
|
||||
throw RuntimeException("Deserializer did not accept default value: $default")
|
||||
@ -49,12 +49,12 @@ abstract class ObservedConfigValue<V : Any>(val parent: ConfigValue<String>) : R
|
||||
|
||||
override fun accept(value: V) {
|
||||
if (cachedValue == null || rawValue != observedValue) {
|
||||
cachedValue = fromValue(rawValue)
|
||||
cachedValue = fromString(rawValue)
|
||||
observedValue = rawValue
|
||||
}
|
||||
|
||||
if (cachedValue != value) {
|
||||
val (newRaw, newValue) = toValue(value)
|
||||
val (newRaw, newValue) = toString(value)
|
||||
|
||||
if (cachedValue != newValue) {
|
||||
rawValue = newRaw
|
||||
|
@ -1,8 +1,11 @@
|
||||
package ru.dbotthepony.mc.otm
|
||||
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffects
|
||||
import net.minecraftforge.common.ForgeConfigSpec
|
||||
import net.minecraftforge.fml.ModLoadingContext
|
||||
import net.minecraftforge.fml.config.ModConfig
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import ru.dbotthepony.mc.otm.block.entity.AndroidStationBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity
|
||||
import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity
|
||||
@ -125,6 +128,23 @@ object ServerConfig {
|
||||
val DRIVE_VIEWER = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.DRIVE_VIEWER)
|
||||
val DRIVE_RACK = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.DRIVE_RACK, capacity = ImpreciseFraction(80_000))
|
||||
|
||||
init {
|
||||
specBuilder.pop()
|
||||
|
||||
specBuilder.comment("Tweaking of android players").push("android_player")
|
||||
}
|
||||
|
||||
val ANDROID_ENERGY_PER_HUNGER_POINT by specBuilder.defineImpreciseFraction("energy_per_hunger", ImpreciseFraction(1000), ImpreciseFraction.ZERO)
|
||||
val ANDROID_MAX_ENERGY by specBuilder.comment("Internal battery of every android has this much storage").defineImpreciseFraction("capacity", ImpreciseFraction(80_000), ImpreciseFraction.ZERO)
|
||||
|
||||
init {
|
||||
specBuilder.pop()
|
||||
|
||||
specBuilder.comment("Tweaking of exosuits").push("exosuit_player")
|
||||
}
|
||||
|
||||
val INFINITE_EXOSUIT_UPGRADES: Boolean by specBuilder.comment("Allows to apply the same upgrade over and over again.", "Obviously completely breaks balance.").define("infinite_upgrades", false)
|
||||
|
||||
init {
|
||||
specBuilder.pop()
|
||||
}
|
||||
|
@ -20,9 +20,11 @@ import ru.dbotthepony.mc.otm.core.defineImpreciseFraction
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu
|
||||
import ru.dbotthepony.mc.otm.registry.MBlockEntities
|
||||
import ru.dbotthepony.mc.otm.registry.MBlocks
|
||||
import ru.dbotthepony.mc.otm.registry.MNames
|
||||
import ru.dbotthepony.mc.otm.registry.WriteOnce
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
MatteryPoweredBlockEntity(MBlockEntities.ANDROID_STATION, p_155229_, p_155230_), MenuProvider {
|
||||
|
||||
@ -31,7 +33,7 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
}
|
||||
|
||||
override val defaultDisplayName: Component
|
||||
get() = MACHINE_NAME
|
||||
get() = MBlocks.ANDROID_STATION.name
|
||||
|
||||
override val energy = object : WorkerEnergyStorage(this@AndroidStationBlockEntity::setChangedLight, ::CAPACITY, ::MAX_IO, { null }) {
|
||||
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
|
||||
@ -96,8 +98,6 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.android_station")
|
||||
|
||||
private var _CAPACITY: ImpreciseFractionConfigValue by WriteOnce()
|
||||
private var _MAX_IO: ImpreciseFractionConfigValue by WriteOnce()
|
||||
private var _ENERGY_PER_OPERATION: ImpreciseFractionConfigValue by WriteOnce()
|
||||
|
@ -1,7 +1,6 @@
|
||||
package ru.dbotthepony.mc.otm.capability
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntAVLTreeMap
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
@ -10,8 +9,8 @@ import net.minecraft.nbt.StringTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.effect.MobEffect
|
||||
import net.minecraft.world.effect.MobEffects
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.MobSpawnType
|
||||
@ -35,7 +34,7 @@ import net.minecraftforge.event.entity.living.LivingSpawnEvent
|
||||
import net.minecraftforge.event.entity.player.EntityItemPickupEvent
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent
|
||||
import net.minecraftforge.eventbus.api.Event
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import org.apache.commons.lang3.mutable.MutableInt
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.mc.otm.*
|
||||
@ -190,7 +189,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
var willBecomeAndroid by synchronizer.bool()
|
||||
var isAndroid by synchronizer.bool()
|
||||
|
||||
val androidEnergy = SynchronizedPowerWithBattery(ply, synchronizer, DEFAULT_MAX_ANDROID_POWER, DEFAULT_MAX_ANDROID_POWER)
|
||||
val androidEnergy = SynchronizedPowerWithBattery(ply, synchronizer, ServerConfig.ANDROID_MAX_ENERGY, ServerConfig.ANDROID_MAX_ENERGY)
|
||||
|
||||
fun invalidateNetworkState() {
|
||||
invalidateNetworkIn = 10
|
||||
@ -210,8 +209,8 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
shouldPlaySound = false
|
||||
iteration = 0
|
||||
deathLog.clear()
|
||||
androidEnergy.batteryLevel = DEFAULT_MAX_ANDROID_POWER
|
||||
androidEnergy.maxBatteryLevel = DEFAULT_MAX_ANDROID_POWER
|
||||
androidEnergy.batteryLevel = ServerConfig.ANDROID_MAX_ENERGY
|
||||
androidEnergy.maxBatteryLevel = ServerConfig.ANDROID_MAX_ENERGY
|
||||
}
|
||||
|
||||
fun becomeAndroidAndKill() {
|
||||
@ -230,7 +229,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
iteration = 0
|
||||
deathLog.clear()
|
||||
androidEnergy.batteryLevel = ImpreciseFraction.ZERO
|
||||
androidEnergy.maxBatteryLevel = DEFAULT_MAX_ANDROID_POWER
|
||||
androidEnergy.maxBatteryLevel = ServerConfig.ANDROID_MAX_ENERGY
|
||||
dropBattery()
|
||||
}
|
||||
|
||||
@ -521,6 +520,17 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
tickInventory()
|
||||
}
|
||||
|
||||
fun preTick() {
|
||||
if (!ply.isAlive) return
|
||||
|
||||
if (isAndroid) {
|
||||
ForgeRegistries.MOB_EFFECTS.tags()?.getTag(ANDROID_IMMUNE_EFFECTS)?.forEach {
|
||||
if (ply.hasEffect(it))
|
||||
ply.removeEffect(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
if (!ply.isAlive) return
|
||||
|
||||
@ -538,10 +548,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
if (ply.airSupply < ply.maxAirSupply)
|
||||
ply.airSupply = ply.maxAirSupply
|
||||
|
||||
for (effect in UNAFFECTED_EFFECTS)
|
||||
if (ply.hasEffect(effect))
|
||||
ply.removeEffect(effect)
|
||||
|
||||
// TODO: Maybe passive drain?
|
||||
// extractEnergyInner(BigDecimal.valueOf(new Random().nextDouble()), false);
|
||||
if (ply.isSwimming && !hasFeature(AndroidFeatures.AIR_BAGS)) {
|
||||
@ -552,28 +558,28 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
val stats = ply.foodData
|
||||
|
||||
while (stats.foodLevel < 18 && androidEnergy.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) {
|
||||
androidEnergy.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false)
|
||||
while (stats.foodLevel < 18 && androidEnergy.extractEnergyInner(ServerConfig.ANDROID_ENERGY_PER_HUNGER_POINT, true) >= ServerConfig.ANDROID_ENERGY_PER_HUNGER_POINT) {
|
||||
androidEnergy.extractEnergyInner(ServerConfig.ANDROID_ENERGY_PER_HUNGER_POINT, false)
|
||||
stats.foodLevel = stats.foodLevel + 1
|
||||
}
|
||||
|
||||
// "block" quick regeneration
|
||||
// also cause power to generate while in peaceful
|
||||
while (stats.foodLevel > 18 && androidEnergy.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) {
|
||||
androidEnergy.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, false)
|
||||
while (stats.foodLevel > 18 && androidEnergy.receiveEnergyInner(ServerConfig.ANDROID_ENERGY_PER_HUNGER_POINT, true) >= ServerConfig.ANDROID_ENERGY_PER_HUNGER_POINT) {
|
||||
androidEnergy.receiveEnergyInner(ServerConfig.ANDROID_ENERGY_PER_HUNGER_POINT, false)
|
||||
stats.foodLevel = stats.foodLevel - 1
|
||||
}
|
||||
|
||||
val foodLevel = stats.foodLevel.toFloat()
|
||||
|
||||
if (stats.saturationLevel < foodLevel) {
|
||||
val extracted = androidEnergy.extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (foodLevel - stats.saturationLevel), false)
|
||||
stats.setSaturation(stats.saturationLevel + (extracted / ENERGY_FOR_HUNGER_POINT).toFloat())
|
||||
val extracted = androidEnergy.extractEnergyInner(ServerConfig.ANDROID_ENERGY_PER_HUNGER_POINT * (foodLevel - stats.saturationLevel), false)
|
||||
stats.setSaturation(stats.saturationLevel + (extracted / ServerConfig.ANDROID_ENERGY_PER_HUNGER_POINT).toFloat())
|
||||
}
|
||||
|
||||
if (stats.exhaustionLevel > 0f) {
|
||||
val extracted = androidEnergy.extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (stats.exhaustionLevel / 4f), false)
|
||||
stats.setExhaustion(stats.exhaustionLevel - (extracted / ENERGY_FOR_HUNGER_POINT).toFloat() * 4f)
|
||||
val extracted = androidEnergy.extractEnergyInner(ServerConfig.ANDROID_ENERGY_PER_HUNGER_POINT * (stats.exhaustionLevel / 4f), false)
|
||||
stats.setExhaustion(stats.exhaustionLevel - (extracted / ServerConfig.ANDROID_ENERGY_PER_HUNGER_POINT).toFloat() * 4f)
|
||||
}
|
||||
|
||||
for (feature in features.values) {
|
||||
@ -653,37 +659,26 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
|
||||
@Suppress("unused")
|
||||
companion object {
|
||||
val UNAFFECTED_EFFECTS = ObjectArraySet<MobEffect>()
|
||||
|
||||
fun registerEffects(event: FMLCommonSetupEvent) {
|
||||
UNAFFECTED_EFFECTS.add(MobEffects.CONDUIT_POWER)
|
||||
UNAFFECTED_EFFECTS.add(MobEffects.HEAL)
|
||||
// maybe it makes things go haywire idk
|
||||
// UNAFFECTED_EFFECTS.add(MobEffects.HARM);
|
||||
UNAFFECTED_EFFECTS.add(MobEffects.REGENERATION)
|
||||
UNAFFECTED_EFFECTS.add(MobEffects.WATER_BREATHING)
|
||||
UNAFFECTED_EFFECTS.add(MobEffects.POISON)
|
||||
// even skeletons can be withered
|
||||
// UNAFFECTED_EFFECTS.add(MobEffects.WITHER);
|
||||
UNAFFECTED_EFFECTS.add(MobEffects.HEALTH_BOOST)
|
||||
UNAFFECTED_EFFECTS.add(MobEffects.ABSORPTION)
|
||||
UNAFFECTED_EFFECTS.add(MobEffects.SATURATION)
|
||||
UNAFFECTED_EFFECTS.add(MobEffects.DOLPHINS_GRACE)
|
||||
}
|
||||
val ANDROID_IMMUNE_EFFECTS: TagKey<MobEffect> = TagKey.create(ForgeRegistries.MOB_EFFECTS.registryKey, ResourceLocation(OverdriveThatMatters.MOD_ID, "android_immune_effects"))
|
||||
|
||||
fun onPlayerTick(event: PlayerTickEvent) {
|
||||
if (event.phase == TickEvent.Phase.START)
|
||||
return
|
||||
|
||||
val ent = event.player
|
||||
|
||||
if (ent.level.isClientSide) {
|
||||
ent.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
it.tickClient()
|
||||
if (event.phase == TickEvent.Phase.START) {
|
||||
if (!ent.level.isClientSide) {
|
||||
ent.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
it.preTick()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ent.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
it.tick()
|
||||
if (ent.level.isClientSide) {
|
||||
ent.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
it.tickClient()
|
||||
}
|
||||
} else {
|
||||
ent.getCapability(MatteryCapability.MATTERY_PLAYER).ifPresentK {
|
||||
it.tick()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -794,7 +789,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
event.original.invalidateCaps()
|
||||
}
|
||||
|
||||
val ENERGY_FOR_HUNGER_POINT = ImpreciseFraction(1000)
|
||||
const val SLEEP_TICKS_LIMIT = 80
|
||||
|
||||
private val itemPickupTicks = WeakHashMap<Player, WeakHashMap<ItemEntity, MutableInt>>()
|
||||
@ -839,7 +833,5 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val DEFAULT_MAX_ANDROID_POWER = ImpreciseFraction(60000)
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import ru.dbotthepony.mc.otm.client.screen.widget.TallHorizontalPowerGaugePanel
|
||||
import ru.dbotthepony.mc.otm.menu.EnergyServoMenu
|
||||
|
||||
class EnergyServoScreen(menu: EnergyServoMenu, inventory: Inventory, title: Component) : MatteryScreen<EnergyServoMenu>(menu, inventory, title) {
|
||||
override fun makeMainFrame(): FramePanel<MatteryScreen<*>>? {
|
||||
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
|
||||
val frame = FramePanel.padded(this,
|
||||
width = AbstractSlotPanel.SIZE * 2f + HorizontalPowerGaugePanel.GAUGE_BACKGROUND_TALL.width + 8f + ProgressGaugePanel.GAUGE_BACKGROUND.width * 2f,
|
||||
AbstractSlotPanel.SIZE, title)
|
||||
|
@ -13,7 +13,7 @@ import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
|
||||
class MatterDecomposerScreen(p_97741_: MatterDecomposerMenu, p_97742_: Inventory, p_97743_: Component) :
|
||||
MatteryScreen<MatterDecomposerMenu>(p_97741_, p_97742_, p_97743_) {
|
||||
|
||||
override fun makeMainFrame(): FramePanel<out MatteryScreen<*>> {
|
||||
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
|
||||
val frame = super.makeMainFrame()!!
|
||||
|
||||
val m = PowerGaugePanel(this, frame, menu.powerWidget, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT)
|
||||
|
@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.core
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
|
||||
@ -348,7 +347,8 @@ fun ImpreciseFraction.formatSi(decimalPlaces: Int = 2): String {
|
||||
|
||||
fun Int.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 2): Component {
|
||||
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
|
||||
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString()) else if (suffix is Component) TextComponent(toString() + " " + suffix.string) else TextComponent(toString() + " " + suffix)
|
||||
val prefix = determineSiPrefix() ?: return if (suffix == "") TextComponent(toString()) else if (suffix is Component) TextComponent(
|
||||
toString() + " " + suffix.string) else TextComponent(toString() + " " + suffix)
|
||||
return TranslatableComponent(prefix.formatLocaleKey, "%f.$decimalPlaces".format(this.toFloat() / prefix.int!!.toFloat()), suffix)
|
||||
}
|
||||
|
||||
|
@ -874,7 +874,7 @@ class ImpreciseFractionConfigValue(
|
||||
val minimum: ImpreciseFraction? = null,
|
||||
val maximum: ImpreciseFraction? = null,
|
||||
) : ObservedConfigValue<ImpreciseFraction>(parent) {
|
||||
override fun fromValue(value: String): ImpreciseFraction? {
|
||||
override fun fromString(value: String): ImpreciseFraction? {
|
||||
try {
|
||||
val parsed = ImpreciseFraction(value)
|
||||
|
||||
@ -890,7 +890,13 @@ class ImpreciseFractionConfigValue(
|
||||
}
|
||||
}
|
||||
|
||||
override fun toValue(value: ImpreciseFraction): Pair<String, ImpreciseFraction> {
|
||||
override fun toString(value: ImpreciseFraction): Pair<String, ImpreciseFraction> {
|
||||
if (minimum != null && minimum > value) {
|
||||
return minimum.toString() to minimum
|
||||
} else if (maximum != null && maximum < value) {
|
||||
return maximum.toString() to maximum
|
||||
}
|
||||
|
||||
return value.toString() to value
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import net.minecraft.world.item.TooltipFlag
|
||||
import net.minecraft.world.item.UseAnim
|
||||
import net.minecraft.world.level.Level
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.ServerConfig
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
@ -46,7 +47,7 @@ class ExoSuitSlotUpgradeItem(
|
||||
}
|
||||
}
|
||||
|
||||
val alreadyHas = id != null && runIfClient(false) {
|
||||
val alreadyHas = (id != null && !ServerConfig.INFINITE_EXOSUIT_UPGRADES) && runIfClient(false) {
|
||||
minecraft.player?.matteryPlayer?.exoSuitSlotCountModifiers?.contains(id) == true
|
||||
}
|
||||
|
||||
@ -60,7 +61,7 @@ class ExoSuitSlotUpgradeItem(
|
||||
override fun use(p_41432_: Level, player: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
val matteryPlayer = player.matteryPlayer ?: return super.use(p_41432_, player, hand)
|
||||
|
||||
if (matteryPlayer.hasExoSuit && (id == null || id !in matteryPlayer.exoSuitSlotCountModifiers)) {
|
||||
if (matteryPlayer.hasExoSuit && ((id == null || ServerConfig.INFINITE_EXOSUIT_UPGRADES) || id !in matteryPlayer.exoSuitSlotCountModifiers)) {
|
||||
player.startUsingItem(hand)
|
||||
return InteractionResultHolder.consume(player.getItemInHand(hand))
|
||||
}
|
||||
@ -72,7 +73,7 @@ class ExoSuitSlotUpgradeItem(
|
||||
if (player !is Player) return super.finishUsingItem(itemStack, level, player)
|
||||
val matteryPlayer = player.matteryPlayer ?: return super.finishUsingItem(itemStack, level, player)
|
||||
|
||||
if (!matteryPlayer.hasExoSuit || (id != null && id in matteryPlayer.exoSuitSlotCountModifiers)) {
|
||||
if (!matteryPlayer.hasExoSuit || (!ServerConfig.INFINITE_EXOSUIT_UPGRADES && id != null && id in matteryPlayer.exoSuitSlotCountModifiers)) {
|
||||
return super.finishUsingItem(itemStack, level, player)
|
||||
}
|
||||
|
||||
@ -81,7 +82,11 @@ class ExoSuitSlotUpgradeItem(
|
||||
|
||||
if (player is ServerPlayer) {
|
||||
if (id != null) {
|
||||
matteryPlayer.exoSuitSlotCountModifiers[id] = slotCount
|
||||
if (ServerConfig.INFINITE_EXOSUIT_UPGRADES && id in matteryPlayer.exoSuitSlotCountModifiers) {
|
||||
matteryPlayer.exoSuitSlotCountModifiers[UUID.randomUUID()] = slotCount
|
||||
} else {
|
||||
matteryPlayer.exoSuitSlotCountModifiers[id] = slotCount
|
||||
}
|
||||
} else {
|
||||
matteryPlayer.exoSuitSlotCountModifiers[UUID.randomUUID()] = slotCount
|
||||
}
|
||||
|
@ -24,6 +24,128 @@ class LazyList<T> : AbstractList<T> {
|
||||
}
|
||||
}
|
||||
|
||||
class ConditionalSet<T> : AbstractSet<T> {
|
||||
// method without boxing
|
||||
fun interface Condition {
|
||||
fun check(): Boolean
|
||||
}
|
||||
|
||||
private val getters: Array<Pair<Condition, T>>
|
||||
|
||||
constructor(vararg getters: Pair<Condition, T>) : super() {
|
||||
this.getters = Array(getters.size) { getters[it] }
|
||||
}
|
||||
|
||||
constructor(getters: List<Pair<Condition, T>>) : super() {
|
||||
this.getters = Array(getters.size) { getters[it] }
|
||||
}
|
||||
|
||||
override val size: Int get() {
|
||||
var i = 0
|
||||
|
||||
for (pair in getters) {
|
||||
if (pair.first.check()) {
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<T> {
|
||||
return object : Iterator<T> {
|
||||
val parent = getters.iterator()
|
||||
private var pair: Pair<Condition, T>? = null
|
||||
|
||||
private fun search() {
|
||||
for (pair in parent) {
|
||||
if (pair.first.check()) {
|
||||
this.pair = pair
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.pair = null
|
||||
}
|
||||
|
||||
init {
|
||||
search()
|
||||
}
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
return pair != null
|
||||
}
|
||||
|
||||
override fun next(): T {
|
||||
val pair = pair ?: throw NoSuchElementException()
|
||||
search()
|
||||
return pair.second
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ConditionalLazySet<T> : AbstractSet<T> {
|
||||
// method without boxing
|
||||
fun interface Condition {
|
||||
fun check(): Boolean
|
||||
}
|
||||
|
||||
private val getters: Array<Pair<Condition, () -> T>>
|
||||
|
||||
constructor(vararg getters: Pair<Condition, () -> T>) : super() {
|
||||
this.getters = Array(getters.size) { getters[it] }
|
||||
}
|
||||
|
||||
constructor(getters: List<Pair<Condition, () -> T>>) : super() {
|
||||
this.getters = Array(getters.size) { getters[it] }
|
||||
}
|
||||
|
||||
override val size: Int get() {
|
||||
var i = 0
|
||||
|
||||
for (pair in getters) {
|
||||
if (pair.first.check()) {
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<T> {
|
||||
return object : Iterator<T> {
|
||||
val parent = getters.iterator()
|
||||
private var pair: Pair<Condition, () -> T>? = null
|
||||
|
||||
private fun search() {
|
||||
for (pair in parent) {
|
||||
if (pair.first.check()) {
|
||||
this.pair = pair
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.pair = null
|
||||
}
|
||||
|
||||
init {
|
||||
search()
|
||||
}
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
return pair != null
|
||||
}
|
||||
|
||||
override fun next(): T {
|
||||
val pair = pair ?: throw NoSuchElementException()
|
||||
search()
|
||||
return pair.second.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class LazyMap<K, T> : AbstractMap<K, T> {
|
||||
override val entries: Set<Map.Entry<K, T>>
|
||||
|
||||
|
@ -30,6 +30,7 @@ import ru.dbotthepony.mc.otm.registry.objects.CrateProperties
|
||||
import ru.dbotthepony.mc.otm.registry.objects.DecorativeBlock
|
||||
import ru.dbotthepony.mc.otm.registry.objects.StripedColoredDecorativeBlock
|
||||
import java.util.function.Supplier
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
@ -41,15 +42,19 @@ fun <T> Registry<T>.register(key: ResourceLocation, value: T): Holder<T> {
|
||||
return (this as WritableRegistry<T>).register(ResourceKey.create(key(), key), value, Lifecycle.stable())
|
||||
}
|
||||
|
||||
private class RegistryDelegate<T>(key: String) {
|
||||
private class RegistryDelegate<T>(key: String) : ReadOnlyProperty<Any, ForgeRegistry<T>> {
|
||||
private var value: Supplier<IForgeRegistry<T>?>? = null
|
||||
|
||||
val location = ResourceLocation(OverdriveThatMatters.MOD_ID, key)
|
||||
val key: ResourceKey<Registry<T>> = ResourceKey.createRegistryKey(location)
|
||||
|
||||
fun get(): IForgeRegistry<T> {
|
||||
fun get(): ForgeRegistry<T> {
|
||||
val supp = value ?: throw IllegalStateException("Tried to access uninitialized registry $location")
|
||||
return supp.get() ?: throw IllegalStateException("Accessing registry $location too early")
|
||||
return supp.get() as ForgeRegistry<T>? ?: throw IllegalStateException("Accessing registry $location too early")
|
||||
}
|
||||
|
||||
override fun getValue(thisRef: Any, property: KProperty<*>): ForgeRegistry<T> {
|
||||
return get()
|
||||
}
|
||||
|
||||
fun build(event: NewRegistryEvent) {
|
||||
@ -82,8 +87,8 @@ object MRegistry {
|
||||
private val features = RegistryDelegate<AndroidFeatureType<*>>("android_features")
|
||||
private val research = RegistryDelegate<AndroidResearchType<*>>("android_research")
|
||||
|
||||
val ANDROID_FEATURES get() = features.get() as ForgeRegistry<AndroidFeatureType<*>>
|
||||
val ANDROID_RESEARCH get() = research.get() as ForgeRegistry<AndroidResearchType<*>>
|
||||
val ANDROID_FEATURES by features
|
||||
val ANDROID_RESEARCH by research
|
||||
|
||||
val ANDROID_FEATURES_LOCATION get() = features.location
|
||||
val ANDROID_RESEARCH_LOCATION get() = research.location
|
||||
|
Loading…
Reference in New Issue
Block a user