Advertisement
skypop

ZombieSelector

Sep 20th, 2016
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.26 KB | None | 0 0
  1. --utils
  2. local function output(line,str,_m)
  3.     _m = _m or term
  4.     _m.setCursorPos(1,line)
  5.     _m.clearLine()
  6.     _m.write(str)
  7. end
  8.  
  9. local _floor = math.floor
  10. local function strTime(sec)
  11.     local str,d,h,m,s = "", _floor(sec/86400),_floor(sec/3600)%24,_floor(sec/60)%60,_floor(sec%60)
  12.     if d>0 then str = d>1 and d.." days " or "1 day " end
  13.     if h>0 then str = str..h.."h" end
  14.     if m>0 then str = str..(m>9 and m or "0"..m) end
  15.     if h==0 then str = m>0 and str..":"..(s>9 and s or "0"..s) or s.."s" end
  16.     return str
  17. end
  18.  
  19. --init
  20. local iniFile = "/.settings/ZombieSelector"
  21. if fs.exists(iniFile) then
  22.     settings.load(iniFile)
  23. end
  24. settings.set("shell.allow_disk_startup",false)
  25. settings.save(iniFile)
  26.  
  27. --init redstone
  28. rs.setOutput("top",false) sleep(.05)
  29. if rs.getInput("top") then
  30.     term.setCursorPos(1,1)
  31.     term.clear()
  32.     error("Redstone input on top should be OFF",0)
  33.     return
  34. end
  35.  
  36. --init Cells positions
  37. if not fs.exists("/cell") then
  38.     local fh = fs.open("/cell","w")
  39.     fh.write([[-- <Peripheral name> = { x = <Num>, y = <Num>, z = <Num> }
  40. -- <Peripheral name> Correspond au nom du coputer qui contrôle la cellule
  41. -- x,y,z Correspondent à la position de la cellule
  42. -- s Le signal redstone de 1 à 15 (confirmation)
  43. computer_0 = { x = 0, y = 0, z = 0, s=0 }
  44. ]])
  45.     fh.close()
  46. end
  47. os.loadAPI("/cell")
  48. if not os.loadAPI("/cell") or type(cell.computer_0) ~= "nil" then
  49.     term.setCursorPos(1,1)
  50.     term.clear()
  51.     print("Required: Edit coords in file /cell")
  52.     print("Press Y/N")
  53.     local confirm = false
  54.     while not confirm do
  55.         local e,k = os.pullEvent("key")
  56.         if e=="key" and (k==keys.y or k==keys.n) then
  57.             confirm = true
  58.             if k==keys.n then
  59.                 sleep(.2)
  60.                 error("Terminated",0)
  61.                 return
  62.             else
  63.                 shell.run("edit /cell")
  64.                 sleep(1)
  65.             end
  66.         end
  67.     end
  68. end
  69.  
  70. --init Career wanted list
  71. if not fs.exists("/wanted") then
  72.     local fh = fs.open("/wanted","w")
  73.     fh.write([[--Career wanted list
  74. -- true: wanted
  75. -- false: unwanted
  76. career = {
  77.     ["Brown Robe (Farmer)"] = true,
  78.     ["Farmer"] = true,
  79.     ["Fisherman"] = true,
  80.     ["Shepherd"] = true,
  81.     ["Fletcher"] = true,
  82.      
  83.     ["White Robe (Librarian)"] = true,
  84.     ["Librarian"] = true,
  85.      
  86.     ["Purple Robe (Priest)"] = true,
  87.     ["Cleric"] = true,
  88.      
  89.     ["Black Apron (Blacksmith)"] = true,
  90.     ["Armorer"] = true,
  91.     ["Weapon Smith"] = true,
  92.     ["Tool Smith"] = true,
  93.      
  94.     ["White Apron (butcher)"] = true,
  95.     ["Butcher"] = true,
  96.     ["Leatherworker"] = true,
  97.      
  98.     ["Green Robe (Nitwit 1.11)"] = true,
  99.     ["Nitwit (1.11)"] = true,
  100. }]])
  101.     fh.close()
  102. end
  103. os.loadAPI("/wanted")
  104.  
  105. --init Peripherals
  106. ed = peripheral.find("EntityDetector")
  107. if not ed then
  108.     term.setCursorPos(1,1)
  109.     term.clear()
  110.     error("Network require Entity Detector (peripheral not found)",0)
  111.     return
  112. end
  113. local _getEntityList = ed.getEntityList
  114.  
  115. wi = peripheral.find("WorldInterface")
  116. if not wi then
  117.     term.setCursorPos(1,1)
  118.     term.clear()
  119.     error("Network require World Interface (peripheral not found",0)
  120.     return
  121. end
  122. local _getBlockInfos = wi.getBlockInfos
  123.  
  124. local drive  = peripheral.find("drive")
  125. if not drive then
  126.     term.setCursorPos(1,1)
  127.     term.clear()
  128.     error("Network require a disk drive (peripheral not found)",0)
  129.     return
  130. end
  131. if not drive.isDiskPresent() or not drive.hasData() then
  132.     term.setCursorPos(1,1)
  133.     term.clear()
  134.     error("Disk drive require Floppy Disk",0)
  135.     return
  136. end
  137. local path = "/"..drive.getMountPath().."/startup"
  138. if drive.getDiskLabel()~="ZombieSelector_RS_Pulse" then
  139.     term.setCursorPos(1,1)
  140.     term.clear()
  141.     print("Overwrite Disk ?")
  142.     print("Press Y/N")
  143.     local confirm = false
  144.     while not confirm do
  145.         local e,k = os.pullEvent("key")
  146.         if e=="key" and (k==keys.y or k==keys.n) then
  147.             confirm = true
  148.             if k==keys.n then
  149.                 sleep(.2)
  150.                 error("Terminated",0)
  151.                 return
  152.             else
  153.                 if fs.exists(path) then
  154.                     fs.delete(path)
  155.                 end
  156.                 drive.setDiskLabel("ZombieSelector_RS_Pulse")
  157.             end
  158.         end
  159.     end
  160. end
  161.  
  162. if not fs.exists(path) then
  163.     sleep(.2)
  164.     term.clear()
  165.     term.setCursorPos(1,1)
  166.     print("Input master computer coords :\nX:\nY:\nZ:")
  167.     term.setCursorPos(3,2)
  168.     local _x = read()
  169.     term.setCursorPos(3,3)
  170.     local _y = read()
  171.     term.setCursorPos(3,4)
  172.     local _z = read()
  173.    
  174.     if not (tonumber(_x) and tonumber(_y) and tonumber(_z)) then
  175.         term.setCursorPos(1,5)
  176.         error("Invalid coords values",0)
  177.         return
  178.     end
  179.     _x,_y,_z = tonumber(_x), tonumber(_y), tonumber(_z)
  180.     local master = _getBlockInfos(_x,_y,_z)
  181.     if not (master
  182.         and master.blockName == "computercraft:CC-Computer"
  183.         and master.datatags.label
  184.         and master.datatags.label == os.getComputerLabel()
  185.     ) then
  186.         term.setCursorPos(1,5)
  187.         error(string.format("Master computer is not on this coords (%s)",master.blockName),0)
  188.         return
  189.     end
  190.  
  191.     local fh = fs.open("/disk/startup","w")
  192.     fh.write(string.format([[local wi = peripheral.find("WorldInterface")
  193. --Coords: Redstone lamp on top of master computer
  194. local lamp = _getBlockInfos(%d,%d,%d)
  195. if lamp.blockName=="minecraft:lit_redstone_lamp"
  196. and lamp.isPowered then
  197.     shell.run("rs pulse top 1 1.6")
  198. end
  199. os.shutdown()
  200. ]],_x, _y+1 ,_z))
  201.     fh.close()
  202. end
  203.  
  204.  
  205.  
  206. --functions
  207.  
  208. --Villager helper
  209. -- profession[e.datatags.Profession][e.datatags.Career]
  210. local profession = {
  211.     [0] = {
  212.         [0] = "Brown Robe (Farmer)",
  213.         [1] = "Farmer",
  214.         [2] = "Fisherman",
  215.         [3] = "Shepherd",
  216.         [4] = "Fletcher",
  217.     },
  218.     [1] = {
  219.         [0] = "White Robe (Librarian)",
  220.         [1] = "Librarian",
  221.     },
  222.     [2] = {
  223.         [0] = "Purple Robe (Priest)",
  224.         [1] = "Cleric",
  225.     },
  226.     [3] = {
  227.         [0] = "Black Apron (Blacksmith)",
  228.         [1] = "Armorer",
  229.         [2] = "Weapon Smith",
  230.         [3] = "Tool Smith",
  231.     },
  232.     [4] = {
  233.         [0] = "White Apron (butcher)",
  234.         [1] = "Butcher",
  235.         [2] = "Leatherworker",
  236.     },
  237.     [5] = {
  238.         [0] = "Green Robe (Nitwit 1.11)",
  239.         [5] = "Nitwit (1.11)",
  240.     },
  241. }
  242. local function getVillagerCareer(e)
  243.     if e and e.type=="EntityVillager" then
  244.         return profession[e.datatags.Profession][e.datatags.Career]
  245.     else
  246.         return false
  247.     end
  248. end
  249.  
  250. local function getCellInfos(pos,raw)
  251.     raw = raw or false
  252.     local t = _getEntityList(1.5,pos.x+.5,pos.y,pos.z+.5)
  253.     if raw then return #t>=1 and t[1] or false end
  254.    
  255.     if not t or #t==0 then
  256.         return false
  257.     else
  258.         local hasZombie = false
  259.         local hasZombieVillager = false
  260.         local hasVillager = false
  261.         local count,_,mob = 0
  262.         for _,mob in pairs(t) do
  263.             mob.x,mob.z = tonumber(mob.x),tonumber(mob.z)
  264.             if mob.x and mob.z
  265.             and mob.x >= pos.x-.1 and mob.x <= pos.x +1.1
  266.             and mob.z >= pos.z-.1 and mob.z <= pos.z +1.1
  267.             then
  268.                 if mob.type=="EntityZombie" then
  269.                     count = count+1
  270.                     hasZombie = true
  271.                     if mob.datatags.IsVillager then
  272.                         hasZombieVillager = mob.datatags.IsVillager
  273.                     end
  274.                 elseif mob.type=="EntityVillager" then
  275.                     count = count+1
  276.                     hasVillager = true
  277.                 end
  278.             end
  279.         end
  280.         if hasZombie then
  281.             return count, "EntityZombie", hasZombieVillager
  282.         elseif hasVillager then
  283.             return count, "EntityVillager"
  284.         end
  285.     end
  286.     return false
  287. end
  288.  
  289. local function isDoorOpen(pos)
  290.     --y+5
  291.     local data = _getBlockInfos(pos.x,pos.y+5,pos.z)
  292.     if data.blockName == "minecraft:fence_gate"
  293.     or data.blockName == "minecraft:spruce_fence_gate"
  294.     or data.blockName == "minecraft:birch_fence_gate"
  295.     or data.blockName == "minecraft:jungle_fence_gate"
  296.     or data.blockName == "minecraft:dark_oak_fence_gate"
  297.     or data.blockName == "minecraft:acacia_fence_gate" then
  298.         return data.isPowered
  299.     else
  300.         --Structure error
  301.         error(string.format([[Block on coords [%d,%d,%d] should be "minecraft:fence_gate". "%s" found]],
  302.             pos.x, pos.y+5, pos.z, data.blockName),0)
  303.         exit()
  304.     end
  305. end
  306.  
  307. local function resetCell(com,pos)
  308.     rs.setAnalogOutput("top",pos.s)
  309.     local c = peripheral.wrap(com)
  310.     sleep(.1)
  311.     if c.isOn() then c.shutdown() end
  312.     c.turnOn()
  313.     while c.isOn() do
  314.         sleep(.1)
  315.     end
  316.     repeat
  317.         sleep(.1)
  318.     until not c.isOn()
  319.     rs.setOutput("top",false)
  320.     sleep(.1)
  321. end
  322.  
  323. local function select()
  324.     local i,com,pos=0
  325.     for com,pos in pairs(cell) do
  326.         local y = 4+(i*3)
  327.         local dump = false
  328.         output(y,string.format("%s[x:%d, y:%d, z:%d]",com,pos.x,pos.y,pos.z))
  329.         local _entity,_type,_isVillager = getCellInfos(pos)
  330.         if not _entity then
  331.             output(y+1,"Empty cell")
  332.             --Check if need reset
  333.             dump = not isDoorOpen(pos)
  334.         elseif _entity>1 then
  335.             output(y+1,"Too many mobs (".._entity..")")
  336.             dump = true
  337.         elseif _type=="EntityVillager" then
  338.             local _e = getCellInfos(pos,true)
  339.             local career = getVillagerCareer(_e)
  340.             if career then
  341.                 dump = not wanted.career[career]
  342.                 output(y+1,string.format("%sVillager (%s) : %s",
  343.                     (_e.datatags.Career==0 and "New " or ""),
  344.                     career,
  345.                     dump and "unwanted" or "wanted")
  346.                 )
  347.             end
  348.         elseif _type=="EntityZombie" then
  349.             output(y+1,"Zombie, "..( _isVillager and "villager" or "not villager"))
  350.             dump = not _isVillager
  351.         elseif _type=="EntityPlayerMP" then
  352.             output(y+1,"Player")
  353.             dump = false
  354.         else
  355.             output(y+1,_type)
  356.             dump = true
  357.         end
  358.         output(y+2,string.rep("-",20))
  359.         i=i+1
  360.         if dump then
  361.             resetCell(com,pos)
  362.         end
  363.     end
  364. end
  365.  
  366. --main
  367. term.clear()
  368. local tick = os.startTimer(.1)
  369. while true do
  370.     local e,p,x,y = os.pullEvent()
  371.     local ts = os.clock()
  372.     if e=="timer" and p==tick then
  373.         --header
  374.         output(1,string.format("#%d - %s",
  375.             os.getComputerID(),
  376.             os.getComputerLabel()))
  377.         output(2,"Running: "..strTime(ts))
  378.         output(3,string.rep("-",20))
  379.         if math.floor(ts)%2==0 then
  380.             select()
  381.         end
  382.         tick = os.startTimer(1)
  383.     end
  384. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement