diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index ccb104f2f..3ffa9e3cd 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -13,12 +13,9 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import ru.dbotthepony.mc.otm.android.AndroidFeatureType; -import ru.dbotthepony.mc.otm.android.AndroidResearchType; import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue; +import ru.dbotthepony.mc.otm.capability.AndroidCapability; import ru.dbotthepony.mc.otm.capability.MatteryCapability; -import ru.dbotthepony.mc.otm.capability.android.AndroidCapability; -import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer; import ru.dbotthepony.mc.otm.capability.drive.DrivePool; import ru.dbotthepony.mc.otm.client.AndroidGui; import ru.dbotthepony.mc.otm.client.EventHandlerKt; @@ -86,7 +83,6 @@ public final class OverdriveThatMatters { MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(TickerKt.class); - MinecraftForge.EVENT_BUS.register(AndroidCapabilityPlayer.Companion); MinecraftForge.EVENT_BUS.register(AndroidCapability.Companion); MinecraftForge.EVENT_BUS.register(MatterRegistryKt.class); MinecraftForge.EVENT_BUS.register(MatterDataKt.class); diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java index 75e5246f0..c9e6fe058 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java @@ -2,7 +2,6 @@ package ru.dbotthepony.mc.otm.capability; import mekanism.api.energy.IStrictEnergyHandler; import net.minecraftforge.common.capabilities.*; -import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability; import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive; import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; import ru.dbotthepony.mc.otm.capability.matter.IMatterTaskProvider; @@ -13,7 +12,7 @@ import ru.dbotthepony.mc.otm.storage.IStorageStack; public class MatteryCapability { public static final Capability ENERGY = CapabilityManager.get(new CapabilityToken<>() {}); - public static final Capability ANDROID = CapabilityManager.get(new CapabilityToken<>() {}); + public static final Capability ANDROID = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability MATTER = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability MATTER_NODE = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability PATTERN = CapabilityManager.get(new CapabilityToken<>() {}); @@ -26,7 +25,7 @@ public class MatteryCapability { @SuppressWarnings("unused") public static void register(final RegisterCapabilitiesEvent event) { event.register(IMatteryEnergyStorage.class); - event.register(IAndroidCapability.class); + event.register(AndroidCapability.class); event.register(IMatterHandler.class); event.register(IPatternStorage.class); event.register(IMatterTaskProvider.class); diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt index 31b76edbd..cd7d01e87 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeature.kt @@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.android import net.minecraft.nbt.CompoundTag import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.event.entity.living.LivingHurtEvent -import ru.dbotthepony.mc.otm.capability.android.AndroidCapability +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.readNbt import ru.dbotthepony.mc.otm.set import ru.dbotthepony.mc.otm.writeNbt @@ -11,7 +11,7 @@ import java.io.InputStream import java.io.OutputStream abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: AndroidCapability) : INBTSerializable { - val entity get() = android.entity + val entity get() = android.ply /** * Whenever there are changes to network diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeatureType.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeatureType.kt index 6108825d2..818956e73 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeatureType.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidFeatureType.kt @@ -4,7 +4,7 @@ import net.minecraft.network.chat.Component import net.minecraft.network.chat.ComponentContents import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.contents.TranslatableContents -import ru.dbotthepony.mc.otm.capability.android.AndroidCapability +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.getKeyNullable import ru.dbotthepony.mc.otm.registry.MRegistry diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt index 9547f923b..4181a4705 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearch.kt @@ -5,7 +5,7 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.network.chat.Component import net.minecraft.world.item.ItemStack import net.minecraftforge.common.util.INBTSerializable -import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.client.render.SkinElement import ru.dbotthepony.mc.otm.readNbt import ru.dbotthepony.mc.otm.set @@ -13,7 +13,7 @@ import ru.dbotthepony.mc.otm.writeNbt import java.io.InputStream import java.io.OutputStream -abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability: AndroidCapabilityPlayer) : INBTSerializable { +abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability: AndroidCapability) : INBTSerializable { var isResearched = false protected set diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt index 8ef3ad6c6..043fadbbb 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidResearchType.kt @@ -7,12 +7,12 @@ import net.minecraft.network.chat.ComponentContents import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.contents.TranslatableContents import ru.dbotthepony.mc.otm.TranslatableComponent -import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.getKeyNullable import ru.dbotthepony.mc.otm.registry.MRegistry fun interface AndroidResearchFactory { - fun factory(type: AndroidResearchType<*>, capability: AndroidCapabilityPlayer): R + fun factory(type: AndroidResearchType<*>, capability: AndroidCapability): R } private fun findPrerequisites( @@ -173,7 +173,7 @@ open class AndroidResearchType( ImmutableList.copyOf(findAllChildren(flatUnlocks)) } - fun factory(capability: AndroidCapabilityPlayer) = factory.factory(this, capability) + fun factory(capability: AndroidCapability) = factory.factory(this, capability) val registryName by lazy { MRegistry.ANDROID_RESEARCH.getKeyNullable(this) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/AttackBoost.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/AttackBoost.kt index f6c56903a..18e40cb7c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/AttackBoost.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/AttackBoost.kt @@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.android.feature import net.minecraft.world.entity.ai.attributes.AttributeModifier import net.minecraft.world.entity.ai.attributes.Attributes import ru.dbotthepony.mc.otm.android.AndroidFeature -import ru.dbotthepony.mc.otm.capability.android.AndroidCapability +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.registry.AndroidFeatures import java.util.* diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ExtendedReach.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ExtendedReach.kt index 6d60727d6..a2bcda974 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ExtendedReach.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ExtendedReach.kt @@ -2,9 +2,8 @@ package ru.dbotthepony.mc.otm.android.feature import net.minecraft.world.entity.ai.attributes.AttributeModifier import net.minecraftforge.common.ForgeMod -import net.minecraftforge.event.entity.living.LivingHurtEvent import ru.dbotthepony.mc.otm.android.AndroidFeature -import ru.dbotthepony.mc.otm.capability.android.AndroidCapability +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.registry.AndroidFeatures import java.util.* diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/LimbOverclocking.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/LimbOverclocking.kt index 813cf0728..ffde8b30f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/LimbOverclocking.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/LimbOverclocking.kt @@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.android.feature import net.minecraft.world.entity.ai.attributes.AttributeModifier import net.minecraft.world.entity.ai.attributes.Attributes import ru.dbotthepony.mc.otm.android.AndroidFeature -import ru.dbotthepony.mc.otm.capability.android.AndroidCapability +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.registry.AndroidFeatures import java.util.* diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt index 3e969b80b..e734f6df6 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsArmor.kt @@ -4,7 +4,7 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.server.level.ServerPlayer import net.minecraftforge.event.entity.living.LivingHurtEvent import ru.dbotthepony.mc.otm.android.AndroidFeature -import ru.dbotthepony.mc.otm.capability.android.AndroidCapability +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.registry.AndroidFeatures diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt index 17a02cb24..396c77634 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/NanobotsRegeneration.kt @@ -4,7 +4,7 @@ import net.minecraft.nbt.CompoundTag import net.minecraft.server.level.ServerPlayer import net.minecraftforge.event.entity.living.LivingHurtEvent import ru.dbotthepony.mc.otm.android.AndroidFeature -import ru.dbotthepony.mc.otm.capability.android.AndroidCapability +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.StatNames diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/StepAssistFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/StepAssistFeature.kt index 3929388df..bbd2d5937 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/StepAssistFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/StepAssistFeature.kt @@ -3,7 +3,7 @@ package ru.dbotthepony.mc.otm.android.feature import net.minecraft.world.entity.ai.attributes.AttributeModifier import net.minecraftforge.common.ForgeMod import ru.dbotthepony.mc.otm.android.AndroidFeature -import ru.dbotthepony.mc.otm.capability.android.AndroidCapability +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.registry.AndroidFeatures import java.util.* diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AndroidCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AndroidCapability.kt new file mode 100644 index 000000000..8f7ed0c6f --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/AndroidCapability.kt @@ -0,0 +1,737 @@ +package ru.dbotthepony.mc.otm.capability + +import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap +import it.unimi.dsi.fastutil.objects.ObjectArraySet +import net.minecraft.ChatFormatting +import net.minecraft.core.Direction +import net.minecraftforge.common.capabilities.ICapabilityProvider +import net.minecraftforge.common.util.INBTSerializable +import net.minecraft.nbt.CompoundTag +import net.minecraft.world.item.ItemStack +import ru.dbotthepony.mc.otm.android.AndroidFeatureType +import ru.dbotthepony.mc.otm.android.AndroidFeature +import java.lang.Runnable +import net.minecraft.server.level.ServerPlayer +import net.minecraftforge.event.entity.living.LivingHurtEvent +import net.minecraft.nbt.ListTag +import net.minecraft.nbt.Tag +import net.minecraft.resources.ResourceLocation +import net.minecraft.world.effect.MobEffect +import net.minecraftforge.common.util.LazyOptional +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent +import net.minecraft.world.effect.MobEffects +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.player.Player +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.capabilities.ForgeCapabilities +import net.minecraftforge.event.AttachCapabilitiesEvent +import net.minecraftforge.eventbus.api.SubscribeEvent +import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent +import net.minecraftforge.event.entity.player.PlayerEvent +import net.minecraftforge.eventbus.api.EventPriority +import ru.dbotthepony.mc.otm.* +import ru.dbotthepony.mc.otm.android.AndroidResearch +import ru.dbotthepony.mc.otm.android.AndroidResearchType +import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage +import ru.dbotthepony.mc.otm.capability.extractEnergy +import ru.dbotthepony.mc.otm.capability.receiveEnergy +import ru.dbotthepony.mc.otm.core.ImpreciseFraction +import ru.dbotthepony.mc.otm.network.* +import ru.dbotthepony.mc.otm.registry.AndroidFeatures +import ru.dbotthepony.mc.otm.registry.MNames +import ru.dbotthepony.mc.otm.registry.MRegistry +import ru.dbotthepony.mc.otm.registry.StatNames +import java.util.* + +@Suppress("unused") +class AndroidCapability(val ply: Player) : ICapabilityProvider, IMatteryEnergyStorage, INBTSerializable { + private var battery = ImpreciseFraction.ZERO + private var maxBattery = ImpreciseFraction(60000) + + var batteryItemStack: ItemStack = ItemStack.EMPTY + + private val features = Object2ObjectArrayMap, AndroidFeature>() + private val networkQueue = ArrayList() + private val queuedTicks = ArrayList() + private var tickedOnce = false + + private var willBecomeAndroidNetwork = false + private var shouldPlaySound = false + private val research = ArrayList() + + private var remoteBattery = ImpreciseFraction(-1) + private var remoteMaxBattery = ImpreciseFraction(-1) + private var remoteBatteryStack = ItemStack.EMPTY + + private var invalidateNetworkIn = 10 + private var remoteIsAndroid = false + + var willBecomeAndroid = false + var isAndroid = false + + var sleepTicks = 0 + + fun invalidateNetworkState() { + invalidateNetworkIn = 10 + } + + val isEverAndroid: Boolean get() = isAndroid || willBecomeAndroid + + fun becomeAndroidSoft() { + if (isAndroid || willBecomeAndroid) return + willBecomeAndroid = true + (ply as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message").withStyle(ChatFormatting.GRAY), false) + } + + fun becomeAndroid() { + if (isAndroid) return + + isAndroid = true + willBecomeAndroid = false + shouldPlaySound = false + battery = ImpreciseFraction(60000) + maxBattery = ImpreciseFraction(60000) + } + + fun becomeAndroidAndKill() { + if (isAndroid) return + + becomeAndroid() + ply.hurt(MRegistry.DAMAGE_BECOME_ANDROID, ply.maxHealth * 2) + } + + fun becomeHumane() { + if (willBecomeAndroid) willBecomeAndroid = false + if (!isAndroid) return + + isAndroid = false + shouldPlaySound = false + battery = ImpreciseFraction(0) + maxBattery = ImpreciseFraction(60000) + dropBattery() + } + + fun becomeHumaneAndKill() { + if (willBecomeAndroid) willBecomeAndroid = false + if (!isAndroid) return + + becomeHumane() + ply.hurt(MRegistry.DAMAGE_BECOME_HUMANE, ply.maxHealth * 2) + } + + fun obliviate(refund: Boolean = true) { + if (refund) { + for (instance in research) { + if (instance.isResearched) { + instance.unResearch() + instance.refund(simulate = false) + } + } + } + + val copy = java.util.List.copyOf(features.values) + + for (feature in copy) { + removeFeature(feature.type) + } + } + + fun getResearch(type: AndroidResearchType): T { + for (instance in research) { + if (instance.type === type) { + return instance as T + } + } + + val instance = type.factory(this) + research.add(instance) + return instance + } + + var lastJumpTicks = 14 + + private fun addFeature(feature: AndroidFeature): Boolean { + if (features.containsKey(feature.type)) return false + features[feature.type] = feature + + if (!ply.level.isClientSide) { + queuedTicks.add(feature::applyModifiers) + } + + if (ply is ServerPlayer) { + sendNetwork(AndroidFeatureSyncPacket(feature)) + } + + return true + } + + @Suppress("unchecked_cast") + fun addFeature(feature: AndroidFeatureType): T { + val get = features[feature] + if (get != null) return get as T + + val factory = feature.create(this) + + features[feature] = factory + + if (!ply.level.isClientSide) { + queuedTicks.add(factory::applyModifiers) + } + + if (ply is ServerPlayer) { + sendNetwork(AndroidFeatureSyncPacket(factory)) + } + + return factory + } + + fun removeFeature(feature: AndroidFeatureType<*>): Boolean { + val removed = features.remove(feature) + + if (removed != null) { + if (!ply.level.isClientSide) { + queuedTicks.add { + removed.removeModifiers() + } + } + + if (ply is ServerPlayer) { + sendNetwork(AndroidFeatureRemovePacket(removed.type)) + } + } + + return removed != null + } + + fun hasFeature(feature: AndroidFeatureType<*>): Boolean { + return features.containsKey(feature) + } + + fun hasFeatureLevel(feature: AndroidFeatureType<*>, level: Int): Boolean { + val get = features[feature] ?: return false + return get.level >= level + } + + @Suppress("unchecked_cast") + fun getFeature(feature: AndroidFeatureType): T? { + return features[feature] as T? + } + + fun onHurt(event: LivingHurtEvent) { + for (feature in features.values) { + feature.onHurt(event) + } + } + + fun computeIfAbsent(feature: AndroidFeatureType): T { + return getFeature(feature) ?: addFeature(feature) + } + + fun getFeatureO(feature: AndroidFeatureType): Optional { + val get = getFeature(feature) + return if (get != null) Optional.of(get) else Optional.empty() + } + + fun ifFeature(feature: AndroidFeatureType, consumer: (T) -> Unit) { + val get = getFeature(feature) + + if (get != null) { + consumer(get) + } + } + + override fun serializeNBT(): CompoundTag { + val tag = CompoundTag() + + tag["energy_stored"] = battery.serializeNBT() + tag["energy_stored_max"] = maxBattery.serializeNBT() + tag["battery"] = batteryItemStack.serializeNBT() + + val featureList = ListTag() + + for (feature in features.values) { + val featureNbt = feature.serializeNBT() + + featureNbt["id"] = feature.type.registryName!!.toString() + featureList.add(featureNbt) + } + + tag["features"] = featureList + + tag["is_android"] = isAndroid + tag["will_become_android"] = willBecomeAndroid + + val list = ListTag() + + for (instance in research) { + val researchTag = instance.serializeNBT() + + researchTag["id"] = instance.type.registryName!!.toString() + list.add(researchTag) + } + + tag["research"] = list + + return tag + } + + override fun deserializeNBT(compound: CompoundTag) { + compound.ifHas("energy_stored") { + battery = ImpreciseFraction.deserializeNBT(it) + } + + compound.ifHas("energy_stored_max") { + maxBattery = ImpreciseFraction.deserializeNBT(it) + } + + compound.ifHas("battery", CompoundTag::class.java) { + batteryItemStack = ItemStack.of(it) + } + + features.clear() + + val featuresNbt = compound.getList("features", Tag.TAG_COMPOUND.toInt()) + + for (tag in featuresNbt) { + if (tag is CompoundTag) { + val feature = MRegistry.ANDROID_FEATURES.getValue(ResourceLocation(tag.getString("id"))) + + if (feature?.isApplicable(this) == true) { + val instance = feature.create(this) + + instance.deserializeNBT(tag) + addFeature(instance) + + if (!ply.level.isClientSide) { + queuedTicks.add(instance::applyModifiers) + } + } + } + } + + isAndroid = compound.getBoolean("is_android") + willBecomeAndroid = compound.getBoolean("will_become_android") + research.clear() + + val list = compound.getList("research", Tag.TAG_COMPOUND.toInt()) + + for (tag in list) { + if (tag is CompoundTag) { + val research = MRegistry.ANDROID_RESEARCH.getValue(ResourceLocation(tag.getString("id"))) + + if (research != null) { + val instance = research.factory(this) + instance.deserializeNBT(tag) + this.research.add(instance) + } + } + } + } + + fun dropBattery() { + if (batteryItemStack.isEmpty) return + ply.spawnAtLocation(batteryItemStack) + batteryItemStack = ItemStack.EMPTY + } + + private fun sendNetwork(packet: Any) { + if (ply is ServerPlayer) { + if (tickedOnce) { + AndroidNetworkChannel.send(ply, packet) + } else { + networkQueue.add(packet) + } + } + } + + fun tickClient() { + queuedTicks.clear() + + if (!ply.isAlive) { + return + } + + if (willBecomeAndroid) { + if (ply.isSleeping) { + sleepTicks++ + } else { + sleepTicks = 0 + } + } + + if (isAndroid) { + for (feature in features.values) { + feature.tickClient() + } + } + } + + fun tick() { + if (!ply.isAlive) return + + if (willBecomeAndroid) { + if (ply.isSleeping) { + sleepTicks++ + + if (sleepTicks > SLEEP_TICKS_LIMIT) { + becomeAndroid() + shouldPlaySound = true + sleepTicks = 0 + + (ply as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false) + } + } else { + sleepTicks = 0 + } + } + + if (isAndroid) { + if (ply.airSupply < ply.maxAirSupply) + ply.airSupply = ply.maxAirSupply + + for (effect in UNAFFECTED_EFFECTS) + if (ply.hasEffect(effect)) + ply.removeEffect(effect) + + if (!batteryItemStack.isEmpty && battery < maxBattery) { + batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresent { + if (it is IMatteryEnergyStorage) { + battery += it.extractEnergyInner(maxBattery - battery, false) + } else { + battery += it.extractEnergy(maxBattery - battery, false) + } + } + } + + // TODO: Maybe passive drain? + // extractEnergyInner(BigDecimal.valueOf(new Random().nextDouble()), false); + if (ply.isSwimming && !hasFeature(AndroidFeatures.AIR_BAGS)) { + ply.isSwimming = false + } + + val stats = ply.foodData + + while (stats.foodLevel < 18 && extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) { + extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false) + stats.foodLevel = stats.foodLevel + 1 + } + + // "block" quick regeneration + // also cause power to generate while in peaceful + while (stats.foodLevel > 18 && receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) { + receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, false) + stats.foodLevel = stats.foodLevel - 1 + } + + val foodLevel = stats.foodLevel.toFloat() + + if (stats.saturationLevel < foodLevel) { + val extracted = extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (foodLevel - stats.saturationLevel), false) + stats.setSaturation(stats.saturationLevel + (extracted / ENERGY_FOR_HUNGER_POINT).toFloat()) + } + + if (stats.exhaustionLevel > 0f) { + val extracted = extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (stats.exhaustionLevel / 4f), false) + stats.setExhaustion(stats.exhaustionLevel - (extracted / ENERGY_FOR_HUNGER_POINT).toFloat() * 4f) + } + + for (feature in features.values) { + feature.tickServer() + } + } + + for (runnable in queuedTicks) { + runnable.run() + } + + queuedTicks.clear() + + if (invalidateNetworkIn > 0 && --invalidateNetworkIn == 0) { + remoteBattery = ImpreciseFraction.MINUS_ONE + remoteMaxBattery = ImpreciseFraction.MINUS_ONE + remoteBatteryStack = ItemStack.EMPTY + + remoteIsAndroid = false + willBecomeAndroidNetwork = false + + for (instance in research) { + instance.isDirty = true + instance.invalidateNetwork() + } + + for (feature in features.values) { + feature.isDirty = true + feature.invalidateNetwork() + } + } + + tickedOnce = true + + if (battery != remoteBattery) { + remoteBattery = battery + sendNetwork(AndroidEnergyLevelPacket(level = battery, isMaxEnergy = false)) + } + + if (maxBattery != remoteMaxBattery) { + remoteMaxBattery = maxBattery + sendNetwork(AndroidEnergyLevelPacket(level = maxBattery, isMaxEnergy = true)) + } + + if (!remoteBatteryStack.equals(batteryItemStack, false)) { + remoteBatteryStack = batteryItemStack.copy() + sendNetwork(AndroidBatteryItemPacket(batteryItemStack)) + } + + if (networkQueue.size != 0) { + for (packet in networkQueue) { + AndroidNetworkChannel.send(ply, packet) + } + + networkQueue.clear() + } + + if (isAndroid != remoteIsAndroid) { + remoteIsAndroid = isAndroid + sendNetwork(IsAndroidPacket(isAndroid)) + shouldPlaySound = false + } + + if (willBecomeAndroid != willBecomeAndroidNetwork) { + willBecomeAndroidNetwork = willBecomeAndroid + sendNetwork(WillBecomeAndroidPacket(willBecomeAndroid)) + } + + for (instance in research) { + if (instance.isDirty) { + instance.isDirty = false + sendNetwork(AndroidResearchSyncPacket(instance)) + } + } + + for (instance in features.values) { + if (instance.isDirty) { + instance.isDirty = false + sendNetwork(AndroidFeatureSyncPacket(instance)) + } + } + } + + override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { + return ImpreciseFraction.ZERO + } + + override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { + @Suppress("name_shadowing") + var howMuch = howMuch + var drained = ImpreciseFraction.ZERO + + if (!batteryItemStack.isEmpty) { + batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { + if (it is IMatteryEnergyStorage) { + val extracted = it.extractEnergyOuter(howMuch, simulate) + drained += extracted + howMuch -= extracted + } else { + val extracted = it.extractEnergy(howMuch, simulate) + drained += extracted + howMuch -= extracted + } + } + + if (howMuch.isZero) { + if (!simulate && ply is ServerPlayer) { + ply.awardStat(StatNames.POWER_CONSUMED, drained.toInt() * 10) + } + + return drained + } + } + + val new = (battery - howMuch).moreThanZero() + drained += battery - new + + if (!simulate) { + battery = new + + if (ply is ServerPlayer) { + ply.awardStat(StatNames.POWER_CONSUMED, drained.toInt() * 10) + } + } + + return drained + } + + override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { + @Suppress("name_shadowing") + var howMuch = howMuch + var received = ImpreciseFraction.ZERO + + if (!batteryItemStack.isEmpty) { + batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { + if (it is IMatteryEnergyStorage) { + val extracted = it.receiveEnergyOuter(howMuch, simulate) + received += extracted + howMuch -= extracted + } else { + val extracted = it.receiveEnergy(howMuch, simulate) + received += extracted + howMuch -= extracted + } + } + + if (howMuch.isZero) { + return received + } + } + + val new = (battery + howMuch).coerceAtMost(maxBattery) + received += new - battery + + if (!simulate) { + battery = new + } + + return received + } + + override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { + return receiveEnergyOuter(howMuch, simulate) + } + + override var batteryLevel: ImpreciseFraction + get() { + if (!batteryItemStack.isEmpty) { + batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { + if (it is IMatteryEnergyStorage) { + return battery + it.batteryLevel + } else { + return battery + it.energyStored + } + } + } + + return battery + } + set(value) { + battery = value + } + + override var maxBatteryLevel: ImpreciseFraction + get() { + if (batteryItemStack != ItemStack.EMPTY) { + batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { + if (it is IMatteryEnergyStorage) { + return maxBattery + it.maxBatteryLevel + } else { + return maxBattery + it.maxEnergyStored + } + } + } + + return maxBattery + } + set(value) { + maxBattery = value + } + + private val resolver = LazyOptional.of { this } + + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { + return if (cap == MatteryCapability.ANDROID) { + resolver.cast() + } else LazyOptional.empty() + } + + @Suppress("unused") + companion object { + @JvmField + val UNAFFECTED_EFFECTS = ObjectArraySet() + + @JvmStatic + 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) + } + + @SubscribeEvent + fun onLivingTick(event: LivingTickEvent) { + val ent = event.entity + + if (ent.level.isClientSide) { + ent.getCapability(MatteryCapability.ANDROID).ifPresentK { + it.tickClient() + } + } else { + ent.getCapability(MatteryCapability.ANDROID).ifPresentK { + it.tick() + } + } + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + fun onHurtEvent(event: LivingHurtEvent) { + if (event.isCanceled) return + + event.entity.getCapability(MatteryCapability.ANDROID).ifPresentK { it.onHurt(event) } + } + + @SubscribeEvent + fun onAttachCapabilityEvent(event: AttachCapabilitiesEvent) { + val ent = event.`object` + + if (ent is Player) { + event.addCapability(MNames.ANDROID_CAPABILITY_RS, AndroidCapability(ent)) + } + } + + @SubscribeEvent + fun onPlayerChangeDimensionEvent(event: PlayerEvent.PlayerChangedDimensionEvent) { + event.entity.getCapability(MatteryCapability.ANDROID) + .ifPresentK { it.invalidateNetworkState() } + } + + @SubscribeEvent + fun onPlayerCloneEvent(event: PlayerEvent.Clone) { + val it = event.entity.android ?: return + + var resolver = event.original.getCapability(MatteryCapability.ANDROID) + + if (!resolver.isPresent || resolver.resolve().isEmpty) { + event.original.reviveCaps() + resolver = event.original.getCapability(MatteryCapability.ANDROID) + } + + if (!resolver.isPresent || resolver.resolve().isEmpty) { + event.original.invalidateCaps() + return + } + + val original = resolver.resolve().get() + + if (original.willBecomeAndroid && event.isWasDeath) { + original.becomeAndroid() + (event.entity as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false) + } + + it.deserializeNBT(original.serializeNBT()) + it.invalidateNetworkState() + event.original.invalidateCaps() + } + + val ENERGY_FOR_HUNGER_POINT = ImpreciseFraction(1000) + const val SLEEP_TICKS_LIMIT = 80 + } +} + +val ICapabilityProvider.android get() = getCapability(MatteryCapability.ANDROID).orNull() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt index 359e9d68d..7c1a09303 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/Ext.kt @@ -5,7 +5,6 @@ import net.minecraft.world.entity.LivingEntity import net.minecraftforge.common.capabilities.ForgeCapabilities import net.minecraftforge.common.capabilities.ICapabilityProvider import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.energy.CapabilityEnergy import net.minecraftforge.energy.IEnergyStorage import net.minecraftforge.fml.ModList import ru.dbotthepony.mc.otm.compat.mekanism.getMekanismEnergySided diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapability.kt deleted file mode 100644 index 58cf95285..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapability.kt +++ /dev/null @@ -1,436 +0,0 @@ -package ru.dbotthepony.mc.otm.capability.android - -import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap -import it.unimi.dsi.fastutil.objects.ObjectArraySet -import net.minecraft.core.Direction -import net.minecraft.world.entity.LivingEntity -import net.minecraftforge.common.capabilities.ICapabilityProvider -import net.minecraftforge.common.util.INBTSerializable -import net.minecraft.nbt.CompoundTag -import net.minecraft.world.item.ItemStack -import ru.dbotthepony.mc.otm.android.AndroidFeatureType -import ru.dbotthepony.mc.otm.android.AndroidFeature -import java.lang.Runnable -import net.minecraft.server.level.ServerPlayer -import net.minecraftforge.event.entity.living.LivingHurtEvent -import net.minecraft.nbt.ListTag -import net.minecraft.nbt.Tag -import net.minecraft.resources.ResourceLocation -import ru.dbotthepony.mc.otm.network.MatteryNetworking -import net.minecraftforge.network.PacketDistributor -import net.minecraft.world.effect.MobEffect -import ru.dbotthepony.mc.otm.capability.MatteryCapability -import net.minecraftforge.energy.CapabilityEnergy -import net.minecraftforge.common.util.LazyOptional -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent -import net.minecraft.world.effect.MobEffects -import net.minecraftforge.common.capabilities.Capability -import net.minecraftforge.common.capabilities.ForgeCapabilities -import net.minecraftforge.eventbus.api.SubscribeEvent -import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent -import net.minecraftforge.eventbus.api.EventPriority -import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage -import ru.dbotthepony.mc.otm.capability.extractEnergy -import ru.dbotthepony.mc.otm.capability.receiveEnergy -import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.ifHas -import ru.dbotthepony.mc.otm.ifPresentK -import ru.dbotthepony.mc.otm.network.AndroidFeatureRemovePacket -import ru.dbotthepony.mc.otm.network.AndroidFeatureSyncPacket -import ru.dbotthepony.mc.otm.network.AndroidNetworkChannel -import ru.dbotthepony.mc.otm.orNull -import ru.dbotthepony.mc.otm.registry.MRegistry -import ru.dbotthepony.mc.otm.registry.StatNames -import ru.dbotthepony.mc.otm.set -import java.util.* - -open class AndroidCapability(final override val entity: LivingEntity) : ICapabilityProvider, IAndroidCapability, INBTSerializable { - protected var battery = ImpreciseFraction.ZERO - protected var maxBattery = ImpreciseFraction(60000) - - override var batteryItemStack: ItemStack = ItemStack.EMPTY - - protected val features = Object2ObjectArrayMap, AndroidFeature>() - protected val networkQueue = ArrayList() - protected val queuedTicks = ArrayList() - protected var tickedOnce = false - - protected fun addFeature(feature: AndroidFeature): Boolean { - if (features.containsKey(feature.type)) return false - features[feature.type] = feature - - if (!entity.level.isClientSide) { - queuedTicks.add(feature::applyModifiers) - } - - if (entity is ServerPlayer) { - sendNetwork(AndroidFeatureSyncPacket(feature)) - } - - return true - } - - @Suppress("unchecked_cast") - override fun addFeature(feature: AndroidFeatureType): T { - val get = features[feature] - if (get != null) return get as T - - val factory = feature.create(this) - - features[feature] = factory - - if (!entity.level.isClientSide) { - queuedTicks.add(factory::applyModifiers) - } - - if (entity is ServerPlayer) { - sendNetwork(AndroidFeatureSyncPacket(factory)) - } - - return factory - } - - override fun removeFeature(feature: AndroidFeatureType<*>): Boolean { - val removed = features.remove(feature) - - if (removed != null) { - if (!entity.level.isClientSide) { - queuedTicks.add { - removed.removeModifiers() - } - } - - if (entity is ServerPlayer) { - sendNetwork(AndroidFeatureRemovePacket(removed.type)) - } - } - - return removed != null - } - - override fun hasFeature(feature: AndroidFeatureType<*>): Boolean { - return features.containsKey(feature) - } - - override fun hasFeatureLevel(feature: AndroidFeatureType<*>, level: Int): Boolean { - val get = features[feature] ?: return false - return get.level >= level - } - - @Suppress("unchecked_cast") - override fun getFeature(feature: AndroidFeatureType): T? { - return features[feature] as T? - } - - override fun onHurt(event: LivingHurtEvent) { - for (feature in features.values) { - feature.onHurt(event) - } - } - - override fun serializeNBT(): CompoundTag { - val tag = CompoundTag() - - tag["energy_stored"] = battery.serializeNBT() - tag["energy_stored_max"] = maxBattery.serializeNBT() - tag["battery"] = batteryItemStack.serializeNBT() - - val featureList = ListTag() - - for (feature in features.values) { - val featureNbt = feature.serializeNBT() - - featureNbt["id"] = feature.type.registryName!!.toString() - featureList.add(featureNbt) - } - - tag["features"] = featureList - return tag - } - - override fun deserializeNBT(compound: CompoundTag?) { - compound!! - - compound.ifHas("energy_stored") { - battery = ImpreciseFraction.deserializeNBT(it) - } - - compound.ifHas("energy_stored_max") { - maxBattery = ImpreciseFraction.deserializeNBT(it) - } - - compound.ifHas("battery", CompoundTag::class.java) { - batteryItemStack = ItemStack.of(it) - } - - features.clear() - - val featuresNbt = compound.getList("features", Tag.TAG_COMPOUND.toInt()) - - for (tag in featuresNbt) { - if (tag is CompoundTag) { - val feature = MRegistry.ANDROID_FEATURES.getValue(ResourceLocation(tag.getString("id"))) - - if (feature?.isApplicable(this) == true) { - val instance = feature.create(this) - - instance.deserializeNBT(tag) - addFeature(instance) - - if (!entity.level.isClientSide) { - queuedTicks.add(instance::applyModifiers) - } - } - } - } - } - - fun dropBattery() { - if (batteryItemStack.isEmpty) return - entity.spawnAtLocation(batteryItemStack) - batteryItemStack = ItemStack.EMPTY - } - - protected fun sendNetwork(packet: Any) { - if (entity is ServerPlayer) { - if (tickedOnce) { - AndroidNetworkChannel.send(entity, packet) - } else { - networkQueue.add(packet) - } - } - } - - protected open fun tickInnerClient() {} - protected open fun tickInnerClientAlways() {} - - override fun tickClient() { - queuedTicks.clear() - - if (!entity.isAlive) - return - - tickInnerClientAlways() - - if (isAndroid) { - tickInnerClient() - - for (feature in features.values) { - feature.tickClient() - } - } - } - - override fun tick() { - if (!entity.isAlive) return - - tickServerAlways() - - if (isAndroid) { - tickServer() - - for (feature in features.values) { - feature.tickServer() - } - } - - for (runnable in queuedTicks) { - runnable.run() - } - - queuedTicks.clear() - } - - protected open fun tickServerAlways() {} - - protected open fun tickServer() { - if (entity.airSupply < entity.maxAirSupply) - entity.airSupply = entity.maxAirSupply - - for (effect in UNAFFECTED_EFFECTS) - if (entity.hasEffect(effect)) - entity.removeEffect(effect) - - if (!batteryItemStack.isEmpty && battery < maxBattery) { - batteryItemStack.getCapability(CapabilityEnergy.ENERGY).ifPresent { - if (it is IMatteryEnergyStorage) { - battery += it.extractEnergyInner(maxBattery - battery, false) - } else { - battery += it.extractEnergy(maxBattery - battery, false) - } - } - } - } - - override fun extractEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { - return ImpreciseFraction.ZERO - } - - override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { - @Suppress("name_shadowing") - var howMuch = howMuch - var drained = ImpreciseFraction.ZERO - - if (!batteryItemStack.isEmpty) { - batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { - if (it is IMatteryEnergyStorage) { - val extracted = it.extractEnergyOuter(howMuch, simulate) - drained += extracted - howMuch -= extracted - } else { - val extracted = it.extractEnergy(howMuch, simulate) - drained += extracted - howMuch -= extracted - } - } - - if (howMuch.isZero) { - if (!simulate && entity is ServerPlayer) { - entity.awardStat(StatNames.POWER_CONSUMED, drained.toInt() * 10) - } - - return drained - } - } - - val new = (battery - howMuch).moreThanZero() - drained += battery - new - - if (!simulate) { - battery = new - - if (entity is ServerPlayer) { - entity.awardStat(StatNames.POWER_CONSUMED, drained.toInt() * 10) - } - } - - return drained - } - - override fun receiveEnergyOuter(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { - var howMuch = howMuch - var received = ImpreciseFraction.ZERO - - if (!batteryItemStack.isEmpty) { - batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { - if (it is IMatteryEnergyStorage) { - val extracted = it.receiveEnergyOuter(howMuch, simulate) - received += extracted - howMuch -= extracted - } else { - val extracted = it.receiveEnergy(howMuch, simulate) - received += extracted - howMuch -= extracted - } - } - - if (howMuch.isZero) { - return received - } - } - - val new = (battery + howMuch).coerceAtMost(maxBattery) - received += new - battery - - if (!simulate) { - battery = new - } - - return received - } - - override fun receiveEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction { - return receiveEnergyOuter(howMuch, simulate) - } - - override var batteryLevel: ImpreciseFraction - get() { - if (!batteryItemStack.isEmpty) { - batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { - if (it is IMatteryEnergyStorage) { - return battery + it.batteryLevel - } else { - return battery + it.energyStored - } - } - } - - return battery - } - set(value) { - battery = value - } - - override var maxBatteryLevel: ImpreciseFraction - get() { - if (batteryItemStack != ItemStack.EMPTY) { - val resolver = batteryItemStack.getCapability(ForgeCapabilities.ENERGY).ifPresentK { - if (it is IMatteryEnergyStorage) { - return maxBattery + it.maxBatteryLevel - } else { - return maxBattery + it.maxEnergyStored - } - } - } - - return maxBattery - } - set(value) { - maxBattery = value - } - - private val resolver = LazyOptional.of { this } - - override fun getCapability(cap: Capability, side: Direction?): LazyOptional { - return if (cap === MatteryCapability.ANDROID) { - resolver.cast() - } else LazyOptional.empty() - } - - @Suppress("unused") - companion object { - @JvmField - val UNAFFECTED_EFFECTS = ObjectArraySet() - - @JvmStatic - 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) - } - - @SubscribeEvent - fun onLivingTick(event: LivingTickEvent) { - val ent = event.entity - - if (ent.level.isClientSide) { - ent.getCapability(MatteryCapability.ANDROID).ifPresentK { - it.tickClient() - } - } else { - ent.getCapability(MatteryCapability.ANDROID).ifPresentK { - it.tick() - } - } - } - - @SubscribeEvent(priority = EventPriority.LOWEST) - fun onHurtEvent(event: LivingHurtEvent) { - if (event.isCanceled) return - - event.entity.getCapability(MatteryCapability.ANDROID).ifPresentK { cap: IAndroidCapability -> cap.onHurt(event) } - } - } -} - -val ICapabilityProvider.android get() = getCapability(MatteryCapability.ANDROID).orNull() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapabilityPlayer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapabilityPlayer.kt deleted file mode 100644 index 2b30c516a..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapabilityPlayer.kt +++ /dev/null @@ -1,356 +0,0 @@ -package ru.dbotthepony.mc.otm.capability.android - -import net.minecraft.ChatFormatting -import net.minecraft.nbt.CompoundTag -import net.minecraft.nbt.ListTag -import net.minecraft.nbt.Tag -import net.minecraft.resources.ResourceLocation -import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.entity.Entity -import net.minecraft.world.entity.player.Player -import net.minecraft.world.item.ItemStack -import net.minecraftforge.event.AttachCapabilitiesEvent -import net.minecraftforge.event.entity.player.PlayerEvent.Clone -import net.minecraftforge.event.entity.player.PlayerEvent.PlayerChangedDimensionEvent -import net.minecraftforge.eventbus.api.SubscribeEvent -import net.minecraftforge.network.PacketDistributor -import ru.dbotthepony.mc.otm.TranslatableComponent -import ru.dbotthepony.mc.otm.android.AndroidResearch -import ru.dbotthepony.mc.otm.android.AndroidResearchType -import ru.dbotthepony.mc.otm.capability.MatteryCapability -import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import ru.dbotthepony.mc.otm.ifPresentK -import ru.dbotthepony.mc.otm.network.* -import ru.dbotthepony.mc.otm.registry.AndroidFeatures -import ru.dbotthepony.mc.otm.registry.MNames -import ru.dbotthepony.mc.otm.registry.MRegistry -import ru.dbotthepony.mc.otm.set -import java.util.* - -class AndroidCapabilityPlayer(val ply: Player) : AndroidCapability(ply) { - override var isAndroid = false - private var remoteIsAndroid = false - - var willBecomeAndroid = false - private var willBecomeAndroidNetwork = false - private var shouldPlaySound = false - private val research = ArrayList() - - private var remoteBattery = ImpreciseFraction(-1) - private var remoteMaxBattery = ImpreciseFraction(-1) - private var remoteBatteryStack = ItemStack.EMPTY - - private var invalidateNetworkIn = 10 - - fun invalidateNetworkState() { - invalidateNetworkIn = 10 - } - - fun isEverAndroid(): Boolean = isAndroid || willBecomeAndroid - - fun becomeAndroidSoft() { - if (isAndroid || willBecomeAndroid) return - willBecomeAndroid = true - (ply as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message").withStyle(ChatFormatting.GRAY), false) - } - - fun becomeAndroid() { - if (isAndroid) return - - isAndroid = true - willBecomeAndroid = false - shouldPlaySound = false - battery = ImpreciseFraction(60000) - maxBattery = ImpreciseFraction(60000) - } - - fun becomeAndroidAndKill() { - if (isAndroid) return - - becomeAndroid() - ply.hurt(MRegistry.DAMAGE_BECOME_ANDROID, ply.maxHealth * 2) - } - - fun becomeHumane() { - if (willBecomeAndroid) willBecomeAndroid = false - if (!isAndroid) return - - isAndroid = false - shouldPlaySound = false - battery = ImpreciseFraction(0) - maxBattery = ImpreciseFraction(60000) - dropBattery() - } - - fun becomeHumaneAndKill() { - if (willBecomeAndroid) willBecomeAndroid = false - if (!isAndroid) return - - becomeHumane() - ply.hurt(MRegistry.DAMAGE_BECOME_HUMANE, ply.maxHealth * 2) - } - - override fun deserializeNBT(compound: CompoundTag?) { - super.deserializeNBT(compound!!) - - isAndroid = compound.getBoolean("is_android") - willBecomeAndroid = compound.getBoolean("will_become_android") - research.clear() - - val list = compound.getList("research", Tag.TAG_COMPOUND.toInt()) - - for (tag in list) { - if (tag is CompoundTag) { - val research = MRegistry.ANDROID_RESEARCH.getValue(ResourceLocation(tag.getString("id"))) - - if (research != null) { - val instance = research.factory(this) - instance.deserializeNBT(tag) - this.research.add(instance) - } - } - } - } - - fun obliviate(refund: Boolean = true) { - if (refund) { - for (instance in research) { - if (instance.isResearched) { - instance.unResearch() - instance.refund(simulate = false) - } - } - } - - val copy = java.util.List.copyOf(features.values) - - for (feature in copy) { - removeFeature(feature.type) - } - } - - override fun serializeNBT(): CompoundTag { - val tag = super.serializeNBT() - - tag["is_android"] = isAndroid - tag["will_become_android"] = willBecomeAndroid - - val list = ListTag() - - for (instance in research) { - val researchTag = instance.serializeNBT() - - researchTag["id"] = instance.type.registryName!!.toString() - list.add(researchTag) - } - - tag["research"] = list - return tag - } - - fun getResearch(type: AndroidResearchType): T { - for (instance in research) { - if (instance.type === type) { - return instance as T - } - } - - val instance = type.factory(this) - research.add(instance) - return instance - } - - var lastJumpTicks = 14 - - override fun tick() { - super.tick() - - if (invalidateNetworkIn > 0 && --invalidateNetworkIn == 0) { - remoteBattery = ImpreciseFraction.MINUS_ONE - remoteMaxBattery = ImpreciseFraction.MINUS_ONE - remoteBatteryStack = ItemStack.EMPTY - - remoteIsAndroid = false - willBecomeAndroidNetwork = false - - for (instance in research) { - instance.isDirty = true - instance.invalidateNetwork() - } - - for (feature in features.values) { - feature.isDirty = true - feature.invalidateNetwork() - } - } - - tickedOnce = true - - if (battery != remoteBattery) { - remoteBattery = battery - sendNetwork(AndroidEnergyLevelPacket(level = battery, isMaxEnergy = false)) - } - - if (maxBattery != remoteMaxBattery) { - remoteMaxBattery = maxBattery - sendNetwork(AndroidEnergyLevelPacket(level = maxBattery, isMaxEnergy = true)) - } - - if (!remoteBatteryStack.equals(batteryItemStack, false)) { - remoteBatteryStack = batteryItemStack.copy() - sendNetwork(AndroidBatteryItemPacket(batteryItemStack)) - } - - if (networkQueue.size != 0) { - for (packet in networkQueue) { - AndroidNetworkChannel.send(ply, packet) - } - - networkQueue.clear() - } - - if (isAndroid != remoteIsAndroid) { - remoteIsAndroid = isAndroid - sendNetwork(IsAndroidPacket(isAndroid)) - shouldPlaySound = false - } - - if (willBecomeAndroid != willBecomeAndroidNetwork) { - willBecomeAndroidNetwork = willBecomeAndroid - sendNetwork(WillBecomeAndroidPacket(willBecomeAndroid)) - } - - for (instance in research) { - if (instance.isDirty) { - instance.isDirty = false - sendNetwork(AndroidResearchSyncPacket(instance)) - } - } - - for (instance in features.values) { - if (instance.isDirty) { - instance.isDirty = false - sendNetwork(AndroidFeatureSyncPacket(instance)) - } - } - } - - var sleepTicks = 0 - - override fun tickInnerClientAlways() { - super.tickInnerClientAlways() - - if (willBecomeAndroid) { - if (ply.isSleeping) { - sleepTicks++ - } else { - sleepTicks = 0 - } - } - } - - override fun tickServerAlways() { - super.tickServerAlways() - - if (willBecomeAndroid) { - if (ply.isSleeping) { - sleepTicks++ - - if (sleepTicks > SLEEP_TICKS_LIMIT) { - becomeAndroid() - shouldPlaySound = true - sleepTicks = 0 - - (ply as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false) - } - } else { - sleepTicks = 0 - } - } - } - - public override fun tickServer() { - super.tickServer() - - // TODO: Maybe passive drain? - // extractEnergyInner(BigDecimal.valueOf(new Random().nextDouble()), false); - if (ply.isSwimming && !hasFeature(AndroidFeatures.AIR_BAGS)) { - ply.isSwimming = false - } - - val stats = ply.foodData - - while (stats.foodLevel < 18 && extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) { - extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false) - stats.foodLevel = stats.foodLevel + 1 - } - - // "block" quick regeneration - // also cause power to generate while in peaceful - while (stats.foodLevel > 18 && receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) { - receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, false) - stats.foodLevel = stats.foodLevel - 1 - } - - val foodLevel = stats.foodLevel.toFloat() - - if (stats.saturationLevel < foodLevel) { - val extracted = extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (foodLevel - stats.saturationLevel), false) - stats.setSaturation(stats.saturationLevel + (extracted / ENERGY_FOR_HUNGER_POINT).toFloat()) - } - - if (stats.exhaustionLevel > 0f) { - val extracted = extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (stats.exhaustionLevel / 4f), false) - stats.setExhaustion(stats.exhaustionLevel - (extracted / ENERGY_FOR_HUNGER_POINT).toFloat() * 4f) - } - } - - @Suppress("unused") - companion object { - @SubscribeEvent - fun onAttachCapabilityEvent(event: AttachCapabilitiesEvent) { - val ent = event.`object` - - if (ent is Player) { - event.addCapability(MNames.ANDROID_CAPABILITY_RS, AndroidCapabilityPlayer(ent)) - } - } - - @SubscribeEvent - fun onPlayerChangeDimensionEvent(event: PlayerChangedDimensionEvent) { - event.entity.getCapability(MatteryCapability.ANDROID) - .ifPresentK { (it as AndroidCapabilityPlayer).invalidateNetworkState() } - } - - @SubscribeEvent - fun onPlayerCloneEvent(event: Clone) { - val it = event.entity.android as AndroidCapabilityPlayer? ?: return - - var resolver = event.original.getCapability(MatteryCapability.ANDROID) - - if (!resolver.isPresent || resolver.resolve().isEmpty) { - event.original.reviveCaps() - resolver = event.original.getCapability(MatteryCapability.ANDROID) - } - - if (!resolver.isPresent || resolver.resolve().isEmpty) { - event.original.invalidateCaps() - return - } - - val original = resolver.resolve().get() as AndroidCapabilityPlayer - - if (original.willBecomeAndroid && event.isWasDeath) { - original.becomeAndroid() - (event.entity as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false) - } - - it.deserializeNBT(original.serializeNBT()) - it.invalidateNetworkState() - event.original.invalidateCaps() - } - - val ENERGY_FOR_HUNGER_POINT = ImpreciseFraction(1000) - const val SLEEP_TICKS_LIMIT = 80 - } -} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/IAndroidCapability.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/IAndroidCapability.kt deleted file mode 100644 index c58df17a6..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/IAndroidCapability.kt +++ /dev/null @@ -1,49 +0,0 @@ -package ru.dbotthepony.mc.otm.capability.android - -import net.minecraft.nbt.CompoundTag -import net.minecraft.world.entity.LivingEntity -import net.minecraft.world.item.ItemStack -import net.minecraftforge.common.util.INBTSerializable -import net.minecraftforge.event.entity.living.LivingHurtEvent -import ru.dbotthepony.mc.otm.android.AndroidFeature -import ru.dbotthepony.mc.otm.android.AndroidFeatureType -import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage -import ru.dbotthepony.mc.otm.core.ImpreciseFraction -import java.util.* - -interface IAndroidCapability : IMatteryEnergyStorage, INBTSerializable { - fun tick() - fun tickClient() - val entity: LivingEntity - fun addFeature(feature: AndroidFeatureType): T - fun removeFeature(feature: AndroidFeatureType<*>): Boolean - fun hasFeature(feature: AndroidFeatureType<*>): Boolean - fun hasFeatureLevel(feature: AndroidFeatureType<*>, level: Int): Boolean - - fun getFeature(feature: AndroidFeatureType): T? - - fun computeIfAbsent(feature: AndroidFeatureType): T { - return getFeature(feature) ?: addFeature(feature) - } - - fun getFeatureO(feature: AndroidFeatureType): Optional { - val get = getFeature(feature) - return if (get != null) Optional.of(get) else Optional.empty() - } - - fun ifFeature(feature: AndroidFeatureType, consumer: (T) -> Unit) { - val get = getFeature(feature) - - if (get != null) { - consumer(get) - } - } - - val isAndroid: Boolean get() = true - - fun onHurt(event: LivingHurtEvent) {} - var batteryItemStack: ItemStack - - override var batteryLevel: ImpreciseFraction - override var maxBatteryLevel: ImpreciseFraction -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidGui.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidGui.kt index 8ed8457ab..c254a68ac 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidGui.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidGui.kt @@ -19,7 +19,7 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.capability.MatteryCapability import ru.dbotthepony.mc.otm.capability.android -import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.ifPresentK import java.util.* @@ -31,7 +31,7 @@ object AndroidGui { private var knownButton: Button? = null private var knownButtonScreen: InBedChatScreen? = null - private var lastState: AndroidCapabilityPlayer? = null + private var lastState: AndroidCapability? = null private val button_shaker = Random() @@ -63,7 +63,7 @@ object AndroidGui { } minecraft.player?.getCapability(MatteryCapability.ANDROID)?.ifPresentK { - if (!(it as AndroidCapabilityPlayer).willBecomeAndroid) { + if (!it.willBecomeAndroid) { knownButton!!.x = knownButtonX knownButton!!.y = knownButtonY knownButtonX = -1 @@ -73,7 +73,7 @@ object AndroidGui { return@ifPresentK } - val dispersion = (10.0 * Math.max(0, it.sleepTicks - 20) / (AndroidCapabilityPlayer.SLEEP_TICKS_LIMIT - 20)).toInt() + val dispersion = (10.0 * Math.max(0, it.sleepTicks - 20) / (AndroidCapability.SLEEP_TICKS_LIMIT - 20)).toInt() knownButton!!.x = knownButtonX - dispersion / 2 + (button_shaker.nextDouble() * dispersion).toInt() @@ -103,7 +103,7 @@ object AndroidGui { knownButtonScreen = screen minecraft.player?.getCapability(MatteryCapability.ANDROID)?.ifPresentK { - if ((it as AndroidCapabilityPlayer).willBecomeAndroid) { + if (it.willBecomeAndroid) { knownButtonScreen = screen } } @@ -134,12 +134,9 @@ object AndroidGui { return } - val lazy = ply.android - var android: AndroidCapabilityPlayer? = null + var android = ply.android - if (lazy != null) { - android = lazy as AndroidCapabilityPlayer - } else if (!ply.isAlive) { + if (!ply.isAlive && android == null) { android = lastState } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/EventHandler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/EventHandler.kt index 3ceda0d91..d976ac5d2 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/EventHandler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/EventHandler.kt @@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.client import net.minecraftforge.client.event.MovementInputUpdateEvent import net.minecraftforge.eventbus.api.SubscribeEvent import ru.dbotthepony.mc.otm.capability.android -import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer import ru.dbotthepony.mc.otm.registry.AndroidFeatures @SubscribeEvent @@ -12,7 +11,7 @@ fun inputEvent(event: MovementInputUpdateEvent) { val ply = event.entity val input = event.input - val cap = ply.android as? AndroidCapabilityPlayer ?: return + val cap = ply.android ?: return if (cap.hasFeature(AndroidFeatures.AIR_BAGS)) return diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/BlackHoleRenderer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/BlackHoleRenderer.kt index c25f5a5bc..eed45ed1c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/BlackHoleRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/BlackHoleRenderer.kt @@ -14,8 +14,7 @@ import org.lwjgl.opengl.GL30 import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.BlackHoleBlockEntity -import ru.dbotthepony.mc.otm.capability.MatteryCapability -import ru.dbotthepony.mc.otm.capability.android.android +import ru.dbotthepony.mc.otm.capability.android import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.registry.MItems import kotlin.math.PI diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt index 1590e1d49..631759cf3 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/AndroidStationScreen.kt @@ -11,13 +11,13 @@ import net.minecraft.world.entity.player.Inventory import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.android.AndroidResearch import ru.dbotthepony.mc.otm.android.AndroidResearchType +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability -import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer -import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability import ru.dbotthepony.mc.otm.client.render.RenderHelper import ru.dbotthepony.mc.otm.client.screen.panels.* import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel import ru.dbotthepony.mc.otm.core.RGBAColor +import ru.dbotthepony.mc.otm.ifPresentK import ru.dbotthepony.mc.otm.menu.AndroidStationMenu import ru.dbotthepony.mc.otm.network.AndroidNetworkChannel import ru.dbotthepony.mc.otm.network.AndroidResearchRequestPacket @@ -43,29 +43,27 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I override fun innerRender(stack: PoseStack, mouse_x: Float, mouse_y: Float, flag: Float) { ru.dbotthepony.mc.otm.client.minecraft.player!!.getCapability(MatteryCapability.ANDROID) - .ifPresent { _cap: IAndroidCapability? -> - if (_cap is AndroidCapabilityPlayer) { - if (node.isResearched) { - RESEARCHED.setSystemColor() - } else if (node.canResearch) { - CAN_BE_RESEARCHED.setSystemColor() - } else { - CAN_NOT_BE_RESEARCHED.setSystemColor() - } + .ifPresentK { + if (node.isResearched) { + RESEARCHED.setSystemColor() + } else if (node.canResearch) { + CAN_BE_RESEARCHED.setSystemColor() + } else { + CAN_NOT_BE_RESEARCHED.setSystemColor() + } - val icon = node.skinIcon + val icon = node.skinIcon - if (icon != null) { - icon.render(stack, 0f, 0f, width, height) - } else { - RenderHelper.drawRect(stack, 0f, 0f, width, height) - } + if (icon != null) { + icon.render(stack, 0f, 0f, width, height) + } else { + RenderHelper.drawRect(stack, 0f, 0f, width, height) + } - val text = node.iconText + val text = node.iconText - if (text != null) { - font.drawShadow(stack, text, width - font.width(text), height - font.lineHeight, -0x1) - } + if (text != null) { + font.drawShadow(stack, text, width - font.width(text), height - font.lineHeight, -0x1) } } } @@ -108,7 +106,7 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I private val createdButtons = Array(100) { arrayOfNulls(1000) } private val createdButtonsIdx = IntArray(100) - private fun dive(cap: AndroidCapabilityPlayer, research: AndroidResearchType<*>, level: Int) { + private fun dive(cap: AndroidCapability, research: AndroidResearchType<*>, level: Int) { if (seen.contains(research)) return seen.add(research) @@ -156,14 +154,11 @@ class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: I } minecraft?.player?.getCapability(MatteryCapability.ANDROID)?.ifPresent { - if (it !is AndroidCapabilityPlayer) - return@ifPresent - Arrays.fill(rows, null) nextX = 0f for (research in MRegistry.ANDROID_RESEARCH.values) { - if (research.definedPrerequisites.size == 0) { + if (research.definedPrerequisites.isEmpty()) { dive(it, research, 0) var max = 0f diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/PillItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/PillItem.kt index ce792ed64..7d7a1833c 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/PillItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/PillItem.kt @@ -15,7 +15,7 @@ import net.minecraftforge.common.util.FakePlayer import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.TranslatableComponent import ru.dbotthepony.mc.otm.capability.MatteryCapability -import ru.dbotthepony.mc.otm.capability.android.AndroidCapabilityPlayer +import ru.dbotthepony.mc.otm.capability.AndroidCapability enum class PillType { BECOME_ANDROID, BECOME_HUMANE, OBLIVION @@ -98,14 +98,14 @@ class PillItem(val pillType: PillType) : val resolver = ply.getCapability(MatteryCapability.ANDROID).resolve() - if (resolver.isEmpty || resolver.get() !is AndroidCapabilityPlayer) + if (resolver.isEmpty) return super.use(level, ply, hand) - val cap = resolver.get() as AndroidCapabilityPlayer + val cap = resolver.get() if ( - pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid() || - pillType == PillType.BECOME_HUMANE && cap.isEverAndroid() || + pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid || + pillType == PillType.BECOME_HUMANE && cap.isEverAndroid || pillType == PillType.OBLIVION && cap.isAndroid ) { ply.startUsingItem(hand) @@ -122,10 +122,10 @@ class PillItem(val pillType: PillType) : if (ent is Player) { val resolver = ent.getCapability(MatteryCapability.ANDROID).resolve() - if (resolver.isEmpty || resolver.get() !is AndroidCapabilityPlayer) + if (resolver.isEmpty) return super.finishUsingItem(stack, level, ent) - val cap = resolver.get() as AndroidCapabilityPlayer + val cap = resolver.get() if (pillType == PillType.OBLIVION && cap.isAndroid) { if (!ent.abilities.instabuild) { @@ -136,7 +136,7 @@ class PillItem(val pillType: PillType) : cap.obliviate() ent.displayClientMessage(TranslatableComponent("otm.pill.message_oblivion").withStyle(ChatFormatting.GRAY), false) } - } else if (pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid()) { + } else if (pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid) { if (ent.abilities.instabuild) { if (ent is ServerPlayer) { cap.becomeAndroid() @@ -148,7 +148,7 @@ class PillItem(val pillType: PillType) : cap.becomeAndroidSoft() } } - } else if (pillType == PillType.BECOME_HUMANE && cap.isEverAndroid()) { + } else if (pillType == PillType.BECOME_HUMANE && cap.isEverAndroid) { if (ent.abilities.instabuild) { if (ent is ServerPlayer) { cap.becomeHumane() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt index 7a2068402..222c18f00 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.kt @@ -6,12 +6,12 @@ import net.minecraft.world.entity.player.Player import net.minecraft.world.inventory.Slot import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.block.entity.AndroidStationBlockEntity +import ru.dbotthepony.mc.otm.capability.AndroidCapability import ru.dbotthepony.mc.otm.capability.MatteryCapability -import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability import ru.dbotthepony.mc.otm.registry.MMenus -private class AndroidStationContainer(val player: Player) : SimpleContainer(1) { - var android: IAndroidCapability? = null +private class AndroidStationContainer(player: Player) : SimpleContainer(1) { + var android: AndroidCapability? = null init { player.getCapability(MatteryCapability.ANDROID).ifPresent { @@ -22,7 +22,7 @@ private class AndroidStationContainer(val player: Player) : SimpleContainer(1) { } private class AndroidBatterySlot(container: AndroidStationContainer, index: Int) : BatterySlot(container, index) { - val android: IAndroidCapability? = container.android + val android: AndroidCapability? = container.android override fun set(stack: ItemStack) { super.set(stack) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/AndroidNetworking.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/AndroidNetworking.kt index 2abee51d9..9540a03f7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/AndroidNetworking.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/AndroidNetworking.kt @@ -10,6 +10,8 @@ import ru.dbotthepony.mc.otm.android.AndroidFeature import ru.dbotthepony.mc.otm.android.AndroidFeatureType import ru.dbotthepony.mc.otm.android.AndroidResearch import ru.dbotthepony.mc.otm.android.AndroidResearchType +import ru.dbotthepony.mc.otm.capability.AndroidCapability +import ru.dbotthepony.mc.otm.capability.android import ru.dbotthepony.mc.otm.capability.android.* import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.core.ImpreciseFraction @@ -24,24 +26,24 @@ import java.util.function.Supplier sealed class AndroidStatusPacket : MatteryPacket { override fun write(buff: FriendlyByteBuf) {} - protected abstract fun play(capability: AndroidCapabilityPlayer) + protected abstract fun play(capability: AndroidCapability) override fun play(context: Supplier) { context.get().packetHandled = true context.get().enqueueWork { - play(minecraft.player?.android as? AndroidCapabilityPlayer ?: return@enqueueWork) + play(minecraft.player?.android ?: return@enqueueWork) } } } object IsAndroidPacket : AndroidStatusPacket() { - override fun play(capability: AndroidCapabilityPlayer) { + override fun play(capability: AndroidCapability) { capability.isAndroid = true } } object IsNotAndroidPacket : AndroidStatusPacket() { - override fun play(capability: AndroidCapabilityPlayer) { + override fun play(capability: AndroidCapability) { capability.isAndroid = false } } @@ -49,13 +51,13 @@ object IsNotAndroidPacket : AndroidStatusPacket() { fun IsAndroidPacket(status: Boolean) = if (status) IsAndroidPacket else IsNotAndroidPacket object WillBecomeAndroidPacket : AndroidStatusPacket() { - override fun play(capability: AndroidCapabilityPlayer) { + override fun play(capability: AndroidCapability) { capability.willBecomeAndroid = true } } object WillNotBecomeAndroidPacket : AndroidStatusPacket() { - override fun play(capability: AndroidCapabilityPlayer) { + override fun play(capability: AndroidCapability) { capability.willBecomeAndroid = false } } @@ -71,7 +73,7 @@ class AndroidResearchRequestPacket(val type: AndroidResearchType<*>) : MatteryPa context.get().packetHandled = true context.get().enqueueWork { val ply = context.get().sender ?: return@enqueueWork - val android = ply.android as? AndroidCapabilityPlayer ?: return@enqueueWork + val android = ply.android ?: return@enqueueWork if (!android.isAndroid || ply.containerMenu !is AndroidStationMenu) return@enqueueWork @@ -107,7 +109,7 @@ class AndroidResearchSyncPacket(val type: AndroidResearchType<*>, val dataList: context.get().packetHandled = true context.get().enqueueWork { - val android = minecraft.player?.android as? AndroidCapabilityPlayer ?: return@enqueueWork + val android = minecraft.player?.android ?: return@enqueueWork android.getResearch(type).readNetwork(ByteArrayInputStream(dataBytes)) } @@ -137,7 +139,7 @@ class AndroidFeatureSyncPacket(val type: AndroidFeatureType<*>, val dataList: Fa context.get().packetHandled = true context.get().enqueueWork { - val android = minecraft.player?.android as? AndroidCapabilityPlayer ?: return@enqueueWork + val android = minecraft.player?.android ?: return@enqueueWork android.computeIfAbsent(type).readNetwork(ByteArrayInputStream(dataBytes)) } @@ -161,7 +163,7 @@ class AndroidFeatureRemovePacket(val type: AndroidFeatureType<*>) : MatteryPacke override fun play(context: Supplier) { context.get().packetHandled = true context.get().enqueueWork { - val android = minecraft.player?.android as? AndroidCapabilityPlayer ?: return@enqueueWork + val android = minecraft.player?.android ?: return@enqueueWork android.removeFeature(type) } @@ -182,7 +184,7 @@ class AndroidBatteryItemPacket(val item: ItemStack) : MatteryPacket { override fun play(context: Supplier) { context.get().packetHandled = true context.get().enqueueWork { - val android = minecraft.player?.android as? AndroidCapabilityPlayer ?: return@enqueueWork + val android = minecraft.player?.android ?: return@enqueueWork android.batteryItemStack = item } @@ -204,7 +206,7 @@ class AndroidEnergyLevelPacket(val level: ImpreciseFraction, val isMaxEnergy: Bo override fun play(context: Supplier) { context.get().packetHandled = true context.get().enqueueWork { - val android = minecraft.player?.android as? AndroidCapabilityPlayer ?: return@enqueueWork + val android = minecraft.player?.android ?: return@enqueueWork if (isMaxEnergy) { android.maxBatteryLevel = level