正确实现实体能量存储能力

This commit is contained in:
Light_Quanta 2025-02-19 14:23:19 +08:00
parent f4e1f495f1
commit 76456c5a93
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
6 changed files with 103 additions and 61 deletions

View file

@ -0,0 +1,64 @@
package com.atsuishio.superbwarfare.capability.energy;
import net.minecraft.nbt.Tag;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraftforge.energy.EnergyStorage;
/**
* 自动同步的实体能量存储能力会和客户端自动同步实体的当前能量值
*/
public class SyncedEntityEnergyStorage extends EnergyStorage {
protected SynchedEntityData entityData;
protected EntityDataAccessor<Integer> energyDataAccessor;
/**
* 自动同步的实体能量存储能力
*
* @param capacity 能量上限
* @param data 实体的entityData
* @param energyDataAccessor 能量的EntityDataAccessor
*/
public SyncedEntityEnergyStorage(int capacity, SynchedEntityData data, EntityDataAccessor<Integer> energyDataAccessor) {
super(capacity, capacity, capacity, 0);
this.entityData = data;
this.energyDataAccessor = energyDataAccessor;
}
@Override
public int receiveEnergy(int maxReceive, boolean simulate) {
var received = super.receiveEnergy(maxReceive, simulate);
if (!simulate) {
entityData.set(energyDataAccessor, this.energy);
}
return received;
}
@Override
public int extractEnergy(int maxExtract, boolean simulate) {
var extracted = super.extractEnergy(maxExtract, simulate);
if (!simulate) {
entityData.set(energyDataAccessor, energy);
}
return extracted;
}
@Override
public int getEnergyStored() {
// 获取同步数据保证客户端能正确获得能量值
return entityData.get(energyDataAccessor);
}
@Override
public void deserializeNBT(Tag nbt) {
super.deserializeNBT(nbt);
entityData.set(energyDataAccessor, energy);
}
}

View file

@ -1,8 +1,6 @@
package com.atsuishio.superbwarfare.compat.jade;
import com.atsuishio.superbwarfare.compat.jade.providers.VehicleEnergyProvider;
import com.atsuishio.superbwarfare.compat.jade.providers.VehicleHealthProvider;
import com.atsuishio.superbwarfare.entity.vehicle.EnergyVehicleEntity;
import com.atsuishio.superbwarfare.entity.vehicle.VehicleEntity;
import snownee.jade.api.IWailaClientRegistration;
import snownee.jade.api.IWailaCommonRegistration;
@ -14,12 +12,11 @@ public class SbwJadePlugin implements IWailaPlugin {
@Override
public void register(IWailaCommonRegistration registration) {
registration.registerEntityDataProvider(VehicleEnergyProvider.INSTANCE, EnergyVehicleEntity.class);
}
@Override
public void registerClient(IWailaClientRegistration registration) {
registration.registerEntityComponent(VehicleHealthProvider.INSTANCE, VehicleEntity.class);
registration.registerEntityComponent(VehicleEnergyProvider.INSTANCE, EnergyVehicleEntity.class);
}
}

View file

@ -1,49 +0,0 @@
package com.atsuishio.superbwarfare.compat.jade.providers;
import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.entity.vehicle.EnergyVehicleEntity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import snownee.jade.api.EntityAccessor;
import snownee.jade.api.IEntityComponentProvider;
import snownee.jade.api.IServerDataProvider;
import snownee.jade.api.ITooltip;
import snownee.jade.api.config.IPluginConfig;
public enum VehicleEnergyProvider implements IEntityComponentProvider,
IServerDataProvider<EntityAccessor> {
INSTANCE;
private static final ResourceLocation ID = ModUtils.loc("vehicle_energy");
@Override
public void appendTooltip(
ITooltip tooltip,
EntityAccessor accessor,
IPluginConfig config
) {
// TODO 正确实现能量显示
if (!accessor.getServerData().contains("Energy")) return;
tooltip.add(
Component.translatable(
accessor.getServerData().getInt("Energy")
+ " / "
+ accessor.getServerData().getInt("MaxEnergy")
)
);
}
@Override
public void appendServerData(CompoundTag data, EntityAccessor accessor) {
var vehicle = (EnergyVehicleEntity) accessor.getEntity();
data.putInt("Energy", vehicle.getEnergy());
data.putInt("MaxEnergy", vehicle.getMaxEnergy());
}
@Override
public ResourceLocation getUid() {
return ID;
}
}

View file

@ -469,7 +469,7 @@ public class AnnihilatorEntity extends EnergyVehicleEntity implements GeoEntity,
}
public void autoAim() {
if (this.entityData.get(ENERGY) <= 0) return;
if (this.getEnergy() <= 0) return;
Entity target = SeekTool.seekLivingEntity(this, this.level(), 64, 30);

View file

@ -1,18 +1,28 @@
package com.atsuishio.superbwarfare.entity.vehicle;
import com.atsuishio.superbwarfare.capability.energy.SyncedEntityEnergyStorage;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.IntTag;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.Level;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.IEnergyStorage;
import org.jetbrains.annotations.NotNull;
import org.joml.Math;
public class EnergyVehicleEntity extends VehicleEntity implements IChargeEntity {
public static final EntityDataAccessor<Integer> ENERGY = SynchedEntityData.defineId(EnergyVehicleEntity.class, EntityDataSerializers.INT);
protected final SyncedEntityEnergyStorage energyStorage = new SyncedEntityEnergyStorage(this.getMaxEnergy(), this.entityData, ENERGY);
protected final LazyOptional<IEnergyStorage> energy = LazyOptional.of(() -> energyStorage);
public EnergyVehicleEntity(EntityType<?> pEntityType, Level pLevel) {
super(pEntityType, pLevel);
this.setEnergy(0);
@ -27,13 +37,21 @@ public class EnergyVehicleEntity extends VehicleEntity implements IChargeEntity
@Override
protected void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
this.entityData.set(ENERGY, compound.getInt("Energy"));
if (compound.get("Energy") instanceof IntTag energyNBT) {
energyStorage.deserializeNBT(energyNBT);
}
}
@Override
public void invalidateCaps() {
super.invalidateCaps();
energy.invalidate();
}
@Override
public void addAdditionalSaveData(CompoundTag compound) {
super.addAdditionalSaveData(compound);
compound.putInt("Energy", this.entityData.get(ENERGY));
compound.put("Energy", energyStorage.serializeNBT());
}
/**
@ -42,7 +60,7 @@ public class EnergyVehicleEntity extends VehicleEntity implements IChargeEntity
* @param amount 要消耗的电量
*/
public void consumeEnergy(int amount) {
this.setEnergy(Math.max(0, this.getEnergy() - amount));
this.energyStorage.extractEnergy(amount, false);
}
public boolean canConsume(int amount) {
@ -50,11 +68,17 @@ public class EnergyVehicleEntity extends VehicleEntity implements IChargeEntity
}
public int getEnergy() {
return this.entityData.get(ENERGY);
return this.energyStorage.getEnergyStored();
}
public void setEnergy(int pEnergy) {
this.entityData.set(ENERGY, Mth.clamp(pEnergy, 0, this.getMaxEnergy()));
int targetEnergy = Mth.clamp(pEnergy, 0, this.getMaxEnergy());
if (targetEnergy > energyStorage.getEnergyStored()) {
energyStorage.receiveEnergy(targetEnergy - energyStorage.getEnergyStored(), false);
} else {
energyStorage.extractEnergy(energyStorage.getEnergyStored() - targetEnergy, false);
}
}
public int getMaxEnergy() {
@ -72,4 +96,9 @@ public class EnergyVehicleEntity extends VehicleEntity implements IChargeEntity
public boolean canCharge() {
return this.getEnergy() < this.getMaxEnergy();
}
@Override
public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap) {
return ForgeCapabilities.ENERGY.orEmpty(cap, energy);
}
}

View file

@ -291,9 +291,10 @@ public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity,
}
public void autoAim() {
if (this.entityData.get(ENERGY) <= 0 || !entityData.get(ACTIVE) || this.entityData.get(COOL_DOWN) > 30) return;
if (this.getEnergy() <= 0 || !entityData.get(ACTIVE) || this.entityData.get(COOL_DOWN) > 30)
return;
if (entityData.get(TARGET_UUID).equals("none") && tickCount %10 == 0) {
if (entityData.get(TARGET_UUID).equals("none") && tickCount % 10 == 0) {
Entity naerestEntity = seekNearLivingEntity(72);
if (naerestEntity != null) {
entityData.set(TARGET_UUID, naerestEntity.getStringUUID());