First prototype vxlan hub
This commit is contained in:
committed by
Kilobyte22
parent
7eb0d9efce
commit
40cfc418d6
@@ -47,9 +47,9 @@ public final class Config {
|
||||
|
||||
@Path("vxlan") public static boolean enable = false;
|
||||
@Path("vxlan") public static String remoteHost = "::1";
|
||||
@Path("vxlan") public static int remotePort = 4789;
|
||||
@Path("vxlan") public static short remotePort = 4789;
|
||||
@Path("vxlan") public static String bindHost = "::1";
|
||||
@Path("vxlan") public static int bindPort = 4789;
|
||||
@Path("vxlan") public static short bindPort = 4789;
|
||||
|
||||
public static boolean computersUseEnergy() {
|
||||
return computerEnergyPerTick > 0 && computerEnergyStorage > 0;
|
||||
|
||||
@@ -23,6 +23,7 @@ public final class Blocks {
|
||||
public static final RegistryObject<NetworkHubBlock> NETWORK_HUB = BLOCKS.register("network_hub", NetworkHubBlock::new);
|
||||
public static final RegistryObject<ProjectorBlock> PROJECTOR = BLOCKS.register("projector", ProjectorBlock::new);
|
||||
public static final RegistryObject<RedstoneInterfaceBlock> REDSTONE_INTERFACE = BLOCKS.register("redstone_interface", RedstoneInterfaceBlock::new);
|
||||
public static final RegistryObject<VxlanBlock> VXLAN_HUB = BLOCKS.register("vxlan_hub", VxlanBlock::new);
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package li.cil.oc2.common.block;
|
||||
|
||||
import li.cil.oc2.common.blockentity.BlockEntities;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class NetworkPortalBlock extends HorizontalDirectionalBlock implements EntityBlock {
|
||||
|
||||
public NetworkPortalBlock() {
|
||||
super(Properties
|
||||
.of(Material.METAL)
|
||||
.sound(SoundType.METAL)
|
||||
.strength(1.5f, 6.0f));
|
||||
registerDefaultState(getStateDefinition().any().setValue(FACING, Direction.NORTH));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(final BlockPlaceContext context) {
|
||||
return super.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(final BlockPos pos, final BlockState state) {
|
||||
return BlockEntities.NETWORK_HUB.get().create(pos, state);
|
||||
}
|
||||
}
|
||||
62
src/main/java/li/cil/oc2/common/block/VxlanBlock.java
Normal file
62
src/main/java/li/cil/oc2/common/block/VxlanBlock.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package li.cil.oc2.common.block;
|
||||
|
||||
import li.cil.oc2.common.blockentity.BlockEntities;
|
||||
import li.cil.oc2.common.blockentity.NetworkHubBlockEntity;
|
||||
import li.cil.oc2.common.blockentity.VxlanBlockEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.SoundType;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class VxlanBlock extends HorizontalDirectionalBlock implements EntityBlock {
|
||||
public VxlanBlock() {
|
||||
super(Properties
|
||||
.of(Material.METAL)
|
||||
.sound(SoundType.METAL)
|
||||
.strength(1.5f, 6.0f));
|
||||
registerDefaultState(getStateDefinition().any().setValue(FACING, Direction.NORTH));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(final BlockPlaceContext context) {
|
||||
return super.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void neighborChanged(final BlockState state, final Level level, final BlockPos pos, final Block changedBlock, final BlockPos changedBlockPos, final boolean isMoving) {
|
||||
final BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
if (blockEntity instanceof final VxlanBlockEntity vxlanEntity) {
|
||||
vxlanEntity.handleNeighborChanged();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// EntityBlock
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(final BlockPos pos, final BlockState state) {
|
||||
return BlockEntities.VXLAN_HUB.get().create(pos, state);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> builder) {
|
||||
super.createBlockStateDefinition(builder);
|
||||
builder.add(FACING);
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ public final class BlockEntities {
|
||||
public static final RegistryObject<BlockEntityType<NetworkHubBlockEntity>> NETWORK_HUB = register(Blocks.NETWORK_HUB, NetworkHubBlockEntity::new);
|
||||
public static final RegistryObject<BlockEntityType<ProjectorBlockEntity>> PROJECTOR = register(Blocks.PROJECTOR, ProjectorBlockEntity::new);
|
||||
public static final RegistryObject<BlockEntityType<RedstoneInterfaceBlockEntity>> REDSTONE_INTERFACE = register(Blocks.REDSTONE_INTERFACE, RedstoneInterfaceBlockEntity::new);
|
||||
public static final RegistryObject<BlockEntityType<VxlanBlockEntity>> VXLAN_HUB = register(Blocks.VXLAN_HUB, VxlanBlockEntity::new);
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
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());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package li.cil.oc2.common.vxlan;
|
||||
|
||||
import li.cil.oc2.api.capabilities.NetworkInterface;
|
||||
import li.cil.oc2.common.Config;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
@@ -9,11 +10,19 @@ import java.util.HashMap;
|
||||
|
||||
public class TunnelManager {
|
||||
|
||||
private final HashMap<Integer, NetworkInterface> tunnels = new HashMap<>();
|
||||
private final HashMap<Integer, TunnelInterface> tunnels = new HashMap<>();
|
||||
private final DatagramSocket socket;
|
||||
private static TunnelManager INSTANCE;
|
||||
private final InetAddress remoteHost;
|
||||
private final short remotePort;
|
||||
private final InetAddress bindHost;
|
||||
private final short bindPort;
|
||||
|
||||
public TunnelManager(InetAddress bindHost, short bindPort, InetAddress remoteHost, short remotePort) throws SocketException {
|
||||
this.remoteHost = remoteHost;
|
||||
this.remotePort = remotePort;
|
||||
this.bindHost = bindHost;
|
||||
this.bindPort = bindPort;
|
||||
socket = new DatagramSocket(bindPort, bindHost);
|
||||
socket.connect(remoteHost, remotePort);
|
||||
}
|
||||
@@ -29,12 +38,7 @@ public class TunnelManager {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
INSTANCE.listen();
|
||||
}
|
||||
}).start();
|
||||
new Thread(() -> INSTANCE.listen()).start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,19 +54,21 @@ public class TunnelManager {
|
||||
}
|
||||
|
||||
byte flags = packet.getData()[0];
|
||||
int vni_1 = packet.getData()[4];
|
||||
int vni = packet.getData()[6]
|
||||
+ packet.getData()[5] << 8
|
||||
+ packet.getData()[4] << 16;
|
||||
|
||||
if ((flags & 0x08) != 0x08) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NetworkInterface iface = tunnels.get(vni);
|
||||
TunnelInterface iface = tunnels.get(vni);
|
||||
|
||||
if (iface != null) {
|
||||
byte[] inner = new byte[packet.getData().length - 8];
|
||||
copyBytes(packet.getData(), inner, 8, 0, packet.getData().length - 8);
|
||||
System.arraycopy(packet.getData(), 8, inner, 0, packet.getData().length - 8);
|
||||
|
||||
iface.writeEthernetFrame(null, inner, 255);
|
||||
iface.target.writeEthernetFrame(iface, inner, 255);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@@ -74,9 +80,44 @@ public class TunnelManager {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private void copyBytes(byte[] input, byte[] output, int inputOffset, int outputOffset, int length) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
output[outputOffset + i] = input[inputOffset + i];
|
||||
public void sendToVti(int vti, byte[] payload) {
|
||||
byte[] buffer = new byte[payload.length + 8];
|
||||
|
||||
System.arraycopy(payload, 0, buffer, 8, payload.length);
|
||||
|
||||
buffer[0] = 0x08;
|
||||
buffer[4] = (byte) ((vti >> 16) & 0xff);
|
||||
buffer[5] = (byte) ((vti >> 8) & 0xff);
|
||||
buffer[6] = (byte) (vti & 0xff);
|
||||
|
||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, this.remoteHost, this.remotePort);
|
||||
}
|
||||
|
||||
public void registerVti(int vti, NetworkInterface iface) {
|
||||
tunnels.put(vti, new TunnelInterface(vti, iface));
|
||||
}
|
||||
|
||||
public void unregisterVti(int vti) {
|
||||
tunnels.remove(vti);
|
||||
}
|
||||
|
||||
public class TunnelInterface implements NetworkInterface {
|
||||
final NetworkInterface target;
|
||||
private final int vti;
|
||||
|
||||
public TunnelInterface(int vti, NetworkInterface iface) {
|
||||
this.vti = vti;
|
||||
this.target = iface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] readEthernetFrame() {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeEthernetFrame(final NetworkInterface source, final byte[] frame, final int timeToLive) {
|
||||
TunnelManager.this.sendToVti(vti, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user