mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-03-18 01:18:12 +00:00
Add redstone relay block (#2002)
- Move redstone methods out of the IAPIEnvironment, and into a new RedstoneAccess. We similarly move the implementation from Environment into a new RedstoneState class. The interface is possibly a little redundant (interfaces with a single implementation are always a little suspect), but it's nice to keep the consumer/producer interfaces separate. - Abstract most redstone API methods into a separate shared class, that can be used by both the rs API and the new redstone relay. - Add the new redstone relay block. The docs are probably a little lacking here, but I really struggled to write anything which wasn't just "look, it's the same as the redstone API".
This commit is contained in:
parent
ba6da3bc6c
commit
4f66ac79d3
@ -8,7 +8,7 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||
SPDX-License-Identifier: MPL-2.0
|
||||
-->
|
||||
|
||||
The [`event!redstone`] event is fired whenever any redstone inputs on the computer change.
|
||||
The [`event!redstone`] event is fired whenever any redstone inputs on the computer or [relay][`redstone_relay`] change.
|
||||
|
||||
## Return values
|
||||
1. [`string`]: The event name.
|
||||
@ -21,3 +21,7 @@ while true do
|
||||
print("A redstone input has changed!")
|
||||
end
|
||||
```
|
||||
|
||||
## See also
|
||||
- [The `redstone` API on computers][`module!redstone`]
|
||||
- [The `redstone_relay` peripheral][`redstone_relay`]
|
||||
|
@ -56,7 +56,7 @@ junit = "5.10.1"
|
||||
jmh = "1.37"
|
||||
|
||||
# Build tools
|
||||
cctJavadoc = "1.8.2"
|
||||
cctJavadoc = "1.8.3"
|
||||
checkstyle = "10.14.1"
|
||||
curseForgeGradle = "1.0.14"
|
||||
errorProne-core = "2.27.0"
|
||||
|
8
projects/common/src/generated/resources/assets/computercraft/blockstates/redstone_relay.json
generated
Normal file
8
projects/common/src/generated/resources/assets/computercraft/blockstates/redstone_relay.json
generated
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"variants": {
|
||||
"facing=east": {"model": "computercraft:block/redstone_relay", "y": 90},
|
||||
"facing=north": {"model": "computercraft:block/redstone_relay", "y": 0},
|
||||
"facing=south": {"model": "computercraft:block/redstone_relay", "y": 180},
|
||||
"facing=west": {"model": "computercraft:block/redstone_relay", "y": 270}
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
"block.computercraft.monitor_advanced": "Advanced Monitor",
|
||||
"block.computercraft.monitor_normal": "Monitor",
|
||||
"block.computercraft.printer": "Printer",
|
||||
"block.computercraft.redstone_relay": "Redstone Relay",
|
||||
"block.computercraft.speaker": "Speaker",
|
||||
"block.computercraft.turtle_advanced": "Advanced Turtle",
|
||||
"block.computercraft.turtle_advanced.upgraded": "Advanced %s Turtle",
|
||||
|
9
projects/common/src/generated/resources/assets/computercraft/models/block/redstone_relay.json
generated
Normal file
9
projects/common/src/generated/resources/assets/computercraft/models/block/redstone_relay.json
generated
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"parent": "minecraft:block/orientable_with_bottom",
|
||||
"textures": {
|
||||
"bottom": "computercraft:block/redstone_relay_bottom",
|
||||
"front": "computercraft:block/redstone_relay_front",
|
||||
"side": "computercraft:block/redstone_relay_side",
|
||||
"top": "computercraft:block/redstone_relay_top"
|
||||
}
|
||||
}
|
1
projects/common/src/generated/resources/assets/computercraft/models/item/redstone_relay.json
generated
Normal file
1
projects/common/src/generated/resources/assets/computercraft/models/item/redstone_relay.json
generated
Normal file
@ -0,0 +1 @@
|
||||
{"parent": "computercraft:block/redstone_relay"}
|
@ -0,0 +1,16 @@
|
||||
{
|
||||
"parent": "minecraft:recipes/root",
|
||||
"criteria": {
|
||||
"has_cable": {
|
||||
"conditions": {"items": [{"items": ["computercraft:wired_modem"]}]},
|
||||
"trigger": "minecraft:inventory_changed"
|
||||
},
|
||||
"has_the_recipe": {
|
||||
"conditions": {"recipe": "computercraft:redstone_relay"},
|
||||
"trigger": "minecraft:recipe_unlocked"
|
||||
}
|
||||
},
|
||||
"requirements": [["has_cable", "has_the_recipe"]],
|
||||
"rewards": {"recipes": ["computercraft:redstone_relay"]},
|
||||
"sends_telemetry_event": false
|
||||
}
|
12
projects/common/src/generated/resources/data/computercraft/loot_tables/blocks/redstone_relay.json
generated
Normal file
12
projects/common/src/generated/resources/data/computercraft/loot_tables/blocks/redstone_relay.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"type": "minecraft:block",
|
||||
"pools": [
|
||||
{
|
||||
"bonus_rolls": 0.0,
|
||||
"conditions": [{"condition": "minecraft:survives_explosion"}],
|
||||
"entries": [{"type": "minecraft:item", "name": "computercraft:redstone_relay"}],
|
||||
"rolls": 1.0
|
||||
}
|
||||
],
|
||||
"random_sequence": "computercraft:blocks/redstone_relay"
|
||||
}
|
@ -97,6 +97,8 @@ class BlockModelProvider {
|
||||
|
||||
registerCable(generators);
|
||||
|
||||
registerRedstoneControl(generators);
|
||||
|
||||
registerTurtleUpgrade(generators, "block/turtle_crafting_table", "block/turtle_crafty_face");
|
||||
registerTurtleUpgrade(generators, "block/turtle_speaker", "block/turtle_speaker_face");
|
||||
registerTurtleModem(generators, "block/turtle_modem_normal", "block/wireless_modem_normal_face");
|
||||
@ -355,6 +357,18 @@ class BlockModelProvider {
|
||||
generators.blockStateOutput.accept(generator);
|
||||
}
|
||||
|
||||
private static void registerRedstoneControl(BlockModelGenerators generators) {
|
||||
var redstoneControl = ModRegistry.Blocks.REDSTONE_RELAY.get();
|
||||
var model = ModelTemplates.CUBE_ORIENTABLE_TOP_BOTTOM.create(
|
||||
redstoneControl, TextureMapping.orientableCube(redstoneControl), generators.modelOutput
|
||||
);
|
||||
generators.blockStateOutput.accept(
|
||||
MultiVariantGenerator.multiVariant(redstoneControl, Variant.variant().with(VariantProperties.MODEL, model))
|
||||
.with(createHorizontalFacingDispatch())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private static final BooleanProperty[] CABLE_DIRECTIONS = { CableBlock.DOWN, CableBlock.UP, CableBlock.NORTH, CableBlock.SOUTH, CableBlock.WEST, CableBlock.EAST };
|
||||
private static final boolean[] BOOLEANS = new boolean[]{ false, true };
|
||||
|
||||
|
@ -80,6 +80,7 @@ public final class LanguageProvider implements DataProvider {
|
||||
add(ModRegistry.Items.WIRED_MODEM.get(), "Wired Modem");
|
||||
add(ModRegistry.Items.CABLE.get(), "Networking Cable");
|
||||
add(ModRegistry.Items.WIRED_MODEM_FULL.get(), "Wired Modem");
|
||||
add(ModRegistry.Items.REDSTONE_RELAY.get(), "Redstone Relay");
|
||||
|
||||
add(ModRegistry.Items.TURTLE_NORMAL.get(), "Turtle");
|
||||
add(ModRegistry.Blocks.TURTLE_NORMAL.get().getDescriptionId() + ".upgraded", "%s Turtle");
|
||||
|
@ -51,6 +51,7 @@ class LootTableProvider {
|
||||
selfDrop(add, ModRegistry.Blocks.WIRED_MODEM_FULL);
|
||||
selfDrop(add, ModRegistry.Blocks.WIRELESS_MODEM_NORMAL);
|
||||
selfDrop(add, ModRegistry.Blocks.WIRELESS_MODEM_ADVANCED);
|
||||
selfDrop(add, ModRegistry.Blocks.REDSTONE_RELAY);
|
||||
|
||||
computerDrop(add, ModRegistry.Blocks.COMPUTER_NORMAL);
|
||||
computerDrop(add, ModRegistry.Blocks.COMPUTER_ADVANCED);
|
||||
|
@ -461,6 +461,17 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
||||
.requires(ingredients.string())
|
||||
.unlockedBy("has_printer", inventoryChange(ModRegistry.Blocks.PRINTER.get()))
|
||||
.save(RecipeWrapper.wrap(ModRegistry.RecipeSerializers.IMPOSTOR_SHAPELESS.get(), add));
|
||||
|
||||
ShapedRecipeBuilder
|
||||
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.REDSTONE_RELAY.get())
|
||||
.pattern("SRS")
|
||||
.pattern("RCR")
|
||||
.pattern("SRS")
|
||||
.define('S', Items.STONE)
|
||||
.define('R', ingredients.redstone())
|
||||
.define('C', ModRegistry.Blocks.CABLE.get())
|
||||
.unlockedBy("has_cable", inventoryChange(ModRegistry.Blocks.CABLE.get()))
|
||||
.save(add);
|
||||
}
|
||||
|
||||
private static DyeColor ofColour(Colour colour) {
|
||||
|
@ -78,9 +78,12 @@ class TagProvider {
|
||||
ModRegistry.Blocks.WIRELESS_MODEM_NORMAL.get(),
|
||||
ModRegistry.Blocks.WIRELESS_MODEM_ADVANCED.get(),
|
||||
ModRegistry.Blocks.WIRED_MODEM_FULL.get(),
|
||||
ModRegistry.Blocks.CABLE.get()
|
||||
ModRegistry.Blocks.CABLE.get(),
|
||||
ModRegistry.Blocks.REDSTONE_RELAY.get()
|
||||
);
|
||||
|
||||
tags.tag(BlockTags.MINEABLE_WITH_AXE).add(ModRegistry.Blocks.LECTERN.get());
|
||||
|
||||
tags.tag(BlockTags.WITHER_IMMUNE).add(ModRegistry.Blocks.COMPUTER_COMMAND.get());
|
||||
|
||||
tags.tag(ExternalModTags.Blocks.CREATE_BRITTLE).add(
|
||||
|
@ -62,6 +62,8 @@ import dan200.computercraft.shared.peripheral.monitor.MonitorBlockEntity;
|
||||
import dan200.computercraft.shared.peripheral.printer.PrinterBlock;
|
||||
import dan200.computercraft.shared.peripheral.printer.PrinterBlockEntity;
|
||||
import dan200.computercraft.shared.peripheral.printer.PrinterMenu;
|
||||
import dan200.computercraft.shared.peripheral.redstone.RedstoneRelayBlock;
|
||||
import dan200.computercraft.shared.peripheral.redstone.RedstoneRelayBlockEntity;
|
||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerBlock;
|
||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerBlockEntity;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
@ -132,7 +134,7 @@ public final class ModRegistry {
|
||||
return BlockBehaviour.Properties.of().strength(2);
|
||||
}
|
||||
|
||||
private static BlockBehaviour.Properties computerProperties() {
|
||||
private static BlockBehaviour.Properties redstoneConductor() {
|
||||
// Computers shouldn't conduct redstone through them, so set isRedstoneConductor to false. This still allows
|
||||
// redstone to connect to computers though as it's a signal source.
|
||||
return properties().isRedstoneConductor((block, level, blockPos) -> false);
|
||||
@ -147,11 +149,11 @@ public final class ModRegistry {
|
||||
}
|
||||
|
||||
public static final RegistryEntry<ComputerBlock<ComputerBlockEntity>> COMPUTER_NORMAL = REGISTRY.register("computer_normal",
|
||||
() -> new ComputerBlock<>(computerProperties().mapColor(MapColor.STONE), BlockEntities.COMPUTER_NORMAL));
|
||||
() -> new ComputerBlock<>(redstoneConductor().mapColor(MapColor.STONE), BlockEntities.COMPUTER_NORMAL));
|
||||
public static final RegistryEntry<ComputerBlock<ComputerBlockEntity>> COMPUTER_ADVANCED = REGISTRY.register("computer_advanced",
|
||||
() -> new ComputerBlock<>(computerProperties().mapColor(MapColor.GOLD), BlockEntities.COMPUTER_ADVANCED));
|
||||
() -> new ComputerBlock<>(redstoneConductor().mapColor(MapColor.GOLD), BlockEntities.COMPUTER_ADVANCED));
|
||||
public static final RegistryEntry<ComputerBlock<ComputerBlockEntity>> COMPUTER_COMMAND = REGISTRY.register("computer_command",
|
||||
() -> new CommandComputerBlock<>(computerProperties().strength(-1, 6000000.0F), BlockEntities.COMPUTER_COMMAND));
|
||||
() -> new CommandComputerBlock<>(redstoneConductor().strength(-1, 6000000.0F), BlockEntities.COMPUTER_COMMAND));
|
||||
|
||||
public static final RegistryEntry<TurtleBlock> TURTLE_NORMAL = REGISTRY.register("turtle_normal",
|
||||
() -> new TurtleBlock(turtleProperties().mapColor(MapColor.STONE), BlockEntities.TURTLE_NORMAL));
|
||||
@ -179,6 +181,9 @@ public final class ModRegistry {
|
||||
public static final RegistryEntry<CustomLecternBlock> LECTERN = REGISTRY.register("lectern", () -> new CustomLecternBlock(
|
||||
BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).strength(2.5F).sound(SoundType.WOOD).ignitedByLava()
|
||||
));
|
||||
|
||||
public static final RegistryEntry<RedstoneRelayBlock> REDSTONE_RELAY = REGISTRY.register("redstone_relay",
|
||||
() -> new RedstoneRelayBlock(redstoneConductor().mapColor(MapColor.STONE)));
|
||||
}
|
||||
|
||||
public static class BlockEntities {
|
||||
@ -222,6 +227,8 @@ public final class ModRegistry {
|
||||
ofBlock(Blocks.WIRELESS_MODEM_ADVANCED, (p, s) -> new WirelessModemBlockEntity(BlockEntities.WIRELESS_MODEM_ADVANCED.get(), p, s, true));
|
||||
|
||||
public static final RegistryEntry<BlockEntityType<CustomLecternBlockEntity>> LECTERN = ofBlock(Blocks.LECTERN, CustomLecternBlockEntity::new);
|
||||
|
||||
public static final RegistryEntry<BlockEntityType<RedstoneRelayBlockEntity>> REDSTONE_RELAY = ofBlock(Blocks.REDSTONE_RELAY, RedstoneRelayBlockEntity::new);
|
||||
}
|
||||
|
||||
public static final class Items {
|
||||
@ -267,6 +274,7 @@ public final class ModRegistry {
|
||||
public static final RegistryEntry<BlockItem> WIRELESS_MODEM_NORMAL = ofBlock(Blocks.WIRELESS_MODEM_NORMAL, BlockItem::new);
|
||||
public static final RegistryEntry<BlockItem> WIRELESS_MODEM_ADVANCED = ofBlock(Blocks.WIRELESS_MODEM_ADVANCED, BlockItem::new);
|
||||
public static final RegistryEntry<BlockItem> WIRED_MODEM_FULL = ofBlock(Blocks.WIRED_MODEM_FULL, BlockItem::new);
|
||||
public static final RegistryEntry<BlockItem> REDSTONE_RELAY = ofBlock(Blocks.REDSTONE_RELAY, BlockItem::new);
|
||||
|
||||
public static final RegistryEntry<CableBlockItem.Cable> CABLE = REGISTRY.register("cable",
|
||||
() -> new CableBlockItem.Cable(Blocks.CABLE.get(), properties()));
|
||||
@ -415,6 +423,7 @@ public final class ModRegistry {
|
||||
out.accept(Items.CABLE.get());
|
||||
out.accept(Items.WIRED_MODEM.get());
|
||||
out.accept(Items.WIRED_MODEM_FULL.get());
|
||||
out.accept(Items.REDSTONE_RELAY.get());
|
||||
|
||||
out.accept(Items.MONITOR_NORMAL.get());
|
||||
out.accept(Items.MONITOR_ADVANCED.get());
|
||||
|
@ -127,7 +127,7 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements
|
||||
// Update the block state if needed.
|
||||
updateBlockState(computer.getState());
|
||||
|
||||
var changes = computer.pollAndResetChanges();
|
||||
var changes = computer.pollRedstoneChanges();
|
||||
if (changes != 0) {
|
||||
for (var direction : DirectionUtil.FACINGS) {
|
||||
if ((changes & (1 << remapToLocalSide(direction).ordinal())) != 0) updateRedstoneTo(direction);
|
||||
@ -195,8 +195,10 @@ public abstract class AbstractComputerBlockEntity extends BlockEntity implements
|
||||
var offsetSide = dir.getOpposite();
|
||||
var localDir = remapToLocalSide(dir);
|
||||
|
||||
computer.setRedstoneInput(localDir, RedstoneUtil.getRedstoneInput(getLevel(), targetPos, dir));
|
||||
computer.setBundledRedstoneInput(localDir, BundledRedstone.getOutput(getLevel(), targetPos, offsetSide));
|
||||
computer.setRedstoneInput(localDir,
|
||||
RedstoneUtil.getRedstoneInput(getLevel(), targetPos, dir),
|
||||
BundledRedstone.getOutput(getLevel(), targetPos, offsetSide)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,8 +134,8 @@ public class ServerComputer implements InputHandler, ComputerEnvironment {
|
||||
*
|
||||
* @return What sides on the computer have changed.
|
||||
*/
|
||||
public int pollAndResetChanges() {
|
||||
return computer.pollAndResetChanges();
|
||||
public int pollRedstoneChanges() {
|
||||
return computer.pollRedstoneChanges();
|
||||
}
|
||||
|
||||
public UUID register() {
|
||||
@ -222,19 +222,15 @@ public class ServerComputer implements InputHandler, ComputerEnvironment {
|
||||
}
|
||||
|
||||
public int getRedstoneOutput(ComputerSide side) {
|
||||
return computer.getEnvironment().getExternalRedstoneOutput(side);
|
||||
return computer.isOn() ? computer.getRedstone().getExternalOutput(side) : 0;
|
||||
}
|
||||
|
||||
public void setRedstoneInput(ComputerSide side, int level) {
|
||||
computer.getEnvironment().setRedstoneInput(side, level);
|
||||
public void setRedstoneInput(ComputerSide side, int level, int bundledState) {
|
||||
computer.getRedstone().setInput(side, level, bundledState);
|
||||
}
|
||||
|
||||
public int getBundledRedstoneOutput(ComputerSide side) {
|
||||
return computer.getEnvironment().getExternalBundledRedstoneOutput(side);
|
||||
}
|
||||
|
||||
public void setBundledRedstoneInput(ComputerSide side, int combination) {
|
||||
computer.getEnvironment().setBundledRedstoneInput(side, combination);
|
||||
return computer.isOn() ? computer.getRedstone().getExternalBundledOutput(side) : 0;
|
||||
}
|
||||
|
||||
public void setPeripheral(ComputerSide side, @Nullable IPeripheral peripheral) {
|
||||
|
@ -0,0 +1,84 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
package dan200.computercraft.shared.peripheral.redstone;
|
||||
|
||||
import dan200.computercraft.shared.common.IBundledRedstoneBlock;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
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.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* The block for redstone relays. This mostly just forwards method calls to the {@linkplain RedstoneRelayBlockEntity
|
||||
* block entity}.
|
||||
*/
|
||||
public final class RedstoneRelayBlock extends HorizontalDirectionalBlock implements EntityBlock, IBundledRedstoneBlock {
|
||||
public RedstoneRelayBlock(Properties properties) {
|
||||
super(properties);
|
||||
registerDefaultState(defaultBlockState().setValue(FACING, Direction.NORTH));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> properties) {
|
||||
properties.add(FACING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext placement) {
|
||||
return defaultBlockState().setValue(FACING, placement.getHorizontalDirection());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
|
||||
super.tick(state, level, pos, random);
|
||||
|
||||
if (level.getBlockEntity(pos) instanceof RedstoneRelayBlockEntity relay) relay.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean isSignalSource(@Nonnull BlockState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public int getDirectSignal(@Nonnull BlockState state, BlockGetter level, @Nonnull BlockPos pos, @Nonnull Direction incomingSide) {
|
||||
return level.getBlockEntity(pos) instanceof RedstoneRelayBlockEntity relay ? relay.getRedstoneOutput(incomingSide.getOpposite()) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
|
||||
return getDirectSignal(state, level, pos, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBundledRedstoneOutput(Level level, BlockPos pos, Direction side) {
|
||||
return level.getBlockEntity(pos) instanceof RedstoneRelayBlockEntity relay ? relay.getBundledRedstoneOutput(side) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void neighborChanged(@Nonnull BlockState state, @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Block neighbourBlock, @Nonnull BlockPos neighbourPos, boolean isMoving) {
|
||||
if (world.getBlockEntity(pos) instanceof RedstoneRelayBlockEntity relay) relay.neighborChanged(neighbourPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new RedstoneRelayBlockEntity(pos, state);
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
package dan200.computercraft.shared.peripheral.redstone;
|
||||
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.redstone.RedstoneState;
|
||||
import dan200.computercraft.impl.BundledRedstone;
|
||||
import dan200.computercraft.shared.ModRegistry;
|
||||
import dan200.computercraft.shared.util.DirectionUtil;
|
||||
import dan200.computercraft.shared.util.RedstoneUtil;
|
||||
import dan200.computercraft.shared.util.TickScheduler;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public final class RedstoneRelayBlockEntity extends BlockEntity {
|
||||
private final TickScheduler.Token tickToken = new TickScheduler.Token(this);
|
||||
|
||||
private final RedstoneState redstoneState = new RedstoneState(() -> TickScheduler.schedule(tickToken));
|
||||
private final RedstoneRelayPeripheral peripheral = new RedstoneRelayPeripheral(redstoneState);
|
||||
|
||||
public RedstoneRelayBlockEntity(BlockPos pos, BlockState blockState) {
|
||||
super(ModRegistry.BlockEntities.REDSTONE_RELAY.get(), pos, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearRemoved() {
|
||||
super.clearRemoved();
|
||||
TickScheduler.schedule(tickToken);
|
||||
}
|
||||
|
||||
void update() {
|
||||
var changes = redstoneState.updateOutput();
|
||||
if (changes != 0) {
|
||||
for (var direction : DirectionUtil.FACINGS) {
|
||||
if ((changes & (1 << mapSide(direction).ordinal())) != 0) updateRedstoneTo(direction);
|
||||
}
|
||||
}
|
||||
|
||||
if (redstoneState.pollInputChanged()) peripheral.queueRedstoneEvent();
|
||||
}
|
||||
|
||||
void neighborChanged(BlockPos neighbour) {
|
||||
for (var dir : DirectionUtil.FACINGS) {
|
||||
var offset = getBlockPos().relative(dir);
|
||||
if (offset.equals(neighbour)) {
|
||||
updateRedstoneInput(dir, offset, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the position is not any adjacent one, update all inputs. This is pretty terrible, but some redstone mods
|
||||
// handle this incorrectly.
|
||||
for (var dir : DirectionUtil.FACINGS) updateRedstoneInput(dir, getBlockPos().relative(dir), false);
|
||||
}
|
||||
|
||||
private void updateRedstoneTo(Direction direction) {
|
||||
RedstoneUtil.propagateRedstoneOutput(getLevel(), getBlockPos(), direction);
|
||||
updateRedstoneInput(direction, getBlockPos().relative(direction), true);
|
||||
}
|
||||
|
||||
private void updateRedstoneInput(Direction dir, BlockPos targetPos, boolean ticking) {
|
||||
var changed = redstoneState.setInput(mapSide(dir),
|
||||
RedstoneUtil.getRedstoneInput(getLevel(), targetPos, dir),
|
||||
BundledRedstone.getOutput(getLevel(), targetPos, dir.getOpposite())
|
||||
);
|
||||
|
||||
// If the input has changed, and we're not currently in update(), then schedule a new tick so we can queue a
|
||||
// redstone event.
|
||||
if (changed && !ticking) TickScheduler.schedule(tickToken);
|
||||
}
|
||||
|
||||
private ComputerSide mapSide(Direction globalSide) {
|
||||
return DirectionUtil.toLocal(getBlockState().getValue(HorizontalDirectionalBlock.FACING), globalSide);
|
||||
}
|
||||
|
||||
int getRedstoneOutput(Direction side) {
|
||||
return redstoneState.getExternalOutput(mapSide(side));
|
||||
}
|
||||
|
||||
int getBundledRedstoneOutput(Direction side) {
|
||||
return redstoneState.getExternalBundledOutput(mapSide(side));
|
||||
}
|
||||
|
||||
public IPeripheral peripheral() {
|
||||
return peripheral;
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
package dan200.computercraft.shared.peripheral.redstone;
|
||||
|
||||
import dan200.computercraft.api.peripheral.AttachedComputerSet;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.core.apis.RedstoneAPI;
|
||||
import dan200.computercraft.core.apis.RedstoneMethods;
|
||||
import dan200.computercraft.core.redstone.RedstoneAccess;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The redstone relay is a peripheral that allows reading and outputting redstone signals.
|
||||
* <p>
|
||||
* The peripheral provides largely identical methods to a computer's built-in {@link RedstoneAPI} API, allowing setting
|
||||
* signals on all six sides of the block ("top", "bottom", "left", "right", "front" and "back").
|
||||
*
|
||||
* <p>
|
||||
* ## Recipe
|
||||
* <div class="recipe-container">
|
||||
* <mc-recipe recipe="computercraft:redstone_relay"></mc-recipe>
|
||||
* </div>
|
||||
*
|
||||
* @cc.usage Toggle the redstone signal above the computer every 0.5 seconds.
|
||||
*
|
||||
* <pre>{@code
|
||||
* local relay = peripheral.find("redstone_relay")
|
||||
* while true do
|
||||
* relay.setOutput("top", not relay.getOutput("top"))
|
||||
* sleep(0.5)
|
||||
* end
|
||||
* }</pre>
|
||||
* @cc.module redstone_relay
|
||||
* @cc.since 1.114.0
|
||||
*/
|
||||
public final class RedstoneRelayPeripheral extends RedstoneMethods implements IPeripheral {
|
||||
private final AttachedComputerSet computers = new AttachedComputerSet();
|
||||
|
||||
RedstoneRelayPeripheral(RedstoneAccess access) {
|
||||
super(access);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getType() {
|
||||
return "redstone_relay";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable IPeripheral other) {
|
||||
return this == other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attach(IComputerAccess computer) {
|
||||
computers.add(computer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach(IComputerAccess computer) {
|
||||
computers.remove(computer);
|
||||
}
|
||||
|
||||
void queueRedstoneEvent() {
|
||||
computers.queueEvent("redstone");
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 289 B |
Binary file not shown.
After Width: | Height: | Size: 334 B |
Binary file not shown.
After Width: | Height: | Size: 316 B |
Binary file not shown.
After Width: | Height: | Size: 289 B |
@ -0,0 +1,99 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.gametest
|
||||
|
||||
import dan200.computercraft.core.computer.ComputerSide
|
||||
import dan200.computercraft.gametest.api.assertBlockHas
|
||||
import dan200.computercraft.gametest.api.getBlockEntity
|
||||
import dan200.computercraft.gametest.api.modifyBlock
|
||||
import dan200.computercraft.gametest.api.sequence
|
||||
import dan200.computercraft.shared.ModRegistry
|
||||
import dan200.computercraft.shared.peripheral.redstone.RedstoneRelayPeripheral
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.gametest.framework.GameTest
|
||||
import net.minecraft.gametest.framework.GameTestHelper
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.LeverBlock
|
||||
import net.minecraft.world.level.block.RedstoneLampBlock
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
|
||||
class Relay_Test {
|
||||
/**
|
||||
* Ensures redstone signals do not travel through relay.
|
||||
*
|
||||
* @see [Computer_Test.No_through_signal]
|
||||
*/
|
||||
@GameTest
|
||||
fun No_through_signal(context: GameTestHelper) = context.sequence {
|
||||
val lamp = BlockPos(2, 2, 4)
|
||||
val lever = BlockPos(2, 2, 0)
|
||||
thenExecute {
|
||||
context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should not be lit")
|
||||
context.modifyBlock(lever) { x -> x.setValue(LeverBlock.POWERED, true) }
|
||||
}
|
||||
thenIdle(3)
|
||||
thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should still not be lit") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to the above, but with a repeater before the relay
|
||||
*
|
||||
* @see [Computer_Test.No_through_signal_reverse]
|
||||
*/
|
||||
@GameTest
|
||||
fun No_through_signal_reverse(context: GameTestHelper) = context.sequence {
|
||||
val lamp = BlockPos(2, 2, 4)
|
||||
val lever = BlockPos(2, 2, 0)
|
||||
thenExecute {
|
||||
context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should not be lit")
|
||||
context.modifyBlock(lever) { x -> x.setValue(LeverBlock.POWERED, true) }
|
||||
}
|
||||
thenIdle(3)
|
||||
thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should still not be lit") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Check relays propagate redstone to surrounding blocks.
|
||||
*
|
||||
* @see [Computer_Test.Set_and_destroy]
|
||||
*/
|
||||
@GameTest
|
||||
fun Set_and_destroy(context: GameTestHelper) = context.sequence {
|
||||
val lamp = BlockPos(2, 2, 3)
|
||||
|
||||
thenExecute {
|
||||
val peripheral = context.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.REDSTONE_RELAY.get())
|
||||
.peripheral()
|
||||
as RedstoneRelayPeripheral
|
||||
peripheral.setOutput(ComputerSide.BACK, true)
|
||||
}
|
||||
thenIdle(1)
|
||||
thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, true, "Lamp should be lit") }
|
||||
thenExecute { context.setBlock(BlockPos(2, 2, 2), Blocks.AIR) }
|
||||
thenIdle(4)
|
||||
thenExecute { context.assertBlockHas(lamp, RedstoneLampBlock.LIT, false, "Lamp should not be lit") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Check relays pick up propagated redstone to surrounding blocks.
|
||||
*
|
||||
* @see [Computer_Test.Self_output_update]
|
||||
*/
|
||||
@GameTest
|
||||
fun Self_output_update(context: GameTestHelper) = context.sequence {
|
||||
fun relay() = context.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.REDSTONE_RELAY.get())
|
||||
.peripheral() as RedstoneRelayPeripheral
|
||||
|
||||
thenExecute { relay().setOutput(ComputerSide.BACK, true) }
|
||||
thenIdle(2)
|
||||
thenExecute { assertEquals(true, relay().getInput(ComputerSide.BACK), "Input should be on") }
|
||||
|
||||
thenIdle(2)
|
||||
|
||||
thenExecute { relay().setOutput(ComputerSide.BACK, false) }
|
||||
thenIdle(2)
|
||||
thenExecute { assertEquals(false, relay().getInput(ComputerSide.BACK), "Input should be off") }
|
||||
}
|
||||
}
|
@ -92,6 +92,7 @@ object TestHooks {
|
||||
Printer_Test::class.java,
|
||||
Printout_Test::class.java,
|
||||
Recipe_Test::class.java,
|
||||
Relay_Test::class.java,
|
||||
Speaker_Test::class.java,
|
||||
Turtle_Test::class.java,
|
||||
)
|
||||
|
141
projects/common/src/testMod/resources/data/cctest/structures/relay_test.no_through_signal.snbt
generated
Normal file
141
projects/common/src/testMod/resources/data/cctest/structures/relay_test.no_through_signal.snbt
generated
Normal file
@ -0,0 +1,141 @@
|
||||
{
|
||||
DataVersion: 2730,
|
||||
size: [5, 5, 5],
|
||||
data: [
|
||||
{pos: [0, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 1, 0], state: "minecraft:air"},
|
||||
{pos: [0, 1, 1], state: "minecraft:air"},
|
||||
{pos: [0, 1, 2], state: "minecraft:air"},
|
||||
{pos: [0, 1, 3], state: "minecraft:air"},
|
||||
{pos: [0, 1, 4], state: "minecraft:air"},
|
||||
{pos: [1, 1, 0], state: "minecraft:air"},
|
||||
{pos: [1, 1, 1], state: "minecraft:air"},
|
||||
{pos: [1, 1, 2], state: "minecraft:air"},
|
||||
{pos: [1, 1, 3], state: "minecraft:air"},
|
||||
{pos: [1, 1, 4], state: "minecraft:air"},
|
||||
{pos: [2, 1, 0], state: "minecraft:lever{face:floor,facing:south,powered:false}"},
|
||||
{pos: [2, 1, 1], state: "minecraft:repeater{delay:1,facing:north,locked:false,powered:false}"},
|
||||
{pos: [2, 1, 2], state: "computercraft:redstone_relay{facing:north}"},
|
||||
{pos: [2, 1, 3], state: "minecraft:redstone_wire{east:none,north:side,power:0,south:none,west:none}"},
|
||||
{pos: [2, 1, 4], state: "minecraft:redstone_lamp{lit:false}"},
|
||||
{pos: [3, 1, 0], state: "minecraft:air"},
|
||||
{pos: [3, 1, 1], state: "minecraft:air"},
|
||||
{pos: [3, 1, 2], state: "minecraft:air"},
|
||||
{pos: [3, 1, 3], state: "minecraft:air"},
|
||||
{pos: [3, 1, 4], state: "minecraft:air"},
|
||||
{pos: [4, 1, 0], state: "minecraft:air"},
|
||||
{pos: [4, 1, 1], state: "minecraft:air"},
|
||||
{pos: [4, 1, 2], state: "minecraft:air"},
|
||||
{pos: [4, 1, 3], state: "minecraft:air"},
|
||||
{pos: [4, 1, 4], state: "minecraft:air"},
|
||||
{pos: [0, 2, 0], state: "minecraft:air"},
|
||||
{pos: [0, 2, 1], state: "minecraft:air"},
|
||||
{pos: [0, 2, 2], state: "minecraft:air"},
|
||||
{pos: [0, 2, 3], state: "minecraft:air"},
|
||||
{pos: [0, 2, 4], state: "minecraft:air"},
|
||||
{pos: [1, 2, 0], state: "minecraft:air"},
|
||||
{pos: [1, 2, 1], state: "minecraft:air"},
|
||||
{pos: [1, 2, 2], state: "minecraft:air"},
|
||||
{pos: [1, 2, 3], state: "minecraft:air"},
|
||||
{pos: [1, 2, 4], state: "minecraft:air"},
|
||||
{pos: [2, 2, 0], state: "minecraft:air"},
|
||||
{pos: [2, 2, 1], state: "minecraft:air"},
|
||||
{pos: [2, 2, 2], state: "minecraft:air"},
|
||||
{pos: [2, 2, 3], state: "minecraft:air"},
|
||||
{pos: [2, 2, 4], state: "minecraft:air"},
|
||||
{pos: [3, 2, 0], state: "minecraft:air"},
|
||||
{pos: [3, 2, 1], state: "minecraft:air"},
|
||||
{pos: [3, 2, 2], state: "minecraft:air"},
|
||||
{pos: [3, 2, 3], state: "minecraft:air"},
|
||||
{pos: [3, 2, 4], state: "minecraft:air"},
|
||||
{pos: [4, 2, 0], state: "minecraft:air"},
|
||||
{pos: [4, 2, 1], state: "minecraft:air"},
|
||||
{pos: [4, 2, 2], state: "minecraft:air"},
|
||||
{pos: [4, 2, 3], state: "minecraft:air"},
|
||||
{pos: [4, 2, 4], state: "minecraft:air"},
|
||||
{pos: [0, 3, 0], state: "minecraft:air"},
|
||||
{pos: [0, 3, 1], state: "minecraft:air"},
|
||||
{pos: [0, 3, 2], state: "minecraft:air"},
|
||||
{pos: [0, 3, 3], state: "minecraft:air"},
|
||||
{pos: [0, 3, 4], state: "minecraft:air"},
|
||||
{pos: [1, 3, 0], state: "minecraft:air"},
|
||||
{pos: [1, 3, 1], state: "minecraft:air"},
|
||||
{pos: [1, 3, 2], state: "minecraft:air"},
|
||||
{pos: [1, 3, 3], state: "minecraft:air"},
|
||||
{pos: [1, 3, 4], state: "minecraft:air"},
|
||||
{pos: [2, 3, 0], state: "minecraft:air"},
|
||||
{pos: [2, 3, 1], state: "minecraft:air"},
|
||||
{pos: [2, 3, 2], state: "minecraft:air"},
|
||||
{pos: [2, 3, 3], state: "minecraft:air"},
|
||||
{pos: [2, 3, 4], state: "minecraft:air"},
|
||||
{pos: [3, 3, 0], state: "minecraft:air"},
|
||||
{pos: [3, 3, 1], state: "minecraft:air"},
|
||||
{pos: [3, 3, 2], state: "minecraft:air"},
|
||||
{pos: [3, 3, 3], state: "minecraft:air"},
|
||||
{pos: [3, 3, 4], state: "minecraft:air"},
|
||||
{pos: [4, 3, 0], state: "minecraft:air"},
|
||||
{pos: [4, 3, 1], state: "minecraft:air"},
|
||||
{pos: [4, 3, 2], state: "minecraft:air"},
|
||||
{pos: [4, 3, 3], state: "minecraft:air"},
|
||||
{pos: [4, 3, 4], state: "minecraft:air"},
|
||||
{pos: [0, 4, 0], state: "minecraft:air"},
|
||||
{pos: [0, 4, 1], state: "minecraft:air"},
|
||||
{pos: [0, 4, 2], state: "minecraft:air"},
|
||||
{pos: [0, 4, 3], state: "minecraft:air"},
|
||||
{pos: [0, 4, 4], state: "minecraft:air"},
|
||||
{pos: [1, 4, 0], state: "minecraft:air"},
|
||||
{pos: [1, 4, 1], state: "minecraft:air"},
|
||||
{pos: [1, 4, 2], state: "minecraft:air"},
|
||||
{pos: [1, 4, 3], state: "minecraft:air"},
|
||||
{pos: [1, 4, 4], state: "minecraft:air"},
|
||||
{pos: [2, 4, 0], state: "minecraft:air"},
|
||||
{pos: [2, 4, 1], state: "minecraft:air"},
|
||||
{pos: [2, 4, 2], state: "minecraft:air"},
|
||||
{pos: [2, 4, 3], state: "minecraft:air"},
|
||||
{pos: [2, 4, 4], state: "minecraft:air"},
|
||||
{pos: [3, 4, 0], state: "minecraft:air"},
|
||||
{pos: [3, 4, 1], state: "minecraft:air"},
|
||||
{pos: [3, 4, 2], state: "minecraft:air"},
|
||||
{pos: [3, 4, 3], state: "minecraft:air"},
|
||||
{pos: [3, 4, 4], state: "minecraft:air"},
|
||||
{pos: [4, 4, 0], state: "minecraft:air"},
|
||||
{pos: [4, 4, 1], state: "minecraft:air"},
|
||||
{pos: [4, 4, 2], state: "minecraft:air"},
|
||||
{pos: [4, 4, 3], state: "minecraft:air"},
|
||||
{pos: [4, 4, 4], state: "minecraft:air"}
|
||||
],
|
||||
entities: [],
|
||||
palette: [
|
||||
"minecraft:polished_andesite",
|
||||
"minecraft:redstone_lamp{lit:false}",
|
||||
"computercraft:redstone_relay{facing:north}",
|
||||
"minecraft:air",
|
||||
"minecraft:lever{face:floor,facing:south,powered:false}",
|
||||
"minecraft:repeater{delay:1,facing:north,locked:false,powered:false}",
|
||||
"minecraft:redstone_wire{east:none,north:side,power:0,south:none,west:none}"
|
||||
]
|
||||
}
|
141
projects/common/src/testMod/resources/data/cctest/structures/relay_test.no_through_signal_reverse.snbt
generated
Normal file
141
projects/common/src/testMod/resources/data/cctest/structures/relay_test.no_through_signal_reverse.snbt
generated
Normal file
@ -0,0 +1,141 @@
|
||||
{
|
||||
DataVersion: 3120,
|
||||
size: [5, 5, 5],
|
||||
data: [
|
||||
{pos: [0, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 1, 0], state: "minecraft:air"},
|
||||
{pos: [0, 1, 1], state: "minecraft:air"},
|
||||
{pos: [0, 1, 2], state: "minecraft:air"},
|
||||
{pos: [0, 1, 3], state: "minecraft:air"},
|
||||
{pos: [0, 1, 4], state: "minecraft:air"},
|
||||
{pos: [1, 1, 0], state: "minecraft:air"},
|
||||
{pos: [1, 1, 1], state: "minecraft:air"},
|
||||
{pos: [1, 1, 2], state: "minecraft:air"},
|
||||
{pos: [1, 1, 3], state: "minecraft:air"},
|
||||
{pos: [1, 1, 4], state: "minecraft:air"},
|
||||
{pos: [2, 1, 0], state: "minecraft:lever{face:floor,facing:south,powered:false}"},
|
||||
{pos: [2, 1, 1], state: "minecraft:repeater{delay:1,facing:north,locked:false,powered:false}"},
|
||||
{pos: [2, 1, 2], state: "computercraft:redstone_relay{facing:north}"},
|
||||
{pos: [2, 1, 3], state: "minecraft:redstone_wire{east:none,north:side,power:0,south:side,west:none}"},
|
||||
{pos: [2, 1, 4], state: "minecraft:redstone_lamp{lit:false}"},
|
||||
{pos: [3, 1, 0], state: "minecraft:air"},
|
||||
{pos: [3, 1, 1], state: "minecraft:air"},
|
||||
{pos: [3, 1, 2], state: "minecraft:air"},
|
||||
{pos: [3, 1, 3], state: "minecraft:air"},
|
||||
{pos: [3, 1, 4], state: "minecraft:air"},
|
||||
{pos: [4, 1, 0], state: "minecraft:air"},
|
||||
{pos: [4, 1, 1], state: "minecraft:air"},
|
||||
{pos: [4, 1, 2], state: "minecraft:air"},
|
||||
{pos: [4, 1, 3], state: "minecraft:air"},
|
||||
{pos: [4, 1, 4], state: "minecraft:air"},
|
||||
{pos: [0, 2, 0], state: "minecraft:air"},
|
||||
{pos: [0, 2, 1], state: "minecraft:air"},
|
||||
{pos: [0, 2, 2], state: "minecraft:air"},
|
||||
{pos: [0, 2, 3], state: "minecraft:air"},
|
||||
{pos: [0, 2, 4], state: "minecraft:air"},
|
||||
{pos: [1, 2, 0], state: "minecraft:air"},
|
||||
{pos: [1, 2, 1], state: "minecraft:air"},
|
||||
{pos: [1, 2, 2], state: "minecraft:air"},
|
||||
{pos: [1, 2, 3], state: "minecraft:air"},
|
||||
{pos: [1, 2, 4], state: "minecraft:air"},
|
||||
{pos: [2, 2, 0], state: "minecraft:air"},
|
||||
{pos: [2, 2, 1], state: "minecraft:air"},
|
||||
{pos: [2, 2, 2], state: "minecraft:air"},
|
||||
{pos: [2, 2, 3], state: "minecraft:air"},
|
||||
{pos: [2, 2, 4], state: "minecraft:air"},
|
||||
{pos: [3, 2, 0], state: "minecraft:air"},
|
||||
{pos: [3, 2, 1], state: "minecraft:air"},
|
||||
{pos: [3, 2, 2], state: "minecraft:air"},
|
||||
{pos: [3, 2, 3], state: "minecraft:air"},
|
||||
{pos: [3, 2, 4], state: "minecraft:air"},
|
||||
{pos: [4, 2, 0], state: "minecraft:air"},
|
||||
{pos: [4, 2, 1], state: "minecraft:air"},
|
||||
{pos: [4, 2, 2], state: "minecraft:air"},
|
||||
{pos: [4, 2, 3], state: "minecraft:air"},
|
||||
{pos: [4, 2, 4], state: "minecraft:air"},
|
||||
{pos: [0, 3, 0], state: "minecraft:air"},
|
||||
{pos: [0, 3, 1], state: "minecraft:air"},
|
||||
{pos: [0, 3, 2], state: "minecraft:air"},
|
||||
{pos: [0, 3, 3], state: "minecraft:air"},
|
||||
{pos: [0, 3, 4], state: "minecraft:air"},
|
||||
{pos: [1, 3, 0], state: "minecraft:air"},
|
||||
{pos: [1, 3, 1], state: "minecraft:air"},
|
||||
{pos: [1, 3, 2], state: "minecraft:air"},
|
||||
{pos: [1, 3, 3], state: "minecraft:air"},
|
||||
{pos: [1, 3, 4], state: "minecraft:air"},
|
||||
{pos: [2, 3, 0], state: "minecraft:air"},
|
||||
{pos: [2, 3, 1], state: "minecraft:air"},
|
||||
{pos: [2, 3, 2], state: "minecraft:air"},
|
||||
{pos: [2, 3, 3], state: "minecraft:air"},
|
||||
{pos: [2, 3, 4], state: "minecraft:air"},
|
||||
{pos: [3, 3, 0], state: "minecraft:air"},
|
||||
{pos: [3, 3, 1], state: "minecraft:air"},
|
||||
{pos: [3, 3, 2], state: "minecraft:air"},
|
||||
{pos: [3, 3, 3], state: "minecraft:air"},
|
||||
{pos: [3, 3, 4], state: "minecraft:air"},
|
||||
{pos: [4, 3, 0], state: "minecraft:air"},
|
||||
{pos: [4, 3, 1], state: "minecraft:air"},
|
||||
{pos: [4, 3, 2], state: "minecraft:air"},
|
||||
{pos: [4, 3, 3], state: "minecraft:air"},
|
||||
{pos: [4, 3, 4], state: "minecraft:air"},
|
||||
{pos: [0, 4, 0], state: "minecraft:air"},
|
||||
{pos: [0, 4, 1], state: "minecraft:air"},
|
||||
{pos: [0, 4, 2], state: "minecraft:air"},
|
||||
{pos: [0, 4, 3], state: "minecraft:air"},
|
||||
{pos: [0, 4, 4], state: "minecraft:air"},
|
||||
{pos: [1, 4, 0], state: "minecraft:air"},
|
||||
{pos: [1, 4, 1], state: "minecraft:air"},
|
||||
{pos: [1, 4, 2], state: "minecraft:air"},
|
||||
{pos: [1, 4, 3], state: "minecraft:air"},
|
||||
{pos: [1, 4, 4], state: "minecraft:air"},
|
||||
{pos: [2, 4, 0], state: "minecraft:air"},
|
||||
{pos: [2, 4, 1], state: "minecraft:air"},
|
||||
{pos: [2, 4, 2], state: "minecraft:air"},
|
||||
{pos: [2, 4, 3], state: "minecraft:air"},
|
||||
{pos: [2, 4, 4], state: "minecraft:air"},
|
||||
{pos: [3, 4, 0], state: "minecraft:air"},
|
||||
{pos: [3, 4, 1], state: "minecraft:air"},
|
||||
{pos: [3, 4, 2], state: "minecraft:air"},
|
||||
{pos: [3, 4, 3], state: "minecraft:air"},
|
||||
{pos: [3, 4, 4], state: "minecraft:air"},
|
||||
{pos: [4, 4, 0], state: "minecraft:air"},
|
||||
{pos: [4, 4, 1], state: "minecraft:air"},
|
||||
{pos: [4, 4, 2], state: "minecraft:air"},
|
||||
{pos: [4, 4, 3], state: "minecraft:air"},
|
||||
{pos: [4, 4, 4], state: "minecraft:air"}
|
||||
],
|
||||
entities: [],
|
||||
palette: [
|
||||
"minecraft:polished_andesite",
|
||||
"minecraft:redstone_lamp{lit:false}",
|
||||
"minecraft:air",
|
||||
"minecraft:lever{face:floor,facing:south,powered:false}",
|
||||
"minecraft:repeater{delay:1,facing:north,locked:false,powered:false}",
|
||||
"minecraft:redstone_wire{east:none,north:side,power:0,south:side,west:none}",
|
||||
"computercraft:redstone_relay{facing:north}"
|
||||
]
|
||||
}
|
137
projects/common/src/testMod/resources/data/cctest/structures/relay_test.self_output_update.snbt
generated
Normal file
137
projects/common/src/testMod/resources/data/cctest/structures/relay_test.self_output_update.snbt
generated
Normal file
@ -0,0 +1,137 @@
|
||||
{
|
||||
DataVersion: 3120,
|
||||
size: [5, 5, 5],
|
||||
data: [
|
||||
{pos: [0, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 1, 0], state: "minecraft:air"},
|
||||
{pos: [0, 1, 1], state: "minecraft:air"},
|
||||
{pos: [0, 1, 2], state: "minecraft:air"},
|
||||
{pos: [0, 1, 3], state: "minecraft:air"},
|
||||
{pos: [0, 1, 4], state: "minecraft:air"},
|
||||
{pos: [1, 1, 0], state: "minecraft:air"},
|
||||
{pos: [1, 1, 1], state: "minecraft:air"},
|
||||
{pos: [1, 1, 2], state: "minecraft:air"},
|
||||
{pos: [1, 1, 3], state: "minecraft:air"},
|
||||
{pos: [1, 1, 4], state: "minecraft:air"},
|
||||
{pos: [2, 1, 0], state: "minecraft:air"},
|
||||
{pos: [2, 1, 1], state: "minecraft:air"},
|
||||
{pos: [2, 1, 2], state: "computercraft:redstone_relay{facing:north}"},
|
||||
{pos: [2, 1, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 1, 4], state: "minecraft:air"},
|
||||
{pos: [3, 1, 0], state: "minecraft:air"},
|
||||
{pos: [3, 1, 1], state: "minecraft:air"},
|
||||
{pos: [3, 1, 2], state: "minecraft:air"},
|
||||
{pos: [3, 1, 3], state: "minecraft:air"},
|
||||
{pos: [3, 1, 4], state: "minecraft:air"},
|
||||
{pos: [4, 1, 0], state: "minecraft:air"},
|
||||
{pos: [4, 1, 1], state: "minecraft:air"},
|
||||
{pos: [4, 1, 2], state: "minecraft:air"},
|
||||
{pos: [4, 1, 3], state: "minecraft:air"},
|
||||
{pos: [4, 1, 4], state: "minecraft:air"},
|
||||
{pos: [0, 2, 0], state: "minecraft:air"},
|
||||
{pos: [0, 2, 1], state: "minecraft:air"},
|
||||
{pos: [0, 2, 2], state: "minecraft:air"},
|
||||
{pos: [0, 2, 3], state: "minecraft:air"},
|
||||
{pos: [0, 2, 4], state: "minecraft:air"},
|
||||
{pos: [1, 2, 0], state: "minecraft:air"},
|
||||
{pos: [1, 2, 1], state: "minecraft:air"},
|
||||
{pos: [1, 2, 2], state: "minecraft:air"},
|
||||
{pos: [1, 2, 3], state: "minecraft:air"},
|
||||
{pos: [1, 2, 4], state: "minecraft:air"},
|
||||
{pos: [2, 2, 0], state: "minecraft:air"},
|
||||
{pos: [2, 2, 1], state: "minecraft:air"},
|
||||
{pos: [2, 2, 2], state: "minecraft:air"},
|
||||
{pos: [2, 2, 3], state: "minecraft:air"},
|
||||
{pos: [2, 2, 4], state: "minecraft:air"},
|
||||
{pos: [3, 2, 0], state: "minecraft:air"},
|
||||
{pos: [3, 2, 1], state: "minecraft:air"},
|
||||
{pos: [3, 2, 2], state: "minecraft:air"},
|
||||
{pos: [3, 2, 3], state: "minecraft:air"},
|
||||
{pos: [3, 2, 4], state: "minecraft:air"},
|
||||
{pos: [4, 2, 0], state: "minecraft:air"},
|
||||
{pos: [4, 2, 1], state: "minecraft:air"},
|
||||
{pos: [4, 2, 2], state: "minecraft:air"},
|
||||
{pos: [4, 2, 3], state: "minecraft:air"},
|
||||
{pos: [4, 2, 4], state: "minecraft:air"},
|
||||
{pos: [0, 3, 0], state: "minecraft:air"},
|
||||
{pos: [0, 3, 1], state: "minecraft:air"},
|
||||
{pos: [0, 3, 2], state: "minecraft:air"},
|
||||
{pos: [0, 3, 3], state: "minecraft:air"},
|
||||
{pos: [0, 3, 4], state: "minecraft:air"},
|
||||
{pos: [1, 3, 0], state: "minecraft:air"},
|
||||
{pos: [1, 3, 1], state: "minecraft:air"},
|
||||
{pos: [1, 3, 2], state: "minecraft:air"},
|
||||
{pos: [1, 3, 3], state: "minecraft:air"},
|
||||
{pos: [1, 3, 4], state: "minecraft:air"},
|
||||
{pos: [2, 3, 0], state: "minecraft:air"},
|
||||
{pos: [2, 3, 1], state: "minecraft:air"},
|
||||
{pos: [2, 3, 2], state: "minecraft:air"},
|
||||
{pos: [2, 3, 3], state: "minecraft:air"},
|
||||
{pos: [2, 3, 4], state: "minecraft:air"},
|
||||
{pos: [3, 3, 0], state: "minecraft:air"},
|
||||
{pos: [3, 3, 1], state: "minecraft:air"},
|
||||
{pos: [3, 3, 2], state: "minecraft:air"},
|
||||
{pos: [3, 3, 3], state: "minecraft:air"},
|
||||
{pos: [3, 3, 4], state: "minecraft:air"},
|
||||
{pos: [4, 3, 0], state: "minecraft:air"},
|
||||
{pos: [4, 3, 1], state: "minecraft:air"},
|
||||
{pos: [4, 3, 2], state: "minecraft:air"},
|
||||
{pos: [4, 3, 3], state: "minecraft:air"},
|
||||
{pos: [4, 3, 4], state: "minecraft:air"},
|
||||
{pos: [0, 4, 0], state: "minecraft:air"},
|
||||
{pos: [0, 4, 1], state: "minecraft:air"},
|
||||
{pos: [0, 4, 2], state: "minecraft:air"},
|
||||
{pos: [0, 4, 3], state: "minecraft:air"},
|
||||
{pos: [0, 4, 4], state: "minecraft:air"},
|
||||
{pos: [1, 4, 0], state: "minecraft:air"},
|
||||
{pos: [1, 4, 1], state: "minecraft:air"},
|
||||
{pos: [1, 4, 2], state: "minecraft:air"},
|
||||
{pos: [1, 4, 3], state: "minecraft:air"},
|
||||
{pos: [1, 4, 4], state: "minecraft:air"},
|
||||
{pos: [2, 4, 0], state: "minecraft:air"},
|
||||
{pos: [2, 4, 1], state: "minecraft:air"},
|
||||
{pos: [2, 4, 2], state: "minecraft:air"},
|
||||
{pos: [2, 4, 3], state: "minecraft:air"},
|
||||
{pos: [2, 4, 4], state: "minecraft:air"},
|
||||
{pos: [3, 4, 0], state: "minecraft:air"},
|
||||
{pos: [3, 4, 1], state: "minecraft:air"},
|
||||
{pos: [3, 4, 2], state: "minecraft:air"},
|
||||
{pos: [3, 4, 3], state: "minecraft:air"},
|
||||
{pos: [3, 4, 4], state: "minecraft:air"},
|
||||
{pos: [4, 4, 0], state: "minecraft:air"},
|
||||
{pos: [4, 4, 1], state: "minecraft:air"},
|
||||
{pos: [4, 4, 2], state: "minecraft:air"},
|
||||
{pos: [4, 4, 3], state: "minecraft:air"},
|
||||
{pos: [4, 4, 4], state: "minecraft:air"}
|
||||
],
|
||||
entities: [],
|
||||
palette: [
|
||||
"minecraft:polished_andesite",
|
||||
"minecraft:air",
|
||||
"computercraft:redstone_relay{facing:north}"
|
||||
]
|
||||
}
|
138
projects/common/src/testMod/resources/data/cctest/structures/relay_test.set_and_destroy.snbt
generated
Normal file
138
projects/common/src/testMod/resources/data/cctest/structures/relay_test.set_and_destroy.snbt
generated
Normal file
@ -0,0 +1,138 @@
|
||||
{
|
||||
DataVersion: 3120,
|
||||
size: [5, 5, 5],
|
||||
data: [
|
||||
{pos: [0, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 1, 0], state: "minecraft:air"},
|
||||
{pos: [0, 1, 1], state: "minecraft:air"},
|
||||
{pos: [0, 1, 2], state: "minecraft:air"},
|
||||
{pos: [0, 1, 3], state: "minecraft:air"},
|
||||
{pos: [0, 1, 4], state: "minecraft:air"},
|
||||
{pos: [1, 1, 0], state: "minecraft:air"},
|
||||
{pos: [1, 1, 1], state: "minecraft:air"},
|
||||
{pos: [1, 1, 2], state: "minecraft:air"},
|
||||
{pos: [1, 1, 3], state: "minecraft:air"},
|
||||
{pos: [1, 1, 4], state: "minecraft:air"},
|
||||
{pos: [2, 1, 0], state: "minecraft:air"},
|
||||
{pos: [2, 1, 1], state: "minecraft:air"},
|
||||
{pos: [2, 1, 2], state: "computercraft:redstone_relay{facing:north}"},
|
||||
{pos: [2, 1, 3], state: "minecraft:redstone_lamp{lit:false}"},
|
||||
{pos: [2, 1, 4], state: "minecraft:air"},
|
||||
{pos: [3, 1, 0], state: "minecraft:air"},
|
||||
{pos: [3, 1, 1], state: "minecraft:air"},
|
||||
{pos: [3, 1, 2], state: "minecraft:air"},
|
||||
{pos: [3, 1, 3], state: "minecraft:air"},
|
||||
{pos: [3, 1, 4], state: "minecraft:air"},
|
||||
{pos: [4, 1, 0], state: "minecraft:air"},
|
||||
{pos: [4, 1, 1], state: "minecraft:air"},
|
||||
{pos: [4, 1, 2], state: "minecraft:air"},
|
||||
{pos: [4, 1, 3], state: "minecraft:air"},
|
||||
{pos: [4, 1, 4], state: "minecraft:air"},
|
||||
{pos: [0, 2, 0], state: "minecraft:air"},
|
||||
{pos: [0, 2, 1], state: "minecraft:air"},
|
||||
{pos: [0, 2, 2], state: "minecraft:air"},
|
||||
{pos: [0, 2, 3], state: "minecraft:air"},
|
||||
{pos: [0, 2, 4], state: "minecraft:air"},
|
||||
{pos: [1, 2, 0], state: "minecraft:air"},
|
||||
{pos: [1, 2, 1], state: "minecraft:air"},
|
||||
{pos: [1, 2, 2], state: "minecraft:air"},
|
||||
{pos: [1, 2, 3], state: "minecraft:air"},
|
||||
{pos: [1, 2, 4], state: "minecraft:air"},
|
||||
{pos: [2, 2, 0], state: "minecraft:air"},
|
||||
{pos: [2, 2, 1], state: "minecraft:air"},
|
||||
{pos: [2, 2, 2], state: "minecraft:air"},
|
||||
{pos: [2, 2, 3], state: "minecraft:air"},
|
||||
{pos: [2, 2, 4], state: "minecraft:air"},
|
||||
{pos: [3, 2, 0], state: "minecraft:air"},
|
||||
{pos: [3, 2, 1], state: "minecraft:air"},
|
||||
{pos: [3, 2, 2], state: "minecraft:air"},
|
||||
{pos: [3, 2, 3], state: "minecraft:air"},
|
||||
{pos: [3, 2, 4], state: "minecraft:air"},
|
||||
{pos: [4, 2, 0], state: "minecraft:air"},
|
||||
{pos: [4, 2, 1], state: "minecraft:air"},
|
||||
{pos: [4, 2, 2], state: "minecraft:air"},
|
||||
{pos: [4, 2, 3], state: "minecraft:air"},
|
||||
{pos: [4, 2, 4], state: "minecraft:air"},
|
||||
{pos: [0, 3, 0], state: "minecraft:air"},
|
||||
{pos: [0, 3, 1], state: "minecraft:air"},
|
||||
{pos: [0, 3, 2], state: "minecraft:air"},
|
||||
{pos: [0, 3, 3], state: "minecraft:air"},
|
||||
{pos: [0, 3, 4], state: "minecraft:air"},
|
||||
{pos: [1, 3, 0], state: "minecraft:air"},
|
||||
{pos: [1, 3, 1], state: "minecraft:air"},
|
||||
{pos: [1, 3, 2], state: "minecraft:air"},
|
||||
{pos: [1, 3, 3], state: "minecraft:air"},
|
||||
{pos: [1, 3, 4], state: "minecraft:air"},
|
||||
{pos: [2, 3, 0], state: "minecraft:air"},
|
||||
{pos: [2, 3, 1], state: "minecraft:air"},
|
||||
{pos: [2, 3, 2], state: "minecraft:air"},
|
||||
{pos: [2, 3, 3], state: "minecraft:air"},
|
||||
{pos: [2, 3, 4], state: "minecraft:air"},
|
||||
{pos: [3, 3, 0], state: "minecraft:air"},
|
||||
{pos: [3, 3, 1], state: "minecraft:air"},
|
||||
{pos: [3, 3, 2], state: "minecraft:air"},
|
||||
{pos: [3, 3, 3], state: "minecraft:air"},
|
||||
{pos: [3, 3, 4], state: "minecraft:air"},
|
||||
{pos: [4, 3, 0], state: "minecraft:air"},
|
||||
{pos: [4, 3, 1], state: "minecraft:air"},
|
||||
{pos: [4, 3, 2], state: "minecraft:air"},
|
||||
{pos: [4, 3, 3], state: "minecraft:air"},
|
||||
{pos: [4, 3, 4], state: "minecraft:air"},
|
||||
{pos: [0, 4, 0], state: "minecraft:air"},
|
||||
{pos: [0, 4, 1], state: "minecraft:air"},
|
||||
{pos: [0, 4, 2], state: "minecraft:air"},
|
||||
{pos: [0, 4, 3], state: "minecraft:air"},
|
||||
{pos: [0, 4, 4], state: "minecraft:air"},
|
||||
{pos: [1, 4, 0], state: "minecraft:air"},
|
||||
{pos: [1, 4, 1], state: "minecraft:air"},
|
||||
{pos: [1, 4, 2], state: "minecraft:air"},
|
||||
{pos: [1, 4, 3], state: "minecraft:air"},
|
||||
{pos: [1, 4, 4], state: "minecraft:air"},
|
||||
{pos: [2, 4, 0], state: "minecraft:air"},
|
||||
{pos: [2, 4, 1], state: "minecraft:air"},
|
||||
{pos: [2, 4, 2], state: "minecraft:air"},
|
||||
{pos: [2, 4, 3], state: "minecraft:air"},
|
||||
{pos: [2, 4, 4], state: "minecraft:air"},
|
||||
{pos: [3, 4, 0], state: "minecraft:air"},
|
||||
{pos: [3, 4, 1], state: "minecraft:air"},
|
||||
{pos: [3, 4, 2], state: "minecraft:air"},
|
||||
{pos: [3, 4, 3], state: "minecraft:air"},
|
||||
{pos: [3, 4, 4], state: "minecraft:air"},
|
||||
{pos: [4, 4, 0], state: "minecraft:air"},
|
||||
{pos: [4, 4, 1], state: "minecraft:air"},
|
||||
{pos: [4, 4, 2], state: "minecraft:air"},
|
||||
{pos: [4, 4, 3], state: "minecraft:air"},
|
||||
{pos: [4, 4, 4], state: "minecraft:air"}
|
||||
],
|
||||
entities: [],
|
||||
palette: [
|
||||
"minecraft:polished_andesite",
|
||||
"minecraft:redstone_lamp{lit:false}",
|
||||
"minecraft:air",
|
||||
"computercraft:redstone_relay{facing:north}"
|
||||
]
|
||||
}
|
@ -43,18 +43,6 @@ public interface IAPIEnvironment {
|
||||
|
||||
void queueEvent(String event, @Nullable Object... args);
|
||||
|
||||
void setOutput(ComputerSide side, int output);
|
||||
|
||||
int getOutput(ComputerSide side);
|
||||
|
||||
int getInput(ComputerSide side);
|
||||
|
||||
void setBundledOutput(ComputerSide side, int output);
|
||||
|
||||
int getBundledOutput(ComputerSide side);
|
||||
|
||||
int getBundledInput(ComputerSide side);
|
||||
|
||||
void setPeripheralChangeListener(@Nullable IPeripheralChangeListener listener);
|
||||
|
||||
@Nullable
|
||||
|
@ -5,9 +5,9 @@
|
||||
package dan200.computercraft.core.apis;
|
||||
|
||||
import dan200.computercraft.api.lua.ILuaAPI;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.redstone.RedstoneAccess;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -53,11 +53,9 @@ import java.util.List;
|
||||
* the Minecraft wiki."
|
||||
* @cc.module redstone
|
||||
*/
|
||||
public class RedstoneAPI implements ILuaAPI {
|
||||
private final IAPIEnvironment environment;
|
||||
|
||||
public RedstoneAPI(IAPIEnvironment environment) {
|
||||
this.environment = environment;
|
||||
public class RedstoneAPI extends RedstoneMethods implements ILuaAPI {
|
||||
public RedstoneAPI(RedstoneAccess environment) {
|
||||
super(environment);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -76,131 +74,4 @@ public class RedstoneAPI implements ILuaAPI {
|
||||
public final List<String> getSides() {
|
||||
return ComputerSide.NAMES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the redstone signal of a specific side on or off.
|
||||
*
|
||||
* @param side The side to set.
|
||||
* @param on Whether the redstone signal should be on or off. When on, a signal strength of 15 is emitted.
|
||||
*/
|
||||
@LuaFunction
|
||||
public final void setOutput(ComputerSide side, boolean on) {
|
||||
environment.setOutput(side, on ? 15 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current redstone output of a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return Whether the redstone output is on or off.
|
||||
* @see #setOutput
|
||||
*/
|
||||
@LuaFunction
|
||||
public final boolean getOutput(ComputerSide side) {
|
||||
return environment.getOutput(side) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current redstone input of a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return Whether the redstone input is on or off.
|
||||
*/
|
||||
@LuaFunction
|
||||
public final boolean getInput(ComputerSide side) {
|
||||
return environment.getInput(side) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the redstone signal strength for a specific side.
|
||||
*
|
||||
* @param side The side to set.
|
||||
* @param value The signal strength between 0 and 15.
|
||||
* @throws LuaException If {@code value} is not between 0 and 15.
|
||||
* @cc.since 1.51
|
||||
*/
|
||||
@LuaFunction({ "setAnalogOutput", "setAnalogueOutput" })
|
||||
public final void setAnalogOutput(ComputerSide side, int value) throws LuaException {
|
||||
if (value < 0 || value > 15) throw new LuaException("Expected number in range 0-15");
|
||||
environment.setOutput(side, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the redstone output signal strength for a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The output signal strength, between 0 and 15.
|
||||
* @cc.since 1.51
|
||||
* @see #setAnalogOutput
|
||||
*/
|
||||
@LuaFunction({ "getAnalogOutput", "getAnalogueOutput" })
|
||||
public final int getAnalogOutput(ComputerSide side) {
|
||||
return environment.getOutput(side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the redstone input signal strength for a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The input signal strength, between 0 and 15.
|
||||
* @cc.since 1.51
|
||||
*/
|
||||
@LuaFunction({ "getAnalogInput", "getAnalogueInput" })
|
||||
public final int getAnalogInput(ComputerSide side) {
|
||||
return environment.getInput(side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bundled cable output for a specific side.
|
||||
*
|
||||
* @param side The side to set.
|
||||
* @param output The colour bitmask to set.
|
||||
* @cc.see colors.subtract For removing a colour from the bitmask.
|
||||
* @cc.see colors.combine For adding a color to the bitmask.
|
||||
*/
|
||||
@LuaFunction
|
||||
public final void setBundledOutput(ComputerSide side, int output) {
|
||||
environment.setBundledOutput(side, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bundled cable output for a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The bundle cable's output.
|
||||
*/
|
||||
@LuaFunction
|
||||
public final int getBundledOutput(ComputerSide side) {
|
||||
return environment.getBundledOutput(side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bundled cable input for a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The bundle cable's input.
|
||||
* @see #testBundledInput To determine if a specific colour is set.
|
||||
*/
|
||||
@LuaFunction
|
||||
public final int getBundledInput(ComputerSide side) {
|
||||
return environment.getBundledInput(side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a specific combination of colours are on for the given side.
|
||||
*
|
||||
* @param side The side to test.
|
||||
* @param mask The mask to test.
|
||||
* @return If the colours are on.
|
||||
* @cc.usage Check if [`colors.white`] and [`colors.black`] are on above the computer.
|
||||
* <pre>{@code
|
||||
* print(redstone.testBundledInput("top", colors.combine(colors.white, colors.black)))
|
||||
* }</pre>
|
||||
* @see #getBundledInput
|
||||
*/
|
||||
@LuaFunction
|
||||
public final boolean testBundledInput(ComputerSide side, int mask) {
|
||||
var input = environment.getBundledInput(side);
|
||||
return (input & mask) == mask;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,147 @@
|
||||
// Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
//
|
||||
// SPDX-License-Identifier: LicenseRef-CCPL
|
||||
package dan200.computercraft.core.apis;
|
||||
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.redstone.RedstoneAccess;
|
||||
|
||||
/**
|
||||
* A base class for all blocks with redstone integration.
|
||||
*/
|
||||
public class RedstoneMethods {
|
||||
private final RedstoneAccess redstone;
|
||||
|
||||
public RedstoneMethods(RedstoneAccess redstone) {
|
||||
this.redstone = redstone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the redstone signal of a specific side on or off.
|
||||
*
|
||||
* @param side The side to set.
|
||||
* @param on Whether the redstone signal should be on or off. When on, a signal strength of 15 is emitted.
|
||||
*/
|
||||
@LuaFunction
|
||||
public final void setOutput(ComputerSide side, boolean on) {
|
||||
redstone.setOutput(side, on ? 15 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current redstone output of a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return Whether the redstone output is on or off.
|
||||
* @see #setOutput
|
||||
*/
|
||||
@LuaFunction
|
||||
public final boolean getOutput(ComputerSide side) {
|
||||
return redstone.getOutput(side) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current redstone input of a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return Whether the redstone input is on or off.
|
||||
*/
|
||||
@LuaFunction
|
||||
public final boolean getInput(ComputerSide side) {
|
||||
return redstone.getInput(side) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the redstone signal strength for a specific side.
|
||||
*
|
||||
* @param side The side to set.
|
||||
* @param value The signal strength between 0 and 15.
|
||||
* @throws LuaException If {@code value} is not between 0 and 15.
|
||||
* @cc.since 1.51
|
||||
*/
|
||||
@LuaFunction({ "setAnalogOutput", "setAnalogueOutput" })
|
||||
public final void setAnalogOutput(ComputerSide side, int value) throws LuaException {
|
||||
if (value < 0 || value > 15) throw new LuaException("Expected number in range 0-15");
|
||||
redstone.setOutput(side, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the redstone output signal strength for a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The output signal strength, between 0 and 15.
|
||||
* @cc.since 1.51
|
||||
* @see #setAnalogOutput
|
||||
*/
|
||||
@LuaFunction({ "getAnalogOutput", "getAnalogueOutput" })
|
||||
public final int getAnalogOutput(ComputerSide side) {
|
||||
return redstone.getOutput(side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the redstone input signal strength for a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The input signal strength, between 0 and 15.
|
||||
* @cc.since 1.51
|
||||
*/
|
||||
@LuaFunction({ "getAnalogInput", "getAnalogueInput" })
|
||||
public final int getAnalogInput(ComputerSide side) {
|
||||
return redstone.getInput(side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bundled cable output for a specific side.
|
||||
*
|
||||
* @param side The side to set.
|
||||
* @param output The colour bitmask to set.
|
||||
* @cc.see colors.subtract For removing a colour from the bitmask.
|
||||
* @cc.see colors.combine For adding a color to the bitmask.
|
||||
*/
|
||||
@LuaFunction
|
||||
public final void setBundledOutput(ComputerSide side, int output) {
|
||||
redstone.setBundledOutput(side, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bundled cable output for a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The bundle cable's output.
|
||||
*/
|
||||
@LuaFunction
|
||||
public final int getBundledOutput(ComputerSide side) {
|
||||
return redstone.getBundledOutput(side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bundled cable input for a specific side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The bundle cable's input.
|
||||
* @see #testBundledInput To determine if a specific colour is set.
|
||||
*/
|
||||
@LuaFunction
|
||||
public final int getBundledInput(ComputerSide side) {
|
||||
return redstone.getBundledInput(side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a specific combination of colours are on for the given side.
|
||||
*
|
||||
* @param side The side to test.
|
||||
* @param mask The mask to test.
|
||||
* @return If the colours are on.
|
||||
* @cc.usage Check if [`colors.white`] and [`colors.black`] are on above this block.
|
||||
* <pre>{@code
|
||||
* print(redstone.testBundledInput("top", colors.combine(colors.white, colors.black)))
|
||||
* }</pre>
|
||||
* @see #getBundledInput
|
||||
*/
|
||||
@LuaFunction
|
||||
public final boolean testBundledInput(ComputerSide side, int mask) {
|
||||
var input = redstone.getBundledInput(side);
|
||||
return (input & mask) == mask;
|
||||
}
|
||||
}
|
@ -12,10 +12,10 @@ import dan200.computercraft.core.ComputerContext;
|
||||
import dan200.computercraft.core.apis.IAPIEnvironment;
|
||||
import dan200.computercraft.core.computer.mainthread.MainThreadScheduler;
|
||||
import dan200.computercraft.core.filesystem.FileSystem;
|
||||
import dan200.computercraft.core.redstone.RedstoneState;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
@ -54,8 +54,7 @@ public class Computer {
|
||||
|
||||
// Additional state about the computer and its environment.
|
||||
private final Environment internalEnvironment;
|
||||
|
||||
private final AtomicInteger externalOutputChanges = new AtomicInteger();
|
||||
private final RedstoneState redstone = new RedstoneState();
|
||||
|
||||
private boolean startRequested;
|
||||
private int ticksSinceStart = -1;
|
||||
@ -87,6 +86,10 @@ public class Computer {
|
||||
return internalEnvironment;
|
||||
}
|
||||
|
||||
public RedstoneState getRedstone() {
|
||||
return redstone;
|
||||
}
|
||||
|
||||
public IAPIEnvironment getAPIEnvironment() {
|
||||
return internalEnvironment;
|
||||
}
|
||||
@ -157,10 +160,8 @@ public class Computer {
|
||||
executor.tick();
|
||||
|
||||
// Update the environment's internal state.
|
||||
if (redstone.pollInputChanged()) queueEvent("redstone", null);
|
||||
internalEnvironment.tick();
|
||||
|
||||
// Propagate the environment's output to the world.
|
||||
externalOutputChanges.accumulateAndGet(internalEnvironment.updateOutput(), (x, y) -> x | y);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,8 +169,8 @@ public class Computer {
|
||||
*
|
||||
* @return What sides on the computer have changed.
|
||||
*/
|
||||
public int pollAndResetChanges() {
|
||||
return externalOutputChanges.getAndSet(0);
|
||||
public int pollRedstoneChanges() {
|
||||
return redstone.updateOutput();
|
||||
}
|
||||
|
||||
public boolean isBlinking() {
|
||||
|
@ -153,11 +153,11 @@ final class ComputerExecutor implements ComputerScheduler.Worker {
|
||||
luaMethods = context.luaMethods();
|
||||
executor = context.computerScheduler().createExecutor(this, metrics);
|
||||
|
||||
var environment = computer.getEnvironment();
|
||||
var environment = computer.getAPIEnvironment();
|
||||
|
||||
// Add all default APIs to the loaded list.
|
||||
addApi(new TermAPI(environment));
|
||||
addApi(new RedstoneAPI(environment));
|
||||
addApi(new RedstoneAPI(computer.getRedstone()));
|
||||
addApi(new FSAPI(environment));
|
||||
addApi(new PeripheralAPI(environment, context.peripheralMethods()));
|
||||
addApi(new OSAPI(environment));
|
||||
@ -434,14 +434,13 @@ final class ComputerExecutor implements ComputerScheduler.Worker {
|
||||
// Shutdown our APIs
|
||||
for (var api : apis) api.shutdown();
|
||||
computer.getEnvironment().reset();
|
||||
computer.getRedstone().clearOutput();
|
||||
|
||||
// Unload filesystem
|
||||
if (fileSystem != null) {
|
||||
fileSystem.close();
|
||||
fileSystem = null;
|
||||
}
|
||||
|
||||
computer.getEnvironment().resetOutput();
|
||||
} finally {
|
||||
isOnLock.unlock();
|
||||
}
|
||||
|
@ -16,24 +16,12 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Represents the "environment" that a {@link Computer} exists in.
|
||||
* <p>
|
||||
* This handles storing and updating of peripherals and redstone.
|
||||
*
|
||||
* <h1>Redstone</h1>
|
||||
* We holds three kinds of arrays for redstone, in normal and bundled versions:
|
||||
* <ul>
|
||||
* <li>{@link #internalOutput} is the redstone output which the computer has currently set. This is read on both
|
||||
* threads, and written on the computer thread.</li>
|
||||
* <li>{@link #externalOutput} is the redstone output currently propagated to the world. This is only read and written
|
||||
* on the main thread.</li>
|
||||
* <li>{@link #input} is the redstone input from external sources. This is read on both threads, and written on the main
|
||||
* thread.</li>
|
||||
* </ul>
|
||||
* This handles storing and updating of peripherals and timers.
|
||||
*
|
||||
* <h1>Peripheral</h1>
|
||||
* We also keep track of peripherals. These are read on both threads, and only written on the main thread.
|
||||
@ -43,17 +31,6 @@ public final class Environment implements IAPIEnvironment {
|
||||
private final ComputerEnvironment environment;
|
||||
private final MetricsObserver metrics;
|
||||
|
||||
private boolean internalOutputChanged = false;
|
||||
private final int[] internalOutput = new int[ComputerSide.COUNT];
|
||||
private final int[] internalBundledOutput = new int[ComputerSide.COUNT];
|
||||
|
||||
private final int[] externalOutput = new int[ComputerSide.COUNT];
|
||||
private final int[] externalBundledOutput = new int[ComputerSide.COUNT];
|
||||
|
||||
private boolean inputChanged = false;
|
||||
private final int[] input = new int[ComputerSide.COUNT];
|
||||
private final int[] bundledInput = new int[ComputerSide.COUNT];
|
||||
|
||||
private final IPeripheral[] peripherals = new IPeripheral[ComputerSide.COUNT];
|
||||
private @Nullable IPeripheralChangeListener peripheralListener = null;
|
||||
|
||||
@ -111,76 +88,6 @@ public final class Environment implements IAPIEnvironment {
|
||||
computer.queueEvent(event, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInput(ComputerSide side) {
|
||||
return input[side.ordinal()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBundledInput(ComputerSide side) {
|
||||
return bundledInput[side.ordinal()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutput(ComputerSide side, int output) {
|
||||
var index = side.ordinal();
|
||||
synchronized (internalOutput) {
|
||||
if (internalOutput[index] != output) {
|
||||
internalOutput[index] = output;
|
||||
internalOutputChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOutput(ComputerSide side) {
|
||||
synchronized (internalOutput) {
|
||||
return computer.isOn() ? internalOutput[side.ordinal()] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBundledOutput(ComputerSide side, int output) {
|
||||
var index = side.ordinal();
|
||||
synchronized (internalOutput) {
|
||||
if (internalBundledOutput[index] != output) {
|
||||
internalBundledOutput[index] = output;
|
||||
internalOutputChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBundledOutput(ComputerSide side) {
|
||||
synchronized (internalOutput) {
|
||||
return computer.isOn() ? internalBundledOutput[side.ordinal()] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int getExternalRedstoneOutput(ComputerSide side) {
|
||||
return computer.isOn() ? externalOutput[side.ordinal()] : 0;
|
||||
}
|
||||
|
||||
public int getExternalBundledRedstoneOutput(ComputerSide side) {
|
||||
return computer.isOn() ? externalBundledOutput[side.ordinal()] : 0;
|
||||
}
|
||||
|
||||
public void setRedstoneInput(ComputerSide side, int level) {
|
||||
var index = side.ordinal();
|
||||
if (input[index] != level) {
|
||||
input[index] = level;
|
||||
inputChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBundledRedstoneInput(ComputerSide side, int combination) {
|
||||
var index = side.ordinal();
|
||||
if (bundledInput[index] != combination) {
|
||||
bundledInput[index] = combination;
|
||||
inputChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the computer starts up or shuts down, to reset any internal state.
|
||||
*
|
||||
@ -197,11 +104,6 @@ public final class Environment implements IAPIEnvironment {
|
||||
* Called on the main thread to update the internal state of the computer.
|
||||
*/
|
||||
void tick() {
|
||||
if (inputChanged) {
|
||||
inputChanged = false;
|
||||
queueEvent("redstone");
|
||||
}
|
||||
|
||||
synchronized (timers) {
|
||||
// Countdown all of our active timers
|
||||
Iterator<Int2ObjectMap.Entry<Timer>> it = timers.int2ObjectEntrySet().iterator();
|
||||
@ -218,45 +120,6 @@ public final class Environment implements IAPIEnvironment {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on the main thread to propagate the internal outputs to the external ones.
|
||||
*
|
||||
* @return If the outputs have changed.
|
||||
*/
|
||||
int updateOutput() {
|
||||
// Mark output as changed if the internal redstone has changed
|
||||
synchronized (internalOutput) {
|
||||
if (!internalOutputChanged) return 0;
|
||||
|
||||
var changed = 0;
|
||||
|
||||
for (var i = 0; i < ComputerSide.COUNT; i++) {
|
||||
if (externalOutput[i] != internalOutput[i]) {
|
||||
externalOutput[i] = internalOutput[i];
|
||||
changed |= 1 << i;
|
||||
}
|
||||
|
||||
if (externalBundledOutput[i] != internalBundledOutput[i]) {
|
||||
externalBundledOutput[i] = internalBundledOutput[i];
|
||||
changed |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
internalOutputChanged = false;
|
||||
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
void resetOutput() {
|
||||
// Reset redstone output
|
||||
synchronized (internalOutput) {
|
||||
Arrays.fill(internalOutput, 0);
|
||||
Arrays.fill(internalBundledOutput, 0);
|
||||
internalOutputChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IPeripheral getPeripheral(ComputerSide side) {
|
||||
|
@ -0,0 +1,63 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
package dan200.computercraft.core.redstone;
|
||||
|
||||
import dan200.computercraft.core.apis.RedstoneMethods;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
|
||||
/**
|
||||
* Common interface between blocks which provide and consume a redstone signal.
|
||||
*
|
||||
* @see RedstoneMethods Lua-facing methods wrapping this interface.
|
||||
* @see RedstoneState A concrete implementation of this class.
|
||||
*/
|
||||
public interface RedstoneAccess {
|
||||
/**
|
||||
* Set the redstone output on a given side.
|
||||
*
|
||||
* @param side The side to set.
|
||||
* @param output The output level, between 0 and 15.
|
||||
*/
|
||||
void setOutput(ComputerSide side, int output);
|
||||
|
||||
/**
|
||||
* Get the redstone output on a given side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The output level, between 0 and 15.
|
||||
*/
|
||||
int getOutput(ComputerSide side);
|
||||
|
||||
/**
|
||||
* Get the redstone input on a given side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The input level, between 0 and 15.
|
||||
*/
|
||||
int getInput(ComputerSide side);
|
||||
|
||||
/**
|
||||
* Set the bundled redstone output on a given side.
|
||||
*
|
||||
* @param side The side to set.
|
||||
* @param output The output state, as a 16-bit bitmask.
|
||||
*/
|
||||
void setBundledOutput(ComputerSide side, int output);
|
||||
|
||||
/**
|
||||
* Get the bundled redstone output on a given side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The output state, as a 16-bit bitmask.
|
||||
*/
|
||||
int getBundledOutput(ComputerSide side);
|
||||
|
||||
/**
|
||||
* Set the bundled redstone input on a given side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The input state, as a 16-bit bitmask.
|
||||
*/
|
||||
int getBundledInput(ComputerSide side);
|
||||
}
|
@ -0,0 +1,248 @@
|
||||
// Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
//
|
||||
// SPDX-License-Identifier: LicenseRef-CCPL
|
||||
package dan200.computercraft.core.redstone;
|
||||
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Manages the state of redstone inputs and ouputs on a computer (or other redstone emitting block).
|
||||
* <p>
|
||||
* As computers execute on a separate thread to the main Minecraft world, computers cannot immediately read or write
|
||||
* redstone values. Instead, we maintain a copy of the block's redstone inputs and outputs, and sync that with the
|
||||
* Minecraft world when needed.
|
||||
*
|
||||
* <h2>Input</h2>
|
||||
* Redstone inputs should be propagated immediately to the internal state of the computer. Computers (and other redstone
|
||||
* blocks) listen for block updates, fetch their neighbour's redstone state, and then call
|
||||
* {@link #setInput(ComputerSide, int, int)}.
|
||||
* <p>
|
||||
* However, we do not want to immediately schedule a {@code "redstone"} event, as otherwise we could schedule many
|
||||
* events in a single tick. Instead, the next time the block is ticked, the consumer should call
|
||||
* {@link #pollInputChanged()} and queue an event if needed.
|
||||
*
|
||||
* <h2>Output</h2>
|
||||
* In order to reduce block updates, we maintain a separate "internal" and "external" output state. Whenever a computer
|
||||
* sets a redstone output, the "internal" state is updated, and a dirty flag is set. When the computer is ticked,
|
||||
* {@link #updateOutput()} should be called, to copy the internal state to the external state. This returns a bitmask
|
||||
* indicating which sides have changed. The external outputs may then be read with {@link #getExternalOutput(ComputerSide)}
|
||||
* and {@link #getExternalBundledOutput(ComputerSide)}.
|
||||
*/
|
||||
public final class RedstoneState implements RedstoneAccess {
|
||||
private final @Nullable Runnable onOutputChanged;
|
||||
|
||||
private final ReentrantLock outputLock = new ReentrantLock();
|
||||
private @GuardedBy("outputLock") boolean internalOutputChanged = false;
|
||||
private final @GuardedBy("outputLock") int[] internalOutput = new int[ComputerSide.COUNT];
|
||||
private final @GuardedBy("outputLock") int[] internalBundledOutput = new int[ComputerSide.COUNT];
|
||||
|
||||
private final int[] externalOutput = new int[ComputerSide.COUNT];
|
||||
private final int[] externalBundledOutput = new int[ComputerSide.COUNT];
|
||||
|
||||
private final ReentrantLock inputLock = new ReentrantLock();
|
||||
private boolean inputChanged = false;
|
||||
private final @GuardedBy("inputLock") int[] input = new int[ComputerSide.COUNT];
|
||||
private final @GuardedBy("inputLock") int[] bundledInput = new int[ComputerSide.COUNT];
|
||||
|
||||
public RedstoneState() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@link RedstoneState}, with a callback function to invoke when the <em>internal</em> output has
|
||||
* changed. This function is called from the computer thread.
|
||||
*
|
||||
* @param outputChanged The function to invoke when output has changed.
|
||||
*/
|
||||
public RedstoneState(@Nullable Runnable outputChanged) {
|
||||
this.onOutputChanged = outputChanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInput(ComputerSide side) {
|
||||
inputLock.lock();
|
||||
try {
|
||||
return input[side.ordinal()];
|
||||
} finally {
|
||||
inputLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBundledInput(ComputerSide side) {
|
||||
inputLock.lock();
|
||||
try {
|
||||
return bundledInput[side.ordinal()];
|
||||
} finally {
|
||||
inputLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutput(ComputerSide side, int output) {
|
||||
var index = side.ordinal();
|
||||
|
||||
outputLock.lock();
|
||||
try {
|
||||
if (internalOutput[index] == output) return;
|
||||
internalOutput[index] = output;
|
||||
setOutputChanged();
|
||||
} finally {
|
||||
outputLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOutput(ComputerSide side) {
|
||||
outputLock.lock();
|
||||
try {
|
||||
return internalOutput[side.ordinal()];
|
||||
} finally {
|
||||
outputLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBundledOutput(ComputerSide side, int output) {
|
||||
var index = side.ordinal();
|
||||
outputLock.lock();
|
||||
try {
|
||||
if (internalBundledOutput[index] == output) return;
|
||||
internalBundledOutput[index] = output;
|
||||
setOutputChanged();
|
||||
} finally {
|
||||
outputLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBundledOutput(ComputerSide side) {
|
||||
outputLock.lock();
|
||||
try {
|
||||
return internalBundledOutput[side.ordinal()];
|
||||
} finally {
|
||||
outputLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("outputLock")
|
||||
private void setOutputChanged() {
|
||||
if (internalOutputChanged) return;
|
||||
internalOutputChanged = true;
|
||||
if (onOutputChanged != null) onOutputChanged.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagate redstone changes from the computer to the outside world. The effective outputs can be acquired with
|
||||
* {@link #getExternalOutput(ComputerSide)} and {@link #getExternalBundledOutput(ComputerSide)}.
|
||||
*
|
||||
* @return A bitmask indicating which sides have changed (indexed via {@link ComputerSide#ordinal()}).
|
||||
*/
|
||||
public int updateOutput() {
|
||||
outputLock.lock();
|
||||
try {
|
||||
if (!internalOutputChanged) return 0;
|
||||
|
||||
var changed = 0;
|
||||
|
||||
for (var i = 0; i < ComputerSide.COUNT; i++) {
|
||||
if (externalOutput[i] != internalOutput[i]) {
|
||||
externalOutput[i] = internalOutput[i];
|
||||
changed |= 1 << i;
|
||||
}
|
||||
|
||||
if (externalBundledOutput[i] != internalBundledOutput[i]) {
|
||||
externalBundledOutput[i] = internalBundledOutput[i];
|
||||
changed |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
internalOutputChanged = false;
|
||||
|
||||
return changed;
|
||||
} finally {
|
||||
outputLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the redstone output for a given side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The effective redstone output.
|
||||
*/
|
||||
public int getExternalOutput(ComputerSide side) {
|
||||
return externalOutput[side.ordinal()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bundled redstone output for a given side.
|
||||
*
|
||||
* @param side The side to get.
|
||||
* @return The effective bundled redstone output.
|
||||
*/
|
||||
public int getExternalBundledOutput(ComputerSide side) {
|
||||
return externalBundledOutput[side.ordinal()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset any redstone output set by the computer.
|
||||
*/
|
||||
public void clearOutput() {
|
||||
outputLock.lock();
|
||||
try {
|
||||
Arrays.fill(internalOutput, 0);
|
||||
Arrays.fill(internalBundledOutput, 0);
|
||||
internalOutputChanged = true;
|
||||
} finally {
|
||||
outputLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the redstone input for a given side.
|
||||
*
|
||||
* @param side The side to update.
|
||||
* @param level The redstone level.
|
||||
* @param bundledState The bundled redstone state.
|
||||
* @return Whether the input has changed.
|
||||
*/
|
||||
public boolean setInput(ComputerSide side, int level, int bundledState) {
|
||||
var index = side.ordinal();
|
||||
inputLock.lock();
|
||||
try {
|
||||
var changed = false;
|
||||
if (input[index] != level) {
|
||||
input[index] = level;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (bundledInput[index] != bundledState) {
|
||||
bundledInput[index] = bundledState;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
inputChanged |= changed;
|
||||
return changed;
|
||||
} finally {
|
||||
inputLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether any redstone inputs set by {@link #setInput(ComputerSide, int, int)} have changed since the last
|
||||
* call to this function.
|
||||
*
|
||||
* @return Whether any redstone inputs has changed.
|
||||
*/
|
||||
public boolean pollInputChanged() {
|
||||
var changed = inputChanged;
|
||||
inputChanged = false;
|
||||
return changed;
|
||||
}
|
||||
}
|
@ -63,34 +63,6 @@ public abstract class BasicApiEnvironment implements IAPIEnvironment {
|
||||
public void reboot() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutput(ComputerSide side, int output) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOutput(ComputerSide side) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInput(ComputerSide side) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBundledOutput(ComputerSide side, int output) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBundledOutput(ComputerSide side) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBundledInput(ComputerSide side) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPeripheralChangeListener(@Nullable IPeripheralChangeListener listener) {
|
||||
}
|
||||
|
12
projects/fabric/src/generated/resources/data/computercraft/recipes/redstone_relay.json
generated
Normal file
12
projects/fabric/src/generated/resources/data/computercraft/recipes/redstone_relay.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "redstone",
|
||||
"key": {
|
||||
"C": {"item": "computercraft:wired_modem"},
|
||||
"R": {"tag": "c:redstone_dusts"},
|
||||
"S": {"item": "minecraft:stone"}
|
||||
},
|
||||
"pattern": ["SRS", "RCR", "SRS"],
|
||||
"result": {"item": "computercraft:redstone_relay"},
|
||||
"show_notification": true
|
||||
}
|
1
projects/fabric/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json
generated
Normal file
1
projects/fabric/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json
generated
Normal file
@ -0,0 +1 @@
|
||||
{"replace": false, "values": ["computercraft:lectern"]}
|
@ -13,6 +13,7 @@
|
||||
"computercraft:wireless_modem_normal",
|
||||
"computercraft:wireless_modem_advanced",
|
||||
"computercraft:wired_modem_full",
|
||||
"computercraft:cable"
|
||||
"computercraft:cable",
|
||||
"computercraft:redstone_relay"
|
||||
]
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ public class ComputerCraft {
|
||||
PeripheralLookup.get().registerForBlockEntity(WirelessModemBlockEntity::getPeripheral, ModRegistry.BlockEntities.WIRELESS_MODEM_ADVANCED.get());
|
||||
PeripheralLookup.get().registerForBlockEntity(WiredModemFullBlockEntity::getPeripheral, ModRegistry.BlockEntities.WIRED_MODEM_FULL.get());
|
||||
PeripheralLookup.get().registerForBlockEntity(CableBlockEntity::getPeripheral, ModRegistry.BlockEntities.CABLE.get());
|
||||
PeripheralLookup.get().registerForBlockEntity((b, d) -> b.peripheral(), ModRegistry.BlockEntities.REDSTONE_RELAY.get());
|
||||
|
||||
WiredElementLookup.get().registerForBlockEntity((b, d) -> b.getElement(), ModRegistry.BlockEntities.WIRED_MODEM_FULL.get());
|
||||
WiredElementLookup.get().registerForBlockEntity(CableBlockEntity::getWiredElement, ModRegistry.BlockEntities.CABLE.get());
|
||||
|
12
projects/forge/src/generated/resources/data/computercraft/recipes/redstone_relay.json
generated
Normal file
12
projects/forge/src/generated/resources/data/computercraft/recipes/redstone_relay.json
generated
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "redstone",
|
||||
"key": {
|
||||
"C": {"item": "computercraft:wired_modem"},
|
||||
"R": {"tag": "forge:dusts/redstone"},
|
||||
"S": {"item": "minecraft:stone"}
|
||||
},
|
||||
"pattern": ["SRS", "RCR", "SRS"],
|
||||
"result": {"item": "computercraft:redstone_relay"},
|
||||
"show_notification": true
|
||||
}
|
1
projects/forge/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json
generated
Normal file
1
projects/forge/src/generated/resources/data/minecraft/tags/blocks/mineable/axe.json
generated
Normal file
@ -0,0 +1 @@
|
||||
{"values": ["computercraft:lectern"]}
|
@ -12,6 +12,7 @@
|
||||
"computercraft:wireless_modem_normal",
|
||||
"computercraft:wireless_modem_advanced",
|
||||
"computercraft:wired_modem_full",
|
||||
"computercraft:cable"
|
||||
"computercraft:cable",
|
||||
"computercraft:redstone_relay"
|
||||
]
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import dan200.computercraft.shared.peripheral.modem.wired.WiredModemFullBlockEnt
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemBlockEntity;
|
||||
import dan200.computercraft.shared.peripheral.monitor.MonitorBlockEntity;
|
||||
import dan200.computercraft.shared.peripheral.printer.PrinterBlockEntity;
|
||||
import dan200.computercraft.shared.peripheral.redstone.RedstoneRelayBlockEntity;
|
||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerBlockEntity;
|
||||
import dan200.computercraft.shared.turtle.blocks.TurtleBlockEntity;
|
||||
import dan200.computercraft.shared.util.CapabilityProvider;
|
||||
@ -43,6 +44,7 @@ import net.minecraftforge.items.wrapper.InvWrapper;
|
||||
import net.minecraftforge.items.wrapper.SidedInvWrapper;
|
||||
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT;
|
||||
import static net.minecraftforge.common.capabilities.ForgeCapabilities.ITEM_HANDLER;
|
||||
|
||||
/**
|
||||
@ -133,15 +135,15 @@ public class ForgeCommonHooks {
|
||||
CapabilityProvider.attach(event, INVENTORY, ITEM_HANDLER, () -> new InvWrapper(diskDrive));
|
||||
CapabilityProvider.attach(event, PERIPHERAL, CAPABILITY_PERIPHERAL, diskDrive::peripheral);
|
||||
} else if (blockEntity instanceof CableBlockEntity cable) {
|
||||
var peripheralHandler = SidedCapabilityProvider.attach(event, PERIPHERAL, Capabilities.CAPABILITY_PERIPHERAL, cable::getPeripheral);
|
||||
var elementHandler = SidedCapabilityProvider.attach(event, WIRED_ELEMENT, Capabilities.CAPABILITY_WIRED_ELEMENT, cable::getWiredElement);
|
||||
var peripheralHandler = SidedCapabilityProvider.attach(event, PERIPHERAL, CAPABILITY_PERIPHERAL, cable::getPeripheral);
|
||||
var elementHandler = SidedCapabilityProvider.attach(event, WIRED_ELEMENT, CAPABILITY_WIRED_ELEMENT, cable::getWiredElement);
|
||||
cable.onModemChanged(() -> {
|
||||
peripheralHandler.invalidate();
|
||||
elementHandler.invalidate();
|
||||
});
|
||||
} else if (blockEntity instanceof WiredModemFullBlockEntity modem) {
|
||||
SidedCapabilityProvider.attach(event, PERIPHERAL, Capabilities.CAPABILITY_PERIPHERAL, modem::getPeripheral);
|
||||
CapabilityProvider.attach(event, WIRED_ELEMENT, Capabilities.CAPABILITY_WIRED_ELEMENT, modem::getElement);
|
||||
SidedCapabilityProvider.attach(event, PERIPHERAL, CAPABILITY_PERIPHERAL, modem::getPeripheral);
|
||||
CapabilityProvider.attach(event, WIRED_ELEMENT, CAPABILITY_WIRED_ELEMENT, modem::getElement);
|
||||
} else if (blockEntity instanceof WirelessModemBlockEntity modem) {
|
||||
var peripheral = SidedCapabilityProvider.attach(event, PERIPHERAL, CAPABILITY_PERIPHERAL, modem::getPeripheral);
|
||||
modem.onModemChanged(peripheral::invalidate);
|
||||
@ -150,12 +152,14 @@ public class ForgeCommonHooks {
|
||||
} else if (blockEntity instanceof SpeakerBlockEntity speaker) {
|
||||
CapabilityProvider.attach(event, PERIPHERAL, CAPABILITY_PERIPHERAL, speaker::peripheral);
|
||||
} else if (blockEntity instanceof PrinterBlockEntity printer) {
|
||||
CapabilityProvider.attach(event, PERIPHERAL, Capabilities.CAPABILITY_PERIPHERAL, printer::peripheral);
|
||||
CapabilityProvider.attach(event, PERIPHERAL, CAPABILITY_PERIPHERAL, printer::peripheral);
|
||||
// We don't need to invalidate here as the block's can't be rotated on the X axis!
|
||||
SidedCapabilityProvider.attach(
|
||||
event, INVENTORY, ITEM_HANDLER,
|
||||
s -> s == null ? new InvWrapper(printer) : new SidedInvWrapper(printer, s)
|
||||
);
|
||||
} else if (blockEntity instanceof RedstoneRelayBlockEntity redstone) {
|
||||
CapabilityProvider.attach(event, PERIPHERAL, CAPABILITY_PERIPHERAL, redstone::peripheral);
|
||||
} else if (Config.enableCommandBlock && blockEntity instanceof CommandBlockEntity commandBlock) {
|
||||
CapabilityProvider.attach(event, PERIPHERAL, CAPABILITY_PERIPHERAL, () -> new CommandBlockPeripheral(commandBlock));
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
"computercraft:printed_page": "Printed Page",
|
||||
"computercraft:printed_pages": "Printed Pages",
|
||||
"computercraft:printer": "Printer",
|
||||
"computercraft:redstone_relay": "Redstone Relay",
|
||||
"computercraft:speaker": "Speaker",
|
||||
"computercraft:treasure_disk": "Floppy Disk",
|
||||
"computercraft:turtle_advanced": "Advanced Turtle",
|
||||
@ -48,6 +49,7 @@
|
||||
"minecraft:purple_dye": "Purple Dye",
|
||||
"minecraft:red_dye": "Red Dye",
|
||||
"minecraft:redstone": "Redstone Dust",
|
||||
"minecraft:stick": "Stick",
|
||||
"minecraft:stone": "Stone",
|
||||
"minecraft:string": "String",
|
||||
"minecraft:white_dye": "White Dye",
|
||||
@ -90,7 +92,7 @@
|
||||
["minecraft:gold_ingot"],
|
||||
["minecraft:gold_ingot"],
|
||||
["minecraft:gold_ingot"],
|
||||
["computercraft:computer_advanced"],
|
||||
["computercraft:computer_normal"],
|
||||
["minecraft:gold_ingot"],
|
||||
["minecraft:gold_ingot"],
|
||||
null,
|
||||
@ -281,6 +283,21 @@
|
||||
"output": "computercraft:printer",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:redstone_relay": {
|
||||
"inputs": [
|
||||
["minecraft:stone"],
|
||||
["minecraft:redstone"],
|
||||
["minecraft:stone"],
|
||||
["minecraft:redstone"],
|
||||
["computercraft:wired_modem"],
|
||||
["minecraft:redstone"],
|
||||
["minecraft:stone"],
|
||||
["minecraft:redstone"],
|
||||
["minecraft:stone"]
|
||||
],
|
||||
"output": "computercraft:redstone_relay",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:speaker": {
|
||||
"inputs": [
|
||||
["minecraft:stone"],
|
||||
@ -311,13 +328,43 @@
|
||||
"output": "computercraft:turtle_advanced",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:turtle_advanced_overlays/turtle_rainbow_overlay": {
|
||||
"inputs": [
|
||||
["minecraft:red_dye"],
|
||||
["minecraft:orange_dye"],
|
||||
["minecraft:yellow_dye"],
|
||||
["minecraft:green_dye"],
|
||||
["minecraft:blue_dye"],
|
||||
["minecraft:purple_dye"],
|
||||
["minecraft:stick"],
|
||||
["computercraft:turtle_advanced"],
|
||||
null
|
||||
],
|
||||
"output": "computercraft:turtle_advanced",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:turtle_advanced_overlays/turtle_trans_overlay": {
|
||||
"inputs": [
|
||||
["minecraft:light_blue_dye"],
|
||||
["minecraft:pink_dye"],
|
||||
["minecraft:white_dye"],
|
||||
["minecraft:stick"],
|
||||
["computercraft:turtle_advanced"],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
],
|
||||
"output": "computercraft:turtle_advanced",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:turtle_advanced_upgrade": {
|
||||
"inputs": [
|
||||
["minecraft:gold_ingot"],
|
||||
["minecraft:gold_ingot"],
|
||||
["minecraft:gold_ingot"],
|
||||
["minecraft:gold_ingot"],
|
||||
["computercraft:computer_advanced"],
|
||||
["computercraft:turtle_normal"],
|
||||
["minecraft:gold_ingot"],
|
||||
null,
|
||||
["minecraft:gold_block"],
|
||||
@ -341,6 +388,36 @@
|
||||
"output": "computercraft:turtle_normal",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:turtle_normal_overlays/turtle_rainbow_overlay": {
|
||||
"inputs": [
|
||||
["minecraft:red_dye"],
|
||||
["minecraft:orange_dye"],
|
||||
["minecraft:yellow_dye"],
|
||||
["minecraft:green_dye"],
|
||||
["minecraft:blue_dye"],
|
||||
["minecraft:purple_dye"],
|
||||
["minecraft:stick"],
|
||||
["computercraft:turtle_normal"],
|
||||
null
|
||||
],
|
||||
"output": "computercraft:turtle_normal",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:turtle_normal_overlays/turtle_trans_overlay": {
|
||||
"inputs": [
|
||||
["minecraft:light_blue_dye"],
|
||||
["minecraft:pink_dye"],
|
||||
["minecraft:white_dye"],
|
||||
["minecraft:stick"],
|
||||
["computercraft:turtle_normal"],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
],
|
||||
"output": "computercraft:turtle_normal",
|
||||
"count": 1
|
||||
},
|
||||
"computercraft:wired_modem": {
|
||||
"inputs": [
|
||||
["minecraft:stone"],
|
||||
@ -397,4 +474,4 @@
|
||||
"count": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
projects/web/src/htmlTransform/export/items/minecraft/stick.png
Normal file
BIN
projects/web/src/htmlTransform/export/items/minecraft/stick.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 154 B |
@ -8,6 +8,9 @@ package cc.tweaked.web.stub;
|
||||
* A no-op stub for {@link java.util.concurrent.locks.ReentrantLock}.
|
||||
*/
|
||||
public class ReentrantLock {
|
||||
public void lock() {
|
||||
}
|
||||
|
||||
public boolean tryLock() {
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user