提交
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
package thaumicenergistics.common.tiles;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import thaumcraft.api.aspects.Aspect;
|
||||
import thaumcraft.api.aspects.IEssentiaTransport;
|
||||
import thaumcraft.common.essentia.EssentiaTransport;
|
||||
import thaumicenergistics.ThaumicEnergistics;
|
||||
import thaumicenergistics.api.storage.IAspectStack;
|
||||
import thaumicenergistics.init.ModBlockEntities;
|
||||
import thaumicenergistics.init.ModItems;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TileEssentiaProvider extends TileProviderBase implements IEssentiaTransport, EssentiaTransport {
|
||||
|
||||
private static final int TICK_RATE_IDLE = 15;
|
||||
private static final int TICK_RATE_URGENT = 5;
|
||||
private int tickCount;
|
||||
private int tickRate = TICK_RATE_IDLE;
|
||||
|
||||
public TileEssentiaProvider(BlockPos pos, BlockState state) {
|
||||
super(ModBlockEntities.ESSENTIA_PROVIDER.get(), pos, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemStack getItemFromTile() {
|
||||
return new ItemStack(ModItems.ESSENTIA_PROVIDER_ITEM.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getIdlePowerUsage() {
|
||||
return 3.0;
|
||||
}
|
||||
|
||||
/** getEssentiaList 短时缓存:TC 管道 suction 每 tick 调 getEssentiaType,避免每 tick 全量遍历。 */
|
||||
private List<IAspectStack> cachedEssentiaList = java.util.List.of();
|
||||
private int essentiaListCacheTimer = 0;
|
||||
private static final int ESSENTIA_LIST_CACHE_TICKS = 20;
|
||||
|
||||
private List<thaumicenergistics.api.storage.IAspectStack> getCachedEssentiaList() {
|
||||
if (essentiaListCacheTimer <= 0) {
|
||||
essentiaListCacheTimer = ESSENTIA_LIST_CACHE_TICKS;
|
||||
cachedEssentiaList = essentiaGrid != null ? essentiaGrid.getEssentiaList() : java.util.List.of();
|
||||
}
|
||||
return cachedEssentiaList;
|
||||
}
|
||||
|
||||
public void serverTick() {
|
||||
if (level == null || level.isClientSide()) return;
|
||||
if (!mainNode.isActive()) return;
|
||||
|
||||
if (essentiaListCacheTimer > 0) essentiaListCacheTimer--;
|
||||
|
||||
if (++tickCount >= tickRate) {
|
||||
tickCount = 0;
|
||||
tickRate = TICK_RATE_IDLE;
|
||||
takeEssentiaFromTransportNeighbors();
|
||||
}
|
||||
}
|
||||
|
||||
// ===== IEssentiaTransport =====
|
||||
|
||||
@Override
|
||||
public boolean isConnectable(Direction side) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInputFrom(Direction side) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canOutputTo(Direction side) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSuction(Aspect aspect, int amount) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Aspect getSuctionType(Direction side) {
|
||||
return null; // 接受所有类型
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSuctionAmount(Direction side) {
|
||||
return 8; // 最大吸力
|
||||
}
|
||||
|
||||
@Override
|
||||
public int takeEssentia(Aspect aspect, int amount, Direction side) {
|
||||
ThaumicEnergistics.LOG.debug("[MyHano-E] takeEssentia: aspect={}, amount={}, side={}, active={}",
|
||||
aspect != null ? aspect.getTag() : "null", amount, side, mainNode.isActive());
|
||||
if (!mainNode.isActive()) return 0;
|
||||
long extracted = extractEssentiaFromNetwork(aspect, amount, false);
|
||||
ThaumicEnergistics.LOG.debug("[MyHano-E] takeEssentia result={}", extracted);
|
||||
if (extracted > 0) {
|
||||
tickRate = TICK_RATE_URGENT;
|
||||
}
|
||||
return (int) extracted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int addEssentia(Aspect aspect, int amount, Direction side) {
|
||||
ThaumicEnergistics.LOG.debug("[MyHano-E] addEssentia: aspect={}, amount={}, side={}, active={}",
|
||||
aspect != null ? aspect.getTag() : "null", amount, side, mainNode.isActive());
|
||||
if (!mainNode.isActive()) return 0;
|
||||
long rejected = injectEssentiaToNetwork(aspect, amount, false);
|
||||
long accepted = amount - rejected;
|
||||
if (accepted > 0) {
|
||||
ThaumicEnergistics.LOG.debug("[MyHano-E] addEssentia accepted={}", accepted);
|
||||
tickRate = TICK_RATE_URGENT;
|
||||
}
|
||||
return (int) accepted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Aspect getEssentiaType(Direction side) {
|
||||
Aspect wanted = getNeighborWantedAspect(side);
|
||||
if (wanted != null && getAspectAmountInNetwork(wanted) > 0) {
|
||||
return wanted;
|
||||
}
|
||||
// 邻居无特定需求时,返回网络中第一种有存量的源质(列表短时缓存,避免 TC 管道每 tick suction 全量遍历)
|
||||
if (essentiaGrid != null) {
|
||||
for (var stack : getCachedEssentiaList()) {
|
||||
if (stack.amount() > 0) {
|
||||
return Aspect.getAspect(stack.aspectId().getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEssentiaAmount(Direction side) {
|
||||
Aspect wanted = getNeighborWantedAspect(side);
|
||||
if (wanted != null) {
|
||||
return (int) Math.min(getAspectAmountInNetwork(wanted), Integer.MAX_VALUE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimumSuction() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean renderExtendedTube() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ===== 内部 =====
|
||||
|
||||
private Aspect getNeighborWantedAspect(Direction side) {
|
||||
BlockPos neighborPos = worldPosition.relative(side);
|
||||
BlockEntity neighbor = level.getBlockEntity(neighborPos);
|
||||
if (neighbor instanceof IEssentiaTransport transport) {
|
||||
return transport.getSuctionType(side.getOpposite());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void takeEssentiaFromTransportNeighbors() {
|
||||
for (Direction side : Direction.values()) {
|
||||
if (!canInputFrom(side)) continue;
|
||||
|
||||
BlockPos sourcePos = worldPosition.relative(side);
|
||||
BlockEntity sourceTile = level.getBlockEntity(sourcePos);
|
||||
if (!(sourceTile instanceof IEssentiaTransport source)) continue;
|
||||
|
||||
Direction sourceSide = side.getOpposite();
|
||||
if (!source.canOutputTo(sourceSide)) continue;
|
||||
if (source.getEssentiaAmount(sourceSide) <= 0) continue;
|
||||
|
||||
int dSuck = getSuctionAmount(side);
|
||||
if (dSuck < source.getMinimumSuction() || dSuck < source.getSuctionAmount(sourceSide)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Aspect sourceAspect = source.getEssentiaType(sourceSide);
|
||||
if (sourceAspect == null) continue;
|
||||
|
||||
// 模拟注入
|
||||
long simulated = injectEssentiaToNetwork(sourceAspect, 1, true);
|
||||
if (simulated == 0) {
|
||||
// 实际提取并注入
|
||||
int taken = source.takeEssentia(sourceAspect, 1, sourceSide);
|
||||
if (taken > 0) {
|
||||
injectEssentiaToNetwork(sourceAspect, taken, false);
|
||||
tickRate = TICK_RATE_URGENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user