Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ public static class Core {
.defaultValue(false)
.build();

public static final ConfigBoolean SELECTION_MATERIALS = bool("selectionMaterials")
.defaultValue(false)
Comment thread
Cjsah marked this conversation as resolved.
.setVisible(isLoadChestTrackerLoaded)
.build();

// 远程交互 - 开关
public static final ConfigBoolean CLOUD_INVENTORY = bool("cloudInventory")
.defaultValue(false)
Expand Down Expand Up @@ -239,6 +244,7 @@ public static class Core {
AUTO_DISABLE_PRINTER,
UPDATE_CHECK,
DEBUG_OUTPUT,
SELECTION_MATERIALS,
CLOUD_INVENTORY,
AUTO_INVENTORY,
INVENTORY_LIST,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package me.aleksilassila.litematica.printer.mixin.printer.litematica;

import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import fi.dy.masa.litematica.materials.MaterialListUtils;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import me.aleksilassila.litematica.printer.utils.LitematicaUtils;
import net.minecraft.world.Container;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

//#if MC >= 260000
//$$ import fi.dy.masa.malilib.util.data.ItemType;
//#else
import fi.dy.masa.malilib.util.ItemType;
//#endif

@Mixin(MaterialListUtils.class)
public class MixinMaterialListUtils {
//#if MC == 12111
@SuppressWarnings("deprecation")
//#endif
@WrapOperation(method = "getMaterialList", at = @At(value = "INVOKE", target = "Lfi/dy/masa/litematica/materials/MaterialListUtils;getInventoryItemCounts(Lnet/minecraft/world/Container;)Lit/unimi/dsi/fastutil/objects/Object2IntOpenHashMap;"))
private static Object2IntOpenHashMap<ItemType> initApplySelectionArea(Container inv, Operation<Object2IntOpenHashMap<ItemType>> original) {
Object2IntOpenHashMap<ItemType> result = original.call(inv);
LitematicaUtils.applySelectionArea(result);
return result;
}
//#if MC == 12111
@SuppressWarnings("deprecation")
//#endif
@WrapOperation(method = "updateAvailableCounts", at = @At(value = "INVOKE", target = "Lfi/dy/masa/litematica/materials/MaterialListUtils;getInventoryItemCounts(Lnet/minecraft/world/Container;)Lit/unimi/dsi/fastutil/objects/Object2IntOpenHashMap;"))
private static Object2IntOpenHashMap<ItemType> updateApplySelectionArea(Container inv, Operation<Object2IntOpenHashMap<ItemType>> original) {
Object2IntOpenHashMap<ItemType> result = original.call(inv);
LitematicaUtils.applySelectionArea(result);
return result;
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
package me.aleksilassila.litematica.printer.printer.zxy.chesttracker;

//#if MC >= 12001

import fi.dy.masa.litematica.materials.MaterialListUtils;
import fi.dy.masa.malilib.util.InventoryUtils;
import me.aleksilassila.litematica.printer.I18n;
import me.aleksilassila.litematica.printer.config.Configs;
import me.aleksilassila.litematica.printer.handler.ClientPlayerTickManager;
import me.aleksilassila.litematica.printer.printer.zxy.inventory.OpenInventoryPacket;
import me.aleksilassila.litematica.printer.printer.zxy.utils.ZxyUtils;
import me.aleksilassila.litematica.printer.utils.MessageUtils;
import me.aleksilassila.litematica.printer.printer.PrinterBox;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.BundleItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.ShulkerBoxBlock;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.NotNull;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import red.jackf.chesttracker.api.memory.Memory;
import red.jackf.chesttracker.api.memory.MemoryBank;
import red.jackf.chesttracker.api.memory.MemoryKey;
import red.jackf.chesttracker.api.providers.MemoryBuilder;
import red.jackf.chesttracker.api.providers.ProviderUtils;
import red.jackf.chesttracker.impl.events.AfterPlayerDestroyBlock;
Expand All @@ -34,8 +43,15 @@

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

//#if MC >= 260000
//$$ import fi.dy.masa.malilib.util.data.ItemType;
//#else
import fi.dy.masa.malilib.util.ItemType;
//#endif

public class MemoryUtils {
@NotNull
static Minecraft client = Minecraft.getInstance();
Expand Down Expand Up @@ -69,7 +85,7 @@ public static void setup() {
// 破坏方块后清除打印机库存的该记录
AfterPlayerDestroyBlock.EVENT.register(cbs -> {
if (PRINTER_MEMORY != null
&& PRINTER_MEMORY.getMetadata().getIntegritySettings().removeOnPlayerBlockBreak
&& PRINTER_MEMORY.getMetadata().getIntegritySettings().removeOnPlayerBlockBreak
) {
ProviderUtils.getPlayersCurrentKey().ifPresent(currentKey -> PRINTER_MEMORY.removeMemory(currentKey, cbs.pos()));
}
Expand All @@ -89,13 +105,15 @@ public static void setup() {
//保存打印机库存
ClientPlayConnectionEvents.DISCONNECT.register((handler, client) -> unLoad());
}
public static void saveMemory(AbstractContainerMenu sc){
if(PRINTER_MEMORY != null && ZxyUtils.printerMemoryAdding || ClientPlayerTickManager.PRINT.isPrinterMemorySync())
save(sc , PRINTER_MEMORY);

public static void saveMemory(AbstractContainerMenu sc) {
if (PRINTER_MEMORY != null && ZxyUtils.printerMemoryAdding || ClientPlayerTickManager.PRINT.isPrinterMemorySync())
save(sc, PRINTER_MEMORY);
MemoryBankAccessImpl.INSTANCE.getLoadedInternal().ifPresent(memoryBank -> save(sc, memoryBank));
ClientPlayerTickManager.PRINT.setPrinterMemorySync(false);
}
public static void createPrinterMemory(){

public static void createPrinterMemory() {
Optional<Coordinate> current = Coordinate.getCurrent();
if (current.isPresent()) {
Coordinate coordinate = current.get();
Expand All @@ -110,7 +128,7 @@ public static void createPrinterMemory(){
bank.setId(s1);
return bank;
});
if(printerMetadata != null){
if (printerMetadata != null) {
PRINTER_MEMORY.setMetadata(printerMetadata);
}
// Metadata metadata = PRINTER_MEMORY.getMetadata();
Expand All @@ -136,29 +154,115 @@ public static void save() {
Storage.save(PRINTER_MEMORY);
}

public static void save(AbstractContainerMenu screen , MemoryBank memoryBank) {
if (memoryBank == null || OpenInventoryPacket.key == null || blockState == null || !Configs.Core.CLOUD_INVENTORY.getBooleanValue()) return;
public static void save(AbstractContainerMenu screen, MemoryBank memoryBank) {
if (memoryBank == null || OpenInventoryPacket.key == null || blockState == null || !Configs.Core.CLOUD_INVENTORY.getBooleanValue())
return;
List<BlockPos> connected;
if (ZxyUtils.printerMemoryAdding && client.level != null) {
connected = ConnectedBlocksGrabber.getConnected(client.level, client.level.getBlockState(OpenInventoryPacket.pos), OpenInventoryPacket.pos);
} else connected = null;
List<ItemStack> items;
if (screen !=null)
if (screen != null)
items = screen.slots.stream()
.filter(slot -> !(slot.container instanceof Inventory))
.map(Slot::getItem)
.toList();
.filter(slot -> !(slot.container instanceof Inventory))
.map(Slot::getItem)
.toList();
else return;

Memory memory = MemoryBuilder.create(items)
.inContainer(blockState.getBlock())
.otherPositions(connected != null ? connected.stream()
.filter(pos -> !pos.equals(connected.get(0)))
.toList() : List.of(OpenInventoryPacket.pos)
).build();
.inContainer(blockState.getBlock())
.otherPositions(connected != null ? connected.stream()
.filter(pos -> !pos.equals(connected.get(0)))
.toList() : List.of(OpenInventoryPacket.pos)
).build();
if (memory != null) {
memoryBank.addMemory(OpenInventoryPacket.key.identifier(),OpenInventoryPacket.pos,memory);
memoryBank.addMemory(OpenInventoryPacket.key.identifier(), OpenInventoryPacket.pos, memory);
}
}

//#if MC == 12111
@SuppressWarnings("deprecation")
//#endif
public static void getSelectionContainerItems(List<PrinterBox> boxes, List<Object2IntOpenHashMap<ItemType>> result) {
if (boxes == null || result == null || boxes.isEmpty() || client.level == null) {
return;
}

MemoryBankImpl bank = MemoryBankAccessImpl.INSTANCE.getLoadedInternal().orElse(null);
if (bank == null) {
return;
}

Identifier dimensionKey = client.level.dimension().identifier();
Optional<MemoryKey> optional = bank.getKey(dimensionKey);
if (optional.isEmpty()) {
return;
}
Map<BlockPos, Memory> memories = optional.get().getMemories();

if (memories == null || memories.isEmpty()) {
return;
}

for (PrinterBox box : boxes) {
if (box == null) {
continue;
}

for (BlockPos pos : box) {
Memory memory = memories.get(pos);
if (memory == null) {
continue;
}

result.add(convertChestTrackerItems(memory));
}
}
}

Comment thread
Cjsah marked this conversation as resolved.
//#if MC == 12111
@SuppressWarnings("deprecation")
//#endif
private static Object2IntOpenHashMap<ItemType> convertChestTrackerItems(Memory memory) {
Object2IntOpenHashMap<ItemType> result = new Object2IntOpenHashMap<>();
if (memory == null || memory.items() == null) {
return result;
}

for (ItemStack stack : memory.items()) {
if (stack == null || stack.isEmpty()) {
continue;
}

// From `MaterialListUtils.getInventoryItemCounts#L174-L203`
Item item = stack.getItem();
if (item instanceof BlockItem blockItem &&
blockItem.getBlock() instanceof ShulkerBoxBlock &&
InventoryUtils.shulkerBoxHasItems(stack)
) {
Object2IntOpenHashMap<ItemType> boxCounts = MaterialListUtils.getStoredItemCounts(stack);

for (ItemType boxType : boxCounts.keySet()) {
result.addTo(boxType, boxCounts.getInt(boxType));
}

boxCounts.clear();
//#if MC > 12004
} else if (item instanceof BundleItem && InventoryUtils.bundleHasItems(stack)) {
Object2IntOpenHashMap<ItemType> bundleCounts = MaterialListUtils.getBundleItemCounts(stack);

for (ItemType bundleType : bundleCounts.keySet()) {
result.addTo(bundleType, bundleCounts.getInt(bundleType));
}

bundleCounts.clear();
//#endif
} else {
result.addTo(new ItemType(stack, true, false), stack.getCount());
}
}

return result;
}
}
//#endif
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import fi.dy.masa.litematica.util.EasyPlaceProtocol;
import fi.dy.masa.litematica.util.PlacementHandler;
import fi.dy.masa.litematica.util.WorldUtils;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import me.aleksilassila.litematica.printer.config.Configs;
import me.aleksilassila.litematica.printer.printer.PrinterBox;
import net.fabricmc.api.EnvType;
Expand All @@ -19,15 +21,18 @@

import java.util.*;

//#if MC >= 260000
//$$ import fi.dy.masa.malilib.util.data.ItemType;
//#else
import fi.dy.masa.malilib.util.ItemType;
//#endif
//#if MC < 11900
//$$ import fi.dy.masa.malilib.util.SubChunkPos;
//#endif

@SuppressWarnings({"BooleanMethodIsAlwaysInverted", "BooleanMethodIsAlwaysInverted"})
@Environment(EnvType.CLIENT)
public class LitematicaUtils {
public static final Minecraft client = Minecraft.getInstance();
public static final LitematicaUtils INSTANCE = new LitematicaUtils();

private LitematicaUtils() {
}
Expand Down Expand Up @@ -94,4 +99,58 @@ static boolean comparePos(Box box, BlockPos pos) {
return printerBox.contains(pos);
}

/**
* 获取当前 Litematica 选区内所有容器方块的物品内容。
*/
//#if MC == 12111
@SuppressWarnings("deprecation")
//#endif
public static void applySelectionArea(Object2IntOpenHashMap<ItemType> items) {
if (!Configs.Core.SELECTION_MATERIALS.getBooleanValue()) {
return;
}

AreaSelection selection = DataManager.getSelectionManager().getCurrentSelection();
if (selection == null) {
return;
}

List<PrinterBox> boxes = getSelectionBoxes(selection);
if (boxes.isEmpty()) {
return;
}

//#if MC >= 12001
if (ModUtils.isChestTrackerLoaded()) {
List<Object2IntOpenHashMap<ItemType>> containerItems = new ObjectArrayList<>();
me.aleksilassila.litematica.printer.printer.zxy.chesttracker.MemoryUtils.getSelectionContainerItems(boxes, containerItems);
for (Object2IntOpenHashMap<ItemType> map : containerItems) {
map.forEach(items::addTo);
}
Comment thread
Cjsah marked this conversation as resolved.
}
//#endif

}

private static List<PrinterBox> getSelectionBoxes(AreaSelection selection) {
if (selection == null) {
return Collections.emptyList();
}

if (DataManager.getSelectionManager().getSelectionMode() == SelectionMode.NORMAL) {
return selection.getAllSubRegionBoxes().stream().map(LitematicaUtils::toPrinterBox).toList();
}

Box box = selection.getSubRegionBox(DataManager.getSimpleArea().getName());
PrinterBox printerBox = toPrinterBox(box);
return printerBox != null ? Collections.singletonList(printerBox) : Collections.emptyList();
}

private static PrinterBox toPrinterBox(Box box) {
if (box == null || box.getPos1() == null || box.getPos2() == null) {
return null;
}
return new PrinterBox(box.getPos1(), box.getPos2());
}

}
2 changes: 2 additions & 0 deletions src/main/resources/assets/litematica-printer/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@
"litematica-printer.config.renderHud.desc": "Display current mode and work progress within range on operation page when printer is working;\nIf §6§lLag Detection§r is enabled, will show prompt when lag is excessive.",
"litematica-printer.config.renderLayerLimit": "Render Layer Limit",
"litematica-printer.config.renderLayerLimit.desc": "Limit printer work range to Litematica's currently rendered layer range.",
"litematica-printer.config.selectionMaterials": "Selection Materials",
"litematica-printer.config.selectionMaterials.desc": "In the Material List, also count items stored in containers within the selected area as already available items. (Requires ChestTracker)",
"litematica-printer.config.selectionType.litematica.renderLayer": "Projection Render Layer",
"litematica-printer.config.selectionType.litematica.selection": "Projection Selection",
"litematica-printer.config.selectionType.litematica.selection.abovePlayer": "Projection Selection (Above Player)",
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/assets/litematica-printer/lang/zh_cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@
"litematica-printer.config.renderHud.desc": "打印机工作时,在操作页面显示当前模式和范围内工作进度;\n如果开启了§6§l延迟检测§r,那么会在延迟过大时显示提示。",
"litematica-printer.config.renderLayerLimit": "渲染层数限制",
"litematica-printer.config.renderLayerLimit.desc": "将打印机工作范围限制为Litematica当前渲染的图层范围。",
"litematica-printer.config.selectionMaterials": "选区算作材料列表",
"litematica-printer.config.selectionMaterials.desc": "将选区内容器中的物品算做材料列表中的已有物品。 (需要 ChestTracker)",
"litematica-printer.config.selectionType.litematica.renderLayer": "投影渲染层",
"litematica-printer.config.selectionType.litematica.selection": "投影选区",
"litematica-printer.config.selectionType.litematica.selection.abovePlayer": "投影选区(玩家之上)",
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/litematica-printer.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"printer.litematica.EasyPlaceUtilsAccessor",
"printer.litematica.InventoryUtilsAccessor",
"printer.litematica.MixinInventoryUtils",
"printer.litematica.MixinMaterialListUtils",
"printer.malilib.config.MixinConfigBase",
"printer.malilib.config.MixinIConfigBase",
"printer.mc.MixinBlockItem",
Expand Down