forked from fnuecke/oc2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/real-world-network' into develop
* 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
Showing
9 changed files
with
400 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
161 changes: 161 additions & 0 deletions
161
src/main/java/li/cil/oc2/common/blockentity/VxlanBlockEntity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | ||
}); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.