Files
computer-craft-AEspatial/main.lua
2025-11-16 18:57:58 +08:00

435 lines
13 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- ME空间原件控制器
-- 功能: 管理ME空间原件的存储和切换
--printUtf8 = load(http.get("https://git.liulikeji.cn/xingluo/ComputerCraft-Utf8/raw/branch/main/utf8ptrint.lua").readAll())()
--function print(a)
-- printUtf8(a,colors.white,colors.lightGray)
--end
-- 全局变量
CONFIG_FILE = "disk_cfg"
CHECK_INTERVAL = 2 -- 检测间隔(秒)
REDSTONE_PULSE_INTERVAL = 0.1 -- 红石脉冲间隔(秒)
MAX_WAIT_CYCLES = 30 -- 最大等待循环次数
peripherals = nil
config = nil
-- 初始化外围设备
local function initPeripherals()
-- 左侧: 红网网卡
local left = peripheral.getType("left")
if left ~= "modem" then
error("左侧没有找到红网网卡!")
end
-- 从配置读取监听端口
local listenPort = config.rednet_ports and config.rednet_ports.listen or 101
peripheral.wrap("left").open(listenPort) -- 打开监听端口
-- 右侧: 扬声器
local right = peripheral.getType("right")
if right ~= "speaker" then
print("警告: 右侧没有找到扬声器")
end
-- 前方: 空间IO端口
local front = peripheral.getType("front")
if front ~= "ae2:spatial_io_port" then
error("前方没有找到空间IO端口!")
end
return {
modem = peripheral.wrap("left"),
speaker = peripheral.wrap("right"),
spatial_io = peripheral.wrap("front")
}
end
-- 读取配置文件
local function readConfig()
if not fs.exists(CONFIG_FILE) then
-- 创建默认配置文件
local defaultConfig = {
current_disk = nil,
current_slot = nil,
disks = {}, -- 格式: {["显示名称"] = 槽位编号}
rednet_ports = {
listen = 101, -- 监听端口
status = 100, -- 状态发送端口
response = 102 -- 响应发送端口
}
}
local file = fs.open(CONFIG_FILE, "w")
file.write(textutils.serialize(defaultConfig))
file.close()
print("已创建默认配置文件,请手动编辑 " .. CONFIG_FILE .. " 配置原件映射")
return defaultConfig
end
local file = fs.open(CONFIG_FILE, "r")
local content = file.readAll()
file.close()
local loadedConfig = textutils.unserialize(content) or {
current_disk = nil,
current_slot = nil,
disks = {}
}
-- 确保端口配置存在
if not loadedConfig.rednet_ports then
loadedConfig.rednet_ports = {
listen = 101,
status = 100,
response = 102
}
else
-- 设置默认值
loadedConfig.rednet_ports.listen = loadedConfig.rednet_ports.listen or 101
loadedConfig.rednet_ports.status = loadedConfig.rednet_ports.status or 100
loadedConfig.rednet_ports.response = loadedConfig.rednet_ports.response or 102
end
return loadedConfig
end
-- 写入配置文件
-- 写入配置文件
local function writeConfig()
-- 创建按槽位排序的disks表
local sortedDisks = {}
-- 先将disks转换为数组形式进行排序
local tempArray = {}
for name, slot in pairs(config.disks) do
table.insert(tempArray, {name = name, slot = slot})
end
-- 按槽位排序
table.sort(tempArray, function(a, b)
return a.slot < b.slot
end)
-- 重新构建有序的disks表
for _, item in ipairs(tempArray) do
sortedDisks[item.name] = item.slot
end
-- 创建临时配置使用排序后的disks
local configToSave = {
rednet_ports = config.rednet_ports,
current_disk = config.current_disk,
current_slot = config.current_slot,
disks = sortedDisks
}
local file = fs.open(CONFIG_FILE, "w")
file.write(textutils.serialize(configToSave))
file.close()
end
-- 播放声音提示
local function playSound(soundType)
if peripherals.speaker then
pcall(function()
if soundType == "success" then
peripherals.speaker.playSound("block.note_block.pling", 1.0, 2.0)
elseif soundType == "working" then
for i=1,3 do
peripherals.speaker.playSound("block.note_block.bass", 3, 1)
sleep(1)
end
elseif soundType == "error" then
peripherals.speaker.playSound("block.note_block.bass", 1.0, 0.5)
end
end)
end
end
-- 发送红石脉冲
local function sendRedstonePulse()
redstone.setOutput("front", true)
sleep(0.1)
redstone.setOutput("front", false)
end
-- 发送状态信息到红网
local function sendStatusUpdate()
-- 从配置读取端口
local statusPort = config.rednet_ports.status
local listenPort = config.rednet_ports.listen
-- 通过红网发送状态
peripherals.modem.transmit(statusPort, listenPort, {
type = "status_update",
current_disk = config.current_disk,
disks = config.disks,
timestamp = os.time()
})
print("状态已发送到端口 " .. statusPort .. ": 当前原件=" .. (config.current_disk or ""))
end
-- 检查空间IO端口状态
local function checkSpatialIOState()
local slots = peripherals.spatial_io.list()
local state = {
slot1 = slots[1], -- 第一格: 未放出/已收回
slot2 = slots[2] -- 第二格: 已放出
}
return state
end
-- 验证槽位是否有物品
local function validateSlotHasItem(slot)
local item = turtle.getItemDetail(slot)
return item ~= nil
end
-- 收回当前原件
local function retractCurrentDisk()
if not config.current_disk or not config.current_slot then
return true -- 没有当前原件,直接返回成功
end
print("开始收回原件: " .. config.current_disk)
-- 切换到当前原件槽位
turtle.select(config.current_slot)
-- 尝试从空间IO端口拿取
if turtle.suck() then
print("235 原件已取回")
end
-- 将原件放入空间IO端口
if not turtle.drop() then
error("无法放入空间IO端口")
end
print("通过红石信号收回原件...")
local waitCycles = 0
while waitCycles < MAX_WAIT_CYCLES do
-- 发送红石脉冲
sendRedstonePulse()
-- 检查空间IO端口状态
local state = checkSpatialIOState()
if state.slot2 and not state.slot1 then
-- 原件已回到第2格尝试拿取
if turtle.suck() then
print("原件收回成功")
return true
end
end
sleep(REDSTONE_PULSE_INTERVAL)
waitCycles = waitCycles + 1
end
print("收回原件超时!")
return false
end
-- 放出目标原件
local function deployTargetDisk(targetDisk)
local targetSlot = config.disks[targetDisk]
if not targetSlot then
error("未找到原件: " .. targetDisk)
end
-- 验证槽位
if not validateSlotHasItem(targetSlot) then
error("槽位 " .. targetSlot .. " 没有物品,无法放出")
end
print("开始放出原件: " .. targetDisk)
-- 切换到目标槽位
turtle.select(targetSlot)
-- 将原件放入空间IO端口
if not turtle.drop() then
error("无法放入空间IO端口")
end
-- 通过红石信号激活放出
print("通过红石信号放出原件...")
local waitCycles = 0
while waitCycles < MAX_WAIT_CYCLES do
-- 发送红石脉冲
sendRedstonePulse()
-- 检查空间IO端口状态
local state = checkSpatialIOState()
if state.slot2 and not state.slot1 then
-- 原件已移动到第二格,放出成功
print("原件放出成功")
return true
end
sleep(REDSTONE_PULSE_INTERVAL)
waitCycles = waitCycles + 1
end
print("放出原件超时!")
return false
end
-- 切换到指定原件
local function switchToDisk(targetDisk)
print("收到切换命令: " .. targetDisk)
-- 检查是否已经是目标原件
if config.current_disk == targetDisk then
print("已经是目标原件,无需切换")
playSound("success")
return true
end
-- 检查目标原件是否存在
if not config.disks[targetDisk] then
print("错误: 未配置原件 '" .. targetDisk .. "'")
playSound("error")
return false
end
playSound("working")
-- 收回当前原件
if not retractCurrentDisk() then
playSound("error")
return false
end
-- 放出目标原件
if not deployTargetDisk(targetDisk) then
playSound("error")
return false
end
-- 更新配置文件
config.current_disk = targetDisk
config.current_slot = config.disks[targetDisk]
writeConfig()
playSound("success")
print("切换完成: " .. targetDisk)
sendStatusUpdate() -- 发送状态更新
return true
end
-- 处理红网消息
local function handleRednetMessage(message)
local responsePort = config.rednet_ports.response
local listenPort = config.rednet_ports.listen
if message.type == "switch_disk" and message.disk_name then
local success = switchToDisk(message.disk_name)
-- 发送响应
peripherals.modem.transmit(responsePort, listenPort, {
type = "switch_response",
disk_name = message.disk_name,
success = success,
timestamp = os.time()
})
elseif message.type == "status_request" then
-- 发送状态信息
peripherals.modem.transmit(responsePort, listenPort, {
type = "status_response",
current_disk = config.current_disk,
disks = config.disks,
timestamp = os.time()
})
elseif message.type == "reload_config" then
-- 重新加载配置
config = readConfig()
peripherals.modem.transmit(responsePort, listenPort, {
type = "reload_response",
success = true,
timestamp = os.time()
})
print("配置已重新加载")
end
end
-- 主循环 - 状态发送
local function main()
print("ME空间原件控制器启动中...")
print("1 外围设备初始化完成")
print("2 当前原件: " .. (config.current_disk or ""))
print("3 配置的原件: ")
for name, slot in pairs(config.disks) do
print(" " .. name .. " -> 槽位 " .. slot)
end
print("4 红网端口配置: ")
print(" 监听端口: " .. config.rednet_ports.listen)
print(" 状态端口: " .. config.rednet_ports.status)
print(" 响应端口: " .. config.rednet_ports.response)
-- 初始状态发送
sendStatusUpdate()
while true do
sleep(CHECK_INTERVAL)
sendStatusUpdate()
end
end
-- 主循环 - 消息监听
local function main1()
local listenPort = config.rednet_ports.listen
while true do
-- 检查红网消息
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
if channel == listenPort and type(message) == "table" then
handleRednetMessage(message)
end
end
end
-- 初始化检查
if not turtle then
error("这个脚本需要在海龟上运行!")
end
-- 检查配置文件是否存在,如果不存在则创建并提示
if not fs.exists(CONFIG_FILE) then
config = readConfig() -- 这会创建默认配置文件
print("请编辑 " .. CONFIG_FILE .. " 文件配置原件映射,格式如下:")
print("{")
print(' current_disk = "原件A",')
print(' current_slot = 1,')
print(' disks = {')
print(' ["原件A"] = 1,')
print(' ["原件B"] = 2,')
print(' ["原件C"] = 3')
print(" },")
print(' rednet_ports = {')
print(' listen = 101, -- 监听端口')
print(' status = 100, -- 状态发送端口')
print(' response = 102 -- 响应发送端口')
print(" }")
print("}")
print("配置完成后重新启动脚本")
return
end
config = readConfig()
peripherals = initPeripherals()
-- 启动程序
parallel.waitForAny(main, main1)