Skip to content

Commit

Permalink
Merge branch 'feature/real-world-network' into develop
Browse files Browse the repository at this point in the history
* feature/real-world-network:
  Re-enable configurability
  This should work
  More debugging!
  Debugging
  Prototype commit fnuecke#3
  Prototype commit 2
  First prototype vxlan hub
  Add initial work on the NetworkPortalBlock
  • Loading branch information
dequbed committed Jan 30, 2022
2 parents 555a07d + 584706a commit b771de3
Show file tree
Hide file tree
Showing 9 changed files with 400 additions and 1 deletion.
6 changes: 6 additions & 0 deletions src/main/java/li/cil/oc2/common/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ public final class Config {

@Path("admin") public static UUID fakePlayerUUID = UUID.fromString("e39dd9a7-514f-4a2d-aa5e-b6030621416d");

@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 String bindHost = "::1";
@Path("vxlan") public static int bindPort = 4789;

public static boolean computersUseEnergy() {
return computerEnergyPerTick > 0 && computerEnergyStorage > 0;
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/li/cil/oc2/common/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import li.cil.oc2.common.tags.ItemTags;
import li.cil.oc2.common.util.RegistryUtils;
import li.cil.oc2.common.util.SoundEvents;
import li.cil.oc2.common.vxlan.TunnelManager;
import li.cil.sedna.Sedna;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
Expand Down Expand Up @@ -51,6 +52,7 @@ public Main() {
DeviceTypes.initialize();
BlockDeviceDataRegistration.initialize();
Firmwares.initialize();
TunnelManager.initialize();

DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> Manuals::initialize);

Expand Down
1 change: 1 addition & 0 deletions src/main/java/li/cil/oc2/common/block/Blocks.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public final class Blocks {
public static final RegistryObject<NetworkHubBlock> NETWORK_HUB = BLOCKS.register("network_hub", NetworkHubBlock::new);
public static final RegistryObject<NetworkSwitchBlock> NETWORK_SWITCH = BLOCKS.register("network_switch", NetworkSwitchBlock::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);

///////////////////////////////////////////////////////////////////

Expand Down
71 changes: 71 additions & 0 deletions src/main/java/li/cil/oc2/common/block/VxlanBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
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.TickableBlockEntity;
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.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
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);
}

@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(final Level level, final BlockState state, final BlockEntityType<T> type) {
return TickableBlockEntity.createServerTicker(level, type, BlockEntities.VXLAN_HUB.get());
}

///////////////////////////////////////////////////////////////////

@Override
protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder);
builder.add(FACING);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public final class BlockEntities {
public static final RegistryObject<BlockEntityType<DiskDriveBlockEntity>> DISK_DRIVE = register(Blocks.DISK_DRIVE, DiskDriveBlockEntity::new);
public static final RegistryObject<BlockEntityType<ChargerBlockEntity>> CHARGER = register(Blocks.CHARGER, ChargerBlockEntity::new);
public static final RegistryObject<BlockEntityType<CreativeEnergyBlockEntity>> CREATIVE_ENERGY = register(Blocks.CREATIVE_ENERGY, CreativeEnergyBlockEntity::new);
public static final RegistryObject<BlockEntityType<VxlanBlockEntity>> VXLAN_HUB = register(Blocks.VXLAN_HUB, VxlanBlockEntity::new);

///////////////////////////////////////////////////////////////////

Expand Down
161 changes: 161 additions & 0 deletions src/main/java/li/cil/oc2/common/blockentity/VxlanBlockEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
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.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.stream.Stream;

public final class VxlanBlockEntity extends ModBlockEntity implements NetworkInterface, TickableBlockEntity {
private static final int TTL_COST = 1;
private int vti = ((int) (Math.random() * Integer.MAX_VALUE)) & 0x00ff_ffff;

private BlockingQueue<byte[]> packetQueue = new ArrayBlockingQueue<byte[]>(32);

///////////////////////////////////////////////////////////////////

// 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.VXLAN_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 serverTick() {
if (level == null) {
return;
}

if (adjacentBlockInterfaces[0] != null) {
packetQueue.forEach(packet -> {
writeEthernetFrame(adjacentBlockInterfaces[0], packet, 255);
});
packetQueue.clear();
} else {
System.out.printf("VXLAN block is unregistered upstream: VTI=%d\n", vti);
}
}

///////////////////////////////////////////////////////////////////

@Override
public void load(CompoundTag tag) {
super.load(tag);
if (!level.isClientSide()) {
vti = tag.getInt("vti");
adjacentBlockInterfaces[0] = TunnelManager.instance().registerVti(vti, packetQueue);
}
}

@Override
public void saveAdditional(CompoundTag tag) {
super.saveAdditional(tag);
if (!level.isClientSide()) {
tag.putInt("vti", vti);
}
}

@Override
protected void onUnload(final boolean isRemove) {
if (!level.isClientSide()) {
adjacentBlockInterfaces[0] = null;
TunnelManager.instance().unregisterVti(vti);
}

super.onUnload(isRemove);
}

@Override
public void onLoad() {
super.onLoad();

if (!level.isClientSide()) {
System.out.println("Tunnel VTI: " + vti);
adjacentBlockInterfaces[0] = TunnelManager.instance().registerVti(vti, this.packetQueue);
}
}

///////////////////////////////////////////////////////////////////



@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());
});
}
}
}
}
1 change: 1 addition & 0 deletions src/main/java/li/cil/oc2/common/item/Items.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public final class Items {
public static final RegistryObject<Item> NETWORK_HUB = register(Blocks.NETWORK_HUB);
public static final RegistryObject<Item> NETWORK_SWITCH = register(Blocks.NETWORK_SWITCH);
public static final RegistryObject<Item> REDSTONE_INTERFACE = register(Blocks.REDSTONE_INTERFACE);
public static final RegistryObject<Item> VXLAN_HUB = register(Blocks.VXLAN_HUB);

///////////////////////////////////////////////////////////////////

Expand Down
Loading

0 comments on commit b771de3

Please sign in to comment.