From e1e4ec871bb84b1d818b3a3760c39c892895def4 Mon Sep 17 00:00:00 2001 From: Jack O'Sullivan Date: Mon, 15 Jan 2024 13:14:17 +0000 Subject: [PATCH] Initial commit --- PriorityQueue.lua | 232 ++++++ alarm.lua | 61 ++ danger.dfpwm | Bin 0 -> 37546 bytes datapack/.gitignore | 1 + .../turtle_upgrades/diamond_pickaxe.json | 6 + datapack/pack.mcmeta | 6 + icon/ore-coal.png | Bin 0 -> 623 bytes icon/ore-copper.png | Bin 0 -> 653 bytes icon/ore-diamond.png | Bin 0 -> 625 bytes icon/ore-ds-coal.png | Bin 0 -> 613 bytes icon/ore-ds-copper.png | Bin 0 -> 636 bytes icon/ore-ds-diamond.png | Bin 0 -> 641 bytes icon/ore-ds-emerald.png | Bin 0 -> 636 bytes icon/ore-ds-gold.png | Bin 0 -> 615 bytes icon/ore-ds-iron.png | Bin 0 -> 624 bytes icon/ore-ds-lapis.png | Bin 0 -> 661 bytes icon/ore-ds-redstone.png | Bin 0 -> 715 bytes icon/ore-emerald.png | Bin 0 -> 634 bytes icon/ore-generic.png | Bin 0 -> 12244 bytes icon/ore-gold.png | Bin 0 -> 633 bytes icon/ore-iron.png | Bin 0 -> 615 bytes icon/ore-lapis.png | Bin 0 -> 676 bytes icon/ore-redstone.png | Bin 0 -> 644 bytes icon/turtle.png | Bin 0 -> 8745 bytes mine.lua | 727 ++++++++++++++++++ mineMonitor.lua | 185 +++++ tree.lua | 134 ++++ 27 files changed, 1352 insertions(+) create mode 100644 PriorityQueue.lua create mode 100644 alarm.lua create mode 100644 danger.dfpwm create mode 100644 datapack/.gitignore create mode 100644 datapack/data/minecraft/computercraft/turtle_upgrades/diamond_pickaxe.json create mode 100644 datapack/pack.mcmeta create mode 100644 icon/ore-coal.png create mode 100644 icon/ore-copper.png create mode 100644 icon/ore-diamond.png create mode 100644 icon/ore-ds-coal.png create mode 100644 icon/ore-ds-copper.png create mode 100644 icon/ore-ds-diamond.png create mode 100644 icon/ore-ds-emerald.png create mode 100644 icon/ore-ds-gold.png create mode 100644 icon/ore-ds-iron.png create mode 100644 icon/ore-ds-lapis.png create mode 100644 icon/ore-ds-redstone.png create mode 100644 icon/ore-emerald.png create mode 100644 icon/ore-generic.png create mode 100644 icon/ore-gold.png create mode 100644 icon/ore-iron.png create mode 100644 icon/ore-lapis.png create mode 100644 icon/ore-redstone.png create mode 100644 icon/turtle.png create mode 100644 mine.lua create mode 100644 mineMonitor.lua create mode 100644 tree.lua diff --git a/PriorityQueue.lua b/PriorityQueue.lua new file mode 100644 index 0000000..9d4cb0e --- /dev/null +++ b/PriorityQueue.lua @@ -0,0 +1,232 @@ +--[[ + + PriorityQueue - v1.0.1 - public domain Lua priority queue + implemented with indirect binary heap + no warranty implied; use at your own risk + + based on binaryheap library (github.com/iskolbin/binaryheap) + + author: Ilya Kolbin (iskolbin@gmail.com) + url: github.com/iskolbin/priorityqueue + + See documentation in README file. + + COMPATIBILITY + + Lua 5.1, 5.2, 5.3, LuaJIT 1, 2 + + LICENSE + + This software is dual-licensed to the public domain and under the following + license: you are granted a perpetual, irrevocable license to copy, modify, + publish, and distribute this file as you see fit. + +--]] + +local floor, setmetatable = math.floor, setmetatable + +local function siftup( self, from ) + local items, priorities, indices, higherpriority = self, self._priorities, self._indices, self._higherpriority + local index = from + local parent = floor( index / 2 ) + while index > 1 and higherpriority( priorities[index], priorities[parent] ) do + priorities[index], priorities[parent] = priorities[parent], priorities[index] + items[index], items[parent] = items[parent], items[index] + indices[items[index]], indices[items[parent]] = index, parent + index = parent + parent = floor( index / 2 ) + end + return index +end + +local function siftdown( self, limit ) + local items, priorities, indices, higherpriority, size = self, self._priorities, self._indices, self._higherpriority, self._size + for index = limit, 1, -1 do + local left = index + index + local right = left + 1 + while left <= size do + local smaller = left + if right <= size and higherpriority( priorities[right], priorities[left] ) then + smaller = right + end + if higherpriority( priorities[smaller], priorities[index] ) then + items[index], items[smaller] = items[smaller], items[index] + priorities[index], priorities[smaller] = priorities[smaller], priorities[index] + indices[items[index]], indices[items[smaller]] = index, smaller + else + break + end + index = smaller + left = index + index + right = left + 1 + end + end +end + +local PriorityQueueMt + +local PriorityQueue = {} + +local function minishigher( a, b ) + return a < b +end + +local function maxishigher( a, b ) + return a > b +end + +function PriorityQueue.new( priority_or_array ) + local t = type( priority_or_array ) + local higherpriority = minishigher + + if t == 'table' then + higherpriority = priority_or_array.higherpriority or higherpriority + elseif t == 'function' or t == 'string' then + higherpriority = priority_or_array + elseif t ~= 'nil' then + local msg = 'Wrong argument type to PriorityQueue.new, it must be table or function or string, has: %q' + error( msg:format( t )) + end + + if type( higherpriority ) == 'string' then + if higherpriority == 'min' then + higherpriority = minishigher + elseif higherpriority == 'max' then + higherpriority = maxishigher + else + local msg = 'Wrong string argument to PriorityQueue.new, it must be "min" or "max", has: %q' + error( msg:format( tostring( higherpriority ))) + end + end + + local self = setmetatable( { + _priorities = {}, + _indices = {}, + _size = 0, + _higherpriority = higherpriority or minishigher + }, PriorityQueueMt ) + + if t == 'table' then + self:batchenq( priority_or_array ) + end + + return self +end + +function PriorityQueue:enqueue( item, priority ) + local items, priorities, indices = self, self._priorities, self._indices + if indices[item] ~= nil then + error( 'Item ' .. tostring(indices[item]) .. ' is already in the heap' ) + end + local size = self._size + 1 + self._size = size + items[size], priorities[size], indices[item] = item, priority, size + siftup( self, size ) + return self +end + +function PriorityQueue:remove( item ) + local index = self._indices[item] + if index ~= nil then + local size = self._size + local items, priorities, indices = self, self._priorities, self._indices + indices[item] = nil + if size == index then + items[size], priorities[size] = nil, nil + self._size = size - 1 + else + local lastitem = items[size] + items[index], priorities[index] = items[size], priorities[size] + items[size], priorities[size] = nil, nil + indices[lastitem] = index + size = size - 1 + self._size = size + if size > 1 then + siftdown( self, siftup( self, index )) + end + end + return true + else + return false + end +end + +function PriorityQueue:contains( item ) + return self._indices[item] ~= nil +end + +function PriorityQueue:update( item, priority ) + local ok = self:remove( item ) + if ok then + self:enqueue( item, priority ) + return true + else + return false + end +end + +function PriorityQueue:dequeue() + local size = self._size + + assert( size > 0, 'Heap is empty' ) + + local items, priorities, indices = self, self._priorities, self._indices + local item, priority = items[1], priorities[1] + indices[item] = nil + + if size > 1 then + local newitem = items[size] + items[1], priorities[1] = newitem, priorities[size] + items[size], priorities[size] = nil, nil + indices[newitem] = 1 + size = size - 1 + self._size = size + siftdown( self, 1 ) + else + items[1], priorities[1] = nil, nil + self._size = 0 + end + + return item, priority +end + +function PriorityQueue:peek() + return self[1], self._priorities[1] +end + +function PriorityQueue:len() + return self._size +end + +function PriorityQueue:empty() + return self._size <= 0 +end + +function PriorityQueue:batchenq( iparray ) + local items, priorities, indices = self, self._priorities, self._indices + local size = self._size + for i = 1, #iparray, 2 do + local item, priority = iparray[i], iparray[i+1] + if indices[item] ~= nil then + error( 'Item ' .. tostring(indices[item]) .. ' is already in the heap' ) + end + size = size + 1 + items[size], priorities[size] = item, priority + indices[item] = size + end + self._size = size + if size > 1 then + siftdown( self, floor( size / 2 )) + end +end + +PriorityQueueMt = { + __index = PriorityQueue, + __len = PriorityQueue.len, +} + +return setmetatable( PriorityQueue, { + __call = function( _, ... ) + return PriorityQueue.new( ... ) + end +} ) diff --git a/alarm.lua b/alarm.lua new file mode 100644 index 0000000..128e7fa --- /dev/null +++ b/alarm.lua @@ -0,0 +1,61 @@ +local dfpwm = require("cc.audio.dfpwm") + +local speaker = peripheral.find("speaker") +local monitor = peripheral.find("monitor") +local chat = peripheral.find("chatBox") +local detector = peripheral.find("playerDetector") + +local distance = 20 +local target = "OROURKEIRE" +--local target = "devplayer0" + +function klaxon() + local decoder = dfpwm.make_decoder() + for chunk in io.lines("data/danger.dfpwm", 16 * 1024) do + local buffer = decoder(chunk) + + while not speaker.playAudio(buffer) do + os.pullEvent("speaker_audio_empty") + end + end +end + +function showWarning() + monitor.clear() + monitor.setTextScale(2) + --[[local w, h = monitor.getSize() + local tw = string.len("WARNING") + for i = 1, 3 do + monitor.setCursorPos(w/2 - tw/2, (h/3)*i) + monitor.write("WARNING") + end]] + monitor.setCursorPos(8, 3) + monitor.write("WARNING") + monitor.setCursorPos(8, 5) + monitor.write("WARNING") + monitor.setCursorPos(8, 8) + monitor.write("WARNING") +end + +function broadcastWarning() + local msg = { + {text = "WARNING", color = "red"}, + {text = ": Kevin is ", color = "white"}, + {text = "IN THE BASE", color = "yellow"}, + {text = "!"}, + } + local msgJSON = textutils.serializeJSON(msg) + chat.sendFormattedMessage(msgJSON) +end + +while true do + if detector.isPlayerInRange(25, target) then + showWarning() + broadcastWarning() + klaxon() + else + monitor.clear() + end + + sleep(1) +end diff --git a/danger.dfpwm b/danger.dfpwm new file mode 100644 index 0000000000000000000000000000000000000000..2f5a0e6ca38df5feb282bf8895962bb0a246a41d GIT binary patch literal 37546 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 literal 0 HcmV?d00001 diff --git a/datapack/.gitignore b/datapack/.gitignore new file mode 100644 index 0000000..c4c4ffc --- /dev/null +++ b/datapack/.gitignore @@ -0,0 +1 @@ +*.zip diff --git a/datapack/data/minecraft/computercraft/turtle_upgrades/diamond_pickaxe.json b/datapack/data/minecraft/computercraft/turtle_upgrades/diamond_pickaxe.json new file mode 100644 index 0000000..7ef8cad --- /dev/null +++ b/datapack/data/minecraft/computercraft/turtle_upgrades/diamond_pickaxe.json @@ -0,0 +1,6 @@ +{ + "type": "computercraft:tool", + "item": "minecraft:diamond_pickaxe", + "adjective": "upgrade.minecraft.diamond_pickaxe.adjective", + "allowEnchantments": true +} diff --git a/datapack/pack.mcmeta b/datapack/pack.mcmeta new file mode 100644 index 0000000..9db5b82 --- /dev/null +++ b/datapack/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "pack_format": 15, + "description": "Enchanted pickaxe for ComputerCraft" + } +} diff --git a/icon/ore-coal.png b/icon/ore-coal.png new file mode 100644 index 0000000000000000000000000000000000000000..ad6169467c8258c02b99e7ff8c4896d538c64060 GIT binary patch literal 623 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9Wz$e7DzrVk}zP_ZSBqJjuCMHHzRn^kQ z%*@P8PfyR&+y4Lm{|_3@i!m@TFeZ7syKrS(_!7pzz`$PO>Fdh=f{{;1#Wc9pKAeGp zQQgzUF(l*O+Znfc4;cusTy~0DzzRpZjyBK8*m%dmZ@YYFasR{g(rq`ldH%leRQ>w( zg*{8Ru}xvvaf0pM_6erf=l2BOZm?oFyC_j(2fuCGJm(tjI$puw#zD+p3_2&2X5V+N zVfMMalI;q^2L;bUwT4?ApWKU@GaYyjd^eQUGinp+lCg0QX7=MRNc?=tV2`8$-z=LF zlLdSSmf1uE%xPWIx%uKB$+e8C3{D)kd<3O=C&(CSH=8bCa|q5*(HF6dD0+M`WY!u+ zQwABaw2qTg8;f3CxZNPta8pK1Qhd_S5aw45ChgK)(|y@FD~o2dTlD@byxJhuAfqC7 zrtM*L!7~{bUJLt#dloV(l^3q$RKM7fW3qrJf%RnfiB;biOcyXcU^Z6WvnKA!C8<`)MX8A;sSHL2MkcxjhPs9(A%+%K#)ei#M%o4jRt5$e?%kF{(U6;; zl9^Ts(qOD>V5Vzm9Aao}Wo%|;U;@!#Uc1AQfq_8-ZbM0CZfbE!Vr~IQ53(g@R;I=f WJvV+tuVi3gVDNPHb6Mw<&;$T8cGq73 literal 0 HcmV?d00001 diff --git a/icon/ore-copper.png b/icon/ore-copper.png new file mode 100644 index 0000000000000000000000000000000000000000..299e72843fb4d9f186d5e4605938f6a4ea4e89f2 GIT binary patch literal 653 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9cz$e7DzrVk}zP_ZSBqJlksw_DsCgwr0 z@4TJX`%~RkjGz#v1!l z;onc6r!0@1<~M!9@$3xlwZ7BU9xY|iWccee|HZ9YHTxMV8KQQWX+FHRW#*J(ep@Fa zNp?{M{seQE=nzE%g?kzE6wTupix|R$kFFP37RZxurGRS!bAw}wgz9RKqwgp9JU)9^ z`s_WQJBh3_q#i8$u)t#MH_FYRTP*r&SCL3=E#GelF{r5}E*TMd4xq literal 0 HcmV?d00001 diff --git a/icon/ore-diamond.png b/icon/ore-diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..6659b080194e9733096380a66c39159544e594b4 GIT binary patch literal 625 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9Wz$e7DzrVk}zP_ZSBt1P{?!vY5=NFZy z&FEdb@#_C?ixw^V|Ns9xv)kDW3=E7(-tI1385h2UF)%Q&mw5WRvcF*D6VlL`9eraq z0|TR`r;B4q#=W=G0|lE61Y9;Yv_`F9)w#kXwjqFfM{eKA(>j>~6K3CCU*H*6SN5$h zRWoXJ#Qs$g`@6Sn`(l((#W4M5&tZRl2Ih)`JRZy!de?S%SIsbQV0xE5%Yl#KpaEB}g@m|C!HzpUDGpo=u6zIJatR-uWo0UBG3z(a47mj-4=r5V zWx&aCKUX@Pi#!i)}qi}MBAy01;(@nDQ#kFsKX;y$IScoCx}1J5i8R*r>6QV#jO zM;l%;YB(`37La1>ViPiD6OeVvTV|Y)#o)%Zab@E{Z61YNAv`BoB|0}$-1=XAv|%Qr zeS}<4&ispYIt&a9swJ)wB`Jv|saDBFsfi`23`Pb9nN|tXV61CkrfX;%VrXn-Y-VL(0?}YzyTg%zfk6XqLrG?CYH>+o hZUIOSk|ibvRwhtAUoSA!GB7YOc)I$ztaD0e0szD#*Gm8Z literal 0 HcmV?d00001 diff --git a/icon/ore-ds-coal.png b/icon/ore-ds-coal.png new file mode 100644 index 0000000000000000000000000000000000000000..5c17500e1d331d90fdbc0ac86af855b82b1bd3c8 GIT binary patch literal 613 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9Tz$e7Dva&KIB_%L0(AL&jU*DXIi%UyO zOI}{y)7$?4|NjLHPpudj7#Neh-Ca08-dy^Ifq{X&#M9T6{RJbRkSc?W?kQ6S21W%> z7srr{dvB))@*Xzeaq(U#;+81ll?Wo)s&}r^-xaAU@cP~I+?@UY=H#T`Zu_>-{o?0K zd7mWSM>FU$$jD6Bu<_X{(J+tk3qyhskL#!G7qurJ&R3kv$hCl-A$Uim$E1DEzr-%o zJJm7RG8l0zTj)8#LGkF-oaGalG8lJod+>-nn&bJT!lvOXW89nWR{bePQoYBL8NV=8 z6i>*|^E&49#2~{UjG>l6gBZg};nxl;1!kT8$+LjBVc{W%hnrps^e66N_{ESR^-JNP{$h!f$r7*f zjaWCB9GG0W+~IVaxd7WalZo05W(@HrDw1tW56?cWtI{x)(LSVM?U_?a(|j2i7*tDK zBT7;dOH!?pi&7IyQW=a4j7)S540R1nLJTdej18@fjI<35tPBh`+`BD@q9HdwB{QuO zq`_F%z)aWBIK=yYbCtyTbTnQGLy; z!_Eti9#Jq|z}MjI!^PLW!Kb3(lfXrxTV}z`e*7O4PCA!{DEpLUIY=@%Ix0JtvYg~z z$+(=YhVfX4f3(0$mlq5S45}rr5hW>!C8<`)MX8A;sSHL2MkcxjhPs9(A%+%K#)ei# zM%o4jRt5$e?%kF{(U6;;l9^Ts(qOD>V5Vzm9Aao}Wo%|;U;@!#Uc1AQfq_8-ZbM0C kZfbE!Vr~IQ53(huRtA<3J@?}`g3=a)r>mdKI;Vst0LHxC>;M1& literal 0 HcmV?d00001 diff --git a/icon/ore-ds-diamond.png b/icon/ore-ds-diamond.png new file mode 100644 index 0000000000000000000000000000000000000000..4c0a8c8c8719bfd81c0dff5879318cfe22a772fe GIT binary patch literal 641 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9iz$e7Dva&KIB_%L0(AL&jU*Fu&!9niA zwesf|MfxYDboE^Q|1Ghy{Qv*|UQN6pyBL$a-CcMZHwPv&Ffg!}c>21szhLAO(on1J zGi+sGU^Mo0aSX}0_jX1g?_mQT7w1F~uS5~IgmRAo4E_6yfZmo=Vi-YVL$ZDBNJn03N{ zC0A2aSg0a=&g}J!rVKOOds$drJbO$e_nc>4!Dz}*l_1Ajuwp{T&OZi@yepV5r1+my z>E`^Pe3bnU)1?L}2A)GN#Qh(LNS*m=Iq{Ev7_%S$hop~JYtxv$l*9uW+;f;uF?gt5 z_`7gPJ#Pl{D~1fQEf4JH-ARZFUSz)LiRl8i1LxV9ZY=41Q1I{o_ z85>#|8EG3BSQ!{>xOZC)MMG|WN@iLmNQ1GiftjwMafqR@m9d$XfeA!|dF>8I1_lNV rxD6$lxv9k^iMa(JJxG?A7+4uwK=fE_O%`BaU|{fc^>bP0l+XkKB{<&n literal 0 HcmV?d00001 diff --git a/icon/ore-ds-emerald.png b/icon/ore-ds-emerald.png new file mode 100644 index 0000000000000000000000000000000000000000..8169c95fb03f20a1dcbd68f1b8cf64a64db60e1f GIT binary patch literal 636 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9iz$e7Dva&KIB_%L0(AL&jU*G)Z|JUMo zlNhQc%%klbKex!t&=f!F^8f#TW`m=F3=9m6N#5=*JdK+JlNlHo*h@TpUD;nS@(HPl z=-%?}W?*2{^K@|x$+-7+Mxfv!2OgK~g<=~5xVJX2>Lf67M;u^!cB1TE>9&Pzvrg6- zPQQJ9zR#vRCaupd=w?dJ@{N1^{Yrxn1K+iUs-C4Yi)G`Pvluk)IrmR6Ka;iS+;Ile z1#At=0zOJ!YOu^!S^v8s(}9=4*O2#O#Cn0Wldor($1{5|Owgb4{et?FHW?S0I}NXy zcPx1}G0@xPurq^H7vp2cWN8gv4aNx*nHbL8pKz|Gq2fk{gKPtzt;;Eu&H6&}YP%jM zE@mucXlIT#nel19U%UANwgbUzy-p1$8l4ZjrnjeDYA|Au7i&-Q;GO2oeljJ03ELEg zIjo)sj52RlyhylVvVbqa@M*i}11S|btABDT(gl?c_xR<^J}HZGr{^n$GoNCJkcbgG zFrA~^Pmyy9!5Dn(FI~*Ap s7&PEElw{_n7MCRE7J&31TVi2lWB}3gSEgbf0|Nttr>mdKI;Vst0E21QFaQ7m literal 0 HcmV?d00001 diff --git a/icon/ore-ds-gold.png b/icon/ore-ds-gold.png new file mode 100644 index 0000000000000000000000000000000000000000..daf378a13b3ee3d35339582cbf62ca10cb1d5d2d GIT binary patch literal 615 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9Tz$e7Dva&KIB_%L0(AL&jU*CLAio)x; ze1G0~|Np=B|NsAr>u2gQFfcGCdAqxCe!RK#4FdxMdx@v7EBgyZJ|R`1_fvM)GB7YI zdAc};WZZi@zHaxV6sd3&}4c zxA0}w&Uj^>$+>{Fp*J^6UTBNc9iO%Hm|rj|sIYJuZ#dghIiG6*|AY7l4Xd^-Ow(%q z+XOIWFe)h2B?NqtVq$nQ)wba`bIk-59i|@#H~Ljh zUTD|wo7rHUnnKI5>@7_Heo7q3W!yUR$L`s(j~*~oF>vs=bKET0{Di&p+xqTw23>}G z0a=qjrX5P1yg@gQV*zVJLd?S%izX&aF{%0Gs?uQBASLqYp}qVcrB7EQm@*hYJZw6> zEUc%L;a~;tQpPO|6&f`s7A&k0^;MY8cb|U&{{k`22hPj+=Uo*(u$EE&eeK#a=X*Hi z85kH;OI#yLQW8s2t&)pU6H8JVj0}uSbPWu34NXD}Ev$?Ut&EJc4GgRd3^v@mEr+5Z zH$NpatrDccSl7Tz*U&h`(Adh@%*wz7qQSg&ha&?6g9hA&lFZ!H;*!MN0+1eLOU$hd YEg*U}mS;_8U|?YIboFyt=akR{04uoK{r~^~ literal 0 HcmV?d00001 diff --git a/icon/ore-ds-iron.png b/icon/ore-ds-iron.png new file mode 100644 index 0000000000000000000000000000000000000000..34afe0262684275d1d3414dfd4b4420f6721e749 GIT binary patch literal 624 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9Wz$e7Dva&KIB_%L0(AL&jU*Ehu-M^zG zbbVj>jrEfs9a#1M|Np}6NpTDe42((M?k-#z7rulsFfg!}c>21szhLAOQWn~IPUbfQ z1EYqgi(^Q}y|*(1d6^6aT(TLtBMvZ$ZD?TCNnqSw;t~I8-N6I7Wp+D?-tPP7vn*O7 z`IS-W-IC~C9`llIqym@@bpO7T8~iNz&x|U)RG(PpECvHlwYcC)DGrmiWZz>s7aF7* zY79QkJM~0PCdX)+i~;Wo#tnfv0tXHl&g`x)<<($xkT|xi%PzQ5NG0;P)a=!a&)H>| zl1>WDKGS}7VQ}t&m5hAs*&cC^AF*9w+%Zu>{blD&9#t zfcb$EdpoaNVH2B0fuXLUNr<6^m9e3fk&(86ft7*5 zhI_Z=P&DM`r(~v8f;1TG8kp%C8iyDfTN#^K8JIvcnAh%bWME*>fZI@#nVVW%l9*cn f(t~V?sgfXQ9~mo+Z=cQU7b5ipta|Nnn~f%r}a1_s6?Z+92oZ(9<-GB7Z(mw5WRvcF*D z6VhP4`O@J#0|TRrr;B4q#=W;Q0(lP`@VIy{6meT9;+6_EmMhBn28rV_K-7`*IeGrX{#!1RP6K`cshUY?j@zM0K}&1`+|3|KuFCxocX zSIbwb<=Pm*HsStbRuAR{3k5VfnhiyI+8#;8X&$)LaCk{tW95p48Z$OeG7yn_HFqV$ zY38)e2@4)P->m-QgQK&SgB`>4c@7&Vd=U?7n93M`N^kG&3wyhEFfcHvmbgZgq$HN4 zS|t~yCYGc!7#SFu=o%R68k&R{T38tyS{WH>8yHv_7;LzATMk7-ZhlH;S|vz>v95uc zuAy;=p|O>*nU#SFM1y(l4o3zC1`W6kC7HRY#U+Wk1t2|0mY5h=8JI%!Tz|`I%)r3F N;OXk;vd$@?2>@79;9md$ literal 0 HcmV?d00001 diff --git a/icon/ore-ds-redstone.png b/icon/ore-ds-redstone.png new file mode 100644 index 0000000000000000000000000000000000000000..07c2dd17901043c73be0d852a92d63875f0277bb GIT binary patch literal 715 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg4rT@hhA$5${$yZaP)PO&@?~JCQe$9fXklRZ z1(JWkz))(y!0;-8fx&791A}WjZtS|IW^q$jI+9GXMYokGmT1l!1YPG0EHAMPTYCUL6Jo z2KEw9Usv`QjC?|BOgH&{++tv0EcA4745_&F_NHagVFLk|z^*Ccl@s6BN2_PB#$P>J zl%()ut|N;<|49*t+}kHoQ|wPR#(3Sb`nQi$Kq0}ZL3rJX!bxlFwa@&ND8=sjB{V7s&l7KT*2W$jYGDE&W|u5j`#(8JtkE#v2e`bPiQ{T{C%RxsUK#a3_n?Z zGIjFM{*&PXlHyCaF(F8yb-%mOzWxmk#~T0l6zpSQWV*(ke*w$0 z@@t|X0~o}fF}Bv*Jh8mKT;ch1%lL=}2FA~f?w))CdlI%BJKB8mrlTszrkVpcZ5zeA z!#ZAfuXLUNr<6^m9e3fk&(86ft7*5hI_Z=P&DM`r(~v8f;1TG8kp%C z8iyDfTN#^K8JIvcnAh%bWME*>fZI@#nVVW%l9*cn(t~V?g_Qx+5{+efrx+L*7(8A5 KT-G@yGywpu^!arF literal 0 HcmV?d00001 diff --git a/icon/ore-emerald.png b/icon/ore-emerald.png new file mode 100644 index 0000000000000000000000000000000000000000..6d158b34e8925f56cb67cd3317883e8c5bfa57d4 GIT binary patch literal 634 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9iz$e7DzrVk}zP_ZSBqJjuC_CWh|JUMo zlNhQc%%klbKex!t&=f!F^8f$;qKn+J3=9m6N#5=*JdK+JlNlHo*h@TpUD;nS@(HO) zok~jRVPIg?@pN$v$+-7+My%i=2cDMmPPz$<+z|(u#5Odr>Lf50r&w>FyMCt9f|+l; z*Z=%kaWZCF-^48~dck(_&OL#P8C4nV?kwwDaYj0=g83E0lpXDI3vCRnjO#5tcr_R& zOsQ$Jh>+2GUb@eLcLn2#(@v~eb*&PMZ(MGWVi4c(!S*XB=d*<$gFY5-*vPn?twKZO z%7+z!-Y(PI8RRth&Y$ZsS-^9Ek@?OaUd>~Pr_vTPnle}}P%|y=eDXAT^Ts$WUJb^C z2DPSVP18H{(=S^dUU+(_Kj^iB=>nF7pUTcA2{%hNEMqKXkl~r- zv3IrS>9%FgAK&`BGkY=YP}y|TAVmD+#Fr10vJUKI)VVS<&H4S!fE;noW?l`(6Wpzb zCrSTlj;>|aVyIJ2+Oy_*Pg)`a1A}UbYeY#(Vo9o1a#3nxNh*Vpfsu)>fuXLUNr<6^ zm9e3fk&(86ft7*5hI_Z=P&DM`r(~v8f;1TG8kp%C8iyDfTN#^K8JIvcnAh%bWME*> rfZI@#nVVW%l9*cn(t~V?g_V&RM9;i4zDpPw7#KWV{an^LB{Ts5y6xbO literal 0 HcmV?d00001 diff --git a/icon/ore-generic.png b/icon/ore-generic.png new file mode 100644 index 0000000000000000000000000000000000000000..ecd9808639c827b81a55518774ffcf64fe17af1b GIT binary patch literal 12244 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 NgQu&X%Q~loCIB5w;_3hZ literal 0 HcmV?d00001 diff --git a/icon/ore-gold.png b/icon/ore-gold.png new file mode 100644 index 0000000000000000000000000000000000000000..625ae904277a25dc5e70baa6cda0abfcac8e1656 GIT binary patch literal 633 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9Wz$e7DzrVkvq@=#SJ|iPzPJu#9Ow8-K ze1G0~FIu$d|NpK3|NpO9_VyA30|R4{x4R2h#)U6o3=9nHC7!;n>@OJkgj6N?9fOh? z7#IybT^vI)?!BFHk+<1Ez&Wx}bQhEM1}5#2)^!KC?ruw;(jIe!Y0evYr%Ba+BE;J> zcV(FE^{UcSonP$BxP`$Wp-|UwxzqhUJh`e_OfQ%Z=uA3uMD5@mm)jStN~AO!#299A zrX^n9y+mDY_iX+J><9R}vp+6xnfc>Hb%wsIJpTe#24%(t0l%hw@pHcT%dTWb#~}te z{sQHfvE2?CG9q`_&NAF$ut~_^VY!^~IEP8bL7w5@q{A%6i3?zj0=fl!>*n@Ek!w09&3dR-9A5Sl{dy>ugg`r}xL!Lsu*`!0y@4Korm@!Bm>UCQ1 zM7_D)f7ZFmmmCXN9X`qPNwlgxHaMi-D14apLk)vl(dLQ`E_EL~S}rmCVi0)7*wy)G zLE_sroC}yAum_yq|GPQI`~m|5gKCLuL`h0wNvc(HQEFmIDua=Mk%_K>p{}7xh@pj* zv7wcbk+y+>m4U&Ad$;9KH00)|WTsVuG#Kj|nCTiChZq`L8Jk%dm_Rg`*Y0p+U|`UI m+fb63n_66wm|FnSgKUYpl@V0Wj|g@K5b$*Mb6Mw<&;$S=z~7+& literal 0 HcmV?d00001 diff --git a/icon/ore-iron.png b/icon/ore-iron.png new file mode 100644 index 0000000000000000000000000000000000000000..9b0f5fdeb4fb2f7ce65cd02fc741697a9ee57129 GIT binary patch literal 615 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9Tz$e7DzrVk}zP_ZSBqJlEJl(&eBy@dW z`Hl6HA01fr|Nno<7eZ+a3=E7(-tI1(A8#&w!@$76UgGKN%Kn0pPe@r(Pv&Sb0|TRy zr;B4q#=W;QF7h@T2slSJibgbw?s5u$!4;ty@(ed~H$ z_1NVd;Q{l={cd|$C-7)2OcxZiR5XtSDg5< z>*W!KD26`{ju94X%x2vcao}fIH1UMP*2;pL0lvx4rt`CY$Y4kdXl!=j72=FoDgNj&1 z1;e*xix$ij_cIS>=x5*HC}8h$ueB$C&Q^w73^ju9Wfb1MI$gsc%TT}A@A2L3rN=!O z7#LJbTq844GeV+O+pMUtc(q2-RWdtU|{fc^>bP0l+XkKfXUuPixvsEtZ~V|lR5Q^fXSTy|NlRk*V@Fuz`&T~?e4;tzt_N@fq{X&#M9T6 z{RJbRkOsrb<}DQr42%JuE{-7?_ukHMEM#`%Vd-zuoZ+O=;-t~iqzOe%J5p}nyeFj| z`ft70=bO8?E{hMIbndue$*fO5ZJvHU9dJ*!{%XTp##x$Gb1!{Z<5t1^ilL%Hx=Q}h z9-h>VicH@OkG$8e;niR?(3o>w@!WYu9+7)(Mn2b6wlMx?mJzcIFmjl+_wt^mD-A*n z&QqG3mpRQST5usJLv4mUn?JJ`0}rbkSB65o^BfbAhxh(R`$-3|Ib>+;XwxWq=^|3R zpDBeyI)JHxr_*gVM}qX3RITcNUEJ?p@r@n+ zAI=>r%-7)6U@Qn!P`MwRU1?Eg@3#43!LA0A1!4^aDT)HkPv;AClxOi=zhxw~!B%0q z+iX_H#03S=K;)Fj6s$@e*Rx39AJCH_k(f2P<~~F zmklVkRZCnWN>UO_QmvAUQWHy38H@~!Omqzlbq!5I3@xmT4Xuofv<(cb3=B5hyDi7S zz<|(@o1c=IRteHztZQJVYiJx|Xl!L{W@TUk(O_P?!;yi3K?80>NoHbP0l+XkK_=f9n literal 0 HcmV?d00001 diff --git a/icon/ore-redstone.png b/icon/ore-redstone.png new file mode 100644 index 0000000000000000000000000000000000000000..8ba92edb4ee1f27ef45424d9a1ce1b651c31a75a GIT binary patch literal 644 zcmeAS@N?(olHy`uVBq!ia0y~yU}ykg7G?$p219|G9}El(3dtTpz6=aiY77hwEes65 zK=Lmb7)lKo7+xhXFj&oCU=S~uvn$Ysfq_9cz$e6Ya!*fveSJwuNk&FSW=za9Hnvmj z?Ee`U{>H@}V_})j%>2KzbN}SY-(_U}|Nnoy?f)DG1_s6?Z+92I{JjSL3=9nHC7!;n z>@OJkgj7wv=JAO!FfbZ;x;Tbp+Nr*VSe@@~&VG zFkbjWD`+lK(=2r|AGcGW<@d@RsO=0}XkRc$UB%!4~xuo!hfl|4ND6<#C zgbwi=Cwg7=RWHN@bTl@{*lf39_F}kTbHhO5X2_@1WufTfmaA zY-Zz^y9`nRj2~Dz-{@D@{477rz`&qd;u=wsl30>zm0XmXSdz+MWME{XYhb8rXcA&* zVP$M+Wn`pnU|?lnu;JcqITQ`K`6-!cl^_kqx&~&thQ=X=##Y8=Rt6>z4d%5w92poG qG~hOrWag$8mn7yEfb<|+Vs2$>4Ao<0Fr9&cfx*+&&t;ucLK6VB2i<=F literal 0 HcmV?d00001 diff --git a/icon/turtle.png b/icon/turtle.png new file mode 100644 index 0000000000000000000000000000000000000000..e7bfa762803f403b76a469b65a1d17cdcdd04f05 GIT binary patch literal 8745 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 PFfe$!`njxgN@xNAm2D+v literal 0 HcmV?d00001 diff --git a/mine.lua b/mine.lua new file mode 100644 index 0000000..5ce3764 --- /dev/null +++ b/mine.lua @@ -0,0 +1,727 @@ +package.path = "/mod/?.lua;" .. package.path +local PriorityQueue = require "PriorityQueue" + +function Set(list) + local set = {} + for _, l in ipairs(list) do set[l] = true end + return set +end + +local yieldTime = 0 +function yield() + if os.clock() - yieldTime > 2 then + sleep(0) + yieldTime = os.clock() + end +end + +function arr(n, init) + local a = {} + for _ = 1, n do + table.insert(a, init) + end + return a +end +function arr2(x, y, init) + local a = {} + for _ = 1, y do + table.insert(a, arr(x, init)) + end + return a +end + +local dirMap = { + ["0,-1"] = 0, + ["0,1"] = 0.5, + ["1,0"] = 0.25, + ["-1,0"] = -0.25, +} +function direction(v) + local d = dirMap[v.x..","..v.z] + assert(d) + return d +end + +function findDistances(points) + local dist = arr2(#points, #points, math.huge) + -- local prev = arr2(#points, #points) + + for i = 1, #points do + for j = 1, #points do + if i ~= j then + dist[i][j] = (points[i] - points[j]):length() + -- prev[i][j] = i + end + end + end + for i = 1, #points do + dist[i][i] = 0 + -- prev[i][i] = i + end + + return dist +end + +function groupOres(ores, dist, offset) + if not offset then + offset = 0 + end + + local groups = {} + for i, o in ipairs(ores) do + table.insert(groups, { + ["type"] = o.name, + ["blocks"] = { + [i] = vector.new(o.x, o.y, o.z), + }, + }) + end + + local didJoin = true + while didJoin do + didJoin = false + for i, io in pairs(groups) do + for x, a in pairs(io.blocks) do + for j, jo in pairs(groups) do + if i ~= j and jo.type == io.type then + for y, b in pairs(jo.blocks) do + -- yield() + assert(a ~= b) + if dist[offset + x][offset + y] == 1 then + for z, p in pairs(jo.blocks) do + io.blocks[z] = p + end + groups[j] = nil + didJoin = true + break + end + end + end + end + end + end + end + + local retGroups = {} + for _, g in pairs(groups) do + local v = vector.new(0, 0, 0) + local retBlocks = {} + for _, p in pairs(g.blocks) do + v = v + p + table.insert(retBlocks, p) + end + g.blocks = retBlocks + g.center = v / #g.blocks + assert(g.center) + table.insert(retGroups, g) + end + + return retGroups +end + +function pathThrough(points, dist, s, e) + -- local n = #points + + -- dist[s][n] = 0 + -- dist[n][s] = 0 + -- dist[e][n] = 0 + -- dist[n][e] = 0 + + -- for k = 1, #points do + -- for i = 1, #points do + -- for j = 1, #points do + -- if dist[i][j] > dist[i][k] + dist[k][j] then + -- dist[i][j] = dist[i][k] + dist[k][j] + -- prev[i][j] = prev[k][j] + -- end + -- end + -- yield() + -- end + -- end + + -- local path = {e} + -- while s ~= e do + -- e = prev[s][e] + -- table.insert(path, 1, e) + -- end + + -- return path + + -- nearest neighbour + local unvisited = {} + local ui = nil + for i = 1, #points do + if not e or i ~= e then + table.insert(unvisited, i) + end + if i == s then + ui = #unvisited + end + end + assert(ui) + + local visited = {} + local route = {} + while #unvisited ~= 1 do + local u = unvisited[ui] + table.remove(unvisited, ui) + + local cDist = math.huge + local closest = nil + for ii = 1, #unvisited do + local i = unvisited[ii] + assert(i ~= u) + if dist[u][i] < cDist then + cDist = dist[u][i] + closest = ii + end + end + assert(closest) + table.insert(route, unvisited[closest]) + ui = closest + end + if e then + table.insert(route, e) + end + + return route +end + +-- A* +function findPath(s, e) + local points = {} + function addPoint(p) + local k = p:tostring() + if not points[k] then + points[k] = p + end + return k + end + s = addPoint(s) + e = addPoint(e) + + function h(i) + return (points[e] - points[i]):length() + end + + function neighbors(k) + local p = points[k] + local ns = { + p + vector.new( 1, 0, 0), + p + vector.new( 0, 1, 0), + p + vector.new( 0, 0, 1), + p + vector.new(-1, 0, 0), + p + vector.new( 0, -1, 0), + p + vector.new( 0, 0, -1), + } + + for i, n in ipairs(ns) do + ns[i] = addPoint(n) + end + return ns + end + + local gScoreT = {} + gScoreT[s] = 0 + function gScore(i) + if gScoreT[i] then + return gScoreT[i] + else + return math.huge + end + end + + local fScoreT = {} + fScoreT[s] = h(s) + function fScore(i) + if fScoreT[i] then + return fScoreT[i] + else + return math.huge + end + end + + local openSet = PriorityQueue(function(a, b) + return fScore(a) < fScore(b) + end) + openSet:enqueue(s, s) + + local prev = {} + local found = false + while not openSet:empty() do + local current = openSet:dequeue() + if current == e then + found = true + break + end + + local ns = neighbors(current) + for _, n in ipairs(ns) do + tentativeG = gScore(current) + 1 + if tentativeG < gScore(n) then + prev[n] = current + gScoreT[n] = tentativeG + fScoreT[n] = tentativeG + h(n) + if not openSet:contains(n) then + openSet:enqueue(n, n) + end + end + end + end + assert(found) + + local path = {points[e]} + local current = e + while prev[current] do + current = prev[current] + table.insert(path, 1, points[current]) + end + return path +end + +local ORES = Set{ + "minecraft:coal_ore", + "minecraft:deepslate_coal_ore", + "minecraft:iron_ore", + "minecraft:deepslate_iron_ore", + "minecraft:copper_ore", + "minecraft:deepslate_copper_ore", + "minecraft:gold_ore", + "minecraft:deepslate_gold_ore", + "minecraft:redstone_ore", + "minecraft:deepslate_redstone_ore", + "minecraft:emerald_ore", + "minecraft:deepslate_emerald_ore", + "minecraft:lapis_ore", + "minecraft:deepslate_lapis_ore", + "minecraft:diamond_ore", + "minecraft:deepslate_diamond_ore", + + "create:ochrum", + "create:zinc_ore", + "create:deepslate_zinc_ore", + "create_new_age:thorium_ore", + + "powah:deepslate_uraninite_ore_poor", + "powah:deepslate_uraninite_ore", + "powah:deepslate_uraninite_ore_dense", + "powah:uraninite_ore_poor", + "powah:uraninite_ore", + "powah:uraninite_ore_dense", + + -- "minecraft:diamond_ore", + -- "minecraft:netherrack", +} +local BLACKLIST = Set{ + "minecraft:diamond_pickaxe", + "computercraft:wireless_modem_advanced", + "advancedperipherals:geo_scanner", + "enderchests:ender_chest", + "functionalstorage:ender_drawer", + "advancedperipherals:chunk_controller", +} +local FUEL = "minecraft:coal" +local CHANNEL = 1337 + +settings.define("mine.name", { + description = "Miner name", + default = "DiggyBoi", + type = "string", +}) + +function selectItem(item, nbt) + for i = 1, 16 do + info = turtle.getItemDetail(i) + if (not item and not info) or (info and info.name == item and (not nbt or item.nbt == nbt)) then + turtle.select(i) + return i + end + end +end + + +Miner = {} +function Miner.new() + local self = setmetatable({}, { __index = Miner }) + self.name = settings.get("mine.name") + self.equipped = { + ["left"] = { + ["last"] = "NONE", + ["lastNbt"] = nil, + ["fun"] = turtle.equipLeft, + }, + ["right"] = { + ["last"] = "NONE", + ["lastNbt"] = nil, + ["fun"] = turtle.equipRight, + }, + } + + -- Get upgrades to a known state by "equipping" nothing + self:equip(nil, "left") + self:equip(nil, "right") + + self:equip("advancedperipherals:geo_scanner", "right") + self.scanner = peripheral.wrap("right") + + self:equip("computercraft:wireless_modem_advanced", "right") + self.modem = peripheral.wrap("right") + self.modem.open(CHANNEL) + + self.pos = vector.new(0, 0, 0) + self:doGPS(true) + + self:equip("advancedperipherals:chunk_controller", "left") + + self.i = 1 + return self +end + +function Miner:equip(item, side, nbt) + local e = self.equipped[side] + if item == e.last and nbt == e.lastNbt then + return + end + + assert(selectItem(item, nbt)) + e.fun() + e.last = item + e.lastNbt = nbt +end + +function Miner:sendMessage(type, msg) + self:equip("computercraft:wireless_modem_advanced", "right") + msg["type"] = type + msg["name"] = self.name + msg["pos"] = self.absolutePos + self.modem.transmit(CHANNEL, CHANNEL, msg) +end + +function Miner:dig(dir) + self:equip("minecraft:diamond_pickaxe", "right") + if dir == "up" then + assert(turtle.digUp()) + elseif dir == "forward" then + assert(turtle.dig()) + elseif dir == "down" then + assert(turtle.digDown()) + end +end + +function Miner:xchgItems() + local slots = {} + local emptySlots = 0 + for i = 1, 16 do + local info = turtle.getItemDetail(i) + if info then + assert(info.name) + if not BLACKLIST[info.name] then + slots[i] = info + end + else + emptySlots = emptySlots + 1 + end + end + + if emptySlots >= 2 and turtle.getFuelLevel() >= 1000 then + return + end + + if turtle.detectDown() then + self:dig("down") + end + + if emptySlots < 2 then + selectItem("enderchests:ender_chest") + assert(turtle.placeDown()) + + for i, info in pairs(slots) do + assert(turtle.select(i)) + assert(turtle.dropDown()) + end + self:dig("down") + end + + if turtle.getFuelLevel() < 1000 then + selectItem("functionalstorage:ender_drawer") + assert(turtle.placeDown()) + assert(turtle.suckDown()) + assert(turtle.refuel()) + self:dig("down") + end +end + +function Miner:safeMove(dir) + if dir == "up" then + while turtle.detectUp() do + self:dig("up") + end + assert(turtle.up()) + elseif dir == "forward" then + while turtle.detect() do + self:dig("forward") + end + assert(turtle.forward()) + else + if turtle.detectDown() then + self:dig("down") + end + assert(turtle.down()) + end +end + +function Miner:doGPS(orientation) + local x, y, z = gps.locate() + assert(x) + self.absolutePos = vector.new(x, y, z) + + if orientation then + assert(turtle.forward()) + x, y, z = gps.locate() + assert(x) + self.dir = vector.new(x, y, z) - self.absolutePos + assert(turtle.back()) + end +end + +function Miner:findOres(radius) + self:equip("advancedperipherals:geo_scanner", "right") + local info, err = self.scanner.scan(radius) + assert(info, err) + + local found = {} + for _, b in ipairs(info) do + -- only ores and avoid bedrock + if ORES[b.name] and self.absolutePos.y + b.y >= -58 then + table.insert(found, b) + end + end + return found +end + +function Miner:faceDir(newDir) + local deltaDir = direction(newDir) - direction(self.dir) + if deltaDir == 0.25 or deltaDir == -0.75 then + assert(turtle.turnRight()) + self.dir = newDir + elseif deltaDir == -0.25 or deltaDir == 0.75 then + assert(turtle.turnLeft()) + self.dir = newDir + elseif deltaDir == 0.5 or deltaDir == -0.5 then + assert(turtle.turnRight()) + assert(turtle.turnRight()) + self.dir = newDir + elseif deltaDir == 0 then + -- nothing to do :) + else + assert(false, "invalid delta dir "..deltaDir) + end +end + +function Miner:navigateThrough(path) + for _, p in ipairs(path) do + -- print("move from to", self.pos, p) + local delta = p - self.pos + assert(delta:length() ~= 0) + -- print("doing", delta) + if delta:length() ~= 1 then + -- print("path finding between points") + local path = findPath(self.pos, p) + table.remove(path, 1) + table.remove(path, #path) + assert(#path ~= 0) + + self:navigateThrough(path) + delta = p - self.pos + end + assert(delta:length() == 1) + + local moveDir = nil + if delta.y == 1 then + moveDir = "up" + elseif delta.y == -1 then + moveDir = "down" + else + self:faceDir(delta) + moveDir = "forward" + end + + self:safeMove(moveDir) + self.pos = p + self.absolutePos = self.absolutePos + delta + end +end + +function Miner:mineOres(radius) + local startingDir = self.dir + self.pos = vector.new(0, 0, 0) + + local ores = self:findOres(radius) + local orePoints = {} + for _, b in ipairs(ores) do + table.insert(orePoints, vector.new(b.x, b.y, b.z)) + end + local veins = groupOres(ores, findDistances(orePoints)) + print("Found "..#ores.." ores ("..#veins.." veins)") + + local veinsPoints = { + self.pos, + self.dir * radius * 2, + } + for _, v in ipairs(veins) do + table.insert(veinsPoints, v.center) + end + + local veinsPath = pathThrough(veinsPoints, findDistances(veinsPoints), 1, 2) + -- strip out end point + table.remove(veinsPath, #veinsPath) + + local veinsSummary = {} + for _, i in ipairs(veinsPath) do + local v = veins[i - 2] + table.insert(veinsSummary, { + pos = self.absolutePos + v.center, + type = v.type, + count = #v.blocks, + }) + end + self:sendMessage("iterationStart", { + i = self.i, + oreCount = #ores, + veins = veinsSummary, + }) + + for pi, i in ipairs(veinsPath) do + self:xchgItems() + + local vein = veins[i - 2] + local closest = nil + local cDist = math.huge + for _, b in ipairs(vein.blocks) do + local d = (b - self.pos):length() + if d < cDist then + closest = b + cDist = d + end + end + assert(closest) + + local pathToStart = findPath(self.pos, closest) + table.remove(pathToStart, 1) + table.remove(pathToStart, #pathToStart) + + print("Moving to vein of " .. #vein.blocks .. " " .. vein.type .. " " .. cDist .. " blocks away starting at", closest) + self:navigateThrough(pathToStart) + + local veinPoints = {self.pos} + for _, b in ipairs(vein.blocks) do + table.insert(veinPoints, b) + end + + local veinPathI = pathThrough(veinPoints, findDistances(veinPoints), 1) + local veinPath = {} + for _, i in ipairs(veinPathI) do + table.insert(veinPath, veinPoints[i]) + end + + print("Digging through vein (" .. #vein.blocks .. " blocks)") + self:sendMessage("veinStart", { + i = pi, + total = #veins, + oreType = vein.type, + oreCount = #vein.blocks, + }) + self:navigateThrough(veinPath) + end + + self:navigateThrough({veinsPoints[2]}) + self:faceDir(startingDir) + self.i = self.i + 1 +end + +local miner = Miner.new() +while true do + miner:mineOres(16) +end + + + + + + + + + + + +-- test code, please ignore +assert(false) + +-- local f, err = fs.open("points.csv", "w") +-- assert(f, err) + +local points = { + vector.new(0, 0, 0), + vector.new(0, 0, -16), +} +for _, b in ipairs(ores) do + -- print("found " .. b.name .. " at " .. b.x .. ", " .. b.y .. ", " .. b.z) + table.insert(points, vector.new(b.x, b.y, b.z)) +end +print("found "..#ores.." ores") + +local dist = findDistances(points) +local groups = groupOres(ores, dist, 2) + +for _, g in ipairs(groups) do + print("group of "..#g.blocks.." "..g.type.." at", g.center) +end +print(#groups, "groups of ore found") + +local gPoints = { + vector.new(0, 0, 0), + vector.new(0, 0, -16), +} +for _, g in ipairs(groups) do + table.insert(gPoints, g.center) +end + +local gDist = findDistances(gPoints) +local gPath = pathThrough(gPoints, gDist, 1, 2) +for _, i in ipairs(gPath) do + local p = gPoints[i] + f.write(p.x..","..p.y..","..p.z.."\n") +end + +f.write("MARK\n") + +-- print(points[1], gPoints[gPath[1]]) +-- local pathTo = findPath(points[1], gPoints[gPath[1]]) +-- for _, p in ipairs(pathTo) do +-- -- local p = pathTo[i] +-- -- print(p) +-- f.write(p.x..","..p.y..","..p.z.."\n") +-- end + +miner:mineOres(groups) + +-- table.remove(pathTo, 1) +-- table.remove(pathTo, #pathTo) +-- miner:navigateThrough(pathTo) + +-- f.write("MARK\n") + +-- local allPath = pathThrough(points, dist, 1, 2) +-- for _, i in ipairs(allPath) do +-- local p = points[i] +-- -- print(points[i]) +-- f.write(p.x..","..p.y..","..p.z.."\n") +-- end + +f.close() + +-- local f = vector.new(1, 0, 0) +-- local p = vector.new(0, -1, 7) +-- local t = vector.new(-1, -1, 7) + +-- print(direction(t - p) - direction(f)) diff --git a/mineMonitor.lua b/mineMonitor.lua new file mode 100644 index 0000000..37e347d --- /dev/null +++ b/mineMonitor.lua @@ -0,0 +1,185 @@ +local CHANNEL = 1337 +local TARGET = "devplayer0" +local ICON_BASE = "https://p.nul.ie/cc/icon/" +local ORE_ICONS = { + ["minecraft:coal_ore"] = "coal", + ["minecraft:deepslate_coal_ore"] = "ds-coal", + ["minecraft:iron_ore"] = "iron", + ["minecraft:deepslate_iron_ore"] = "ds-iron", + ["minecraft:copper_ore"] = "copper", + ["minecraft:deepslate_copper_ore"] = "ds-copper", + ["minecraft:gold_ore"] = "gold", + ["minecraft:deepslate_gold_ore"] = "ds-gold", + ["minecraft:redstone_ore"] = "redstone", + ["minecraft:deepslate_redstone_ore"] = "ds-redstone", + ["minecraft:emerald_ore"] = "emerald", + ["minecraft:deepslate_emerald_ore"] = "ds-emerald", + ["minecraft:lapis_ore"] = "lapis", + ["minecraft:deepslate_lapis_ore"] = "ds-lapis", + ["minecraft:diamond_ore"] = "diamond", + ["minecraft:deepslate_diamond_ore"] = "ds-diamond", + + -- ["create:ochrum"] =, + -- ["create:zinc_ore"] =, + -- ["create:deepslate_zinc_ore"] =, + -- ["create_new_age:thorium_ore"] =, + + -- ["powah:deepslate_uraninite_ore_poor"] =, + -- ["powah:deepslate_uraninite_ore"] =, + -- ["powah:deepslate_uraninite_ore_dense"] =, + -- ["powah:uraninite_ore_poor"] =, + -- ["powah:uraninite_ore"] =, + -- ["powah:uraninite_ore_dense"] =, +} + +function oreIcon(t) + local i = "generic" + if ORE_ICONS[t] then + i = ORE_ICONS[t] + end + + return ICON_BASE .. "ore-" .. i .. ".png" +end + +local modem = peripheral.find("modem") +-- local monitor = peripheral.find("monitor") +local chat = peripheral.find("chatBox") +local cartographer = peripheral.find("cartographer") + +function vecToStr(v) + return v.x .. "," .. v.y .. "," .. v.z +end + +function markerSet(msg) + return "autominer_" .. msg.name +end + +function setPosMarker(msg) + local id = markerSet(msg) + local mId = id .. "_pos" + cartographer.removeMarker(id, mId) + cartographer.addPOIMarker( + id, mId, msg.name, msg.name .. "'s position", + msg.pos.x, msg.pos.y, msg.pos.z, + ICON_BASE .. "turtle.png") +end + +function handleStart(msg) + local cMsg = { + {text = msg.name, color = "green"}, + {text = " @ ", color = "white"}, + {text = vecToStr(msg.pos), color = "aqua"}, + {text = " found ", color = "white"}, + {text = tostring(msg.oreCount), color = "red"}, + {text = " ores (", color = "white"}, + {text = tostring(#msg.veins), color = "red"}, + {text = " veins) on iteration ", color = "white"}, + {text = tostring(msg.i), color = "green"}, + {text = "!", color = "white"}, + } + local msgJSON = textutils.serializeJSON(cMsg) + chat.sendFormattedMessage(msgJSON, "AutoMine") + + local id = markerSet(msg) + cartographer.addMarkerSet(id, "AutoMiner " .. msg.name) + cartographer.clearMarkerSet(id) + + setPosMarker(msg) + + local orePoints = {} + for i, v in ipairs(msg.veins) do + table.insert(orePoints, v.pos) + cartographer.addPOIMarker( + id, id .. "_vein_" .. i, v.count .. " " .. v.type, "Vein of " .. v.count .. " " .. v.type, + v.pos.x, v.pos.y, v.pos.z, + oreIcon(v.type)) + end + + cartographer.addLineMarker( + id, id .. "_vein_path", "Mining path #" .. msg.i, "Current mining path", + "#FF00FF", 0.7, 3, + orePoints) +end + +function handleVein(msg) + local cMsg = { + {text = msg.name, color = "green"}, + {text = " @ ", color = "white"}, + {text = vecToStr(msg.pos), color = "aqua"}, + {text = " is mining ", color = "white"}, + {text = tostring(msg.oreCount), color = "red"}, + {text = " ", color = "white"}, + {text = msg.oreType, color = "dark_purple"}, + {text = " (vein ", color = "white"}, + {text = tostring(msg.i), color = "red"}, + {text = " / ", color = "white"}, + {text = tostring(msg.total), color = "red"}, + {text = ")!", color = "white"}, + } + local msgJSON = textutils.serializeJSON(cMsg) + chat.sendFormattedMessageToPlayer(msgJSON, TARGET, "AutoMine") + + local id = markerSet(msg) + setPosMarker(msg) + if msg.i ~= 1 then + cartographer.removeMarker(id, id .. "_vein_" .. (msg.i - 1)) + end +end + +cartographer.refreshIntegrations() + +modem.open(CHANNEL) + +-- handleStart({ +-- i = 69, +-- oreCount = 1337, +-- veins = { +-- { +-- pos = {x = 297, y = 124, z = 1935}, +-- type = "minecraft:coal_ore", +-- count = 12, +-- }, +-- { +-- pos = {x = 297, y = 134, z = 1935}, +-- type = "minecraft:iron_ore", +-- count = 7, +-- }, +-- { +-- pos = {x = 400, y = 134, z = 1935}, +-- type = "minecraft:diamond_ore", +-- count = 2, +-- }, +-- { +-- pos = {x = 400, y = 134, z = 1975}, +-- type = "minecraft:sussy_ore", +-- count = 7, +-- } +-- }, +-- name = "test", +-- pos = {x = 297, y = 154, z = 1935}, +-- }) +-- handleVein({ +-- i = 2, +-- total = 69, +-- oreCount = 1337, +-- oreType = "minecraft:yeet", +-- name = "test", +-- pos = {x = 1, y = 2, z = 3}, +-- }) +-- assert(false) + +while true do + local event, side, channel, replyChannel, msg, distance = os.pullEvent("modem_message") + if channel == CHANNEL then + if msg.type == "iterationStart" then + handleStart(msg) + -- sendChat(msg.name.." found "..msg.oreCount.." ores ("..msg.veinCount.." veins)") + -- for _, v in ipairs(msg.path) do + -- print("vein path "..v.x..", "..v.y..", "..v.z) + -- end + elseif msg.type == "veinStart" then + handleVein(msg) + -- sendChat(msg.name.." is mining "..msg.count.." "..msg.oreType.." (vein "..msg.i..") @ "..msg.pos.x..", "..msg.pos.y..", "..msg.pos.z) + end + end +end diff --git a/tree.lua b/tree.lua new file mode 100644 index 0000000..daf29aa --- /dev/null +++ b/tree.lua @@ -0,0 +1,134 @@ +local dirt = "minecraft:dirt" +local sapling = "minecraft:oak_sapling" +local meal = "minecraft:bone_meal" +local log = "minecraft:oak_log" +local apple = "minecraft:apple" +local stick = "minecraft:stick" +local items = { + sapling, meal, log, apple, stick +} + +local mealCount = 16 + +function selectItem(item) + for i = 1, 16 do + info = turtle.getItemDetail(i) + if info and info.name == item then + turtle.select(i) + return i + end + end +end + +Farmer = {} +function Farmer:new(invName) + local t = setmetatable({}, { __index = Farmer }) + t.invName = invName + return t +end + +function Farmer:connectInv() + local m = peripheral.find("modem") + self.mName= m.getNameLocal() + self.inv = peripheral.wrap(self.invName) +end + +function Farmer:unload(item) + for i = 1, 16 do + info = turtle.getItemDetail(i) + if info and info.name == item then + -- print(item, self.mName, i) + self.inv.pullItems(self.mName, i) + sleep(0.5) + end + end +end + +function Farmer:yoink(item, count) + for i, info in pairs(self.inv.list()) do + if info.name == item then + if info.count >= count then + self.inv.pushItems(self.mName, i, count) + sleep(0.5) + return true + end + end + end + + return false +end + +function Farmer:farmTree(noMeal) + assert(turtle.turnRight()) + assert(turtle.turnRight()) + assert(turtle.forward()) + assert(turtle.forward()) + assert(turtle.down()) + + assert(selectItem(dirt)) + assert(turtle.place()) + assert(turtle.up()) + assert(selectItem(sapling)) + assert(turtle.place()) + + if noMeal then + while true do + local present, info = turtle.inspect() + assert(present) + if info.name == log then + break + end + sleep(20) + end + else + assert(selectItem(meal)) + local grown = false + for i = 1, mealCount do + turtle.place() + sleep(1) + local present, info = turtle.inspect() + assert(present) + if info.name == log then + grown = true + break + end + end + if not grown then + assert(false, "failed to grow tree") + end + end + + turtle.select(1) + assert(turtle.dig()) + assert(turtle.down()) + assert(turtle.dig()) + assert(turtle.up()) + sleep(5) + assert(turtle.down()) + for i = 1, 8 do + sleep(0.5) + turtle.suck() + end + + assert(turtle.up()) + assert(turtle.turnRight()) + assert(turtle.turnRight()) + assert(turtle.forward()) + assert(turtle.forward()) + sleep(0.5) +end + +function Farmer:xchgItems() + self:connectInv() + for _, i in pairs(items) do + self:unload(i) + end + assert(self:yoink(sapling, 1)) + return self:yoink(meal, mealCount) +end + +local f = Farmer:new("ae2:interface_0") +while true do + local noMeal = not f:xchgItems() + f:farmTree(noMeal) +end