Skip to content

Commit

Permalink
feat: configuration card
Browse files Browse the repository at this point in the history
  • Loading branch information
raoulvdberge committed Oct 31, 2023
1 parent 8728857 commit 8330c0d
Show file tree
Hide file tree
Showing 20 changed files with 365 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Curios integration on Forge.
- Trinkets integration on Fabric.
- Storage Monitor
- Configuration Card. It copies device configurations and can transfer upgrades.

### Changed

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package com.refinedmods.refinedstorage2.platform.api.blockentity;

import java.util.List;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.item.Item;
import org.apiguardian.api.API;

@API(status = API.Status.STABLE, since = "2.0.0-milestone.3.2")
public interface ConfigurationCardTarget {
BlockEntityType<?> getBlockEntityType();

void writeConfiguration(CompoundTag tag);

void readConfiguration(CompoundTag tag);

List<Item> getUpgradeItems();

boolean addUpgradeItem(Item upgradeItem);
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
import com.refinedmods.refinedstorage2.platform.common.internal.storage.type.ItemStorageType;
import com.refinedmods.refinedstorage2.platform.common.internal.storage.type.StorageTypes;
import com.refinedmods.refinedstorage2.platform.common.internal.upgrade.UpgradeDestinations;
import com.refinedmods.refinedstorage2.platform.common.item.ConfigurationCardItem;
import com.refinedmods.refinedstorage2.platform.common.item.FluidStorageDiskItem;
import com.refinedmods.refinedstorage2.platform.common.item.FortuneUpgradeItem;
import com.refinedmods.refinedstorage2.platform.common.item.ItemStorageDiskItem;
Expand Down Expand Up @@ -321,6 +322,10 @@ private void registerSimpleItems(final RegistryCallback<Item> callback) {
for (final ProcessorItem.Type type : ProcessorItem.Type.values()) {
registerProcessor(callback, type);
}
Items.INSTANCE.setConfigurationCard(callback.register(
ContentIds.CONFIGURATION_CARD,
ConfigurationCardItem::new
));
}

private void registerProcessor(final RegistryCallback<Item> callback, final ProcessorItem.Type type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import com.refinedmods.refinedstorage2.platform.common.block.ColorableBlock;
import com.refinedmods.refinedstorage2.platform.common.util.RedstoneMode;

import java.util.Collections;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;

Expand All @@ -18,6 +20,7 @@
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
Expand Down Expand Up @@ -85,8 +88,13 @@ public void readConfiguration(final CompoundTag tag) {
}

@Override
public BlockEntityType<?> getBlockEntityType() {
return getType();
public List<Item> getUpgradeItems() {
return Collections.emptyList();
}

@Override
public boolean addUpgradeItem(final Item upgradeItem) {
return false;
}

public void updateActiveness(final BlockState state,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
import com.refinedmods.refinedstorage2.platform.common.content.Items;
import com.refinedmods.refinedstorage2.platform.common.internal.upgrade.UpgradeDestinations;

import java.util.ArrayList;
import java.util.List;

import com.google.common.util.concurrent.RateLimiter;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
Expand Down Expand Up @@ -63,6 +67,24 @@ private void upgradeContainerChanged() {
}
}

@Override
public List<Item> getUpgradeItems() {
final List<Item> upgradeItems = new ArrayList<>();
for (int i = 0; i < upgradeContainer.getContainerSize(); ++i) {
final ItemStack itemStack = upgradeContainer.getItem(i);
if (itemStack.isEmpty()) {
continue;
}
upgradeItems.add(itemStack.getItem());
}
return upgradeItems;
}

@Override
public boolean addUpgradeItem(final Item upgradeItem) {
return upgradeContainer.addItem(new ItemStack(upgradeItem)).isEmpty();
}

@Override
public void saveAdditional(final CompoundTag tag) {
super.saveAdditional(tag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,6 @@ public void writeConfiguration(final CompoundTag tag) {
tag.putInt(TAG_MODE, DetectorModeSettings.getDetectorMode(getNode().getMode()));
}

@Override
public void load(final CompoundTag tag) {
super.load(tag);
initialize();
propagateAmount();
}

@Override
public void readConfiguration(final CompoundTag tag) {
super.readConfiguration(tag);
Expand All @@ -89,6 +82,8 @@ public void readConfiguration(final CompoundTag tag) {
if (tag.contains(TAG_MODE)) {
getNode().setMode(DetectorModeSettings.getDetectorMode(tag.getInt(TAG_MODE)));
}
initialize();
propagateAmount();
}

public void setAmount(final double amount) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public final class ContentIds {
public static final ResourceLocation RANGE_UPGRADE = createIdentifier("range_upgrade");
public static final ResourceLocation CREATIVE_RANGE_UPGRADE = createIdentifier("creative_range_upgrade");
public static final ResourceLocation STORAGE_MONITOR = createIdentifier("storage_monitor");
public static final ResourceLocation CONFIGURATION_CARD = createIdentifier("configuration_card");

private ContentIds() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,6 @@ private static void appendItems(final Consumer<ItemStack> consumer) {
itemConsumer.accept(Items.INSTANCE.getWirelessGrid());
consumer.accept(Items.INSTANCE.getWirelessGrid().createAtEnergyCapacity());
itemConsumer.accept(Items.INSTANCE.getCreativeWirelessGrid());
itemConsumer.accept(Items.INSTANCE.getConfigurationCard());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ public final class Items {
private Supplier<WirelessGridItem> wirelessGrid;
@Nullable
private Supplier<WirelessGridItem> creativeWirelessGrid;
@Nullable
private Supplier<Item> configurationCard;

private Items() {
}
Expand Down Expand Up @@ -353,4 +355,12 @@ public WirelessGridItem getCreativeWirelessGrid() {
public void setCreativeWirelessGrid(final Supplier<WirelessGridItem> supplier) {
this.creativeWirelessGrid = supplier;
}

public Item getConfigurationCard() {
return Objects.requireNonNull(configurationCard).get();
}

public void setConfigurationCard(final Supplier<Item> supplier) {
this.configurationCard = supplier;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package com.refinedmods.refinedstorage2.platform.common.item;

import com.refinedmods.refinedstorage2.platform.api.blockentity.ConfigurationCardTarget;
import com.refinedmods.refinedstorage2.platform.api.item.HelpTooltipComponent;

import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;

import net.minecraft.ChatFormatting;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.tooltip.TooltipComponent;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;

import static com.refinedmods.refinedstorage2.platform.common.util.IdentifierUtil.createTranslation;
import static java.util.Objects.requireNonNull;

// TODO: textures
public class ConfigurationCardItem extends Item {
private static final Component EMPTY_HELP = createTranslation("item", "configuration_card.empty_help");
private static final Component CONFIGURED_HELP = createTranslation("item", "configuration_card.configured_help");

private static final Component EMPTY = createTranslation("item", "configuration_card.empty")
.withStyle(ChatFormatting.GRAY);

private static final String TAG_TYPE = "type";
private static final String TAG_CONFIG = "config";
private static final String TAG_UPGRADES = "upgrades";

public ConfigurationCardItem() {
super(new Item.Properties().stacksTo(1));
}

@Override
public InteractionResult useOn(final UseOnContext ctx) {
if (ctx.getLevel().isClientSide() || ctx.getPlayer() == null) {
return InteractionResult.CONSUME;
}
final BlockEntity blockEntity = ctx.getLevel().getBlockEntity(ctx.getClickedPos());
if (!(blockEntity instanceof ConfigurationCardTarget target)) {
return InteractionResult.CONSUME;
}
final ItemStack stack = ctx.getItemInHand();
if (stack.getTag() == null) {
writeConfiguration(stack, ctx.getPlayer(), target, blockEntity.getType());
return InteractionResult.CONSUME;
}
return applyConfiguration(ctx.getPlayer(), blockEntity, target, stack.getTag());
}

private InteractionResult applyConfiguration(
final Player player,
final BlockEntity targetBlockEntity,
final ConfigurationCardTarget target,
final CompoundTag tag
) {
final BlockEntityType<?> existingConfiguredType = getConfiguredType(tag);
if (existingConfiguredType != targetBlockEntity.getType()) {
return configurationCardIsConfiguredForDifferentType(player, existingConfiguredType);
}
target.readConfiguration(tag.getCompound(TAG_CONFIG));
tryTransferUpgrades(player, target, tag);
targetBlockEntity.setChanged();
player.sendSystemMessage(createTranslation("item", "configuration_card.applied_configuration"));
return InteractionResult.SUCCESS;
}

private void tryTransferUpgrades(final Player player, final ConfigurationCardTarget target, final CompoundTag tag) {
final ListTag upgradesTag = tag.getList(TAG_UPGRADES, Tag.TAG_STRING);
for (final Tag upgradeItemTag : upgradesTag) {
final ResourceLocation upgradeItemKey = new ResourceLocation(upgradeItemTag.getAsString());
final Item upgradeItem = BuiltInRegistries.ITEM.get(upgradeItemKey);
final int upgradeIndexInPlayerInventory = player.getInventory().findSlotMatchingItem(
new ItemStack(upgradeItem)
);
if (upgradeIndexInPlayerInventory >= 0 && target.addUpgradeItem(upgradeItem)) {
player.getInventory().removeItem(upgradeIndexInPlayerInventory, 1);
}
}
}

private InteractionResult configurationCardIsConfiguredForDifferentType(
final Player player,
@Nullable final BlockEntityType<?> existingConfiguredType
) {
if (existingConfiguredType != null) {
player.sendSystemMessage(createTranslation(
"item",
"configuration_card.cannot_apply_configuration",
getConfiguredTypeTranslation(existingConfiguredType).withStyle(ChatFormatting.YELLOW)
));
}
return InteractionResult.CONSUME;
}

private void writeConfiguration(final ItemStack stack,
final Player player,
final ConfigurationCardTarget target,
final BlockEntityType<?> type) {
final CompoundTag tag = new CompoundTag();
tag.putString(TAG_TYPE, requireNonNull(BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(type)).toString());
tag.put(TAG_CONFIG, createConfigTag(target));
tag.put(TAG_UPGRADES, createUpgradesTag(target));
stack.setTag(tag);
sendCopiedConfigurationMessage(player, type);
}

private CompoundTag createConfigTag(final ConfigurationCardTarget target) {
final CompoundTag tag = new CompoundTag();
target.writeConfiguration(tag);
return tag;
}

private ListTag createUpgradesTag(final ConfigurationCardTarget target) {
final ListTag tag = new ListTag();
target.getUpgradeItems().forEach(item -> {
final ResourceLocation itemKey = BuiltInRegistries.ITEM.getKey(item);
tag.add(StringTag.valueOf(itemKey.toString()));
});
return tag;
}

private void sendCopiedConfigurationMessage(final Player player, final BlockEntityType<?> configuredType) {
if (player.level().isClientSide()) {
return;
}
player.sendSystemMessage(createTranslation(
"item",
"configuration_card.copied_configuration",
getConfiguredTypeTranslation(configuredType).withStyle(ChatFormatting.YELLOW)
));
}

@Override
public InteractionResultHolder<ItemStack> use(final Level level, final Player player, final InteractionHand hand) {
if (player.isCrouching()) {
if (!level.isClientSide()) {
player.sendSystemMessage(createTranslation("item", "configuration_card.cleared_configuration"));
}
return new InteractionResultHolder<>(InteractionResult.CONSUME, new ItemStack(this));
}
return super.use(level, player, hand);
}

@Override
public void appendHoverText(final ItemStack stack,
@Nullable final Level level,
final List<Component> lines,
final TooltipFlag flag) {
super.appendHoverText(stack, level, lines, flag);
if (stack.getTag() == null) {
lines.add(EMPTY);
return;
}
final BlockEntityType<?> configuredType = getConfiguredType(stack.getTag());
if (configuredType == null) {
return;
}
lines.add(createTranslation(
"item",
"configuration_card.configured",
getConfiguredTypeTranslation(configuredType).withStyle(ChatFormatting.WHITE)
).withStyle(ChatFormatting.GRAY));
}

@Nullable
private BlockEntityType<?> getConfiguredType(final CompoundTag tag) {
final ResourceLocation type = new ResourceLocation(tag.getString(TAG_TYPE));
return BuiltInRegistries.BLOCK_ENTITY_TYPE.get(type);
}

private MutableComponent getConfiguredTypeTranslation(final BlockEntityType<?> type) {
final ResourceLocation typeId = BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(type);
if (typeId == null) {
return Component.empty();
}
return Component.translatable("block." + typeId.getNamespace() + "." + typeId.getPath());
}

@Override
public Optional<TooltipComponent> getTooltipImage(final ItemStack stack) {
return Optional.of(new HelpTooltipComponent(isActive(stack) ? CONFIGURED_HELP : EMPTY_HELP));
}

public boolean isActive(final ItemStack stack) {
return stack.getTag() != null && stack.getTag().contains(TAG_TYPE);
}
}
Loading

0 comments on commit 8330c0d

Please sign in to comment.