Skip to content

Instantly share code, notes, and snippets.

@EvanHsieh0415
Last active March 29, 2025 01:45
Show Gist options
  • Save EvanHsieh0415/0b317050d40872084d643d2b9777f4cd to your computer and use it in GitHub Desktop.
Save EvanHsieh0415/0b317050d40872084d643d2b9777f4cd to your computer and use it in GitHub Desktop.
【KJS 7 &AE 2】 实现中键从AE中获取光标指向方块 - [KJS]KubeJS https://www.mcmod.cn/post/4954.html
// requires: ae2
(() => {
const { keyPickItem } = Client.options; // 「选取方块」对应的 KeyMapping
ClientEvents.tick((event) => {
let { player } = event;
if (!keyPickItem.isDown()) return;
player.sendData("kubejs.key.pickItem", {});
});
})();
// requires: ae2
(() => {
const $ILinkStatus = Java.loadClass("appeng.api.storage.ILinkStatus");
const $WirelessTerminalItem = Java.loadClass("appeng.items.tools.powered.WirelessTerminalItem");
const $IActionSource = Java.loadClass("appeng.api.networking.security.IActionSource");
const $AEItemKey = Java.loadClass("appeng.api.stacks.AEItemKey");
const $MenuLocators = Java.loadClass("appeng.menu.locator.MenuLocators");
const $StorageHelper = Java.loadClass("appeng.api.storage.StorageHelper");
const $Actionable = Java.loadClass("appeng.api.config.Actionable");
/**
* 判断物品堆是否为无线终端
* @param { $Item_ | $ItemStack_ } item
* @returns { boolean }
*/
function isWirelessTerminal(item) {
return item.item instanceof $WirelessTerminalItem;
}
// 快捷栏(0-8)
const HOTBAR_INDEX = [0, 9];
// 背包剩余槽位(9-35)
const INVENTORY_INDEX = [9, 36];
/**
* 寻找无线终端
* @param { $Player_ } player
* @returns { $ItemStack_ | null }
*/
function findWirelessTerminal(player) {
/** @type {(() => ($ItemStack_|null))[]} */
const checkSlots = [
// 优先检查主手
() => player.mainHandItem,
// 其次检查副手
() => player.offhandItem,
// 检查快捷栏
() => {
for (let slot = HOTBAR_INDEX[0]; slot < HOTBAR_INDEX[1]; slot++) {
let stack = player.inventory.getStackInSlot(slot);
if (isWirelessTerminal(stack)) return stack;
}
return null;
},
// 检查 Curios 饰品栏
() => {
if (!Platform.isModLoaded("powerfuljs")) return null;
const capabilities = Capabilities.entity("curios:item_handler");
if (capabilities === null) return null;
const curios = player.getCapability(capabilities);
if (curios === null) return null;
const index = curios.find(isWirelessTerminal);
if (index != -1) return curios.getStackInSlot(index);
return null;
},
// 检查背包剩余槽位
() => {
for (let slot = INVENTORY_INDEX[0]; slot < INVENTORY_INDEX[1]; slot++) {
let stack = player.inventory.getStackInSlot(slot);
if (isWirelessTerminal(stack)) return stack;
}
return null;
},
];
for (let slotCheck of checkSlots) {
let stack = slotCheck();
if (stack !== null && isWirelessTerminal(stack)) return stack;
}
return null;
}
/**
* 将物品放入离当前选中槽位最近的空快捷栏槽位
* @param { $Player_ } player
* @param { $ItemStack_ } itemStack
* @returns { number } 成功设置的槽位号,找不到返回-1
*/
function setEmptyHandSlot(player, itemStack) {
const selectedSlot = player.selectedSlot;
const slots = [0, 1, 2, 3, 4, 5, 6, 7, 8];
// 按与选中槽位的距离排序:优先当前槽位→左右相邻→逐渐向外扩展
slots.sort((a, b) => {
let distA = Math.abs(a - selectedSlot);
let distB = Math.abs(b - selectedSlot);
// 距离相同则按序号排序
return distA - distB || a - b;
});
const selectedItem = player.inventory.getStackInSlot(selectedSlot);
if (selectedItem.empty) {
player.inventory.setStackInSlot(selectedSlot, itemStack);
return selectedSlot;
}
// 寻找第一个非手持且为空的槽位
for (let slot of slots) {
if (slot === selectedSlot) continue;
let slotItem = player.inventory.getStackInSlot(slot);
if (slotItem.empty) {
player.inventory.setStackInSlot(slot, itemStack);
return slot;
}
}
return -1; // 全满
}
NetworkEvents.dataReceived("kubejs.key.pickItem", (event) => {
const { player } = event;
const keyStats = player.persistentData.getBoolean("kubejs:key_pickItem");
if (keyStats) {
player.persistentData.putBoolean("kubejs:key_pickItem", false);
return;
} else {
player.persistentData.putBoolean("kubejs:key_pickItem", true);
}
const hitResult = player.rayTrace();
if (!hitResult.block) return;
const itemStack = hitResult.block.item;
if (player.inventory.find({ item: itemStack.id }) > -1) return;
const wirelessTerminal = findWirelessTerminal(player);
if (wirelessTerminal == null) return;
/** @type {{ item: $WirelessTerminalItem_ }} */
const { item } = wirelessTerminal;
const menu = item.getMenuHost(player, $MenuLocators.forStack(wirelessTerminal), null);
const linkStatus = menu.getLinkStatus();
// 检查无线终端与ME网络的链接状态
if (linkStatus !== $ILinkStatus.ofConnected()) {
// 若无线终端无法访问链接网络,显示无法访问的原因
player.setStatusMessage(linkStatus.statusDescription());
return;
}
// ME 网络的存储服务
const { inventory } = menu;
const AEItemKey = $AEItemKey["of(net.minecraft.world.item.ItemStack)"](itemStack);
const result = $StorageHelper.poweredExtraction(
menu,
inventory,
AEItemKey,
1,
$IActionSource.ofPlayer(player),
$Actionable.SIMULATE
);
if (result <= 0) return;
const emptySlot = setEmptyHandSlot(player, itemStack);
if (emptySlot == -1) return;
player.selectedSlot = emptySlot;
$StorageHelper.poweredExtraction(
menu,
inventory,
AEItemKey,
1,
$IActionSource.ofPlayer(player),
$Actionable.MODULATE
);
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment