tClearChunky.lua

331 lines · 9.3 KB

Open raw

{program="tClearChunky",version="1.0",date="2024-10-22"}

Copy & run

wget https://perlytiara.github.io/turtles.tips/raw/programs/perlytiara/tClear/tClearChunky.lua
1--{program="tClearChunky",version="1.0",date="2024-10-22"}
2---------------------------------------
3-- tClearChunky by Kaikaku
4-- 2024-10-22, v1.0 chunky wireless turtle
5---------------------------------------
6
7---------------------------------------
8---- DESCRIPTION ----------------------
9---------------------------------------
10-- Chunky wireless turtle that pairs with a main mining turtle
11-- to keep chunks loaded and prevent the main turtle from breaking
12-- due to chunk unloading. Follows the main turtle's movements.
13
14---------------------------------------
15---- ASSUMPTIONS ----------------------
16---------------------------------------
17-- Requires a wireless modem for communication
18-- Should be placed one block to the right of the main turtle
19
20---------------------------------------
21---- VARIABLES: template --------------
22---------------------------------------
23local cVersion ="v1.0"
24local cPrgName ="tClearChunky"
25local blnDebugPrint = true
26
27---------------------------------------
28---- VARIABLES: specific --------------
29---------------------------------------
30local masterTurtleId = nil
31local chunkLoadingInterval = 2 -- seconds between chunk loading signals
32local position = {x = 0, y = 0, z = -1, facing = 0} -- relative to master (to the left)
33local isActive = false
34
35---------------------------------------
36---- Communication functions -----------
37---------------------------------------
38local function findModem()
39 for _, p in pairs(rs.getSides()) do
40 if peripheral.isPresent(p) and peripheral.getType(p) == "modem" then
41 return p
42 end
43 end
44 error("No wireless modem attached to this turtle.")
45end
46
47local function sendChunkLoad()
48 if masterTurtleId then
49 rednet.send(masterTurtleId, {
50 type = "chunk_load",
51 id = os.getComputerID(),
52 position = position,
53 timestamp = os.time()
54 }, "tclear-chunky")
55 end
56end
57
58local function sendStatus(status, data)
59 if masterTurtleId then
60 rednet.send(masterTurtleId, {
61 type = "status",
62 status = status,
63 id = os.getComputerID(),
64 data = data or {},
65 timestamp = os.time()
66 }, "tclear-chunky")
67 end
68end
69
70---------------------------------------
71---- Movement functions ---------------
72---------------------------------------
73local function moveTo(targetX, targetY, targetZ, targetFacing)
74 -- Calculate relative movement needed from current position to target
75 local dx = targetX - position.x
76 local dy = targetY - position.y
77 local dz = targetZ - position.z
78 local dfacing = (targetFacing - position.facing) % 4
79
80 debugPrint("Moving from (" .. position.x .. "," .. position.y .. "," .. position.z .. ") to (" .. targetX .. "," .. targetY .. "," .. targetZ .. ")")
81 debugPrint("Delta: dx=" .. dx .. " dy=" .. dy .. " dz=" .. dz .. " dfacing=" .. dfacing)
82
83 -- Turn to correct facing first
84 if dfacing == 1 then
85 turtle.turnRight()
86 position.facing = (position.facing + 1) % 4
87 elseif dfacing == 2 then
88 turtle.turnRight()
89 turtle.turnRight()
90 position.facing = (position.facing + 2) % 4
91 elseif dfacing == 3 then
92 turtle.turnLeft()
93 position.facing = (position.facing - 1) % 4
94 end
95
96 -- Move vertically first
97 while dy > 0 do
98 if turtle.up() then
99 dy = dy - 1
100 position.y = position.y + 1
101 debugPrint("Moved up to y=" .. position.y)
102 else
103 debugPrint("Cannot move up, blocked")
104 break
105 end
106 end
107 while dy < 0 do
108 if turtle.down() then
109 dy = dy + 1
110 position.y = position.y - 1
111 debugPrint("Moved down to y=" .. position.y)
112 else
113 debugPrint("Cannot move down, blocked")
114 break
115 end
116 end
117
118 -- Move horizontally - handle X movement (forward/backward relative to facing)
119 while dx > 0 do
120 -- Try to dig if blocked, but don't get stuck
121 if not turtle.forward() then
122 debugPrint("Blocked, trying to dig forward")
123 turtle.dig()
124 sleep(0.1) -- Brief pause after digging
125 if turtle.forward() then
126 dx = dx - 1
127 position.x = position.x + 1
128 debugPrint("Moved forward to x=" .. position.x)
129 else
130 debugPrint("Still blocked after digging, giving up")
131 break
132 end
133 else
134 dx = dx - 1
135 position.x = position.x + 1
136 debugPrint("Moved forward to x=" .. position.x)
137 end
138 end
139 while dx < 0 do
140 -- Turn around to move backward
141 turtle.turnLeft()
142 turtle.turnLeft()
143 if not turtle.forward() then
144 debugPrint("Blocked, trying to dig backward")
145 turtle.dig()
146 sleep(0.1)
147 if turtle.forward() then
148 dx = dx + 1
149 position.x = position.x - 1
150 debugPrint("Moved backward to x=" .. position.x)
151 else
152 debugPrint("Still blocked after digging backward, giving up")
153 end
154 else
155 dx = dx + 1
156 position.x = position.x - 1
157 debugPrint("Moved backward to x=" .. position.x)
158 end
159 turtle.turnLeft()
160 turtle.turnLeft()
161 if dx < 0 then break end -- If still can't move, give up
162 end
163
164 -- Move sideways - handle Z movement (left/right relative to facing)
165 while dz > 0 do
166 turtle.turnRight()
167 if not turtle.forward() then
168 debugPrint("Blocked, trying to dig right")
169 turtle.dig()
170 sleep(0.1)
171 if turtle.forward() then
172 dz = dz - 1
173 position.z = position.z + 1
174 debugPrint("Moved right to z=" .. position.z)
175 else
176 debugPrint("Still blocked after digging right")
177 end
178 else
179 dz = dz - 1
180 position.z = position.z + 1
181 debugPrint("Moved right to z=" .. position.z)
182 end
183 turtle.turnLeft()
184 if dz > 0 then break end -- If still can't move, give up
185 end
186 while dz < 0 do
187 turtle.turnLeft()
188 if not turtle.forward() then
189 debugPrint("Blocked, trying to dig left")
190 turtle.dig()
191 sleep(0.1)
192 if turtle.forward() then
193 dz = dz + 1
194 position.z = position.z - 1
195 debugPrint("Moved left to z=" .. position.z)
196 else
197 debugPrint("Still blocked after digging left")
198 end
199 else
200 dz = dz + 1
201 position.z = position.z - 1
202 debugPrint("Moved left to z=" .. position.z)
203 end
204 turtle.turnRight()
205 if dz < 0 then break end -- If still can't move, give up
206 end
207
208 -- Update final facing
209 position.facing = targetFacing
210 debugPrint("Final position: (" .. position.x .. "," .. position.y .. "," .. position.z .. ") facing=" .. position.facing)
211end
212
213---------------------------------------
214---- Main functions --------------------
215---------------------------------------
216local function debugPrint(str)
217 if blnDebugPrint then
218 print("[Chunky] " .. str)
219 end
220end
221
222local function processMessage(message)
223 if message.type == "find_chunky" then
224 -- Master turtle is looking for chunky turtles
225 print("Master turtle " .. (message.masterId or "unknown") .. " is looking for chunky turtles")
226 -- Send response
227 rednet.send(message.masterId, {
228 type = "chunky_available",
229 id = os.getComputerID(),
230 timestamp = os.time()
231 }, "tclear-chunky")
232 print("Sent response to master turtle")
233 return true
234
235 elseif message.type == "pair" then
236 masterTurtleId = message.masterId
237 isActive = true
238 print("SUCCESS: Paired with master turtle " .. masterTurtleId)
239 print("Chunky turtle is now active and ready to follow!")
240 sendStatus("paired", {chunkyId = os.getComputerID()})
241 return true
242
243 elseif message.type == "move" then
244 if isActive and message.target then
245 debugPrint("Moving to " .. message.target.x .. "," .. message.target.y .. "," .. message.target.z)
246 moveTo(message.target.x, message.target.y, message.target.z, message.target.facing or 0)
247 sendStatus("moved", {position = position})
248 return true
249 end
250
251 elseif message.type == "stop" then
252 isActive = false
253 debugPrint("Stopped by master turtle")
254 sendStatus("stopped", {})
255 return true
256
257 elseif message.type == "ping" then
258 sendStatus("alive", {position = position})
259 return true
260 end
261
262 return false
263end
264
265---------------------------------------
266---- Main program ----------------------
267---------------------------------------
268
269-- Initialize
270local modemSide = findModem()
271rednet.open(modemSide)
272
273local thisId = os.getComputerID()
274print("tClearChunky v" .. cVersion .. " starting...")
275print("Chunky turtle ID: " .. thisId)
276print("Waiting for pairing with master turtle...")
277
278-- Send initial broadcast to find master
279rednet.broadcast({
280 type = "chunky_available",
281 id = thisId,
282 timestamp = os.time()
283}, "tclear-chunky")
284
285print("Sent initial broadcast - waiting for master turtle...")
286
287-- Main loop
288local lastChunkLoad = 0
289local lastBroadcast = 0
290local broadcastInterval = 5 -- Send broadcast every 5 seconds
291
292while true do
293 local timer = os.startTimer(0.1) -- Check for messages every 0.1 seconds
294
295 -- Handle rednet messages
296 local senderId, message, protocol = rednet.receive(0.1)
297 if senderId then
298 -- Accept messages on multiple protocols
299 if protocol == "tclear-chunky" or protocol == "tclear-run" or protocol == "tclear" or protocol == nil then
300 local handled = processMessage(message)
301 if handled then
302 print("Processed message from " .. senderId)
303 end
304 end
305 end
306
307 -- Send chunk loading signal periodically
308 local currentTime = os.time()
309 if isActive and (currentTime - lastChunkLoad) >= chunkLoadingInterval then
310 sendChunkLoad()
311 lastChunkLoad = currentTime
312 end
313
314 -- Send periodic broadcasts if not paired yet
315 if not isActive and (currentTime - lastBroadcast) >= broadcastInterval then
316 rednet.broadcast({
317 type = "chunky_available",
318 id = thisId,
319 timestamp = currentTime
320 }, "tclear-chunky")
321 print("Sent broadcast - still waiting for master turtle...")
322 lastBroadcast = currentTime
323 end
324
325 -- Handle timer events (cleanup)
326 local event, timerId = os.pullEvent("timer")
327 if timerId == timer then
328 -- Timer expired, continue loop
329 end
330end
331