Merge android capability into rigid single class
since it is relevant only for player anyway
This commit is contained in:
parent
589d3a5499
commit
c24176374c
@ -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);
|
||||
|
@ -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<IMatteryEnergyStorage> ENERGY = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final Capability<IAndroidCapability> ANDROID = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final Capability<AndroidCapability> ANDROID = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final Capability<IMatterHandler> MATTER = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final Capability<IMatterGraphNode> MATTER_NODE = CapabilityManager.get(new CapabilityToken<>() {});
|
||||
public static final Capability<IPatternStorage> 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);
|
||||
|
@ -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<CompoundTag> {
|
||||
val entity get() = android.entity
|
||||
val entity get() = android.ply
|
||||
|
||||
/**
|
||||
* Whenever there are changes to network
|
||||
|
@ -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
|
||||
|
||||
|
@ -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<CompoundTag> {
|
||||
abstract class AndroidResearch(val type: AndroidResearchType<*>, val capability: AndroidCapability) : INBTSerializable<CompoundTag> {
|
||||
var isResearched = false
|
||||
protected set
|
||||
|
||||
|
@ -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<R : AndroidResearch> {
|
||||
fun factory(type: AndroidResearchType<*>, capability: AndroidCapabilityPlayer): R
|
||||
fun factory(type: AndroidResearchType<*>, capability: AndroidCapability): R
|
||||
}
|
||||
|
||||
private fun findPrerequisites(
|
||||
@ -173,7 +173,7 @@ open class AndroidResearchType<R : AndroidResearch>(
|
||||
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)
|
||||
|
@ -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.*
|
||||
|
||||
|
@ -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.*
|
||||
|
||||
|
@ -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.*
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.*
|
||||
|
||||
|
@ -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<CompoundTag> {
|
||||
private var battery = ImpreciseFraction.ZERO
|
||||
private var maxBattery = ImpreciseFraction(60000)
|
||||
|
||||
var batteryItemStack: ItemStack = ItemStack.EMPTY
|
||||
|
||||
private val features = Object2ObjectArrayMap<AndroidFeatureType<*>, AndroidFeature>()
|
||||
private val networkQueue = ArrayList<Any>()
|
||||
private val queuedTicks = ArrayList<Runnable>()
|
||||
private var tickedOnce = false
|
||||
|
||||
private var willBecomeAndroidNetwork = false
|
||||
private var shouldPlaySound = false
|
||||
private val research = ArrayList<AndroidResearch>()
|
||||
|
||||
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 <T : AndroidResearch> getResearch(type: AndroidResearchType<T>): 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 <T : AndroidFeature> addFeature(feature: AndroidFeatureType<T>): 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 <T : AndroidFeature> getFeature(feature: AndroidFeatureType<T>): T? {
|
||||
return features[feature] as T?
|
||||
}
|
||||
|
||||
fun onHurt(event: LivingHurtEvent) {
|
||||
for (feature in features.values) {
|
||||
feature.onHurt(event)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : AndroidFeature> computeIfAbsent(feature: AndroidFeatureType<T>): T {
|
||||
return getFeature(feature) ?: addFeature(feature)
|
||||
}
|
||||
|
||||
fun <T : AndroidFeature> getFeatureO(feature: AndroidFeatureType<T>): Optional<T> {
|
||||
val get = getFeature(feature)
|
||||
return if (get != null) Optional.of(get) else Optional.empty()
|
||||
}
|
||||
|
||||
fun <T : AndroidFeature> ifFeature(feature: AndroidFeatureType<T>, 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 <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||
return if (cap == MatteryCapability.ANDROID) {
|
||||
resolver.cast()
|
||||
} else LazyOptional.empty()
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
companion object {
|
||||
@JvmField
|
||||
val UNAFFECTED_EFFECTS = ObjectArraySet<MobEffect>()
|
||||
|
||||
@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<Entity?>) {
|
||||
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()
|
@ -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
|
||||
|
@ -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<CompoundTag> {
|
||||
protected var battery = ImpreciseFraction.ZERO
|
||||
protected var maxBattery = ImpreciseFraction(60000)
|
||||
|
||||
override var batteryItemStack: ItemStack = ItemStack.EMPTY
|
||||
|
||||
protected val features = Object2ObjectArrayMap<AndroidFeatureType<*>, AndroidFeature>()
|
||||
protected val networkQueue = ArrayList<Any>()
|
||||
protected val queuedTicks = ArrayList<Runnable>()
|
||||
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 <T : AndroidFeature> addFeature(feature: AndroidFeatureType<T>): 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 <T : AndroidFeature> getFeature(feature: AndroidFeatureType<T>): 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 <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||
return if (cap === MatteryCapability.ANDROID) {
|
||||
resolver.cast()
|
||||
} else LazyOptional.empty()
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
companion object {
|
||||
@JvmField
|
||||
val UNAFFECTED_EFFECTS = ObjectArraySet<MobEffect>()
|
||||
|
||||
@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()
|
@ -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<AndroidResearch>()
|
||||
|
||||
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 <T : AndroidResearch> getResearch(type: AndroidResearchType<T>): 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<Entity?>) {
|
||||
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
|
||||
}
|
||||
}
|
@ -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<CompoundTag> {
|
||||
fun tick()
|
||||
fun tickClient()
|
||||
val entity: LivingEntity
|
||||
fun <T : AndroidFeature> addFeature(feature: AndroidFeatureType<T>): T
|
||||
fun removeFeature(feature: AndroidFeatureType<*>): Boolean
|
||||
fun hasFeature(feature: AndroidFeatureType<*>): Boolean
|
||||
fun hasFeatureLevel(feature: AndroidFeatureType<*>, level: Int): Boolean
|
||||
|
||||
fun <T : AndroidFeature> getFeature(feature: AndroidFeatureType<T>): T?
|
||||
|
||||
fun <T : AndroidFeature> computeIfAbsent(feature: AndroidFeatureType<T>): T {
|
||||
return getFeature(feature) ?: addFeature(feature)
|
||||
}
|
||||
|
||||
fun <T : AndroidFeature> getFeatureO(feature: AndroidFeatureType<T>): Optional<T> {
|
||||
val get = getFeature(feature)
|
||||
return if (get != null) Optional.of(get) else Optional.empty()
|
||||
}
|
||||
|
||||
fun <T : AndroidFeature> ifFeature(feature: AndroidFeatureType<T>, 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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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<AndroidResearchButton>(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
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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<NetworkEvent.Context>) {
|
||||
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<NetworkEvent.Context>) {
|
||||
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<NetworkEvent.Context>) {
|
||||
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<NetworkEvent.Context>) {
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user