Skip to content

Commit

Permalink
Merge pull request #271 from JohanVonElectrum/ss-command-feature
Browse files Browse the repository at this point in the history
ss-command-feature
  • Loading branch information
Matthias1590 authored Jun 14, 2023
2 parents f36d8f8 + c1b5770 commit 0a94f07
Show file tree
Hide file tree
Showing 5 changed files with 246 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package tools.redstone.redstonetools.features.arguments.serializers;

import tools.redstone.redstonetools.utils.SignalBlock;

public class SignalBlockSerializer extends EnumSerializer<SignalBlock> {
private static final SignalBlockSerializer INSTANCE = new SignalBlockSerializer();

private SignalBlockSerializer() {
super(SignalBlock.class);
}

public static SignalBlockSerializer signalBlock() {
return INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package tools.redstone.redstonetools.features.commands;

import com.google.auto.service.AutoService;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import net.minecraft.item.ItemStack;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Text;
import tools.redstone.redstonetools.features.AbstractFeature;
import tools.redstone.redstonetools.features.Feature;
import tools.redstone.redstonetools.features.arguments.Argument;
import tools.redstone.redstonetools.features.arguments.serializers.SignalBlockSerializer;
import tools.redstone.redstonetools.features.feedback.Feedback;
import tools.redstone.redstonetools.utils.SignalBlock;

import java.util.Random;

import static tools.redstone.redstonetools.features.arguments.serializers.IntegerSerializer.integer;

@AutoService(AbstractFeature.class)
@Feature(name = "Signal Strength Block", description = "Creates a block with the specified signal strength.", command = "ssb")
public class SignalStrengthBlockFeature extends CommandFeature {

public static final Argument<Integer> signalStrength = Argument
.ofType(integer(0));

public static final Argument<SignalBlock> block = Argument
.ofType(SignalBlockSerializer.signalBlock())
.withDefault(SignalBlock.AUTO);

@Override
protected Feedback execute(ServerCommandSource source) throws CommandSyntaxException {
try {
ItemStack itemStack = block.getValue().getItemStack(signalStrength.getValue());
source.getPlayer().giveItemStack(itemStack);
} catch (IllegalArgumentException | IllegalStateException e) {
return Feedback.error(e.getMessage());
}

//funny
if(signalStrength.getValue() == 0) {
String[] funny = {
"Why would you want this??", "Wtf are you going to use this for?", "What for?",
"... Ok, if you're sure.", "I'm 99% sure you could just use any other block.",
"This seems unnecessary.", "Is that a typo?", "Do you just like the glint?",
"Wow, what a fancy but otherwise useless barrel.", "For decoration?"};
return Feedback.success(funny[new Random().nextInt(funny.length)]);
}

return Feedback.none();
}

}

This file was deleted.

47 changes: 47 additions & 0 deletions src/main/java/tools/redstone/redstonetools/utils/SignalBlock.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package tools.redstone.redstonetools.utils;

import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack;

public enum SignalBlock {
COMPOSTER(Blocks.COMPOSTER, SignalBlockSupplier.composter()),
BARREL(Blocks.BARREL, SignalBlockSupplier.container(27)),
CHEST(Blocks.CHEST, SignalBlockSupplier.container(27)),
SHULKER_BOX(Blocks.SHULKER_BOX, SignalBlockSupplier.container(27)),
DISPENSER(Blocks.DISPENSER, SignalBlockSupplier.container(9)),
DROPPER(Blocks.DROPPER, SignalBlockSupplier.container(9)),
HOPPER(Blocks.HOPPER, SignalBlockSupplier.container(5)),
BREWING_STAND(Blocks.BREWING_STAND, SignalBlockSupplier.container(5)),
FURNACE(Blocks.FURNACE, SignalBlockSupplier.container(3)),
SMOKER(Blocks.SMOKER, SignalBlockSupplier.container(3)),
BLAST_FURNACE(Blocks.BLAST_FURNACE, SignalBlockSupplier.container(3)),
COMMAND_BLOCK(Blocks.COMMAND_BLOCK, SignalBlockSupplier.commandBlock()),
AUTO(null, null);

private final Block block;
private final SignalBlockSupplier supplier;

SignalBlock(Block block, SignalBlockSupplier supplier) {
this.block = block;
this.supplier = supplier;
}

public static SignalBlock getBestBlock(int signal) {
return signal < 1780
? BARREL
: COMMAND_BLOCK;
}

public ItemStack getItemStack(int signal) {
if (block == null || supplier == null)
return getBestBlock(signal).getItemStack(signal);

return supplier.getItemStack(block, signal);
}

@Override
public String toString() {
return this.name().toLowerCase();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package tools.redstone.redstonetools.utils;

import net.minecraft.block.Block;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.text.LiteralText;
import net.minecraft.text.MutableText;
import net.minecraft.util.Formatting;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.registry.Registry;

@FunctionalInterface
public interface SignalBlockSupplier {

NbtCompound createNbt(int signalStrength);

default ItemStack getItemStack(Block block, int signalStrength) {
ItemStack item = new ItemStack(block);
setCompoundNbt(item, this.createNbt(signalStrength));
setItemName(item, signalStrength);
return item;
}

static SignalBlockSupplier container(int slots) {
return signalStrength -> {
if (isInvalidSignalStrength(signalStrength, 1779))
throw new IllegalArgumentException("Container signal must be 0-1779");

NbtCompound tags = new NbtCompound();
NbtList itemsTag = new NbtList();

Item item = getBestItem(signalStrength, slots);
int stackSize = getStackSize(signalStrength, item);
int itemsNeeded = signalStrength == 1
? 1
: (int) Math.ceil(slots * (signalStrength - 1) / 14D * item.getMaxCount());
String itemId = Registry.ITEM.getId(item).toString();

// Check that the calculated number of items is correct.
// This is to prevent problems with items that have a maximum stack size of 1 but stackSize > 1.
// TODO: This can be improved by removing an item and adding stackable items up to the desired signal strength.
// Even with the improvement, this will still fail for inventories with no available slots.
if (calculateComparatorOutput(itemsNeeded, slots, item.getMaxCount()) != signalStrength)
throw new IllegalStateException("This signal strength cannot be achieved with the selected container");

for (int slot = 0, count = itemsNeeded; count > 0; slot++, count -= stackSize) {
NbtCompound slotTag = new NbtCompound();
slotTag.putByte("Slot", (byte) slot);
slotTag.putString("id", itemId);
slotTag.putByte("Count", (byte) Math.min(stackSize, count));
itemsTag.add(slotTag);
}

NbtCompound tag = new NbtCompound();
tag.put("Items", itemsTag);
tags.put("BlockEntityTag", tag);

return tags;
};
}

static SignalBlockSupplier composter() {
return signalStrength -> {
if (signalStrength == 7 || isInvalidSignalStrength(signalStrength, 8))
throw new IllegalArgumentException("Composter signal must be 0-6 or 8");

NbtCompound tags = new NbtCompound();
NbtCompound tag = new NbtCompound();
tag.putInt("level", signalStrength);
tags.put("BlockStateTag", tag);
return tags;
};
}

static SignalBlockSupplier commandBlock() {
return signalStrength -> {
if (isInvalidSignalStrength(signalStrength, Integer.MAX_VALUE))
throw new IllegalArgumentException("Command block signal must be positive");

NbtCompound tags = new NbtCompound();
NbtCompound tag = new NbtCompound();
tag.putInt("SuccessCount", signalStrength);
tags.put("BlockEntityTag", tag);
return tags;
};
}

private static boolean isInvalidSignalStrength(int signalStrength, int maxSignalStrength) {
return signalStrength < 0 || signalStrength > maxSignalStrength;
}

private static int calculateComparatorOutput(int items, int slots, int item$getMaxCount) {
float f = (float) items / (float) item$getMaxCount;
return MathHelper.floor((f /= (float)slots) * 14.0f) + (items > 0 ? 1 : 0);
}

private static Item getBestItem(int signalStrength, int slots) {
if (signalStrength > 15)
return Items.WHITE_SHULKER_BOX;
else if (slots >= 15)
return Items.WOODEN_SHOVEL;
else
return Items.STICK;
}

private static int getStackSize(int signalStrength, Item item) {
if (signalStrength > 897)
return 127;
else if (signalStrength > 15)
return 64;
else
return item.getMaxCount();
}

private static void setCompoundNbt(ItemStack item, NbtCompound nbt) {
nbt.putBoolean("HideFlags", true);
item.setNbt(nbt);
item.addEnchantment(Enchantment.byRawId(0), 0);
}

private static void setItemName(ItemStack item, int signalStrength) {
MutableText text = new LiteralText(String.valueOf(signalStrength));
text.setStyle(text.getStyle().withColor(Formatting.RED));
item.setCustomName(text);
}

}

0 comments on commit 0a94f07

Please sign in to comment.