122 lines
4.2 KiB
Java
122 lines
4.2 KiB
Java
package li.cil.oc2.common.blockentity;
|
|
|
|
import li.cil.oc2.api.capabilities.NetworkInterface;
|
|
import li.cil.oc2.common.Constants;
|
|
import li.cil.oc2.common.capabilities.Capabilities;
|
|
import li.cil.oc2.common.util.LazyOptionalUtils;
|
|
import li.cil.oc2.common.util.LevelUtils;
|
|
import li.cil.oc2.common.vxlan.TunnelManager;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraftforge.common.util.LazyOptional;
|
|
|
|
import javax.annotation.Nullable;
|
|
import java.util.Arrays;
|
|
import java.util.Objects;
|
|
import java.util.stream.Stream;
|
|
|
|
public final class VxlanBlockEntity extends ModBlockEntity implements NetworkInterface {
|
|
private static final int TTL_COST = 1;
|
|
private int vti = ((int) (Math.random() * Integer.MAX_VALUE)) & 0x00ff_ffff;
|
|
private boolean initialized = false;
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
// Each face and the default TunnelInterface connecting to the outernet
|
|
private final NetworkInterface[] adjacentBlockInterfaces = new NetworkInterface[Constants.BLOCK_FACE_COUNT + 1];
|
|
private boolean haveAdjacentBlocksChanged = true;
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
public VxlanBlockEntity(final BlockPos pos, final BlockState state) {
|
|
super(BlockEntities.NETWORK_HUB.get(), pos, state);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
public void handleNeighborChanged() {
|
|
haveAdjacentBlocksChanged = true;
|
|
}
|
|
|
|
@Override
|
|
public byte[] readEthernetFrame() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void writeEthernetFrame(final NetworkInterface source, final byte[] frame, final int timeToLive) {
|
|
getAdjacentInterfaces().forEach(adjacentInterface -> {
|
|
if (adjacentInterface != source) {
|
|
adjacentInterface.writeEthernetFrame(this, frame, timeToLive - TTL_COST);
|
|
}
|
|
});
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
@Override
|
|
public void load(CompoundTag tag) {
|
|
super.load(tag);
|
|
vti = tag.getInt("vti");
|
|
}
|
|
|
|
@Override
|
|
protected void onUnload(final boolean isRemove) {
|
|
TunnelManager.instance().unregisterVti(vti);
|
|
|
|
super.onUnload(isRemove);
|
|
}
|
|
|
|
@Override
|
|
public void onLoad() {
|
|
super.onLoad();
|
|
|
|
TunnelManager.instance().registerVti(vti, this);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
@Override
|
|
protected void collectCapabilities(final CapabilityCollector collector, @Nullable final Direction direction) {
|
|
collector.offer(Capabilities.NETWORK_INTERFACE, this);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
private Stream<NetworkInterface> getAdjacentInterfaces() {
|
|
validateAdjacentBlocks();
|
|
return Arrays.stream(adjacentBlockInterfaces).filter(Objects::nonNull);
|
|
}
|
|
|
|
private void validateAdjacentBlocks() {
|
|
if (isRemoved() || !haveAdjacentBlocksChanged) {
|
|
return;
|
|
}
|
|
|
|
for (final Direction side : Constants.DIRECTIONS) {
|
|
adjacentBlockInterfaces[side.get3DDataValue() + 1] = null;
|
|
}
|
|
|
|
haveAdjacentBlocksChanged = false;
|
|
|
|
if (level == null || level.isClientSide()) {
|
|
return;
|
|
}
|
|
|
|
final BlockPos pos = getBlockPos();
|
|
for (final Direction side : Constants.DIRECTIONS) {
|
|
final BlockEntity neighborBlockEntity = LevelUtils.getBlockEntityIfChunkExists(level, pos.relative(side));
|
|
if (neighborBlockEntity != null) {
|
|
final LazyOptional<NetworkInterface> optional = neighborBlockEntity.getCapability(Capabilities.NETWORK_INTERFACE, side.getOpposite());
|
|
optional.ifPresent(adjacentInterface -> {
|
|
adjacentBlockInterfaces[side.get3DDataValue() + 1] = adjacentInterface;
|
|
LazyOptionalUtils.addWeakListener(optional, this, (hub, unused) -> hub.handleNeighborChanged());
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|