Advertisement
JakobM7

PowerPoint.lua

Apr 17th, 2025 (edited)
349
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.15 KB | None | 0 0
  1. -- Script to control get data from a energy Detector in minecraft and output it to a control station over a wireless modem
  2.  
  3. -- This script is designed to be run on a computer in the game Minecraft, using the ComputerCraft mod.
  4. -- AUTHOR: JAKOB MEYER
  5.  
  6. ----------------------
  7. -- GLOBAL VARIABLES --
  8. ----------------------
  9.  
  10.  
  11. local configured = false
  12. local config
  13. local pwr
  14. local modem
  15. local pointName
  16. local energyCubes
  17. local energyStorage
  18. local timeout = 3
  19. local inf = math.huge
  20.  
  21.  
  22.  
  23. --------------------
  24. -- UTIL FUNCTIONS --
  25. --------------------
  26.  
  27. function split(str, sep)
  28.   if sep == nil then
  29.     sep = "%s"
  30.   end
  31.   local t = {}
  32.   for token in string.gmatch(str, "([^" .. sep .. "]+)") do
  33.     table.insert(t, token)
  34.   end
  35.   return t
  36. end
  37.  
  38. function AutodetectMultiple(typelist)
  39.   local peri = {}
  40.   local periCount = 0
  41.   for _, name in ipairs(peripheral.getNames()) do
  42.     local periType = peripheral.getType(name)
  43.  
  44.     local isInList = false
  45.     for _, typ in ipairs(typelist) do
  46.       if periType == typ then
  47.         isInList = true
  48.         break
  49.       end
  50.     end
  51.     print("is in List:" .. tostring(isInList) .. " Name: " .. name .. " Type: " .. periType)
  52.     if isInList then
  53.       periCount = periCount + 1
  54.       peri[periCount] = name
  55.     end
  56.   end
  57.   return peri
  58. end
  59.  
  60. function AutodetectOne(type)
  61.  
  62.   local mult = AutodetectMultiple(type)
  63.   if #mult == 1 then
  64.     return AutodetectMultiple({type})[1]
  65.   end
  66.   if #mult > 1 then
  67.     print("Multiple " .. type .. " found. Please specify one:")
  68.     for i=1, #mult do
  69.       print(i .. ": " .. mult[i])
  70.     end
  71.     local event, key = os.pullEvent("key")
  72.     if key-48 >= 1 and key-48 <= #mult then
  73.       return mult[key-48]
  74.     else
  75.       print("Invalid input.")
  76.       return AutodetectOne(type)
  77.     end
  78.   end
  79.  
  80.   return AutodetectMultiple({type})[1]
  81.  
  82. end
  83.  
  84. ----------------------------
  85. -- CONFIGURATION FUNCTION --
  86. ----------------------------
  87.  
  88.  
  89. function Configure()
  90.   print("starting config program")
  91.  
  92.   -- check if config file exists, ask if user wants to use it or delete it
  93.   if fs.exists("config") then
  94.     print("Config file found. Use it? (y/n), default: y")
  95.     local event, key = os.pullEvent("key")
  96.     if key == keys.n then
  97.       print("deleting config file")
  98.       fs.delete("config")
  99.     end
  100.   end
  101.  
  102.  
  103.   -- create default config file if no config file exists
  104.   if not fs.exists("config") then
  105.     print("creating config file with default values")
  106.     local config = {
  107.       pointName = os.getComputerLabel() or "PLEASE ENTER NAME",
  108.       pwrPos = "",
  109.       modemPos = "",
  110.  
  111.       -- TYPE:
  112.       -- 1: consumer, 10: consumer with Buffer,
  113.       -- 2: producer, 20: producer with Buffer,
  114.       -- 0: storage(In+Out), 3: none
  115.       type = 1,
  116.       priority = 3,
  117.       transferRateLimit = inf,
  118.      
  119.       energyCubes = {},
  120.     }
  121.     local configFile = fs.open("config", "w")
  122.     configFile.write(textutils.serialize(config))
  123.     configFile.close()
  124.   end
  125.  
  126.  
  127.  
  128.  
  129.   local configFile = fs.open("config", "r")
  130.   local configData = textutils.unserialize(configFile.readAll())
  131.   configFile.close()
  132.   print("Config file found. Loading current config data")
  133.  
  134.   -- NAME
  135.   sleep(0.5)
  136.   term.clear()
  137.   term.setCursorPos(1, 1)
  138.   print("Please enter a name for this power Point (" .. configData.pointName .. "):")
  139.   local name = read()
  140.   if name ~= "" then
  141.     configData.pointName = name
  142.   end
  143.  
  144.   -- TYPE
  145.   term.clear()
  146.   term.setCursorPos(1, 1)
  147.   print("Please enter the type of this power point (" .. configData.type .. "):")
  148.   print("1: consumer, 10: consumer with Buffer \n2: producer, 20: producer with Buffer \n0: storage(In+Out), 3: none")
  149.   local type = read()
  150.   if type ~= "" then
  151.     configData.type = tonumber(type)
  152.   end
  153.  
  154.  
  155.   -- PRIORITY
  156.   term.clear()
  157.   term.setCursorPos(1, 1)
  158.   print("Please enter the priority of this power point (" .. configData.priority .. ")")
  159.   print("0: shutdown, \n1: very low, \n2: low, \n3: medium, \n4: high, \n5: very high")
  160.   local priority = read()
  161.   if priority ~= "" then
  162.     configData.priority = tonumber(priority)
  163.   end
  164.  
  165.   --TRANSFER RATE LIMIT
  166.   term.clear()
  167.   term.setCursorPos(1, 1)
  168.   print("Please enter the transfer rate limit of this power point (" .. configData.transferRateLimit .. "):")
  169.   local transferRateLimit = read()
  170.   if transferRateLimit ~= "" then
  171.     configData.transferRateLimit = tonumber(transferRateLimit)
  172.   end
  173.  
  174.  
  175.   -- AUTOMATIC DETECTION
  176.   term.clear()
  177.   term.setCursorPos(1, 1)
  178.   print("Do you want to use auto detect for the peripheral? (y/n) (default: y)")
  179.   local event, key = os.pullEvent("key")
  180.   if key == keys.n then
  181.  
  182.       -- MANUAL
  183.  
  184.       -- ENERGY DETECTOR POSITION
  185.     term.clear()
  186.     term.setCursorPos(1, 1)
  187.     print("Please enter the position/side of the energy detector (" .. configData.pwrPos .. "):")
  188.     local pwrPos = read()
  189.     if pwrPos ~= "" then
  190.       configData.pwrPos = pwrPos
  191.     end
  192.  
  193.  
  194.     -- MODEM POSITION
  195.     term.clear()
  196.     term.setCursorPos(1, 1)
  197.     print("Please enter the position/side of the modem (" .. configData.modemPos .. "):")
  198.     local modemPos = read()
  199.     if modemPos ~= "" then
  200.       configData.modemPos = modemPos
  201.     end
  202.  
  203.  
  204.     -- ENERGY CUBES
  205.     term.clear()
  206.     term.setCursorPos(1, 1)
  207.     print("Please enter the names/titles of the energy cubes. Seperate with spaces \n(default: autodetect):")
  208.     local energyCubePos = read()
  209.     if energyCubePos ~= "" then
  210.       configData.energyCubes = split(energyCubePos, " ")
  211.     else
  212.       local typelist = {"energyCube", "basicEnergyCube", "advancedEnergyCube", "eliteEnergyCube", "ultimateEnergyCube", "creativeEnergyCube"}
  213.       local periList = AutodetectMultiple(typelist)
  214.       configData.energyCubes = periList
  215.     end
  216.      
  217.   else
  218.  
  219.     -- AUTOMATIC
  220.    
  221.     -- Energy Detector
  222.     local pwrPos = AutodetectOne("energyDetector")
  223.     if pwrPos then
  224.       configData.pwrPos = pwrPos
  225.     else
  226.       print("No energy detector found")
  227.       sleep(5)
  228.     end
  229.  
  230.     -- Modem
  231.     local modemPos = AutodetectOne("modem")
  232.     if modemPos then
  233.       configData.modemPos = modemPos
  234.     else
  235.       print("No modem found")
  236.       sleep(5)
  237.     end
  238.     -- Energy Cubes
  239.     local typelist = {"energyCube", "basicEnergyCube", "advancedEnergyCube", "eliteEnergyCube", "ultimateEnergyCube", "creativeEnergyCube"}
  240.     local periList = AutodetectMultiple(typelist)
  241.     configData.energyCubes = periList
  242.   end
  243.  
  244.   -- summary of the config
  245.   term.clear()
  246.   term.setCursorPos(1, 1)
  247.   print("Summary of the config:")
  248.   print("Name: " .. configData.pointName)
  249.   print("Type: " .. configData.type)
  250.   print("Priority: " .. configData.priority)
  251.   print("Transfer Rate Limit: " .. configData.transferRateLimit)
  252.   print("Energy Detector Position: " .. configData.pwrPos)
  253.   print("Modem Position: " .. configData.modemPos)
  254.   print("Energy Cubes: " .. table.concat(configData.energyCubes, ", "))
  255.   print("Do you want to save the config? (y/n) (default: y)")
  256.   local event, key = os.pullEvent("key")
  257.   if key == keys.n then
  258.     print("Config not saved")
  259.     Configure()
  260.     return
  261.   else
  262.     -- save config file
  263.     local configFile = fs.open("config", "w")
  264.     configFile.write(textutils.serialize(configData))
  265.     configFile.close()
  266.     print("Config saved")
  267.   end
  268.   configured = true
  269. end
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279. -----------------------
  280. -- RUNTIME FUNCTIONS --
  281. -----------------------
  282.  
  283.  
  284. function setLimit(limit)
  285.     pwr.setTransferRateLimit(limit)
  286. end
  287.  
  288. function checkTransferRate()
  289.     local currentRate = pwr.getTransferRate()
  290.     return currentRate
  291. end
  292.  
  293. function checkTransferRateLimit()
  294.     local currentLimit = pwr.getTransferRateLimit()
  295.     return currentLimit
  296. end
  297.  
  298. function getEnergy()
  299.   if energyStorage then
  300.     local energyJoules = 0
  301.     for i=1, #energyCubes do
  302.       energyJoules = energyJoules + energyCubes[i].getEnergy()
  303.     end
  304.       return energyJoules * 0.4
  305.   else
  306.       return 0
  307.   end
  308. end
  309.  
  310. function getMaxEnergy()
  311.     if energyStorage then
  312.      
  313.       local maxEnergyJoules = 0
  314.       for i=1, #energyCubes do
  315.         maxEnergyJoules = maxEnergyJoules + energyCubes[i].getMaxEnergy()
  316.       end
  317.         return maxEnergyJoules * 0.4
  318.     else
  319.         return 0
  320.     end
  321. end
  322.  
  323.  
  324.  
  325. -------------------------
  326. -- DEVICE REGISTRATION --
  327. -------------------------
  328.  
  329.  
  330.  
  331.  
  332. function registerPoint()
  333.   local deviceName = config.pointName
  334.   local pointType = config.type
  335.   local rate = checkTransferRate()
  336.   local limit = checkTransferRateLimit()
  337.   local priority = config.priority
  338.   local storageAmount = getEnergy()
  339.   local maxStorageAmount = getMaxEnergy()
  340.  
  341.   modem.transmit(101, 100, {"registerPoint", deviceName = deviceName, type=pointType, rate=rate, limit=limit, priority=priority,storageAmount=storageAmount, maxStorageAmount=maxStorageAmount})
  342.   print("Sending registration: " .. deviceName .. " with type: " .. pointType .. " rate: " .. rate .. " limit: " .. limit .. " priority: " .. priority .. "storageAmount: " .. storageAmount .. " maxStorageAmount: " .. maxStorageAmount)
  343.  
  344.   local timer = os.startTimer(timeout) -- wait for 5 seconds for the confirmation
  345.   local registered = false
  346.   local timeoutet = false
  347.   repeat
  348.     local event, side, channel, replyChannel, message = os.pullEvent()
  349.     if event == "modem_message" then
  350.       if channel == 100 and type(message) and message[1] == "registered" then
  351.  
  352.         os.cancelTimer(timer)
  353.         timer = os.startTimer(timeout)
  354.  
  355.         if message[2] == config.pointName and message[3] == config.type and message[4] == config.priority then
  356.           print("Received register confirmation: " .. message[2])
  357.           registered = true
  358.         else
  359.           modem.transmit(101, 100, {"registerPoint", deviceName = deviceName, type=pointType, rate=rate, limit=limit, priority=priority,storageAmount=storageAmount, maxStorageAmount=maxStorageAmount})
  360.           print("Resending registration: " .. deviceName .. " with type: " .. pointType .. " rate: " .. rate .. " limit: " .. limit .. " priority: " .. priority .. "storageAmount: " .. storageAmount .. " maxStorageAmount: " .. maxStorageAmount)
  361.         end
  362.       end
  363.     elseif event == "timer" then
  364.       print("Timeout waiting for register confirmation")
  365.       timeoutet = true
  366.     end
  367.    
  368.   until registered == true or timeoutet == true
  369. end
  370.  
  371.  
  372.  
  373.  
  374.  
  375. ------------------
  376. -- STARTUP CODE --
  377. ------------------
  378.  
  379.  
  380.  
  381. if fs.exists("config") then
  382.   local configFile = fs.open("config", "r")
  383.   config = textutils.unserialize(configFile.readAll())
  384.   configFile.close()
  385. else
  386.   print("Config file not found")
  387.   Configure()
  388. end
  389.  
  390.  
  391. local configFile = fs.open("config", "r")
  392. config = textutils.unserialize(configFile.readAll())
  393. configFile.close()
  394.  
  395. pwr = peripheral.wrap(config.pwrPos)
  396. modem = peripheral.wrap(config.modemPos)
  397. pointName = config.pointName
  398. energyCubes = {}
  399. energyStorage = false
  400. if config.energyCubes ~= {} then
  401.   energyStorage = true
  402.   for i= 1, #config.energyCubes do
  403.     energyCubes[i] = peripheral.wrap(config.energyCubes[i])
  404.   end
  405. end
  406.  
  407.  
  408.  
  409.  
  410. modem.open(537) -- channel for sending data to control station
  411. modem.open(538) --channel for receiving commadns
  412. modem.open(100) -- listen for register command from control station
  413. modem.open(101) -- Answer to register command from control station
  414.  
  415.  
  416.  
  417.  
  418. ------------------
  419. -- RUNTIME LOOP --
  420. ------------------
  421.  
  422.  
  423.  
  424.  
  425. --Exptected message format:
  426. -- {pointName, "getTransferRate"}
  427. -- {pointName, "getTransferRateLimit"}
  428. -- {pointName, "setLimit", limit}
  429. -- {pointName, "getEnergy"}
  430. -- {pointName, "getMaxEnergy"}
  431.  
  432. while true do
  433.     -- check for messages from the control station
  434.     local event, side, channel, replyChannel, message = os.pullEvent("modem_message")
  435.  
  436.     if channel == 538 and type(message) and message[1] == pointName then
  437.  
  438.       --getTransferRate
  439.       if message[2] == "getTransferRate"  then
  440.         local currentRate = checkTransferRate()
  441.         modem.transmit(537, 0, {pointName, currentRate})
  442.         print("Sending transfer rate: " .. currentRate)
  443.  
  444.       --getTransferRateLimit
  445.       elseif message[2] == "getTransferRateLimit"  then
  446.         local currentLimit = checkTransferRateLimit()
  447.         modem.transmit(537, 0, {pointName, currentLimit})
  448.         print("Sending transfer rate limit: " .. currentLimit)
  449.  
  450.       --setLimit
  451.       elseif message[2] == "setLimit"  then
  452.         local limit = tonumber(message[3])
  453.         if limit then
  454.           setLimit(limit)
  455.           modem.transmit(537, 0, {pointName, limit})
  456.         else
  457.           modem.transmit(537, 0, {pointName, "400"})
  458.         end
  459.  
  460.       --getEnergy
  461.       elseif message[2] == "getEnergy" then
  462.         local energy = getEnergy()
  463.         modem.transmit(537, 0, {pointName, energy})
  464.         print("Sending current energy storage: " .. energy)
  465.  
  466.       elseif message[2] == "getMaxEnergy" then
  467.         local maxEnergy = getMaxEnergy()
  468.         modem.transmit(537, 0, {pointName, maxEnergy})
  469.         print("Sending max energy storage: " .. maxEnergy)
  470.      
  471.       end
  472.  
  473.     elseif channel == 100 and type(message) and message[1] == "registerPoints" and message[2] =="ALL" then
  474.       -- register all points
  475.       print("ControlStation requested registering all points")
  476.       registerPoint()
  477.     end
  478.  
  479. end
  480.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement