No anvil, no problem

- Clipboards can now be used to manually write to Display Boards and Nixie Tubes
- Clipboards can now be used as Material Checklists in the Schematicannon
- Added Clipboard recipe and clearing recipe
This commit is contained in:
simibubi 2023-03-26 18:01:52 +02:00
parent 9dd5cde745
commit ef07383a74
16 changed files with 320 additions and 50 deletions

View File

@ -567,7 +567,7 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
0f4e5a2fc58580df5b156fdac438ddeb6b57e386 assets/create/lang/en_ud.json
85d790bedbdc65bb6e6377edcc63e7b00455e879 assets/create/lang/en_us.json
2502e2934b3e39763f5619e1522b0b6f98bc26d7 assets/create/lang/en_us.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
@ -2316,6 +2316,8 @@ ba80332510acab3f60f30d8b802ee2d450fd51b9 data/create/advancements/recipes/create
1dea56b4759da676f0edf0878ec834a4129d110b data/create/advancements/recipes/create.base/copper_ladder_from_plates_copper_stonecutting.json
3397bed32684183c2896348e3010f47137e3216d data/create/advancements/recipes/create.base/copycat_panel_from_zinc_ingot_stonecutting.json
3c22b58635d4b1c1e4c4033e43b7b4a74b1af186 data/create/advancements/recipes/create.base/copycat_step_from_zinc_ingot_stonecutting.json
3194b8da04cfb26f070b0a14f210f0117f252993 data/create/advancements/recipes/create.base/crafting/appliances/clipboard.json
a1746099602e91fd23fba112016d41c71f9de62e data/create/advancements/recipes/create.base/crafting/appliances/clipboard_clear.json
376bda381f3dedb52b03eb1504b103d8ddd1b672 data/create/advancements/recipes/create.base/crafting/appliances/copper_backtank.json
9833d16405f8c51646590e98588fb410f96d9523 data/create/advancements/recipes/create.base/crafting/appliances/copper_diving_boots.json
680c982dd1d3c45bed4d390fc0da5042750c157a data/create/advancements/recipes/create.base/crafting/appliances/copper_diving_helmet.json
@ -4004,6 +4006,8 @@ bea832822e0e5f0048eb94649641ea541e11f943 data/create/recipes/copper_shingles_fro
10fdc13f5b2b745e13e6e4e949a07ceaf4544a26 data/create/recipes/copper_tiles_from_plates_copper_stonecutting.json
89aed29928cdfa7cdde43d4a51fc4387497ddde0 data/create/recipes/copycat_panel_from_zinc_ingot_stonecutting.json
c06a4519139a33250c01297b532ba6ac7d76284c data/create/recipes/copycat_step_from_zinc_ingot_stonecutting.json
005f8ad32598ea98314031e66b06e95e1f8ddd13 data/create/recipes/crafting/appliances/clipboard.json
db648fd89bc2030f3e1e9baa0d2b5b69238dec4c data/create/recipes/crafting/appliances/clipboard_clear.json
eb18d5972484418fa5a768633e68688ad20d2bd7 data/create/recipes/crafting/appliances/copper_backtank.json
5771562086710eb5a3a05d464989d2f23d6c5e86 data/create/recipes/crafting/appliances/copper_diving_boots.json
ec38ddb44e4bf8eaaba6f9d27e8469234fc98528 data/create/recipes/crafting/appliances/copper_diving_helmet.json

View File

@ -1212,7 +1212,7 @@
"create.gui.schematicannon.option.skipMissing": "Skip missing Blocks",
"create.gui.schematicannon.option.skipBlockEntities": "Protect Block Entities",
"create.gui.schematicannon.slot.gunpowder": "Add gunpowder to fuel the cannon",
"create.gui.schematicannon.slot.listPrinter": "Place books here to print a Checklist for your Schematic",
"create.gui.schematicannon.slot.listPrinter": "Place a Clipboard or Book here to print a Checklist for your Schematic",
"create.gui.schematicannon.slot.schematic": "Add your Schematic here. Make sure it is deployed at a specific location.",
"create.gui.schematicannon.option.skipMissing.description": "If the cannon cannot find a required Block for placement, it will continue at the next Location.",
"create.gui.schematicannon.option.skipBlockEntities.description": "The cannon will avoid replacing data holding blocks such as Chests.",

View File

@ -0,0 +1,34 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"create:crafting/appliances/clipboard"
]
},
"criteria": {
"has_item": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"create:andesite_alloy"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "create:crafting/appliances/clipboard"
}
}
},
"requirements": [
[
"has_item",
"has_the_recipe"
]
]
}

View File

@ -0,0 +1,34 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"create:crafting/appliances/clipboard_clear"
]
},
"criteria": {
"has_item": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": [
"create:clipboard"
]
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "create:crafting/appliances/clipboard_clear"
}
}
},
"requirements": [
[
"has_item",
"has_the_recipe"
]
]
}

View File

@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"A",
"P",
"G"
],
"key": {
"G": {
"tag": "minecraft:planks"
},
"P": {
"item": "minecraft:paper"
},
"A": {
"item": "create:andesite_alloy"
}
},
"result": {
"item": "create:clipboard"
}
}

View File

@ -0,0 +1,11 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"item": "create:clipboard"
}
],
"result": {
"item": "create:clipboard"
}
}

View File

@ -13,12 +13,19 @@ import net.minecraft.world.item.ItemStack;
public class ClipboardEntry {
boolean checked;
MutableComponent text;
public boolean checked;
public MutableComponent text;
public ItemStack icon;
public ClipboardEntry(boolean checked, MutableComponent text) {
this.checked = checked;
this.text = text;
this.icon = ItemStack.EMPTY;
}
public ClipboardEntry displayItem(ItemStack icon) {
this.icon = icon;
return this;
}
public static List<List<ClipboardEntry>> readAll(ItemStack clipboardItem) {
@ -29,6 +36,17 @@ public class ClipboardEntry {
.readCompoundList(pageTag.getList("Entries", Tag.TAG_COMPOUND), ClipboardEntry::readNBT));
}
public static List<ClipboardEntry> getLastViewedEntries(ItemStack heldItem) {
List<List<ClipboardEntry>> pages = ClipboardEntry.readAll(heldItem);
if (pages.isEmpty())
return new ArrayList<>();
int page = heldItem.getTag() == null ? 0
: Math.min(heldItem.getTag()
.getInt("PreviouslyOpenedPage"), pages.size() - 1);
List<ClipboardEntry> entries = pages.get(page);
return entries;
}
public static void saveAll(List<List<ClipboardEntry>> entries, ItemStack clipboardItem) {
CompoundTag tag = clipboardItem.getOrCreateTag();
tag.put("Pages", NBTHelper.writeCompoundList(entries, list -> {
@ -42,11 +60,18 @@ public class ClipboardEntry {
CompoundTag nbt = new CompoundTag();
nbt.putBoolean("Checked", checked);
nbt.putString("Text", Component.Serializer.toJson(text));
if (icon.isEmpty())
return nbt;
nbt.put("Icon", icon.serializeNBT());
return nbt;
}
public static ClipboardEntry readNBT(CompoundTag tag) {
return new ClipboardEntry(tag.getBoolean("Checked"), Component.Serializer.fromJson(tag.getString("Text")));
ClipboardEntry clipboardEntry =
new ClipboardEntry(tag.getBoolean("Checked"), Component.Serializer.fromJson(tag.getString("Text")));
if (tag.contains("Icon"))
clipboardEntry.displayItem(ItemStack.of(tag.getCompound("Icon")));
return clipboardEntry;
}
}

View File

@ -64,6 +64,7 @@ public class ClipboardScreen extends AbstractSimiScreen {
int hoveredEntry;
boolean hoveredCheck;
boolean readonly;
DisplayCache displayCache = DisplayCache.EMPTY;
TextFieldHelper editContext;
@ -91,6 +92,10 @@ public class ClipboardScreen extends AbstractSimiScreen {
editContext = new TextFieldHelper(this::getCurrentEntryText, this::setCurrentEntryText, this::getClipboard,
this::setClipboard, this::validateTextForEntry);
editingIndex = startEmpty ? 0 : -1;
readonly = item.getTag() != null && item.getTag()
.getBoolean("Readonly");
if (readonly)
editingIndex = -1;
}
@Override
@ -122,7 +127,7 @@ public class ClipboardScreen extends AbstractSimiScreen {
addRenderableWidget(forward);
addRenderableWidget(backward);
forward.visible = currentPage < 50;
forward.visible = currentPage < 50 && (!readonly || currentPage + 1 < pages.size());
backward.visible = currentPage > 0;
}
@ -153,7 +158,8 @@ public class ClipboardScreen extends AbstractSimiScreen {
for (int i = 0; i < currentEntries.size(); i++) {
ClipboardEntry clipboardEntry = currentEntries.get(i);
String text = clipboardEntry.text.getString();
totalHeight += Math.max(12, font.split(Components.literal(text), 150)
totalHeight +=
Math.max(12, font.split(Components.literal(text), clipboardEntry.icon.isEmpty() ? 150 : 130)
.size() * 9 + 3);
if (totalHeight > my) {
@ -211,17 +217,24 @@ public class ClipboardScreen extends AbstractSimiScreen {
if (currentPage == previously)
return;
editingIndex = -1;
if (pages.size() <= currentPage)
if (pages.size() <= currentPage) {
if (readonly) {
currentPage = previously;
return;
}
pages.add(new ArrayList<>());
}
currentEntries = pages.get(currentPage);
if (currentEntries.isEmpty()) {
currentEntries.add(new ClipboardEntry(false, Components.empty()));
if (!readonly) {
editingIndex = 0;
editContext.setCursorToEnd();
clearDisplayCacheAfterChange();
}
}
forward.visible = currentPage < 50;
forward.visible = currentPage < 50 && (!readonly || currentPage + 1 < pages.size());
backward.visible = currentPage > 0;
if (next)
@ -245,20 +258,24 @@ public class ClipboardScreen extends AbstractSimiScreen {
for (int i = 0; i < currentEntries.size(); i++) {
ClipboardEntry clipboardEntry = currentEntries.get(i);
boolean checked = clipboardEntry.checked;
int iconOffset = clipboardEntry.icon.isEmpty() ? 0 : 16;
font.draw(ms, "\u25A1", x + 45, y + 51, checked ? 0x668D7F6B : 0xff8D7F6B);
if (checked)
font.draw(ms, "\u2714", x + 45, y + 50, 0x31B25D);
List<FormattedCharSequence> split = font.split(clipboardEntry.text, 150);
List<FormattedCharSequence> split = font.split(clipboardEntry.text, 150 - iconOffset);
if (split.isEmpty()) {
y += 12;
continue;
}
if (!clipboardEntry.icon.isEmpty())
itemRenderer.renderGuiItem(clipboardEntry.icon, x + 54, y + 50);
for (FormattedCharSequence sequence : split) {
if (i != editingIndex)
font.draw(ms, sequence, x + 58, y + 50, checked ? 0x31B25D : 0x311A00);
font.draw(ms, sequence, x + 58 + iconOffset, y + 50, checked ? 0x31B25D : 0x311A00);
y += 9;
}
y += 3;
@ -525,7 +542,7 @@ public class ClipboardScreen extends AbstractSimiScreen {
return true;
}
if (hoveredEntry != editingIndex) {
if (hoveredEntry != editingIndex && !readonly) {
editingIndex = hoveredEntry;
if (hoveredEntry >= currentEntries.size()) {
currentEntries.add(new ClipboardEntry(false, Components.empty()));

View File

@ -1,11 +0,0 @@
package com.simibubi.create.content.curiosities.clipboard;
import net.minecraft.SharedConstants;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.BookEditScreen;
public class ClipboardScreenHelper {
}

View File

@ -2,13 +2,16 @@ package com.simibubi.create.content.logistics.block.redstone;
import static net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED;
import java.util.List;
import java.util.Random;
import java.util.function.BiConsumer;
import com.simibubi.create.AllBlockEntityTypes;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.content.curiosities.clipboard.ClipboardEntry;
import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement;
import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
@ -19,6 +22,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
@ -76,20 +80,31 @@ public class NixieTubeBlock extends DoubleFaceAttachedBlock
return InteractionResult.SUCCESS;
}
boolean display = heldItem.getItem() == Items.NAME_TAG && heldItem.hasCustomHoverName();
boolean display =
heldItem.getItem() == Items.NAME_TAG && heldItem.hasCustomHoverName() || AllItems.CLIPBOARD.isIn(heldItem);
DyeColor dye = DyeColor.getColor(heldItem);
if (!display && dye == null)
return InteractionResult.PASS;
if (world.isClientSide)
return InteractionResult.SUCCESS;
CompoundTag tag = heldItem.getTagElement("display");
String tagElement = tag != null && tag.contains("Name", Tag.TAG_STRING) ? tag.getString("Name") : null;
if (AllItems.CLIPBOARD.isIn(heldItem)) {
List<ClipboardEntry> entries = ClipboardEntry.getLastViewedEntries(heldItem);
for (int i = 0; i < entries.size();) {
tagElement = Component.Serializer.toJson(entries.get(i).text);
break;
}
}
if (world.isClientSide)
return InteractionResult.SUCCESS;
String tagUsed = tagElement;
walkNixies(world, pos, (currentPos, rowPosition) -> {
if (display)
withBlockEntityDo(world, currentPos, be -> be.displayCustomText(tagElement, rowPosition));
withBlockEntityDo(world, currentPos, be -> be.displayCustomText(tagUsed, rowPosition));
if (dye != null)
world.setBlockAndUpdate(currentPos, withColor(state, dye));
});

View File

@ -8,12 +8,15 @@ import java.util.function.Predicate;
import com.simibubi.create.AllBlockEntityTypes;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.content.contraptions.base.KineticBlockEntity;
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.content.curiosities.clipboard.ClipboardEntry;
import com.simibubi.create.foundation.block.IBE;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
@ -27,6 +30,7 @@ import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
@ -158,7 +162,8 @@ public class FlapDisplayBlock extends HorizontalKineticBlock
return InteractionResult.SUCCESS;
}
boolean display = heldItem.getItem() == Items.NAME_TAG && heldItem.hasCustomHoverName();
boolean display =
heldItem.getItem() == Items.NAME_TAG && heldItem.hasCustomHoverName() || AllItems.CLIPBOARD.isIn(heldItem);
DyeColor dye = DyeColor.getColor(heldItem);
if (!display && dye == null)
@ -171,8 +176,20 @@ public class FlapDisplayBlock extends HorizontalKineticBlock
CompoundTag tag = heldItem.getTagElement("display");
String tagElement = tag != null && tag.contains("Name", Tag.TAG_STRING) ? tag.getString("Name") : null;
if (display)
if (display) {
if (AllItems.CLIPBOARD.isIn(heldItem)) {
List<ClipboardEntry> entries = ClipboardEntry.getLastViewedEntries(heldItem);
int line = lineIndex;
for (int i = 0; i < entries.size(); i++) {
for (String string : entries.get(i).text.getString()
.split("\n"))
flapBE.applyTextManually(line++, Component.Serializer.toJson(Components.literal(string)));
}
return InteractionResult.SUCCESS;
}
flapBE.applyTextManually(lineIndex, tagElement);
}
if (dye != null) {
world.playSound(null, pos, SoundEvents.DYE_USE, SoundSource.BLOCKS, 1.0F, 1.0F);
flapBE.setColour(lineIndex, dye);
@ -315,7 +332,8 @@ public class FlapDisplayBlock extends HorizontalKineticBlock
BlockPos relative = pPos.relative(d);
BlockState adjacent = pLevel.getBlockState(relative);
if (canConnect(pState, adjacent))
KineticBlockEntity.switchToBlockState(pLevel, relative, updateColumn(pLevel, relative, adjacent, false));
KineticBlockEntity.switchToBlockState(pLevel, relative,
updateColumn(pLevel, relative, adjacent, false));
}
}

View File

@ -6,6 +6,10 @@ import java.util.List;
import java.util.Locale;
import com.google.common.collect.Sets;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.curiosities.clipboard.ClipboardEntry;
import com.simibubi.create.content.curiosities.clipboard.ClipboardOverrides;
import com.simibubi.create.content.curiosities.clipboard.ClipboardOverrides.ClipboardType;
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
import com.simibubi.create.foundation.utility.Components;
import com.simibubi.create.foundation.utility.Lang;
@ -27,6 +31,7 @@ import net.minecraft.world.item.Items;
public class MaterialChecklist {
public static final int MAX_ENTRIES_PER_PAGE = 5;
public static final int MAX_ENTRIES_PER_CLIPBOARD_PAGE = 7;
public Object2IntMap<Item> gathered = new Object2IntArrayMap<>();
public Object2IntMap<Item> required = new Object2IntArrayMap<>();
@ -70,7 +75,7 @@ public class MaterialChecklist {
gathered.put(item, stack.getCount());
}
public ItemStack createItem() {
public ItemStack createWrittenBook() {
ItemStack book = new ItemStack(Items.WRITTEN_BOOK);
CompoundTag tag = book.getOrCreateTag();
@ -88,9 +93,11 @@ public class MaterialChecklist {
List<Item> keys = new ArrayList<>(Sets.union(required.keySet(), damageRequired.keySet()));
Collections.sort(keys, (item1, item2) -> {
Locale locale = Locale.ENGLISH;
String name1 = item1.getDescription().getString()
String name1 = item1.getDescription()
.getString()
.toLowerCase(locale);
String name2 = item2.getDescription().getString()
String name2 = item2.getDescription()
.getString()
.toLowerCase(locale);
return name1.compareTo(name2);
});
@ -109,30 +116,33 @@ public class MaterialChecklist {
if (itemsWritten == MAX_ENTRIES_PER_PAGE) {
itemsWritten = 0;
textComponent.append(Components.literal("\n >>>").withStyle(ChatFormatting.BLUE));
textComponent.append(Components.literal("\n >>>")
.withStyle(ChatFormatting.BLUE));
pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent)));
textComponent = Components.empty();
}
itemsWritten++;
textComponent.append(entry(new ItemStack(item), amount, true));
textComponent.append(entry(new ItemStack(item), amount, true, true));
}
for (Item item : completed) {
if (itemsWritten == MAX_ENTRIES_PER_PAGE) {
itemsWritten = 0;
textComponent.append(Components.literal("\n >>>").withStyle(ChatFormatting.DARK_GREEN));
textComponent.append(Components.literal("\n >>>")
.withStyle(ChatFormatting.DARK_GREEN));
pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent)));
textComponent = Components.empty();
}
itemsWritten++;
textComponent.append(entry(new ItemStack(item), getRequiredAmount(item), false));
textComponent.append(entry(new ItemStack(item), getRequiredAmount(item), false, true));
}
pages.add(StringTag.valueOf(Component.Serializer.toJson(textComponent)));
tag.put("pages", pages);
tag.putBoolean("readonly", true);
tag.putString("author", "Schematicannon");
tag.putString("title", ChatFormatting.BLUE + "Material Checklist");
textComponent = Lang.translateDirect("materialChecklist")
@ -145,6 +155,80 @@ public class MaterialChecklist {
return book;
}
public ItemStack createWrittenClipboard() {
ItemStack clipboard = AllItems.CLIPBOARD.asStack();
CompoundTag tag = clipboard.getOrCreateTag();
int itemsWritten = 0;
List<List<ClipboardEntry>> pages = new ArrayList<>();
List<ClipboardEntry> currentPage = new ArrayList<>();
if (blocksNotLoaded) {
currentPage.add(new ClipboardEntry(false, Lang.translateDirect("materialChecklist.blocksNotLoaded")
.withStyle(ChatFormatting.RED)));
}
List<Item> keys = new ArrayList<>(Sets.union(required.keySet(), damageRequired.keySet()));
Collections.sort(keys, (item1, item2) -> {
Locale locale = Locale.ENGLISH;
String name1 = item1.getDescription()
.getString()
.toLowerCase(locale);
String name2 = item2.getDescription()
.getString()
.toLowerCase(locale);
return name1.compareTo(name2);
});
List<Item> completed = new ArrayList<>();
for (Item item : keys) {
int amount = getRequiredAmount(item);
if (gathered.containsKey(item))
amount -= gathered.getInt(item);
if (amount <= 0) {
completed.add(item);
continue;
}
if (itemsWritten == MAX_ENTRIES_PER_CLIPBOARD_PAGE) {
itemsWritten = 0;
currentPage.add(new ClipboardEntry(false, Components.literal(">>>")
.withStyle(ChatFormatting.DARK_GRAY)));
pages.add(currentPage);
currentPage = new ArrayList<>();
}
itemsWritten++;
currentPage.add(new ClipboardEntry(false, entry(new ItemStack(item), amount, true, false))
.displayItem(new ItemStack(item)));
}
for (Item item : completed) {
if (itemsWritten == MAX_ENTRIES_PER_PAGE) {
itemsWritten = 0;
currentPage.add(new ClipboardEntry(true, Components.literal(">>>")
.withStyle(ChatFormatting.DARK_GREEN)));
pages.add(currentPage);
currentPage = new ArrayList<>();
}
itemsWritten++;
currentPage.add(new ClipboardEntry(true, entry(new ItemStack(item), getRequiredAmount(item), false, false))
.displayItem(new ItemStack(item)));
}
pages.add(currentPage);
ClipboardEntry.saveAll(pages, clipboard);
ClipboardOverrides.switchTo(ClipboardType.WRITTEN, clipboard);
clipboard.getOrCreateTagElement("display")
.putString("Name", Component.Serializer.toJson(Lang.translateDirect("materialChecklist")
.setStyle(Style.EMPTY.withItalic(Boolean.FALSE))));
tag.putBoolean("Readonly", true);
clipboard.setTag(tag);
return clipboard;
}
public int getRequiredAmount(Item item) {
int amount = required.getOrDefault(item, 0);
if (damageRequired.containsKey(item))
@ -152,7 +236,7 @@ public class MaterialChecklist {
return amount;
}
private Component entry(ItemStack item, int amount, boolean unfinished) {
private MutableComponent entry(ItemStack item, int amount, boolean unfinished, boolean forBook) {
int stacks = amount / 64;
int remainder = amount % 64;
MutableComponent tc = Components.empty();
@ -160,11 +244,14 @@ public class MaterialChecklist {
.setStyle(Style.EMPTY
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(item)))));
if (!unfinished)
if (!unfinished && forBook)
tc.append(" \u2714");
if (!unfinished || forBook)
tc.withStyle(unfinished ? ChatFormatting.BLUE : ChatFormatting.DARK_GREEN);
return tc.append(Components.literal("\n" + " x" + amount).withStyle(ChatFormatting.BLACK))
.append(Components.literal(" | " + stacks + "\u25A4 +" + remainder + "\n").withStyle(ChatFormatting.GRAY));
return tc.append(Components.literal("\n" + " x" + amount)
.withStyle(ChatFormatting.BLACK))
.append(Components.literal(" | " + stacks + "\u25A4 +" + remainder + (forBook ? "\n" : ""))
.withStyle(ChatFormatting.GRAY));
}
}

View File

@ -700,8 +700,9 @@ public class SchematicannonBlockEntity extends SmartBlockEntity implements MenuP
updateChecklist();
dontUpdateChecklist = true;
inventory.extractItem(BookInput, 1, false);
ItemStack stack = checklist.createItem();
ItemStack extractItem = inventory.extractItem(BookInput, 1, false);
ItemStack stack = AllItems.CLIPBOARD.isIn(extractItem) ? checklist.createWrittenClipboard()
: checklist.createWrittenBook();
stack.setCount(inventory.getStackInSlot(BookOutput)
.getCount() + 1);
inventory.setStackInSlot(BookOutput, stack);

View File

@ -28,7 +28,8 @@ public class SchematicannonInventory extends ItemStackHandler {
case 1: // Blueprint output
return false;
case 2: // Book input
return stack.sameItem(new ItemStack(Items.BOOK)) || stack.sameItem(new ItemStack(Items.WRITTEN_BOOK));
return AllItems.CLIPBOARD.isIn(stack) || stack.sameItem(new ItemStack(Items.BOOK))
|| stack.sameItem(new ItemStack(Items.WRITTEN_BOOK));
case 3: // Material List output
return false;
case 4: // Gunpowder

View File

@ -1011,6 +1011,18 @@ public class StandardRecipeGen extends CreateRecipeProvider {
.viaShapeless(b -> b.requires(I.wheatFlour())
.requires(Items.WATER_BUCKET)),
CLIPBOARD = create(AllItems.CLIPBOARD).unlockedBy(I::andesite)
.viaShaped(b -> b.define('G', I.planks())
.define('P', Items.PAPER)
.define('A', I.andesite())
.pattern("A")
.pattern("P")
.pattern("G")),
CLIPBOARD_CLEAR = create(AllItems.CLIPBOARD).withSuffix("_clear")
.unlockedBy(AllItems.CLIPBOARD::get)
.viaShapeless(b -> b.requires(AllItems.CLIPBOARD.get())),
DIVING_HELMET = create(AllItems.COPPER_DIVING_HELMET).unlockedBy(I::copper)
.viaShaped(b -> b.define('G', Tags.Items.GLASS)
.define('P', I.copper())

View File

@ -357,7 +357,7 @@
"create.gui.schematicannon.option.skipBlockEntities": "Protect Block Entities",
"create.gui.schematicannon.slot.gunpowder": "Add gunpowder to fuel the cannon",
"create.gui.schematicannon.slot.listPrinter": "Place books here to print a Checklist for your Schematic",
"create.gui.schematicannon.slot.listPrinter": "Place a Clipboard or Book here to print a Checklist for your Schematic",
"create.gui.schematicannon.slot.schematic": "Add your Schematic here. Make sure it is deployed at a specific location.",
"create.gui.schematicannon.option.skipMissing.description": "If the cannon cannot find a required Block for placement, it will continue at the next Location.",