Skip to content

Commit 84659f9

Browse files
committed
Redstone: Redstone in tunnel. API test success.
Implements a probably-very-unoptimized redstone_in tunnel implementation, which is a proper test of the new API code and tunnel definitions. Success one!
1 parent a7e54ed commit 84659f9

24 files changed

+498
-163
lines changed

src/main/java/com/robotgryphon/compactmachines/api/tunnels/IRedstoneTunnel.java

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.robotgryphon.compactmachines.api.tunnels;
2+
3+
import com.robotgryphon.compactmachines.teleportation.DimensionalPosition;
4+
import net.minecraft.block.BlockState;
5+
import net.minecraft.util.Direction;
6+
import net.minecraft.world.IWorldReader;
7+
8+
import javax.annotation.Nonnull;
9+
import java.util.Optional;
10+
11+
public interface ITunnelConnectionInfo {
12+
@Nonnull
13+
Optional<DimensionalPosition> getConnectedPosition(EnumTunnelSide side);
14+
15+
@Nonnull
16+
Optional<BlockState> getConnectedState(EnumTunnelSide side);
17+
18+
Optional<? extends IWorldReader> getConnectedWorld(EnumTunnelSide side);
19+
20+
/**
21+
* Gets the connection information for sidedness.
22+
*
23+
* For inside the machine, gets the side the tunnel was placed on.
24+
* For outside the machine, gets the side of the machine the tunnel is connected to.
25+
*
26+
* @param side Which side of the tunnel to get directional info for.
27+
*/
28+
Direction getConnectedSide(EnumTunnelSide side);
29+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.robotgryphon.compactmachines.api.tunnels.redstone;
2+
3+
import com.robotgryphon.compactmachines.api.tunnels.ITunnelConnectionInfo;
4+
import net.minecraft.block.BlockState;
5+
import net.minecraft.server.MinecraftServer;
6+
import net.minecraft.util.Direction;
7+
import net.minecraft.util.math.BlockPos;
8+
import net.minecraft.world.IBlockReader;
9+
10+
/**
11+
* A redstone reader reads a redstone value from outside the machine (from a given side).
12+
*/
13+
public interface IRedstoneReaderTunnel extends IRedstoneTunnel {
14+
15+
int getStrongPower(ITunnelConnectionInfo connectionInfo);
16+
17+
int getWeakPower(ITunnelConnectionInfo connectionInfo);
18+
19+
/**
20+
* Called by the tunnel wall blocks to check if a redstone signal can be pulled
21+
* from the outside. This should almost always return true, but if you need custom
22+
* logic then you can implement it here.
23+
*
24+
* @param connectionInfo Connection information for the tunnel instance.
25+
* @return
26+
*/
27+
default boolean canConnectRedstone(ITunnelConnectionInfo connectionInfo) {
28+
return true;
29+
}
30+
31+
void onPowerChanged(ITunnelConnectionInfo connectionInfo, int latestPower);
32+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.robotgryphon.compactmachines.api.tunnels.redstone;
2+
3+
public interface IRedstoneTunnel {
4+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.robotgryphon.compactmachines.api.tunnels.redstone;
2+
3+
import com.robotgryphon.compactmachines.api.tunnels.ITunnelConnectionInfo;
4+
import net.minecraft.block.BlockState;
5+
import net.minecraft.util.Direction;
6+
import net.minecraft.util.math.BlockPos;
7+
import net.minecraft.world.IBlockReader;
8+
9+
/**
10+
* A redstone writer sends a redstone value from inside the machine (redstone connected to a tunnel).
11+
*/
12+
public interface IRedstoneWriterTunnel extends IRedstoneTunnel {
13+
14+
int getStrongPower(ITunnelConnectionInfo connectionInfo);
15+
16+
int getWeakPower(ITunnelConnectionInfo connectionInfo);
17+
}

src/main/java/com/robotgryphon/compactmachines/block/BlockCompactMachine.java

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package com.robotgryphon.compactmachines.block;
22

3+
import com.robotgryphon.compactmachines.CompactMachines;
4+
import com.robotgryphon.compactmachines.api.tunnels.ITunnelConnectionInfo;
5+
import com.robotgryphon.compactmachines.api.tunnels.redstone.IRedstoneReaderTunnel;
6+
import com.robotgryphon.compactmachines.api.tunnels.redstone.IRedstoneTunnel;
37
import com.robotgryphon.compactmachines.block.tiles.CompactMachineTile;
8+
import com.robotgryphon.compactmachines.block.tiles.TunnelWallTile;
49
import com.robotgryphon.compactmachines.compat.theoneprobe.providers.CompactMachineProvider;
510
import com.robotgryphon.compactmachines.compat.theoneprobe.IProbeData;
611
import com.robotgryphon.compactmachines.compat.theoneprobe.IProbeDataProvider;
@@ -10,6 +15,7 @@
1015
import com.robotgryphon.compactmachines.core.Registration;
1116
import com.robotgryphon.compactmachines.reference.EnumMachineSize;
1217
import com.robotgryphon.compactmachines.reference.Reference;
18+
import com.robotgryphon.compactmachines.tunnels.TunnelHelper;
1319
import com.robotgryphon.compactmachines.util.CompactMachineUtil;
1420
import net.minecraft.block.Block;
1521
import net.minecraft.block.BlockState;
@@ -32,7 +38,9 @@
3238
import net.minecraft.world.server.ServerWorld;
3339

3440
import javax.annotation.Nullable;
41+
import java.util.Arrays;
3542
import java.util.Optional;
43+
import java.util.Set;
3644
import java.util.UUID;
3745

3846
public class BlockCompactMachine extends Block implements IProbeDataProvider {
@@ -56,7 +64,7 @@ public float getPlayerRelativeBlockHardness(BlockState state, PlayerEntity playe
5664

5765

5866
// If there are players inside, check config for break handling
59-
if(hasPlayers) {
67+
if (hasPlayers) {
6068
EnumMachinePlayersBreakHandling hand = ServerConfig.MACHINE_PLAYER_BREAK_HANDLING.get();
6169
switch (hand) {
6270
case UNBREAKABLE:
@@ -103,6 +111,58 @@ public int getWeakPower(BlockState blockState, IBlockReader blockAccess, BlockPo
103111
return 0;
104112
}
105113

114+
@Override
115+
public void neighborChanged(BlockState state, World world, BlockPos pos, Block changedBlock, BlockPos changedPos, boolean isMoving) {
116+
super.neighborChanged(state, world, pos, changedBlock, changedPos, isMoving);
117+
118+
if (world.isRemote)
119+
return;
120+
121+
ServerWorld serverWorld = (ServerWorld) world;
122+
123+
BlockState changedState = serverWorld.getBlockState(changedPos);
124+
125+
CompactMachineTile machine = (CompactMachineTile) serverWorld.getTileEntity(pos);
126+
if (machine == null)
127+
return;
128+
129+
ServerWorld compactWorld = serverWorld.getServer().getWorld(Registration.COMPACT_DIMENSION);
130+
if (compactWorld == null) {
131+
CompactMachines.LOGGER.warn("Warning: Compact Dimension was null! Cannot fetch internal state for machine neighbor change listener.");
132+
return;
133+
}
134+
135+
CompactMachines.LOGGER.debug(changedBlock);
136+
137+
// Determine whether it's an immediate neighbor; if so, execute ...
138+
Arrays.stream(Direction.values())
139+
.filter(hd -> pos.offset(hd).equals(changedPos))
140+
.findFirst()
141+
.ifPresent(facing -> {
142+
Set<BlockPos> tunnelsForMachineSide = TunnelHelper.getTunnelsForMachineSide(machine.machineId, serverWorld, facing);
143+
for (BlockPos tunnelPos : tunnelsForMachineSide) {
144+
// TODO: Tunnel definition lookup, check for IRedstoneTunnel instances
145+
TunnelWallTile tunnelTile = (TunnelWallTile) compactWorld.getTileEntity(tunnelPos);
146+
if (tunnelTile == null) continue;
147+
148+
compactWorld.notifyNeighborsOfStateChange(tunnelPos, Registration.BLOCK_TUNNEL_WALL.get());
149+
150+
ITunnelConnectionInfo connInfo = TunnelHelper.generateConnectionInfo(tunnelTile);
151+
152+
tunnelTile.getTunnelDefinition().ifPresent(tunnelDefinition -> {
153+
if (tunnelDefinition instanceof IRedstoneReaderTunnel) {
154+
// Send redstone changes into machine
155+
156+
157+
IRedstoneReaderTunnel rrt = (IRedstoneReaderTunnel) tunnelDefinition;
158+
int latestPower = world.getRedstonePower(changedPos, facing);
159+
rrt.onPowerChanged(connInfo, latestPower);
160+
}
161+
});
162+
}
163+
});
164+
}
165+
106166
@Override
107167
public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos, BlockPos neighbor) {
108168
super.onNeighborChange(state, world, pos, neighbor);
@@ -116,19 +176,6 @@ public void onNeighborChange(BlockState state, IWorldReader world, BlockPos pos,
116176
// return;
117177
// }
118178

119-
// Determine whether it's an immediate neighbor ...
120-
Direction facing = null;
121-
for (Direction dir : Direction.values()) {
122-
if (pos.offset(dir).equals(neighbor)) {
123-
facing = dir;
124-
break;
125-
}
126-
}
127-
128-
// And do nothing if it isnt, e.g. diagonal
129-
if (facing == null) {
130-
return;
131-
}
132179

133180
// TODO Tile Entity and Server Stuff
134181
// // Make sure we don't stack overflow when we get in a notifyBlockChange loop.

src/main/java/com/robotgryphon/compactmachines/block/tiles/TunnelWallTile.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import net.minecraft.util.ResourceLocation;
1717
import net.minecraft.util.math.BlockPos;
1818
import net.minecraft.util.math.vector.Vector3d;
19+
import net.minecraft.world.IWorldReader;
1920
import net.minecraft.world.chunk.Chunk;
2021
import net.minecraft.world.server.ServerWorld;
2122
import net.minecraftforge.common.capabilities.Capability;
@@ -78,6 +79,32 @@ public void handleUpdateTag(BlockState state, CompoundNBT tag) {
7879
}
7980
}
8081

82+
public Optional<? extends IWorldReader> getConnectedWorld() {
83+
if (world == null || world.isRemote())
84+
return Optional.empty();
85+
86+
ServerWorld serverWorld = (ServerWorld) world;
87+
88+
Optional<CompactMachineRegistrationData> machineInfo = getMachineInfo();
89+
if (!machineInfo.isPresent())
90+
return Optional.empty();
91+
92+
Direction outsideDir = getConnectedSide();
93+
94+
CompactMachineRegistrationData regData = machineInfo.get();
95+
96+
// Is the machine placed in world? If not, do not return an outside position
97+
if (!regData.isPlacedInWorld())
98+
return Optional.empty();
99+
100+
DimensionalPosition machinePosition = regData.getOutsidePosition(serverWorld.getServer());
101+
if (machinePosition != null) {
102+
return machinePosition.getWorld(serverWorld.getServer());
103+
}
104+
105+
return Optional.empty();
106+
}
107+
81108
/**
82109
* Gets the position outside the machine where this tunnel is connected to.
83110
*
@@ -134,6 +161,10 @@ public Direction getConnectedSide() {
134161
return blockState.get(TunnelWallBlock.CONNECTED_SIDE);
135162
}
136163

164+
public Optional<ResourceLocation> getTunnelDefinitionId() {
165+
return Optional.ofNullable(this.tunnelType);
166+
}
167+
137168
public Optional<TunnelDefinition> getTunnelDefinition() {
138169
if(tunnelType == null)
139170
return Optional.empty();
@@ -142,7 +173,7 @@ public Optional<TunnelDefinition> getTunnelDefinition() {
142173
.findRegistry(TunnelDefinition.class)
143174
.getValue(tunnelType);
144175

145-
return Optional.of(definition);
176+
return Optional.ofNullable(definition);
146177
}
147178

148179
@Nonnull

src/main/java/com/robotgryphon/compactmachines/block/walls/TunnelWallBlock.java

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package com.robotgryphon.compactmachines.block.walls;
22

3+
import com.robotgryphon.compactmachines.api.tunnels.ITunnelConnectionInfo;
34
import com.robotgryphon.compactmachines.block.tiles.TunnelWallTile;
45
import com.robotgryphon.compactmachines.compat.theoneprobe.IProbeData;
56
import com.robotgryphon.compactmachines.compat.theoneprobe.IProbeDataProvider;
67
import com.robotgryphon.compactmachines.compat.theoneprobe.providers.TunnelProvider;
78
import com.robotgryphon.compactmachines.core.Registration;
89
import com.robotgryphon.compactmachines.api.tunnels.TunnelDefinition;
910
import com.robotgryphon.compactmachines.tunnels.TunnelHelper;
10-
import com.robotgryphon.compactmachines.api.tunnels.IRedstoneTunnel;
11+
import com.robotgryphon.compactmachines.api.tunnels.redstone.IRedstoneReaderTunnel;
1112
import net.minecraft.block.Block;
1213
import net.minecraft.block.BlockState;
1314
import net.minecraft.entity.item.ItemEntity;
@@ -59,8 +60,9 @@ public boolean canConnectRedstone(BlockState state, IBlockReader world, BlockPos
5960
return false;
6061

6162
TunnelDefinition definition = tunnelInfo.get();
62-
if (definition instanceof IRedstoneTunnel) {
63-
return ((IRedstoneTunnel) definition).canConnectRedstone(world, state, pos, side);
63+
if (definition instanceof IRedstoneReaderTunnel) {
64+
ITunnelConnectionInfo conn = TunnelHelper.generateConnectionInfo(world, pos);
65+
return ((IRedstoneReaderTunnel) definition).canConnectRedstone(conn);
6466
}
6567

6668
return false;
@@ -73,15 +75,6 @@ public boolean canProvidePower(BlockState state) {
7375

7476
@Override
7577
public int getStrongPower(BlockState state, IBlockReader world, BlockPos pos, Direction side) {
76-
Optional<TunnelDefinition> tunnelInfo = getTunnelInfo(world, pos);
77-
if (!tunnelInfo.isPresent())
78-
return 0;
79-
80-
TunnelDefinition definition = tunnelInfo.get();
81-
if (definition instanceof IRedstoneTunnel) {
82-
return ((IRedstoneTunnel) definition).getStrongPower(world, state, pos, side);
83-
}
84-
8578
return 0;
8679
}
8780

@@ -92,8 +85,10 @@ public int getWeakPower(BlockState state, IBlockReader world, BlockPos pos, Dire
9285
return 0;
9386

9487
TunnelDefinition definition = tunnelInfo.get();
95-
if (definition instanceof IRedstoneTunnel) {
96-
return ((IRedstoneTunnel) definition).getWeakPower(world, state, pos, side);
88+
if (definition instanceof IRedstoneReaderTunnel) {
89+
ITunnelConnectionInfo conn = TunnelHelper.generateConnectionInfo(world, pos);
90+
int weak = ((IRedstoneReaderTunnel) definition).getWeakPower(conn);
91+
return weak;
9792
}
9893

9994
return 0;

src/main/java/com/robotgryphon/compactmachines/client/ClientEventHandler.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
public class ClientEventHandler {
1515

1616
@SubscribeEvent
17-
public static void onColors(final ColorHandlerEvent.Block colors) {
17+
public static void onItemColors(final ColorHandlerEvent.Item colors) {
18+
colors.getItemColors().register(new TunnelItemColor(), Registration.ITEM_TUNNEL.get());
19+
}
20+
21+
@SubscribeEvent
22+
public static void onBlockColors(final ColorHandlerEvent.Block colors) {
1823
colors.getBlockColors().register(new TunnelColors(), Registration.BLOCK_TUNNEL_WALL.get());
1924
}
2025

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.robotgryphon.compactmachines.client;
2+
3+
import com.robotgryphon.compactmachines.api.tunnels.TunnelDefinition;
4+
import com.robotgryphon.compactmachines.item.TunnelItem;
5+
import net.minecraft.client.renderer.color.IItemColor;
6+
import net.minecraft.item.ItemStack;
7+
8+
import java.util.Optional;
9+
10+
public class TunnelItemColor implements IItemColor {
11+
@Override
12+
public int getColor(ItemStack stack, int tintIndex) {
13+
Optional<TunnelDefinition> definition = TunnelItem.getDefinition(stack);
14+
if(!definition.isPresent())
15+
return 0;
16+
17+
TunnelDefinition actualDef = definition.get();
18+
if (tintIndex == 0) {
19+
return actualDef.getTunnelRingColor();
20+
}
21+
22+
return actualDef.getTunnelIndicatorColor();
23+
}
24+
}

0 commit comments

Comments
 (0)