diff --git a/main/java/ella/techia/block/Connector.java b/main/java/ella/techia/block/Connector.java index e583db3..fdf38c9 100644 --- a/main/java/ella/techia/block/Connector.java +++ b/main/java/ella/techia/block/Connector.java @@ -25,13 +25,13 @@ import net.minecraft.world.WorldView; public class Connector extends LetiConnectable /*implements LetiBlock, Waterloggable*/ { - static final VoxelShape BASE_SHAPE = createCuboidShape( 5d, 5d, 5d, 11d, 11d, 11d); - static final VoxelShape NORTH_SHAPE = createCuboidShape( 6d, 6d, 0d, 10d, 10d, 5d); - static final VoxelShape SOUTH_SHAPE = createCuboidShape( 6d, 6d, 11d, 10d, 10d, 16d); - static final VoxelShape EAST_SHAPE = createCuboidShape(11d, 6d, 6d, 16d, 10d, 10d); - static final VoxelShape WEST_SHAPE = createCuboidShape( 0d, 6d, 6d, 5d, 10d, 10d); - static final VoxelShape UP_SHAPE = createCuboidShape( 6d, 11d, 6d, 10d, 16d, 10d); - static final VoxelShape DOWN_SHAPE = createCuboidShape( 6d, 0d, 6d, 10d, 5d, 10d); + final VoxelShape BASE_SHAPE = createCuboidShape( 5d, 5d, 5d, 11d, 11d, 11d); + final VoxelShape NORTH_SHAPE = createCuboidShape( 6d, 6d, 0d, 10d, 10d, 5d); + final VoxelShape SOUTH_SHAPE = createCuboidShape( 6d, 6d, 11d, 10d, 10d, 16d); + final VoxelShape EAST_SHAPE = createCuboidShape(11d, 6d, 6d, 16d, 10d, 10d); + final VoxelShape WEST_SHAPE = createCuboidShape( 0d, 6d, 6d, 5d, 10d, 10d); + final VoxelShape UP_SHAPE = createCuboidShape( 6d, 11d, 6d, 10d, 16d, 10d); + final VoxelShape DOWN_SHAPE = createCuboidShape( 6d, 0d, 6d, 10d, 5d, 10d); public Connector(net.minecraft.block.AbstractBlock.Settings settings){ super(settings); @@ -47,25 +47,8 @@ public class Connector extends LetiConnectable /*implements LetiBlock, Waterlogg super.onBroken(world, pos, state); LetiNetwork.remove(world, pos); } - @Override - public BlockState getStateForNeighborUpdate( - BlockState state, - Direction side, - BlockState neighborState, - WorldAccess world, - BlockPos pos, - BlockPos neighborPos - ){ - // can't be assed to only update one side - // FIXME probably extremely laggy on medium to big networks - return state - .with(Properties.NORTH, LetiNetwork.connects(world.getBlockState(pos.north()), Direction.SOUTH)) - .with(Properties.SOUTH, LetiNetwork.connects(world.getBlockState(pos.south()), Direction.NORTH)) - .with(Properties.EAST , LetiNetwork.connects(world.getBlockState(pos.east() ), Direction.WEST )) - .with(Properties.WEST , LetiNetwork.connects(world.getBlockState(pos.west() ), Direction.EAST )) - .with(Properties.UP , LetiNetwork.connects(world.getBlockState(pos.up() ), Direction.DOWN )) - .with(Properties.DOWN , LetiNetwork.connects(world.getBlockState(pos.down() ), Direction.UP )) - /*.with(Properties.POWERED, /*powered(world.getBlockState(pos))* /false)*/; + public boolean output(/*ServerWorld world, BlockPos pos,*/ BlockState state, Direction direction){ + return state.get(Properties.POWERED); } } diff --git a/main/java/ella/techia/block/LetiConnectable.java b/main/java/ella/techia/block/LetiConnectable.java index 4998c9f..5e7d992 100644 --- a/main/java/ella/techia/block/LetiConnectable.java +++ b/main/java/ella/techia/block/LetiConnectable.java @@ -23,17 +23,17 @@ import net.minecraft.world.World; import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldView; -public class LetiConnectable extends Block implements LetiBlock, Waterloggable { +public abstract class LetiConnectable extends Block implements LetiBlock, Waterloggable { - static final VoxelShape BASE_SHAPE; - static final VoxelShape NORTH_SHAPE; - static final VoxelShape SOUTH_SHAPE; - static final VoxelShape EAST_SHAPE; - static final VoxelShape WEST_SHAPE; - static final VoxelShape UP_SHAPE; - static final VoxelShape DOWN_SHAPE; + abstract final VoxelShape BASE_SHAPE; + abstract final VoxelShape NORTH_SHAPE; + abstract final VoxelShape SOUTH_SHAPE; + abstract final VoxelShape EAST_SHAPE; + abstract final VoxelShape WEST_SHAPE; + abstract final VoxelShape UP_SHAPE; + abstract final VoxelShape DOWN_SHAPE; - public LetiToggle(net.minecraft.block.AbstractBlock.Settings settings){ + public LetiConnectable(net.minecraft.block.AbstractBlock.Settings settings){ super(settings); this.setDefaultState( this.stateManager.getDefaultState() @@ -123,10 +123,6 @@ public class LetiConnectable extends Block implements LetiBlock, Waterloggable { public boolean connects(BlockState state, Direction direction){ return true; } - @Override - public boolean output(/*ServerWorld world, BlockPos pos,*/ BlockState state, Direction direction){ - return state.get(Properties.POWERED); - } /*@Override BlockState rotate(BlockState state, BlockRotation rotation){ return state; diff --git a/main/java/ella/techia/leti/LetiNetwork.java b/main/java/ella/techia/leti/LetiNetwork.java index 5069447..6125c2d 100644 --- a/main/java/ella/techia/leti/LetiNetwork.java +++ b/main/java/ella/techia/leti/LetiNetwork.java @@ -5,22 +5,26 @@ import java.util.Map.Entry; import net.minecraft.state.property.Properties; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; -import net.minecraft.world.ServerWorld; +import net.minecraft.world.World; public class LetiNetwork { - private static final Map, LetiNetwork> networks = Maps.newHashMap(); - private ServerWorld world; + private static final Map, LetiNetwork> networks = Maps.newHashMap(); + private World world; ArrayList nodes; ArrayList> inputs; - public LetiNetwork(ServerWorld world, BlockPos pos){ + boolean powered; + private LetiNetwork(World world){ this.world = world; nodes = new ArrayList<>(); - nodes.add(pos); inputs = new ArrayList<>(); // TODO population of inputs is nowhere in the code // NOTE handling outputs probably happens when set(boolean) updates states, but we may want to look into this further } + private LetiNetwork(World world, BlockPos pos){ + this(world); + add(pos); + } // NOTE that this code assumes correct behaviour of callers and that it does what it's meant to do // this is of course not ideal, but as long as it's not messed up in this mod it should be fine... @@ -29,71 +33,86 @@ public class LetiNetwork { for(BlockPos pos : nodes){ world.setBlockState(pos, world.getBlockState(pos).with(Properties.POWERED, powered)); } + this.powered = powered; } // assumes that there is no node here already - public static void new(ServerWorld world, BlockPos pos){ + // this name is probably a misnomer, what this code really does is finds a network for a position that isn't already in a network + public static void new(World world, BlockPos pos){ if(!(world.getBlockState(pos).getBlock() instanceof Connector)) throw new IllegalArgumentException("Only connectors may be in a network"); // check adjacent positions for networks, if >1 join them together, if >0 join the network, if 0 create a network LetiNetwork current = null; for(BlockPos np : neighbors(pos)){ - Entry key = new Entry<>(world, pos); + Entry key = new Entry<>(world, pos); if(networks.containsKey(key)){ if(current == null){ current = networks.get(key); current.add(pos); } - else current.mergeWith(networks.get(key)); + else if(!current.equals(networks.get(key))) current.mergeWith(networks.get(key)); } } if(current == null){ - networks.set(new Entry(world, pos), new LetiNetwork(world, pos)); + new LetiNetwork(world, pos); } } - public static LetiNetwork at(ServerWorld world, BlockPos pos){ - return networks.get(new Entry(world, pos)); + public static LetiNetwork at(World world, BlockPos pos){ + return networks.get(new Entry(world, pos)); } - private void add(ServerWorld world, BlockPos pos){ + private void add(BlockPos pos){ nodes.add(pos); - networks.set(new Entry(world, pos), this); + networks.set(new Entry(world, pos), this); } - private void remove(ServerWorld world, BlockPos pos){ + private static void remove(World world, BlockPos pos){ nodes.remove(pos); - networks.remove(new Entry(world, pos)); - // FIXME known bug: won't separate networks - // start at pos, traverse neighbours (and add those searched to an array to prevent loops), + networks.remove(new Entry(world, pos)); + + // start at neighbours of pos, traverse neighbours (and add those searched to an array to prevent loops), // check if we found all (equal), report error if too many entries were found // if fewer entries were found, traverse through all other directions and replace those to a new network - // i was thinking what if these blocks are on different networks but that should never happen - // this code is a start but recursion... - /*ArrayList found; - int finds = 0; for(BlockPos np : neighbors(pos)){ - Entry key = new Entry<>(world, np); - if(networks.containsKey(key)){ - LetiNetwork n = networks.get(key); - if(!found.contains(key.getValue())){ - found.add(key.getValue()); - ++finds; - recurse(np); + if(nodes.contains(np)){ + ArrayList found = new ArrayList<>(); + ArrayList next = new ArrayList<>(); + while(!next.isEmpty()){ + for(BlockPos nep : neighbors(next.get(0))){ + if(nodes.contains(nep) && !found.contains(next.get(0))) + next.add(nep); + } + found.add(next.get(0)); + next.remove(0); + } + int finds = found.size(); + int s = nodes.size(); + if(finds > s){ + throw new AssertionError("Found " + finds + " nodes; network has " + s + " nodes"); + } + if(finds == s){ + break; + } + // known issue: this is a lot of unnecessary overwriting + // if two blocks adjacing the removed block are connected the first network will get wiped out immediately + LetiNetwork n = new LetiNetwork(world); + for(BlockPos nep : found){ + n.add(nep); } } - }*/ + } } - private void addInput(ServerWorld world, BlockPos pos, Direction direction){ + private void addInput(World world, BlockPos pos, Direction direction){ inputs.add(new Entry(pos, direction)); } - private void removeInput(ServerWorld world, BlockPos pos, Direction direction){ + private void removeInput(World world, BlockPos pos, Direction direction){ inputs.remove(new Entry(pos, direction)); } private void mergeWith(LetiNetwork network){ for(BlockPos pos : nodes){ - Entry entry = new Entry<>(world, pos) + Entry entry = new Entry<>(world, pos) network.add(pos); networks.set(entry, network); } @@ -146,7 +165,7 @@ public class LetiNetwork { public static ArrayList findAdjacentNetworks(){ ArrayList ret; for(BlockPos np : neighbors(pos)){ - Entry key = new Entry<>(world, np); + Entry key = new Entry<>(world, np); if(networks.containsKey(key)){ LetiNetwork n = networks.get(key); if(!ret.contains(n)) ret.add(n);