-
Notifications
You must be signed in to change notification settings - Fork 182
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
132 changed files
with
6,617 additions
and
3,601 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package mrtjp.projectred.core; | ||
|
||
import codechicken.multipart.api.part.TMultiPart; | ||
import codechicken.multipart.block.TileMultiPart; | ||
import net.minecraft.block.Block; | ||
import net.minecraft.block.BlockState; | ||
import net.minecraft.tileentity.TileEntity; | ||
import net.minecraft.util.Direction; | ||
import net.minecraft.util.math.BlockPos; | ||
import net.minecraft.world.World; | ||
|
||
public class CenterLookup { | ||
|
||
//Starting conditions | ||
public final World world; | ||
public final BlockPos pos; | ||
public final int direction; | ||
|
||
// Located objects | ||
public final BlockState state; | ||
public final Block block; | ||
public final TileEntity tile; | ||
public final TMultiPart part; | ||
|
||
// Conditions for reverse lookup | ||
public final BlockPos otherPos; | ||
public final int otherDirection; | ||
|
||
public CenterLookup(World world, BlockPos pos, int direction, BlockState state, TileEntity tile, TMultiPart part, BlockPos otherPos, int otherDirection) { | ||
this.world = world; | ||
this.pos = pos; | ||
this.direction = direction; | ||
this.state = state; | ||
this.block = state.getBlock(); | ||
this.tile = tile; | ||
this.part = part; | ||
this.otherPos = otherPos; | ||
this.otherDirection = otherDirection; | ||
} | ||
|
||
public static CenterLookup lookupInsideFace(World world, BlockPos pos, int direction) { | ||
|
||
int otherDir = direction ^ 1; | ||
|
||
BlockState state = world.getBlockState(pos); | ||
TileEntity tile = world.getBlockEntity(pos); | ||
TMultiPart part = null; | ||
if (tile instanceof TileMultiPart) { | ||
part = ((TileMultiPart) tile).getSlottedPart(direction); | ||
} | ||
|
||
return new CenterLookup(world, pos, direction, state, tile, part, pos, otherDir); | ||
} | ||
|
||
public static CenterLookup lookupStraightCenter(World world, BlockPos pos, int direction) { | ||
|
||
BlockPos otherPos = pos.relative(Direction.values()[direction]); | ||
int otherDir = direction ^ 1; | ||
|
||
BlockState state = world.getBlockState(otherPos); | ||
TileEntity tile = world.getBlockEntity(otherPos); | ||
TMultiPart part = null; | ||
if (tile instanceof TileMultiPart) { | ||
part = ((TileMultiPart) tile).getSlottedPart(6); | ||
} | ||
|
||
return new CenterLookup(world, pos, direction, state, tile, part, otherPos, otherDir); | ||
} | ||
} |
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,110 @@ | ||
package mrtjp.projectred.core; | ||
|
||
import codechicken.lib.vec.Rotation; | ||
import codechicken.multipart.api.part.TMultiPart; | ||
import codechicken.multipart.block.TileMultiPart; | ||
import net.minecraft.block.Block; | ||
import net.minecraft.block.BlockState; | ||
import net.minecraft.tileentity.TileEntity; | ||
import net.minecraft.util.Direction; | ||
import net.minecraft.util.math.BlockPos; | ||
import net.minecraft.world.World; | ||
|
||
public class FaceLookup { | ||
|
||
//Starting conditions | ||
public final World world; | ||
public final BlockPos pos; | ||
public final int side; | ||
public final int r; | ||
|
||
//Located objects | ||
public final BlockState state; | ||
public final Block block; | ||
public final TileEntity tile; | ||
public final TMultiPart part; | ||
|
||
//Conditions for reverse lookup | ||
public final BlockPos otherPos; | ||
public final int otherSide; | ||
public final int otherRotation; | ||
|
||
public FaceLookup(World world, BlockPos pos, int side, int r, BlockState state, TileEntity tile, TMultiPart part, BlockPos otherPos, int otherSide, int otherRotation) { | ||
this.world = world; | ||
this.pos = pos; | ||
this.side = side; | ||
this.r = r; | ||
this.state = state; | ||
this.block = state.getBlock(); | ||
this.tile = tile; | ||
this.part = part; | ||
this.otherPos = otherPos; | ||
this.otherSide = otherSide; | ||
this.otherRotation = otherRotation; | ||
} | ||
|
||
public static FaceLookup lookupCorner(World world, BlockPos pos, int side, int r) { | ||
int absDir = Rotation.rotateSide(side, r); | ||
int otherSide = absDir ^ 1; | ||
int otherRotation = Rotation.rotationTo(absDir ^ 1, side ^ 1); | ||
|
||
BlockPos pos2 = pos | ||
.relative(Direction.values()[absDir]) | ||
.relative(Direction.values()[side]); | ||
|
||
BlockState state = world.getBlockState(pos2); | ||
TileEntity tile = world.getBlockEntity(pos2); | ||
TMultiPart part = null; | ||
if (tile instanceof TileMultiPart) { | ||
part = ((TileMultiPart) tile).getSlottedPart(otherSide); | ||
} | ||
|
||
return new FaceLookup(world, pos, side, r, state, tile, part, pos2, otherSide, otherRotation); | ||
} | ||
|
||
public static FaceLookup lookupStraight(World world, BlockPos pos, int side, int r) { | ||
int otherSide = side; | ||
int otherRotation = (r + 2) % 4; | ||
|
||
BlockPos pos2 = pos.relative(Direction.values()[Rotation.rotateSide(side, r)]); | ||
|
||
BlockState state = world.getBlockState(pos2); | ||
TileEntity tile = world.getBlockEntity(pos2); | ||
TMultiPart part = null; | ||
if (tile instanceof TileMultiPart) { | ||
part = ((TileMultiPart) tile).getSlottedPart(otherSide); | ||
} | ||
|
||
return new FaceLookup(world, pos, side, r, state, tile, part, pos2, otherSide, otherRotation); | ||
} | ||
|
||
public static FaceLookup lookupInsideFace(World world, BlockPos pos, int side, int r) { | ||
int absDir = Rotation.rotateSide(side, r); | ||
int otherSide = absDir; | ||
int otherRotation = Rotation.rotationTo(absDir, side); | ||
|
||
BlockState state = world.getBlockState(pos); | ||
TileEntity tile = world.getBlockEntity(pos); | ||
TMultiPart part = null; | ||
if (tile instanceof TileMultiPart) { | ||
part = ((TileMultiPart) tile).getSlottedPart(otherSide); | ||
} | ||
|
||
return new FaceLookup(world, pos, side, r, state, tile, part, pos, otherSide, otherRotation); | ||
} | ||
|
||
public static FaceLookup lookupInsideCenter(World world, BlockPos pos, int side) { | ||
|
||
int otherSide = side; | ||
int otherRotation = -1; // Part is not on face | ||
|
||
BlockState state = world.getBlockState(pos); | ||
TileEntity tile = world.getBlockEntity(pos); | ||
TMultiPart part = null; | ||
if (tile instanceof TileMultiPart) { | ||
part = ((TileMultiPart) tile).getSlottedPart(6); | ||
} | ||
|
||
return new FaceLookup(world, pos, side, -1, state, tile, part, pos, otherRotation, otherSide); | ||
} | ||
} |
191 changes: 191 additions & 0 deletions
191
src/core/scala/mrtjp/projectred/core/RedstonePropagator.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,191 @@ | ||
package mrtjp.projectred.core; | ||
|
||
import codechicken.multipart.api.part.TMultiPart; | ||
import codechicken.multipart.block.TileMultiPart; | ||
import codechicken.multipart.init.CBMultipartModContent; | ||
import com.google.common.collect.HashMultimap; | ||
import mrtjp.projectred.core.part.IPropagationPart; | ||
import net.minecraft.block.Blocks; | ||
import net.minecraft.block.RedstoneWireBlock; | ||
import net.minecraft.util.math.BlockPos; | ||
import net.minecraft.world.World; | ||
|
||
import java.util.Collection; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class RedstonePropagator { | ||
/** | ||
* Standard operation procedure, no special propagation rules. The | ||
* propagator signal may not have increased. | ||
*/ | ||
public static final int RISING = 0; | ||
/** | ||
* Used when the propagator signal dropped (to 0). Propagation should | ||
* continue until a rising or constant change is encountered at which point | ||
* a RISING should be propagated back to this wire. | ||
*/ | ||
public static final int DROPPING = 1; | ||
/** | ||
* Used when a wire's connection state has changed. Even if the signal | ||
* remains the same, new connections still need to be recalculated | ||
*/ | ||
public static final int FORCE = 2; | ||
/** | ||
* Used when the propagator did not change signal, but a new connection may | ||
* have been established and signal needs recalculating | ||
*/ | ||
public static final int FORCED = 3; | ||
|
||
private static final LinkedList<PropagationRun> reusableRuns = new LinkedList<>(); | ||
private static PropagationRun currentRun = null; | ||
private static PropagationRun finishingRun = null; | ||
|
||
private static boolean canRedwiresProvidePower = true; | ||
private static boolean canConnectRedwires = true; | ||
|
||
public static boolean canConnectRedwires() { | ||
return canConnectRedwires; | ||
} | ||
public static void setCanConnectRedwires(boolean canConnectRedwires) { | ||
RedstonePropagator.canConnectRedwires = canConnectRedwires; | ||
} | ||
|
||
public static boolean canRedwiresProvidePower() { | ||
return canRedwiresProvidePower; | ||
} | ||
public static void setDustProvidesPower(boolean dustProvidesPower) { | ||
((RedstoneWireBlock)Blocks.REDSTONE_WIRE).shouldSignal = dustProvidesPower; | ||
} | ||
public static void setRedwiresProvidePower(boolean canRedwiresProvidePower) { | ||
RedstonePropagator.canRedwiresProvidePower = canRedwiresProvidePower; | ||
} | ||
|
||
public static void resetPowerFlags() { | ||
setDustProvidesPower(true); | ||
setRedwiresProvidePower(true); | ||
setCanConnectRedwires(true); | ||
} | ||
|
||
public static void addNeighborChange(World world, BlockPos pos) { | ||
currentRun.neighborChanges.put(world, pos); | ||
} | ||
|
||
public static void addPartChange(TMultiPart part) { | ||
currentRun.partChanges.put(part.tile(), part); | ||
} | ||
|
||
public static void logCalculation() { | ||
if (finishingRun != null) { | ||
finishingRun.recalcs++; | ||
} | ||
} | ||
|
||
public static void propagateTo(IPropagationPart part, IPropagationPart from, int mode) { | ||
if (currentRun != null) { | ||
currentRun.add(part, from, mode); | ||
return; | ||
} | ||
currentRun = reusableRuns.isEmpty() ? new PropagationRun() : reusableRuns.removeFirst(); | ||
currentRun.add(part, from, mode); | ||
currentRun.executeRun(finishingRun); | ||
} | ||
|
||
public static void propagateTo(IPropagationPart part, int mode) { | ||
propagateTo(part, null, mode); | ||
} | ||
|
||
public static void propagateAnalogDrop(IPropagationPart part) { | ||
currentRun.addAnalogDrop(part); | ||
} | ||
|
||
private static class PropagationRun { | ||
|
||
private PropagationRun parent; | ||
private IPropagationPart lastCaller; | ||
private int count = 0; | ||
private int recalcs = 0; | ||
|
||
HashMultimap<TileMultiPart, TMultiPart> partChanges = HashMultimap.create(); | ||
HashMultimap<World, BlockPos> neighborChanges = HashMultimap.create(); | ||
List<Runnable> propagationTasks = new LinkedList<>(); | ||
List<Runnable> analogDropPropagationTasks = new LinkedList<>(); | ||
|
||
void clear() { | ||
partChanges.clear(); | ||
neighborChanges.clear(); | ||
count = 0; | ||
recalcs = 0; | ||
lastCaller = null; | ||
reusableRuns.add(this); | ||
} | ||
|
||
void executeRun(PropagationRun parent) { | ||
this.parent = parent; | ||
RedstonePropagator.currentRun = this; | ||
runLoop(); | ||
finishRun(); | ||
} | ||
|
||
void runLoop() { | ||
do { | ||
List<Runnable> pTasks = propagationTasks; | ||
propagationTasks = new LinkedList<>(); | ||
|
||
pTasks.forEach(Runnable::run); | ||
|
||
if (propagationTasks.isEmpty() && !analogDropPropagationTasks.isEmpty()) { | ||
propagationTasks = analogDropPropagationTasks; | ||
analogDropPropagationTasks = new LinkedList<>(); | ||
} | ||
} while (!propagationTasks.isEmpty()); | ||
} | ||
|
||
void finishRun() { | ||
RedstonePropagator.currentRun = null; | ||
|
||
if (partChanges.isEmpty() && neighborChanges.isEmpty()) { | ||
RedstonePropagator.finishingRun = parent; | ||
clear(); | ||
return; | ||
} | ||
|
||
RedstonePropagator.finishingRun = this; | ||
|
||
// Notify part changes in bulk | ||
for (Map.Entry<TileMultiPart, Collection<TMultiPart>> entry : partChanges.asMap().entrySet()) { | ||
Collection<TMultiPart> parts = entry.getValue(); | ||
for (TMultiPart part : parts) { | ||
((IPropagationPart) part).onSignalUpdate(); | ||
} | ||
entry.getKey().multiPartChange(parts); | ||
} | ||
|
||
// Notify normal neighbor changes in bulk | ||
for (Map.Entry<World, Collection<BlockPos>> entry : neighborChanges.asMap().entrySet()) { | ||
World world = entry.getKey(); | ||
Collection<BlockPos> positions = entry.getValue(); | ||
for (BlockPos pos : positions) { | ||
world.neighborChanged(pos, CBMultipartModContent.blockMultipart, pos); | ||
} | ||
} | ||
|
||
RedstonePropagator.finishingRun = parent; | ||
clear(); | ||
} | ||
|
||
void add(IPropagationPart part, IPropagationPart from, int mode) { | ||
if (from != lastCaller) { | ||
lastCaller = from; | ||
count++; | ||
} | ||
propagationTasks.add(() -> part.updateAndPropagate(from, mode)); | ||
} | ||
|
||
void addAnalogDrop(IPropagationPart part) { | ||
analogDropPropagationTasks.add(() -> part.updateAndPropagate(null, RISING)); | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.