Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main/antlr/SFML.g
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ boolexpr : TRUE #BooleanTrue
| boolexpr AND boolexpr #BooleanConjunction
| boolexpr OR boolexpr #BooleanDisjunction
| setOp? labelaccess HAS itemcomparison #BooleanHas
| REDSTONE (comparisonOp number)? #BooleanRedstone
;
itemcomparison : comparisonOp number item ;
comparisonOp : GT
Expand Down
36 changes: 32 additions & 4 deletions src/main/java/ca/teamdman/sfm/common/block/ManagerBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,62 @@
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.*;
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.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraftforge.network.NetworkHooks;

import javax.annotation.Nullable;

public class ManagerBlock extends BaseEntityBlock implements EntityBlock, ICable {
public static final BooleanProperty TRIGGERED = BlockStateProperties.TRIGGERED;

public ManagerBlock() {
super(BlockBehaviour.Properties
.of(Material.PISTON)
.destroyTime(2)
.sound(SoundType.METAL));
registerDefaultState(getStateDefinition().any().setValue(TRIGGERED, false));
}

@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(TRIGGERED);
}

public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}


@Override
public void neighborChanged(
BlockState state,
Level level,
BlockPos pos,
Block block,
BlockPos neighbourPos,
boolean movedByPiston
) {
if (!(level.getBlockEntity(pos) instanceof ManagerBlockEntity mgr)) return;
var isPowered = level.hasNeighborSignal(pos) || level.hasNeighborSignal(pos.above());
var debounce = state.getValue(TRIGGERED);
if (isPowered && !debounce) {
mgr.trackRedstonePulseUnprocessed();
level.setBlock(pos, state.setValue(TRIGGERED, true), 4);
} else if (!isPowered && debounce) {
level.setBlock(pos, state.setValue(TRIGGERED, false), 4);
}
}

@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return SFMBlockEntities.MANAGER_BLOCK_ENTITY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ public int getCount() {
return 1;
}
};
private int unprocessedRedstonePulses = 0; // used by redstone trigger

public void trackRedstonePulseUnprocessed() {
unprocessedRedstonePulses++;
}

public void clearRedstonePulseQueue() {
unprocessedRedstonePulses = 0;
}

public int getUnprocessedRedstonePulseCount() {
return unprocessedRedstonePulses;
}

public ManagerBlockEntity(BlockPos blockPos, BlockState blockState) {
super(SFMBlockEntities.MANAGER_BLOCK_ENTITY.get(), blockPos, blockState);
Expand Down Expand Up @@ -127,6 +140,7 @@ public void syntaxError(
try {
programAST = new ASTBuilder().visitProgram(context);
DiskItem.setProgramName(disk, programAST.name());
programAST.addWarnings(disk);
} catch (ResourceLocationException | IllegalArgumentException e) {
errors.add(e.getMessage());
} catch (Throwable t) {
Expand Down
25 changes: 20 additions & 5 deletions src/main/java/ca/teamdman/sfm/common/program/ProgramContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,31 @@ public class ProgramContext {
private final List<InputStatement> INPUTS = new ArrayList<>();
private final Level LEVEL;

private final int REDSTONE_PULSES;

public ProgramContext(ManagerBlockEntity manager) {
this.MANAGER = manager;
NETWORK = CableNetworkManager
this.MANAGER = manager;
NETWORK = CableNetworkManager
.getOrRegisterNetwork(MANAGER)
.get();
LEVEL = MANAGER.getLevel();
LEVEL = MANAGER.getLevel();
REDSTONE_PULSES = MANAGER.getUnprocessedRedstonePulseCount();
}

public ProgramContext(ProgramContext other) {
MANAGER = other.MANAGER;
NETWORK = other.NETWORK;
LEVEL = other.LEVEL;
REDSTONE_PULSES = other.REDSTONE_PULSES;
INPUTS.addAll(other.INPUTS);
}

public int getRedstonePulses() {
return REDSTONE_PULSES;
}

public void clear() {
INPUTS.clear();
public ProgramContext fork() {
return new ProgramContext(this);
}

public ManagerBlockEntity getManager() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public ProgramExecutor(Program program, ManagerBlockEntity manager) {

public void tick() {
var context = new ProgramContext(MANAGER);

// update warnings on disk item every 20 seconds
if (MANAGER
.getLevel()
.getGameTime() % 20 == 0) {
Expand All @@ -27,6 +29,7 @@ public void tick() {
.ifPresent(PROGRAM::addWarnings);
}
PROGRAM.tick(context);
MANAGER.clearRedstonePulseQueue();
}

public Set<String> getReferencedLabels() {
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/ca/teamdman/sfml/ast/ASTBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,36 @@ public ASTNode visitTimerTrigger(SFMLParser.TimerTriggerContext ctx) {
return new TimerTrigger(time, block);
}

@Override
public ASTNode visitBooleanRedstone(SFMLParser.BooleanRedstoneContext ctx) {
ComparisonOperator comp = ComparisonOperator.GREATER_OR_EQUAL;
Quantity num = new Quantity(0);
if (ctx.comparisonOp() != null && ctx.number() != null) {
comp = visitComparisonOp(ctx.comparisonOp());
num = visitNumber(ctx.number());
}

ComparisonOperator finalComp = comp;
int finalNum = num.value();
return new BoolExpr(
programContext -> finalComp.test(
programContext
.getManager()
.getLevel()
.getBestNeighborSignal(programContext
.getManager()
.getBlockPos()),
finalNum
)
);
}

@Override
public ASTNode visitPulseTrigger(SFMLParser.PulseTriggerContext ctx) {
var block = visitBlock(ctx.block());
return new RedstoneTrigger(block);
}

@Override
public Quantity visitNumber(SFMLParser.NumberContext ctx) {
return new Quantity(Integer.parseInt(ctx.getText()));
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/ca/teamdman/sfml/ast/OutputStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import net.minecraftforge.items.IItemHandler;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public record OutputStatement(
Expand All @@ -18,7 +17,7 @@ public record OutputStatement(
@Override
public void tick(ProgramContext context) {
var inputSlots = context.getInputs().flatMap(x -> x.getSlots(context));
var outputSlots = getSlots(context).collect(Collectors.toList());
var outputSlots = getSlots(context).toList();
grabbing:
for (var in : (Iterable<LimitedInputSlot>) inputSlots::iterator) {
for (var out : outputSlots) {
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/ca/teamdman/sfml/ast/Program.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,10 @@ public void addWarnings(ItemStack disk) {
public void tick(ProgramContext context) {
for (Trigger t : triggers) {
if (t.shouldTick(context)) {
var start = System.nanoTime();
t.tick(context);
context.clear();
var end = System.nanoTime();
var diff = end - start;
// var start = System.nanoTime();
t.tick(context.fork());
// var end = System.nanoTime();
// var diff = end - start;
// SFM.LOGGER.debug("Took {}ms ({}us)", diff / 1000000, diff);
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/ca/teamdman/sfml/ast/RedstoneTrigger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package ca.teamdman.sfml.ast;

import ca.teamdman.sfm.common.program.ProgramContext;

public record RedstoneTrigger(
Block block
) implements Trigger {

@Override
public void tick(ProgramContext context) {
for (int i = 0; i < context.getRedstonePulses(); i++) {
block.tick(context);
}
}

@Override
public boolean shouldTick(ProgramContext manager) {
return manager.getManager().getUnprocessedRedstonePulseCount() > 0;
}
}