Skip to content

Commit

Permalink
Implemented simple //write for binary values (RedstoneTools#268)
Browse files Browse the repository at this point in the history
  • Loading branch information
DreiMu committed Jun 7, 2023
1 parent 7cd3dac commit eb0121b
Showing 1 changed file with 107 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package tools.redstone.redstonetools.features.commands;

import com.google.auto.service.AutoService;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.sk89q.worldedit.math.BlockVector3;
import net.minecraft.block.Blocks;
import net.minecraft.block.RedstoneLampBlock;
import net.minecraft.command.argument.BlockStateArgument;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.util.math.BlockPos;
import tools.redstone.redstonetools.features.AbstractFeature;
import tools.redstone.redstonetools.features.Feature;
import tools.redstone.redstonetools.features.arguments.Argument;
import tools.redstone.redstonetools.features.feedback.Feedback;
import tools.redstone.redstonetools.utils.WorldEditUtils;

import java.math.BigInteger;
import java.util.Collections;

import static tools.redstone.redstonetools.features.arguments.serializers.BigIntegerSerializer.bigInteger;
import static tools.redstone.redstonetools.features.arguments.serializers.BlockStateArgumentSerializer.blockState;
import static tools.redstone.redstonetools.features.arguments.serializers.BoolSerializer.bool;
import static tools.redstone.redstonetools.features.arguments.serializers.IntegerSerializer.integer;
import static tools.redstone.redstonetools.features.arguments.serializers.NumberBaseSerializer.numberBase;

@AutoService(AbstractFeature.class)
@Feature(name = "Binary Block Write", description = "Interprets your WorldEdit selection as a binary number.", command = "/write")
public class BinaryBlockWriteFeature extends CommandFeature {
private static final BlockStateArgument LIT_LAMP_ARG = new BlockStateArgument(
Blocks.REDSTONE_LAMP.getDefaultState().with(RedstoneLampBlock.LIT, true),
Collections.singleton(RedstoneLampBlock.LIT),
null
);

private static final BlockStateArgument UNLIT_LAMP_ARG = new BlockStateArgument(
Blocks.REDSTONE_LAMP.getDefaultState().with(RedstoneLampBlock.LIT, false),
Collections.singleton(RedstoneLampBlock.LIT),
null
);

public static final Argument<Integer> offset = Argument
.ofType(integer(1))
.withDefault(2);
public static final Argument<BlockStateArgument> onBlock = Argument
.ofType(blockState())
.withDefault(LIT_LAMP_ARG);

public static final Argument<BlockStateArgument> offBlock = Argument
.ofType(blockState())
.withDefault(UNLIT_LAMP_ARG);

public static final Argument<BigInteger> number = Argument
.ofType(bigInteger());

@Override
protected Feedback execute(ServerCommandSource source) throws CommandSyntaxException {
var selectionOrFeedback = WorldEditUtils.getSelection(source.getPlayer());

if (selectionOrFeedback.right().isPresent()) {
return selectionOrFeedback.right().get();
}

assert selectionOrFeedback.left().isPresent();
var selection = selectionOrFeedback.left().get();

var boundingBox = selection.getBoundingBox();
var pos1 = boundingBox.getPos1();
var pos2 = boundingBox.getPos2();
var direction = pos2.subtract(pos1).normalize();

// prevent infinite loop
if (direction.lengthSq() == 0) {
direction = BlockVector3.at(0, 0, 1);
}

var spacingVector = direction.multiply(offset.getValue());

if (direction.getBlockX() + direction.getBlockY() + direction.getBlockZ() > 1) {
return Feedback.invalidUsage("The selection must have 2 axis the same");
}

var bits = number.getValue().toString(2);

if (spacingVector.length() * boundingBox.getVolume() < bits.length()) {
return Feedback.invalidUsage("The selection is too small to write the number");
}

var stringIndex = 0;
for (BlockVector3 point = pos1; boundingBox.contains(point); point = point.add(spacingVector)) {
var pos = new BlockPos(point.getBlockX(), point.getBlockY(), point.getBlockZ());

BlockStateArgument state;

if (stringIndex >= bits.length()) {
state = offBlock.getValue();
} else {
state = bits.charAt(stringIndex) == '1' ? onBlock.getValue() : offBlock.getValue();
stringIndex++;
}

source.getPlayer().getWorld().setBlockState(pos, state.getBlockState());
}

return Feedback.success("Wrote " + bits);
}

}

0 comments on commit eb0121b

Please sign in to comment.