SHOW:
|
|
- or go back to the newest paste.
1 | --[[ | |
2 | HPWebcamAble presents... | |
3 | ControlMe | |
4 | ||
5 | --=== Description ===-- | |
6 | This program lets you control a turtle from a pocket computer! | |
7 | ||
8 | This version of the program is for the POCKET COMPUTER | |
9 | Get the Turtle version here: pastebin.com/zjn3E5LS | |
10 | ||
11 | ||
12 | --=== Installation ===-- | |
13 | Pastebin Code: mTGccYbM | |
14 | ||
15 | To download a file from pastebin, run this command in a computer: | |
16 | pastebin get <code> <file name> | |
17 | ||
18 | ||
19 | --=== Update History ===-- | |
20 | The pastebin will always have the most recent version | |
21 | ||
22 | |1.0| | |
23 | -Release | |
24 | ]] | |
25 | ||
26 | --=== Variables ===-- | |
27 | local args = {...} | |
28 | local protocalName = "controlme" | |
29 | local turtleID | |
30 | local w,h = term.getSize() | |
31 | local tools = {} | |
32 | local knownTools = { | |
33 | ["modem"] = {text = "Modem", upAndDown = false}, | |
34 | ["minecraft:diamond_pickaxe"] = {text = "Mine", upAndDown = true, action = "turtle.dig"}, | |
35 | ["minecraft:diamond_sword"] = {text = "Attack", upAndDown = true, action = "turtle.attack"}, | |
36 | ["minecraft:diamond_hoe"] = {text = "Hoe", upAndDown = true, action = "turtle.dig"}, | |
37 | ["minecraft:diamond_axe"] = {text = "Chop", upAndDown = true, action = "turtle.dig"}, | |
38 | ["minecraft:diamond_shovel"] = {text = "Dig", upAndDown = true, action = "turtle.dig"} | |
39 | } | |
40 | local turtleImage = [[ffffffffff | |
41 | f77777777f | |
42 | f77ffff77f | |
43 | f77777777f | |
44 | f88888888f | |
45 | f88888888f | |
46 | ffffffffff | |
47 | ]] | |
48 | local inventoryImage = [[77777777777777777 | |
49 | 78887888788878887 | |
50 | 78887888788878887 | |
51 | 77777777777777777 | |
52 | 78887888788878887 | |
53 | 78887888788878887 | |
54 | 77777777777777777 | |
55 | 78887888788878887 | |
56 | 78887888788878887 | |
57 | 77777777777777777 | |
58 | 78887888788878887 | |
59 | 78887888788878887 | |
60 | 77777777777777777 | |
61 | ]] | |
62 | ||
63 | -- Load Images | |
64 | do | |
65 | local f = fs.open("temp","w") f.write(turtleImage) f.close() | |
66 | turtleImage = paintutils.loadImage("temp") | |
67 | f = fs.open("temp","w") f.write(inventoryImage) f.close() | |
68 | inventoryImage = paintutils.loadImage("temp") fs.delete("temp") | |
69 | end | |
70 | ||
71 | --=== Functions ===-- | |
72 | local function color(text,back) | |
73 | local temp = text and term.setTextColor(text) or nil | |
74 | temp = back and term.setBackgroundColor(back) or nil | |
75 | end | |
76 | ||
77 | local function printC(text,y) | |
78 | if type(text) ~= "string" or type(y) ~= "number" then error("expected string,number, got "..type(text)..","..type(y),2) end | |
79 | local lenght = #text | |
80 | local start = math.floor((w-lenght)/2)+1 | |
81 | term.setCursorPos(start,y) | |
82 | term.write(text) | |
83 | return start,start+lenght | |
84 | end | |
85 | ||
86 | -- These functions are from my Screen API | |
87 | -- http://pastebin.com/4j4mJsWw | |
88 | local default = { | |
89 | object = { | |
90 | text = nil, | |
91 | name = "default", | |
92 | minX = 1,minY = 1, | |
93 | maxX = 7,maxY = 3, | |
94 | states = { | |
95 | on = {text = colors.white, back = colors.lime}, | |
96 | off = {text = colors.white, back = colors.red} | |
97 | }, | |
98 | clickable = false, | |
99 | visible = true, | |
100 | state = "off", | |
101 | action = nil | |
102 | }, | |
103 | clickArea = { | |
104 | name = "default", | |
105 | minX = 1,minY = 1, | |
106 | maxX = 5,maxY = 3, | |
107 | clickable = true, | |
108 | action = nil | |
109 | } | |
110 | } | |
111 | ||
112 | local function fillTable(toFill,fillWith) --Used by the API | |
113 | if toFill == nil then toFill = {} end | |
114 | for a,b in pairs(fillWith) do | |
115 | if type(b) == "table" then | |
116 | toFill[a] = fillTable(toFill[a],b) | |
117 | else | |
118 | toFill[a] = toFill[a]==nil and b or toFill[a] | |
119 | end | |
120 | end | |
121 | return toFill | |
122 | end | |
123 | ||
124 | local function countIndexes(tbl) --Also used by API | |
125 | local total = 0 | |
126 | for a,b in pairs(tbl) do total = total+1 end | |
127 | return total | |
128 | end | |
129 | ||
130 | local function assert(check,err,lvl) | |
131 | lvl = lvl or 2 | |
132 | if not check then error(err,lvl+1) end | |
133 | return check | |
134 | end | |
135 | ||
136 | function new(nBackground) | |
137 | local api = {} | |
138 | local objects = {} | |
139 | local clickAreas = {} | |
140 | local background = nBackground | |
141 | ||
142 | function api.checkPos(x,y) | |
143 | x,y = tonumber(x),tonumber(y) | |
144 | assert(x and y,"expected number,number") | |
145 | for name,data in pairs(clickAreas) do | |
146 | if x >= data.minX and x <= data.maxX and y >= data.minY and y <= data.maxY and data.clickable then | |
147 | if type(data.action)=="function" then return true,true,data.action() | |
148 | else return true,false,"click_area",name end | |
149 | end | |
150 | end | |
151 | for name,data in pairs(objects) do | |
152 | if data.clickable and data.visible and x >= data.minX and x <= data.maxX and y >= data.minY and y <= data.maxY then | |
153 | if type(data.action)=="function" then return true,true,data.action() | |
154 | else return true,false,"object",name end | |
155 | end | |
156 | end | |
157 | return false | |
158 | end | |
159 | ||
160 | function api.handleEvents(bUseRaw) | |
161 | local pull = bUseRaw and os.pullEventRaw or os.pullEvent | |
162 | local event = {pull()} | |
163 | if event[1] == "mouse_click" then | |
164 | local wasElement,hadFunction,elementType,name = api.checkPos(event[3],event[4]) | |
165 | if wasElement then | |
166 | if not hadFunction then | |
167 | return elementType,name,event[2] | |
168 | else return nil | |
169 | end | |
170 | end | |
171 | end | |
172 | return unpack(event) | |
173 | end | |
174 | ||
175 | function api.setDefaultObject(newDefaultObject) | |
176 | assert(type(newDefaultObject)=="table","expected table, got "..type(newDefaultObject)) | |
177 | default.object = fillTable(newDefaultObject,default.object) | |
178 | end | |
179 | ||
180 | function api.setDefaultClickArea(newDefaultClickArea) | |
181 | assert(type(newDefaultClickArea)=="table","expected table, got "..type(newDefaultClickArea)) | |
182 | default.clickArea = fillTable(newDefaultClickArea,default.clickArea) | |
183 | end | |
184 | ||
185 | function api.draw() | |
186 | if background then term.setBackgroundColor(background) term.clear() end | |
187 | for name,data in pairs(objects) do | |
188 | api.drawObject(name) | |
189 | end | |
190 | end | |
191 | ||
192 | function api.addClickArea(clickAreaInfo) | |
193 | assert(type(clickAreaInfo)=="table","expected table, got "..type(clickAreaInfo)) | |
194 | fillTable(clickAreaInfo,default.clickArea) | |
195 | assert(clickAreas[clickAreaInfo.name]==nil,"an object with the name '"..clickAreaInfo.name.."' already exists") | |
196 | clickAreas[clickAreaInfo.name] = clickAreaInfo | |
197 | end | |
198 | ||
199 | function api.toggleClickArea(name) | |
200 | assert(clickAreas[name]~=nil,"Click Area '"..name.."' doesn't exist") | |
201 | clickAreas[name].clickable = not clickAreas[name].clickable | |
202 | return clickAreas[name].clickable | |
203 | end | |
204 | ||
205 | function api.getClickArea(name) | |
206 | assert(clickAreas[name]~=nil,"Click Area '"..name.."' doesn't exist") | |
207 | return clickAreas[name] | |
208 | end | |
209 | ||
210 | function api.addObject(objectInfo) | |
211 | assert(type(objectInfo)=="table","expected table, got "..type(objectInfo)) | |
212 | objectInfo = fillTable(objectInfo,default.object) | |
213 | assert(objects[objectInfo.name]==nil,"an object with the name '"..objectInfo.name.."' already exists") | |
214 | objects[objectInfo.name] = objectInfo | |
215 | end | |
216 | ||
217 | function api.drawObject(name) | |
218 | assert(objects[name]~=nil,"Object '"..name.."' doesn't exsist") | |
219 | local objData = objects[name] | |
220 | if objData.visible == false then return end | |
221 | assert(objData.states~=nil,"Object '"..name.."' has no states!") | |
222 | assert(objData.states[objData.state],"Object '"..name.."' doesn't have state '"..objData.state.."'") | |
223 | term.setBackgroundColor(objData.states[objData.state].back) | |
224 | term.setTextColor(objData.states[objData.state].text) | |
225 | for i = 0, objData.maxY-objData.minY do | |
226 | term.setCursorPos(objData.minX,objData.minY+i) | |
227 | term.write(string.rep(" ",objData.maxX-objData.minX+1)) | |
228 | end | |
229 | if objData.text then | |
230 | local xPos = objData.minX+math.floor(((objData.maxX-objData.minX+1)-#objData.text)/2) | |
231 | local yPos = objData.minY+(objData.maxY-objData.minY)/2 | |
232 | term.setCursorPos(xPos,yPos) term.write(objData.text) | |
233 | end | |
234 | end | |
235 | ||
236 | function api.toggleObjectState(name) -- Only works if an object has two states | |
237 | assert(objects[name]~=nil,"Object '"..name.."' doesn't exist") | |
238 | assert(countIndexes(objects[name].states)==2,"Object '"..name.."' can't be toggled, it doesn't have two states") | |
239 | curState = objects[name].state | |
240 | for a,b in pairs(objects[name].states) do | |
241 | if a ~= curState then | |
242 | objects[name].state = a | |
243 | end | |
244 | end | |
245 | return objects[name].state | |
246 | end | |
247 | ||
248 | function api.setObjectState(name,state) | |
249 | assert(objects[name] ~= nil,"Object '"..name.."' doesn't exist") | |
250 | assert(objects[name].states[state],"Object '"..name.."' doesn't have state '"..state.."'") | |
251 | objects[name].state = state | |
252 | end | |
253 | ||
254 | function api.getObject(name) | |
255 | assert(objects[name] ~= nil,"Object '"..name.."' doesn't exist") | |
256 | return objects[name] | |
257 | end | |
258 | ||
259 | function api.toggleObjectVisible(name) | |
260 | assert(objects[name] ~= nil,"Object '"..name.."' doesn't exist") | |
261 | objects[name].visible = not objects[name].visible | |
262 | return objects[name].visible | |
263 | end | |
264 | ||
265 | function api.toggleObjectClickable(name) | |
266 | assert(objects[name] ~= nil,"Object '"..name.."' doesn't exist") | |
267 | objects[name].clickable = not objects[name].clickable | |
268 | return objects[name].clickable | |
269 | end | |
270 | ||
271 | return api | |
272 | end | |
273 | -- End Screen API | |
274 | ||
275 | local function checkMessage(event,skipTableCheck,skipIDCheck) | |
276 | return event[4] == protocalName and (skipTableCheck or type(event[3]) == "table") and (skipIDCheck or event[2] == turtleID) | |
277 | end | |
278 | ||
279 | local function message(message) | |
280 | rednet.send(turtleID,message,protocalName) | |
281 | end | |
282 | ||
283 | local function broadcast(message) | |
284 | rednet.broadcast(message,protocalName) | |
285 | end | |
286 | ||
287 | local function execute(func,waitTime) | |
288 | message({action="execute",func=func}) | |
289 | local timer = waitTime and os.startTimer(waitTime) or "done" | |
290 | local completed = false | |
291 | while true do | |
292 | local event = {os.pullEvent()} | |
293 | if event[1] == "rednet_message" and checkMessage(event) and event[3].action == "completed" then | |
294 | if timer == "done" then return event[3].result | |
295 | else completed = true end | |
296 | elseif event[1] == "timer" and timer == event[2] then | |
297 | if completed then break | |
298 | else timer = "done" end | |
299 | end | |
300 | end | |
301 | end | |
302 | ||
303 | local function getModem() | |
304 | for a,b in pairs(rs.getSides()) do | |
305 | if peripheral.getType(b) == "modem" and peripheral.call(b,"isWireless") then | |
306 | return b | |
307 | end | |
308 | end | |
309 | end | |
310 | ||
311 | local function waitForMessage(skipTableCheck,skipIDCheck) | |
312 | while true do | |
313 | local event = {os.pullEvent("rednet_message")} | |
314 | if checkMessage(event,skipTableCheck,skipIDCheck) then | |
315 | return event[3] | |
316 | end | |
317 | end | |
318 | end | |
319 | ||
320 | -- Create the screen | |
321 | local mainScreen = new() | |
322 | ||
323 | local function action(buttonName,func,waitTime) | |
324 | mainScreen.getObject(buttonName).state = "active" mainScreen.drawObject(buttonName) | |
325 | execute(func,waitTime or 0.5) | |
326 | mainScreen.getObject(buttonName).state = "on" mainScreen.drawObject(buttonName) | |
327 | end | |
328 | ||
329 | local function forward() | |
330 | action("forward","turtle.forward()") | |
331 | end | |
332 | ||
333 | local function turnLeft() | |
334 | action("turnLeft","turtle.turnLeft()") | |
335 | end | |
336 | ||
337 | local function turnRight() | |
338 | action("turnRight","turtle.turnRight()") | |
339 | end | |
340 | ||
341 | local function back() | |
342 | action("back","turtle.back()") | |
343 | end | |
344 | ||
345 | local function up() | |
346 | action("up","turtle.up()") | |
347 | end | |
348 | ||
349 | local function down() | |
350 | action("down","turtle.down()") | |
351 | end | |
352 | ||
353 | local drawMainScreen | |
354 | ||
355 | local function options() | |
356 | -- Silly animition that I love so please don't question it | |
357 | for i = 0, 12 do | |
358 | color(colors.white,colors.blue) term.clear() | |
359 | paintutils.drawImage(turtleImage,9,7-(i/2)) | |
360 | color(colors.white,colors.green) term.setCursorPos(1,h-i) term.clearLine() printC("Options",h-i) | |
361 | color(colors.white,colors.brown) | |
362 | for a = 0, i-1 do | |
363 | term.setCursorPos(1,h-a) term.clearLine() | |
364 | end | |
365 | sleep(0.1) | |
366 | end | |
367 | ||
368 | color(colors.black,colors.lightGray) | |
369 | printC(" ",10) | |
370 | printC(" Disconnect ",11) | |
371 | printC(" and Exit ",12) | |
372 | printC(" ",13) | |
373 | printC(" ",15) | |
374 | printC(" Back ",16) | |
375 | printC(" ",17) | |
376 | ||
377 | while true do | |
378 | local event = {os.pullEvent("mouse_click")} | |
379 | if event[4] == 10 or event[4] == 11 or event[4] == 12 or event[4] == 1 then | |
380 | error() | |
381 | elseif event[4] == 16 or event[4] == 15 or event[4] == 17 then | |
382 | break | |
383 | end | |
384 | end | |
385 | ||
386 | for i = 12, 0, -1 do | |
387 | color(colors.white,colors.blue) term.clear() | |
388 | paintutils.drawImage(turtleImage,9,7-(i/2)) | |
389 | color(colors.white,colors.green) term.setCursorPos(1,h-i) term.clearLine() printC("Options",h-i) | |
390 | color(colors.white,colors.brown) | |
391 | for a = 0, i-1 do | |
392 | term.setCursorPos(1,h-a) term.clearLine() | |
393 | end | |
394 | sleep(0.1) | |
395 | end | |
396 | drawMainScreen() | |
397 | end | |
398 | ||
399 | -- Add buttons | |
400 | --mainScreen.addObject({name="inventory", minX=10, maxY=12, state="default", maxX=17, clickable=false, visible=true, states={default={text=1,back=256,},}, minY=11, text="View Inv", }) | |
401 | mainScreen.addObject({name="turnRight", minX=20, maxY=18, state="on", maxX=25, clickable=true, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, minY=16, text="Turn R", action=turnRight}) | |
402 | mainScreen.addObject({name="actionLeft", minX=20, maxY=11, state="on", maxX=26, clickable=false, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, text="No Tool", minY=9, }) | |
403 | mainScreen.addObject({name="turnLeft", minX=2, maxY=18, state="on", maxX=7, clickable=true, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, minY=16, text="Turn L", action=turnLeft}) | |
404 | mainScreen.addObject({name="actionRightDown", minX=3, maxY=13, state="on", maxX=7, clickable=false, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, minY=13, text="v", }) | |
405 | mainScreen.addObject({name="actionRight", minX=1, maxY=11, state="on", maxX=7, clickable=false, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, minY=9, text="No Tool", }) | |
406 | mainScreen.addObject({name="back", minX=9, maxY=17, state="on", maxX=18, clickable=true, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, minY=15, text="Backward", action=back}) | |
407 | mainScreen.addObject({minY=20, minX=1, state="default", maxY=20, maxX=26, clickable=true, visible=true, states={default={text=1,back=8192,},}, name="options", text="Options", action = options}) | |
408 | mainScreen.addObject({name="actionRightUp", minX=3, maxY=7, state="on", maxX=7, clickable=true, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, minY=7, text="^", }) | |
409 | mainScreen.addObject({name="actionLeftDown", minX=20, maxY=13, state="on", maxX=24, clickable=false, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, text="v", minY=13, }) | |
410 | mainScreen.addObject({name="down", minX=20, maxY=4, state="on", maxX=25, clickable=true, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, text="Down", minY=2, action=down}) | |
411 | mainScreen.addObject({name="up", minX=2, maxY=4, state="on", maxX=7, clickable=true, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, text="Up", minY=2, action=up}) | |
412 | mainScreen.addObject({name="actionLeftUp", minX=20, maxY=7, state="on", maxX=24, clickable=false, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, text="^", minY=7, }) | |
413 | mainScreen.addObject({name="forward", minX=9, maxY=5, state="on", maxX=18, clickable=true, visible=true, states={off={text=1,back=256,},on={text=32768,back=1,},active={text=1,back=32,},}, minY=3, text="Forward", action=forward}) | |
414 | -- Function to draw the screen | |
415 | drawMainScreen = function() | |
416 | color(nil,colors.blue) term.clear() | |
417 | paintutils.drawImage(turtleImage,9,7) | |
418 | mainScreen.draw() | |
419 | end | |
420 | ||
421 | local function getFreeSlot() | |
422 | for i = 1, 16 do | |
423 | local result = execute("turtle.getItemCount("..i..")") | |
424 | if result == 0 then | |
425 | return i | |
426 | end | |
427 | end | |
428 | return false | |
429 | end | |
430 | ||
431 | local function showToolName(name,side) | |
432 | local obj = mainScreen.getObject("action"..side) | |
433 | local up = mainScreen.getObject("action"..side.."Up") | |
434 | local down = mainScreen.getObject("action"..side.."Down") | |
435 | if knownTools[name] then | |
436 | obj.text = knownTools[name].text | |
437 | obj.state = "on" | |
438 | obj.clickable = true | |
439 | if knownTools[name].action then | |
440 | obj.action = function() action("action"..side,knownTools[ tools.left ].action.."()",0.2) end | |
441 | end | |
442 | mainScreen.drawObject("action"..side) | |
443 | if knownTools[name].upAndDown then | |
444 | up.state = "on" | |
445 | up.clickable = true | |
446 | up.action = function() action("action"..side.."Up",knownTools[name].action.."Up()",0.2) end | |
447 | down.state = "on" | |
448 | down.clickable = true | |
449 | down.action = function() action("action"..side.."Down",knownTools[name].action.."Down()",0.2) end | |
450 | mainScreen.drawObject("action"..side.."Up") | |
451 | mainScreen.drawObject("action"..side.."Down") | |
452 | else | |
453 | up.state = "off" | |
454 | up.clickable = false | |
455 | down.state = "off" | |
456 | down.clickable = false | |
457 | mainScreen.drawObject("action"..side.."Up") | |
458 | mainScreen.drawObject("action"..side.."Down") | |
459 | end | |
460 | else | |
461 | obj.text = name=="none" and "No Tool" or "?" | |
462 | obj.state ="off" | |
463 | obj.clickable = false | |
464 | mainScreen.drawObject("action"..side) | |
465 | up.state = "off" | |
466 | up.clickable = false | |
467 | down.state = "off" | |
468 | down.clickable = false | |
469 | mainScreen.drawObject("action"..side.."Up") | |
470 | mainScreen.drawObject("action"..side.."Down") | |
471 | end | |
472 | end | |
473 | ||
474 | local function getLeftTool() | |
475 | message({action="getLeftTool"}) | |
476 | while true do | |
477 | local msg = waitForMessage() | |
478 | if msg.action == "getLeftTool" then | |
479 | tools.left = msg.result | |
480 | return msg.result | |
481 | end | |
482 | end | |
483 | end | |
484 | ||
485 | local function getRightTool() | |
486 | message({action="getRightTool"}) | |
487 | while true do | |
488 | local msg = waitForMessage() | |
489 | if msg.action == "getRightTool" then | |
490 | tools.right = msg.result | |
491 | return msg.result | |
492 | end | |
493 | end | |
494 | end | |
495 | ||
496 | local function detectTools() | |
497 | showToolName(getRightTool(),"Right") | |
498 | showToolName(getLeftTool(),"Left") | |
499 | end | |
500 | ||
501 | --=== Program ===-- | |
502 | if not pocket then | |
503 | printError("This program requires a pocket computer!") | |
504 | return | |
505 | elseif args[1] == "help" then | |
506 | print("ControlMe") | |
507 | print("By HPWebcamAble") | |
508 | print("") | |
509 | print("Use this program to remotly control your turtle!") | |
510 | print("Start this program on your pockect computer and the corresponding program on a turtle and control away!") | |
511 | end | |
512 | ||
513 | do | |
514 | local modemSide = getModem() | |
515 | if modemSide then | |
516 | rednet.open(modemSide) | |
517 | else | |
518 | printError("This program requires a wireless modem") | |
519 | return | |
520 | end | |
521 | end | |
522 | ||
523 | local continue = true | |
524 | while continue do | |
525 | color(colors.white,colors.black) term.clear() | |
526 | printC("Enter your Turtle's ID:",5) | |
527 | term.setCursorPos(math.floor(w/2)-2,6) | |
528 | local input = tonumber(read()) | |
529 | ||
530 | if input then | |
531 | color(colors.white,colors.black) term.clear() | |
532 | printC("Connecting to",5) | |
533 | printC("turtle ID "..input,6) | |
534 | printC("(*)",8) | |
535 | local state = 1 | |
536 | ||
537 | turtleID = input | |
538 | message({action="connect",id=input}) | |
539 | local timer = os.startTimer(1) | |
540 | while true do | |
541 | local event = {os.pullEventRaw()} | |
542 | if event[1] == "terminate" then | |
543 | term.clear() term.setCursorPos(1,1) print("Program terminated") | |
544 | return | |
545 | elseif event[1] == "rednet_message" and checkMessage(event,true) then | |
546 | if event[3] == "connected" then | |
547 | continue = false | |
548 | break | |
549 | end | |
550 | elseif event[1] == "timer" and event[2] == timer then | |
551 | state = (state == 4 and 1 or state+1) | |
552 | term.clearLine() printC(string.rep("(",state).."*"..string.rep(")",state),8) | |
553 | message({action="connect",id=input}) | |
554 | timer = os.startTimer(1) | |
555 | end | |
556 | end | |
557 | end | |
558 | end | |
559 | ||
560 | local function heartbeat() | |
561 | ||
562 | message("ping") | |
563 | local timer = os.startTimer(2) | |
564 | while true do | |
565 | local event = {os.pullEvent()} | |
566 | if event[1] == "rednet_message" then | |
567 | if checkMessage(event,true) and event[3] == "pong" then | |
568 | sleep(3) | |
569 | message("ping") | |
570 | timer = os.startTimer(2) | |
571 | end | |
572 | elseif event[1] == "timer" and event[2] == timer then | |
573 | color(colors.white,colors.black) term.setCursorPos(1,1) term.clear() print("Lost contact with turtle!") | |
574 | error("FORCEQUIT") | |
575 | end | |
576 | end | |
577 | ||
578 | end | |
579 | ||
580 | local function main() | |
581 | ||
582 | drawMainScreen() | |
583 | detectTools() | |
584 | ||
585 | while true do | |
586 | local event = {mainScreen.handleEvents()} | |
587 | if event[1] == "rednet_message" and checkMessage(event) then | |
588 | local msg = event[3] | |
589 | if msg.action == "ping" then | |
590 | message("pong") | |
591 | end | |
592 | elseif event[1] == "key" then | |
593 | if event[2] == keys.up or event[2] == keys.w then | |
594 | forward() | |
595 | elseif event[2] == keys.down or event[2] == keys.s then | |
596 | back() | |
597 | elseif event[2] == keys.right or event[2] == keys.d then | |
598 | turnRight() | |
599 | elseif event[2] == keys.left or event[2] == keys.a then | |
600 | turnLeft() | |
601 | elseif event[2] == keys.space then | |
602 | up() | |
603 | elseif event[2] == keys.leftShift then | |
604 | down() | |
605 | elseif event[2] == keys.q then | |
606 | ||
607 | end | |
608 | elseif event[1] == "object" then | |
609 | ||
610 | end | |
611 | end | |
612 | ||
613 | end | |
614 | ||
615 | local function run() | |
616 | parallel.waitForAny(main,heartbeat) | |
617 | end | |
618 | ||
619 | local state,err = pcall(run) | |
620 | ||
621 | if err then | |
622 | if not err:find("Terminated") and not err:find("FORCEQUIT") then | |
623 | color(colors.white,colors.black) | |
624 | term.clear() | |
625 | printC("An error occured:",1) | |
626 | term.setCursorPos(1,3) | |
627 | print(err) | |
628 | elseif not err:find("FORCEQUIT") then | |
629 | color(colors.white,colors.black) | |
630 | term.clear() | |
631 | term.setCursorPos(1,1) | |
632 | end | |
633 | else | |
634 | color(colors.white,colors.black) | |
635 | term.clear() | |
636 | term.setCursorPos(1,1) | |
637 | end |