Move Android capability to kotlin and fix issues along the way
This commit is contained in:
parent
0acbdc8c69
commit
9efb4d6176
@ -126,8 +126,8 @@ public class OverdriveThatMatters {
|
|||||||
|
|
||||||
// Register ourselves for server and other game events we are interested in
|
// Register ourselves for server and other game events we are interested in
|
||||||
MinecraftForge.EVENT_BUS.register(this);
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
MinecraftForge.EVENT_BUS.register(AndroidCapabilityPlayer.class);
|
MinecraftForge.EVENT_BUS.register(AndroidCapabilityPlayer.Companion);
|
||||||
MinecraftForge.EVENT_BUS.register(AndroidCapability.class);
|
MinecraftForge.EVENT_BUS.register(AndroidCapability.Companion);
|
||||||
MinecraftForge.EVENT_BUS.register(MatterRegistry.class);
|
MinecraftForge.EVENT_BUS.register(MatterRegistry.class);
|
||||||
MinecraftForge.EVENT_BUS.register(BlockEntityBlackHole.BlackHoleExplosionQueue.class);
|
MinecraftForge.EVENT_BUS.register(BlockEntityBlackHole.BlackHoleExplosionQueue.class);
|
||||||
|
|
||||||
|
@ -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.MethodsReturnNonnullByDefault
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import javax.annotation.ParametersAreNonnullByDefault
|
||||||
import net.minecraft.nbt.ListTag;
|
import net.minecraft.world.entity.LivingEntity
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraftforge.common.capabilities.ICapabilityProvider
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.world.effect.MobEffect;
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.effect.MobEffects;
|
import ru.dbotthepony.mc.otm.android.AndroidFeatureType
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
||||||
import net.minecraft.world.item.ItemStack;
|
import java.lang.Runnable
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
import net.minecraft.server.level.ServerPlayer
|
||||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
import ru.dbotthepony.mc.otm.network.android.AndroidFeaturePacket
|
||||||
import net.minecraftforge.common.util.INBTSerializable;
|
import net.minecraftforge.event.entity.living.LivingHurtEvent
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraft.nbt.ListTag
|
||||||
import net.minecraftforge.energy.CapabilityEnergy;
|
import net.minecraft.nbt.Tag
|
||||||
import net.minecraftforge.energy.IEnergyStorage;
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraftforge.event.entity.living.LivingEvent;
|
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
||||||
import net.minecraftforge.event.entity.living.LivingHurtEvent;
|
import net.minecraftforge.network.PacketDistributor
|
||||||
import net.minecraftforge.eventbus.api.EventPriority;
|
import ru.dbotthepony.mc.otm.network.android.AndroidEnergyPacket
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import ru.dbotthepony.mc.otm.network.android.AndroidBatteryPacket
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
import net.minecraft.world.effect.MobEffect
|
||||||
import net.minecraftforge.network.PacketDistributor;
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.Registry;
|
import net.minecraftforge.energy.CapabilityEnergy
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidFeature;
|
import net.minecraftforge.common.util.LazyOptional
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
|
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
|
||||||
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
|
import net.minecraft.world.effect.MobEffects
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
import net.minecraftforge.common.capabilities.Capability
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction;
|
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
|
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent
|
||||||
import ru.dbotthepony.mc.otm.network.android.AndroidBatteryPacket;
|
import net.minecraftforge.eventbus.api.EventPriority
|
||||||
import ru.dbotthepony.mc.otm.network.android.AndroidEnergyPacket;
|
import ru.dbotthepony.mc.otm.Registry
|
||||||
import ru.dbotthepony.mc.otm.network.android.AndroidFeaturePacket;
|
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
||||||
|
import ru.dbotthepony.mc.otm.capability.extractEnergy
|
||||||
import javax.annotation.Nonnull;
|
import ru.dbotthepony.mc.otm.capability.receiveEnergy
|
||||||
import javax.annotation.Nullable;
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import ru.dbotthepony.mc.otm.ifHas
|
||||||
import java.math.BigDecimal;
|
import ru.dbotthepony.mc.otm.set
|
||||||
import java.util.*;
|
import java.util.*
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
@MethodsReturnNonnullByDefault
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
public class AndroidCapability implements ICapabilityProvider, IAndroidCapability, INBTSerializable<CompoundTag> {
|
open class AndroidCapability(@JvmField protected val ent: LivingEntity) : ICapabilityProvider, IAndroidCapability, INBTSerializable<CompoundTag?> {
|
||||||
protected final LivingEntity ent;
|
@JvmField
|
||||||
protected Fraction energy_stored = Fraction.ZERO;
|
protected var energy_stored = Fraction.ZERO
|
||||||
protected Fraction energy_stored_max = new Fraction(60_000);
|
@JvmField
|
||||||
protected ItemStack battery = ItemStack.EMPTY;
|
protected var energy_stored_max = Fraction(60000)
|
||||||
|
|
||||||
private Fraction network_energy = new Fraction(-1);
|
override var batteryItemStack = ItemStack.EMPTY
|
||||||
private Fraction network_energy_max = new Fraction(-1);
|
|
||||||
private ItemStack network_battery = ItemStack.EMPTY;
|
|
||||||
|
|
||||||
protected final Map<AndroidFeatureType<?>, AndroidFeature> features = new HashMap<>();
|
private var network_energy = Fraction(-1)
|
||||||
protected final ArrayList<Object> network_queue = new ArrayList<>();
|
private var network_energy_max = Fraction(-1)
|
||||||
|
private var network_battery = ItemStack.EMPTY
|
||||||
|
|
||||||
protected final ArrayList<Runnable> delayed_tick_server = new ArrayList<>();
|
@JvmField protected val features: MutableMap<AndroidFeatureType<*>?, AndroidFeature> = HashMap()
|
||||||
|
@JvmField protected val network_queue = ArrayList<Any>()
|
||||||
protected boolean network_first = false;
|
@JvmField protected val delayed_tick_server = ArrayList<Runnable>()
|
||||||
|
@JvmField protected var network_first = false
|
||||||
protected boolean addFeature(AndroidFeature feature) {
|
|
||||||
if (features.containsKey(feature.type))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
features.put(feature.type, feature);
|
|
||||||
|
|
||||||
|
protected fun addFeature(feature: AndroidFeature): Boolean {
|
||||||
|
if (features.containsKey(feature.type)) return false
|
||||||
|
features[feature.type] = feature
|
||||||
if (!ent.level.isClientSide) {
|
if (!ent.level.isClientSide) {
|
||||||
delayed_tick_server.add(feature::applyModifiers);
|
delayed_tick_server.add(Runnable { feature.applyModifiers() })
|
||||||
}
|
}
|
||||||
|
if (ent is ServerPlayer) {
|
||||||
if (ent instanceof ServerPlayer ply) {
|
sendNetwork(AndroidFeaturePacket(true, feature))
|
||||||
sendNetwork(new AndroidFeaturePacket(true, feature));
|
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun <T : AndroidFeature> addFeature(feature: AndroidFeatureType<T>): T {
|
||||||
@SuppressWarnings("unchecked")
|
val get = features[feature]
|
||||||
public <T extends AndroidFeature> T addFeature(@Nonnull AndroidFeatureType<T> feature) {
|
if (get != null) return get as T
|
||||||
var get = features.get(feature);
|
|
||||||
|
|
||||||
if (get != null)
|
val factory = feature.factory(this)
|
||||||
return (T) get;
|
|
||||||
|
|
||||||
var factory = feature.factory(this);
|
features[feature] = factory
|
||||||
features.put(feature, factory);
|
|
||||||
|
|
||||||
if (!ent.level.isClientSide) {
|
if (!ent.level.isClientSide) {
|
||||||
delayed_tick_server.add(factory::applyModifiers);
|
delayed_tick_server.add(Runnable { factory!!.applyModifiers() })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ent instanceof ServerPlayer ply) {
|
if (ent is ServerPlayer) {
|
||||||
sendNetwork(new AndroidFeaturePacket(true, factory));
|
sendNetwork(AndroidFeaturePacket(true, factory))
|
||||||
}
|
}
|
||||||
|
|
||||||
return factory;
|
return factory
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun removeFeature(feature: AndroidFeatureType<*>): Boolean {
|
||||||
public boolean removeFeature(@Nonnull AndroidFeatureType<?> feature) {
|
val removed = features.remove(feature)
|
||||||
var removed = features.remove(feature);
|
|
||||||
|
|
||||||
if (removed != null) {
|
if (removed != null) {
|
||||||
if (!ent.level.isClientSide) {
|
if (!ent.level.isClientSide) {
|
||||||
delayed_tick_server.add(removed::removeModifiers);
|
delayed_tick_server.add { removed.removeModifiers() }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ent instanceof ServerPlayer ply) {
|
if (ent is ServerPlayer) {
|
||||||
sendNetwork(new AndroidFeaturePacket(false, removed));
|
sendNetwork(AndroidFeaturePacket(false, removed))
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun hasFeature(feature: AndroidFeatureType<*>): Boolean {
|
||||||
public boolean hasFeature(@Nullable AndroidFeatureType<?> feature) {
|
return features.containsKey(feature)
|
||||||
return features.containsKey(feature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun hasFeatureLevel(feature: AndroidFeatureType<*>, level: Int): Boolean {
|
||||||
public boolean hasFeatureLevel(@Nullable AndroidFeatureType<?> feature, int level) {
|
val get = features[feature] ?: return false
|
||||||
var get = features.get(feature);
|
return get.level >= level
|
||||||
|
|
||||||
if (get == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return get.getLevel() >= level;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
override fun <T : AndroidFeature> getFeature(feature: AndroidFeatureType<T>): T? {
|
||||||
@SuppressWarnings("unchecked")
|
return features[feature] as T?
|
||||||
public <T extends AndroidFeature> T getFeature(AndroidFeatureType<T> feature) {
|
|
||||||
return (T) features.get(feature);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Set<MobEffect> 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) {
|
if (ent is ServerPlayer) {
|
||||||
UNAFFECTED_EFFECTS.add(MobEffects.CONDUIT_POWER);
|
for (feature in features.values) {
|
||||||
UNAFFECTED_EFFECTS.add(MobEffects.HEAL);
|
sendNetwork(AndroidFeaturePacket(true, feature))
|
||||||
// maybe it makes things go haywire idk
|
feature.invalidateNetwork()
|
||||||
// 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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun setEnergy(value: Fraction?) {
|
||||||
public void setEnergy(Fraction value) {
|
energy_stored = value!!
|
||||||
energy_stored = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun setMaxEnergy(value: Fraction?) {
|
||||||
public void setMaxEnergy(Fraction value) {
|
energy_stored_max = value!!
|
||||||
energy_stored_max = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AndroidCapability(LivingEntity ent) {
|
override fun onHurt(event: LivingHurtEvent?) {
|
||||||
this.ent = ent;
|
for (feature in features.values) {
|
||||||
}
|
feature.onHurt(event)
|
||||||
|
|
||||||
@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
|
override fun serializeNBT(): CompoundTag {
|
||||||
@Nonnull
|
val tag = CompoundTag()
|
||||||
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());
|
|
||||||
|
|
||||||
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()) {
|
val featureList = ListTag()
|
||||||
var compound = new CompoundTag();
|
|
||||||
feature.serializeNBT(compound);
|
for (feature in features.values) {
|
||||||
compound.putString("id", Objects.requireNonNull(feature.type.getRegistryName()).toString());
|
val featureNbt = CompoundTag()
|
||||||
features_nbt.add(compound);
|
feature.serializeNBT(featureNbt)
|
||||||
|
|
||||||
|
featureNbt["id"] = feature.type.registryName!!.toString()
|
||||||
|
featureList.add(featureNbt)
|
||||||
}
|
}
|
||||||
|
|
||||||
tag.put("features", features_nbt);
|
tag["features"] = featureList
|
||||||
|
return tag
|
||||||
return tag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun deserializeNBT(compound: CompoundTag?) {
|
||||||
public void deserializeNBT(CompoundTag compound) {
|
compound!!
|
||||||
if (compound.contains("energy_stored"))
|
|
||||||
energy_stored = Fraction.deserializeNBT(compound.get("energy_stored"));
|
|
||||||
|
|
||||||
if (compound.contains("energy_stored_max"))
|
compound.ifHas("energy_stored") {
|
||||||
energy_stored_max = Fraction.deserializeNBT(compound.get("energy_stored_max"));
|
energy_stored = Fraction.deserializeNBT(it)
|
||||||
|
}
|
||||||
|
|
||||||
if (compound.contains("battery"))
|
compound.ifHas("energy_stored_max") {
|
||||||
battery = ItemStack.of(compound.getCompound("battery"));
|
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) {
|
val featuresNbt = compound.getList("features", Tag.TAG_COMPOUND.toInt())
|
||||||
if (_tag instanceof CompoundTag tag) {
|
|
||||||
var get_feature = Registry.ANDROID_FEATURES.getValue(new ResourceLocation(tag.getString("id")));
|
|
||||||
|
|
||||||
if (get_feature != null && get_feature.isApplicable(this)) {
|
for (tag in featuresNbt) {
|
||||||
var feature = get_feature.factory(this);
|
if (tag is CompoundTag) {
|
||||||
feature.deserializeNBT(tag);
|
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) {
|
feature.deserializeNBT(tag)
|
||||||
delayed_tick_server.add(feature::applyModifiers);
|
addFeature(feature)
|
||||||
|
|
||||||
|
if (!ent.level.isClientSide) {
|
||||||
|
delayed_tick_server.add(Runnable { feature.applyModifiers() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dropBattery() {
|
fun dropBattery() {
|
||||||
if (battery.isEmpty())
|
if (batteryItemStack.isEmpty) return
|
||||||
return;
|
ent.spawnAtLocation(batteryItemStack)
|
||||||
|
batteryItemStack = ItemStack.EMPTY
|
||||||
ent.spawnAtLocation(battery);
|
|
||||||
battery = ItemStack.EMPTY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void sendNetwork(Object packet) {
|
protected fun sendNetwork(packet: Any) {
|
||||||
if (ent instanceof ServerPlayer ply) {
|
if (ent is ServerPlayer) {
|
||||||
if (network_first) {
|
if (network_first) {
|
||||||
MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with(() -> ply), packet);
|
MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with { ent }, packet)
|
||||||
} else {
|
} else {
|
||||||
network_queue.add(packet);
|
network_queue.add(packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void tickNetwork() {
|
protected open fun tickNetwork() {
|
||||||
network_first = true;
|
network_first = true
|
||||||
|
|
||||||
if (ent instanceof ServerPlayer ply) {
|
if (ent is ServerPlayer) {
|
||||||
if (!energy_stored.equals(network_energy)) {
|
if (energy_stored != network_energy) {
|
||||||
network_energy = energy_stored;
|
network_energy = energy_stored
|
||||||
sendNetwork(new AndroidEnergyPacket(false, energy_stored));
|
sendNetwork(AndroidEnergyPacket(false, energy_stored))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!energy_stored_max.equals(network_energy_max)) {
|
if (energy_stored_max != network_energy_max) {
|
||||||
network_energy_max = energy_stored_max;
|
network_energy_max = energy_stored_max
|
||||||
sendNetwork(new AndroidEnergyPacket(true, energy_stored_max));
|
sendNetwork(AndroidEnergyPacket(true, energy_stored_max))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!network_battery.equals(battery, false)) {
|
if (!network_battery.equals(batteryItemStack, false)) {
|
||||||
network_battery = battery.copy();
|
network_battery = batteryItemStack.copy()
|
||||||
sendNetwork(new AndroidBatteryPacket(battery));
|
sendNetwork(AndroidBatteryPacket(batteryItemStack))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (network_queue.size() != 0) {
|
if (network_queue.size != 0) {
|
||||||
for (var packet : network_queue) {
|
for (packet in network_queue) {
|
||||||
MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with(() -> ply), packet);
|
MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with {ent}, packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
network_queue.clear();
|
network_queue.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void tickInnerClient() {
|
protected open fun tickInnerClient() {}
|
||||||
|
protected open fun tickInnerClientAlways() {}
|
||||||
}
|
|
||||||
|
|
||||||
protected void tickInnerClientAlways() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tickClient() {
|
|
||||||
delayed_tick_server.clear();
|
|
||||||
|
|
||||||
if (!ent.isAlive())
|
|
||||||
return;
|
|
||||||
|
|
||||||
tickInnerClientAlways();
|
|
||||||
|
|
||||||
|
override fun tickClient() {
|
||||||
|
delayed_tick_server.clear()
|
||||||
|
if (!ent.isAlive) return
|
||||||
|
tickInnerClientAlways()
|
||||||
if (isAndroid()) {
|
if (isAndroid()) {
|
||||||
tickInnerClient();
|
tickInnerClient()
|
||||||
|
for (feature in features.values) {
|
||||||
for (var feature : features.values()) {
|
feature.tickClient()
|
||||||
feature.tickClient();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun tick() {
|
||||||
public void tick() {
|
if (!ent.isAlive) return
|
||||||
if (!ent.isAlive())
|
tickServerAlways()
|
||||||
return;
|
|
||||||
|
|
||||||
tickServerAlways();
|
|
||||||
|
|
||||||
if (isAndroid()) {
|
if (isAndroid()) {
|
||||||
tickServer();
|
tickServer()
|
||||||
|
for (feature in features.values) {
|
||||||
for (var feature : features.values()) {
|
feature.tickServer()
|
||||||
feature.tickServer();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (runnable in delayed_tick_server) {
|
||||||
for (var runnable : delayed_tick_server) {
|
runnable.run()
|
||||||
runnable.run();
|
|
||||||
}
|
}
|
||||||
|
delayed_tick_server.clear()
|
||||||
delayed_tick_server.clear();
|
tickNetwork()
|
||||||
tickNetwork();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void tickServerAlways() {
|
protected open fun tickServerAlways() {}
|
||||||
|
|
||||||
}
|
protected open fun tickServer() {
|
||||||
|
if (ent.airSupply < ent.maxAirSupply)
|
||||||
|
ent.airSupply = ent.maxAirSupply
|
||||||
|
|
||||||
protected void tickServer() {
|
for (effect in UNAFFECTED_EFFECTS)
|
||||||
if (ent.getAirSupply() < ent.getMaxAirSupply())
|
|
||||||
ent.setAirSupply(ent.getMaxAirSupply());
|
|
||||||
|
|
||||||
for (var effect : UNAFFECTED_EFFECTS)
|
|
||||||
if (ent.hasEffect(effect))
|
if (ent.hasEffect(effect))
|
||||||
ent.removeEffect(effect);
|
ent.removeEffect(effect)
|
||||||
|
|
||||||
if (!battery.isEmpty()) {
|
if (!batteryItemStack.isEmpty && energy_stored < energy_stored_max) {
|
||||||
Fraction demand = energy_stored_max.minus(energy_stored);
|
batteryItemStack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
|
||||||
|
if (it is IMatteryEnergyStorage) {
|
||||||
if (demand.compareTo(Fraction.ZERO) > 0) {
|
energy_stored += it.extractEnergyInner(energy_stored_max - energy_stored, false)
|
||||||
Optional<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve();
|
} else {
|
||||||
|
energy_stored += it.extractEnergy(energy_stored_max - energy_stored, false)
|
||||||
if (get_mattery.isPresent()) {
|
|
||||||
demand = demand.minus(get_mattery.get().extractEnergyInner(demand, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demand.compareTo(Fraction.ONE) >= 0) {
|
|
||||||
Optional<IEnergyStorage> 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 fun extractEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
|
||||||
@Override
|
return Fraction.ZERO
|
||||||
public Fraction extractEnergyOuter(Fraction howMuch, boolean simulate) {
|
|
||||||
return Fraction.ZERO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
override fun extractEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
|
||||||
@Override
|
var howMuch = howMuch
|
||||||
public Fraction extractEnergyInner(Fraction howMuch, boolean simulate) {
|
var drained = Fraction.ZERO
|
||||||
Fraction drained = Fraction.ZERO;
|
|
||||||
|
|
||||||
if (battery != ItemStack.EMPTY) {
|
if (!batteryItemStack.isEmpty) {
|
||||||
Optional<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve();
|
batteryItemStack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
|
||||||
|
if (it is IMatteryEnergyStorage) {
|
||||||
if (get_mattery.isPresent()) {
|
val extracted = it.extractEnergyOuter(howMuch, simulate)
|
||||||
Fraction changed = get_mattery.get().extractEnergyOuter(howMuch, simulate);
|
drained += extracted
|
||||||
|
howMuch -= extracted
|
||||||
if (changed.compareTo(Fraction.ZERO) > 0) {
|
} else {
|
||||||
drained = drained.plus(changed);
|
val extracted = it.extractEnergy(howMuch, simulate)
|
||||||
howMuch = howMuch.minus(changed);
|
drained += extracted
|
||||||
|
howMuch -= extracted
|
||||||
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.compareTo(Fraction.ONE) >= 0) {
|
if (howMuch.isZero()) {
|
||||||
Optional<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve();
|
if (!simulate && ent is ServerPlayer) {
|
||||||
|
ent.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10)
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return drained
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Fraction new_energy = energy_stored.minus(howMuch).max(Fraction.ZERO);
|
val new = (energy_stored - howMuch).moreThanZero()
|
||||||
drained = drained.plus(energy_stored.minus(new_energy));
|
drained += energy_stored - new
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
energy_stored = new_energy;
|
energy_stored = new
|
||||||
|
|
||||||
if (ent instanceof ServerPlayer ply) {
|
if (ent is ServerPlayer) {
|
||||||
ply.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10);
|
ent.awardStat(Registry.Names.POWER_CONSUMED, drained.toInt() * 10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return drained;
|
return drained
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
override fun receiveEnergyOuter(howMuch: Fraction, simulate: Boolean): Fraction {
|
||||||
@Override
|
var howMuch = howMuch
|
||||||
public Fraction receiveEnergyOuter(Fraction howMuch, boolean simulate) {
|
var received = Fraction.ZERO
|
||||||
Fraction received = Fraction.ZERO;
|
|
||||||
|
|
||||||
if (battery != ItemStack.EMPTY) {
|
if (!batteryItemStack.isEmpty) {
|
||||||
Optional<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve();
|
batteryItemStack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
|
||||||
|
if (it is IMatteryEnergyStorage) {
|
||||||
if (get_mattery.isPresent()) {
|
val extracted = it.receiveEnergyOuter(howMuch, simulate)
|
||||||
Fraction changed = get_mattery.get().receiveEnergyOuter(howMuch, simulate);
|
received += extracted
|
||||||
|
howMuch -= extracted
|
||||||
if (changed.compareTo(Fraction.ZERO) > 0) {
|
} else {
|
||||||
received = received.plus(changed);
|
val extracted = it.receiveEnergy(howMuch, simulate)
|
||||||
howMuch = howMuch.minus(changed);
|
received += extracted
|
||||||
|
howMuch -= extracted
|
||||||
if (howMuch.compareTo(Fraction.ZERO) <= 0) {
|
|
||||||
return received;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (howMuch.compareTo(Fraction.ONE) >= 0) {
|
if (howMuch.isZero()) {
|
||||||
Optional<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve();
|
return received
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Fraction new_energy = energy_stored.plus(howMuch).min(energy_stored_max);
|
val new = (energy_stored + howMuch).min(energy_stored_max)
|
||||||
received = received.plus(new_energy.minus(energy_stored));
|
received += new - energy_stored
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
energy_stored = new_energy;
|
energy_stored = new
|
||||||
}
|
}
|
||||||
|
|
||||||
return received;
|
return received
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
override fun receiveEnergyInner(howMuch: Fraction, simulate: Boolean): Fraction {
|
||||||
@Override
|
return receiveEnergyOuter(howMuch, simulate)
|
||||||
public Fraction receiveEnergyInner(Fraction howMuch, boolean simulate) {
|
|
||||||
return receiveEnergyOuter(howMuch, simulate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun getEntity(): LivingEntity {
|
||||||
public LivingEntity getEntity() {
|
return ent
|
||||||
return this.ent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
override fun getBatteryLevel(): Fraction {
|
||||||
@Override
|
if (!batteryItemStack.isEmpty) {
|
||||||
public ItemStack getBatteryItemStack() {
|
val resolver = batteryItemStack.getCapability(CapabilityEnergy.ENERGY).resolve()
|
||||||
return battery;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (resolver.isPresent) {
|
||||||
public void setBatteryItemStack(@Nonnull ItemStack stack) {
|
val it = resolver.get()
|
||||||
battery = stack;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
if (it is IMatteryEnergyStorage) {
|
||||||
@Nonnull
|
return energy_stored + it.batteryLevel
|
||||||
public Fraction getBatteryLevel() {
|
} else {
|
||||||
if (battery != ItemStack.EMPTY) {
|
return energy_stored + it.energyStored
|
||||||
Optional<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve();
|
}
|
||||||
|
|
||||||
if (get_mattery.isPresent()) {
|
|
||||||
return get_mattery.get().getBatteryLevel().plus(energy_stored);
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve();
|
|
||||||
|
|
||||||
if (get_energy.isPresent()) {
|
|
||||||
return energy_stored.plus(get_energy.get().getEnergyStored());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return energy_stored;
|
return energy_stored
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun getMaxBatteryLevel(): Fraction {
|
||||||
@Nonnull
|
if (batteryItemStack != ItemStack.EMPTY) {
|
||||||
public Fraction getMaxBatteryLevel() {
|
val resolver = batteryItemStack.getCapability(CapabilityEnergy.ENERGY).resolve()
|
||||||
if (battery != ItemStack.EMPTY) {
|
|
||||||
Optional<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve();
|
|
||||||
|
|
||||||
if (get_mattery.isPresent()) {
|
if (resolver.isPresent) {
|
||||||
return get_mattery.get().getMaxBatteryLevel().plus(energy_stored_max);
|
val it = resolver.get()
|
||||||
}
|
|
||||||
|
|
||||||
Optional<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve();
|
if (it is IMatteryEnergyStorage) {
|
||||||
|
return energy_stored_max + it.maxBatteryLevel
|
||||||
if (get_energy.isPresent()) {
|
} else {
|
||||||
return energy_stored_max.plus(get_energy.get().getMaxEnergyStored());
|
return energy_stored_max + it.maxEnergyStored
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return energy_stored_max;
|
return energy_stored_max
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LazyOptional<IAndroidCapability> resolver = LazyOptional.of(() -> this).cast();
|
private val resolver = LazyOptional.of { this }
|
||||||
|
|
||||||
@Nonnull
|
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||||
@Override
|
return if (cap === MatteryCapability.ANDROID) {
|
||||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
|
resolver.cast()
|
||||||
if (cap == MatteryCapability.ANDROID) {
|
} else LazyOptional.empty()
|
||||||
return resolver.cast();
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
companion object {
|
||||||
|
@JvmField
|
||||||
|
val UNAFFECTED_EFFECTS: MutableSet<MobEffect> = 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) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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.ChatFormatting
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.ListTag
|
||||||
import net.minecraft.nbt.ListTag;
|
import net.minecraft.nbt.Tag
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.network.chat.TranslatableComponent
|
||||||
import net.minecraft.network.chat.TranslatableComponent;
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.server.level.ServerPlayer
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.world.entity.Entity
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraftforge.event.AttachCapabilitiesEvent
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.event.entity.player.PlayerEvent.Clone
|
||||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
import net.minecraftforge.event.entity.player.PlayerEvent.PlayerChangedDimensionEvent
|
||||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import ru.dbotthepony.mc.otm.Registry
|
||||||
import ru.dbotthepony.mc.otm.Registry;
|
import ru.dbotthepony.mc.otm.android.AndroidResearch
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidResearch;
|
import ru.dbotthepony.mc.otm.android.AndroidResearchType
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidResearchType;
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction;
|
import ru.dbotthepony.mc.otm.network.android.AndroidResearchPacket
|
||||||
import ru.dbotthepony.mc.otm.network.android.AndroidResearchPacket;
|
import ru.dbotthepony.mc.otm.network.android.AndroidStatusPacket
|
||||||
import ru.dbotthepony.mc.otm.network.android.AndroidStatusPacket;
|
import ru.dbotthepony.mc.otm.set
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
class AndroidCapabilityPlayer(@JvmField val ply: Player) : AndroidCapability(ply) {
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
@JvmField
|
||||||
import java.math.BigDecimal;
|
var is_android = false
|
||||||
import java.util.ArrayList;
|
private var network_is_android = false
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
@JvmField
|
||||||
@ParametersAreNonnullByDefault
|
var will_become_android = false
|
||||||
public class AndroidCapabilityPlayer extends AndroidCapability {
|
private var network_will_become_android = false
|
||||||
public boolean is_android = false;
|
private val research = ArrayList<AndroidResearch>()
|
||||||
private boolean network_is_android = false;
|
|
||||||
|
|
||||||
public boolean will_become_android = false;
|
override fun invalidateNetworkState() {
|
||||||
private boolean network_will_become_android = false;
|
super.invalidateNetworkState()
|
||||||
|
|
||||||
private final ArrayList<AndroidResearch> research_list = new ArrayList<>();
|
network_is_android = false
|
||||||
|
network_will_become_android = false
|
||||||
|
|
||||||
@Override
|
for (instance in research) {
|
||||||
public void invalidateNetworkState() {
|
instance.dirty = true
|
||||||
super.invalidateNetworkState();
|
|
||||||
network_is_android = false;
|
|
||||||
network_will_become_android = false;
|
|
||||||
|
|
||||||
for (var instance : research_list) {
|
|
||||||
instance.dirty = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun isAndroid(): Boolean = is_android
|
||||||
public boolean isAndroid() {
|
fun isEverAndroid(): Boolean = is_android || will_become_android
|
||||||
return is_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() {
|
fun becomeAndroid() {
|
||||||
return is_android || will_become_android;
|
if (is_android) return
|
||||||
|
|
||||||
|
is_android = true
|
||||||
|
will_become_android = false
|
||||||
|
energy_stored = Fraction(60000)
|
||||||
|
energy_stored_max = Fraction(60000)
|
||||||
}
|
}
|
||||||
|
|
||||||
public void becomeAndroidSoft() {
|
fun becomeAndroidAndKill() {
|
||||||
if (is_android || will_become_android)
|
if (is_android) return
|
||||||
return;
|
|
||||||
|
|
||||||
will_become_android = true;
|
becomeAndroid()
|
||||||
|
ply.hurt(Registry.DAMAGE_BECOME_ANDROID, ply.maxHealth * 2)
|
||||||
if (ent instanceof ServerPlayer ply) {
|
|
||||||
ply.displayClientMessage(new TranslatableComponent("otm.pill.message").withStyle(ChatFormatting.GRAY), false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void becomeAndroid() {
|
fun becomeHumane() {
|
||||||
if (is_android)
|
if (will_become_android) will_become_android = false
|
||||||
return;
|
if (!is_android) return
|
||||||
|
|
||||||
is_android = true;
|
is_android = false
|
||||||
will_become_android = false;
|
energy_stored = Fraction(0)
|
||||||
energy_stored = new Fraction(60_000);
|
energy_stored_max = Fraction(60000)
|
||||||
energy_stored_max = new Fraction(60_000);
|
dropBattery()
|
||||||
}
|
}
|
||||||
|
|
||||||
public void becomeAndroidAndKill() {
|
fun becomeHumaneAndKill() {
|
||||||
if (is_android)
|
if (will_become_android) will_become_android = false
|
||||||
return;
|
if (!is_android) return
|
||||||
|
|
||||||
becomeAndroid();
|
becomeHumane()
|
||||||
ply.hurt(Registry.DAMAGE_BECOME_ANDROID, ply.getMaxHealth() * 2);
|
ply.hurt(Registry.DAMAGE_BECOME_HUMANE, ply.maxHealth * 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
public void becomeHumane() {
|
override fun deserializeNBT(compound: CompoundTag?) {
|
||||||
if (will_become_android)
|
super.deserializeNBT(compound!!)
|
||||||
will_become_android = false;
|
|
||||||
|
|
||||||
if (!is_android)
|
is_android = compound.getBoolean("is_android")
|
||||||
return;
|
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);
|
for (tag in list) {
|
||||||
energy_stored_max = new Fraction(60_000);
|
if (tag is CompoundTag) {
|
||||||
|
val research = Registry.ANDROID_RESEARCH.getValue(ResourceLocation(tag.getString("id")))
|
||||||
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")));
|
|
||||||
|
|
||||||
if (research != null) {
|
if (research != null) {
|
||||||
var instance = research.factory(this);
|
val instance = research.factory(this)
|
||||||
instance.deserializeNBT(tag);
|
instance.deserializeNBT(tag)
|
||||||
research_list.add(instance);
|
this.research.add(instance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
override fun serializeNBT(): CompoundTag {
|
||||||
@Override
|
val tag = super.serializeNBT()
|
||||||
public CompoundTag serializeNBT() {
|
|
||||||
CompoundTag tag = super.serializeNBT();
|
|
||||||
tag.putBoolean("is_android", is_android);
|
|
||||||
tag.putBoolean("will_become_android", will_become_android);
|
|
||||||
|
|
||||||
var list = new ListTag();
|
tag["is_android"] = is_android
|
||||||
|
tag["will_become_android"] = will_become_android
|
||||||
|
|
||||||
for (var instance : research_list) {
|
val list = ListTag()
|
||||||
var _tag = new CompoundTag();
|
|
||||||
instance.serializeNBT(_tag);
|
for (instance in research) {
|
||||||
_tag.putString("id", Objects.requireNonNull(instance.type.getRegistryName()).toString());
|
val researchTag = CompoundTag()
|
||||||
list.add(_tag);
|
instance.serializeNBT(researchTag)
|
||||||
|
|
||||||
|
researchTag["id"] = instance.type.registryName!!.toString()
|
||||||
|
list.add(researchTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
tag.put("research", list);
|
tag["research"] = list
|
||||||
|
return tag
|
||||||
return tag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
fun <T : AndroidResearch> getResearch(type: AndroidResearchType<T>): T {
|
||||||
public <T extends AndroidResearch> T getResearch(AndroidResearchType<T> type) {
|
for (instance in research) {
|
||||||
for (var instance : research_list) {
|
if (instance.type === type) {
|
||||||
if (instance.type == type) {
|
return instance as T
|
||||||
return (T) instance;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var instance = type.factory(this);
|
val instance = type.factory(this)
|
||||||
research_list.add(instance);
|
research.add(instance)
|
||||||
return instance;
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@JvmField
|
||||||
@SuppressWarnings("unused")
|
var last_jump_ticks = 14
|
||||||
public static void onAttachCapabilityEvent(AttachCapabilitiesEvent<Entity> 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<IAndroidCapability> 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();
|
|
||||||
|
|
||||||
|
override fun tickNetwork() {
|
||||||
|
super.tickNetwork()
|
||||||
if (is_android != network_is_android) {
|
if (is_android != network_is_android) {
|
||||||
network_is_android = is_android;
|
network_is_android = is_android
|
||||||
sendNetwork(new AndroidStatusPacket(AndroidStatusPacket.Type.IS_ANDROID, is_android));
|
sendNetwork(AndroidStatusPacket(AndroidStatusPacket.Type.IS_ANDROID, is_android))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (will_become_android != network_will_become_android) {
|
if (will_become_android != network_will_become_android) {
|
||||||
network_will_become_android = will_become_android;
|
network_will_become_android = will_become_android
|
||||||
sendNetwork(new AndroidStatusPacket(AndroidStatusPacket.Type.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) {
|
if (instance.dirty) {
|
||||||
instance.dirty = false;
|
instance.dirty = false
|
||||||
sendNetwork(new AndroidResearchPacket(instance));
|
sendNetwork(AndroidResearchPacket(instance))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Fraction ENERGY_FOR_HUNGER_POINT = new Fraction(1000);
|
@JvmField
|
||||||
|
var sleep_ticks = 0
|
||||||
|
|
||||||
public int sleep_ticks = 0;
|
override fun tickInnerClientAlways() {
|
||||||
public static final int SLEEP_TICKS_LIMIT = 80;
|
super.tickInnerClientAlways()
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tickInnerClientAlways() {
|
|
||||||
super.tickInnerClientAlways();
|
|
||||||
|
|
||||||
if (will_become_android) {
|
if (will_become_android) {
|
||||||
if (ent.isSleeping()) {
|
if (ply.isSleeping) {
|
||||||
sleep_ticks++;
|
sleep_ticks++
|
||||||
} else {
|
} else {
|
||||||
sleep_ticks = 0;
|
sleep_ticks = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun tickServerAlways() {
|
||||||
protected void tickServerAlways() {
|
super.tickServerAlways()
|
||||||
super.tickServerAlways();
|
|
||||||
|
|
||||||
if (will_become_android) {
|
if (will_become_android) {
|
||||||
if (ent.isSleeping()) {
|
if (ply.isSleeping) {
|
||||||
sleep_ticks++;
|
sleep_ticks++
|
||||||
|
|
||||||
if (sleep_ticks > SLEEP_TICKS_LIMIT) {
|
if (sleep_ticks > SLEEP_TICKS_LIMIT) {
|
||||||
becomeAndroid();
|
becomeAndroid()
|
||||||
sleep_ticks = 0;
|
sleep_ticks = 0
|
||||||
|
|
||||||
if (ent instanceof ServerPlayer ply) {
|
(ply as? ServerPlayer)?.displayClientMessage(TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false)
|
||||||
ply.displayClientMessage(new TranslatableComponent("otm.pill.message_finish").withStyle(ChatFormatting.DARK_RED), false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sleep_ticks = 0;
|
sleep_ticks = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public override fun tickServer() {
|
||||||
public void tickServer() {
|
super.tickServer()
|
||||||
super.tickServer();
|
|
||||||
|
|
||||||
// TODO: Maybe passive drain?
|
// TODO: Maybe passive drain?
|
||||||
// extractEnergyInner(BigDecimal.valueOf(new Random().nextDouble()), false);
|
// extractEnergyInner(BigDecimal.valueOf(new Random().nextDouble()), false);
|
||||||
|
if (ply.isSwimming && !hasFeature(Registry.AndroidFeatures.AIR_BAGS)) {
|
||||||
if (ply.isSwimming() && !hasFeature(Registry.AndroidFeatures.AIR_BAGS)) {
|
ply.isSwimming = false
|
||||||
ply.setSwimming(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) {
|
while (stats.foodLevel < 18 && extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) {
|
||||||
this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false);
|
extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false)
|
||||||
stats.setFoodLevel(stats.getFoodLevel() + 1);
|
stats.foodLevel = stats.foodLevel + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// "block" quick regeneration
|
// "block" quick regeneration
|
||||||
// also cause power to generate while in peaceful
|
// 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) {
|
while (stats.foodLevel > 18 && receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, true) >= ENERGY_FOR_HUNGER_POINT) {
|
||||||
this.receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, false);
|
receiveEnergyInner(ENERGY_FOR_HUNGER_POINT, false)
|
||||||
stats.setFoodLevel(stats.getFoodLevel() - 1);
|
stats.foodLevel = stats.foodLevel - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var food_level = (float) stats.getFoodLevel();
|
val foodLevel = stats.foodLevel.toFloat()
|
||||||
|
|
||||||
if (stats.getSaturationLevel() < food_level) {
|
if (stats.saturationLevel < foodLevel) {
|
||||||
Fraction extracted = this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT.times(food_level - stats.getSaturationLevel()), false);
|
val extracted = extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (foodLevel - stats.saturationLevel), false)
|
||||||
stats.setSaturation(stats.getSaturationLevel() + extracted.div(ENERGY_FOR_HUNGER_POINT).toFloat());
|
stats.setSaturation(stats.saturationLevel + (extracted / ENERGY_FOR_HUNGER_POINT).toFloat())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stats.getExhaustionLevel() > 0f) {
|
if (stats.exhaustionLevel > 0f) {
|
||||||
Fraction extracted = this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT.times(stats.getExhaustionLevel() / 4f), false);
|
val extracted = extractEnergyInner(ENERGY_FOR_HUNGER_POINT * (stats.exhaustionLevel / 4f), false)
|
||||||
stats.setExhaustion(stats.getExhaustionLevel() - extracted.div(ENERGY_FOR_HUNGER_POINT).toFloat() * 4f);
|
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(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
|
||||||
|
}
|
||||||
}
|
}
|
@ -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.nbt.CompoundTag;
|
import net.minecraft.world.entity.LivingEntity
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraftforge.common.util.INBTSerializable
|
||||||
import net.minecraftforge.common.util.INBTSerializable;
|
import net.minecraftforge.event.entity.living.LivingHurtEvent
|
||||||
import net.minecraftforge.event.entity.living.LivingHurtEvent;
|
import ru.dbotthepony.mc.otm.android.AndroidFeature
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidFeature;
|
import ru.dbotthepony.mc.otm.android.AndroidFeatureType
|
||||||
import ru.dbotthepony.mc.otm.android.AndroidFeatureType;
|
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction;
|
import java.util.*
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
interface IAndroidCapability : IMatteryEnergyStorage, INBTSerializable<CompoundTag?> {
|
||||||
import javax.annotation.Nullable;
|
fun tick()
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
fun tickClient()
|
||||||
import java.math.BigDecimal;
|
fun getEntity(): LivingEntity
|
||||||
import java.util.Optional;
|
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
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
fun <T : AndroidFeature> getFeature(feature: AndroidFeatureType<T>): T?
|
||||||
@ParametersAreNonnullByDefault
|
|
||||||
public interface IAndroidCapability extends IMatteryEnergyStorage, INBTSerializable<CompoundTag> {
|
|
||||||
void tick();
|
|
||||||
void tickClient();
|
|
||||||
LivingEntity getEntity();
|
|
||||||
|
|
||||||
<T extends AndroidFeature> T addFeature(AndroidFeatureType<T> feature);
|
fun <T : AndroidFeature> getFeatureO(feature: AndroidFeatureType<T>): Optional<T> {
|
||||||
boolean removeFeature(AndroidFeatureType<?> feature);
|
val get = getFeature(feature)
|
||||||
boolean hasFeature(@Nullable AndroidFeatureType<?> feature);
|
return if (get != null) Optional.of(get) else Optional.empty()
|
||||||
boolean hasFeatureLevel(@Nullable AndroidFeatureType<?> feature, int level);
|
|
||||||
@Nullable
|
|
||||||
<T extends AndroidFeature> T getFeature(AndroidFeatureType<T> feature);
|
|
||||||
|
|
||||||
default <T extends AndroidFeature> Optional<T> getFeatureO(AndroidFeatureType<T> feature) {
|
|
||||||
var get = getFeature(feature);
|
|
||||||
return get != null ? Optional.of(get) : Optional.empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean isAndroid() {
|
fun <T : AndroidFeature> ifFeature(feature: AndroidFeatureType<T>, consumer: (T) -> Unit) {
|
||||||
return true;
|
val get = getFeature(feature)
|
||||||
|
|
||||||
|
if (get != null) {
|
||||||
|
consumer(get)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default void onHurt(LivingHurtEvent event) {}
|
|
||||||
|
|
||||||
ItemStack getBatteryItemStack();
|
fun isAndroid(): Boolean = true
|
||||||
void setBatteryItemStack(ItemStack stack);
|
|
||||||
|
|
||||||
void invalidateNetworkState(); // tell capability that player forgot everything, and everything needs to be re-networked
|
fun onHurt(event: LivingHurtEvent?) {}
|
||||||
|
var batteryItemStack: ItemStack
|
||||||
void setEnergy(Fraction value);
|
fun invalidateNetworkState() // tell capability that player forgot everything, and everything needs to be re-networked
|
||||||
void setMaxEnergy(Fraction value);
|
fun setEnergy(value: Fraction?)
|
||||||
|
fun setMaxEnergy(value: Fraction?)
|
||||||
}
|
}
|
@ -19,9 +19,7 @@ import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
|
|||||||
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu
|
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
class AndroidStationScreen constructor(p_97741_: AndroidStationMenu, p_97742_: Inventory, p_97743_: Component) :
|
||||||
|
|
||||||
class AndroidStationScreen(p_97741_: AndroidStationMenu, p_97742_: Inventory, p_97743_: Component) :
|
|
||||||
MatteryScreen<AndroidStationMenu>(p_97741_, p_97742_, p_97743_) {
|
MatteryScreen<AndroidStationMenu>(p_97741_, p_97742_, p_97743_) {
|
||||||
|
|
||||||
internal inner class AndroidResearchButton(parent: EditablePanel?, private val node: AndroidResearch) :
|
internal inner class AndroidResearchButton(parent: EditablePanel?, private val node: AndroidResearch) :
|
||||||
|
@ -53,7 +53,7 @@ class ItemPill(val pillType: PillType) :
|
|||||||
|
|
||||||
val cap = resolver.get() as AndroidCapabilityPlayer
|
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)
|
ply.startUsingItem(hand)
|
||||||
return InteractionResultHolder.consume(ply.getItemInHand(hand))
|
return InteractionResultHolder.consume(ply.getItemInHand(hand))
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ class ItemPill(val pillType: PillType) :
|
|||||||
|
|
||||||
val cap = resolver.get() as AndroidCapabilityPlayer
|
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.abilities.instabuild) {
|
||||||
if (ent is ServerPlayer) {
|
if (ent is ServerPlayer) {
|
||||||
cap.becomeAndroid()
|
cap.becomeAndroid()
|
||||||
@ -85,7 +85,7 @@ class ItemPill(val pillType: PillType) :
|
|||||||
cap.becomeAndroidSoft()
|
cap.becomeAndroidSoft()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (pillType == PillType.BECOME_HUMANE && cap.isEverAndroid) {
|
} else if (pillType == PillType.BECOME_HUMANE && cap.isEverAndroid()) {
|
||||||
if (ent.abilities.instabuild) {
|
if (ent.abilities.instabuild) {
|
||||||
if (ent is ServerPlayer) {
|
if (ent is ServerPlayer) {
|
||||||
cap.becomeHumane()
|
cap.becomeHumane()
|
||||||
|
Loading…
Reference in New Issue
Block a user