From 9efb4d6176693b836b5a2562b7a8658b71df780c Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 31 Dec 2021 18:09:16 +0700 Subject: [PATCH] Move Android capability to kotlin and fix issues along the way --- .../mc/otm/OverdriveThatMatters.java | 4 +- .../capability/android/AndroidCapability.kt | 731 ++++++++---------- .../android/AndroidCapabilityPlayer.kt | 431 +++++------ .../capability/android/IAndroidCapability.kt | 78 +- .../otm/client/screen/AndroidStationScreen.kt | 4 +- .../ru/dbotthepony/mc/otm/item/ItemPill.kt | 6 +- 6 files changed, 548 insertions(+), 706 deletions(-) diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index b30db5e4e..cbe1d0de0 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -126,8 +126,8 @@ public class OverdriveThatMatters { // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); - MinecraftForge.EVENT_BUS.register(AndroidCapabilityPlayer.class); - MinecraftForge.EVENT_BUS.register(AndroidCapability.class); + MinecraftForge.EVENT_BUS.register(AndroidCapabilityPlayer.Companion); + MinecraftForge.EVENT_BUS.register(AndroidCapability.Companion); MinecraftForge.EVENT_BUS.register(MatterRegistry.class); MinecraftForge.EVENT_BUS.register(BlockEntityBlackHole.BlackHoleExplosionQueue.class); 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 index 34fae34fe..c07f12793 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapability.kt @@ -1,586 +1,479 @@ -package ru.dbotthepony.mc.otm.capability.android; +package ru.dbotthepony.mc.otm.capability.android -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.Direction; -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.effect.MobEffect; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.energy.CapabilityEnergy; -import net.minecraftforge.energy.IEnergyStorage; -import net.minecraftforge.event.entity.living.LivingEvent; -import net.minecraftforge.event.entity.living.LivingHurtEvent; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.minecraftforge.network.PacketDistributor; -import ru.dbotthepony.mc.otm.Registry; -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.capability.MatteryCapability; -import ru.dbotthepony.mc.otm.core.Fraction; -import ru.dbotthepony.mc.otm.network.MatteryNetworking; -import ru.dbotthepony.mc.otm.network.android.AndroidBatteryPacket; -import ru.dbotthepony.mc.otm.network.android.AndroidEnergyPacket; -import ru.dbotthepony.mc.otm.network.android.AndroidFeaturePacket; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; -import java.util.*; +import net.minecraft.MethodsReturnNonnullByDefault +import net.minecraft.core.Direction +import javax.annotation.ParametersAreNonnullByDefault +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 ru.dbotthepony.mc.otm.network.android.AndroidFeaturePacket +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 ru.dbotthepony.mc.otm.network.android.AndroidEnergyPacket +import ru.dbotthepony.mc.otm.network.android.AndroidBatteryPacket +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.eventbus.api.SubscribeEvent +import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent +import net.minecraftforge.eventbus.api.EventPriority +import ru.dbotthepony.mc.otm.Registry +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.Fraction +import ru.dbotthepony.mc.otm.ifHas +import ru.dbotthepony.mc.otm.set +import java.util.* @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class AndroidCapability implements ICapabilityProvider, IAndroidCapability, INBTSerializable { - protected final LivingEntity ent; - protected Fraction energy_stored = Fraction.ZERO; - protected Fraction energy_stored_max = new Fraction(60_000); - protected ItemStack battery = ItemStack.EMPTY; +open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapabilityProvider, IAndroidCapability, INBTSerializable { + @JvmField + protected var energy_stored = Fraction.ZERO + @JvmField + protected var energy_stored_max = Fraction(60000) - private Fraction network_energy = new Fraction(-1); - private Fraction network_energy_max = new Fraction(-1); - private ItemStack network_battery = ItemStack.EMPTY; + override var batteryItemStack = ItemStack.EMPTY - protected final Map, AndroidFeature> features = new HashMap<>(); - protected final ArrayList network_queue = new ArrayList<>(); + private var network_energy = Fraction(-1) + private var network_energy_max = Fraction(-1) + private var network_battery = ItemStack.EMPTY - protected final ArrayList delayed_tick_server = new ArrayList<>(); - - protected boolean network_first = false; - - protected boolean addFeature(AndroidFeature feature) { - if (features.containsKey(feature.type)) - return false; - - features.put(feature.type, feature); + @JvmField protected val features: MutableMap?, AndroidFeature> = HashMap() + @JvmField protected val network_queue = ArrayList() + @JvmField protected val delayed_tick_server = ArrayList() + @JvmField protected var network_first = false + protected fun addFeature(feature: AndroidFeature): Boolean { + if (features.containsKey(feature.type)) return false + features[feature.type] = feature if (!ent.level.isClientSide) { - delayed_tick_server.add(feature::applyModifiers); + delayed_tick_server.add(Runnable { feature.applyModifiers() }) } - - if (ent instanceof ServerPlayer ply) { - sendNetwork(new AndroidFeaturePacket(true, feature)); + if (ent is ServerPlayer) { + sendNetwork(AndroidFeaturePacket(true, feature)) } - - return true; + return true } - @Override - @SuppressWarnings("unchecked") - public T addFeature(@Nonnull AndroidFeatureType feature) { - var get = features.get(feature); + override fun addFeature(feature: AndroidFeatureType): T { + val get = features[feature] + if (get != null) return get as T - if (get != null) - return (T) get; + val factory = feature.factory(this) - var factory = feature.factory(this); - features.put(feature, factory); + features[feature] = factory if (!ent.level.isClientSide) { - delayed_tick_server.add(factory::applyModifiers); + delayed_tick_server.add(Runnable { factory!!.applyModifiers() }) } - if (ent instanceof ServerPlayer ply) { - sendNetwork(new AndroidFeaturePacket(true, factory)); + if (ent is ServerPlayer) { + sendNetwork(AndroidFeaturePacket(true, factory)) } - return factory; + return factory } - @Override - public boolean removeFeature(@Nonnull AndroidFeatureType feature) { - var removed = features.remove(feature); + override fun removeFeature(feature: AndroidFeatureType<*>): Boolean { + val removed = features.remove(feature) if (removed != null) { if (!ent.level.isClientSide) { - delayed_tick_server.add(removed::removeModifiers); + delayed_tick_server.add { removed.removeModifiers() } } - if (ent instanceof ServerPlayer ply) { - sendNetwork(new AndroidFeaturePacket(false, removed)); + if (ent is ServerPlayer) { + sendNetwork(AndroidFeaturePacket(false, removed)) } - return true; + return true } - return false; + return false } - @Override - public boolean hasFeature(@Nullable AndroidFeatureType feature) { - return features.containsKey(feature); + override fun hasFeature(feature: AndroidFeatureType<*>): Boolean { + return features.containsKey(feature) } - @Override - public boolean hasFeatureLevel(@Nullable AndroidFeatureType feature, int level) { - var get = features.get(feature); - - if (get == null) { - return false; - } - - return get.getLevel() >= level; + override fun hasFeatureLevel(feature: AndroidFeatureType<*>, level: Int): Boolean { + val get = features[feature] ?: return false + return get.level >= level } - @Nullable - @SuppressWarnings("unchecked") - public T getFeature(AndroidFeatureType feature) { - return (T) features.get(feature); + override fun getFeature(feature: AndroidFeatureType): T? { + return features[feature] as T? } - public static final Set UNAFFECTED_EFFECTS = new HashSet<>(); + override fun invalidateNetworkState() { + network_energy = Fraction.MINUS_ONE + network_energy_max = Fraction.MINUS_ONE + network_battery = ItemStack.EMPTY - public static void registerEffects(final FMLCommonSetupEvent event) { - 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); - } - - @Override - public void invalidateNetworkState() { - network_energy = Fraction.MINUS_ONE; - network_energy_max = Fraction.MINUS_ONE; - network_battery = ItemStack.EMPTY; - - if (ent instanceof ServerPlayer ply) { - for (var feature : features.values()) { - sendNetwork(new AndroidFeaturePacket(true, feature)); - feature.invalidateNetwork(); + if (ent is ServerPlayer) { + for (feature in features.values) { + sendNetwork(AndroidFeaturePacket(true, feature)) + feature.invalidateNetwork() } } } - @Override - public void setEnergy(Fraction value) { - energy_stored = value; + override fun setEnergy(value: Fraction?) { + energy_stored = value!! } - @Override - public void setMaxEnergy(Fraction value) { - energy_stored_max = value; + override fun setMaxEnergy(value: Fraction?) { + energy_stored_max = value!! } - public AndroidCapability(LivingEntity ent) { - this.ent = ent; - } - - @SubscribeEvent - @SuppressWarnings("unused") - public static void onLivingTick(LivingEvent.LivingUpdateEvent event) { - var ent = event.getEntity(); - ent.getCapability(MatteryCapability.ANDROID).ifPresent(ent.level.isClientSide ? IAndroidCapability::tickClient : IAndroidCapability::tick); - } - - @SubscribeEvent(priority = EventPriority.LOWEST) - @SuppressWarnings("unused") - public static void onHurtEvent(LivingHurtEvent event) { - if (event.isCanceled()) - return; - - var ent = event.getEntity(); - ent.getCapability(MatteryCapability.ANDROID).ifPresent((cap) -> cap.onHurt(event)); - } - - public void onHurt(LivingHurtEvent event) { - for (var feature : features.values()) { - feature.onHurt(event); + override fun onHurt(event: LivingHurtEvent?) { + for (feature in features.values) { + feature.onHurt(event) } } - @Override - @Nonnull - public CompoundTag serializeNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString("energy_stored", energy_stored.toString()); - tag.putString("energy_stored_max", energy_stored_max.toString()); - tag.put("battery", battery.serializeNBT()); + override fun serializeNBT(): CompoundTag { + val tag = CompoundTag() - var features_nbt = new ListTag(); + tag["energy_stored"] = energy_stored.serializeNBT() + tag["energy_stored_max"] = energy_stored_max.serializeNBT() + tag["battery"] = batteryItemStack.serializeNBT() - for (var feature : features.values()) { - var compound = new CompoundTag(); - feature.serializeNBT(compound); - compound.putString("id", Objects.requireNonNull(feature.type.getRegistryName()).toString()); - features_nbt.add(compound); + val featureList = ListTag() + + for (feature in features.values) { + val featureNbt = CompoundTag() + feature.serializeNBT(featureNbt) + + featureNbt["id"] = feature.type.registryName!!.toString() + featureList.add(featureNbt) } - tag.put("features", features_nbt); - - return tag; + tag["features"] = featureList + return tag } - @Override - public void deserializeNBT(CompoundTag compound) { - if (compound.contains("energy_stored")) - energy_stored = Fraction.deserializeNBT(compound.get("energy_stored")); + override fun deserializeNBT(compound: CompoundTag?) { + compound!! - if (compound.contains("energy_stored_max")) - energy_stored_max = Fraction.deserializeNBT(compound.get("energy_stored_max")); + compound.ifHas("energy_stored") { + energy_stored = Fraction.deserializeNBT(it) + } - if (compound.contains("battery")) - battery = ItemStack.of(compound.getCompound("battery")); + compound.ifHas("energy_stored_max") { + energy_stored_max = Fraction.deserializeNBT(it) + } - features.clear(); + compound.ifHas("battery", CompoundTag::class.java) { + batteryItemStack = ItemStack.of(it) + } - var features_nbt = compound.getList("features", Tag.TAG_COMPOUND); + features.clear() - for (var _tag : features_nbt) { - if (_tag instanceof CompoundTag tag) { - var get_feature = Registry.ANDROID_FEATURES.getValue(new ResourceLocation(tag.getString("id"))); + val featuresNbt = compound.getList("features", Tag.TAG_COMPOUND.toInt()) - if (get_feature != null && get_feature.isApplicable(this)) { - var feature = get_feature.factory(this); - feature.deserializeNBT(tag); + for (tag in featuresNbt) { + if (tag is CompoundTag) { + val feature = Registry.ANDROID_FEATURES.getValue(ResourceLocation(tag.getString("id"))) - addFeature(feature); + if (feature != null && feature.isApplicable(this)) { + val feature = feature.factory(this) - if (ent.level == null || !ent.level.isClientSide) { - delayed_tick_server.add(feature::applyModifiers); + feature.deserializeNBT(tag) + addFeature(feature) + + if (!ent.level.isClientSide) { + delayed_tick_server.add(Runnable { feature.applyModifiers() }) } } } } } - public void dropBattery() { - if (battery.isEmpty()) - return; - - ent.spawnAtLocation(battery); - battery = ItemStack.EMPTY; + fun dropBattery() { + if (batteryItemStack.isEmpty) return + ent.spawnAtLocation(batteryItemStack) + batteryItemStack = ItemStack.EMPTY } - protected void sendNetwork(Object packet) { - if (ent instanceof ServerPlayer ply) { + protected fun sendNetwork(packet: Any) { + if (ent is ServerPlayer) { if (network_first) { - MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with(() -> ply), packet); + MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with { ent }, packet) } else { - network_queue.add(packet); + network_queue.add(packet) } } } - protected void tickNetwork() { - network_first = true; + protected open fun tickNetwork() { + network_first = true - if (ent instanceof ServerPlayer ply) { - if (!energy_stored.equals(network_energy)) { - network_energy = energy_stored; - sendNetwork(new AndroidEnergyPacket(false, energy_stored)); + if (ent is ServerPlayer) { + if (energy_stored != network_energy) { + network_energy = energy_stored + sendNetwork(AndroidEnergyPacket(false, energy_stored)) } - if (!energy_stored_max.equals(network_energy_max)) { - network_energy_max = energy_stored_max; - sendNetwork(new AndroidEnergyPacket(true, energy_stored_max)); + if (energy_stored_max != network_energy_max) { + network_energy_max = energy_stored_max + sendNetwork(AndroidEnergyPacket(true, energy_stored_max)) } - if (!network_battery.equals(battery, false)) { - network_battery = battery.copy(); - sendNetwork(new AndroidBatteryPacket(battery)); + if (!network_battery.equals(batteryItemStack, false)) { + network_battery = batteryItemStack.copy() + sendNetwork(AndroidBatteryPacket(batteryItemStack)) } - if (network_queue.size() != 0) { - for (var packet : network_queue) { - MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with(() -> ply), packet); + if (network_queue.size != 0) { + for (packet in network_queue) { + MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with {ent}, packet) } - network_queue.clear(); + network_queue.clear() } } } - protected void tickInnerClient() { - - } - - protected void tickInnerClientAlways() { - - } - - @Override - public void tickClient() { - delayed_tick_server.clear(); - - if (!ent.isAlive()) - return; - - tickInnerClientAlways(); + protected open fun tickInnerClient() {} + protected open fun tickInnerClientAlways() {} + override fun tickClient() { + delayed_tick_server.clear() + if (!ent.isAlive) return + tickInnerClientAlways() if (isAndroid()) { - tickInnerClient(); - - for (var feature : features.values()) { - feature.tickClient(); + tickInnerClient() + for (feature in features.values) { + feature.tickClient() } } } - @Override - public void tick() { - if (!ent.isAlive()) - return; - - tickServerAlways(); - + override fun tick() { + if (!ent.isAlive) return + tickServerAlways() if (isAndroid()) { - tickServer(); - - for (var feature : features.values()) { - feature.tickServer(); + tickServer() + for (feature in features.values) { + feature.tickServer() } } - - for (var runnable : delayed_tick_server) { - runnable.run(); + for (runnable in delayed_tick_server) { + runnable.run() } - - delayed_tick_server.clear(); - tickNetwork(); + delayed_tick_server.clear() + tickNetwork() } - protected void tickServerAlways() { + protected open fun tickServerAlways() {} - } + protected open fun tickServer() { + if (ent.airSupply < ent.maxAirSupply) + ent.airSupply = ent.maxAirSupply - protected void tickServer() { - if (ent.getAirSupply() < ent.getMaxAirSupply()) - ent.setAirSupply(ent.getMaxAirSupply()); - - for (var effect : UNAFFECTED_EFFECTS) + for (effect in UNAFFECTED_EFFECTS) if (ent.hasEffect(effect)) - ent.removeEffect(effect); + ent.removeEffect(effect) - if (!battery.isEmpty()) { - Fraction demand = energy_stored_max.minus(energy_stored); - - if (demand.compareTo(Fraction.ZERO) > 0) { - Optional get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve(); - - if (get_mattery.isPresent()) { - demand = demand.minus(get_mattery.get().extractEnergyInner(demand, false)); + if (!batteryItemStack.isEmpty && energy_stored < energy_stored_max) { + batteryItemStack.getCapability(CapabilityEnergy.ENERGY).ifPresent { + if (it is IMatteryEnergyStorage) { + energy_stored += it.extractEnergyInner(energy_stored_max - energy_stored, false) + } else { + energy_stored += it.extractEnergy(energy_stored_max - energy_stored, false) } - - if (demand.compareTo(Fraction.ONE) >= 0) { - Optional get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve(); - - if (get_energy.isPresent()) { - demand = demand.minus(MatteryCapability.drainFE(get_energy.get(), demand, false)); - } - } - - energy_stored = energy_stored_max.minus(demand); } } } - @Nonnull - @Override - public Fraction extractEnergyOuter(Fraction howMuch, boolean simulate) { - return Fraction.ZERO; + override fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction { + return Fraction.ZERO } - @Nonnull - @Override - public Fraction extractEnergyInner(Fraction howMuch, boolean simulate) { - Fraction drained = Fraction.ZERO; + override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction { + var howMuch = howMuch + var drained = Fraction.ZERO - if (battery != ItemStack.EMPTY) { - Optional get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve(); - - if (get_mattery.isPresent()) { - Fraction changed = get_mattery.get().extractEnergyOuter(howMuch, simulate); - - if (changed.compareTo(Fraction.ZERO) > 0) { - drained = drained.plus(changed); - howMuch = howMuch.minus(changed); - - if (howMuch.compareTo(Fraction.ZERO) <= 0) { - if (!simulate && ent instanceof ServerPlayer ply) { - ply.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10); - } - - return drained; - } + if (!batteryItemStack.isEmpty) { + batteryItemStack.getCapability(CapabilityEnergy.ENERGY).ifPresent { + 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.compareTo(Fraction.ONE) >= 0) { - Optional get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve(); - - if (get_energy.isPresent()) { - Fraction changed = MatteryCapability.drainFE(get_energy.get(), howMuch, simulate); - - if (changed.compareTo(Fraction.ZERO) > 0) { - drained = drained.plus(changed); - howMuch = howMuch.minus(changed); - - if (howMuch.compareTo(Fraction.ZERO) <= 0) { - if (!simulate && ent instanceof ServerPlayer ply) { - ply.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10); - } - - return drained; - } - } + if (howMuch.isZero()) { + if (!simulate && ent is ServerPlayer) { + ent.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10) } + + return drained } } - Fraction new_energy = energy_stored.minus(howMuch).max(Fraction.ZERO); - drained = drained.plus(energy_stored.minus(new_energy)); + val new = (energy_stored - howMuch).moreThanZero() + drained += energy_stored - new if (!simulate) { - energy_stored = new_energy; + energy_stored = new - if (ent instanceof ServerPlayer ply) { - ply.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10); + if (ent is ServerPlayer) { + ent.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10) } } - return drained; + return drained } - @Nonnull - @Override - public Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate) { - Fraction received = Fraction.ZERO; + override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction { + var howMuch = howMuch + var received = Fraction.ZERO - if (battery != ItemStack.EMPTY) { - Optional get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve(); - - if (get_mattery.isPresent()) { - Fraction changed = get_mattery.get().receiveEnergyOuter(howMuch, simulate); - - if (changed.compareTo(Fraction.ZERO) > 0) { - received = received.plus(changed); - howMuch = howMuch.minus(changed); - - if (howMuch.compareTo(Fraction.ZERO) <= 0) { - return received; - } + if (!batteryItemStack.isEmpty) { + batteryItemStack.getCapability(CapabilityEnergy.ENERGY).ifPresent { + 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.compareTo(Fraction.ONE) >= 0) { - Optional get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve(); - - if (get_energy.isPresent()) { - Fraction changed = MatteryCapability.floodFE(get_energy.get(), howMuch, simulate); - - if (changed.compareTo(Fraction.ZERO) > 0) { - received = received.plus(changed); - howMuch = howMuch.minus(changed); - - if (howMuch.compareTo(Fraction.ZERO) <= 0) { - return received; - } - } - } + if (howMuch.isZero()) { + return received } } - Fraction new_energy = energy_stored.plus(howMuch).min(energy_stored_max); - received = received.plus(new_energy.minus(energy_stored)); + val new = (energy_stored + howMuch).min(energy_stored_max) + received += new - energy_stored if (!simulate) { - energy_stored = new_energy; + energy_stored = new } - return received; + return received } - @Nonnull - @Override - public Fraction receiveEnergyInner(Fraction howMuch, boolean simulate) { - return receiveEnergyOuter(howMuch, simulate); + override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction { + return receiveEnergyOuter(howMuch, simulate) } - @Override - public LivingEntity getEntity() { - return this.ent; + override fun getEntity(): LivingEntity { + return ent } - @Nonnull - @Override - public ItemStack getBatteryItemStack() { - return battery; - } + override fun getBatteryLevel(): Fraction { + if (!batteryItemStack.isEmpty) { + val resolver = batteryItemStack.getCapability(CapabilityEnergy.ENERGY).resolve() - @Override - public void setBatteryItemStack(@Nonnull ItemStack stack) { - battery = stack; - } + if (resolver.isPresent) { + val it = resolver.get() - @Override - @Nonnull - public Fraction getBatteryLevel() { - if (battery != ItemStack.EMPTY) { - Optional get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve(); - - if (get_mattery.isPresent()) { - return get_mattery.get().getBatteryLevel().plus(energy_stored); - } - - Optional get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve(); - - if (get_energy.isPresent()) { - return energy_stored.plus(get_energy.get().getEnergyStored()); + if (it is IMatteryEnergyStorage) { + return energy_stored + it.batteryLevel + } else { + return energy_stored + it.energyStored + } } } - return energy_stored; + return energy_stored } - @Override - @Nonnull - public Fraction getMaxBatteryLevel() { - if (battery != ItemStack.EMPTY) { - Optional get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve(); + override fun getMaxBatteryLevel(): Fraction { + if (batteryItemStack != ItemStack.EMPTY) { + val resolver = batteryItemStack.getCapability(CapabilityEnergy.ENERGY).resolve() - if (get_mattery.isPresent()) { - return get_mattery.get().getMaxBatteryLevel().plus(energy_stored_max); - } + if (resolver.isPresent) { + val it = resolver.get() - Optional get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve(); - - if (get_energy.isPresent()) { - return energy_stored_max.plus(get_energy.get().getMaxEnergyStored()); + if (it is IMatteryEnergyStorage) { + return energy_stored_max + it.maxBatteryLevel + } else { + return energy_stored_max + it.maxEnergyStored + } } } - return energy_stored_max; + return energy_stored_max } - private final LazyOptional resolver = LazyOptional.of(() -> this).cast(); + private val resolver = LazyOptional.of { this } - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (cap == MatteryCapability.ANDROID) { - return resolver.cast(); + 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: MutableSet = HashSet() + + @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) } - return LazyOptional.empty(); + @SubscribeEvent + fun onLivingTick(event: LivingUpdateEvent) { + val ent = event.entity + + if (ent.level.isClientSide) { + ent.getCapability(MatteryCapability.ANDROID).ifPresent { + it.tickClient() + } + } else { + ent.getCapability(MatteryCapability.ANDROID).ifPresent { + it.tick() + } + } + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + fun onHurtEvent(event: LivingHurtEvent) { + if (event.isCanceled) return + + val ent = event.entity + ent.getCapability(MatteryCapability.ANDROID).ifPresent { cap: IAndroidCapability -> cap.onHurt(event) } + } } -} +} \ No newline at end of file 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 index 38b3c4890..3713aa97e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapabilityPlayer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/AndroidCapabilityPlayer.kt @@ -1,328 +1,285 @@ -package ru.dbotthepony.mc.otm.capability.android; +package ru.dbotthepony.mc.otm.capability.android -import net.minecraft.ChatFormatting; -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.TranslatableComponent; -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.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.event.AttachCapabilitiesEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import ru.dbotthepony.mc.otm.Registry; -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.Fraction; -import ru.dbotthepony.mc.otm.network.android.AndroidResearchPacket; -import ru.dbotthepony.mc.otm.network.android.AndroidStatusPacket; +import net.minecraft.ChatFormatting +import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.ListTag +import net.minecraft.nbt.Tag +import net.minecraft.network.chat.TranslatableComponent +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.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 ru.dbotthepony.mc.otm.Registry +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.Fraction +import ru.dbotthepony.mc.otm.network.android.AndroidResearchPacket +import ru.dbotthepony.mc.otm.network.android.AndroidStatusPacket +import ru.dbotthepony.mc.otm.set +import java.util.* -import javax.annotation.Nonnull; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Objects; +class AndroidCapabilityPlayer(@JvmField val ply: Player) : AndroidCapability(ply) { + @JvmField + var is_android = false + private var network_is_android = false -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class AndroidCapabilityPlayer extends AndroidCapability { - public boolean is_android = false; - private boolean network_is_android = false; + @JvmField + var will_become_android = false + private var network_will_become_android = false + private val research = ArrayList() - public boolean will_become_android = false; - private boolean network_will_become_android = false; + override fun invalidateNetworkState() { + super.invalidateNetworkState() - private final ArrayList research_list = new ArrayList<>(); + network_is_android = false + network_will_become_android = false - @Override - public void invalidateNetworkState() { - super.invalidateNetworkState(); - network_is_android = false; - network_will_become_android = false; - - for (var instance : research_list) { - instance.dirty = true; + for (instance in research) { + instance.dirty = true } } - @Override - public boolean isAndroid() { - return is_android; + override fun isAndroid(): Boolean = is_android + fun isEverAndroid(): Boolean = is_android || will_become_android + + fun becomeAndroidSoft() { + if (is_android || will_become_android) return + will_become_android = true + (ply as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message").withStyle(ChatFormatting.GRAY), false) } - public boolean isEverAndroid() { - return is_android || will_become_android; + fun becomeAndroid() { + if (is_android) return + + is_android = true + will_become_android = false + energy_stored = Fraction(60000) + energy_stored_max = Fraction(60000) } - public void becomeAndroidSoft() { - if (is_android || will_become_android) - return; + fun becomeAndroidAndKill() { + if (is_android) return - will_become_android = true; - - if (ent instanceof ServerPlayer ply) { - ply.displayClientMessage(new TranslatableComponent("otm.pill.message").withStyle(ChatFormatting.GRAY), false); - } + becomeAndroid() + ply.hurt(Registry.DAMAGE_BECOME_ANDROID, ply.maxHealth * 2) } - public void becomeAndroid() { - if (is_android) - return; + fun becomeHumane() { + if (will_become_android) will_become_android = false + if (!is_android) return - is_android = true; - will_become_android = false; - energy_stored = new Fraction(60_000); - energy_stored_max = new Fraction(60_000); + is_android = false + energy_stored = Fraction(0) + energy_stored_max = Fraction(60000) + dropBattery() } - public void becomeAndroidAndKill() { - if (is_android) - return; + fun becomeHumaneAndKill() { + if (will_become_android) will_become_android = false + if (!is_android) return - becomeAndroid(); - ply.hurt(Registry.DAMAGE_BECOME_ANDROID, ply.getMaxHealth() * 2); + becomeHumane() + ply.hurt(Registry.DAMAGE_BECOME_HUMANE, ply.maxHealth * 2) } - public void becomeHumane() { - if (will_become_android) - will_become_android = false; + override fun deserializeNBT(compound: CompoundTag?) { + super.deserializeNBT(compound!!) - if (!is_android) - return; + is_android = compound.getBoolean("is_android") + will_become_android = compound.getBoolean("will_become_android") + research.clear() - is_android = false; + val list = compound.getList("research", Tag.TAG_COMPOUND.toInt()) - energy_stored = new Fraction(0); - energy_stored_max = new Fraction(60_000); - - dropBattery(); - } - - public void becomeHumaneAndKill() { - if (will_become_android) - will_become_android = false; - - if (!is_android) - return; - - becomeHumane(); - ply.hurt(Registry.DAMAGE_BECOME_HUMANE, ply.getMaxHealth() * 2); - } - - @Override - public void deserializeNBT(CompoundTag compound) { - super.deserializeNBT(compound); - - is_android = compound.getBoolean("is_android"); - will_become_android = compound.getBoolean("will_become_android"); - - research_list.clear(); - - var list = compound.getList("research", Tag.TAG_COMPOUND); - - for (var _tag : list) { - if (_tag instanceof CompoundTag tag) { - var research = Registry.ANDROID_RESEARCH.getValue(new ResourceLocation(tag.getString("id"))); + for (tag in list) { + if (tag is CompoundTag) { + val research = Registry.ANDROID_RESEARCH.getValue(ResourceLocation(tag.getString("id"))) if (research != null) { - var instance = research.factory(this); - instance.deserializeNBT(tag); - research_list.add(instance); + val instance = research.factory(this) + instance.deserializeNBT(tag) + this.research.add(instance) } } } } - @Nonnull - @Override - public CompoundTag serializeNBT() { - CompoundTag tag = super.serializeNBT(); - tag.putBoolean("is_android", is_android); - tag.putBoolean("will_become_android", will_become_android); + override fun serializeNBT(): CompoundTag { + val tag = super.serializeNBT() - var list = new ListTag(); + tag["is_android"] = is_android + tag["will_become_android"] = will_become_android - for (var instance : research_list) { - var _tag = new CompoundTag(); - instance.serializeNBT(_tag); - _tag.putString("id", Objects.requireNonNull(instance.type.getRegistryName()).toString()); - list.add(_tag); + val list = ListTag() + + for (instance in research) { + val researchTag = CompoundTag() + instance.serializeNBT(researchTag) + + researchTag["id"] = instance.type.registryName!!.toString() + list.add(researchTag) } - tag.put("research", list); - - return tag; + tag["research"] = list + return tag } - @SuppressWarnings("unchecked") - public T getResearch(AndroidResearchType type) { - for (var instance : research_list) { - if (instance.type == type) { - return (T) instance; + fun getResearch(type: AndroidResearchType): T { + for (instance in research) { + if (instance.type === type) { + return instance as T } } - var instance = type.factory(this); - research_list.add(instance); - return instance; + val instance = type.factory(this) + research.add(instance) + return instance } - @SubscribeEvent - @SuppressWarnings("unused") - public static void onAttachCapabilityEvent(AttachCapabilitiesEvent event) { - if (event.getObject() instanceof Player ply) { - event.addCapability(Registry.Names.ANDROID_CAPABILITY, new AndroidCapabilityPlayer(ply)); - } - } - - @SubscribeEvent - @SuppressWarnings("unused") - public static void onPlayerChangeDimensionEvent(PlayerEvent.PlayerChangedDimensionEvent event) { - event.getPlayer().getCapability(MatteryCapability.ANDROID).ifPresent(IAndroidCapability::invalidateNetworkState); - } - - @SubscribeEvent - @SuppressWarnings("unused") - public static void onPlayerCloneEvent(PlayerEvent.Clone event) { - event.getPlayer().getCapability(MatteryCapability.ANDROID).ifPresent((cap) -> { - LazyOptional resolver = event.getOriginal().getCapability(MatteryCapability.ANDROID); - - if (!resolver.isPresent() || resolver.resolve().isEmpty()) { - event.getOriginal().reviveCaps(); - resolver = event.getOriginal().getCapability(MatteryCapability.ANDROID); - } - - if (!resolver.isPresent() || resolver.resolve().isEmpty()) { - event.getOriginal().invalidateCaps(); - return; - } - - var original = (AndroidCapabilityPlayer) resolver.resolve().get(); - - if (original.will_become_android && event.isWasDeath()) { - original.becomeAndroid(); - - if (event.getPlayer() instanceof ServerPlayer ply) { - ply.displayClientMessage(new TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false); - } - } - - cap.deserializeNBT(original.serializeNBT()); - cap.invalidateNetworkState(); - event.getOriginal().invalidateCaps(); - }); - } - - public int last_jump_ticks = 14; - public final Player ply; - - public AndroidCapabilityPlayer(Player ent) { - super(ent); - ply = ent; - } - - @Override - protected void tickNetwork() { - super.tickNetwork(); + @JvmField + var last_jump_ticks = 14 + override fun tickNetwork() { + super.tickNetwork() if (is_android != network_is_android) { - network_is_android = is_android; - sendNetwork(new AndroidStatusPacket(AndroidStatusPacket.Type.IS_ANDROID, is_android)); + network_is_android = is_android + sendNetwork(AndroidStatusPacket(AndroidStatusPacket.Type.IS_ANDROID, is_android)) } if (will_become_android != network_will_become_android) { - network_will_become_android = will_become_android; - sendNetwork(new AndroidStatusPacket(AndroidStatusPacket.Type.WILL_BECOME_ANDROID, will_become_android)); + network_will_become_android = will_become_android + sendNetwork(AndroidStatusPacket(AndroidStatusPacket.Type.WILL_BECOME_ANDROID, will_become_android)) } - for (var instance : research_list) { + for (instance in research) { if (instance.dirty) { - instance.dirty = false; - sendNetwork(new AndroidResearchPacket(instance)); + instance.dirty = false + sendNetwork(AndroidResearchPacket(instance)) } } } - public static final Fraction ENERGY_FOR_HUNGER_POINT = new Fraction(1000); + @JvmField + var sleep_ticks = 0 - public int sleep_ticks = 0; - public static final int SLEEP_TICKS_LIMIT = 80; - - @Override - protected void tickInnerClientAlways() { - super.tickInnerClientAlways(); + override fun tickInnerClientAlways() { + super.tickInnerClientAlways() if (will_become_android) { - if (ent.isSleeping()) { - sleep_ticks++; + if (ply.isSleeping) { + sleep_ticks++ } else { - sleep_ticks = 0; + sleep_ticks = 0 } } } - @Override - protected void tickServerAlways() { - super.tickServerAlways(); + override fun tickServerAlways() { + super.tickServerAlways() if (will_become_android) { - if (ent.isSleeping()) { - sleep_ticks++; + if (ply.isSleeping) { + sleep_ticks++ if (sleep_ticks > SLEEP_TICKS_LIMIT) { - becomeAndroid(); - sleep_ticks = 0; + becomeAndroid() + sleep_ticks = 0 - if (ent instanceof ServerPlayer ply) { - ply.displayClientMessage(new TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false); - } + (ply as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false) } } else { - sleep_ticks = 0; + sleep_ticks = 0 } } } - @Override - public void tickServer() { - super.tickServer(); + public override fun tickServer() { + super.tickServer() // TODO: Maybe passive drain? // extractEnergyInner(BigDecimal.valueOf(new Random().nextDouble()), false); - - if (ply.isSwimming() && !hasFeature(Registry.AndroidFeatures.AIR_BAGS)) { - ply.setSwimming(false); + if (ply.isSwimming && !hasFeature(Registry.AndroidFeatures.AIR_BAGS)) { + ply.isSwimming = false } - var stats = ply.getFoodData(); + val stats = ply.foodData - while (stats.getFoodLevel() < 18 && this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true).compareTo(ENERGY_FOR_HUNGER_POINT) == 0) { - this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false); - stats.setFoodLevel(stats.getFoodLevel() + 1); + 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.getFoodLevel() > 18 && this.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, true).compareTo(ENERGY_FOR_HUNGER_POINT) == 0) { - this.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, false); - stats.setFoodLevel(stats.getFoodLevel() - 1); + 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 } - var food_level = (float) stats.getFoodLevel(); + val foodLevel = stats.foodLevel.toFloat() - if (stats.getSaturationLevel() < food_level) { - Fraction extracted = this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT.times(food_level - stats.getSaturationLevel()), false); - stats.setSaturation(stats.getSaturationLevel() + extracted.div(ENERGY_FOR_HUNGER_POINT).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.getExhaustionLevel() > 0f) { - Fraction extracted = this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT.times(stats.getExhaustionLevel() / 4f), false); - stats.setExhaustion(stats.getExhaustionLevel() - extracted.div(ENERGY_FOR_HUNGER_POINT).toFloat() * 4f); + 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(Registry.Names.ANDROID_CAPABILITY, AndroidCapabilityPlayer(ent)) + } + } + + @SubscribeEvent + fun onPlayerChangeDimensionEvent(event: PlayerChangedDimensionEvent) { + event.player.getCapability(MatteryCapability.ANDROID) + .ifPresent { it.invalidateNetworkState() } + } + + @SubscribeEvent + fun onPlayerCloneEvent(event: Clone) { + event.player.getCapability(MatteryCapability.ANDROID).ifPresent { + 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@ifPresent + } + + val original = resolver.resolve().get() as AndroidCapabilityPlayer + + if (original.will_become_android && event.isWasDeath) { + original.becomeAndroid() + (event.player 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 = Fraction(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 index cb7606868..ed16ea726 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/IAndroidCapability.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/capability/android/IAndroidCapability.kt @@ -1,51 +1,45 @@ -package ru.dbotthepony.mc.otm.capability.android; +package ru.dbotthepony.mc.otm.capability.android -import net.minecraft.MethodsReturnNonnullByDefault; -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.Fraction; +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.Fraction +import java.util.* -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; -import java.util.Optional; +interface IAndroidCapability : IMatteryEnergyStorage, INBTSerializable { + fun tick() + fun tickClient() + fun getEntity(): LivingEntity + fun addFeature(feature: AndroidFeatureType): T + fun removeFeature(feature: AndroidFeatureType<*>): Boolean + fun hasFeature(feature: AndroidFeatureType<*>): Boolean + fun hasFeatureLevel(feature: AndroidFeatureType<*>, level: Int): Boolean -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public interface IAndroidCapability extends IMatteryEnergyStorage, INBTSerializable { - void tick(); - void tickClient(); - LivingEntity getEntity(); + fun getFeature(feature: AndroidFeatureType): T? - T addFeature(AndroidFeatureType feature); - boolean removeFeature(AndroidFeatureType feature); - boolean hasFeature(@Nullable AndroidFeatureType feature); - boolean hasFeatureLevel(@Nullable AndroidFeatureType feature, int level); - @Nullable - T getFeature(AndroidFeatureType feature); - - default Optional getFeatureO(AndroidFeatureType feature) { - var get = getFeature(feature); - return get != null ? Optional.of(get) : Optional.empty(); + fun getFeatureO(feature: AndroidFeatureType): Optional { + val get = getFeature(feature) + return if (get != null) Optional.of(get) else Optional.empty() } - default boolean isAndroid() { - return true; + fun ifFeature(feature: AndroidFeatureType, consumer: (T) -> Unit) { + val get = getFeature(feature) + + if (get != null) { + consumer(get) + } } - default void onHurt(LivingHurtEvent event) {} - ItemStack getBatteryItemStack(); - void setBatteryItemStack(ItemStack stack); + fun isAndroid(): Boolean = true - void invalidateNetworkState(); // tell capability that player forgot everything, and everything needs to be re-networked - - void setEnergy(Fraction value); - void setMaxEnergy(Fraction value); -} + fun onHurt(event: LivingHurtEvent?) {} + var batteryItemStack: ItemStack + fun invalidateNetworkState() // tell capability that player forgot everything, and everything needs to be re-networked + fun setEnergy(value: Fraction?) + fun setMaxEnergy(value: Fraction?) +} \ No newline at end of file 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 5ddc544a1..642c3ce4a 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 @@ -19,9 +19,7 @@ import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel import ru.dbotthepony.mc.otm.menu.AndroidStationMenu import java.util.* - - -class AndroidStationScreen(p_97741_: AndroidStationMenu, p_97742_: Inventory, p_97743_: Component) : +class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: Inventory, p_97743_: Component) : MatteryScreen(p_97741_, p_97742_, p_97743_) { internal inner class AndroidResearchButton(parent: EditablePanel?, private val node: AndroidResearch) : diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/ItemPill.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/ItemPill.kt index 6845ac40f..1c280876b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/ItemPill.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/ItemPill.kt @@ -53,7 +53,7 @@ class ItemPill(val pillType: PillType) : val cap = resolver.get() as AndroidCapabilityPlayer - if (pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid || pillType == PillType.BECOME_HUMANE && cap.isEverAndroid) { + if (pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid() || pillType == PillType.BECOME_HUMANE && cap.isEverAndroid()) { ply.startUsingItem(hand) return InteractionResultHolder.consume(ply.getItemInHand(hand)) } @@ -73,7 +73,7 @@ class ItemPill(val pillType: PillType) : val cap = resolver.get() as AndroidCapabilityPlayer - if (pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid) { + if (pillType == PillType.BECOME_ANDROID && !cap.isEverAndroid()) { if (ent.abilities.instabuild) { if (ent is ServerPlayer) { cap.becomeAndroid() @@ -85,7 +85,7 @@ class ItemPill(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()